diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java index 94ca24c9db9f2..b458d8b72adef 100644 --- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java +++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java @@ -17,18 +17,18 @@ package com.android.server.job.controllers; import android.app.job.JobInfo; -import android.content.BroadcastReceiver; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.net.ConnectivityManager; +import android.net.ConnectivityManager.NetworkCallback; import android.net.INetworkPolicyListener; +import android.net.Network; +import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkPolicyManager; +import android.os.Process; import android.os.UserHandle; import android.util.Slog; -import com.android.internal.os.BackgroundThread; import com.android.internal.annotations.GuardedBy; import com.android.server.job.JobSchedulerService; import com.android.server.job.StateChangedListener; @@ -46,9 +46,12 @@ import java.util.ArrayList; public class ConnectivityController extends StateController implements ConnectivityManager.OnNetworkActiveListener { private static final String TAG = "JobScheduler.Conn"; + private static final boolean DEBUG = false; private final ConnectivityManager mConnManager; private final NetworkPolicyManager mNetPolicyManager; + private boolean mConnected; + private boolean mValidated; @GuardedBy("mLock") private final ArrayList mTrackedJobs = new ArrayList(); @@ -73,10 +76,9 @@ public class ConnectivityController extends StateController implements mConnManager = mContext.getSystemService(ConnectivityManager.class); mNetPolicyManager = mContext.getSystemService(NetworkPolicyManager.class); - final IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); - mContext.registerReceiverAsUser( - mConnectivityReceiver, UserHandle.SYSTEM, intentFilter, null, null); + mConnected = mValidated = false; + mConnManager.registerDefaultNetworkCallback(mNetworkCallback); mNetPolicyManager.registerListener(mNetPolicyListener); } @@ -84,7 +86,7 @@ public class ConnectivityController extends StateController implements public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) { if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint() || jobStatus.hasNotRoamingConstraint()) { - updateConstraintsSatisfied(jobStatus); + updateConstraintsSatisfied(jobStatus, null); mTrackedJobs.add(jobStatus); } } @@ -98,18 +100,43 @@ public class ConnectivityController extends StateController implements } } - private boolean updateConstraintsSatisfied(JobStatus jobStatus) { + private boolean updateConstraintsSatisfied(JobStatus jobStatus, + NetworkCapabilities capabilities) { + final int jobUid = jobStatus.getSourceUid(); final boolean ignoreBlocked = (jobStatus.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0; - final NetworkInfo info = mConnManager.getActiveNetworkInfoForUid(jobStatus.getSourceUid(), - ignoreBlocked); - final boolean connected = (info != null) && info.isConnected(); + final NetworkInfo info = mConnManager.getActiveNetworkInfoForUid(jobUid, ignoreBlocked); + if (capabilities == null) { + final Network network = mConnManager.getActiveNetworkForUid(jobUid, ignoreBlocked); + capabilities = mConnManager.getNetworkCapabilities(network); + } + + final boolean validated = capabilities != null + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); + final boolean connected = info != null && info.isConnected(); + final boolean connectionUsable = connected && validated; final boolean unmetered = connected && !info.isMetered(); final boolean notRoaming = connected && !info.isRoaming(); boolean changed = false; - changed |= jobStatus.setConnectivityConstraintSatisfied(connected); + changed |= jobStatus.setConnectivityConstraintSatisfied(connectionUsable); changed |= jobStatus.setUnmeteredConstraintSatisfied(unmetered); changed |= jobStatus.setNotRoamingConstraintSatisfied(notRoaming); + + // Track system-uid connected/validated as a general reportable proxy for the + // overall state of connectivity constraint satisfiability. + if (jobUid == Process.SYSTEM_UID) { + mConnected = connected; + mValidated = validated; + } + + if (DEBUG) { + Slog.i(TAG, "Connectivity " + (changed ? "CHANGED" : "unchanged") + + " for " + jobStatus + ": usable=" + connectionUsable + + " connected=" + connected + + " validated=" + validated + + " unmetered=" + unmetered + + " notRoaming=" + notRoaming); + } return changed; } @@ -119,13 +146,13 @@ public class ConnectivityController extends StateController implements * @param uid only update jobs belonging to this UID, or {@code -1} to * update all tracked jobs. */ - private void updateTrackedJobs(int uid) { + private void updateTrackedJobs(int uid, NetworkCapabilities capabilities) { synchronized (mLock) { boolean changed = false; for (int i = 0; i < mTrackedJobs.size(); i++) { final JobStatus js = mTrackedJobs.get(i); if (uid == -1 || uid == js.getSourceUid()) { - changed |= updateConstraintsSatisfied(js); + changed |= updateConstraintsSatisfied(js, capabilities); } } if (changed) { @@ -152,38 +179,61 @@ public class ConnectivityController extends StateController implements } } - private BroadcastReceiver mConnectivityReceiver = new BroadcastReceiver() { + private final NetworkCallback mNetworkCallback = new NetworkCallback() { @Override - public void onReceive(Context context, Intent intent) { - updateTrackedJobs(-1); + public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { + if (DEBUG) { + Slog.v(TAG, "onCapabilitiesChanged() : " + networkCapabilities); + } + updateTrackedJobs(-1, networkCapabilities); + } + + @Override + public void onLost(Network network) { + if (DEBUG) { + Slog.v(TAG, "Network lost"); + } + updateTrackedJobs(-1, null); } }; - private INetworkPolicyListener mNetPolicyListener = new INetworkPolicyListener.Stub() { + private final INetworkPolicyListener mNetPolicyListener = new INetworkPolicyListener.Stub() { @Override public void onUidRulesChanged(int uid, int uidRules) { - updateTrackedJobs(uid); + if (DEBUG) { + Slog.v(TAG, "Uid rules changed for " + uid); + } + updateTrackedJobs(uid, null); } @Override public void onMeteredIfacesChanged(String[] meteredIfaces) { - updateTrackedJobs(-1); + // We track this via our NetworkCallback } @Override public void onRestrictBackgroundChanged(boolean restrictBackground) { - updateTrackedJobs(-1); + if (DEBUG) { + Slog.v(TAG, "Background restriction change to " + restrictBackground); + } + updateTrackedJobs(-1, null); } @Override public void onUidPoliciesChanged(int uid, int uidPolicies) { - updateTrackedJobs(uid); + if (DEBUG) { + Slog.v(TAG, "Uid policy changed for " + uid); + } + updateTrackedJobs(uid, null); } }; @Override public void dumpControllerStateLocked(PrintWriter pw, int filterUid) { - pw.println("Connectivity."); + pw.print("Connectivity: connected="); + pw.print(mConnected); + pw.print(" validated="); + pw.println(mValidated); pw.print("Tracking "); pw.print(mTrackedJobs.size()); pw.println(":");