Merge "Delay frozen app sockets close until the cellular modem wakes up" into main
This commit is contained in:
@@ -934,6 +934,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
private final Map<String, ApplicationSelfCertifiedNetworkCapabilities>
|
||||
mSelfCertifiedCapabilityCache = new HashMap<>();
|
||||
|
||||
// Flag to enable the feature of closing frozen app sockets.
|
||||
private final boolean mDestroyFrozenSockets;
|
||||
|
||||
// Flag to optimize closing frozen app sockets by waiting for the cellular modem to wake up.
|
||||
private final boolean mDelayDestroyFrozenSockets;
|
||||
|
||||
// Uids that ConnectivityService is pending to close sockets of.
|
||||
private final Set<Integer> mPendingFrozenUids = new ArraySet<>();
|
||||
|
||||
/**
|
||||
* Implements support for the legacy "one network per network type" model.
|
||||
*
|
||||
@@ -1772,8 +1781,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mCdmps = null;
|
||||
}
|
||||
|
||||
if (mDeps.isAtLeastU()
|
||||
&& mDeps.isFeatureEnabled(context, KEY_DESTROY_FROZEN_SOCKETS_VERSION)) {
|
||||
mDestroyFrozenSockets = mDeps.isAtLeastU()
|
||||
&& mDeps.isFeatureEnabled(context, KEY_DESTROY_FROZEN_SOCKETS_VERSION);
|
||||
mDelayDestroyFrozenSockets = mDeps.isAtLeastU()
|
||||
&& mDeps.isFeatureEnabled(context, DELAY_DESTROY_FROZEN_SOCKETS_VERSION);
|
||||
if (mDestroyFrozenSockets) {
|
||||
final UidFrozenStateChangedCallback frozenStateChangedCallback =
|
||||
new UidFrozenStateChangedCallback() {
|
||||
@Override
|
||||
@@ -2983,26 +2995,109 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the cell network is idle.
|
||||
* @return true if the cell network state is idle
|
||||
* false if the cell network state is active or unknown
|
||||
*/
|
||||
private boolean isCellNetworkIdle() {
|
||||
final NetworkAgentInfo defaultNai = getDefaultNetwork();
|
||||
if (defaultNai == null
|
||||
|| !defaultNai.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
|
||||
// mNetworkActivityTracker only tracks the activity of the default network. So if the
|
||||
// cell network is not the default network, cell network state is unknown.
|
||||
// TODO(b/279380356): Track cell network state when the cell is not the default network
|
||||
return false;
|
||||
}
|
||||
|
||||
return !mNetworkActivityTracker.isDefaultNetworkActive();
|
||||
}
|
||||
|
||||
private void handleFrozenUids(int[] uids, int[] frozenStates) {
|
||||
final ArraySet<Integer> 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()) {
|
||||
if (ownerUids.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mDelayDestroyFrozenSockets && 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);
|
||||
} else {
|
||||
try {
|
||||
mDeps.destroyLiveTcpSocketsByOwnerUids(ownerUids);
|
||||
} catch (Exception e) {
|
||||
} catch (SocketException | InterruptedIOException | ErrnoException e) {
|
||||
loge("Exception in socket destroy: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void closePendingFrozenSockets() {
|
||||
ensureRunningOnConnectivityServiceThread();
|
||||
|
||||
try {
|
||||
mDeps.destroyLiveTcpSocketsByOwnerUids(mPendingFrozenUids);
|
||||
} catch (SocketException | InterruptedIOException | ErrnoException e) {
|
||||
loge("Failed to close pending frozen app sockets: " + e);
|
||||
}
|
||||
mPendingFrozenUids.clear();
|
||||
}
|
||||
|
||||
private void handleReportNetworkActivity(final NetworkActivityParams params) {
|
||||
mNetworkActivityTracker.handleReportNetworkActivity(params);
|
||||
|
||||
if (mDelayDestroyFrozenSockets
|
||||
&& params.isActive
|
||||
&& params.label == TRANSPORT_CELLULAR
|
||||
&& !mPendingFrozenUids.isEmpty()) {
|
||||
closePendingFrozenSockets();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the cellular network is no longer the default network, close pending frozen sockets.
|
||||
*
|
||||
* @param newNetwork new default network
|
||||
* @param oldNetwork old default network
|
||||
*/
|
||||
private void maybeClosePendingFrozenSockets(NetworkAgentInfo newNetwork,
|
||||
NetworkAgentInfo oldNetwork) {
|
||||
final boolean isOldNetworkCellular = oldNetwork != null
|
||||
&& oldNetwork.networkCapabilities.hasTransport(TRANSPORT_CELLULAR);
|
||||
final boolean isNewNetworkCellular = newNetwork != null
|
||||
&& newNetwork.networkCapabilities.hasTransport(TRANSPORT_CELLULAR);
|
||||
|
||||
if (isOldNetworkCellular
|
||||
&& !isNewNetworkCellular
|
||||
&& !mPendingFrozenUids.isEmpty()) {
|
||||
closePendingFrozenSockets();
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpCloseFrozenAppSockets(IndentingPrintWriter pw) {
|
||||
pw.println("CloseFrozenAppSockets:");
|
||||
pw.increaseIndent();
|
||||
pw.print("mDestroyFrozenSockets="); pw.println(mDestroyFrozenSockets);
|
||||
pw.print("mDelayDestroyFrozenSockets="); pw.println(mDelayDestroyFrozenSockets);
|
||||
pw.print("mPendingFrozenUids="); pw.println(mPendingFrozenUids);
|
||||
pw.decreaseIndent();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static final String KEY_DESTROY_FROZEN_SOCKETS_VERSION = "destroy_frozen_sockets_version";
|
||||
@VisibleForTesting
|
||||
static final String DELAY_DESTROY_FROZEN_SOCKETS_VERSION =
|
||||
"delay_destroy_frozen_sockets_version";
|
||||
|
||||
private void enforceInternetPermission() {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
@@ -3604,6 +3699,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
pw.println();
|
||||
dumpAvoidBadWifiSettings(pw);
|
||||
|
||||
pw.println();
|
||||
dumpCloseFrozenAppSockets(pw);
|
||||
|
||||
pw.println();
|
||||
|
||||
if (!CollectionUtils.contains(args, SHORT_ARG)) {
|
||||
@@ -4671,6 +4769,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// incorrect) behavior.
|
||||
mNetworkActivityTracker.updateDataActivityTracking(
|
||||
null /* newNetwork */, nai);
|
||||
maybeClosePendingFrozenSockets(null /* newNetwork */, nai);
|
||||
ensureNetworkTransitionWakelock(nai.toShortString());
|
||||
}
|
||||
}
|
||||
@@ -5877,7 +5976,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
case EVENT_REPORT_NETWORK_ACTIVITY:
|
||||
final NetworkActivityParams arg = (NetworkActivityParams) msg.obj;
|
||||
mNetworkActivityTracker.handleReportNetworkActivity(arg);
|
||||
handleReportNetworkActivity(arg);
|
||||
break;
|
||||
case EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED:
|
||||
handleMobileDataPreferredUidsChanged();
|
||||
@@ -9117,6 +9216,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mLingerMonitor.noteLingerDefaultNetwork(oldDefaultNetwork, newDefaultNetwork);
|
||||
}
|
||||
mNetworkActivityTracker.updateDataActivityTracking(newDefaultNetwork, oldDefaultNetwork);
|
||||
maybeClosePendingFrozenSockets(newDefaultNetwork, oldDefaultNetwork);
|
||||
mProxyTracker.setDefaultProxy(null != newDefaultNetwork
|
||||
? newDefaultNetwork.linkProperties.getHttpProxy() : null);
|
||||
resetHttpProxyForNonDefaultNetwork(oldDefaultNetwork);
|
||||
|
||||
@@ -154,6 +154,7 @@ import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALID
|
||||
import static android.os.Process.INVALID_UID;
|
||||
import static android.system.OsConstants.IPPROTO_TCP;
|
||||
|
||||
import static com.android.server.ConnectivityService.DELAY_DESTROY_FROZEN_SOCKETS_VERSION;
|
||||
import static com.android.server.ConnectivityService.KEY_DESTROY_FROZEN_SOCKETS_VERSION;
|
||||
import static com.android.server.ConnectivityService.MAX_NETWORK_REQUESTS_PER_SYSTEM_UID;
|
||||
import static com.android.server.ConnectivityService.PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED;
|
||||
@@ -214,6 +215,7 @@ import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.clearInvocations;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
@@ -2130,6 +2132,8 @@ public class ConnectivityServiceTest {
|
||||
return true;
|
||||
case KEY_DESTROY_FROZEN_SOCKETS_VERSION:
|
||||
return true;
|
||||
case DELAY_DESTROY_FROZEN_SOCKETS_VERSION:
|
||||
return true;
|
||||
default:
|
||||
return super.isFeatureEnabled(context, name);
|
||||
}
|
||||
@@ -2280,7 +2284,9 @@ public class ConnectivityServiceTest {
|
||||
@Override @SuppressWarnings("DirectInvocationOnMock")
|
||||
public void destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids) {
|
||||
// Call mocked destroyLiveTcpSocketsByOwnerUids so that test can verify this method call
|
||||
mDestroySocketsWrapper.destroyLiveTcpSocketsByOwnerUids(ownerUids);
|
||||
// Create copy of ownerUids so that tests can verify the correct value even if the
|
||||
// ConnectivityService update the ownerUids after this method call.
|
||||
mDestroySocketsWrapper.destroyLiveTcpSocketsByOwnerUids(new ArraySet<>(ownerUids));
|
||||
}
|
||||
|
||||
final ArrayTrackRecord<Pair<Integer, Long>>.ReadHead mScheduledEvaluationTimeouts =
|
||||
@@ -11290,6 +11296,9 @@ public class ConnectivityServiceTest {
|
||||
}
|
||||
|
||||
private void doTestInterfaceClassActivityChanged(final int transportType) throws Exception {
|
||||
final BaseNetdUnsolicitedEventListener netdUnsolicitedEventListener =
|
||||
getRegisteredNetdUnsolicitedEventListener();
|
||||
|
||||
final int legacyType = transportToLegacyType(transportType);
|
||||
final LinkProperties lp = new LinkProperties();
|
||||
lp.setInterfaceName(transportToTestIfaceName(transportType));
|
||||
@@ -11306,12 +11315,8 @@ public class ConnectivityServiceTest {
|
||||
|
||||
mCm.addDefaultNetworkActiveListener(listener);
|
||||
|
||||
ArgumentCaptor<BaseNetdUnsolicitedEventListener> netdCallbackCaptor =
|
||||
ArgumentCaptor.forClass(BaseNetdUnsolicitedEventListener.class);
|
||||
verify(mMockNetd).registerUnsolicitedEventListener(netdCallbackCaptor.capture());
|
||||
|
||||
// Interface goes to inactive state
|
||||
netdCallbackCaptor.getValue().onInterfaceClassActivityChanged(false /* isActive */,
|
||||
netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
|
||||
transportType, TIMESTAMP, NETWORK_ACTIVITY_NO_UID);
|
||||
mServiceContext.expectDataActivityBroadcast(legacyType, false /* isActive */,
|
||||
TIMESTAMP);
|
||||
@@ -11319,7 +11324,7 @@ public class ConnectivityServiceTest {
|
||||
assertFalse(mCm.isDefaultNetworkActive());
|
||||
|
||||
// Interface goes to active state
|
||||
netdCallbackCaptor.getValue().onInterfaceClassActivityChanged(true /* isActive */,
|
||||
netdUnsolicitedEventListener.onInterfaceClassActivityChanged(true /* isActive */,
|
||||
transportType, TIMESTAMP, TEST_PACKAGE_UID);
|
||||
mServiceContext.expectDataActivityBroadcast(legacyType, true /* isActive */, TIMESTAMP);
|
||||
assertTrue(onNetworkActiveCv.block(TEST_CALLBACK_TIMEOUT_MS));
|
||||
@@ -18566,6 +18571,27 @@ public class ConnectivityServiceTest {
|
||||
anyInt());
|
||||
}
|
||||
|
||||
// UidFrozenStateChangedCallback is added in U API.
|
||||
// Returning UidFrozenStateChangedCallback directly makes the test fail on T- devices since
|
||||
// AndroidJUnit4ClassRunner iterates all declared methods and tries to resolve the return type.
|
||||
// Solve this by wrapping it in an AtomicReference. Because of erasure, this removes the
|
||||
// resolving problem as the type isn't seen dynamically.
|
||||
private AtomicReference<UidFrozenStateChangedCallback> getUidFrozenStateChangedCallback() {
|
||||
ArgumentCaptor<UidFrozenStateChangedCallback> activityManagerCallbackCaptor =
|
||||
ArgumentCaptor.forClass(UidFrozenStateChangedCallback.class);
|
||||
verify(mActivityManager).registerUidFrozenStateChangedCallback(any(),
|
||||
activityManagerCallbackCaptor.capture());
|
||||
return new AtomicReference<>(activityManagerCallbackCaptor.getValue());
|
||||
}
|
||||
|
||||
private BaseNetdUnsolicitedEventListener getRegisteredNetdUnsolicitedEventListener()
|
||||
throws RemoteException {
|
||||
ArgumentCaptor<BaseNetdUnsolicitedEventListener> netdCallbackCaptor =
|
||||
ArgumentCaptor.forClass(BaseNetdUnsolicitedEventListener.class);
|
||||
verify(mMockNetd).registerUnsolicitedEventListener(netdCallbackCaptor.capture());
|
||||
return netdCallbackCaptor.getValue();
|
||||
}
|
||||
|
||||
private static final int TEST_FROZEN_UID = 1000;
|
||||
private static final int TEST_UNFROZEN_UID = 2000;
|
||||
|
||||
@@ -18576,22 +18602,177 @@ public class ConnectivityServiceTest {
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testFrozenUidSocketDestroy() throws Exception {
|
||||
ArgumentCaptor<UidFrozenStateChangedCallback> callbackArg =
|
||||
ArgumentCaptor.forClass(UidFrozenStateChangedCallback.class);
|
||||
|
||||
verify(mActivityManager).registerUidFrozenStateChangedCallback(any(),
|
||||
callbackArg.capture());
|
||||
final UidFrozenStateChangedCallback callback =
|
||||
getUidFrozenStateChangedCallback().get();
|
||||
|
||||
final int[] uids = {TEST_FROZEN_UID, TEST_UNFROZEN_UID};
|
||||
final int[] frozenStates = {UID_FROZEN_STATE_FROZEN, UID_FROZEN_STATE_UNFROZEN};
|
||||
|
||||
callbackArg.getValue().onUidFrozenStateChanged(uids, frozenStates);
|
||||
callback.onUidFrozenStateChanged(uids, frozenStates);
|
||||
|
||||
waitForIdle();
|
||||
|
||||
verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(Set.of(TEST_FROZEN_UID));
|
||||
}
|
||||
|
||||
private void doTestDelayFrozenUidSocketDestroy(int transportType,
|
||||
boolean freezeWithNetworkInactive, boolean expectDelay) throws Exception {
|
||||
final TestNetworkCallback defaultCallback = new TestNetworkCallback();
|
||||
final LinkProperties lp = new LinkProperties();
|
||||
lp.setInterfaceName(transportToTestIfaceName(transportType));
|
||||
final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(transportType, lp);
|
||||
testAndCleanup(() -> {
|
||||
final UidFrozenStateChangedCallback uidFrozenStateChangedCallback =
|
||||
getUidFrozenStateChangedCallback().get();
|
||||
final BaseNetdUnsolicitedEventListener netdUnsolicitedEventListener =
|
||||
getRegisteredNetdUnsolicitedEventListener();
|
||||
|
||||
mCm.registerDefaultNetworkCallback(defaultCallback);
|
||||
agent.connect(true);
|
||||
defaultCallback.expectAvailableThenValidatedCallbacks(agent);
|
||||
if (freezeWithNetworkInactive) {
|
||||
// Make network inactive
|
||||
netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
|
||||
transportType, TIMESTAMP, NETWORK_ACTIVITY_NO_UID);
|
||||
}
|
||||
|
||||
// Freeze TEST_FROZEN_UID and TEST_UNFROZEN_UID
|
||||
final int[] uids1 = {TEST_FROZEN_UID, TEST_UNFROZEN_UID};
|
||||
final int[] frozenStates1 = {UID_FROZEN_STATE_FROZEN, UID_FROZEN_STATE_FROZEN};
|
||||
uidFrozenStateChangedCallback.onUidFrozenStateChanged(uids1, frozenStates1);
|
||||
waitForIdle();
|
||||
|
||||
if (expectDelay) {
|
||||
verify(mDestroySocketsWrapper, never()).destroyLiveTcpSocketsByOwnerUids(any());
|
||||
} else {
|
||||
verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(
|
||||
Set.of(TEST_FROZEN_UID, TEST_UNFROZEN_UID));
|
||||
clearInvocations(mDestroySocketsWrapper);
|
||||
}
|
||||
|
||||
// Unfreeze TEST_UNFROZEN_UID
|
||||
final int[] uids2 = {TEST_UNFROZEN_UID};
|
||||
final int[] frozenStates2 = {UID_FROZEN_STATE_UNFROZEN};
|
||||
uidFrozenStateChangedCallback.onUidFrozenStateChanged(uids2, frozenStates2);
|
||||
|
||||
// Make network active
|
||||
netdUnsolicitedEventListener.onInterfaceClassActivityChanged(true /* isActive */,
|
||||
transportType, TIMESTAMP, TEST_PACKAGE_UID);
|
||||
waitForIdle();
|
||||
|
||||
if (expectDelay) {
|
||||
verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(
|
||||
Set.of(TEST_FROZEN_UID));
|
||||
} else {
|
||||
verify(mDestroySocketsWrapper, never()).destroyLiveTcpSocketsByOwnerUids(any());
|
||||
}
|
||||
}, () -> { // Cleanup
|
||||
agent.disconnect();
|
||||
}, () -> {
|
||||
mCm.unregisterNetworkCallback(defaultCallback);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testDelayFrozenUidSocketDestroy_ActiveCellular() throws Exception {
|
||||
doTestDelayFrozenUidSocketDestroy(TRANSPORT_CELLULAR,
|
||||
false /* freezeWithNetworkInactive */, false /* expectDelay */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testDelayFrozenUidSocketDestroy_InactiveCellular() throws Exception {
|
||||
// When the default network is cellular and cellular network is inactive, closing socket
|
||||
// is delayed.
|
||||
doTestDelayFrozenUidSocketDestroy(TRANSPORT_CELLULAR,
|
||||
true /* freezeWithNetworkInactive */, true /* expectDelay */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testDelayFrozenUidSocketDestroy_ActiveWifi() throws Exception {
|
||||
doTestDelayFrozenUidSocketDestroy(TRANSPORT_WIFI,
|
||||
false /* freezeWithNetworkInactive */, false /* expectDelay */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testDelayFrozenUidSocketDestroy_InactiveWifi() throws Exception {
|
||||
doTestDelayFrozenUidSocketDestroy(TRANSPORT_WIFI,
|
||||
true /* freezeWithNetworkInactive */, false /* expectDelay */);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param switchToWifi if true, simulate a migration of the default network to wifi
|
||||
* if false, simulate a cell disconnection
|
||||
*/
|
||||
private void doTestLoseCellDefaultNetwork_ClosePendingFrozenSockets(final boolean switchToWifi)
|
||||
throws Exception {
|
||||
final UidFrozenStateChangedCallback uidFrozenStateChangedCallback =
|
||||
getUidFrozenStateChangedCallback().get();
|
||||
final BaseNetdUnsolicitedEventListener netdUnsolicitedEventListener =
|
||||
getRegisteredNetdUnsolicitedEventListener();
|
||||
|
||||
final LinkProperties wifiLp = new LinkProperties();
|
||||
wifiLp.setInterfaceName(WIFI_IFNAME);
|
||||
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
|
||||
|
||||
final LinkProperties cellLp = new LinkProperties();
|
||||
cellLp.setInterfaceName(MOBILE_IFNAME);
|
||||
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
|
||||
|
||||
final TestNetworkCallback defaultCallback = new TestNetworkCallback();
|
||||
mCm.registerDefaultNetworkCallback(defaultCallback);
|
||||
try {
|
||||
mCellAgent.connect(true);
|
||||
defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
|
||||
|
||||
// Make cell network inactive
|
||||
netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
|
||||
TRANSPORT_CELLULAR, TIMESTAMP, NETWORK_ACTIVITY_NO_UID);
|
||||
|
||||
// Freeze TEST_FROZEN_UID
|
||||
final int[] uids = {TEST_FROZEN_UID};
|
||||
final int[] frozenStates = {UID_FROZEN_STATE_FROZEN};
|
||||
uidFrozenStateChangedCallback.onUidFrozenStateChanged(uids, frozenStates);
|
||||
waitForIdle();
|
||||
|
||||
// Closing frozen sockets should be delayed since the default network is cellular
|
||||
// and cellular network is inactive.
|
||||
verify(mDestroySocketsWrapper, never()).destroyLiveTcpSocketsByOwnerUids(any());
|
||||
|
||||
if (switchToWifi) {
|
||||
mWiFiAgent.connect(true);
|
||||
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
|
||||
} else {
|
||||
mCellAgent.disconnect();
|
||||
waitForIdle();
|
||||
}
|
||||
|
||||
// Pending frozen sockets should be closed since the cellular network is no longer the
|
||||
// default network.
|
||||
verify(mDestroySocketsWrapper)
|
||||
.destroyLiveTcpSocketsByOwnerUids(Set.of(TEST_FROZEN_UID));
|
||||
} finally {
|
||||
mCm.unregisterNetworkCallback(defaultCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testLoseCellDefaultNetwork_SwitchToWifi_ClosePendingFrozenSockets()
|
||||
throws Exception {
|
||||
doTestLoseCellDefaultNetwork_ClosePendingFrozenSockets(true /* switchToWifi */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testLoseCellDefaultNetwork_NoDefaultNetwork_ClosePendingFrozenSockets()
|
||||
throws Exception {
|
||||
doTestLoseCellDefaultNetwork_ClosePendingFrozenSockets(false /* switchToWifi */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisconnectSuspendedNetworkStopClatd() throws Exception {
|
||||
final TestNetworkCallback networkCallback = new TestNetworkCallback();
|
||||
|
||||
Reference in New Issue
Block a user