diff options
7 files changed, 115 insertions, 39 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java index af867b936d72..41b342cc258c 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -1220,6 +1220,7 @@ public class JobSchedulerService extends com.android.server.SystemService void updateUidState(int uid, int procState) { synchronized (mLock) { + final int prevPriority = mUidPriorityOverride.get(uid, JobInfo.PRIORITY_DEFAULT); if (procState == ActivityManager.PROCESS_STATE_TOP) { // Only use this if we are exactly the top app. All others can live // with just the foreground priority. This means that persistent processes @@ -1232,6 +1233,16 @@ public class JobSchedulerService extends com.android.server.SystemService } else { mUidPriorityOverride.delete(uid); } + final int newPriority = mUidPriorityOverride.get(uid, JobInfo.PRIORITY_DEFAULT); + if (prevPriority != newPriority) { + if (DEBUG) { + Slog.d(TAG, "UID " + uid + " priority changed from " + prevPriority + + " to " + newPriority); + } + for (int c = 0; c < mControllers.size(); ++c) { + mControllers.get(c).onUidPriorityChangedLocked(uid, newPriority); + } + } } } diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java index b97ca20b5d16..f30b75c1af93 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java @@ -29,6 +29,7 @@ import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.Network; import android.net.NetworkCapabilities; +import android.net.NetworkPolicyManager; import android.net.NetworkRequest; import android.os.Handler; import android.os.Looper; @@ -83,6 +84,19 @@ public final class ConnectivityController extends RestrictingController implemen */ private static final long MIN_STATS_UPDATE_INTERVAL_MS = 30_000L; + private static final int UNBYPASSABLE_BG_BLOCKED_REASONS = + ~ConnectivityManager.BLOCKED_REASON_NONE; + private static final int UNBYPASSABLE_EJ_BLOCKED_REASONS = + ~(ConnectivityManager.BLOCKED_REASON_APP_STANDBY + | ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER + | ConnectivityManager.BLOCKED_REASON_DOZE); + private static final int UNBYPASSABLE_FOREGROUND_BLOCKED_REASONS = + ~(ConnectivityManager.BLOCKED_REASON_APP_STANDBY + | ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER + | ConnectivityManager.BLOCKED_REASON_DOZE + | ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER + | ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED); + private final ConnectivityManager mConnManager; private final NetworkPolicyManagerInternal mNetPolicyManagerInternal; @@ -152,6 +166,9 @@ public final class ConnectivityController extends RestrictingController implemen } else if (us1.earliestEJEnqueueTime > us2.earliestEJEnqueueTime) { return 1; } + if (us1.basePriority != us2.basePriority) { + return us2.basePriority - us1.basePriority; + } if (us1.earliestEnqueueTime < us2.earliestEnqueueTime) { return -1; } @@ -454,6 +471,16 @@ public final class ConnectivityController extends RestrictingController implemen postAdjustCallbacks(); } + @GuardedBy("mLock") + @Override + public void onUidPriorityChangedLocked(int uid, int newPriority) { + UidStats uidStats = mUidStats.get(uid); + if (uidStats != null && uidStats.basePriority != newPriority) { + uidStats.basePriority = newPriority; + maybeAdjustRegisteredCallbacksLocked(); + } + } + private boolean isUsable(NetworkCapabilities capabilities) { return capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); @@ -757,6 +784,42 @@ public final class ConnectivityController extends RestrictingController implemen } } + @GuardedBy("mLock") + @Nullable + private Network getNetworkLocked(@NonNull JobStatus jobStatus) { + final UidDefaultNetworkCallback defaultNetworkCallback = + mCurrentDefaultNetworkCallbacks.get(jobStatus.getSourceUid()); + if (defaultNetworkCallback == null) { + return null; + } + + UidStats uidStats = mUidStats.get(jobStatus.getSourceUid()); + + final int unbypassableBlockedReasons; + // TOP will probably have fewer reasons, so we may not have to worry about returning + // BG_BLOCKED for a TOP app. However, better safe than sorry. + if (uidStats.basePriority >= JobInfo.PRIORITY_BOUND_FOREGROUND_SERVICE + || (jobStatus.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) { + if (DEBUG) { + Slog.d(TAG, "Using FG bypass for " + jobStatus.getSourceUid()); + } + unbypassableBlockedReasons = UNBYPASSABLE_FOREGROUND_BLOCKED_REASONS; + } else if (jobStatus.shouldTreatAsExpeditedJob() || jobStatus.startedAsExpeditedJob) { + if (DEBUG) { + Slog.d(TAG, "Using EJ bypass for " + jobStatus.getSourceUid()); + } + unbypassableBlockedReasons = UNBYPASSABLE_EJ_BLOCKED_REASONS; + } else { + if (DEBUG) { + Slog.d(TAG, "Using BG bypass for " + jobStatus.getSourceUid()); + } + unbypassableBlockedReasons = UNBYPASSABLE_BG_BLOCKED_REASONS; + } + + return (unbypassableBlockedReasons & defaultNetworkCallback.mBlockedReasons) == 0 + ? defaultNetworkCallback.mDefaultNetwork : null; + } + private boolean updateConstraintsSatisfied(JobStatus jobStatus) { final long nowElapsed = sElapsedRealtimeClock.millis(); final UidDefaultNetworkCallback defaultNetworkCallback = @@ -765,9 +828,7 @@ public final class ConnectivityController extends RestrictingController implemen maybeRegisterDefaultNetworkCallbackLocked(jobStatus); return updateConstraintsSatisfied(jobStatus, nowElapsed, null, null); } - final Network network = - (jobStatus.shouldIgnoreNetworkBlocking() || !defaultNetworkCallback.mBlocked) - ? defaultNetworkCallback.mDefaultNetwork : null; + final Network network = getNetworkLocked(jobStatus); final NetworkCapabilities capabilities = getNetworkCapabilities(network); return updateConstraintsSatisfied(jobStatus, nowElapsed, network, capabilities); } @@ -829,32 +890,15 @@ public final class ConnectivityController extends RestrictingController implemen return false; } - final Network network = defaultNetworkCallback.mBlocked - ? null : defaultNetworkCallback.mDefaultNetwork; - final NetworkCapabilities capabilities = getNetworkCapabilities(network); - final boolean networkMatch = (filterNetwork == null - || Objects.equals(filterNetwork, network)); - // Ignore blocked - final Network exemptedNetwork = defaultNetworkCallback.mDefaultNetwork; - final NetworkCapabilities exemptedNetworkCapabilities = - getNetworkCapabilities(exemptedNetwork); - final boolean exemptedNetworkMatch = - (filterNetwork == null || Objects.equals(filterNetwork, exemptedNetwork)); - final long nowElapsed = sElapsedRealtimeClock.millis(); boolean changed = false; for (int i = jobs.size() - 1; i >= 0; i--) { final JobStatus js = jobs.valueAt(i); - Network net = network; - NetworkCapabilities netCap = capabilities; - boolean match = networkMatch; - - if (js.shouldIgnoreNetworkBlocking()) { - net = exemptedNetwork; - netCap = exemptedNetworkCapabilities; - match = exemptedNetworkMatch; - } + final Network net = getNetworkLocked(js); + final NetworkCapabilities netCap = getNetworkCapabilities(net); + final boolean match = (filterNetwork == null + || Objects.equals(filterNetwork, net)); // Update either when we have a network match, or when the // job hasn't yet been evaluated against the currently @@ -950,7 +994,7 @@ public final class ConnectivityController extends RestrictingController implemen private int mUid; @Nullable private Network mDefaultNetwork; - private boolean mBlocked; + private int mBlockedReasons; private void setUid(int uid) { mUid = uid; @@ -968,17 +1012,17 @@ public final class ConnectivityController extends RestrictingController implemen } @Override - public void onBlockedStatusChanged(Network network, boolean blocked) { + public void onBlockedStatusChanged(Network network, int blockedReasons) { if (DEBUG) { Slog.v(TAG, "default-onBlockedStatusChanged(" + mUid + "): " - + network + " -> " + blocked); + + network + " -> " + blockedReasons); } if (mUid == UserHandle.USER_NULL) { return; } synchronized (mLock) { mDefaultNetwork = network; - mBlocked = blocked; + mBlockedReasons = blockedReasons; updateTrackedJobsLocked(mUid, network); } } @@ -1037,7 +1081,7 @@ public final class ConnectivityController extends RestrictingController implemen pw.print("Network: "); pw.print(mDefaultNetwork); pw.print(" (blocked="); - pw.print(mBlocked); + pw.print(NetworkPolicyManager.blockedReasonsToString(mBlockedReasons)); pw.print(")"); } pw.println(); @@ -1046,6 +1090,7 @@ public final class ConnectivityController extends RestrictingController implemen private static class UidStats { public final int uid; + public int basePriority; public int numRunning; public int numReadyWithConnectivity; public int numRequestedNetworkAvailable; @@ -1062,6 +1107,7 @@ public final class ConnectivityController extends RestrictingController implemen private void dumpLocked(IndentingPrintWriter pw, final long nowElapsed) { pw.print("UidStats{"); pw.print("uid", uid); + pw.print("pri", basePriority); pw.print("#run", numRunning); pw.print("#readyWithConn", numReadyWithConnectivity); pw.print("#netAvail", numRequestedNetworkAvailable); diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java index 80e68e9a883b..95eb220cfeb4 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java @@ -1139,11 +1139,6 @@ public final class JobStatus { && (mDynamicConstraints & CONSTRAINT_BACKGROUND_NOT_RESTRICTED) == 0); } - boolean shouldIgnoreNetworkBlocking() { - return (getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0 - || (shouldTreatAsExpeditedJob() || startedAsExpeditedJob); - } - /** @return true if the constraint was changed, false otherwise. */ boolean setChargingConstraintSatisfied(final long nowElapsed, boolean state) { return setConstraintSatisfied(CONSTRAINT_CHARGING, nowElapsed, state); diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java index a33ba5b3f8bc..334876f57f29 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java @@ -25,6 +25,7 @@ import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.proto.ProtoOutputStream; +import com.android.internal.annotations.GuardedBy; import com.android.server.job.JobSchedulerService; import com.android.server.job.JobSchedulerService.Constants; import com.android.server.job.StateChangedListener; @@ -125,6 +126,14 @@ public abstract class StateController { public void reevaluateStateLocked(int uid) { } + /** + * Called when a UID's base priority has changed. The more positive the priority, the more + * important the UID is. + */ + @GuardedBy("mLock") + public void onUidPriorityChangedLocked(int uid, int newPriority) { + } + protected boolean wouldBeReadyWithConstraintLocked(JobStatus jobStatus, int constraint) { // This is very cheap to check (just a few conditions on data in JobStatus). final boolean jobWouldBeReady = jobStatus.wouldBeReadyWithConstraint(constraint); diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index da3febddd973..632eb15ecdde 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -769,7 +769,7 @@ public class NetworkPolicyManager { @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @NonNull public static String blockedReasonsToString(int blockedReasons) { - return DebugUtils.flagsToString(NetworkPolicyManager.class, "BLOCKED_", blockedReasons); + return DebugUtils.flagsToString(ConnectivityManager.class, "BLOCKED_", blockedReasons); } /** diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 2494816d34a7..352eac3567fe 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -435,8 +435,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** * Message to indicate that reasons for why an uid is blocked changed. * arg1 = uid - * arg2 = oldBlockedReasons - * obj = newBlockedReasons + * arg2 = newBlockedReasons + * obj = oldBlockedReasons */ private static final int MSG_BLOCKED_REASON_CHANGED = 21; @@ -4665,7 +4665,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { + ", oldRule=" + uidRulesToString(oldUidRules & MASK_METERED_NETWORKS) + ", newRule=" + uidRulesToString(newUidRules & MASK_METERED_NETWORKS) + ", newUidRules=" + uidRulesToString(newUidRules) - + ", oldUidRules=" + uidRulesToString(oldUidRules)); + + ", oldUidRules=" + uidRulesToString(oldUidRules) + + ", 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)); } if (newUidRules == RULE_NONE) { @@ -5897,6 +5904,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { effectiveBlockedReasons = blockedReasons; // If the uid is not subject to any blocked reasons, then return early if (blockedReasons == BLOCKED_REASON_NONE) { + if (LOGV) { + Log.v(TAG, "updateEffectiveBlockedReasons(): no blocked reasons"); + } return; } if ((allowedReasons & ALLOWED_REASON_SYSTEM) != 0) { @@ -5929,6 +5939,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if ((allowedReasons & ALLOWED_METERED_REASON_USER_EXEMPTED) != 0) { effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_DATA_SAVER; } + if (LOGV) { + Log.v(TAG, "updateEffectiveBlockedReasons()" + + ": blockedReasons=" + Integer.toBinaryString(blockedReasons) + + ", effectiveReasons=" + Integer.toBinaryString(effectiveBlockedReasons)); + } } } diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java index 1b8f9c767e3e..0cd470ae7ec4 100644 --- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java @@ -654,7 +654,7 @@ public class ConnectivityControllerTest { generalCallback.onCapabilitiesChanged(net, caps); if (uidCallback != null) { uidCallback.onAvailable(net); - uidCallback.onBlockedStatusChanged(net, false); + uidCallback.onBlockedStatusChanged(net, ConnectivityManager.BLOCKED_REASON_NONE); uidCallback.onCapabilitiesChanged(net, caps); } } |