diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index 69ce602907..99ed4ce4d2 100755 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -1006,7 +1006,11 @@ public class ConnectivityService extends IConnectivityManager.Stub private final boolean mAllowSysUiConnectivityReports; // Uids that ConnectivityService is pending to close sockets of. - private final Set mPendingFrozenUids = new ArraySet<>(); + // Key is uid and value is reasons of socket destroy + private final SparseIntArray mDestroySocketPendingUids = new SparseIntArray(); + + private static final int DESTROY_SOCKET_REASON_NONE = 0; + private static final int DESTROY_SOCKET_REASON_FROZEN = 1 << 0; // Flag to drop packets to VPN addresses ingressing via non-VPN interfaces. private final boolean mIngressToVpnAddressFiltering; @@ -3349,47 +3353,51 @@ public class ConnectivityService extends IConnectivityManager.Stub return !mNetworkActivityTracker.isDefaultNetworkActive(); } - private void handleFrozenUids(int[] uids, int[] frozenStates) { - final ArraySet ownerUids = new ArraySet<>(); - - for (int i = 0; i < uids.length; i++) { - if (frozenStates[i] == UID_FROZEN_STATE_FROZEN) { - ownerUids.add(uids[i]); - } else { - mPendingFrozenUids.remove(uids[i]); - } - } - - if (ownerUids.isEmpty()) { - return; - } - - if (mDelayDestroySockets && isCellNetworkIdle()) { - // Delay closing sockets to avoid waking the cell modem up. - // Wi-Fi network state is not considered since waking Wi-Fi modem up is much cheaper - // than waking cell modem up. - mPendingFrozenUids.addAll(ownerUids); + private void updateDestroySocketReasons(final int uid, final int reason, + final boolean addReason) { + final int destroyReasons = mDestroySocketPendingUids.get(uid, DESTROY_SOCKET_REASON_NONE); + if (addReason) { + mDestroySocketPendingUids.put(uid, destroyReasons | reason); } else { - try { - mDeps.destroyLiveTcpSocketsByOwnerUids(ownerUids); - } catch (SocketException | InterruptedIOException | ErrnoException e) { - loge("Exception in socket destroy: " + e); + final int newDestroyReasons = destroyReasons & ~reason; + if (newDestroyReasons == DESTROY_SOCKET_REASON_NONE) { + mDestroySocketPendingUids.delete(uid); + } else { + mDestroySocketPendingUids.put(uid, newDestroyReasons); } } } + private void handleFrozenUids(int[] uids, int[] frozenStates) { + ensureRunningOnConnectivityServiceThread(); + for (int i = 0; i < uids.length; i++) { + final int uid = uids[i]; + final boolean addReason = frozenStates[i] == UID_FROZEN_STATE_FROZEN; + updateDestroySocketReasons(uid, DESTROY_SOCKET_REASON_FROZEN, addReason); + } + + if (!mDelayDestroySockets || !isCellNetworkIdle()) { + destroyPendingSockets(); + } + } + private void destroyPendingSockets() { ensureRunningOnConnectivityServiceThread(); - if (mPendingFrozenUids.isEmpty()) { + if (mDestroySocketPendingUids.size() == 0) { return; } + Set uids = new ArraySet<>(); + for (int i = 0; i < mDestroySocketPendingUids.size(); i++) { + uids.add(mDestroySocketPendingUids.keyAt(i)); + } + try { - mDeps.destroyLiveTcpSocketsByOwnerUids(mPendingFrozenUids); + mDeps.destroyLiveTcpSocketsByOwnerUids(uids); } catch (SocketException | InterruptedIOException | ErrnoException e) { loge("Failed to destroy sockets: " + e); } - mPendingFrozenUids.clear(); + mDestroySocketPendingUids.clear(); } private void handleReportNetworkActivity(final NetworkActivityParams params) { @@ -3429,12 +3437,19 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void dumpCloseFrozenAppSockets(IndentingPrintWriter pw) { - pw.println("CloseFrozenAppSockets:"); + private void dumpDestroySockets(IndentingPrintWriter pw) { + pw.println("DestroySockets:"); pw.increaseIndent(); pw.print("mDestroyFrozenSockets="); pw.println(mDestroyFrozenSockets); pw.print("mDelayDestroySockets="); pw.println(mDelayDestroySockets); - pw.print("mPendingFrozenUids="); pw.println(mPendingFrozenUids); + pw.print("mDestroySocketPendingUids:"); + pw.increaseIndent(); + for (int i = 0; i < mDestroySocketPendingUids.size(); i++) { + final int uid = mDestroySocketPendingUids.keyAt(i); + final int reasons = mDestroySocketPendingUids.valueAt(i); + pw.print(uid + ": reasons=" + reasons); + } + pw.decreaseIndent(); pw.decreaseIndent(); } @@ -4093,7 +4108,7 @@ public class ConnectivityService extends IConnectivityManager.Stub dumpAvoidBadWifiSettings(pw); pw.println(); - dumpCloseFrozenAppSockets(pw); + dumpDestroySockets(pw); pw.println(); dumpBpfProgramStatus(pw);