blob: 99569a8449dda757c1a2d6fd471dc228bb3a8a6e [file] [log] [blame]
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001/*
2 * Copyright (C) 2011 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
17package com.android.server.net;
18
Jeff Sharkey21c9c452011-06-07 12:26:43 -070019import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
Jeff Sharkey1b861272011-05-22 00:34:52 -070020import static android.Manifest.permission.DUMP;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070021import static android.Manifest.permission.MANAGE_APP_TOKENS;
Jeff Sharkey21c9c452011-06-07 12:26:43 -070022import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
Jeff Sharkey22c055e2011-06-12 21:13:51 -070023import static android.Manifest.permission.READ_PHONE_STATE;
Jeff Sharkey21c9c452011-06-07 12:26:43 -070024import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
Jeff Sharkey22c055e2011-06-12 21:13:51 -070025import static android.net.NetworkPolicy.LIMIT_DISABLED;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070026import static android.net.NetworkPolicyManager.POLICY_NONE;
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -070027import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND;
28import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
29import static android.net.NetworkPolicyManager.RULE_REJECT_PAID;
Jeff Sharkeycd2ca402011-06-10 15:14:07 -070030import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
Jeff Sharkey1b861272011-05-22 00:34:52 -070031import static android.net.NetworkPolicyManager.dumpPolicy;
32import static android.net.NetworkPolicyManager.dumpRules;
Jeff Sharkey22c055e2011-06-12 21:13:51 -070033import static android.net.TrafficStats.TEMPLATE_MOBILE_ALL;
34import static android.net.TrafficStats.isNetworkTemplateMobile;
Jeff Sharkey21c9c452011-06-07 12:26:43 -070035import static android.text.format.DateUtils.DAY_IN_MILLIS;
Jeff Sharkey21c9c452011-06-07 12:26:43 -070036import static com.android.internal.util.Preconditions.checkNotNull;
37import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
38import static org.xmlpull.v1.XmlPullParser.START_TAG;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070039
Jeff Sharkeya4620792011-05-20 15:29:23 -070040import android.app.IActivityManager;
41import android.app.IProcessObserver;
42import android.content.BroadcastReceiver;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070043import android.content.Context;
Jeff Sharkeya4620792011-05-20 15:29:23 -070044import android.content.Intent;
45import android.content.IntentFilter;
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -070046import android.net.ConnectivityManager;
Jeff Sharkey21c9c452011-06-07 12:26:43 -070047import android.net.IConnectivityManager;
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -070048import android.net.INetworkPolicyListener;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070049import android.net.INetworkPolicyManager;
Jeff Sharkey75279902011-05-24 18:39:45 -070050import android.net.INetworkStatsService;
Jeff Sharkey21c9c452011-06-07 12:26:43 -070051import android.net.NetworkPolicy;
52import android.net.NetworkState;
53import android.net.NetworkStats;
54import android.os.Environment;
55import android.os.Handler;
56import android.os.HandlerThread;
Jeff Sharkeya4620792011-05-20 15:29:23 -070057import android.os.IPowerManager;
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -070058import android.os.RemoteCallbackList;
Jeff Sharkeya4620792011-05-20 15:29:23 -070059import android.os.RemoteException;
Jeff Sharkey22c055e2011-06-12 21:13:51 -070060import android.telephony.TelephonyManager;
61import android.text.format.Time;
Jeff Sharkey21c9c452011-06-07 12:26:43 -070062import android.util.NtpTrustedTime;
Jeff Sharkeya4620792011-05-20 15:29:23 -070063import android.util.Slog;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070064import android.util.SparseArray;
65import android.util.SparseBooleanArray;
66import android.util.SparseIntArray;
Jeff Sharkey21c9c452011-06-07 12:26:43 -070067import android.util.TrustedTime;
68import android.util.Xml;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070069
Jeff Sharkey21c9c452011-06-07 12:26:43 -070070import com.android.internal.os.AtomicFile;
71import com.android.internal.util.FastXmlSerializer;
72import com.android.internal.util.Objects;
73import com.google.android.collect.Lists;
74import com.google.android.collect.Maps;
75
76import org.xmlpull.v1.XmlPullParser;
77import org.xmlpull.v1.XmlPullParserException;
78import org.xmlpull.v1.XmlSerializer;
79
80import java.io.File;
Jeff Sharkey1b861272011-05-22 00:34:52 -070081import java.io.FileDescriptor;
Jeff Sharkey21c9c452011-06-07 12:26:43 -070082import java.io.FileInputStream;
83import java.io.FileNotFoundException;
84import java.io.FileOutputStream;
85import java.io.IOException;
Jeff Sharkey1b861272011-05-22 00:34:52 -070086import java.io.PrintWriter;
Jeff Sharkey21c9c452011-06-07 12:26:43 -070087import java.net.ProtocolException;
88import java.util.ArrayList;
89import java.util.Arrays;
90import java.util.HashMap;
91
92import libcore.io.IoUtils;
Jeff Sharkey1b861272011-05-22 00:34:52 -070093
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070094/**
95 * Service that maintains low-level network policy rules and collects usage
96 * statistics to drive those rules.
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -070097 * <p>
98 * Derives active rules by combining a given policy with other system status,
99 * and delivers to listeners, such as {@link ConnectivityManager}, for
100 * enforcement.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700101 */
102public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
103 private static final String TAG = "NetworkPolicy";
104 private static final boolean LOGD = true;
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700105 private static final boolean LOGV = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700106
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700107 private static final int VERSION_CURRENT = 1;
108
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700109 private static final long KB_IN_BYTES = 1024;
110 private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
111 private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
112
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700113 private static final String TAG_POLICY_LIST = "policy-list";
114 private static final String TAG_NETWORK_POLICY = "network-policy";
115 private static final String TAG_UID_POLICY = "uid-policy";
116
117 private static final String ATTR_VERSION = "version";
118 private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
119 private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
120 private static final String ATTR_CYCLE_DAY = "cycleDay";
121 private static final String ATTR_WARNING_BYTES = "warningBytes";
122 private static final String ATTR_LIMIT_BYTES = "limitBytes";
123 private static final String ATTR_UID = "uid";
124 private static final String ATTR_POLICY = "policy";
125
126 private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
127
Jeff Sharkey75279902011-05-24 18:39:45 -0700128 private final Context mContext;
129 private final IActivityManager mActivityManager;
130 private final IPowerManager mPowerManager;
131 private final INetworkStatsService mNetworkStats;
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700132 private final TrustedTime mTime;
133
134 private IConnectivityManager mConnManager;
Jeff Sharkeya4620792011-05-20 15:29:23 -0700135
Jeff Sharkey75279902011-05-24 18:39:45 -0700136 private final Object mRulesLock = new Object();
Jeff Sharkeya4620792011-05-20 15:29:23 -0700137
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -0700138 private boolean mScreenOn;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700139
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700140 /** Current policy for network templates. */
141 private ArrayList<NetworkPolicy> mNetworkPolicy = Lists.newArrayList();
142
143 /** Current policy for each UID. */
Jeff Sharkeya4620792011-05-20 15:29:23 -0700144 private SparseIntArray mUidPolicy = new SparseIntArray();
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -0700145 /** Current derived network rules for each UID. */
146 private SparseIntArray mUidRules = new SparseIntArray();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700147
148 /** Foreground at both UID and PID granularity. */
Jeff Sharkeya4620792011-05-20 15:29:23 -0700149 private SparseBooleanArray mUidForeground = new SparseBooleanArray();
150 private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
151 SparseBooleanArray>();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700152
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -0700153 private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
154 INetworkPolicyListener>();
155
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700156 private final HandlerThread mHandlerThread;
157 private final Handler mHandler;
158
159 private final AtomicFile mPolicyFile;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700160
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -0700161 // TODO: keep whitelist of system-critical services that should never have
162 // rules enforced, such as system, phone, and radio UIDs.
163
Jeff Sharkey75279902011-05-24 18:39:45 -0700164 public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
165 IPowerManager powerManager, INetworkStatsService networkStats) {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700166 // TODO: move to using cached NtpTrustedTime
167 this(context, activityManager, powerManager, networkStats, new NtpTrustedTime(),
168 getSystemDir());
169 }
170
171 private static File getSystemDir() {
172 return new File(Environment.getDataDirectory(), "system");
173 }
174
175 public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
176 IPowerManager powerManager, INetworkStatsService networkStats, TrustedTime time,
177 File systemDir) {
Jeff Sharkeya4620792011-05-20 15:29:23 -0700178 mContext = checkNotNull(context, "missing context");
179 mActivityManager = checkNotNull(activityManager, "missing activityManager");
180 mPowerManager = checkNotNull(powerManager, "missing powerManager");
Jeff Sharkey75279902011-05-24 18:39:45 -0700181 mNetworkStats = checkNotNull(networkStats, "missing networkStats");
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700182 mTime = checkNotNull(time, "missing TrustedTime");
183
184 mHandlerThread = new HandlerThread(TAG);
185 mHandlerThread.start();
Jeff Sharkeyaf11d482011-06-13 00:14:31 -0700186 mHandler = new Handler(mHandlerThread.getLooper());
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700187
188 mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
189 }
190
191 public void bindConnectivityManager(IConnectivityManager connManager) {
192 mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
Jeff Sharkeya4620792011-05-20 15:29:23 -0700193 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700194
Jeff Sharkeya4620792011-05-20 15:29:23 -0700195 public void systemReady() {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700196 synchronized (mRulesLock) {
197 // read policy from disk
198 readPolicyLocked();
199 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700200
Jeff Sharkeya4620792011-05-20 15:29:23 -0700201 updateScreenOn();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700202
Jeff Sharkeya4620792011-05-20 15:29:23 -0700203 try {
204 mActivityManager.registerProcessObserver(mProcessObserver);
205 } catch (RemoteException e) {
206 // ouch, no foregroundActivities updates means some processes may
207 // never get network access.
208 Slog.e(TAG, "unable to register IProcessObserver", e);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700209 }
Jeff Sharkeya4620792011-05-20 15:29:23 -0700210
211 // TODO: traverse existing processes to know foreground state, or have
212 // activitymanager dispatch current state when new observer attached.
213
214 final IntentFilter screenFilter = new IntentFilter();
215 screenFilter.addAction(Intent.ACTION_SCREEN_ON);
216 screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
217 mContext.registerReceiver(mScreenReceiver, screenFilter);
218
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700219 // watch for network interfaces to be claimed
220 final IntentFilter ifaceFilter = new IntentFilter();
221 ifaceFilter.addAction(CONNECTIVITY_ACTION);
222 mContext.registerReceiver(mIfaceReceiver, ifaceFilter, CONNECTIVITY_INTERNAL, mHandler);
223
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700224 }
225
Jeff Sharkeya4620792011-05-20 15:29:23 -0700226 private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
227 @Override
228 public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
229 // only someone like AMS should only be calling us
Jeff Sharkey75279902011-05-24 18:39:45 -0700230 mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700231
Jeff Sharkeya4620792011-05-20 15:29:23 -0700232 synchronized (mRulesLock) {
233 // because a uid can have multiple pids running inside, we need to
234 // remember all pid states and summarize foreground at uid level.
235
236 // record foreground for this specific pid
237 SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
238 if (pidForeground == null) {
239 pidForeground = new SparseBooleanArray(2);
240 mUidPidForeground.put(uid, pidForeground);
241 }
242 pidForeground.put(pid, foregroundActivities);
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700243 computeUidForegroundLocked(uid);
Jeff Sharkeya4620792011-05-20 15:29:23 -0700244 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700245 }
Jeff Sharkeya4620792011-05-20 15:29:23 -0700246
247 @Override
248 public void onProcessDied(int pid, int uid) {
249 // only someone like AMS should only be calling us
Jeff Sharkey75279902011-05-24 18:39:45 -0700250 mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
Jeff Sharkeya4620792011-05-20 15:29:23 -0700251
252 synchronized (mRulesLock) {
253 // clear records and recompute, when they exist
254 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
255 if (pidForeground != null) {
256 pidForeground.delete(pid);
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700257 computeUidForegroundLocked(uid);
Jeff Sharkeya4620792011-05-20 15:29:23 -0700258 }
259 }
260 }
261 };
262
263 private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
264 @Override
265 public void onReceive(Context context, Intent intent) {
266 synchronized (mRulesLock) {
267 // screen-related broadcasts are protected by system, no need
268 // for permissions check.
269 updateScreenOn();
270 }
271 }
272 };
273
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700274 /**
275 * Receiver that watches for {@link IConnectivityManager} to claim network
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700276 * interfaces. Used to apply {@link NetworkPolicy} to matching networks.
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700277 */
278 private BroadcastReceiver mIfaceReceiver = new BroadcastReceiver() {
279 @Override
280 public void onReceive(Context context, Intent intent) {
281 // on background handler thread, and verified CONNECTIVITY_INTERNAL
282 // permission above.
283 synchronized (mRulesLock) {
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700284 ensureActiveMobilePolicyLocked();
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700285 updateIfacesLocked();
286 }
287 }
288 };
289
290 /**
291 * Examine all connected {@link NetworkState}, looking for
292 * {@link NetworkPolicy} that need to be enforced. When matches found, set
293 * remaining quota based on usage cycle and historical stats.
294 */
295 private void updateIfacesLocked() {
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700296 if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700297
298 final NetworkState[] states;
299 try {
300 states = mConnManager.getAllNetworkState();
301 } catch (RemoteException e) {
302 Slog.w(TAG, "problem reading network state");
303 return;
304 }
305
306 // first, derive identity for all connected networks, which can be used
307 // to match against templates.
308 final HashMap<NetworkIdentity, String> networks = Maps.newHashMap();
309 for (NetworkState state : states) {
310 // stash identity and iface away for later use
311 if (state.networkInfo.isConnected()) {
312 final String iface = state.linkProperties.getInterfaceName();
313 final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
314 networks.put(ident, iface);
315 }
316 }
317
318 // build list of rules and ifaces to enforce them against
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700319 final HashMap<NetworkPolicy, String[]> rules = Maps.newHashMap();
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700320 final ArrayList<String> ifaceList = Lists.newArrayList();
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700321 for (NetworkPolicy policy : mNetworkPolicy) {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700322
323 // collect all active ifaces that match this template
324 ifaceList.clear();
325 for (NetworkIdentity ident : networks.keySet()) {
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700326 if (ident.matchesTemplate(policy.networkTemplate, policy.subscriberId)) {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700327 final String iface = networks.get(ident);
328 ifaceList.add(iface);
329 }
330 }
331
332 if (ifaceList.size() > 0) {
333 final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]);
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700334 rules.put(policy, ifaces);
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700335 }
336 }
337
338 // try refreshing time source when stale
339 if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
340 mTime.forceRefresh();
341 }
342
343 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
344 : System.currentTimeMillis();
345
346 // apply each policy that we found ifaces for; compute remaining data
347 // based on current cycle and historical stats, and push to kernel.
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700348 for (NetworkPolicy policy : rules.keySet()) {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700349 final String[] ifaces = rules.get(policy);
350
351 final long start = computeLastCycleBoundary(currentTime, policy);
352 final long end = currentTime;
353
354 final NetworkStats stats;
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700355 final long total;
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700356 try {
357 stats = mNetworkStats.getSummaryForNetwork(
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700358 start, end, policy.networkTemplate, policy.subscriberId);
359 total = stats.rx[0] + stats.tx[0];
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700360 } catch (RemoteException e) {
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700361 Slog.w(TAG, "problem reading summary for template " + policy.networkTemplate);
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700362 continue;
363 }
364
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700365 if (LOGD) {
366 Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700367 + Arrays.toString(ifaces));
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700368 }
369
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700370 // TODO: register for warning notification trigger through NMS
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700371
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700372 if (policy.limitBytes != NetworkPolicy.LIMIT_DISABLED) {
373 // remaining "quota" is based on usage in current cycle
374 final long quota = Math.max(0, policy.limitBytes - total);
375
376 // TODO: push quota rule down through NMS
377 }
378 }
379 }
380
381 /**
382 * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
383 * have at least a default mobile policy defined.
384 */
385 private void ensureActiveMobilePolicyLocked() {
386 if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
387 final String subscriberId = getActiveSubscriberId();
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700388
389 // examine to see if any policy is defined for active mobile
390 boolean mobileDefined = false;
391 for (NetworkPolicy policy : mNetworkPolicy) {
392 if (isNetworkTemplateMobile(policy.networkTemplate)
393 && Objects.equal(subscriberId, policy.subscriberId)) {
394 mobileDefined = true;
395 }
396 }
397
398 if (!mobileDefined) {
399 Slog.i(TAG, "no policy for active mobile network; generating default policy");
400
401 // default mobile policy has combined 4GB warning, and assume usage
402 // cycle starts today today.
403
404 // TODO: move this policy definition to overlay or secure setting
405 final Time time = new Time(Time.TIMEZONE_UTC);
406 time.setToNow();
407 final int cycleDay = time.monthDay;
408
409 mNetworkPolicy.add(new NetworkPolicy(
410 TEMPLATE_MOBILE_ALL, subscriberId, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED));
Jeff Sharkeyfcc79772011-06-13 22:28:34 -0700411 writePolicyLocked();
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700412 }
413 }
414
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700415 private void readPolicyLocked() {
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700416 if (LOGV) Slog.v(TAG, "readPolicyLocked()");
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700417
418 // clear any existing policy and read from disk
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700419 mNetworkPolicy.clear();
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700420 mUidPolicy.clear();
421
422 FileInputStream fis = null;
423 try {
424 fis = mPolicyFile.openRead();
425 final XmlPullParser in = Xml.newPullParser();
426 in.setInput(fis, null);
427
428 int type;
429 int version = VERSION_CURRENT;
430 while ((type = in.next()) != END_DOCUMENT) {
431 final String tag = in.getName();
432 if (type == START_TAG) {
433 if (TAG_POLICY_LIST.equals(tag)) {
434 version = readIntAttribute(in, ATTR_VERSION);
435
436 } else if (TAG_NETWORK_POLICY.equals(tag)) {
437 final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
438 final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700439 final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
440 final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
441 final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
442
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700443 mNetworkPolicy.add(new NetworkPolicy(
444 networkTemplate, subscriberId, cycleDay, warningBytes, limitBytes));
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700445
446 } else if (TAG_UID_POLICY.equals(tag)) {
447 final int uid = readIntAttribute(in, ATTR_UID);
448 final int policy = readIntAttribute(in, ATTR_POLICY);
449
450 mUidPolicy.put(uid, policy);
451 }
452 }
453 }
454
455 } catch (FileNotFoundException e) {
456 // missing policy is okay, probably first boot
457 } catch (IOException e) {
458 Slog.e(TAG, "problem reading network stats", e);
459 } catch (XmlPullParserException e) {
460 Slog.e(TAG, "problem reading network stats", e);
461 } finally {
462 IoUtils.closeQuietly(fis);
463 }
464 }
465
466 private void writePolicyLocked() {
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700467 if (LOGV) Slog.v(TAG, "writePolicyLocked()");
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700468
469 FileOutputStream fos = null;
470 try {
471 fos = mPolicyFile.startWrite();
472
473 XmlSerializer out = new FastXmlSerializer();
474 out.setOutput(fos, "utf-8");
475 out.startDocument(null, true);
476
477 out.startTag(null, TAG_POLICY_LIST);
478 writeIntAttribute(out, ATTR_VERSION, VERSION_CURRENT);
479
480 // write all known network policies
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700481 for (NetworkPolicy policy : mNetworkPolicy) {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700482 out.startTag(null, TAG_NETWORK_POLICY);
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700483 writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, policy.networkTemplate);
484 if (policy.subscriberId != null) {
485 out.attribute(null, ATTR_SUBSCRIBER_ID, policy.subscriberId);
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700486 }
487 writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
488 writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
489 writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
490 out.endTag(null, TAG_NETWORK_POLICY);
491 }
492
493 // write all known uid policies
494 for (int i = 0; i < mUidPolicy.size(); i++) {
495 final int uid = mUidPolicy.keyAt(i);
496 final int policy = mUidPolicy.valueAt(i);
497
498 out.startTag(null, TAG_UID_POLICY);
499 writeIntAttribute(out, ATTR_UID, uid);
500 writeIntAttribute(out, ATTR_POLICY, policy);
501 out.endTag(null, TAG_UID_POLICY);
502 }
503
504 out.endTag(null, TAG_POLICY_LIST);
505 out.endDocument();
506
507 mPolicyFile.finishWrite(fos);
508 } catch (IOException e) {
509 if (fos != null) {
510 mPolicyFile.failWrite(fos);
511 }
512 }
513 }
514
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700515 @Override
516 public void setUidPolicy(int uid, int policy) {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700517 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
Jeff Sharkeya4620792011-05-20 15:29:23 -0700518
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -0700519 final int oldPolicy;
Jeff Sharkeya4620792011-05-20 15:29:23 -0700520 synchronized (mRulesLock) {
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -0700521 oldPolicy = getUidPolicy(uid);
Jeff Sharkeya4620792011-05-20 15:29:23 -0700522 mUidPolicy.put(uid, policy);
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -0700523
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700524 // uid policy changed, recompute rules and persist policy.
525 updateRulesForUidLocked(uid);
526 writePolicyLocked();
527 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700528 }
529
530 @Override
531 public int getUidPolicy(int uid) {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700532 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
533
Jeff Sharkeya4620792011-05-20 15:29:23 -0700534 synchronized (mRulesLock) {
535 return mUidPolicy.get(uid, POLICY_NONE);
536 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700537 }
538
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -0700539 @Override
540 public void registerListener(INetworkPolicyListener listener) {
541 mListeners.register(listener);
542
543 synchronized (mRulesLock) {
544 // dispatch any existing rules to new listeners
545 final int size = mUidRules.size();
546 for (int i = 0; i < size; i++) {
547 final int uid = mUidRules.keyAt(i);
548 final int uidRules = mUidRules.valueAt(i);
549 if (uidRules != RULE_ALLOW_ALL) {
550 try {
551 listener.onRulesChanged(uid, uidRules);
552 } catch (RemoteException e) {
553 }
554 }
555 }
556 }
557 }
558
559 @Override
560 public void unregisterListener(INetworkPolicyListener listener) {
561 mListeners.unregister(listener);
562 }
563
Jeff Sharkey1b861272011-05-22 00:34:52 -0700564 @Override
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700565 public void setNetworkPolicies(NetworkPolicy[] policies) {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700566 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
567
568 synchronized (mRulesLock) {
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700569 mNetworkPolicy.clear();
570 for (NetworkPolicy policy : policies) {
571 mNetworkPolicy.add(policy);
572 }
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700573
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700574 updateIfacesLocked();
575 writePolicyLocked();
576 }
577 }
578
579 @Override
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700580 public NetworkPolicy[] getNetworkPolicies() {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700581 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700582 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700583
584 synchronized (mRulesLock) {
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700585 return mNetworkPolicy.toArray(new NetworkPolicy[mNetworkPolicy.size()]);
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700586 }
587 }
588
589 @Override
Jeff Sharkey1b861272011-05-22 00:34:52 -0700590 protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
Jeff Sharkey75279902011-05-24 18:39:45 -0700591 mContext.enforceCallingOrSelfPermission(DUMP, TAG);
Jeff Sharkey1b861272011-05-22 00:34:52 -0700592
593 synchronized (mRulesLock) {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700594 fout.println("Network policies:");
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700595 for (NetworkPolicy policy : mNetworkPolicy) {
596 fout.print(" "); fout.println(policy.toString());
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700597 }
598
Jeff Sharkey1b861272011-05-22 00:34:52 -0700599 fout.println("Policy status for known UIDs:");
600
601 final SparseBooleanArray knownUids = new SparseBooleanArray();
602 collectKeys(mUidPolicy, knownUids);
603 collectKeys(mUidForeground, knownUids);
604 collectKeys(mUidRules, knownUids);
605
606 final int size = knownUids.size();
607 for (int i = 0; i < size; i++) {
608 final int uid = knownUids.keyAt(i);
609 fout.print(" UID=");
610 fout.print(uid);
611
612 fout.print(" policy=");
613 final int policyIndex = mUidPolicy.indexOfKey(uid);
614 if (policyIndex < 0) {
615 fout.print("UNKNOWN");
616 } else {
617 dumpPolicy(fout, mUidPolicy.valueAt(policyIndex));
618 }
619
620 fout.print(" foreground=");
621 final int foregroundIndex = mUidPidForeground.indexOfKey(uid);
622 if (foregroundIndex < 0) {
623 fout.print("UNKNOWN");
624 } else {
625 dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex));
626 }
627
628 fout.print(" rules=");
629 final int rulesIndex = mUidRules.indexOfKey(uid);
630 if (rulesIndex < 0) {
631 fout.print("UNKNOWN");
632 } else {
633 dumpRules(fout, mUidRules.valueAt(rulesIndex));
634 }
635
636 fout.println();
637 }
638 }
639 }
Jeff Sharkey9599cc52011-05-22 14:59:31 -0700640
641 @Override
642 public boolean isUidForeground(int uid) {
643 synchronized (mRulesLock) {
644 // only really in foreground when screen is also on
645 return mUidForeground.get(uid, false) && mScreenOn;
646 }
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -0700647 }
648
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700649 /**
650 * Foreground for PID changed; recompute foreground at UID level. If
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700651 * changed, will trigger {@link #updateRulesForUidLocked(int)}.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700652 */
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700653 private void computeUidForegroundLocked(int uid) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700654 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
655
656 // current pid is dropping foreground; examine other pids
657 boolean uidForeground = false;
658 final int size = pidForeground.size();
659 for (int i = 0; i < size; i++) {
660 if (pidForeground.valueAt(i)) {
661 uidForeground = true;
662 break;
663 }
664 }
665
666 final boolean oldUidForeground = mUidForeground.get(uid, false);
667 if (oldUidForeground != uidForeground) {
668 // foreground changed, push updated rules
669 mUidForeground.put(uid, uidForeground);
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700670 updateRulesForUidLocked(uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700671 }
672 }
673
Jeff Sharkeya4620792011-05-20 15:29:23 -0700674 private void updateScreenOn() {
675 synchronized (mRulesLock) {
676 try {
677 mScreenOn = mPowerManager.isScreenOn();
678 } catch (RemoteException e) {
679 }
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700680 updateRulesForScreenLocked();
Jeff Sharkeya4620792011-05-20 15:29:23 -0700681 }
682 }
683
684 /**
685 * Update rules that might be changed by {@link #mScreenOn} value.
686 */
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700687 private void updateRulesForScreenLocked() {
Jeff Sharkeya4620792011-05-20 15:29:23 -0700688 // only update rules for anyone with foreground activities
689 final int size = mUidForeground.size();
690 for (int i = 0; i < size; i++) {
691 if (mUidForeground.valueAt(i)) {
692 final int uid = mUidForeground.keyAt(i);
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700693 updateRulesForUidLocked(uid);
Jeff Sharkeya4620792011-05-20 15:29:23 -0700694 }
695 }
696 }
697
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700698 private void updateRulesForUidLocked(int uid) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700699 final int uidPolicy = getUidPolicy(uid);
Jeff Sharkey9599cc52011-05-22 14:59:31 -0700700 final boolean uidForeground = isUidForeground(uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700701
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -0700702 // derive active rules based on policy and active state
703 int uidRules = RULE_ALLOW_ALL;
704 if (!uidForeground && (uidPolicy & POLICY_REJECT_PAID_BACKGROUND) != 0) {
705 // uid in background, and policy says to block paid data
706 uidRules = RULE_REJECT_PAID;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700707 }
708
Jeff Sharkeyc006f1a2011-05-19 17:12:49 -0700709 // TODO: only dispatch when rules actually change
710
711 // record rule locally to dispatch to new listeners
712 mUidRules.put(uid, uidRules);
713
714 // dispatch changed rule to existing listeners
Jeff Sharkeyaf11d482011-06-13 00:14:31 -0700715 final int length = mListeners.beginBroadcast();
716 for (int i = 0; i < length; i++) {
717 final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
718 if (listener != null) {
719 try {
720 listener.onRulesChanged(uid, uidRules);
721 } catch (RemoteException e) {
722 }
723 }
724 }
725 mListeners.finishBroadcast();
Jeff Sharkey22c055e2011-06-12 21:13:51 -0700726 }
727
728 private String getActiveSubscriberId() {
729 final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService(
730 Context.TELEPHONY_SERVICE);
731 return telephony.getSubscriberId();
732 }
733
Jeff Sharkey1b861272011-05-22 00:34:52 -0700734 private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
735 final int size = source.size();
736 for (int i = 0; i < size; i++) {
737 target.put(source.keyAt(i), true);
738 }
739 }
740
741 private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) {
742 final int size = source.size();
743 for (int i = 0; i < size; i++) {
744 target.put(source.keyAt(i), true);
745 }
746 }
747
748 private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) {
749 fout.print("[");
750 final int size = value.size();
751 for (int i = 0; i < size; i++) {
752 fout.print(value.keyAt(i) + "=" + value.valueAt(i));
753 if (i < size - 1) fout.print(",");
754 }
755 fout.print("]");
756 }
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700757
758 private static int readIntAttribute(XmlPullParser in, String name) throws IOException {
759 final String value = in.getAttributeValue(null, name);
760 try {
761 return Integer.parseInt(value);
762 } catch (NumberFormatException e) {
763 throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
764 }
765 }
766
767 private static long readLongAttribute(XmlPullParser in, String name) throws IOException {
768 final String value = in.getAttributeValue(null, name);
769 try {
770 return Long.parseLong(value);
771 } catch (NumberFormatException e) {
772 throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
773 }
774 }
775
776 private static void writeIntAttribute(XmlSerializer out, String name, int value)
777 throws IOException {
778 out.attribute(null, name, Integer.toString(value));
779 }
780
781 private static void writeLongAttribute(XmlSerializer out, String name, long value)
782 throws IOException {
783 out.attribute(null, name, Long.toString(value));
784 }
785
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -0700786}