Cache network capabilities.
Cache network capabilities to reduce the number of calls
ConnectivityController makes to ConnectivityManager.
Bug: 164460449
Bug: 166702583
Test: atest com.android.server.job.controllers.ConnectivityControllerTest
Test: atest CtsJobSchedulerTestCases
Change-Id: I501e5153d7bffd2494aec484c74b9e1b6252aeeb
(cherry picked from commit 6f9ab02900)
This commit is contained in:
@@ -22,6 +22,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
||||
|
||||
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.job.JobInfo;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.ConnectivityManager.NetworkCallback;
|
||||
@@ -86,9 +87,12 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
@GuardedBy("mLock")
|
||||
private final SparseArray<ArraySet<JobStatus>> mRequestedWhitelistJobs = new SparseArray<>();
|
||||
|
||||
/** List of currently available networks. */
|
||||
/**
|
||||
* Set of currently available networks mapped to their latest network capabilities. Cache the
|
||||
* latest capabilities to avoid unnecessary calls into ConnectivityManager.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private final ArraySet<Network> mAvailableNetworks = new ArraySet<>();
|
||||
private final ArrayMap<Network, NetworkCapabilities> mAvailableNetworks = new ArrayMap<>();
|
||||
|
||||
private static final int MSG_DATA_SAVER_TOGGLED = 0;
|
||||
private static final int MSG_UID_RULES_CHANGES = 1;
|
||||
@@ -165,9 +169,8 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
public boolean isNetworkAvailable(JobStatus job) {
|
||||
synchronized (mLock) {
|
||||
for (int i = 0; i < mAvailableNetworks.size(); ++i) {
|
||||
final Network network = mAvailableNetworks.valueAt(i);
|
||||
final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(
|
||||
network);
|
||||
final Network network = mAvailableNetworks.keyAt(i);
|
||||
final NetworkCapabilities capabilities = mAvailableNetworks.valueAt(i);
|
||||
final boolean satisfied = isSatisfied(job, network, capabilities, mConstants);
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "isNetworkAvailable(" + job + ") with network " + network
|
||||
@@ -427,9 +430,33 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private NetworkCapabilities getNetworkCapabilities(@Nullable Network network) {
|
||||
if (network == null) {
|
||||
return null;
|
||||
}
|
||||
synchronized (mLock) {
|
||||
// There is technically a race here if the Network object is reused. This can happen
|
||||
// only if that Network disconnects and the auto-incrementing network ID in
|
||||
// ConnectivityService wraps. This should no longer be a concern if/when we only make
|
||||
// use of asynchronous calls.
|
||||
if (mAvailableNetworks.get(network) != null) {
|
||||
return mAvailableNetworks.get(network);
|
||||
}
|
||||
|
||||
// This should almost never happen because any time a new network connects, the
|
||||
// NetworkCallback would populate mAvailableNetworks. However, it's currently necessary
|
||||
// because we also call synchronous methods such as getActiveNetworkForUid.
|
||||
// TODO(134978280): remove after switching to callback-based APIs
|
||||
final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network);
|
||||
mAvailableNetworks.put(network, capabilities);
|
||||
return capabilities;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean updateConstraintsSatisfied(JobStatus jobStatus) {
|
||||
final Network network = mConnManager.getActiveNetworkForUid(jobStatus.getSourceUid());
|
||||
final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network);
|
||||
final NetworkCapabilities capabilities = getNetworkCapabilities(network);
|
||||
return updateConstraintsSatisfied(jobStatus, network, capabilities);
|
||||
}
|
||||
|
||||
@@ -470,19 +497,13 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
*/
|
||||
private void updateTrackedJobs(int filterUid, Network filterNetwork) {
|
||||
synchronized (mLock) {
|
||||
// Since this is a really hot codepath, temporarily cache any
|
||||
// answers that we get from ConnectivityManager.
|
||||
final ArrayMap<Network, NetworkCapabilities> networkToCapabilities = new ArrayMap<>();
|
||||
|
||||
boolean changed = false;
|
||||
if (filterUid == -1) {
|
||||
for (int i = mTrackedJobs.size() - 1; i >= 0; i--) {
|
||||
changed |= updateTrackedJobsLocked(mTrackedJobs.valueAt(i),
|
||||
filterNetwork, networkToCapabilities);
|
||||
changed |= updateTrackedJobsLocked(mTrackedJobs.valueAt(i), filterNetwork);
|
||||
}
|
||||
} else {
|
||||
changed = updateTrackedJobsLocked(mTrackedJobs.get(filterUid),
|
||||
filterNetwork, networkToCapabilities);
|
||||
changed = updateTrackedJobsLocked(mTrackedJobs.get(filterUid), filterNetwork);
|
||||
}
|
||||
if (changed) {
|
||||
mStateChangedListener.onControllerStateChanged();
|
||||
@@ -490,18 +511,13 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
}
|
||||
}
|
||||
|
||||
private boolean updateTrackedJobsLocked(ArraySet<JobStatus> jobs, Network filterNetwork,
|
||||
ArrayMap<Network, NetworkCapabilities> networkToCapabilities) {
|
||||
private boolean updateTrackedJobsLocked(ArraySet<JobStatus> jobs, Network filterNetwork) {
|
||||
if (jobs == null || jobs.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Network network = mConnManager.getActiveNetworkForUid(jobs.valueAt(0).getSourceUid());
|
||||
NetworkCapabilities capabilities = networkToCapabilities.get(network);
|
||||
if (capabilities == null) {
|
||||
capabilities = mConnManager.getNetworkCapabilities(network);
|
||||
networkToCapabilities.put(network, capabilities);
|
||||
}
|
||||
final NetworkCapabilities capabilities = getNetworkCapabilities(network);
|
||||
final boolean networkMatch = (filterNetwork == null
|
||||
|| Objects.equals(filterNetwork, network));
|
||||
|
||||
@@ -544,9 +560,9 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
@Override
|
||||
public void onAvailable(Network network) {
|
||||
if (DEBUG) Slog.v(TAG, "onAvailable: " + network);
|
||||
synchronized (mLock) {
|
||||
mAvailableNetworks.add(network);
|
||||
}
|
||||
// Documentation says not to call getNetworkCapabilities here but wait for
|
||||
// onCapabilitiesChanged instead. onCapabilitiesChanged should be called immediately
|
||||
// after this, so no need to update mAvailableNetworks here.
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -554,6 +570,9 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "onCapabilitiesChanged: " + network);
|
||||
}
|
||||
synchronized (mLock) {
|
||||
mAvailableNetworks.put(network, capabilities);
|
||||
}
|
||||
updateTrackedJobs(-1, network);
|
||||
}
|
||||
|
||||
@@ -630,6 +649,8 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
pw.println("Available networks:");
|
||||
pw.increaseIndent();
|
||||
for (int i = 0; i < mAvailableNetworks.size(); i++) {
|
||||
pw.print(mAvailableNetworks.keyAt(i));
|
||||
pw.print(": ");
|
||||
pw.println(mAvailableNetworks.valueAt(i));
|
||||
}
|
||||
pw.decreaseIndent();
|
||||
@@ -667,7 +688,7 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
mRequestedWhitelistJobs.keyAt(i));
|
||||
}
|
||||
for (int i = 0; i < mAvailableNetworks.size(); i++) {
|
||||
Network network = mAvailableNetworks.valueAt(i);
|
||||
Network network = mAvailableNetworks.keyAt(i);
|
||||
if (network != null) {
|
||||
network.dumpDebug(proto,
|
||||
StateControllerProto.ConnectivityController.AVAILABLE_NETWORKS);
|
||||
|
||||
Reference in New Issue
Block a user