blob: f5aac087f9b0503ecae4541f5004e196eb5a76a2 [file] [log] [blame]
Matthew Williams6de79e22014-05-01 10:47:00 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
Christopher Tate7060b042014-06-09 19:50:00 -070017package com.android.server.job.controllers;
Matthew Williams6de79e22014-05-01 10:47:00 -070018
Jeff Sharkey1b6519b2016-04-28 15:33:18 -060019import android.app.job.JobInfo;
Matthew Williams6de79e22014-05-01 10:47:00 -070020import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.net.ConnectivityManager;
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -060025import android.net.INetworkPolicyListener;
Matthew Williams6de79e22014-05-01 10:47:00 -070026import android.net.NetworkInfo;
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -060027import android.net.NetworkPolicyManager;
Matthew Williams6de79e22014-05-01 10:47:00 -070028import android.os.UserHandle;
Matthew Williams9b9244b62014-05-14 11:06:04 -070029import android.util.Slog;
Matthew Williams6de79e22014-05-01 10:47:00 -070030
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -060031import com.android.internal.annotations.GuardedBy;
Christopher Tate7060b042014-06-09 19:50:00 -070032import com.android.server.job.JobSchedulerService;
33import com.android.server.job.StateChangedListener;
Matthew Williams6de79e22014-05-01 10:47:00 -070034
Matthew Williamseffacfa2014-06-05 20:56:40 -070035import java.io.PrintWriter;
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -060036import java.util.ArrayList;
Matthew Williams6de79e22014-05-01 10:47:00 -070037
38/**
Matthew Williams9b9244b62014-05-14 11:06:04 -070039 * Handles changes in connectivity.
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -060040 * <p>
41 * Each app can have a different default networks or different connectivity
42 * status due to user-requested network policies, so we need to check
43 * constraints on a per-UID basis.
Matthew Williams6de79e22014-05-01 10:47:00 -070044 */
Matthew Williamseffacfa2014-06-05 20:56:40 -070045public class ConnectivityController extends StateController implements
46 ConnectivityManager.OnNetworkActiveListener {
Christopher Tate7060b042014-06-09 19:50:00 -070047 private static final String TAG = "JobScheduler.Conn";
Matthew Williams6de79e22014-05-01 10:47:00 -070048
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -060049 private final ConnectivityManager mConnManager;
50 private final NetworkPolicyManager mNetPolicyManager;
51
52 @GuardedBy("mLock")
53 private final ArrayList<JobStatus> mTrackedJobs = new ArrayList<JobStatus>();
54
Matthew Williams9b9244b62014-05-14 11:06:04 -070055 /** Singleton. */
56 private static ConnectivityController mSingleton;
Matthew Williamseffacfa2014-06-05 20:56:40 -070057 private static Object sCreationLock = new Object();
Matthew Williams691e93e2014-05-12 15:33:09 -070058
Christopher Tate7060b042014-06-09 19:50:00 -070059 public static ConnectivityController get(JobSchedulerService jms) {
Matthew Williamseffacfa2014-06-05 20:56:40 -070060 synchronized (sCreationLock) {
61 if (mSingleton == null) {
Dianne Hackborn33d31c52016-02-16 10:30:33 -080062 mSingleton = new ConnectivityController(jms, jms.getContext(), jms.getLock());
Matthew Williamseffacfa2014-06-05 20:56:40 -070063 }
64 return mSingleton;
Matthew Williams9b9244b62014-05-14 11:06:04 -070065 }
Matthew Williams9b9244b62014-05-14 11:06:04 -070066 }
67
Dianne Hackborn33d31c52016-02-16 10:30:33 -080068 private ConnectivityController(StateChangedListener stateChangedListener, Context context,
69 Object lock) {
70 super(stateChangedListener, context, lock);
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -060071
72 mConnManager = mContext.getSystemService(ConnectivityManager.class);
73 mNetPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
74
75 final IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
Matthew Williams6de79e22014-05-01 10:47:00 -070076 mContext.registerReceiverAsUser(
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -060077 mConnectivityReceiver, UserHandle.SYSTEM, intentFilter, null, null);
78
79 mNetPolicyManager.registerListener(mNetPolicyListener);
Matthew Williams6de79e22014-05-01 10:47:00 -070080 }
81
82 @Override
Dianne Hackbornb0001f62016-02-16 10:30:33 -080083 public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -060084 if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()
85 || jobStatus.hasNotRoamingConstraint()) {
86 updateConstraintsSatisfied(jobStatus);
Dianne Hackbornb0001f62016-02-16 10:30:33 -080087 mTrackedJobs.add(jobStatus);
Matthew Williamseffacfa2014-06-05 20:56:40 -070088 }
89 }
90
91 @Override
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -060092 public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
93 boolean forUpdate) {
94 if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()
95 || jobStatus.hasNotRoamingConstraint()) {
Dianne Hackbornb0001f62016-02-16 10:30:33 -080096 mTrackedJobs.remove(jobStatus);
Matthew Williamseffacfa2014-06-05 20:56:40 -070097 }
Matthew Williams6de79e22014-05-01 10:47:00 -070098 }
99
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -0600100 private boolean updateConstraintsSatisfied(JobStatus jobStatus) {
Jeff Sharkey1b6519b2016-04-28 15:33:18 -0600101 final boolean ignoreBlocked = (jobStatus.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
102 final NetworkInfo info = mConnManager.getActiveNetworkInfoForUid(jobStatus.getSourceUid(),
103 ignoreBlocked);
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -0600104 final boolean connected = (info != null) && info.isConnected();
105 final boolean unmetered = connected && !info.isMetered();
106 final boolean notRoaming = connected && !info.isRoaming();
107
108 boolean changed = false;
109 changed |= jobStatus.setConnectivityConstraintSatisfied(connected);
110 changed |= jobStatus.setUnmeteredConstraintSatisfied(unmetered);
111 changed |= jobStatus.setNotRoamingConstraintSatisfied(notRoaming);
112 return changed;
113 }
114
Matthew Williams6de79e22014-05-01 10:47:00 -0700115 /**
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -0600116 * Update all jobs tracked by this controller.
117 *
118 * @param uid only update jobs belonging to this UID, or {@code -1} to
119 * update all tracked jobs.
Matthew Williams6de79e22014-05-01 10:47:00 -0700120 */
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -0600121 private void updateTrackedJobs(int uid) {
Dianne Hackborn33d31c52016-02-16 10:30:33 -0800122 synchronized (mLock) {
Matthew Williamseffacfa2014-06-05 20:56:40 -0700123 boolean changed = false;
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -0600124 for (int i = 0; i < mTrackedJobs.size(); i++) {
125 final JobStatus js = mTrackedJobs.get(i);
126 if (uid == -1 || uid == js.getSourceUid()) {
127 changed |= updateConstraintsSatisfied(js);
Matthew Williamseffacfa2014-06-05 20:56:40 -0700128 }
Matthew Williamseffacfa2014-06-05 20:56:40 -0700129 }
130 if (changed) {
131 mStateChangedListener.onControllerStateChanged();
Matthew Williams6de79e22014-05-01 10:47:00 -0700132 }
133 }
Matthew Williamseffacfa2014-06-05 20:56:40 -0700134 }
135
136 /**
Christopher Tate7060b042014-06-09 19:50:00 -0700137 * We know the network has just come up. We want to run any jobs that are ready.
Matthew Williamseffacfa2014-06-05 20:56:40 -0700138 */
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -0600139 @Override
Matthew Williamseffacfa2014-06-05 20:56:40 -0700140 public synchronized void onNetworkActive() {
Dianne Hackborn33d31c52016-02-16 10:30:33 -0800141 synchronized (mLock) {
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -0600142 for (int i = 0; i < mTrackedJobs.size(); i++) {
143 final JobStatus js = mTrackedJobs.get(i);
Christopher Tate7060b042014-06-09 19:50:00 -0700144 if (js.isReady()) {
Matthew Williamseffacfa2014-06-05 20:56:40 -0700145 if (DEBUG) {
Christopher Tate7060b042014-06-09 19:50:00 -0700146 Slog.d(TAG, "Running " + js + " due to network activity.");
Matthew Williamseffacfa2014-06-05 20:56:40 -0700147 }
Christopher Tate7060b042014-06-09 19:50:00 -0700148 mStateChangedListener.onRunJobNow(js);
Matthew Williamseffacfa2014-06-05 20:56:40 -0700149 }
150 }
Matthew Williams9b9244b62014-05-14 11:06:04 -0700151 }
Matthew Williams6de79e22014-05-01 10:47:00 -0700152 }
153
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -0600154 private BroadcastReceiver mConnectivityReceiver = new BroadcastReceiver() {
Matthew Williams6de79e22014-05-01 10:47:00 -0700155 @Override
156 public void onReceive(Context context, Intent intent) {
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -0600157 updateTrackedJobs(-1);
158 }
159 };
160
161 private INetworkPolicyListener mNetPolicyListener = new INetworkPolicyListener.Stub() {
162 @Override
163 public void onUidRulesChanged(int uid, int uidRules) {
164 updateTrackedJobs(uid);
165 }
166
167 @Override
168 public void onMeteredIfacesChanged(String[] meteredIfaces) {
169 updateTrackedJobs(-1);
170 }
171
172 @Override
173 public void onRestrictBackgroundChanged(boolean restrictBackground) {
174 updateTrackedJobs(-1);
175 }
176
177 @Override
178 public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) {
179 updateTrackedJobs(uid);
Matthew Williams6de79e22014-05-01 10:47:00 -0700180 }
181 };
Matthew Williamseffacfa2014-06-05 20:56:40 -0700182
183 @Override
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800184 public void dumpControllerStateLocked(PrintWriter pw) {
Matthew Williamseffacfa2014-06-05 20:56:40 -0700185 pw.println("Conn.");
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -0600186 for (int i = 0; i < mTrackedJobs.size(); i++) {
187 final JobStatus js = mTrackedJobs.get(i);
Shreyas Basarge0529dac2016-03-15 22:19:04 +0000188 pw.println(String.valueOf(js.getJobId() + "," + js.getUid())
Christopher Tate7060b042014-06-09 19:50:00 -0700189 + ": C=" + js.hasConnectivityConstraint()
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -0600190 + ", UM=" + js.hasUnmeteredConstraint()
191 + ", NR=" + js.hasNotRoamingConstraint());
Matthew Williamseffacfa2014-06-05 20:56:40 -0700192 }
193 }
Robert Greenwalt6078b502014-06-11 16:05:07 -0700194}