Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f7994fe6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "ConnectivityController tracks jobs by UID."

parents d4341724 8639b574
Loading
Loading
Loading
Loading
+87 −54
Original line number Original line Diff line number Diff line
@@ -55,6 +55,8 @@ import java.util.function.Predicate;
 * Each app can have a different default networks or different connectivity
 * Each app can have a different default networks or different connectivity
 * status due to user-requested network policies, so we need to check
 * status due to user-requested network policies, so we need to check
 * constraints on a per-UID basis.
 * constraints on a per-UID basis.
 *
 * Test: atest com.android.server.job.controllers.ConnectivityControllerTest
 */
 */
public final class ConnectivityController extends StateController implements
public final class ConnectivityController extends StateController implements
        ConnectivityManager.OnNetworkActiveListener {
        ConnectivityManager.OnNetworkActiveListener {
@@ -65,8 +67,9 @@ public final class ConnectivityController extends StateController implements
    private final ConnectivityManager mConnManager;
    private final ConnectivityManager mConnManager;
    private final NetworkPolicyManager mNetPolicyManager;
    private final NetworkPolicyManager mNetPolicyManager;


    /** List of tracked jobs keyed by source UID. */
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private final ArraySet<JobStatus> mTrackedJobs = new ArraySet<>();
    private final SparseArray<ArraySet<JobStatus>> mTrackedJobs = new SparseArray<>();


    public ConnectivityController(JobSchedulerService service) {
    public ConnectivityController(JobSchedulerService service) {
        super(service);
        super(service);
@@ -87,7 +90,12 @@ public final class ConnectivityController extends StateController implements
    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
        if (jobStatus.hasConnectivityConstraint()) {
        if (jobStatus.hasConnectivityConstraint()) {
            updateConstraintsSatisfied(jobStatus);
            updateConstraintsSatisfied(jobStatus);
            mTrackedJobs.add(jobStatus);
            ArraySet<JobStatus> jobs = mTrackedJobs.get(jobStatus.getSourceUid());
            if (jobs == null) {
                jobs = new ArraySet<>();
                mTrackedJobs.put(jobStatus.getSourceUid(), jobs);
            }
            jobs.add(jobStatus);
            jobStatus.setTrackingController(JobStatus.TRACKING_CONNECTIVITY);
            jobStatus.setTrackingController(JobStatus.TRACKING_CONNECTIVITY);
        }
        }
    }
    }
@@ -97,7 +105,10 @@ public final class ConnectivityController extends StateController implements
    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
            boolean forUpdate) {
            boolean forUpdate) {
        if (jobStatus.clearTrackingController(JobStatus.TRACKING_CONNECTIVITY)) {
        if (jobStatus.clearTrackingController(JobStatus.TRACKING_CONNECTIVITY)) {
            mTrackedJobs.remove(jobStatus);
            ArraySet<JobStatus> jobs = mTrackedJobs.get(jobStatus.getSourceUid());
            if (jobs != null) {
                jobs.remove(jobStatus);
            }
        }
        }
    }
    }


@@ -244,43 +255,52 @@ public final class ConnectivityController extends StateController implements
        synchronized (mLock) {
        synchronized (mLock) {
            // Since this is a really hot codepath, temporarily cache any
            // Since this is a really hot codepath, temporarily cache any
            // answers that we get from ConnectivityManager.
            // answers that we get from ConnectivityManager.
            final SparseArray<Network> uidToNetwork = new SparseArray<>();
            final SparseArray<NetworkCapabilities> networkToCapabilities = new SparseArray<>();
            final SparseArray<NetworkCapabilities> networkToCapabilities = new SparseArray<>();


            boolean changed = false;
            boolean changed = false;
            if (filterUid == -1) {
                for (int i = mTrackedJobs.size() - 1; i >= 0; i--) {
                for (int i = mTrackedJobs.size() - 1; i >= 0; i--) {
                final JobStatus js = mTrackedJobs.valueAt(i);
                    changed |= updateTrackedJobsLocked(mTrackedJobs.valueAt(i),
                final int uid = js.getSourceUid();
                            filterNetwork, networkToCapabilities);
                }
            } else {
                changed = updateTrackedJobsLocked(mTrackedJobs.get(filterUid),
                        filterNetwork, networkToCapabilities);
            }
            if (changed) {
                mStateChangedListener.onControllerStateChanged();
            }
        }
    }


                final boolean uidMatch = (filterUid == -1 || filterUid == uid);
    private boolean updateTrackedJobsLocked(ArraySet<JobStatus> jobs, Network filterNetwork,
                if (uidMatch) {
            SparseArray<NetworkCapabilities> networkToCapabilities) {
                    Network network = uidToNetwork.get(uid);
        if (jobs == null || jobs.size() == 0) {
                    if (network == null) {
            return false;
                        network = mConnManager.getActiveNetworkForUid(uid);
                        uidToNetwork.put(uid, network);
        }
        }


                    // Update either when we have a network match, or when the
        final Network network = mConnManager.getActiveNetworkForUid(jobs.valueAt(0).getSourceUid());
                    // job hasn't yet been evaluated against the currently
                    // active network; typically when we just lost a network.
                    final boolean networkMatch = (filterNetwork == null
                            || Objects.equals(filterNetwork, network));
                    final boolean forceUpdate = !Objects.equals(js.network, network);
                    if (networkMatch || forceUpdate) {
        final int netId = network != null ? network.netId : -1;
        final int netId = network != null ? network.netId : -1;
        NetworkCapabilities capabilities = networkToCapabilities.get(netId);
        NetworkCapabilities capabilities = networkToCapabilities.get(netId);
        if (capabilities == null) {
        if (capabilities == null) {
            capabilities = mConnManager.getNetworkCapabilities(network);
            capabilities = mConnManager.getNetworkCapabilities(network);
            networkToCapabilities.put(netId, capabilities);
            networkToCapabilities.put(netId, capabilities);
        }
        }
        final boolean networkMatch = (filterNetwork == null
                || Objects.equals(filterNetwork, network));

        boolean changed = false;
        for (int i = jobs.size() - 1; i >= 0; i--) {
            final JobStatus js = jobs.valueAt(i);

            // Update either when we have a network match, or when the
            // job hasn't yet been evaluated against the currently
            // active network; typically when we just lost a network.
            if (networkMatch || !Objects.equals(js.network, network)) {
                changed |= updateConstraintsSatisfied(js, network, capabilities);
                changed |= updateConstraintsSatisfied(js, network, capabilities);
            }
            }
        }
        }
            }
        return changed;
            if (changed) {
                mStateChangedListener.onControllerStateChanged();
            }
        }
    }
    }


    /**
    /**
@@ -290,7 +310,9 @@ public final class ConnectivityController extends StateController implements
    public void onNetworkActive() {
    public void onNetworkActive() {
        synchronized (mLock) {
        synchronized (mLock) {
            for (int i = mTrackedJobs.size()-1; i >= 0; i--) {
            for (int i = mTrackedJobs.size()-1; i >= 0; i--) {
                final JobStatus js = mTrackedJobs.valueAt(i);
                final ArraySet<JobStatus> jobs = mTrackedJobs.valueAt(i);
                for (int j = jobs.size() - 1; j >= 0; j--) {
                    final JobStatus js = jobs.valueAt(j);
                    if (js.isReady()) {
                    if (js.isReady()) {
                        if (DEBUG) {
                        if (DEBUG) {
                            Slog.d(TAG, "Running " + js + " due to network activity.");
                            Slog.d(TAG, "Running " + js + " due to network activity.");
@@ -300,6 +322,7 @@ public final class ConnectivityController extends StateController implements
                }
                }
            }
            }
        }
        }
    }


    private final NetworkCallback mNetworkCallback = new NetworkCallback() {
    private final NetworkCallback mNetworkCallback = new NetworkCallback() {
        @Override
        @Override
@@ -334,8 +357,12 @@ public final class ConnectivityController extends StateController implements
    public void dumpControllerStateLocked(IndentingPrintWriter pw,
    public void dumpControllerStateLocked(IndentingPrintWriter pw,
            Predicate<JobStatus> predicate) {
            Predicate<JobStatus> predicate) {
        for (int i = 0; i < mTrackedJobs.size(); i++) {
        for (int i = 0; i < mTrackedJobs.size(); i++) {
            final JobStatus js = mTrackedJobs.valueAt(i);
            final ArraySet<JobStatus> jobs = mTrackedJobs.valueAt(i);
            if (predicate.test(js)) {
            for (int j = 0; j < jobs.size(); j++) {
                final JobStatus js = jobs.valueAt(j);
                if (!predicate.test(js)) {
                    continue;
                }
                pw.print("#");
                pw.print("#");
                js.printUniqueId(pw);
                js.printUniqueId(pw);
                pw.print(" from ");
                pw.print(" from ");
@@ -355,21 +382,27 @@ public final class ConnectivityController extends StateController implements
        final long mToken = proto.start(StateControllerProto.CONNECTIVITY);
        final long mToken = proto.start(StateControllerProto.CONNECTIVITY);


        for (int i = 0; i < mTrackedJobs.size(); i++) {
        for (int i = 0; i < mTrackedJobs.size(); i++) {
            final JobStatus js = mTrackedJobs.valueAt(i);
            final ArraySet<JobStatus> jobs = mTrackedJobs.valueAt(i);
            for (int j = 0; j < jobs.size(); j++) {
                final JobStatus js = jobs.valueAt(j);
                if (!predicate.test(js)) {
                if (!predicate.test(js)) {
                    continue;
                    continue;
                }
                }
            final long jsToken = proto.start(StateControllerProto.ConnectivityController.TRACKED_JOBS);
                final long jsToken = proto.start(
            js.writeToShortProto(proto, StateControllerProto.ConnectivityController.TrackedJob.INFO);
                        StateControllerProto.ConnectivityController.TRACKED_JOBS);
                js.writeToShortProto(proto,
                        StateControllerProto.ConnectivityController.TrackedJob.INFO);
                proto.write(StateControllerProto.ConnectivityController.TrackedJob.SOURCE_UID,
                proto.write(StateControllerProto.ConnectivityController.TrackedJob.SOURCE_UID,
                        js.getSourceUid());
                        js.getSourceUid());
                NetworkRequest rn = js.getJob().getRequiredNetwork();
                NetworkRequest rn = js.getJob().getRequiredNetwork();
                if (rn != null) {
                if (rn != null) {
                    rn.writeToProto(proto,
                    rn.writeToProto(proto,
                        StateControllerProto.ConnectivityController.TrackedJob.REQUIRED_NETWORK);
                            StateControllerProto.ConnectivityController.TrackedJob
                                    .REQUIRED_NETWORK);
                }
                }
                proto.end(jsToken);
                proto.end(jsToken);
            }
            }
        }


        proto.end(mToken);
        proto.end(mToken);
        proto.end(token);
        proto.end(token);