summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/OWNERS2
-rw-r--r--core/java/android/app/ActivityManager.java5
-rw-r--r--core/java/android/app/ActivityManagerInternal.java19
-rw-r--r--core/java/android/net/NetworkPolicyManager.java6
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java122
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java2
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java3
-rw-r--r--services/core/java/com/android/server/am/PendingStartActivityUids.java4
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java20
-rw-r--r--services/core/java/com/android/server/am/UidObserverController.java1
-rw-r--r--services/core/java/com/android/server/am/UidRecord.java26
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java29
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyLogger.java56
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java640
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java141
-rw-r--r--services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java48
18 files changed, 720 insertions, 424 deletions
diff --git a/apex/jobscheduler/OWNERS b/apex/jobscheduler/OWNERS
index c77ea336990d..58434f165aa2 100644
--- a/apex/jobscheduler/OWNERS
+++ b/apex/jobscheduler/OWNERS
@@ -1,7 +1,9 @@
ctate@android.com
ctate@google.com
dplotnikov@google.com
+jji@google.com
kwekua@google.com
omakoto@google.com
suprabh@google.com
+varunshah@google.com
yamasani@google.com
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index db45466d98d2..6a877f97f180 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -4658,6 +4658,11 @@ public class ActivityManager {
}
/** @hide */
+ public static boolean isProcStateConsideredInteraction(@ProcessState int procState) {
+ return (procState <= PROCESS_STATE_TOP || procState == PROCESS_STATE_BOUND_TOP);
+ }
+
+ /** @hide */
public static String procStateToString(int procState) {
final String procStateStr;
switch (procState) {
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 4c30f56e40d6..7ec361922afc 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -209,6 +209,12 @@ public abstract class ActivityManagerInternal {
public abstract void notifyNetworkPolicyRulesUpdated(int uid, long procStateSeq);
/**
+ * Inform ActivityManagerService about the latest {@code blockedReasons} for an uid, which
+ * can be used to understand whether the {@code uid} is allowed to access network or not.
+ */
+ public abstract void onUidBlockedReasonsChanged(int uid, int blockedReasons);
+
+ /**
* @return true if runtime was restarted, false if it's normal boot
*/
public abstract boolean isRuntimeRestarted();
@@ -581,7 +587,7 @@ public abstract class ActivityManagerInternal {
* @param uid uid
* @param pid pid of the ProcessRecord that is pending top.
*/
- public abstract void addPendingTopUid(int uid, int pid);
+ public abstract void addPendingTopUid(int uid, int pid, @Nullable IApplicationThread thread);
/**
* Delete uid from the ActivityManagerService PendingStartActivityUids list.
@@ -680,4 +686,15 @@ public abstract class ActivityManagerInternal {
*/
void notifyActivityEventChanged();
}
+
+ /**
+ * Register the UidObserver for NetworkPolicyManager service.
+ *
+ * This is equivalent to calling
+ * {@link IActivityManager#registerUidObserver(IUidObserver, int, int, String)} but having a
+ * separate method for NetworkPolicyManager service so that it's UidObserver can be called
+ * separately outside the usual UidObserver flow.
+ */
+ public abstract void registerNetworkPolicyUidObserver(@NonNull IUidObserver observer,
+ int which, int cutpoint, @NonNull String callingPackage);
}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 2c2a703b16e2..9341105675a2 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -817,11 +817,13 @@ public class NetworkPolicyManager {
public static final class UidState {
public int uid;
public int procState;
+ public long procStateSeq;
public int capability;
- public UidState(int uid, int procState, int capability) {
+ public UidState(int uid, int procState, long procStateSeq, int capability) {
this.uid = uid;
this.procState = procState;
+ this.procStateSeq = procStateSeq;
this.capability = capability;
}
@@ -830,6 +832,8 @@ public class NetworkPolicyManager {
final StringBuilder sb = new StringBuilder();
sb.append("{procState=");
sb.append(procStateToString(procState));
+ sb.append(",seq=");
+ sb.append(procStateSeq);
sb.append(",cap=");
ActivityManager.printCapabilitiesSummary(sb, capability);
sb.append("}");
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0f450e16be2d..ec9f1fe9212a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -28,6 +28,7 @@ import static android.app.ActivityManager.INSTR_FLAG_DISABLE_ISOLATED_STORAGE;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS;
import static android.app.ActivityManager.INSTR_FLAG_NO_RESTART;
import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
@@ -45,6 +46,13 @@ import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+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;
+import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
+import static android.net.ConnectivityManager.BLOCKED_REASON_DOZE;
+import static android.net.ConnectivityManager.BLOCKED_REASON_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
import static android.os.FactoryTest.FACTORY_TEST_OFF;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
@@ -1415,6 +1423,10 @@ public class ActivityManagerService extends IActivityManager.Stub
final ActivityThread mSystemThread;
final UidObserverController mUidObserverController;
+ private volatile IUidObserver mNetworkPolicyUidObserver;
+
+ @GuardedBy("mUidNetworkBlockedReasons")
+ private final SparseIntArray mUidNetworkBlockedReasons = new SparseIntArray();
private final class AppDeathRecipient implements IBinder.DeathRecipient {
final ProcessRecord mApp;
@@ -6784,6 +6796,9 @@ public class ActivityManagerService extends IActivityManager.Stub
}
synchronized (mProcLock) {
+ if (mPendingStartActivityUids.isPendingTopUid(uid)) {
+ return PROCESS_STATE_TOP;
+ }
return mProcessList.getUidProcStateLOSP(uid);
}
}
@@ -10375,7 +10390,7 @@ public class ActivityManagerService extends IActivityManager.Stub
"Native",
"System", "Persistent", "Persistent Service", "Foreground",
"Visible", "Perceptible", "Perceptible Low", "Perceptible Medium",
- "Heavy Weight", "Backup",
+ "Backup", "Heavy Weight",
"A Services", "Home",
"Previous", "B Services", "Cached"
};
@@ -10383,7 +10398,7 @@ public class ActivityManagerService extends IActivityManager.Stub
"native",
"sys", "pers", "persvc", "fore",
"vis", "percept", "perceptl", "perceptm",
- "heavy", "backup",
+ "backup", "heavy",
"servicea", "home",
"prev", "serviceb", "cached"
};
@@ -14447,7 +14462,6 @@ public class ActivityManagerService extends IActivityManager.Stub
uid, change, procState, procStateSeq, capability, ephemeral);
if (uidRec != null) {
uidRec.setLastReportedChange(enqueuedChange);
- uidRec.updateLastDispatchedProcStateSeq(enqueuedChange);
}
// Directly update the power manager, since we sit on top of it and it is critical
@@ -15585,18 +15599,13 @@ public class ActivityManagerService extends IActivityManager.Stub
return;
}
record.lastNetworkUpdatedProcStateSeq = procStateSeq;
- if (record.curProcStateSeq > procStateSeq) {
- if (DEBUG_NETWORK) {
- Slog.d(TAG_NETWORK, "No need to handle older seq no., Uid: " + uid
- + ", curProcstateSeq: " + record.curProcStateSeq
- + ", procStateSeq: " + procStateSeq);
- }
- return;
- }
- if (record.waitingForNetwork) {
+ if (record.procStateSeqWaitingForNetwork != 0
+ && procStateSeq >= record.procStateSeqWaitingForNetwork) {
if (DEBUG_NETWORK) {
Slog.d(TAG_NETWORK, "Notifying all blocking threads for uid: " + uid
- + ", procStateSeq: " + procStateSeq);
+ + ", procStateSeq: " + procStateSeq
+ + ", procStateSeqWaitingForNetwork: "
+ + record.procStateSeqWaitingForNetwork);
}
record.networkStateLock.notifyAll();
}
@@ -15604,6 +15613,17 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
+ public void onUidBlockedReasonsChanged(int uid, int blockedReasons) {
+ synchronized (mUidNetworkBlockedReasons) {
+ if (blockedReasons == BLOCKED_REASON_NONE) {
+ mUidNetworkBlockedReasons.delete(uid);
+ } else {
+ mUidNetworkBlockedReasons.put(uid, blockedReasons);
+ }
+ }
+ }
+
+ @Override
public boolean isRuntimeRestarted() {
return mSystemServiceManager.isRuntimeRestarted();
}
@@ -16301,8 +16321,51 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
- public void addPendingTopUid(int uid, int pid) {
- mPendingStartActivityUids.add(uid, pid);
+ public void addPendingTopUid(int uid, int pid, @Nullable IApplicationThread thread) {
+ final boolean isNewPending = mPendingStartActivityUids.add(uid, pid);
+ // We need to update the network rules for the app coming to the top state so that
+ // it can access network when the device or the app is in a restricted state
+ // (e.g. battery/data saver) but since waiting for updateOomAdj to complete and then
+ // informing NetworkPolicyManager might get delayed, informing the state change as soon
+ // as we know app is going to come to the top state.
+ if (isNewPending && mNetworkPolicyUidObserver != null) {
+ try {
+ final long procStateSeq = mProcessList.getNextProcStateSeq();
+ mNetworkPolicyUidObserver.onUidStateChanged(uid, PROCESS_STATE_TOP,
+ procStateSeq, PROCESS_CAPABILITY_ALL);
+ if (thread != null && isNetworkingBlockedForUid(uid)) {
+ thread.setNetworkBlockSeq(procStateSeq);
+ }
+ } catch (RemoteException e) {
+ Slog.d(TAG, "Error calling setNetworkBlockSeq", e);
+ }
+ }
+ }
+
+ private boolean isNetworkingBlockedForUid(int uid) {
+ synchronized (mUidNetworkBlockedReasons) {
+ // TODO: We can consider only those blocked reasons that will be overridden
+ // by the TOP state. For other ones, there is no point in waiting.
+ // TODO: We can reuse this data in
+ // ProcessList#incrementProcStateSeqAndNotifyAppsLOSP instead of calling into
+ // NetworkManagementService.
+ final int uidBlockedReasons = mUidNetworkBlockedReasons.get(
+ uid, BLOCKED_REASON_NONE);
+ if (uidBlockedReasons == BLOCKED_REASON_NONE) {
+ return false;
+ }
+ final int topExemptedBlockedReasons = BLOCKED_REASON_BATTERY_SAVER
+ | BLOCKED_REASON_DOZE
+ | BLOCKED_REASON_APP_STANDBY
+ | BLOCKED_REASON_LOW_POWER_STANDBY
+ | BLOCKED_METERED_REASON_DATA_SAVER
+ | BLOCKED_METERED_REASON_USER_RESTRICTED;
+ final int effectiveBlockedReasons =
+ uidBlockedReasons & ~topExemptedBlockedReasons;
+ // Only consider it as blocked if it is not blocked by a reason
+ // that is not exempted by app being in the top state.
+ return effectiveBlockedReasons == BLOCKED_REASON_NONE;
+ }
}
@Override
@@ -16449,6 +16512,14 @@ public class ActivityManagerService extends IActivityManager.Stub
public void setStopUserOnSwitch(int value) {
ActivityManagerService.this.setStopUserOnSwitch(value);
}
+
+ @Override
+ public void registerNetworkPolicyUidObserver(@NonNull IUidObserver observer,
+ int which, int cutpoint, @NonNull String callingPackage) {
+ mNetworkPolicyUidObserver = observer;
+ mUidObserverController.register(observer, which, cutpoint, callingPackage,
+ Binder.getCallingUid());
+ }
}
long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
@@ -16528,23 +16599,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
synchronized (record.networkStateLock) {
- if (record.lastDispatchedProcStateSeq < procStateSeq) {
- if (DEBUG_NETWORK) {
- Slog.d(TAG_NETWORK, "Uid state change for seq no. " + procStateSeq + " is not "
- + "dispatched to NPMS yet, so don't wait. Uid: " + callingUid
- + " lastProcStateSeqDispatchedToObservers: "
- + record.lastDispatchedProcStateSeq);
- }
- return;
- }
- if (record.curProcStateSeq > procStateSeq) {
- if (DEBUG_NETWORK) {
- Slog.d(TAG_NETWORK, "Ignore the wait requests for older seq numbers. Uid: "
- + callingUid + ", curProcStateSeq: " + record.curProcStateSeq
- + ", procStateSeq: " + procStateSeq);
- }
- return;
- }
if (record.lastNetworkUpdatedProcStateSeq >= procStateSeq) {
if (DEBUG_NETWORK) {
Slog.d(TAG_NETWORK, "Network rules have been already updated for seq no. "
@@ -16560,9 +16614,9 @@ public class ActivityManagerService extends IActivityManager.Stub
+ " Uid: " + callingUid + " procStateSeq: " + procStateSeq);
}
final long startTime = SystemClock.uptimeMillis();
- record.waitingForNetwork = true;
+ record.procStateSeqWaitingForNetwork = procStateSeq;
record.networkStateLock.wait(mWaitForNetworkTimeoutMs);
- record.waitingForNetwork = false;
+ record.procStateSeqWaitingForNetwork = 0;
final long totalTime = SystemClock.uptimeMillis() - startTime;
if (totalTime >= mWaitForNetworkTimeoutMs || DEBUG_NETWORK) {
Slog.w(TAG_NETWORK, "Total time waited for network rules to get updated: "
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 2030b19b6b9a..dedd89883687 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1978,7 +1978,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
mHandler.post(() -> {
synchronized (mStats) {
mStats.noteBluetoothScanStoppedFromSourceLocked(localWs, isUnoptimized,
- uptime, elapsedRealtime);
+ elapsedRealtime, uptime);
}
});
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 9e0441004568..ce40f85972f5 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -2911,8 +2911,7 @@ public class OomAdjuster {
// To avoid some abuse patterns, we are going to be careful about what we consider
// to be an app interaction. Being the top activity doesn't count while the display
// is sleeping, nor do short foreground services.
- if (state.getCurProcState() <= PROCESS_STATE_TOP
- || state.getCurProcState() == PROCESS_STATE_BOUND_TOP) {
+ if (ActivityManager.isProcStateConsideredInteraction(state.getCurProcState())) {
isInteraction = true;
state.setFgInteractionTime(0);
} else if (state.getCurProcState() <= PROCESS_STATE_FOREGROUND_SERVICE) {
diff --git a/services/core/java/com/android/server/am/PendingStartActivityUids.java b/services/core/java/com/android/server/am/PendingStartActivityUids.java
index 20f6bb205dc4..5beda3197581 100644
--- a/services/core/java/com/android/server/am/PendingStartActivityUids.java
+++ b/services/core/java/com/android/server/am/PendingStartActivityUids.java
@@ -44,10 +44,12 @@ final class PendingStartActivityUids {
mContext = context;
}
- synchronized void add(int uid, int pid) {
+ synchronized boolean add(int uid, int pid) {
if (mPendingUids.get(uid) == null) {
mPendingUids.put(uid, new Pair<>(pid, SystemClock.elapsedRealtime()));
+ return true;
}
+ return false;
}
synchronized void delete(int uid, long nowElapsed) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 1e66ed42ff96..dc80c4b33297 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -482,9 +482,8 @@ public final class ProcessList {
* Having a global counter ensures that seq numbers are monotonically increasing for a
* particular uid even when the uidRecord is re-created.
*/
- @GuardedBy("mService")
@VisibleForTesting
- long mProcStateSeqCounter = 0;
+ volatile long mProcStateSeqCounter = 0;
/**
* A global counter for generating sequence numbers to uniquely identify pending process starts.
@@ -4878,13 +4877,17 @@ public final class ProcessList {
}
/**
- * Checks if any uid is coming from background to foreground or vice versa and if so, increments
- * the {@link UidRecord#curProcStateSeq} corresponding to that uid using global seq counter
- * {@link ProcessList#mProcStateSeqCounter} and notifies the app if it needs to block.
+ * Increments the {@link UidRecord#curProcStateSeq} for all uids using global seq counter
+ * {@link ProcessList#mProcStateSeqCounter} and checks if any uid is coming
+ * from background to foreground or vice versa and if so, notifies the app if it needs to block.
*/
@VisibleForTesting
@GuardedBy(anyOf = {"mService", "mProcLock"})
void incrementProcStateSeqAndNotifyAppsLOSP(ActiveUids activeUids) {
+ for (int i = activeUids.size() - 1; i >= 0; --i) {
+ final UidRecord uidRec = activeUids.valueAt(i);
+ uidRec.curProcStateSeq = getNextProcStateSeq();
+ }
if (mService.mWaitForNetworkTimeoutMs <= 0) {
return;
}
@@ -4911,7 +4914,6 @@ public final class ProcessList {
continue;
}
synchronized (uidRec.networkStateLock) {
- uidRec.curProcStateSeq = ++mProcStateSeqCounter; // TODO: use method
if (blockState == NETWORK_STATE_BLOCK) {
if (blockingUids == null) {
blockingUids = new ArrayList<>();
@@ -4922,7 +4924,7 @@ public final class ProcessList {
Slog.d(TAG_NETWORK, "uid going to background, notifying all blocking"
+ " threads for uid: " + uidRec);
}
- if (uidRec.waitingForNetwork) {
+ if (uidRec.procStateSeqWaitingForNetwork != 0) {
uidRec.networkStateLock.notifyAll();
}
}
@@ -4956,6 +4958,10 @@ public final class ProcessList {
}
}
+ long getNextProcStateSeq() {
+ return ++mProcStateSeqCounter;
+ }
+
/**
* Create a server socket in system_server, zygote will connect to it
* in order to send unsolicited messages to system_server.
diff --git a/services/core/java/com/android/server/am/UidObserverController.java b/services/core/java/com/android/server/am/UidObserverController.java
index c1bfe25618b2..67b9ae67bbd9 100644
--- a/services/core/java/com/android/server/am/UidObserverController.java
+++ b/services/core/java/com/android/server/am/UidObserverController.java
@@ -219,7 +219,6 @@ public class UidObserverController {
validateUid.setCurProcState(item.procState);
validateUid.setSetCapability(item.capability);
validateUid.setCurCapability(item.capability);
- validateUid.lastDispatchedProcStateSeq = item.procStateSeq;
}
}
}
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index 4ba59faea9ec..2ec08a45236f 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -95,16 +95,9 @@ public final class UidRecord {
long lastNetworkUpdatedProcStateSeq;
/**
- * Last seq number for which AcitivityManagerService dispatched uid state change to
- * NetworkPolicyManagerService.
+ * Indicates if any thread is waiting for network rules to get updated for {@link #mUid}.
*/
- @GuardedBy("networkStateUpdate")
- long lastDispatchedProcStateSeq;
-
- /**
- * Indicates if any thread is waiting for network rules to get updated for {@link #uid}.
- */
- volatile boolean waitingForNetwork;
+ volatile long procStateSeqWaitingForNetwork;
/**
* Indicates whether this uid has internet permission or not.
@@ -309,18 +302,6 @@ public final class UidRecord {
mUid) == PackageManager.PERMISSION_GRANTED;
}
- /**
- * If the change being dispatched is not CHANGE_GONE (not interested in
- * these changes), then update the {@link #lastDispatchedProcStateSeq} with
- * {@link #curProcStateSeq}.
- */
- public void updateLastDispatchedProcStateSeq(int changeToDispatch) {
- if ((changeToDispatch & CHANGE_GONE) == 0) {
- lastDispatchedProcStateSeq = curProcStateSeq;
- }
- }
-
-
void dumpDebug(ProtoOutputStream proto, long fieldId) {
long token = proto.start(fieldId);
proto.write(UidRecordProto.UID, mUid);
@@ -341,7 +322,6 @@ public final class UidRecord {
proto.write(UidRecordProto.ProcStateSequence.CURURENT, curProcStateSeq);
proto.write(UidRecordProto.ProcStateSequence.LAST_NETWORK_UPDATED,
lastNetworkUpdatedProcStateSeq);
- proto.write(UidRecordProto.ProcStateSequence.LAST_DISPATCHED, lastDispatchedProcStateSeq);
proto.end(seqToken);
proto.end(token);
@@ -412,8 +392,6 @@ public final class UidRecord {
sb.append(curProcStateSeq);
sb.append(",");
sb.append(lastNetworkUpdatedProcStateSeq);
- sb.append(",");
- sb.append(lastDispatchedProcStateSeq);
sb.append(")}");
return sb.toString();
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 33440a3591f6..c53a9a63be65 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -85,6 +85,7 @@ import android.net.ipsec.ike.ChildSessionParams;
import android.net.ipsec.ike.IkeSession;
import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.IkeSessionParams;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
@@ -2267,6 +2268,11 @@ public class Vpn {
profile.setAllowedAlgorithms(Ikev2VpnProfile.DEFAULT_ALGORITHMS);
startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN);
return;
+ case VpnProfile.TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS:
+ // All the necessary IKE options should come from IkeTunnelConnectionParams in the
+ // profile.
+ startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN);
+ return;
case VpnProfile.TYPE_L2TP_IPSEC_PSK:
racoon = new String[] {
iface, profile.server, "udppsk", profile.ipsecIdentifier,
@@ -2702,10 +2708,23 @@ public class Vpn {
resetIkeState();
mActiveNetwork = network;
- final IkeSessionParams ikeSessionParams =
- VpnIkev2Utils.buildIkeSessionParams(mContext, mProfile, network);
- final ChildSessionParams childSessionParams =
- VpnIkev2Utils.buildChildSessionParams(mProfile.getAllowedAlgorithms());
+ // Get Ike options from IkeTunnelConnectionParams if it's available in the
+ // profile.
+ final IkeTunnelConnectionParams ikeTunConnParams =
+ mProfile.getIkeTunnelConnectionParams();
+ final IkeSessionParams ikeSessionParams;
+ final ChildSessionParams childSessionParams;
+ if (ikeTunConnParams != null) {
+ final IkeSessionParams.Builder builder = new IkeSessionParams.Builder(
+ ikeTunConnParams.getIkeSessionParams()).setNetwork(network);
+ ikeSessionParams = builder.build();
+ childSessionParams = ikeTunConnParams.getTunnelModeChildSessionParams();
+ } else {
+ ikeSessionParams = VpnIkev2Utils.buildIkeSessionParams(
+ mContext, mProfile, network);
+ childSessionParams = VpnIkev2Utils.buildChildSessionParams(
+ mProfile.getAllowedAlgorithms());
+ }
// TODO: Remove the need for adding two unused addresses with
// IPsec tunnels.
@@ -3226,6 +3245,7 @@ public class Vpn {
case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
+ case VpnProfile.TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS:
if (!mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_IPSEC_TUNNELS)) {
throw new UnsupportedOperationException(
@@ -3399,6 +3419,7 @@ public class Vpn {
case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
+ case VpnProfile.TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS:
mVpnRunner =
new IkeV2VpnRunner(Ikev2VpnProfile.fromVpnProfile(profile));
mVpnRunner.start();
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 33ac6cdb269e..c9631549cd76 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -77,6 +77,8 @@ public class NetworkPolicyLogger {
private static final int EVENT_FIREWALL_CHAIN_ENABLED = 12;
private static final int EVENT_UPDATE_METERED_RESTRICTED_PKGS = 13;
private static final int EVENT_APP_IDLE_WL_CHANGED = 14;
+ private static final int EVENT_METERED_ALLOWLIST_CHANGED = 15;
+ private static final int EVENT_METERED_DENYLIST_CHANGED = 16;
private final LogBuffer mNetworkBlockedBuffer = new LogBuffer(MAX_NETWORK_BLOCKED_LOG_SIZE);
private final LogBuffer mUidStateChangeBuffer = new LogBuffer(MAX_LOG_SIZE);
@@ -89,7 +91,7 @@ public class NetworkPolicyLogger {
void networkBlocked(int uid, @Nullable UidBlockedState uidBlockedState) {
synchronized (mLock) {
if (LOGD || uid == mDebugUid) {
- Slog.d(TAG, "Blocked state of uid: " + uidBlockedState.toString());
+ Slog.d(TAG, "Blocked state of " + uid + ": " + uidBlockedState.toString());
}
if (uidBlockedState == null) {
mNetworkBlockedBuffer.networkBlocked(uid, BLOCKED_REASON_NONE, ALLOWED_REASON_NONE,
@@ -245,6 +247,24 @@ public class NetworkPolicyLogger {
}
}
+ void meteredAllowlistChanged(int uid, boolean added) {
+ synchronized (mLock) {
+ if (LOGD || mDebugUid == uid) {
+ Slog.d(TAG, getMeteredAllowlistChangedLog(uid, added));
+ }
+ mEventsBuffer.meteredAllowlistChanged(uid, added);
+ }
+ }
+
+ void meteredDenylistChanged(int uid, boolean added) {
+ synchronized (mLock) {
+ if (LOGD || mDebugUid == uid) {
+ Slog.d(TAG, getMeteredDenylistChangedLog(uid, added));
+ }
+ mEventsBuffer.meteredDenylistChanged(uid, added);
+ }
+ }
+
void setDebugUid(int uid) {
mDebugUid = uid;
}
@@ -320,6 +340,14 @@ public class NetworkPolicyLogger {
return "Firewall chain " + getFirewallChainName(chain) + " state: " + enabled;
}
+ private static String getMeteredAllowlistChangedLog(int uid, boolean added) {
+ return "metered-allowlist for " + uid + " changed to " + added;
+ }
+
+ private static String getMeteredDenylistChangedLog(int uid, boolean added) {
+ return "metered-denylist for " + uid + " changed to " + added;
+ }
+
private static String getFirewallChainName(int chain) {
switch (chain) {
case FIREWALL_CHAIN_DOZABLE:
@@ -520,6 +548,28 @@ public class NetworkPolicyLogger {
data.timeStamp = System.currentTimeMillis();
}
+ public void meteredAllowlistChanged(int uid, boolean added) {
+ final Data data = getNextSlot();
+ if (data == null) return;
+
+ data.reset();
+ data.type = EVENT_METERED_ALLOWLIST_CHANGED;
+ data.ifield1 = uid;
+ data.bfield1 = added;
+ data.timeStamp = System.currentTimeMillis();
+ }
+
+ public void meteredDenylistChanged(int uid, boolean added) {
+ final Data data = getNextSlot();
+ if (data == null) return;
+
+ data.reset();
+ data.type = EVENT_METERED_DENYLIST_CHANGED;
+ data.ifield1 = uid;
+ data.bfield1 = added;
+ data.timeStamp = System.currentTimeMillis();
+ }
+
public void reverseDump(IndentingPrintWriter pw) {
final Data[] allData = toArray();
for (int i = allData.length - 1; i >= 0; --i) {
@@ -567,6 +617,10 @@ public class NetworkPolicyLogger {
return getUidFirewallRuleChangedLog(data.ifield1, data.ifield2, data.ifield3);
case EVENT_FIREWALL_CHAIN_ENABLED:
return getFirewallChainEnabledLog(data.ifield1, data.bfield1);
+ case EVENT_METERED_ALLOWLIST_CHANGED:
+ return getMeteredAllowlistChangedLog(data.ifield1, data.bfield1);
+ case EVENT_METERED_DENYLIST_CHANGED:
+ return getMeteredDenylistChangedLog(data.ifield1, data.bfield1);
default:
return String.valueOf(data.type);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index ea851ba9669f..0c47efe57563 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -26,6 +26,9 @@ import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
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.procStateToString;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import static android.content.Intent.ACTION_PACKAGE_ADDED;
@@ -90,6 +93,8 @@ import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.RULE_REJECT_RESTRICTED_MODE;
import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED;
+import static android.net.NetworkPolicyManager.allowedReasonsToString;
+import static android.net.NetworkPolicyManager.blockedReasonsToString;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileInLowPowerStandby;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
@@ -160,6 +165,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -418,6 +424,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final int MSG_SET_NETWORK_TEMPLATE_ENABLED = 18;
private static final int MSG_SUBSCRIPTION_PLANS_CHANGED = 19;
private static final int MSG_STATS_PROVIDER_WARNING_OR_LIMIT_REACHED = 20;
+
// TODO: Add similar docs for other messages.
/**
* Message to indicate that reasons for why an uid is blocked changed.
@@ -425,7 +432,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* arg2 = newBlockedReasons
* obj = oldBlockedReasons
*/
- private static final int MSG_BLOCKED_REASON_CHANGED = 21;
+ private static final int MSG_UID_BLOCKED_REASON_CHANGED = 21;
+
/**
* Message to indicate that subscription plans expired and should be cleared.
* arg1 = subId
@@ -434,6 +442,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
*/
private static final int MSG_CLEAR_SUBSCRIPTION_PLANS = 22;
+ /**
+ * Message to indicate that reasons for why some uids are blocked changed.
+ * obj = SparseArray<SomeArgs> where key = uid and value = SomeArgs object with
+ * value.argi1 = oldEffectiveBlockedReasons,
+ * value.argi2 = newEffectiveBlockedReasons,
+ * value.argi3 = uidRules
+ */
+ private static final int MSG_UIDS_BLOCKED_REASONS_CHANGED = 23;
+
private static final int UID_MSG_STATE_CHANGED = 100;
private static final int UID_MSG_GONE = 101;
@@ -471,7 +488,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final Object mUidRulesFirstLock = new Object();
final Object mNetworkPoliciesSecondLock = new Object();
- @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"})
+ @GuardedBy(anyOf = {"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"})
volatile boolean mSystemReady;
@GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictBackground;
@@ -594,7 +611,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@GuardedBy("mUidRulesFirstLock")
private final SparseArray<UidState> mUidState = new SparseArray<>();
- @GuardedBy("mUidRulesFirstLock")
+ @GuardedBy("mUidBlockedState")
private final SparseArray<UidBlockedState> mUidBlockedState = new SparseArray<>();
/** Objects used temporarily while computing the new blocked state for each uid. */
@@ -909,6 +926,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
mAppStandby = LocalServices.getService(AppStandbyInternal.class);
+ mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
synchronized (mUidRulesFirstLock) {
synchronized (mNetworkPoliciesSecondLock) {
@@ -986,12 +1004,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
- mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
try {
final int changes = ActivityManager.UID_OBSERVER_PROCSTATE
| ActivityManager.UID_OBSERVER_GONE
| ActivityManager.UID_OBSERVER_CAPABILITY;
- mActivityManager.registerUidObserver(mUidObserver, changes,
+ mActivityManagerInternal.registerNetworkPolicyUidObserver(mUidObserver, changes,
NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE, "android");
mNetworkManager.registerObserver(mAlertObserver);
} catch (RemoteException e) {
@@ -1107,7 +1124,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
callbackInfo = new UidStateCallbackInfo();
mUidStateCallbackInfos.put(uid, callbackInfo);
}
- callbackInfo.update(uid, procState, procStateSeq, capability);
+ if (callbackInfo.procStateSeq == -1 || procStateSeq > callbackInfo.procStateSeq) {
+ callbackInfo.update(uid, procState, procStateSeq, capability);
+ }
if (!callbackInfo.isPending) {
mUidEventHandler.obtainMessage(UID_MSG_STATE_CHANGED, callbackInfo)
.sendToTarget();
@@ -1131,8 +1150,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final class UidStateCallbackInfo {
public int uid;
- public int procState;
- public long procStateSeq;
+ public int procState = ActivityManager.PROCESS_STATE_NONEXISTENT;
+ public long procStateSeq = -1;
@ProcessCapability
public int capability;
public boolean isPending;
@@ -3298,7 +3317,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (mSystemReady) {
// Device idle change means we need to rebuild rules for all
// known apps, so do a global refresh.
- updateRulesForRestrictPowerUL();
+ handleDeviceIdleModeChangedUL(enabled);
}
}
if (enabled) {
@@ -3947,7 +3966,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final SparseBooleanArray knownUids = new SparseBooleanArray();
collectKeys(mUidState, knownUids);
- collectKeys(mUidBlockedState, knownUids);
+ synchronized (mUidBlockedState) {
+ collectKeys(mUidBlockedState, knownUids);
+ }
fout.println("Status for all known UIDs:");
fout.increaseIndent();
@@ -3965,12 +3986,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
fout.print(uidState.toString());
}
- final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
- if (uidBlockedState == null) {
- fout.print(" blocked_state={null}");
- } else {
- fout.print(" blocked_state=");
- fout.print(uidBlockedState.toString());
+ 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.println();
}
@@ -4038,13 +4061,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* {@link #updateRulesForPowerRestrictionsUL(int)}. Returns true if the state was updated.
*/
@GuardedBy("mUidRulesFirstLock")
- private boolean updateUidStateUL(int uid, int procState, @ProcessCapability int capability) {
+ private boolean updateUidStateUL(int uid, int procState, long procStateSeq,
+ @ProcessCapability int capability) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateUidStateUL");
try {
final UidState oldUidState = mUidState.get(uid);
+ if (oldUidState != null && procStateSeq < oldUidState.procStateSeq) {
+ if (LOGV) {
+ Slog.v(TAG, "Ignoring older uid state updates; uid=" + uid
+ + ",procState=" + procStateToString(procState) + ",seq=" + procStateSeq
+ + ",cap=" + capability + ",oldUidState=" + oldUidState);
+ }
+ return false;
+ }
if (oldUidState == null || oldUidState.procState != procState
|| oldUidState.capability != capability) {
- final UidState newUidState = new UidState(uid, procState, capability);
+ final UidState newUidState = new UidState(uid, procState, procStateSeq, capability);
// state changed, push updated rules
mUidState.put(uid, newUidState);
updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, newUidState);
@@ -4052,14 +4084,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
!= isProcStateAllowedWhileIdleOrPowerSaveMode(newUidState);
if (allowedWhileIdleOrPowerSaveModeChanged) {
- updateRuleForAppIdleUL(uid);
+ updateRuleForAppIdleUL(uid, procState);
if (mDeviceIdleMode) {
updateRuleForDeviceIdleUL(uid);
}
if (mRestrictPower) {
updateRuleForRestrictPowerUL(uid);
}
- updateRulesForPowerRestrictionsUL(uid);
+ updateRulesForPowerRestrictionsUL(uid, procState);
}
if (mLowPowerStandbyActive) {
boolean allowedInLpsChanged =
@@ -4067,7 +4099,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
!= isProcStateAllowedWhileInLowPowerStandby(newUidState);
if (allowedInLpsChanged) {
if (!allowedWhileIdleOrPowerSaveModeChanged) {
- updateRulesForPowerRestrictionsUL(uid);
+ updateRulesForPowerRestrictionsUL(uid, procState);
}
updateRuleForLowPowerStandbyUL(uid);
}
@@ -4145,9 +4177,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mUidFirewallRestrictedModeRules.clear();
forEachUid("updateRestrictedModeAllowlist", uid -> {
synchronized (mUidRulesFirstLock) {
- final UidBlockedState uidBlockedState = updateBlockedReasonsForRestrictedModeUL(
+ final int effectiveBlockedReasons = updateBlockedReasonsForRestrictedModeUL(
uid);
- final int newFirewallRule = getRestrictedModeFirewallRule(uidBlockedState);
+ final int newFirewallRule = getRestrictedModeFirewallRule(effectiveBlockedReasons);
// setUidFirewallRulesUL will allowlist all uids that are passed to it, so only add
// non-default rules.
@@ -4167,7 +4199,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@VisibleForTesting
@GuardedBy("mUidRulesFirstLock")
void updateRestrictedModeForUidUL(int uid) {
- final UidBlockedState uidBlockedState = updateBlockedReasonsForRestrictedModeUL(uid);
+ final int effectiveBlockedReasons = updateBlockedReasonsForRestrictedModeUL(uid);
// if restricted networking mode is on, and the app has an access exemption, the uid rule
// will not change, but the firewall rule will have to be updated.
@@ -4175,37 +4207,48 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// Note: setUidFirewallRule also updates mUidFirewallRestrictedModeRules.
// In this case, default firewall rules can also be added.
setUidFirewallRuleUL(FIREWALL_CHAIN_RESTRICTED, uid,
- getRestrictedModeFirewallRule(uidBlockedState));
+ getRestrictedModeFirewallRule(effectiveBlockedReasons));
}
}
@GuardedBy("mUidRulesFirstLock")
- private UidBlockedState updateBlockedReasonsForRestrictedModeUL(int uid) {
- final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid(
- mUidBlockedState, uid);
- final int oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
- if (mRestrictedNetworkingMode) {
- uidBlockedState.blockedReasons |= BLOCKED_REASON_RESTRICTED_MODE;
- } else {
- uidBlockedState.blockedReasons &= ~BLOCKED_REASON_RESTRICTED_MODE;
- }
- if (hasRestrictedModeAccess(uid)) {
- uidBlockedState.allowedReasons |= ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
- } else {
- uidBlockedState.allowedReasons &= ~ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
+ private int updateBlockedReasonsForRestrictedModeUL(int uid) {
+ final boolean hasRestrictedModeAccess = hasRestrictedModeAccess(uid);
+ final int oldEffectiveBlockedReasons;
+ final int newEffectiveBlockedReasons;
+ final int uidRules;
+ synchronized (mUidBlockedState) {
+ final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid(
+ mUidBlockedState, uid);
+ oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
+ if (mRestrictedNetworkingMode) {
+ uidBlockedState.blockedReasons |= BLOCKED_REASON_RESTRICTED_MODE;
+ } else {
+ uidBlockedState.blockedReasons &= ~BLOCKED_REASON_RESTRICTED_MODE;
+ }
+ if (hasRestrictedModeAccess) {
+ uidBlockedState.allowedReasons |= ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
+ } else {
+ uidBlockedState.allowedReasons &= ~ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
+ }
+ uidBlockedState.updateEffectiveBlockedReasons();
+
+ newEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
+ uidRules = oldEffectiveBlockedReasons == newEffectiveBlockedReasons
+ ? RULE_NONE
+ : uidBlockedState.deriveUidRules();
}
- uidBlockedState.updateEffectiveBlockedReasons();
- if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) {
- postBlockedReasonsChangedMsg(uid,
- uidBlockedState.effectiveBlockedReasons, oldEffectiveBlockedReasons);
+ if (oldEffectiveBlockedReasons != newEffectiveBlockedReasons) {
+ handleBlockedReasonsChanged(uid,
+ newEffectiveBlockedReasons, oldEffectiveBlockedReasons);
- postUidRulesChangedMsg(uid, uidBlockedState.deriveUidRules());
+ postUidRulesChangedMsg(uid, uidRules);
}
- return uidBlockedState;
+ return newEffectiveBlockedReasons;
}
- private static int getRestrictedModeFirewallRule(UidBlockedState uidBlockedState) {
- if ((uidBlockedState.effectiveBlockedReasons & BLOCKED_REASON_RESTRICTED_MODE) != 0) {
+ private static int getRestrictedModeFirewallRule(int effectiveBlockedReasons) {
+ if ((effectiveBlockedReasons & BLOCKED_REASON_RESTRICTED_MODE) != 0) {
// rejected in restricted mode, this is the default behavior.
return FIREWALL_RULE_DEFAULT;
} else {
@@ -4309,12 +4352,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mUidFirewallLowPowerStandbyModeRules.clear();
for (int i = mUidState.size() - 1; i >= 0; i--) {
final int uid = mUidState.keyAt(i);
- UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
- if (hasInternetPermissionUL(uid) && uidBlockedState != null
- && (uidBlockedState.effectiveBlockedReasons
+ final int effectiveBlockedReasons = getEffectiveBlockedReasons(uid);
+ if (hasInternetPermissionUL(uid) && (effectiveBlockedReasons
& BLOCKED_REASON_LOW_POWER_STANDBY) == 0) {
- mUidFirewallLowPowerStandbyModeRules.put(mUidBlockedState.keyAt(i),
- FIREWALL_RULE_ALLOW);
+ mUidFirewallLowPowerStandbyModeRules.put(uid, FIREWALL_RULE_ALLOW);
}
}
setUidFirewallRulesUL(FIREWALL_CHAIN_LOW_POWER_STANDBY,
@@ -4333,10 +4374,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return;
}
- final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
- if (mUidState.contains(uid) && uidBlockedState != null
- && (uidBlockedState.effectiveBlockedReasons & BLOCKED_REASON_LOW_POWER_STANDBY)
- == 0) {
+ final int effectiveBlockedReasons = getEffectiveBlockedReasons(uid);
+ if (mUidState.contains(uid)
+ && (effectiveBlockedReasons & BLOCKED_REASON_LOW_POWER_STANDBY) == 0) {
mUidFirewallLowPowerStandbyModeRules.put(uid, FIREWALL_RULE_ALLOW);
setUidFirewallRuleUL(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid, FIREWALL_RULE_ALLOW);
} else {
@@ -4428,7 +4468,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@GuardedBy("mUidRulesFirstLock")
- void updateRuleForAppIdleUL(int uid) {
+ void updateRuleForAppIdleUL(int uid, int uidProcessState) {
if (!isUidValidForDenylistRulesUL(uid)) return;
if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
@@ -4436,7 +4476,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
try {
int appId = UserHandle.getAppId(uid);
- if (!mPowerSaveTempWhitelistAppIds.get(appId) && isUidIdle(uid)
+ if (!mPowerSaveTempWhitelistAppIds.get(appId) && isUidIdle(uid, uidProcessState)
&& !isUidForegroundOnRestrictPowerUL(uid)) {
setUidFirewallRuleUL(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DENY);
if (LOGD) Log.d(TAG, "updateRuleForAppIdleUL DENY " + uid);
@@ -4465,9 +4505,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (!isUidValidForDenylistRulesUL(uid)) {
continue;
}
- final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid(
- mUidBlockedState, uid);
- if (!enableChain && (uidBlockedState.blockedReasons & ~BLOCKED_METERED_REASON_MASK)
+ final int blockedReasons = getBlockedReasons(uid);
+ if (!enableChain && (blockedReasons & ~BLOCKED_METERED_REASON_MASK)
== BLOCKED_REASON_NONE) {
// Chain isn't enabled and the uid had no restrictions to begin with.
continue;
@@ -4512,6 +4551,71 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
+ @GuardedBy("mUidRulesFirstLock")
+ private void handleDeviceIdleModeChangedUL(boolean enabled) {
+ Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictPowerUL");
+ try {
+ updateRulesForDeviceIdleUL();
+ if (enabled) {
+ forEachUid("updateRulesForRestrictPower", uid -> {
+ synchronized (mUidRulesFirstLock) {
+ updateRulesForPowerRestrictionsUL(uid);
+ }
+ });
+ } else {
+ // TODO: Note that we could handle the case of enabling-doze state similar
+ // to this but first, we need to update how we listen to uid state changes
+ // so that we always get a callback when a process moves from a NONEXISTENT state
+ // to a "background" state.
+ handleDeviceIdleModeDisabledUL();
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
+ }
+ }
+
+ @GuardedBy("mUidRulesFirstLock")
+ private void handleDeviceIdleModeDisabledUL() {
+ Trace.traceBegin(TRACE_TAG_NETWORK, "handleDeviceIdleModeDisabledUL");
+ try {
+ final SparseArray<SomeArgs> uidStateUpdates = new SparseArray<>();
+ synchronized (mUidBlockedState) {
+ final int size = mUidBlockedState.size();
+ for (int i = 0; i < size; ++i) {
+ final int uid = mUidBlockedState.keyAt(i);
+ final UidBlockedState uidBlockedState = mUidBlockedState.valueAt(i);
+ if ((uidBlockedState.blockedReasons & BLOCKED_REASON_DOZE) == 0) {
+ continue;
+ }
+ uidBlockedState.blockedReasons &= ~BLOCKED_REASON_DOZE;
+ final int oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
+ uidBlockedState.updateEffectiveBlockedReasons();
+ if (LOGV) {
+ Log.v(TAG, "handleDeviceIdleModeDisabled(" + uid + "); "
+ + "newUidBlockedState=" + uidBlockedState
+ + ", oldEffectiveBlockedReasons=" + oldEffectiveBlockedReasons);
+ }
+ if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) {
+ final SomeArgs someArgs = SomeArgs.obtain();
+ someArgs.argi1 = oldEffectiveBlockedReasons;
+ someArgs.argi2 = uidBlockedState.effectiveBlockedReasons;
+ someArgs.argi3 = uidBlockedState.deriveUidRules();
+ uidStateUpdates.append(uid, someArgs);
+ // TODO: Update the state for all changed uids together.
+ mActivityManagerInternal.onUidBlockedReasonsChanged(uid,
+ uidBlockedState.effectiveBlockedReasons);
+ }
+ }
+ }
+ if (uidStateUpdates.size() != 0) {
+ mHandler.obtainMessage(MSG_UIDS_BLOCKED_REASONS_CHANGED, uidStateUpdates)
+ .sendToTarget();
+ }
+ } finally {
+ Trace.traceEnd(TRACE_TAG_NETWORK);
+ }
+ }
+
// TODO: rename / document to make it clear these are global (not app-specific) rules
@GuardedBy("mUidRulesFirstLock")
private void updateRulesForRestrictPowerUL() {
@@ -4543,9 +4647,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
try {
// update rules for all installed applications
- final PackageManager pm = mContext.getPackageManager();
final List<UserInfo> users;
- final List<ApplicationInfo> apps;
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "list-users");
try {
@@ -4553,26 +4655,30 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} finally {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
- Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "list-uids");
+ Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "iterate-uids");
try {
- apps = pm.getInstalledApplications(
- PackageManager.MATCH_ANY_USER | PackageManager.MATCH_DISABLED_COMPONENTS
- | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
+ final PackageManagerInternal packageManagerInternal = LocalServices.getService(
+ PackageManagerInternal.class);
+ final int usersSize = users.size();
+ for (int i = 0; i < usersSize; ++i) {
+ final int userId = users.get(i).id;
+ final SparseBooleanArray sharedAppIdsHandled = new SparseBooleanArray();
+ packageManagerInternal.forEachInstalledPackage(androidPackage -> {
+ final int appId = androidPackage.getUid();
+ if (androidPackage.getSharedUserId() != null) {
+ if (sharedAppIdsHandled.indexOfKey(appId) < 0) {
+ sharedAppIdsHandled.put(appId, true);
+ } else {
+ return;
+ }
+ }
+ final int uid = UserHandle.getUid(userId, appId);
+ consumer.accept(uid);
+ }, userId);
+ }
} finally {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
-
- final int usersSize = users.size();
- final int appsSize = apps.size();
- for (int i = 0; i < usersSize; i++) {
- final UserInfo user = users.get(i);
- for (int j = 0; j < appsSize; j++) {
- final ApplicationInfo app = apps.get(j);
- final int uid = UserHandle.getUid(user.id, app.uid);
- consumer.accept(uid);
- }
- }
} finally {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
@@ -4586,7 +4692,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final UserInfo user = users.get(i);
int uid = UserHandle.getUid(user.id, appId);
// Update external firewall rules.
- updateRuleForAppIdleUL(uid);
+ updateRuleForAppIdleUL(uid, PROCESS_STATE_UNKNOWN);
updateRuleForDeviceIdleUL(uid);
updateRuleForRestrictPowerUL(uid);
// Update internal rules.
@@ -4634,7 +4740,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} else {
mAppIdleTempWhitelistAppIds.delete(uid);
}
- updateRuleForAppIdleUL(uid);
+ updateRuleForAppIdleUL(uid, PROCESS_STATE_UNKNOWN);
updateRulesForPowerRestrictionsUL(uid);
} finally {
Binder.restoreCallingIdentity(token);
@@ -4660,7 +4766,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/** Returns if the UID is currently considered idle. */
@VisibleForTesting
boolean isUidIdle(int uid) {
+ return isUidIdle(uid, PROCESS_STATE_UNKNOWN);
+ }
+
+ private boolean isUidIdle(int uid, int uidProcessState) {
synchronized (mUidRulesFirstLock) {
+ if (uidProcessState != PROCESS_STATE_UNKNOWN && isProcStateConsideredInteraction(
+ uidProcessState)) {
+ return false;
+ }
if (mAppIdleTempWhitelistAppIds.get(uid)) {
// UID is temporarily allowlisted.
return false;
@@ -4709,7 +4823,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@GuardedBy("mUidRulesFirstLock")
private void onUidDeletedUL(int uid) {
// First cleanup in-memory state synchronously...
- mUidBlockedState.delete(uid);
+ synchronized (mUidBlockedState) {
+ mUidBlockedState.delete(uid);
+ }
+ mUidState.delete(uid);
+ mActivityManagerInternal.onUidBlockedReasonsChanged(uid, BLOCKED_REASON_NONE);
mUidPolicy.delete(uid);
mUidFirewallStandbyRules.delete(uid);
mUidFirewallDozableRules.delete(uid);
@@ -4745,7 +4863,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private void updateRestrictionRulesForUidUL(int uid) {
// Methods below only changes the firewall rules for the power-related modes.
updateRuleForDeviceIdleUL(uid);
- updateRuleForAppIdleUL(uid);
+ updateRuleForAppIdleUL(uid, PROCESS_STATE_UNKNOWN);
updateRuleForRestrictPowerUL(uid);
// If the uid has the necessary permissions, then it should be added to the restricted mode
@@ -4821,11 +4939,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
final boolean isForeground = isUidForegroundOnRestrictBackgroundUL(uid);
final boolean isRestrictedByAdmin = isRestrictedByAdminUL(uid);
- final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid(
- mUidBlockedState, uid);
- final UidBlockedState previousUidBlockedState = getOrCreateUidBlockedStateForUid(
- mTmpUidBlockedState, uid);
- previousUidBlockedState.copyFrom(uidBlockedState);
final boolean isDenied = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
final boolean isAllowed = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0;
@@ -4840,18 +4953,47 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
newAllowedReasons |= (isForeground ? ALLOWED_METERED_REASON_FOREGROUND : 0);
newAllowedReasons |= (isAllowed ? ALLOWED_METERED_REASON_USER_EXEMPTED : 0);
- uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
- & ~BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
- uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons
- & ~ALLOWED_METERED_REASON_MASK) | newAllowedReasons;
- uidBlockedState.updateEffectiveBlockedReasons();
- final int oldEffectiveBlockedReasons = previousUidBlockedState.effectiveBlockedReasons;
- final int newEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
+ final int oldEffectiveBlockedReasons;
+ final int newEffectiveBlockedReasons;
+ final int oldAllowedReasons;
+ final int uidRules;
+ synchronized (mUidBlockedState) {
+ final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid(
+ mUidBlockedState, uid);
+ final UidBlockedState previousUidBlockedState = getOrCreateUidBlockedStateForUid(
+ mTmpUidBlockedState, uid);
+ previousUidBlockedState.copyFrom(uidBlockedState);
+
+ uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
+ & ~BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
+ uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons
+ & ~ALLOWED_METERED_REASON_MASK) | newAllowedReasons;
+ uidBlockedState.updateEffectiveBlockedReasons();
+
+ oldEffectiveBlockedReasons = previousUidBlockedState.effectiveBlockedReasons;
+ newEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
+ oldAllowedReasons = previousUidBlockedState.allowedReasons;
+ uidRules = (oldEffectiveBlockedReasons == newEffectiveBlockedReasons)
+ ? RULE_NONE : uidBlockedState.deriveUidRules();
+
+ if (LOGV) {
+ Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")"
+ + ": isForeground=" + isForeground
+ + ", isDenied=" + isDenied
+ + ", isAllowed=" + isAllowed
+ + ", isRestrictedByAdmin=" + isRestrictedByAdmin
+ + ", oldBlockedState=" + previousUidBlockedState
+ + ", newBlockedState=" + uidBlockedState
+ + ", newBlockedMeteredReasons=" + blockedReasonsToString(newBlockedReasons)
+ + ", newAllowedMeteredReasons=" + allowedReasonsToString(
+ newAllowedReasons));
+ }
+ }
if (oldEffectiveBlockedReasons != newEffectiveBlockedReasons) {
- postBlockedReasonsChangedMsg(uid,
+ handleBlockedReasonsChanged(uid,
newEffectiveBlockedReasons, oldEffectiveBlockedReasons);
- postUidRulesChangedMsg(uid, uidBlockedState.deriveUidRules());
+ postUidRulesChangedMsg(uid, uidRules);
}
// Note that the conditionals below are for avoiding unnecessary calls to netd.
@@ -4867,29 +5009,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
final int allowlistReasons = ALLOWED_METERED_REASON_FOREGROUND
| ALLOWED_METERED_REASON_USER_EXEMPTED;
- final int oldAllowedReasons = previousUidBlockedState.allowedReasons;
if ((oldAllowedReasons & allowlistReasons) != ALLOWED_REASON_NONE
|| (newAllowedReasons & allowlistReasons) != ALLOWED_REASON_NONE) {
setMeteredNetworkAllowlist(uid,
(newAllowedReasons & allowlistReasons) != ALLOWED_REASON_NONE);
}
-
- if (LOGV) {
- Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")"
- + ": isForeground=" +isForeground
- + ", isDenied=" + isDenied
- + ", isAllowed=" + isAllowed
- + ", isRestrictedByAdmin=" + isRestrictedByAdmin
- + ", oldBlockedState=" + previousUidBlockedState.toString()
- + ", newBlockedState="
- + ", oldBlockedMeteredReasons=" + NetworkPolicyManager.blockedReasonsToString(
- uidBlockedState.blockedReasons & BLOCKED_METERED_REASON_MASK)
- + ", oldBlockedMeteredEffectiveReasons="
- + NetworkPolicyManager.blockedReasonsToString(
- uidBlockedState.effectiveBlockedReasons & BLOCKED_METERED_REASON_MASK)
- + ", oldAllowedMeteredReasons=" + NetworkPolicyManager.blockedReasonsToString(
- uidBlockedState.allowedReasons & BLOCKED_METERED_REASON_MASK));
- }
}
/**
@@ -4913,7 +5037,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
*/
@GuardedBy("mUidRulesFirstLock")
private void updateRulesForPowerRestrictionsUL(int uid) {
- updateRulesForPowerRestrictionsUL(uid, isUidIdle(uid));
+ updateRulesForPowerRestrictionsUL(uid, PROCESS_STATE_UNKNOWN);
+ }
+
+ @GuardedBy("mUidRulesFirstLock")
+ private void updateRulesForPowerRestrictionsUL(int uid, int uidProcState) {
+ updateRulesForPowerRestrictionsUL(uid, isUidIdle(uid, uidProcState));
}
/**
@@ -4949,56 +5078,66 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid, mDeviceIdleMode);
- final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid(
- mUidBlockedState, uid);
- final UidBlockedState previousUidBlockedState = getOrCreateUidBlockedStateForUid(
- mTmpUidBlockedState, uid);
- previousUidBlockedState.copyFrom(uidBlockedState);
+ final int oldEffectiveBlockedReasons;
+ final int newEffectiveBlockedReasons;
+ final int uidRules;
+ synchronized (mUidBlockedState) {
+ final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid(
+ mUidBlockedState, uid);
+ final UidBlockedState previousUidBlockedState = getOrCreateUidBlockedStateForUid(
+ mTmpUidBlockedState, uid);
+ previousUidBlockedState.copyFrom(uidBlockedState);
+
+ int newBlockedReasons = BLOCKED_REASON_NONE;
+ int newAllowedReasons = ALLOWED_REASON_NONE;
+ newBlockedReasons |= (mRestrictPower ? BLOCKED_REASON_BATTERY_SAVER : 0);
+ newBlockedReasons |= (mDeviceIdleMode ? BLOCKED_REASON_DOZE : 0);
+ newBlockedReasons |= (mLowPowerStandbyActive ? BLOCKED_REASON_LOW_POWER_STANDBY : 0);
+ newBlockedReasons |= (isUidIdle ? BLOCKED_REASON_APP_STANDBY : 0);
+ newBlockedReasons |= (uidBlockedState.blockedReasons & BLOCKED_REASON_RESTRICTED_MODE);
+
+ newAllowedReasons |= (isSystem(uid) ? ALLOWED_REASON_SYSTEM : 0);
+ newAllowedReasons |= (isForeground ? ALLOWED_REASON_FOREGROUND : 0);
+ newAllowedReasons |= (isTop ? ALLOWED_REASON_TOP : 0);
+ newAllowedReasons |= (isWhitelistedFromPowerSaveUL(uid, true)
+ ? ALLOWED_REASON_POWER_SAVE_ALLOWLIST : 0);
+ newAllowedReasons |= (isWhitelistedFromPowerSaveExceptIdleUL(uid)
+ ? ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST : 0);
+ newAllowedReasons |= (uidBlockedState.allowedReasons
+ & ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS);
+ newAllowedReasons |= (isAllowlistedFromLowPowerStandbyUL(uid))
+ ? ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST : 0;
+
+ uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
+ & BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
+ uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons
+ & ALLOWED_METERED_REASON_MASK) | newAllowedReasons;
+ uidBlockedState.updateEffectiveBlockedReasons();
- int newBlockedReasons = BLOCKED_REASON_NONE;
- int newAllowedReasons = ALLOWED_REASON_NONE;
- newBlockedReasons |= (mRestrictPower ? BLOCKED_REASON_BATTERY_SAVER : 0);
- newBlockedReasons |= (mDeviceIdleMode ? BLOCKED_REASON_DOZE : 0);
- newBlockedReasons |= (mLowPowerStandbyActive ? BLOCKED_REASON_LOW_POWER_STANDBY : 0);
- newBlockedReasons |= (isUidIdle ? BLOCKED_REASON_APP_STANDBY : 0);
- newBlockedReasons |= (uidBlockedState.blockedReasons & BLOCKED_REASON_RESTRICTED_MODE);
-
- newAllowedReasons |= (isSystem(uid) ? ALLOWED_REASON_SYSTEM : 0);
- newAllowedReasons |= (isForeground ? ALLOWED_REASON_FOREGROUND : 0);
- newAllowedReasons |= (isTop ? ALLOWED_REASON_TOP : 0);
- newAllowedReasons |= (isWhitelistedFromPowerSaveUL(uid, true)
- ? ALLOWED_REASON_POWER_SAVE_ALLOWLIST : 0);
- newAllowedReasons |= (isWhitelistedFromPowerSaveExceptIdleUL(uid)
- ? ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST : 0);
- newAllowedReasons |= (uidBlockedState.allowedReasons
- & ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS);
- newAllowedReasons |= (isAllowlistedFromLowPowerStandbyUL(uid))
- ? ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST : 0;
-
- uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
- & BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
- uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons
- & ALLOWED_METERED_REASON_MASK) | newAllowedReasons;
- uidBlockedState.updateEffectiveBlockedReasons();
- if (previousUidBlockedState.effectiveBlockedReasons
- != uidBlockedState.effectiveBlockedReasons) {
- postBlockedReasonsChangedMsg(uid,
- uidBlockedState.effectiveBlockedReasons,
- previousUidBlockedState.effectiveBlockedReasons);
-
- postUidRulesChangedMsg(uid, uidBlockedState.deriveUidRules());
- }
-
- if (LOGV) {
- Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")"
- + ", isIdle: " + isUidIdle
- + ", mRestrictPower: " + mRestrictPower
- + ", mDeviceIdleMode: " + mDeviceIdleMode
- + ", isForeground=" + isForeground
- + ", isTop=" + isTop
- + ", isWhitelisted=" + isWhitelisted
- + ", oldUidBlockedState=" + previousUidBlockedState.toString()
- + ", newUidBlockedState=" + uidBlockedState.toString());
+ if (LOGV) {
+ Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")"
+ + ", isIdle: " + isUidIdle
+ + ", mRestrictPower: " + mRestrictPower
+ + ", mDeviceIdleMode: " + mDeviceIdleMode
+ + ", isForeground=" + isForeground
+ + ", isTop=" + isTop
+ + ", isWhitelisted=" + isWhitelisted
+ + ", oldUidBlockedState=" + previousUidBlockedState
+ + ", newUidBlockedState=" + uidBlockedState);
+ }
+
+ oldEffectiveBlockedReasons = previousUidBlockedState.effectiveBlockedReasons;
+ newEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
+ uidRules = oldEffectiveBlockedReasons == newEffectiveBlockedReasons
+ ? RULE_NONE
+ : uidBlockedState.deriveUidRules();
+ }
+ if (oldEffectiveBlockedReasons != newEffectiveBlockedReasons) {
+ handleBlockedReasonsChanged(uid,
+ newEffectiveBlockedReasons,
+ oldEffectiveBlockedReasons);
+
+ postUidRulesChangedMsg(uid, uidRules);
}
}
@@ -5011,7 +5150,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
synchronized (mUidRulesFirstLock) {
mLogger.appIdleStateChanged(uid, idle);
- updateRuleForAppIdleUL(uid);
+ updateRuleForAppIdleUL(uid, PROCESS_STATE_UNKNOWN);
updateRulesForPowerRestrictionsUL(uid);
}
} catch (NameNotFoundException nnfe) {
@@ -5027,9 +5166,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
+ private void handleBlockedReasonsChanged(int uid, int newEffectiveBlockedReasons,
+ int oldEffectiveBlockedReasons) {
+ mActivityManagerInternal.onUidBlockedReasonsChanged(uid, newEffectiveBlockedReasons);
+ postBlockedReasonsChangedMsg(uid, newEffectiveBlockedReasons, oldEffectiveBlockedReasons);
+ }
+
private void postBlockedReasonsChangedMsg(int uid, int newEffectiveBlockedReasons,
int oldEffectiveBlockedReasons) {
- mHandler.obtainMessage(MSG_BLOCKED_REASON_CHANGED, uid,
+ mHandler.obtainMessage(MSG_UID_BLOCKED_REASON_CHANGED, uid,
newEffectiveBlockedReasons, oldEffectiveBlockedReasons)
.sendToTarget();
}
@@ -5276,7 +5421,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
return true;
}
- case MSG_BLOCKED_REASON_CHANGED: {
+ case MSG_UID_BLOCKED_REASON_CHANGED: {
final int uid = msg.arg1;
final int newBlockedReasons = msg.arg2;
final int oldBlockedReasons = (int) msg.obj;
@@ -5289,6 +5434,35 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mListeners.finishBroadcast();
return true;
}
+ case MSG_UIDS_BLOCKED_REASONS_CHANGED: {
+ final SparseArray<SomeArgs> uidStateUpdates = (SparseArray<SomeArgs>) msg.obj;
+ final int uidsSize = uidStateUpdates.size();
+ final int listenersSize = mListeners.beginBroadcast();
+ for (int i = 0; i < listenersSize; ++i) {
+ final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+ for (int uidIndex = 0; uidIndex < uidsSize; ++uidIndex) {
+ final int uid = uidStateUpdates.keyAt(uidIndex);
+ final SomeArgs someArgs = uidStateUpdates.valueAt(uidIndex);
+ final int oldBlockedReasons = someArgs.argi1;
+ final int newBlockedReasons = someArgs.argi2;
+ final int uidRules = someArgs.argi3;
+
+ dispatchBlockedReasonChanged(listener, uid,
+ oldBlockedReasons, newBlockedReasons);
+ if (LOGV) {
+ Slog.v(TAG, "Dispatching rules=" + uidRulesToString(uidRules)
+ + " for uid=" + uid);
+ }
+ dispatchUidRulesChanged(listener, uid, uidRules);
+ }
+ }
+ mListeners.finishBroadcast();
+
+ for (int uidIndex = 0; uidIndex < uidsSize; ++uidIndex) {
+ uidStateUpdates.valueAt(uidIndex).recycle();
+ }
+ return true;
+ }
default: {
return false;
}
@@ -5301,21 +5475,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public boolean handleMessage(Message msg) {
switch (msg.what) {
case UID_MSG_STATE_CHANGED: {
- final UidStateCallbackInfo uidStateCallbackInfo =
- (UidStateCallbackInfo) msg.obj;
- final int uid;
- final int procState;
- final long procStateSeq;
- final int capability;
- synchronized (mUidStateCallbackInfos) {
- uid = uidStateCallbackInfo.uid;
- procState = uidStateCallbackInfo.procState;
- procStateSeq = uidStateCallbackInfo.procStateSeq;
- capability = uidStateCallbackInfo.capability;
- uidStateCallbackInfo.isPending = false;
- }
-
- handleUidChanged(uid, procState, procStateSeq, capability);
+ handleUidChanged((UidStateCallbackInfo) msg.obj);
return true;
}
case UID_MSG_GONE: {
@@ -5330,17 +5490,28 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
};
- void handleUidChanged(int uid, int procState, long procStateSeq,
- @ProcessCapability int capability) {
+ void handleUidChanged(@NonNull UidStateCallbackInfo uidStateCallbackInfo) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "onUidStateChanged");
try {
boolean updated;
+ final int uid;
+ final int procState;
+ final long procStateSeq;
+ final int capability;
synchronized (mUidRulesFirstLock) {
+ synchronized (mUidStateCallbackInfos) {
+ uid = uidStateCallbackInfo.uid;
+ procState = uidStateCallbackInfo.procState;
+ procStateSeq = uidStateCallbackInfo.procStateSeq;
+ capability = uidStateCallbackInfo.capability;
+ uidStateCallbackInfo.isPending = false;
+ }
+
// We received a uid state change callback, add it to the history so that it
// will be useful for debugging.
mLogger.uidStateChanged(uid, procState, procStateSeq, capability);
// Now update the network policy rules as per the updated uid state.
- updated = updateUidStateUL(uid, procState, capability);
+ updated = updateUidStateUL(uid, procState, procStateSeq, capability);
// Updating the network rules is done, so notify AMS about this.
mActivityManagerInternal.notifyNetworkPolicyRulesUpdated(uid, procStateSeq);
}
@@ -5437,6 +5608,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (LOGV) Slog.v(TAG, "setMeteredNetworkDenylist " + uid + ": " + enable);
try {
mNetworkManager.setUidOnMeteredNetworkDenylist(uid, enable);
+ mLogger.meteredDenylistChanged(uid, enable);
+ if (Process.isApplicationUid(uid)) {
+ final int sdkSandboxUid = Process.toSdkSandboxUid(uid);
+ mNetworkManager.setUidOnMeteredNetworkDenylist(sdkSandboxUid, enable);
+ mLogger.meteredDenylistChanged(sdkSandboxUid, enable);
+ }
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem setting denylist (" + enable + ") rules for " + uid, e);
} catch (RemoteException e) {
@@ -5448,6 +5625,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (LOGV) Slog.v(TAG, "setMeteredNetworkAllowlist " + uid + ": " + enable);
try {
mNetworkManager.setUidOnMeteredNetworkAllowlist(uid, enable);
+ mLogger.meteredAllowlistChanged(uid, enable);
+ if (Process.isApplicationUid(uid)) {
+ final int sdkSandboxUid = Process.toSdkSandboxUid(uid);
+ mNetworkManager.setUidOnMeteredNetworkAllowlist(sdkSandboxUid, enable);
+ mLogger.meteredAllowlistChanged(sdkSandboxUid, enable);
+ }
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem setting allowlist (" + enable + ") rules for " + uid, e);
} catch (RemoteException e) {
@@ -5486,12 +5669,31 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
+ private void addSdkSandboxUidsIfNeeded(SparseIntArray uidRules) {
+ final int size = uidRules.size();
+ final SparseIntArray sdkSandboxUids = new SparseIntArray();
+ for (int index = 0; index < size; index++) {
+ final int uid = uidRules.keyAt(index);
+ final int rule = uidRules.valueAt(index);
+ if (Process.isApplicationUid(uid)) {
+ sdkSandboxUids.put(Process.toSdkSandboxUid(uid), rule);
+ }
+ }
+
+ for (int index = 0; index < sdkSandboxUids.size(); index++) {
+ final int uid = sdkSandboxUids.keyAt(index);
+ final int rule = sdkSandboxUids.valueAt(index);
+ uidRules.put(uid, rule);
+ }
+ }
+
/**
* Set uid rules on a particular firewall chain. This is going to synchronize the rules given
* here to netd. It will clean up dead rules and make sure the target chain only contains rules
* specified here.
*/
private void setUidFirewallRulesUL(int chain, SparseIntArray uidRules) {
+ addSdkSandboxUidsIfNeeded(uidRules);
try {
int size = uidRules.size();
int[] uids = new int[size];
@@ -5534,6 +5736,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
try {
mNetworkManager.setFirewallUidRule(chain, uid, rule);
mLogger.uidFirewallRuleChanged(chain, uid, rule);
+ if (Process.isApplicationUid(uid)) {
+ final int sdkSandboxUid = Process.toSdkSandboxUid(uid);
+ mNetworkManager.setFirewallUidRule(chain, sdkSandboxUid, rule);
+ mLogger.uidFirewallRuleChanged(chain, sdkSandboxUid, rule);
+ }
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem setting firewall uid rules", e);
} catch (RemoteException e) {
@@ -5570,22 +5777,28 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
*/
private void resetUidFirewallRules(int uid) {
try {
- mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_DEFAULT);
- mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
- mNetworkManager
- .setFirewallUidRule(FIREWALL_CHAIN_POWERSAVE, uid, FIREWALL_RULE_DEFAULT);
- mNetworkManager
- .setFirewallUidRule(FIREWALL_CHAIN_RESTRICTED, uid, FIREWALL_RULE_DEFAULT);
- mNetworkManager
- .setFirewallUidRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid,
- FIREWALL_RULE_DEFAULT);
+ mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_DOZABLE, uid,
+ FIREWALL_RULE_DEFAULT);
+ mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_STANDBY, uid,
+ FIREWALL_RULE_DEFAULT);
+ mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_POWERSAVE, uid,
+ FIREWALL_RULE_DEFAULT);
+ mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_RESTRICTED, uid,
+ FIREWALL_RULE_DEFAULT);
+ mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid,
+ FIREWALL_RULE_DEFAULT);
mNetworkManager.setUidOnMeteredNetworkAllowlist(uid, false);
+ mLogger.meteredAllowlistChanged(uid, false);
mNetworkManager.setUidOnMeteredNetworkDenylist(uid, false);
+ mLogger.meteredDenylistChanged(uid, false);
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem resetting firewall uid rules for " + uid, e);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
+ if (Process.isApplicationUid(uid)) {
+ resetUidFirewallRules(Process.toSdkSandboxUid(uid));
+ }
}
@Deprecated
@@ -5745,7 +5958,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG);
int blockedReasons;
- synchronized (mUidRulesFirstLock) {
+ synchronized (mUidBlockedState) {
final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
blockedReasons = uidBlockedState == null
? BLOCKED_REASON_NONE : uidBlockedState.effectiveBlockedReasons;
@@ -5763,7 +5976,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@Override
public boolean isUidRestrictedOnMeteredNetworks(int uid) {
mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG);
- synchronized (mUidRulesFirstLock) {
+ synchronized (mUidBlockedState) {
final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
int blockedReasons = uidBlockedState == null
? BLOCKED_REASON_NONE : uidBlockedState.effectiveBlockedReasons;
@@ -6011,10 +6224,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return restrictedUids != null && restrictedUids.contains(uid);
}
- private static boolean hasRule(int uidRules, int rule) {
- return (uidRules & rule) != 0;
- }
-
private static boolean getBooleanDefeatingNullable(@Nullable PersistableBundle bundle,
String key, boolean defaultValue) {
return (bundle != null) ? bundle.getBoolean(key, defaultValue) : defaultValue;
@@ -6030,16 +6239,39 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return uidBlockedState;
}
+ private int getEffectiveBlockedReasons(int uid) {
+ synchronized (mUidBlockedState) {
+ final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
+ return uidBlockedState == null
+ ? BLOCKED_REASON_NONE
+ : uidBlockedState.effectiveBlockedReasons;
+ }
+ }
+
+ private int getBlockedReasons(int uid) {
+ synchronized (mUidBlockedState) {
+ final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
+ return uidBlockedState == null
+ ? BLOCKED_REASON_NONE
+ : uidBlockedState.blockedReasons;
+ }
+ }
+
@VisibleForTesting
static final class UidBlockedState {
public int blockedReasons;
public int allowedReasons;
public int effectiveBlockedReasons;
+ private UidBlockedState(int blockedReasons, int allowedReasons,
+ int effectiveBlockedReasons) {
+ this.blockedReasons = blockedReasons;
+ this.allowedReasons = allowedReasons;
+ this.effectiveBlockedReasons = effectiveBlockedReasons;
+ }
+
UidBlockedState() {
- blockedReasons = BLOCKED_REASON_NONE;
- allowedReasons = ALLOWED_REASON_NONE;
- effectiveBlockedReasons = BLOCKED_REASON_NONE;
+ this(BLOCKED_REASON_NONE, ALLOWED_REASON_NONE, BLOCKED_REASON_NONE);
}
void updateEffectiveBlockedReasons() {
@@ -6276,7 +6508,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
if (LOGV) {
- Slog.v(TAG, "uidBlockedState=" + this.toString()
+ Slog.v(TAG, "uidBlockedState=" + this
+ " -> uidRule=" + uidRulesToString(uidRule));
}
return uidRule;
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 3ccb06ccef15..ab8527e7ec41 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -1123,7 +1123,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
/** Makes the process have top state before oom-adj is computed from a posted message. */
void addToPendingTop() {
- mAtm.mAmInternal.addPendingTopUid(mUid, mPid);
+ mAtm.mAmInternal.addPendingTopUid(mUid, mPid, mThread);
}
void updateServiceConnectionActivities() {
@@ -1176,7 +1176,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
// update ActivityManagerService.PendingStartActivityUids list.
if (topProcessState == ActivityManager.PROCESS_STATE_TOP) {
- mAtm.mAmInternal.addPendingTopUid(mUid, mPid);
+ mAtm.mAmInternal.addPendingTopUid(mUid, mPid, mThread);
}
prepareOomAdjustment();
// Posting the message at the front of queue so WM lock isn't held when we call into AM,
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
index 8c21a39c20d1..16406bcb9a1f 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
@@ -129,7 +129,7 @@ public class ActivityManagerInternalTest {
thread2.assertWaiting("Unexpected state for " + record2);
thread2.interrupt();
- mAms.mProcessList.mActiveUids.clear();
+ clearActiveUids();
}
private UidRecord addActiveUidRecord(int uid, long curProcStateSeq,
@@ -137,11 +137,21 @@ public class ActivityManagerInternalTest {
final UidRecord record = new UidRecord(uid, mAms);
record.lastNetworkUpdatedProcStateSeq = lastNetworkUpdatedProcStateSeq;
record.curProcStateSeq = curProcStateSeq;
- record.waitingForNetwork = true;
- mAms.mProcessList.mActiveUids.put(uid, record);
+ record.procStateSeqWaitingForNetwork = 1;
+ addActiveUidRecord(uid, record);
return record;
}
+ @SuppressWarnings("GuardedBy")
+ private void addActiveUidRecord(int uid, UidRecord record) {
+ mAms.mProcessList.mActiveUids.put(uid, record);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ private void clearActiveUids() {
+ mAms.mProcessList.mActiveUids.clear();
+ }
+
static class CustomThread extends Thread {
private static final long WAIT_TIMEOUT_MS = 1000;
private static final long WAIT_INTERVAL_MS = 100;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 12e0d8bc5d62..968a3e2c354e 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -191,8 +191,6 @@ public class ActivityManagerServiceTest {
verifySeqCounterAndInteractions(uidRec,
PROCESS_STATE_TOP, // prevState
PROCESS_STATE_TOP, // curState
- 0, // expectedGlobalCounter
- 0, // exptectedCurProcStateSeq
NETWORK_STATE_NO_CHANGE, // expectedBlockState
false); // expectNotify
@@ -200,8 +198,6 @@ public class ActivityManagerServiceTest {
verifySeqCounterAndInteractions(uidRec,
PROCESS_STATE_FOREGROUND_SERVICE, // prevState
PROCESS_STATE_SERVICE, // curState
- 1, // expectedGlobalCounter
- 1, // exptectedCurProcStateSeq
NETWORK_STATE_UNBLOCK, // expectedBlockState
true); // expectNotify
@@ -213,8 +209,6 @@ public class ActivityManagerServiceTest {
verifySeqCounterAndInteractions(uidRec,
PROCESS_STATE_TRANSIENT_BACKGROUND, // prevState
PROCESS_STATE_IMPORTANT_BACKGROUND, // curState
- 42, // expectedGlobalCounter
- 1, // exptectedCurProcStateSeq
NETWORK_STATE_NO_CHANGE, // expectedBlockState
false); // expectNotify
@@ -222,73 +216,22 @@ public class ActivityManagerServiceTest {
verifySeqCounterAndInteractions(uidRec,
PROCESS_STATE_LAST_ACTIVITY, // prevState
PROCESS_STATE_TOP, // curState
- 43, // expectedGlobalCounter
- 43, // exptectedCurProcStateSeq
NETWORK_STATE_BLOCK, // expectedBlockState
false); // expectNotify
// verify waiting threads are not notified.
- uidRec.waitingForNetwork = false;
+ uidRec.procStateSeqWaitingForNetwork = 0;
// Uid state is moving from foreground to background.
verifySeqCounterAndInteractions(uidRec,
PROCESS_STATE_FOREGROUND_SERVICE, // prevState
PROCESS_STATE_SERVICE, // curState
- 44, // expectedGlobalCounter
- 44, // exptectedCurProcStateSeq
NETWORK_STATE_UNBLOCK, // expectedBlockState
false); // expectNotify
-
- // Verify when uid is not restricted, procStateSeq is not incremented.
- uidRec.waitingForNetwork = true;
- mInjector.setNetworkRestrictedForUid(false);
- verifySeqCounterAndInteractions(uidRec,
- PROCESS_STATE_IMPORTANT_BACKGROUND, // prevState
- PROCESS_STATE_TOP, // curState
- 44, // expectedGlobalCounter
- 44, // exptectedCurProcStateSeq
- -1, // expectedBlockState, -1 to verify there are no interactions with main thread.
- false); // expectNotify
-
- // Verify when waitForNetworkTimeout is 0, then procStateSeq is not incremented.
- mAms.mWaitForNetworkTimeoutMs = 0;
- mInjector.setNetworkRestrictedForUid(true);
- verifySeqCounterAndInteractions(uidRec,
- PROCESS_STATE_TOP, // prevState
- PROCESS_STATE_IMPORTANT_BACKGROUND, // curState
- 44, // expectedGlobalCounter
- 44, // exptectedCurProcStateSeq
- -1, // expectedBlockState, -1 to verify there are no interactions with main thread.
- false); // expectNotify
-
- // Verify when the uid doesn't have internet permission, then procStateSeq is not
- // incremented.
- uidRec.hasInternetPermission = false;
- mAms.mWaitForNetworkTimeoutMs = 111;
- mInjector.setNetworkRestrictedForUid(true);
- verifySeqCounterAndInteractions(uidRec,
- PROCESS_STATE_CACHED_ACTIVITY, // prevState
- PROCESS_STATE_FOREGROUND_SERVICE, // curState
- 44, // expectedGlobalCounter
- 44, // exptectedCurProcStateSeq
- -1, // expectedBlockState, -1 to verify there are no interactions with main thread.
- false); // expectNotify
-
- // Verify procStateSeq is not incremented when the uid is not an application, regardless
- // of the process state.
- final int notAppUid = 111;
- final UidRecord uidRec2 = addUidRecord(notAppUid);
- verifySeqCounterAndInteractions(uidRec2,
- PROCESS_STATE_CACHED_EMPTY, // prevState
- PROCESS_STATE_TOP, // curState
- 44, // expectedGlobalCounter
- 0, // exptectedCurProcStateSeq
- -1, // expectedBlockState, -1 to verify there are no interactions with main thread.
- false); // expectNotify
}
private UidRecord addUidRecord(int uid) {
final UidRecord uidRec = new UidRecord(uid, mAms);
- uidRec.waitingForNetwork = true;
+ uidRec.procStateSeqWaitingForNetwork = 1;
uidRec.hasInternetPermission = true;
mAms.mProcessList.mActiveUids.put(uid, uidRec);
@@ -305,18 +248,26 @@ public class ActivityManagerServiceTest {
@SuppressWarnings("GuardedBy")
private void verifySeqCounterAndInteractions(UidRecord uidRec, int prevState, int curState,
- int expectedGlobalCounter, int expectedCurProcStateSeq, int expectedBlockState,
- boolean expectNotify) throws Exception {
+ int expectedBlockState, boolean expectNotify) throws Exception {
CustomThread thread = new CustomThread(uidRec.networkStateLock);
thread.startAndWait("Unexpected state for " + uidRec);
uidRec.setSetProcState(prevState);
uidRec.setCurProcState(curState);
+ final long beforeProcStateSeq = mAms.mProcessList.mProcStateSeqCounter;
+
mAms.mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(mAms.mProcessList.mActiveUids);
- // @SuppressWarnings("GuardedBy")
- assertEquals(expectedGlobalCounter, mAms.mProcessList.mProcStateSeqCounter);
- assertEquals(expectedCurProcStateSeq, uidRec.curProcStateSeq);
+ final long afterProcStateSeq = beforeProcStateSeq
+ + mAms.mProcessList.mActiveUids.size();
+ assertEquals("beforeProcStateSeq=" + beforeProcStateSeq
+ + ",activeUids.size=" + mAms.mProcessList.mActiveUids.size(),
+ afterProcStateSeq, mAms.mProcessList.mProcStateSeqCounter);
+ assertTrue("beforeProcStateSeq=" + beforeProcStateSeq
+ + ",afterProcStateSeq=" + afterProcStateSeq
+ + ",uidCurProcStateSeq=" + uidRec.curProcStateSeq,
+ uidRec.curProcStateSeq > beforeProcStateSeq
+ && uidRec.curProcStateSeq <= afterProcStateSeq);
for (int i = mAms.mProcessList.getLruSizeLOSP() - 1; i >= 0; --i) {
final ProcessRecord app = mAms.mProcessList.getLruProcessesLOSP().get(i);
@@ -815,48 +766,11 @@ public class ActivityManagerServiceTest {
}
@Test
- public void testEnqueueUidChangeLocked_procStateSeqUpdated() {
- final UidRecord uidRecord = new UidRecord(TEST_UID, mAms);
- uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ1;
-
- // Verify with no pending changes for TEST_UID.
- verifyLastProcStateSeqUpdated(uidRecord, -1, TEST_PROC_STATE_SEQ1);
-
- // Add a pending change for TEST_UID and verify enqueueUidChangeLocked still works as
- // expected.
- uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ2;
- verifyLastProcStateSeqUpdated(uidRecord, -1, TEST_PROC_STATE_SEQ2);
- }
-
- @Test
public void testEnqueueUidChangeLocked_nullUidRecord() {
// Use "null" uidRecord to make sure there is no crash.
mAms.enqueueUidChangeLocked(null, TEST_UID, UidRecord.CHANGE_ACTIVE);
}
- private void verifyLastProcStateSeqUpdated(UidRecord uidRecord, int uid, long curProcstateSeq) {
- // Test enqueueUidChangeLocked with every UidRecord.CHANGE_*
- for (int i = 0; i < UID_RECORD_CHANGES.length; ++i) {
- final int changeToDispatch = UID_RECORD_CHANGES[i];
- // Reset lastProcStateSeqDispatchToObservers after every test.
- uidRecord.lastDispatchedProcStateSeq = 0;
- mAms.enqueueUidChangeLocked(uidRecord, uid, changeToDispatch);
- // Verify there is no effect on curProcStateSeq.
- assertEquals(curProcstateSeq, uidRecord.curProcStateSeq);
- if ((changeToDispatch & UidRecord.CHANGE_GONE) != 0) {
- // Since the change is CHANGE_GONE or CHANGE_GONE_IDLE, verify that
- // lastProcStateSeqDispatchedToObservers is not updated.
- assertNotEquals(uidRecord.curProcStateSeq,
- uidRecord.lastDispatchedProcStateSeq);
- } else {
- // Since the change is neither CHANGE_GONE nor CHANGE_GONE_IDLE, verify that
- // lastProcStateSeqDispatchedToObservers has been updated to curProcStateSeq.
- assertEquals(uidRecord.curProcStateSeq,
- uidRecord.lastDispatchedProcStateSeq);
- }
- }
- }
-
@MediumTest
@Test
public void testEnqueueUidChangeLocked_dispatchUidsChanged() {
@@ -893,29 +807,10 @@ public class ActivityManagerServiceTest {
// Check there is no crash when there is no UidRecord for myUid
mAms.waitForNetworkStateUpdate(TEST_PROC_STATE_SEQ1);
- // Verify there is no waiting when UidRecord.curProcStateSeq is greater than
- // the procStateSeq in the request to wait.
- verifyWaitingForNetworkStateUpdate(
- TEST_PROC_STATE_SEQ1, // curProcStateSeq
- TEST_PROC_STATE_SEQ1, // lastDsipatchedProcStateSeq
- TEST_PROC_STATE_SEQ1 - 4, // lastNetworkUpdatedProcStateSeq
- TEST_PROC_STATE_SEQ1 - 2, // procStateSeqToWait
- false); // expectWait
-
- // Verify there is no waiting when the procStateSeq in the request to wait is
- // not dispatched to NPMS.
- verifyWaitingForNetworkStateUpdate(
- TEST_PROC_STATE_SEQ1, // curProcStateSeq
- TEST_PROC_STATE_SEQ1 - 1, // lastDsipatchedProcStateSeq
- TEST_PROC_STATE_SEQ1 - 1, // lastNetworkUpdatedProcStateSeq
- TEST_PROC_STATE_SEQ1, // procStateSeqToWait
- false); // expectWait
-
// Verify there is not waiting when the procStateSeq in the request already has
// an updated network state.
verifyWaitingForNetworkStateUpdate(
TEST_PROC_STATE_SEQ1, // curProcStateSeq
- TEST_PROC_STATE_SEQ1, // lastDsipatchedProcStateSeq
TEST_PROC_STATE_SEQ1, // lastNetworkUpdatedProcStateSeq
TEST_PROC_STATE_SEQ1, // procStateSeqToWait
false); // expectWait
@@ -923,18 +818,16 @@ public class ActivityManagerServiceTest {
// Verify waiting for network works
verifyWaitingForNetworkStateUpdate(
TEST_PROC_STATE_SEQ1, // curProcStateSeq
- TEST_PROC_STATE_SEQ1, // lastDsipatchedProcStateSeq
TEST_PROC_STATE_SEQ1 - 1, // lastNetworkUpdatedProcStateSeq
TEST_PROC_STATE_SEQ1, // procStateSeqToWait
true); // expectWait
}
private void verifyWaitingForNetworkStateUpdate(long curProcStateSeq,
- long lastDispatchedProcStateSeq, long lastNetworkUpdatedProcStateSeq,
+ long lastNetworkUpdatedProcStateSeq,
final long procStateSeqToWait, boolean expectWait) throws Exception {
final UidRecord record = new UidRecord(Process.myUid(), mAms);
record.curProcStateSeq = curProcStateSeq;
- record.lastDispatchedProcStateSeq = lastDispatchedProcStateSeq;
record.lastNetworkUpdatedProcStateSeq = lastNetworkUpdatedProcStateSeq;
mAms.mProcessList.mActiveUids.put(Process.myUid(), record);
@@ -953,7 +846,7 @@ public class ActivityManagerServiceTest {
}
thread.assertTerminated(errMsg);
assertTrue(thread.mNotified);
- assertFalse(record.waitingForNetwork);
+ assertEquals(0, record.procStateSeqWaitingForNetwork);
} else {
thread.start();
thread.assertTerminated(errMsg);
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index af8ac6f412f5..0f2fe4434bfa 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -118,6 +118,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.content.pm.UserInfo;
import android.net.ConnectivityManager;
@@ -166,6 +167,7 @@ import com.android.internal.util.test.BroadcastInterceptingContext.FutureIntent;
import com.android.internal.util.test.FsUtil;
import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.usage.AppStandbyInternal;
import com.google.common.util.concurrent.AbstractFuture;
@@ -216,6 +218,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
@@ -274,6 +277,7 @@ public class NetworkPolicyManagerServiceTest {
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
private ActivityManagerInternal mActivityManagerInternal;
+ private PackageManagerInternal mPackageManagerInternal;
private IUidObserver mUidObserver;
private INetworkManagementEventObserver mNetworkObserver;
@@ -335,6 +339,7 @@ public class NetworkPolicyManagerServiceTest {
when(usageStats.getIdleUidsForUser(anyInt())).thenReturn(new int[]{});
mActivityManagerInternal = addLocalServiceMock(ActivityManagerInternal.class);
+ mPackageManagerInternal = addLocalServiceMock(PackageManagerInternal.class);
final PowerSaveState state = new PowerSaveState.Builder()
.setBatterySaverEnabled(false).build();
@@ -436,14 +441,14 @@ public class NetworkPolicyManagerServiceTest {
setNetpolicyXml(context);
doAnswer(new Answer<Void>() {
-
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
mUidObserver = (IUidObserver) invocation.getArguments()[0];
Log.d(TAG, "set mUidObserver to " + mUidObserver);
return null;
}
- }).when(mActivityManager).registerUidObserver(any(), anyInt(), anyInt(), any(String.class));
+ }).when(mActivityManagerInternal).registerNetworkPolicyUidObserver(any(),
+ anyInt(), anyInt(), any(String.class));
mFutureIntent = newRestrictBackgroundChangedFuture();
mDeps = new TestDependencies(mServiceContext);
@@ -483,8 +488,15 @@ public class NetworkPolicyManagerServiceTest {
.thenReturn(buildApplicationInfo(PKG_NAME_B, UID_B));
when(mPackageManager.getApplicationInfo(eq(PKG_NAME_C), anyInt()))
.thenReturn(buildApplicationInfo(PKG_NAME_C, UID_C));
- when(mPackageManager.getInstalledApplications(anyInt())).thenReturn(
- buildInstalledApplicationInfoList());
+ doAnswer(arg -> {
+ final Consumer<AndroidPackage> consumer =
+ (Consumer<AndroidPackage>) arg.getArguments()[0];
+ for (AndroidPackage androidPackage : buildInstalledPackageList()) {
+ consumer.accept(androidPackage);
+ }
+ return null;
+ }).when(mPackageManagerInternal).forEachInstalledPackage(
+ any(Consumer.class), anyInt());
when(mUserManager.getUsers()).thenReturn(buildUserInfoList());
when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true);
when(mNetworkManager.setDataSaverModeEnabled(anyBoolean())).thenReturn(true);
@@ -536,6 +548,7 @@ public class NetworkPolicyManagerServiceTest {
LocalServices.removeServiceForTest(DeviceIdleInternal.class);
LocalServices.removeServiceForTest(AppStandbyInternal.class);
LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
}
@After
@@ -978,19 +991,20 @@ public class NetworkPolicyManagerServiceTest {
@Test
public void testUidForeground() throws Exception {
// push all uids into background
- callOnUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE, 0);
- callOnUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE, 0);
+ 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));
// push one of the uids into foreground
- callOnUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP, 0);
+ callOnUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP, procStateSeq++);
assertTrue(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
// and swap another uid into foreground
- callOnUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE, 0);
- callOnUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP, 0);
+ 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));
}
@@ -2037,14 +2051,20 @@ public class NetworkPolicyManagerServiceTest {
return ai;
}
- private List<ApplicationInfo> buildInstalledApplicationInfoList() {
- final List<ApplicationInfo> installedApps = new ArrayList<>();
- installedApps.add(buildApplicationInfo(PKG_NAME_A, UID_A));
- installedApps.add(buildApplicationInfo(PKG_NAME_B, UID_B));
- installedApps.add(buildApplicationInfo(PKG_NAME_C, UID_C));
+ private List<AndroidPackage> buildInstalledPackageList() {
+ final List<AndroidPackage> installedApps = new ArrayList<>();
+ installedApps.add(createPackageMock(UID_A));
+ installedApps.add(createPackageMock(UID_B));
+ installedApps.add(createPackageMock(UID_C));
return installedApps;
}
+ private AndroidPackage createPackageMock(int uid) {
+ final AndroidPackage androidPackage = mock(AndroidPackage.class);
+ when(androidPackage.getUid()).thenReturn(uid);
+ return androidPackage;
+ }
+
private List<UserInfo> buildUserInfoList() {
final List<UserInfo> users = new ArrayList<>();
users.add(new UserInfo(USER_ID, "user1", 0));