Optionally have ConnectivityService kill sockets for frozen apps

To do this we register a UidFrozenStateChangedCallback with
ActivityManager. The callback then queues up work on the Handler thread
to consume the original callback args and kill appropriate sockets.

Test: atest ConnectivityServiceTests
Bug: 277100090
Change-Id: I93f174811aef726145a18ea90443ddfc1456478e
This commit is contained in:
Mark Fasheh
2023-05-04 20:23:11 +00:00
parent ac7a0e3ee9
commit 7c999d8d4c
2 changed files with 111 additions and 0 deletions

View File

@@ -17,6 +17,7 @@
package com.android.server;
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN;
import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.FEATURE_WIFI;
@@ -110,6 +111,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.ActivityManager.UidFrozenStateChangedCallback;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
@@ -786,6 +789,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/
private static final int EVENT_SET_LOW_TCP_POLLING_UNTIL = 60;
/**
* Event to inform the ConnectivityService handler when a uid has been frozen or unfrozen.
*/
private static final int EVENT_UID_FROZEN_STATE_CHANGED = 61;
/**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown.
@@ -1691,6 +1699,32 @@ public class ConnectivityService extends IConnectivityManager.Stub
} else {
mCdmps = null;
}
if (SdkLevel.isAtLeastU()
&& mDeps.isFeatureEnabled(context, KEY_DESTROY_FROZEN_SOCKETS_VERSION)) {
final UidFrozenStateChangedCallback frozenStateChangedCallback =
new UidFrozenStateChangedCallback() {
@Override
public void onUidFrozenStateChanged(int[] uids, int[] frozenStates) {
if (uids.length != frozenStates.length) {
Log.wtf(TAG, "uids has length " + uids.length
+ " but frozenStates has length " + frozenStates.length);
return;
}
final UidFrozenStateChangedArgs args =
new UidFrozenStateChangedArgs(uids, frozenStates);
mHandler.sendMessage(
mHandler.obtainMessage(EVENT_UID_FROZEN_STATE_CHANGED, args));
}
};
final ActivityManager activityManager =
mContext.getSystemService(ActivityManager.class);
activityManager.registerUidFrozenStateChangedCallback(
(Runnable r) -> r.run(), frozenStateChangedCallback);
}
}
/**
@@ -2859,6 +2893,39 @@ public class ConnectivityService extends IConnectivityManager.Stub
setUidBlockedReasons(uid, blockedReasons);
}
static final class UidFrozenStateChangedArgs {
final int[] mUids;
final int[] mFrozenStates;
UidFrozenStateChangedArgs(int[] uids, int[] frozenStates) {
mUids = uids;
mFrozenStates = frozenStates;
}
}
private void handleFrozenUids(int[] uids, int[] frozenStates) {
final ArraySet<Range<Integer>> ranges = new ArraySet<>();
for (int i = 0; i < uids.length; i++) {
if (frozenStates[i] == UID_FROZEN_STATE_FROZEN) {
Integer uidAsInteger = Integer.valueOf(uids[i]);
ranges.add(new Range(uidAsInteger, uidAsInteger));
}
}
if (!ranges.isEmpty()) {
final Set<Integer> exemptUids = new ArraySet<>();
try {
mDeps.destroyLiveTcpSockets(ranges, exemptUids);
} catch (Exception e) {
loge("Exception in socket destroy: " + e);
}
}
}
@VisibleForTesting
static final String KEY_DESTROY_FROZEN_SOCKETS_VERSION = "destroy_frozen_sockets_version";
private void enforceInternetPermission() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERNET,
@@ -5722,6 +5789,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
mKeepaliveTracker.handleSetTestLowTcpPollingTimer(time);
break;
}
case EVENT_UID_FROZEN_STATE_CHANGED:
UidFrozenStateChangedArgs args = (UidFrozenStateChangedArgs) msg.obj;
handleFrozenUids(args.mUids, args.mFrozenStates);
break;
}
}
}