Merge "Use pending uid state when calculating network blocked state." into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
742405591b
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.net;
|
||||
|
||||
import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
|
||||
import static android.app.ActivityManager.procStateToString;
|
||||
import static android.content.pm.PackageManager.GET_SIGNATURES;
|
||||
|
||||
@@ -805,6 +806,9 @@ public class NetworkPolicyManager {
|
||||
/** @hide */
|
||||
public static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(
|
||||
int procState, @ProcessCapability int capability) {
|
||||
if (procState == PROCESS_STATE_UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
return procState <= FOREGROUND_THRESHOLD_STATE
|
||||
|| (capability & ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0;
|
||||
}
|
||||
@@ -832,6 +836,9 @@ public class NetworkPolicyManager {
|
||||
/** @hide */
|
||||
public static boolean isProcStateAllowedWhileOnRestrictBackground(int procState,
|
||||
@ProcessCapability int capabilities) {
|
||||
if (procState == PROCESS_STATE_UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
return procState <= FOREGROUND_THRESHOLD_STATE
|
||||
// This is meant to be a user-initiated job, and therefore gets similar network
|
||||
// access to FGS.
|
||||
|
||||
@@ -28,6 +28,7 @@ import static android.Manifest.permission.READ_PHONE_STATE;
|
||||
import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
|
||||
import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
|
||||
import static android.app.ActivityManager.isProcStateConsideredInteraction;
|
||||
import static android.app.ActivityManager.printCapabilitiesSummary;
|
||||
import static android.app.ActivityManager.procStateToString;
|
||||
import static android.app.PendingIntent.FLAG_IMMUTABLE;
|
||||
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
|
||||
@@ -1133,6 +1134,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
if (!callbackInfo.isPending) {
|
||||
mUidEventHandler.obtainMessage(UID_MSG_STATE_CHANGED, callbackInfo)
|
||||
.sendToTarget();
|
||||
callbackInfo.isPending = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1156,6 +1158,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
this.procStateSeq = procStateSeq;
|
||||
this.capability = capability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("{");
|
||||
sb.append("uid=").append(uid).append(",");
|
||||
sb.append("proc_state=").append(procStateToString(procState)).append(",");
|
||||
sb.append("seq=").append(procStateSeq).append(",");
|
||||
sb.append("cap="); printCapabilitiesSummary(sb, capability); sb.append(",");
|
||||
sb.append("pending=").append(isPending);
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
final private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() {
|
||||
@@ -3982,31 +3997,31 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
synchronized (mUidBlockedState) {
|
||||
collectKeys(mUidBlockedState, knownUids);
|
||||
}
|
||||
synchronized (mUidStateCallbackInfos) {
|
||||
collectKeys(mUidStateCallbackInfos, knownUids);
|
||||
}
|
||||
|
||||
fout.println("Status for all known UIDs:");
|
||||
fout.increaseIndent();
|
||||
size = knownUids.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final int uid = knownUids.keyAt(i);
|
||||
fout.print("UID=");
|
||||
fout.print(uid);
|
||||
fout.print("UID", uid);
|
||||
|
||||
final UidState uidState = mUidState.get(uid);
|
||||
if (uidState == null) {
|
||||
fout.print(" state={null}");
|
||||
} else {
|
||||
fout.print(" state=");
|
||||
fout.print(uidState.toString());
|
||||
}
|
||||
fout.print("state", uidState);
|
||||
|
||||
synchronized (mUidBlockedState) {
|
||||
final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
|
||||
if (uidBlockedState == null) {
|
||||
fout.print(" blocked_state={null}");
|
||||
} else {
|
||||
fout.print(" blocked_state=");
|
||||
fout.print(uidBlockedState);
|
||||
}
|
||||
fout.print("blocked_state", uidBlockedState);
|
||||
}
|
||||
|
||||
synchronized (mUidStateCallbackInfos) {
|
||||
final UidStateCallbackInfo callbackInfo = mUidStateCallbackInfos.get(uid);
|
||||
fout.println();
|
||||
fout.increaseIndent();
|
||||
fout.print("callback_info", callbackInfo);
|
||||
fout.decreaseIndent();
|
||||
}
|
||||
fout.println();
|
||||
}
|
||||
@@ -4052,27 +4067,49 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isUidForeground(int uid) {
|
||||
synchronized (mUidRulesFirstLock) {
|
||||
return isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.get(uid));
|
||||
@GuardedBy("mUidRulesFirstLock")
|
||||
boolean isUidForegroundOnRestrictBackgroundUL(int uid) {
|
||||
final UidState uidState = mUidState.get(uid);
|
||||
if (isProcStateAllowedWhileOnRestrictBackground(uidState)) {
|
||||
return true;
|
||||
}
|
||||
// Check if there is any pending state change.
|
||||
synchronized (mUidStateCallbackInfos) {
|
||||
final UidStateCallbackInfo callbackInfo = mUidStateCallbackInfos.get(uid);
|
||||
final long prevProcStateSeq = uidState != null ? uidState.procStateSeq : -1;
|
||||
if (callbackInfo != null && callbackInfo.isPending
|
||||
&& callbackInfo.procStateSeq >= prevProcStateSeq) {
|
||||
return isProcStateAllowedWhileOnRestrictBackground(callbackInfo.procState,
|
||||
callbackInfo.capability);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@GuardedBy("mUidRulesFirstLock")
|
||||
private boolean isUidForegroundOnRestrictBackgroundUL(int uid) {
|
||||
boolean isUidForegroundOnRestrictPowerUL(int uid) {
|
||||
final UidState uidState = mUidState.get(uid);
|
||||
return isProcStateAllowedWhileOnRestrictBackground(uidState);
|
||||
}
|
||||
|
||||
@GuardedBy("mUidRulesFirstLock")
|
||||
private boolean isUidForegroundOnRestrictPowerUL(int uid) {
|
||||
final UidState uidState = mUidState.get(uid);
|
||||
return isProcStateAllowedWhileIdleOrPowerSaveMode(uidState);
|
||||
if (isProcStateAllowedWhileIdleOrPowerSaveMode(uidState)) {
|
||||
return true;
|
||||
}
|
||||
// Check if there is any pending state change.
|
||||
synchronized (mUidStateCallbackInfos) {
|
||||
final UidStateCallbackInfo callbackInfo = mUidStateCallbackInfos.get(uid);
|
||||
final long prevProcStateSeq = uidState != null ? uidState.procStateSeq : -1;
|
||||
if (callbackInfo != null && callbackInfo.isPending
|
||||
&& callbackInfo.procStateSeq >= prevProcStateSeq) {
|
||||
return isProcStateAllowedWhileIdleOrPowerSaveMode(callbackInfo.procState,
|
||||
callbackInfo.capability);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@GuardedBy("mUidRulesFirstLock")
|
||||
private boolean isUidTop(int uid) {
|
||||
final UidState uidState = mUidState.get(uid);
|
||||
// TODO: Consider taking pending uid state change into account.
|
||||
return isProcStateAllowedWhileInLowPowerStandby(uidState);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,12 @@ package com.android.server.net;
|
||||
|
||||
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
|
||||
import static android.Manifest.permission.NETWORK_STACK;
|
||||
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
|
||||
import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
|
||||
import static android.app.ActivityManager.PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
|
||||
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
|
||||
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
|
||||
import static android.app.ActivityManager.PROCESS_STATE_TOP;
|
||||
import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER;
|
||||
import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED;
|
||||
import static android.net.ConnectivityManager.BLOCKED_REASON_APP_STANDBY;
|
||||
@@ -396,6 +402,26 @@ public class NetworkPolicyManagerServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Use TestLooperManager instead.
|
||||
/**
|
||||
* Helper that leverages try-with-resources to pause dispatch of
|
||||
* {@link #mHandlerThread} until released.
|
||||
*/
|
||||
static class SyncBarrier implements AutoCloseable {
|
||||
private final int mToken;
|
||||
private Handler mHandler;
|
||||
|
||||
SyncBarrier(Handler handler) {
|
||||
mHandler = handler;
|
||||
mToken = mHandler.getLooper().getQueue().postSyncBarrier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
mHandler.getLooper().getQueue().removeSyncBarrier(mToken);
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void callSystemReady() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -1018,25 +1044,113 @@ public class NetworkPolicyManagerServiceTest {
|
||||
// don't check for side-effects (like calls to NetworkManagementService) neither cover all
|
||||
// different modes (Data Saver, Battery Saver, Doze, App idle, etc...).
|
||||
// These scenarios are extensively tested on CTS' HostsideRestrictBackgroundNetworkTests.
|
||||
@SuppressWarnings("GuardedBy")
|
||||
@Test
|
||||
public void testUidForeground() throws Exception {
|
||||
// push all uids into background
|
||||
long procStateSeq = 0;
|
||||
callOnUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE, procStateSeq++);
|
||||
callOnUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE, procStateSeq++);
|
||||
assertFalse(mService.isUidForeground(UID_A));
|
||||
assertFalse(mService.isUidForeground(UID_B));
|
||||
callAndWaitOnUidStateChanged(UID_A, PROCESS_STATE_SERVICE, procStateSeq++);
|
||||
callAndWaitOnUidStateChanged(UID_B, PROCESS_STATE_SERVICE, procStateSeq++);
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_B));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_B));
|
||||
|
||||
// push one of the uids into foreground
|
||||
callOnUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP, procStateSeq++);
|
||||
assertTrue(mService.isUidForeground(UID_A));
|
||||
assertFalse(mService.isUidForeground(UID_B));
|
||||
callAndWaitOnUidStateChanged(UID_A, PROCESS_STATE_TOP, procStateSeq++);
|
||||
assertTrue(mService.isUidForegroundOnRestrictPowerUL(UID_A));
|
||||
assertTrue(mService.isUidForegroundOnRestrictBackgroundUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_B));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_B));
|
||||
|
||||
// and swap another uid into foreground
|
||||
callOnUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE, procStateSeq++);
|
||||
callOnUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP, procStateSeq++);
|
||||
assertFalse(mService.isUidForeground(UID_A));
|
||||
assertTrue(mService.isUidForeground(UID_B));
|
||||
callAndWaitOnUidStateChanged(UID_A, PROCESS_STATE_SERVICE, procStateSeq++);
|
||||
callAndWaitOnUidStateChanged(UID_B, PROCESS_STATE_TOP, procStateSeq++);
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_A));
|
||||
assertTrue(mService.isUidForegroundOnRestrictPowerUL(UID_B));
|
||||
assertTrue(mService.isUidForegroundOnRestrictBackgroundUL(UID_B));
|
||||
|
||||
// change capability of an uid to allow access to power restricted network
|
||||
callAndWaitOnUidStateChanged(UID_A, PROCESS_STATE_SERVICE, procStateSeq++,
|
||||
PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK);
|
||||
callAndWaitOnUidStateChanged(UID_B, PROCESS_STATE_SERVICE, procStateSeq++,
|
||||
PROCESS_CAPABILITY_NONE);
|
||||
assertTrue(mService.isUidForegroundOnRestrictPowerUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_B));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_B));
|
||||
|
||||
// change capability of an uid to allow access to user restricted network
|
||||
callAndWaitOnUidStateChanged(UID_A, PROCESS_STATE_IMPORTANT_FOREGROUND, procStateSeq++,
|
||||
PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK);
|
||||
callAndWaitOnUidStateChanged(UID_B, PROCESS_STATE_SERVICE, procStateSeq++,
|
||||
PROCESS_CAPABILITY_NONE);
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_A));
|
||||
assertTrue(mService.isUidForegroundOnRestrictBackgroundUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_B));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_B));
|
||||
}
|
||||
|
||||
@SuppressWarnings("GuardedBy")
|
||||
@Test
|
||||
public void testUidForeground_withPendingState() throws Exception {
|
||||
long procStateSeq = 0;
|
||||
callAndWaitOnUidStateChanged(UID_A, PROCESS_STATE_SERVICE,
|
||||
procStateSeq++, PROCESS_CAPABILITY_NONE);
|
||||
callAndWaitOnUidStateChanged(UID_B, PROCESS_STATE_SERVICE,
|
||||
procStateSeq++, PROCESS_CAPABILITY_NONE);
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_B));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_B));
|
||||
|
||||
try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
|
||||
// Verify that a callback with an old procStateSeq is ignored.
|
||||
callOnUidStatechanged(UID_A, PROCESS_STATE_TOP, 0,
|
||||
PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK);
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_B));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_B));
|
||||
|
||||
callOnUidStatechanged(UID_A, PROCESS_STATE_SERVICE, procStateSeq++,
|
||||
PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK);
|
||||
assertTrue(mService.isUidForegroundOnRestrictPowerUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_B));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_B));
|
||||
|
||||
callOnUidStatechanged(UID_A, PROCESS_STATE_IMPORTANT_FOREGROUND, procStateSeq++,
|
||||
PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK);
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_A));
|
||||
assertTrue(mService.isUidForegroundOnRestrictBackgroundUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_B));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_B));
|
||||
|
||||
callOnUidStatechanged(UID_A, PROCESS_STATE_TOP, procStateSeq++,
|
||||
PROCESS_CAPABILITY_NONE);
|
||||
assertTrue(mService.isUidForegroundOnRestrictPowerUL(UID_A));
|
||||
assertTrue(mService.isUidForegroundOnRestrictBackgroundUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_B));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_B));
|
||||
}
|
||||
waitForUidEventHandlerIdle();
|
||||
|
||||
assertTrue(mService.isUidForegroundOnRestrictPowerUL(UID_A));
|
||||
assertTrue(mService.isUidForegroundOnRestrictBackgroundUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_B));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_B));
|
||||
|
||||
try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
|
||||
callOnUidStatechanged(UID_A, PROCESS_STATE_SERVICE, procStateSeq++,
|
||||
PROCESS_CAPABILITY_NONE);
|
||||
assertTrue(mService.isUidForegroundOnRestrictPowerUL(UID_A));
|
||||
assertTrue(mService.isUidForegroundOnRestrictBackgroundUL(UID_A));
|
||||
assertFalse(mService.isUidForegroundOnRestrictPowerUL(UID_B));
|
||||
assertFalse(mService.isUidForegroundOnRestrictBackgroundUL(UID_B));
|
||||
}
|
||||
waitForUidEventHandlerIdle();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1417,14 +1531,28 @@ public class NetworkPolicyManagerServiceTest {
|
||||
@Test
|
||||
public void testOnUidStateChanged_notifyAMS() throws Exception {
|
||||
final long procStateSeq = 222;
|
||||
callOnUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE, procStateSeq);
|
||||
callAndWaitOnUidStateChanged(UID_A, PROCESS_STATE_SERVICE, procStateSeq);
|
||||
verify(mActivityManagerInternal).notifyNetworkPolicyRulesUpdated(UID_A, procStateSeq);
|
||||
}
|
||||
|
||||
private void callOnUidStateChanged(int uid, int procState, long procStateSeq)
|
||||
private void callAndWaitOnUidStateChanged(int uid, int procState, long procStateSeq)
|
||||
throws Exception {
|
||||
mUidObserver.onUidStateChanged(uid, procState, procStateSeq,
|
||||
ActivityManager.PROCESS_CAPABILITY_NONE);
|
||||
callAndWaitOnUidStateChanged(uid, procState, procStateSeq,
|
||||
PROCESS_CAPABILITY_NONE);
|
||||
}
|
||||
|
||||
private void callAndWaitOnUidStateChanged(int uid, int procState, long procStateSeq,
|
||||
int capability) throws Exception {
|
||||
callOnUidStatechanged(uid, procState, procStateSeq, capability);
|
||||
waitForUidEventHandlerIdle();
|
||||
}
|
||||
|
||||
private void callOnUidStatechanged(int uid, int procState, long procStateSeq, int capability)
|
||||
throws Exception {
|
||||
mUidObserver.onUidStateChanged(uid, procState, procStateSeq, capability);
|
||||
}
|
||||
|
||||
private void waitForUidEventHandlerIdle() throws Exception {
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
mService.mUidEventHandler.post(() -> {
|
||||
latch.countDown();
|
||||
@@ -1927,9 +2055,9 @@ public class NetworkPolicyManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void testLowPowerStandbyAllowlist() throws Exception {
|
||||
callOnUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP, 0);
|
||||
callOnUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
|
||||
callOnUidStateChanged(UID_C, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
|
||||
callAndWaitOnUidStateChanged(UID_A, PROCESS_STATE_TOP, 0);
|
||||
callAndWaitOnUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
|
||||
callAndWaitOnUidStateChanged(UID_C, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
|
||||
expectHasInternetPermission(UID_A, true);
|
||||
expectHasInternetPermission(UID_B, true);
|
||||
expectHasInternetPermission(UID_C, true);
|
||||
|
||||
Reference in New Issue
Block a user