Merge "Check network blocked reasons for job satisfaction." into sc-dev

This commit is contained in:
Kweku Adams
2021-04-06 15:04:01 +00:00
committed by Android (Google) Code Review
7 changed files with 115 additions and 39 deletions

View File

@@ -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);
}
}
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
/**

View File

@@ -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));
}
}
}

View File

@@ -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);
}
}