1/*
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
19import static android.Manifest.permission.ACCESS_NETWORK_STATE;
20import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
21import static android.Manifest.permission.DUMP;
22import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
23import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
24import static android.Manifest.permission.READ_PHONE_STATE;
25import static android.content.Intent.ACTION_PACKAGE_ADDED;
26import static android.content.Intent.ACTION_UID_REMOVED;
27import static android.content.Intent.EXTRA_UID;
28import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
29import static android.net.ConnectivityManager.TYPE_ETHERNET;
30import static android.net.ConnectivityManager.TYPE_MOBILE;
31import static android.net.ConnectivityManager.TYPE_WIFI;
32import static android.net.ConnectivityManager.TYPE_WIMAX;
33import static android.net.ConnectivityManager.isNetworkTypeMobile;
34import static android.net.NetworkPolicy.CYCLE_NONE;
35import static android.net.NetworkPolicy.LIMIT_DISABLED;
36import static android.net.NetworkPolicy.SNOOZE_NEVER;
37import static android.net.NetworkPolicy.WARNING_DISABLED;
38import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
39import static android.net.NetworkPolicyManager.POLICY_NONE;
40import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
41import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
42import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
43import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
44import static android.net.NetworkPolicyManager.dumpPolicy;
45import static android.net.NetworkPolicyManager.dumpRules;
46import static android.net.NetworkTemplate.MATCH_ETHERNET;
47import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
48import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
49import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
50import static android.net.NetworkTemplate.MATCH_WIFI;
51import static android.net.NetworkTemplate.buildTemplateMobileAll;
52import static android.net.TrafficStats.MB_IN_BYTES;
53import static android.net.wifi.WifiInfo.removeDoubleQuotes;
54import static android.net.wifi.WifiManager.CHANGE_REASON_ADDED;
55import static android.net.wifi.WifiManager.CHANGE_REASON_REMOVED;
56import static android.net.wifi.WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION;
57import static android.net.wifi.WifiManager.EXTRA_CHANGE_REASON;
58import static android.net.wifi.WifiManager.EXTRA_NETWORK_INFO;
59import static android.net.wifi.WifiManager.EXTRA_WIFI_CONFIGURATION;
60import static android.net.wifi.WifiManager.EXTRA_WIFI_INFO;
61import static android.telephony.TelephonyManager.SIM_STATE_READY;
62import static android.text.format.DateUtils.DAY_IN_MILLIS;
63import static com.android.internal.util.ArrayUtils.appendInt;
64import static com.android.internal.util.Preconditions.checkNotNull;
65import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
66import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readBooleanAttribute;
67import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readIntAttribute;
68import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readLongAttribute;
69import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeBooleanAttribute;
70import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeIntAttribute;
71import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeLongAttribute;
72import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
73import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
74import static org.xmlpull.v1.XmlPullParser.START_TAG;
75
76import android.app.IActivityManager;
77import android.app.INotificationManager;
78import android.app.IProcessObserver;
79import android.app.Notification;
80import android.app.PendingIntent;
81import android.content.BroadcastReceiver;
82import android.content.ComponentName;
83import android.content.Context;
84import android.content.Intent;
85import android.content.IntentFilter;
86import android.content.pm.ApplicationInfo;
87import android.content.pm.PackageManager;
88import android.content.pm.UserInfo;
89import android.content.res.Resources;
90import android.net.ConnectivityManager;
91import android.net.IConnectivityManager;
92import android.net.INetworkManagementEventObserver;
93import android.net.INetworkPolicyListener;
94import android.net.INetworkPolicyManager;
95import android.net.INetworkStatsService;
96import android.net.NetworkIdentity;
97import android.net.NetworkInfo;
98import android.net.NetworkPolicy;
99import android.net.NetworkQuotaInfo;
100import android.net.NetworkState;
101import android.net.NetworkTemplate;
102import android.net.wifi.WifiConfiguration;
103import android.net.wifi.WifiInfo;
104import android.net.wifi.WifiManager;
105import android.os.Binder;
106import android.os.Environment;
107import android.os.Handler;
108import android.os.HandlerThread;
109import android.os.INetworkManagementService;
110import android.os.IPowerManager;
111import android.os.Message;
112import android.os.MessageQueue.IdleHandler;
113import android.os.RemoteCallbackList;
114import android.os.RemoteException;
115import android.os.UserId;
116import android.provider.Settings;
117import android.telephony.TelephonyManager;
118import android.text.format.Formatter;
119import android.text.format.Time;
120import android.util.Log;
121import android.util.NtpTrustedTime;
122import android.util.Slog;
123import android.util.SparseArray;
124import android.util.SparseBooleanArray;
125import android.util.SparseIntArray;
126import android.util.TrustedTime;
127import android.util.Xml;
128
129import com.android.internal.R;
130import com.android.internal.os.AtomicFile;
131import com.android.internal.util.FastXmlSerializer;
132import com.android.internal.util.IndentingPrintWriter;
133import com.android.internal.util.Objects;
134import com.google.android.collect.Lists;
135import com.google.android.collect.Maps;
136import com.google.android.collect.Sets;
137
138import org.xmlpull.v1.XmlPullParser;
139import org.xmlpull.v1.XmlPullParserException;
140import org.xmlpull.v1.XmlSerializer;
141
142import java.io.File;
143import java.io.FileDescriptor;
144import java.io.FileInputStream;
145import java.io.FileNotFoundException;
146import java.io.FileOutputStream;
147import java.io.IOException;
148import java.io.PrintWriter;
149import java.net.ProtocolException;
150import java.util.ArrayList;
151import java.util.Arrays;
152import java.util.HashMap;
153import java.util.HashSet;
154import java.util.List;
155import java.util.Map;
156
157import libcore.io.IoUtils;
158
159/**
160 * Service that maintains low-level network policy rules, using
161 * {@link NetworkStatsService} statistics to drive those rules.
162 * <p>
163 * Derives active rules by combining a given policy with other system status,
164 * and delivers to listeners, such as {@link ConnectivityManager}, for
165 * enforcement.
166 */
167public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
168    private static final String TAG = "NetworkPolicy";
169    private static final boolean LOGD = false;
170    private static final boolean LOGV = false;
171
172    private static final int VERSION_INIT = 1;
173    private static final int VERSION_ADDED_SNOOZE = 2;
174    private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3;
175    private static final int VERSION_ADDED_METERED = 4;
176    private static final int VERSION_SPLIT_SNOOZE = 5;
177    private static final int VERSION_ADDED_TIMEZONE = 6;
178    private static final int VERSION_ADDED_INFERRED = 7;
179    private static final int VERSION_SWITCH_APP_ID = 8;
180    private static final int VERSION_ADDED_NETWORK_ID = 9;
181    private static final int VERSION_LATEST = VERSION_ADDED_NETWORK_ID;
182
183    // @VisibleForTesting
184    public static final int TYPE_WARNING = 0x1;
185    public static final int TYPE_LIMIT = 0x2;
186    public static final int TYPE_LIMIT_SNOOZED = 0x3;
187
188    private static final String TAG_POLICY_LIST = "policy-list";
189    private static final String TAG_NETWORK_POLICY = "network-policy";
190    private static final String TAG_UID_POLICY = "uid-policy";
191    private static final String TAG_APP_POLICY = "app-policy";
192
193    private static final String ATTR_VERSION = "version";
194    private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
195    private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
196    private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
197    private static final String ATTR_NETWORK_ID = "networkId";
198    private static final String ATTR_CYCLE_DAY = "cycleDay";
199    private static final String ATTR_CYCLE_TIMEZONE = "cycleTimezone";
200    private static final String ATTR_WARNING_BYTES = "warningBytes";
201    private static final String ATTR_LIMIT_BYTES = "limitBytes";
202    private static final String ATTR_LAST_SNOOZE = "lastSnooze";
203    private static final String ATTR_LAST_WARNING_SNOOZE = "lastWarningSnooze";
204    private static final String ATTR_LAST_LIMIT_SNOOZE = "lastLimitSnooze";
205    private static final String ATTR_METERED = "metered";
206    private static final String ATTR_INFERRED = "inferred";
207    private static final String ATTR_UID = "uid";
208    private static final String ATTR_APP_ID = "appId";
209    private static final String ATTR_POLICY = "policy";
210
211    private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground";
212
213    // @VisibleForTesting
214    public static final String ACTION_ALLOW_BACKGROUND =
215            "com.android.server.net.action.ALLOW_BACKGROUND";
216    public static final String ACTION_SNOOZE_WARNING =
217            "com.android.server.net.action.SNOOZE_WARNING";
218
219    private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
220
221    private static final int MSG_RULES_CHANGED = 1;
222    private static final int MSG_METERED_IFACES_CHANGED = 2;
223    private static final int MSG_FOREGROUND_ACTIVITIES_CHANGED = 3;
224    private static final int MSG_PROCESS_DIED = 4;
225    private static final int MSG_LIMIT_REACHED = 5;
226    private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6;
227    private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7;
228    private static final int MSG_SCREEN_ON_CHANGED = 8;
229
230    private final Context mContext;
231    private final IActivityManager mActivityManager;
232    private final IPowerManager mPowerManager;
233    private final INetworkStatsService mNetworkStats;
234    private final INetworkManagementService mNetworkManager;
235    private final TrustedTime mTime;
236
237    private IConnectivityManager mConnManager;
238    private INotificationManager mNotifManager;
239
240    private final Object mRulesLock = new Object();
241
242    private volatile boolean mScreenOn;
243    private volatile boolean mRestrictBackground;
244
245    private final boolean mSuppressDefaultPolicy;
246
247    /** Defined network policies. */
248    private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap();
249    /** Currently active network rules for ifaces. */
250    private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap();
251
252    /** Defined app policies. */
253    private SparseIntArray mAppPolicy = new SparseIntArray();
254    /** Currently derived rules for each UID. */
255    private SparseIntArray mUidRules = new SparseIntArray();
256
257    /** Set of ifaces that are metered. */
258    private HashSet<String> mMeteredIfaces = Sets.newHashSet();
259    /** Set of over-limit templates that have been notified. */
260    private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet();
261
262    /** Set of currently active {@link Notification} tags. */
263    private HashSet<String> mActiveNotifs = Sets.newHashSet();
264
265    /** Foreground at both UID and PID granularity. */
266    private SparseBooleanArray mUidForeground = new SparseBooleanArray();
267    private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
268            SparseBooleanArray>();
269
270    private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
271            INetworkPolicyListener>();
272
273    private final HandlerThread mHandlerThread;
274    private final Handler mHandler;
275
276    private final AtomicFile mPolicyFile;
277
278    // TODO: keep whitelist of system-critical services that should never have
279    // rules enforced, such as system, phone, and radio UIDs.
280
281    // TODO: migrate notifications to SystemUI
282
283    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
284            IPowerManager powerManager, INetworkStatsService networkStats,
285            INetworkManagementService networkManagement) {
286        this(context, activityManager, powerManager, networkStats, networkManagement,
287                NtpTrustedTime.getInstance(context), getSystemDir(), false);
288    }
289
290    private static File getSystemDir() {
291        return new File(Environment.getDataDirectory(), "system");
292    }
293
294    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
295            IPowerManager powerManager, INetworkStatsService networkStats,
296            INetworkManagementService networkManagement, TrustedTime time, File systemDir,
297            boolean suppressDefaultPolicy) {
298        mContext = checkNotNull(context, "missing context");
299        mActivityManager = checkNotNull(activityManager, "missing activityManager");
300        mPowerManager = checkNotNull(powerManager, "missing powerManager");
301        mNetworkStats = checkNotNull(networkStats, "missing networkStats");
302        mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
303        mTime = checkNotNull(time, "missing TrustedTime");
304
305        mHandlerThread = new HandlerThread(TAG);
306        mHandlerThread.start();
307        mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
308
309        mSuppressDefaultPolicy = suppressDefaultPolicy;
310
311        mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
312    }
313
314    public void bindConnectivityManager(IConnectivityManager connManager) {
315        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
316    }
317
318    public void bindNotificationManager(INotificationManager notifManager) {
319        mNotifManager = checkNotNull(notifManager, "missing INotificationManager");
320    }
321
322    public void systemReady() {
323        if (!isBandwidthControlEnabled()) {
324            Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy");
325            return;
326        }
327
328        synchronized (mRulesLock) {
329            // read policy from disk
330            readPolicyLocked();
331
332            if (mRestrictBackground) {
333                updateRulesForRestrictBackgroundLocked();
334                updateNotificationsLocked();
335            }
336        }
337
338        updateScreenOn();
339
340        try {
341            mActivityManager.registerProcessObserver(mProcessObserver);
342            mNetworkManager.registerObserver(mAlertObserver);
343        } catch (RemoteException e) {
344            // ignored; both services live in system_server
345        }
346
347        // TODO: traverse existing processes to know foreground state, or have
348        // activitymanager dispatch current state when new observer attached.
349
350        final IntentFilter screenFilter = new IntentFilter();
351        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
352        screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
353        mContext.registerReceiver(mScreenReceiver, screenFilter);
354
355        // watch for network interfaces to be claimed
356        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
357        mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
358
359        // listen for package/uid changes to update policy
360        final IntentFilter packageFilter = new IntentFilter();
361        packageFilter.addAction(ACTION_PACKAGE_ADDED);
362        packageFilter.addAction(ACTION_UID_REMOVED);
363        mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
364
365        // listen for stats update events
366        final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
367        mContext.registerReceiver(
368                mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
369
370        // listen for restrict background changes from notifications
371        final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
372        mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler);
373
374        // listen for snooze warning from notifications
375        final IntentFilter snoozeWarningFilter = new IntentFilter(ACTION_SNOOZE_WARNING);
376        mContext.registerReceiver(mSnoozeWarningReceiver, snoozeWarningFilter,
377                MANAGE_NETWORK_POLICY, mHandler);
378
379        // listen for configured wifi networks to be removed
380        final IntentFilter wifiConfigFilter = new IntentFilter(CONFIGURED_NETWORKS_CHANGED_ACTION);
381        mContext.registerReceiver(
382                mWifiConfigReceiver, wifiConfigFilter, CONNECTIVITY_INTERNAL, mHandler);
383
384        // listen for wifi state changes to catch metered hint
385        final IntentFilter wifiStateFilter = new IntentFilter(
386                WifiManager.NETWORK_STATE_CHANGED_ACTION);
387        mContext.registerReceiver(
388                mWifiStateReceiver, wifiStateFilter, CONNECTIVITY_INTERNAL, mHandler);
389
390    }
391
392    private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
393        @Override
394        public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
395            mHandler.obtainMessage(MSG_FOREGROUND_ACTIVITIES_CHANGED,
396                    pid, uid, foregroundActivities).sendToTarget();
397        }
398
399        @Override
400        public void onImportanceChanged(int pid, int uid, int importance) {
401        }
402
403        @Override
404        public void onProcessDied(int pid, int uid) {
405            mHandler.obtainMessage(MSG_PROCESS_DIED, pid, uid).sendToTarget();
406        }
407    };
408
409    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
410        @Override
411        public void onReceive(Context context, Intent intent) {
412            synchronized (mRulesLock) {
413                // screen-related broadcasts are protected by system, no need
414                // for permissions check.
415                mHandler.obtainMessage(MSG_SCREEN_ON_CHANGED).sendToTarget();
416            }
417        }
418    };
419
420    private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
421        @Override
422        public void onReceive(Context context, Intent intent) {
423            // on background handler thread, and PACKAGE_ADDED and UID_REMOVED
424            // are protected broadcasts.
425
426            final String action = intent.getAction();
427            final int uid = intent.getIntExtra(EXTRA_UID, 0);
428            final int appId = UserId.getAppId(uid);
429            synchronized (mRulesLock) {
430                if (ACTION_PACKAGE_ADDED.equals(action)) {
431                    // NOTE: PACKAGE_ADDED is currently only sent once, and is
432                    // not broadcast when users are added.
433
434                    // update rules for UID, since it might be subject to
435                    // global background data policy.
436                    if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
437                    updateRulesForAppLocked(appId);
438
439                } else if (ACTION_UID_REMOVED.equals(action)) {
440                    // NOTE: UID_REMOVED is currently only sent once, and is not
441                    // broadcast when users are removed.
442
443                    // remove any policy and update rules to clean up.
444                    if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
445
446                    mAppPolicy.delete(appId);
447                    updateRulesForAppLocked(appId);
448                    writePolicyLocked();
449                }
450            }
451        }
452    };
453
454    /**
455     * Receiver that watches for {@link INetworkStatsService} updates, which we
456     * use to check against {@link NetworkPolicy#warningBytes}.
457     */
458    private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() {
459        @Override
460        public void onReceive(Context context, Intent intent) {
461            // on background handler thread, and verified
462            // READ_NETWORK_USAGE_HISTORY permission above.
463
464            maybeRefreshTrustedTime();
465            synchronized (mRulesLock) {
466                updateNetworkEnabledLocked();
467                updateNotificationsLocked();
468            }
469        }
470    };
471
472    /**
473     * Receiver that watches for {@link Notification} control of
474     * {@link #mRestrictBackground}.
475     */
476    private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() {
477        @Override
478        public void onReceive(Context context, Intent intent) {
479            // on background handler thread, and verified MANAGE_NETWORK_POLICY
480            // permission above.
481
482            setRestrictBackground(false);
483        }
484    };
485
486    /**
487     * Receiver that watches for {@link Notification} control of
488     * {@link NetworkPolicy#lastWarningSnooze}.
489     */
490    private BroadcastReceiver mSnoozeWarningReceiver = new BroadcastReceiver() {
491        @Override
492        public void onReceive(Context context, Intent intent) {
493            // on background handler thread, and verified MANAGE_NETWORK_POLICY
494            // permission above.
495
496            final NetworkTemplate template = intent.getParcelableExtra(EXTRA_NETWORK_TEMPLATE);
497            performSnooze(template, TYPE_WARNING);
498        }
499    };
500
501    /**
502     * Receiver that watches for {@link WifiConfiguration} to be changed.
503     */
504    private BroadcastReceiver mWifiConfigReceiver = new BroadcastReceiver() {
505        @Override
506        public void onReceive(Context context, Intent intent) {
507            // on background handler thread, and verified CONNECTIVITY_INTERNAL
508            // permission above.
509
510            final int reason = intent.getIntExtra(EXTRA_CHANGE_REASON, CHANGE_REASON_ADDED);
511            if (reason == CHANGE_REASON_REMOVED) {
512                final WifiConfiguration config = intent.getParcelableExtra(
513                        EXTRA_WIFI_CONFIGURATION);
514                if (config.SSID != null) {
515                    final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(
516                            removeDoubleQuotes(config.SSID));
517                    synchronized (mRulesLock) {
518                        if (mNetworkPolicy.containsKey(template)) {
519                            mNetworkPolicy.remove(template);
520                            writePolicyLocked();
521                        }
522                    }
523                }
524            }
525        }
526    };
527
528    /**
529     * Receiver that watches {@link WifiInfo} state changes to infer metered
530     * state. Ignores hints when policy is user-defined.
531     */
532    private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
533        @Override
534        public void onReceive(Context context, Intent intent) {
535            // on background handler thread, and verified CONNECTIVITY_INTERNAL
536            // permission above.
537
538            // ignore when not connected
539            final NetworkInfo netInfo = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
540            if (!netInfo.isConnected()) return;
541
542            final WifiInfo info = intent.getParcelableExtra(EXTRA_WIFI_INFO);
543            final boolean meteredHint = info.getMeteredHint();
544
545            final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(
546                    removeDoubleQuotes(info.getSSID()));
547            synchronized (mRulesLock) {
548                NetworkPolicy policy = mNetworkPolicy.get(template);
549                if (policy == null && meteredHint) {
550                    // policy doesn't exist, and AP is hinting that it's
551                    // metered: create an inferred policy.
552                    policy = new NetworkPolicy(template, CYCLE_NONE, Time.TIMEZONE_UTC,
553                            WARNING_DISABLED, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER,
554                            meteredHint, true);
555                    addNetworkPolicyLocked(policy);
556
557                } else if (policy != null && policy.inferred) {
558                    // policy exists, and was inferred: update its current
559                    // metered state.
560                    policy.metered = meteredHint;
561
562                    // since this is inferred for each wifi session, just update
563                    // rules without persisting.
564                    updateNetworkRulesLocked();
565                }
566            }
567        }
568    };
569
570    /**
571     * Observer that watches for {@link INetworkManagementService} alerts.
572     */
573    private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
574        @Override
575        public void limitReached(String limitName, String iface) {
576            // only someone like NMS should be calling us
577            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
578
579            if (!LIMIT_GLOBAL_ALERT.equals(limitName)) {
580                mHandler.obtainMessage(MSG_LIMIT_REACHED, iface).sendToTarget();
581            }
582        }
583    };
584
585    /**
586     * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
587     * to show visible notifications as needed.
588     */
589    private void updateNotificationsLocked() {
590        if (LOGV) Slog.v(TAG, "updateNotificationsLocked()");
591
592        // keep track of previously active notifications
593        final HashSet<String> beforeNotifs = Sets.newHashSet();
594        beforeNotifs.addAll(mActiveNotifs);
595        mActiveNotifs.clear();
596
597        // TODO: when switching to kernel notifications, compute next future
598        // cycle boundary to recompute notifications.
599
600        // examine stats for each active policy
601        final long currentTime = currentTimeMillis();
602        for (NetworkPolicy policy : mNetworkPolicy.values()) {
603            // ignore policies that aren't relevant to user
604            if (!isTemplateRelevant(policy.template)) continue;
605            if (!policy.hasCycle()) continue;
606
607            final long start = computeLastCycleBoundary(currentTime, policy);
608            final long end = currentTime;
609            final long totalBytes = getTotalBytes(policy.template, start, end);
610
611            if (policy.isOverLimit(totalBytes)) {
612                if (policy.lastLimitSnooze >= start) {
613                    enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
614                } else {
615                    enqueueNotification(policy, TYPE_LIMIT, totalBytes);
616                    notifyOverLimitLocked(policy.template);
617                }
618
619            } else {
620                notifyUnderLimitLocked(policy.template);
621
622                if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start) {
623                    enqueueNotification(policy, TYPE_WARNING, totalBytes);
624                }
625            }
626        }
627
628        // ongoing notification when restricting background data
629        if (mRestrictBackground) {
630            enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND);
631        }
632
633        // cancel stale notifications that we didn't renew above
634        for (String tag : beforeNotifs) {
635            if (!mActiveNotifs.contains(tag)) {
636                cancelNotification(tag);
637            }
638        }
639    }
640
641    /**
642     * Test if given {@link NetworkTemplate} is relevant to user based on
643     * current device state, such as when
644     * {@link TelephonyManager#getSubscriberId()} matches. This is regardless of
645     * data connection status.
646     */
647    private boolean isTemplateRelevant(NetworkTemplate template) {
648        final TelephonyManager tele = TelephonyManager.from(mContext);
649
650        switch (template.getMatchRule()) {
651            case MATCH_MOBILE_3G_LOWER:
652            case MATCH_MOBILE_4G:
653            case MATCH_MOBILE_ALL:
654                // mobile templates are relevant when SIM is ready and
655                // subscriberId matches.
656                if (tele.getSimState() == SIM_STATE_READY) {
657                    return Objects.equal(tele.getSubscriberId(), template.getSubscriberId());
658                } else {
659                    return false;
660                }
661        }
662        return true;
663    }
664
665    /**
666     * Notify that given {@link NetworkTemplate} is over
667     * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
668     */
669    private void notifyOverLimitLocked(NetworkTemplate template) {
670        if (!mOverLimitNotified.contains(template)) {
671            mContext.startActivity(buildNetworkOverLimitIntent(template));
672            mOverLimitNotified.add(template);
673        }
674    }
675
676    private void notifyUnderLimitLocked(NetworkTemplate template) {
677        mOverLimitNotified.remove(template);
678    }
679
680    /**
681     * Build unique tag that identifies an active {@link NetworkPolicy}
682     * notification of a specific type, like {@link #TYPE_LIMIT}.
683     */
684    private String buildNotificationTag(NetworkPolicy policy, int type) {
685        return TAG + ":" + policy.template.hashCode() + ":" + type;
686    }
687
688    /**
689     * Show notification for combined {@link NetworkPolicy} and specific type,
690     * like {@link #TYPE_LIMIT}. Okay to call multiple times.
691     */
692    private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
693        final String tag = buildNotificationTag(policy, type);
694        final Notification.Builder builder = new Notification.Builder(mContext);
695        builder.setOnlyAlertOnce(true);
696        builder.setWhen(0L);
697
698        final Resources res = mContext.getResources();
699        switch (type) {
700            case TYPE_WARNING: {
701                final CharSequence title = res.getText(R.string.data_usage_warning_title);
702                final CharSequence body = res.getString(R.string.data_usage_warning_body);
703
704                builder.setSmallIcon(R.drawable.stat_notify_error);
705                builder.setTicker(title);
706                builder.setContentTitle(title);
707                builder.setContentText(body);
708
709                final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template);
710                builder.setDeleteIntent(PendingIntent.getBroadcast(
711                        mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
712
713                final Intent viewIntent = buildViewDataUsageIntent(policy.template);
714                builder.setContentIntent(PendingIntent.getActivity(
715                        mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT));
716
717                break;
718            }
719            case TYPE_LIMIT: {
720                final CharSequence body = res.getText(R.string.data_usage_limit_body);
721
722                final CharSequence title;
723                switch (policy.template.getMatchRule()) {
724                    case MATCH_MOBILE_3G_LOWER:
725                        title = res.getText(R.string.data_usage_3g_limit_title);
726                        break;
727                    case MATCH_MOBILE_4G:
728                        title = res.getText(R.string.data_usage_4g_limit_title);
729                        break;
730                    case MATCH_MOBILE_ALL:
731                        title = res.getText(R.string.data_usage_mobile_limit_title);
732                        break;
733                    case MATCH_WIFI:
734                        title = res.getText(R.string.data_usage_wifi_limit_title);
735                        break;
736                    default:
737                        title = null;
738                        break;
739                }
740
741                builder.setOngoing(true);
742                builder.setSmallIcon(R.drawable.stat_notify_disabled);
743                builder.setTicker(title);
744                builder.setContentTitle(title);
745                builder.setContentText(body);
746
747                final Intent intent = buildNetworkOverLimitIntent(policy.template);
748                builder.setContentIntent(PendingIntent.getActivity(
749                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
750                break;
751            }
752            case TYPE_LIMIT_SNOOZED: {
753                final long overBytes = totalBytes - policy.limitBytes;
754                final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body,
755                        Formatter.formatFileSize(mContext, overBytes));
756
757                final CharSequence title;
758                switch (policy.template.getMatchRule()) {
759                    case MATCH_MOBILE_3G_LOWER:
760                        title = res.getText(R.string.data_usage_3g_limit_snoozed_title);
761                        break;
762                    case MATCH_MOBILE_4G:
763                        title = res.getText(R.string.data_usage_4g_limit_snoozed_title);
764                        break;
765                    case MATCH_MOBILE_ALL:
766                        title = res.getText(R.string.data_usage_mobile_limit_snoozed_title);
767                        break;
768                    case MATCH_WIFI:
769                        title = res.getText(R.string.data_usage_wifi_limit_snoozed_title);
770                        break;
771                    default:
772                        title = null;
773                        break;
774                }
775
776                builder.setOngoing(true);
777                builder.setSmallIcon(R.drawable.stat_notify_error);
778                builder.setTicker(title);
779                builder.setContentTitle(title);
780                builder.setContentText(body);
781
782                final Intent intent = buildViewDataUsageIntent(policy.template);
783                builder.setContentIntent(PendingIntent.getActivity(
784                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
785                break;
786            }
787        }
788
789        // TODO: move to NotificationManager once we can mock it
790        try {
791            final String packageName = mContext.getPackageName();
792            final int[] idReceived = new int[1];
793            mNotifManager.enqueueNotificationWithTag(
794                    packageName, tag, 0x0, builder.getNotification(), idReceived);
795            mActiveNotifs.add(tag);
796        } catch (RemoteException e) {
797            // ignored; service lives in system_server
798        }
799    }
800
801    /**
802     * Show ongoing notification to reflect that {@link #mRestrictBackground}
803     * has been enabled.
804     */
805    private void enqueueRestrictedNotification(String tag) {
806        final Resources res = mContext.getResources();
807        final Notification.Builder builder = new Notification.Builder(mContext);
808
809        final CharSequence title = res.getText(R.string.data_usage_restricted_title);
810        final CharSequence body = res.getString(R.string.data_usage_restricted_body);
811
812        builder.setOnlyAlertOnce(true);
813        builder.setOngoing(true);
814        builder.setSmallIcon(R.drawable.stat_notify_error);
815        builder.setTicker(title);
816        builder.setContentTitle(title);
817        builder.setContentText(body);
818
819        final Intent intent = buildAllowBackgroundDataIntent();
820        builder.setContentIntent(
821                PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
822
823        // TODO: move to NotificationManager once we can mock it
824        try {
825            final String packageName = mContext.getPackageName();
826            final int[] idReceived = new int[1];
827            mNotifManager.enqueueNotificationWithTag(packageName, tag,
828                    0x0, builder.getNotification(), idReceived);
829            mActiveNotifs.add(tag);
830        } catch (RemoteException e) {
831            // ignored; service lives in system_server
832        }
833    }
834
835    private void cancelNotification(String tag) {
836        // TODO: move to NotificationManager once we can mock it
837        try {
838            final String packageName = mContext.getPackageName();
839            mNotifManager.cancelNotificationWithTag(
840                    packageName, tag, 0x0);
841        } catch (RemoteException e) {
842            // ignored; service lives in system_server
843        }
844    }
845
846    /**
847     * Receiver that watches for {@link IConnectivityManager} to claim network
848     * interfaces. Used to apply {@link NetworkPolicy} to matching networks.
849     */
850    private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
851        @Override
852        public void onReceive(Context context, Intent intent) {
853            // on background handler thread, and verified CONNECTIVITY_INTERNAL
854            // permission above.
855
856            maybeRefreshTrustedTime();
857            synchronized (mRulesLock) {
858                ensureActiveMobilePolicyLocked();
859                updateNetworkEnabledLocked();
860                updateNetworkRulesLocked();
861                updateNotificationsLocked();
862            }
863        }
864    };
865
866    /**
867     * Proactively control network data connections when they exceed
868     * {@link NetworkPolicy#limitBytes}.
869     */
870    private void updateNetworkEnabledLocked() {
871        if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()");
872
873        // TODO: reset any policy-disabled networks when any policy is removed
874        // completely, which is currently rare case.
875
876        final long currentTime = currentTimeMillis();
877        for (NetworkPolicy policy : mNetworkPolicy.values()) {
878            // shortcut when policy has no limit
879            if (policy.limitBytes == LIMIT_DISABLED || !policy.hasCycle()) {
880                setNetworkTemplateEnabled(policy.template, true);
881                continue;
882            }
883
884            final long start = computeLastCycleBoundary(currentTime, policy);
885            final long end = currentTime;
886            final long totalBytes = getTotalBytes(policy.template, start, end);
887
888            // disable data connection when over limit and not snoozed
889            final boolean overLimitWithoutSnooze = policy.isOverLimit(totalBytes)
890                    && policy.lastLimitSnooze < start;
891            final boolean networkEnabled = !overLimitWithoutSnooze;
892
893            setNetworkTemplateEnabled(policy.template, networkEnabled);
894        }
895    }
896
897    /**
898     * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}
899     * for the given {@link NetworkTemplate}.
900     */
901    private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
902        final TelephonyManager tele = TelephonyManager.from(mContext);
903
904        switch (template.getMatchRule()) {
905            case MATCH_MOBILE_3G_LOWER:
906            case MATCH_MOBILE_4G:
907            case MATCH_MOBILE_ALL:
908                // TODO: offer more granular control over radio states once
909                // 4965893 is available.
910                if (tele.getSimState() == SIM_STATE_READY
911                        && Objects.equal(tele.getSubscriberId(), template.getSubscriberId())) {
912                    setPolicyDataEnable(TYPE_MOBILE, enabled);
913                    setPolicyDataEnable(TYPE_WIMAX, enabled);
914                }
915                break;
916            case MATCH_WIFI:
917                setPolicyDataEnable(TYPE_WIFI, enabled);
918                break;
919            case MATCH_ETHERNET:
920                setPolicyDataEnable(TYPE_ETHERNET, enabled);
921                break;
922            default:
923                throw new IllegalArgumentException("unexpected template");
924        }
925    }
926
927    /**
928     * Examine all connected {@link NetworkState}, looking for
929     * {@link NetworkPolicy} that need to be enforced. When matches found, set
930     * remaining quota based on usage cycle and historical stats.
931     */
932    private void updateNetworkRulesLocked() {
933        if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
934
935        final NetworkState[] states;
936        try {
937            states = mConnManager.getAllNetworkState();
938        } catch (RemoteException e) {
939            // ignored; service lives in system_server
940            return;
941        }
942
943        // first, derive identity for all connected networks, which can be used
944        // to match against templates.
945        final HashMap<NetworkIdentity, String> networks = Maps.newHashMap();
946        for (NetworkState state : states) {
947            // stash identity and iface away for later use
948            if (state.networkInfo.isConnected()) {
949                final String iface = state.linkProperties.getInterfaceName();
950                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
951                networks.put(ident, iface);
952            }
953        }
954
955        // build list of rules and ifaces to enforce them against
956        mNetworkRules.clear();
957        final ArrayList<String> ifaceList = Lists.newArrayList();
958        for (NetworkPolicy policy : mNetworkPolicy.values()) {
959
960            // collect all active ifaces that match this template
961            ifaceList.clear();
962            for (Map.Entry<NetworkIdentity, String> entry : networks.entrySet()) {
963                final NetworkIdentity ident = entry.getKey();
964                if (policy.template.matches(ident)) {
965                    final String iface = entry.getValue();
966                    ifaceList.add(iface);
967                }
968            }
969
970            if (ifaceList.size() > 0) {
971                final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]);
972                mNetworkRules.put(policy, ifaces);
973            }
974        }
975
976        long lowestRule = Long.MAX_VALUE;
977        final HashSet<String> newMeteredIfaces = Sets.newHashSet();
978
979        // apply each policy that we found ifaces for; compute remaining data
980        // based on current cycle and historical stats, and push to kernel.
981        final long currentTime = currentTimeMillis();
982        for (NetworkPolicy policy : mNetworkRules.keySet()) {
983            final String[] ifaces = mNetworkRules.get(policy);
984
985            final long start;
986            final long totalBytes;
987            if (policy.hasCycle()) {
988                start = computeLastCycleBoundary(currentTime, policy);
989                totalBytes = getTotalBytes(policy.template, start, currentTime);
990            } else {
991                start = Long.MAX_VALUE;
992                totalBytes = 0;
993            }
994
995            if (LOGD) {
996                Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
997                        + Arrays.toString(ifaces));
998            }
999
1000            final boolean hasWarning = policy.warningBytes != LIMIT_DISABLED;
1001            final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
1002            if (hasLimit || policy.metered) {
1003                final long quotaBytes;
1004                if (!hasLimit) {
1005                    // metered network, but no policy limit; we still need to
1006                    // restrict apps, so push really high quota.
1007                    quotaBytes = Long.MAX_VALUE;
1008                } else if (policy.lastLimitSnooze >= start) {
1009                    // snoozing past quota, but we still need to restrict apps,
1010                    // so push really high quota.
1011                    quotaBytes = Long.MAX_VALUE;
1012                } else {
1013                    // remaining "quota" bytes are based on total usage in
1014                    // current cycle. kernel doesn't like 0-byte rules, so we
1015                    // set 1-byte quota and disable the radio later.
1016                    quotaBytes = Math.max(1, policy.limitBytes - totalBytes);
1017                }
1018
1019                if (ifaces.length > 1) {
1020                    // TODO: switch to shared quota once NMS supports
1021                    Slog.w(TAG, "shared quota unsupported; generating rule for each iface");
1022                }
1023
1024                for (String iface : ifaces) {
1025                    removeInterfaceQuota(iface);
1026                    setInterfaceQuota(iface, quotaBytes);
1027                    newMeteredIfaces.add(iface);
1028                }
1029            }
1030
1031            // keep track of lowest warning or limit of active policies
1032            if (hasWarning && policy.warningBytes < lowestRule) {
1033                lowestRule = policy.warningBytes;
1034            }
1035            if (hasLimit && policy.limitBytes < lowestRule) {
1036                lowestRule = policy.limitBytes;
1037            }
1038        }
1039
1040        mHandler.obtainMessage(MSG_ADVISE_PERSIST_THRESHOLD, lowestRule).sendToTarget();
1041
1042        // remove quota on any trailing interfaces
1043        for (String iface : mMeteredIfaces) {
1044            if (!newMeteredIfaces.contains(iface)) {
1045                removeInterfaceQuota(iface);
1046            }
1047        }
1048        mMeteredIfaces = newMeteredIfaces;
1049
1050        final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
1051        mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
1052    }
1053
1054    /**
1055     * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
1056     * have at least a default mobile policy defined.
1057     */
1058    private void ensureActiveMobilePolicyLocked() {
1059        if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
1060        if (mSuppressDefaultPolicy) return;
1061
1062        final TelephonyManager tele = TelephonyManager.from(mContext);
1063
1064        // avoid creating policy when SIM isn't ready
1065        if (tele.getSimState() != SIM_STATE_READY) return;
1066
1067        final String subscriberId = tele.getSubscriberId();
1068        final NetworkIdentity probeIdent = new NetworkIdentity(
1069                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
1070
1071        // examine to see if any policy is defined for active mobile
1072        boolean mobileDefined = false;
1073        for (NetworkPolicy policy : mNetworkPolicy.values()) {
1074            if (policy.template.matches(probeIdent)) {
1075                mobileDefined = true;
1076            }
1077        }
1078
1079        if (!mobileDefined) {
1080            Slog.i(TAG, "no policy for active mobile network; generating default policy");
1081
1082            // build default mobile policy, and assume usage cycle starts today
1083            final long warningBytes = mContext.getResources().getInteger(
1084                    com.android.internal.R.integer.config_networkPolicyDefaultWarning)
1085                    * MB_IN_BYTES;
1086
1087            final Time time = new Time();
1088            time.setToNow();
1089
1090            final int cycleDay = time.monthDay;
1091            final String cycleTimezone = time.timezone;
1092
1093            final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
1094            final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone,
1095                    warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true);
1096            addNetworkPolicyLocked(policy);
1097        }
1098    }
1099
1100    private void readPolicyLocked() {
1101        if (LOGV) Slog.v(TAG, "readPolicyLocked()");
1102
1103        // clear any existing policy and read from disk
1104        mNetworkPolicy.clear();
1105        mAppPolicy.clear();
1106
1107        FileInputStream fis = null;
1108        try {
1109            fis = mPolicyFile.openRead();
1110            final XmlPullParser in = Xml.newPullParser();
1111            in.setInput(fis, null);
1112
1113            int type;
1114            int version = VERSION_INIT;
1115            while ((type = in.next()) != END_DOCUMENT) {
1116                final String tag = in.getName();
1117                if (type == START_TAG) {
1118                    if (TAG_POLICY_LIST.equals(tag)) {
1119                        version = readIntAttribute(in, ATTR_VERSION);
1120                        if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) {
1121                            mRestrictBackground = readBooleanAttribute(
1122                                    in, ATTR_RESTRICT_BACKGROUND);
1123                        } else {
1124                            mRestrictBackground = false;
1125                        }
1126
1127                    } else if (TAG_NETWORK_POLICY.equals(tag)) {
1128                        final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
1129                        final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
1130                        final String networkId;
1131                        if (version >= VERSION_ADDED_NETWORK_ID) {
1132                            networkId = in.getAttributeValue(null, ATTR_NETWORK_ID);
1133                        } else {
1134                            networkId = null;
1135                        }
1136                        final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
1137                        final String cycleTimezone;
1138                        if (version >= VERSION_ADDED_TIMEZONE) {
1139                            cycleTimezone = in.getAttributeValue(null, ATTR_CYCLE_TIMEZONE);
1140                        } else {
1141                            cycleTimezone = Time.TIMEZONE_UTC;
1142                        }
1143                        final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
1144                        final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
1145                        final long lastLimitSnooze;
1146                        if (version >= VERSION_SPLIT_SNOOZE) {
1147                            lastLimitSnooze = readLongAttribute(in, ATTR_LAST_LIMIT_SNOOZE);
1148                        } else if (version >= VERSION_ADDED_SNOOZE) {
1149                            lastLimitSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
1150                        } else {
1151                            lastLimitSnooze = SNOOZE_NEVER;
1152                        }
1153                        final boolean metered;
1154                        if (version >= VERSION_ADDED_METERED) {
1155                            metered = readBooleanAttribute(in, ATTR_METERED);
1156                        } else {
1157                            switch (networkTemplate) {
1158                                case MATCH_MOBILE_3G_LOWER:
1159                                case MATCH_MOBILE_4G:
1160                                case MATCH_MOBILE_ALL:
1161                                    metered = true;
1162                                    break;
1163                                default:
1164                                    metered = false;
1165                            }
1166                        }
1167                        final long lastWarningSnooze;
1168                        if (version >= VERSION_SPLIT_SNOOZE) {
1169                            lastWarningSnooze = readLongAttribute(in, ATTR_LAST_WARNING_SNOOZE);
1170                        } else {
1171                            lastWarningSnooze = SNOOZE_NEVER;
1172                        }
1173                        final boolean inferred;
1174                        if (version >= VERSION_ADDED_INFERRED) {
1175                            inferred = readBooleanAttribute(in, ATTR_INFERRED);
1176                        } else {
1177                            inferred = false;
1178                        }
1179
1180                        final NetworkTemplate template = new NetworkTemplate(
1181                                networkTemplate, subscriberId, networkId);
1182                        mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay,
1183                                cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
1184                                lastLimitSnooze, metered, inferred));
1185
1186                    } else if (TAG_UID_POLICY.equals(tag) && version < VERSION_SWITCH_APP_ID) {
1187                        final int uid = readIntAttribute(in, ATTR_UID);
1188                        final int policy = readIntAttribute(in, ATTR_POLICY);
1189
1190                        final int appId = UserId.getAppId(uid);
1191                        if (UserId.isApp(appId)) {
1192                            setAppPolicyUnchecked(appId, policy, false);
1193                        } else {
1194                            Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
1195                        }
1196                    } else if (TAG_APP_POLICY.equals(tag) && version >= VERSION_SWITCH_APP_ID) {
1197                        final int appId = readIntAttribute(in, ATTR_APP_ID);
1198                        final int policy = readIntAttribute(in, ATTR_POLICY);
1199
1200                        if (UserId.isApp(appId)) {
1201                            setAppPolicyUnchecked(appId, policy, false);
1202                        } else {
1203                            Slog.w(TAG, "unable to apply policy to appId " + appId + "; ignoring");
1204                        }
1205                    }
1206                }
1207            }
1208
1209        } catch (FileNotFoundException e) {
1210            // missing policy is okay, probably first boot
1211            upgradeLegacyBackgroundData();
1212        } catch (IOException e) {
1213            Log.wtf(TAG, "problem reading network policy", e);
1214        } catch (XmlPullParserException e) {
1215            Log.wtf(TAG, "problem reading network policy", e);
1216        } finally {
1217            IoUtils.closeQuietly(fis);
1218        }
1219    }
1220
1221    /**
1222     * Upgrade legacy background data flags, notifying listeners of one last
1223     * change to always-true.
1224     */
1225    private void upgradeLegacyBackgroundData() {
1226        mRestrictBackground = Settings.Secure.getInt(
1227                mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1;
1228
1229        // kick off one last broadcast if restricted
1230        if (mRestrictBackground) {
1231            final Intent broadcast = new Intent(
1232                    ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
1233            mContext.sendBroadcast(broadcast);
1234        }
1235    }
1236
1237    private void writePolicyLocked() {
1238        if (LOGV) Slog.v(TAG, "writePolicyLocked()");
1239
1240        FileOutputStream fos = null;
1241        try {
1242            fos = mPolicyFile.startWrite();
1243
1244            XmlSerializer out = new FastXmlSerializer();
1245            out.setOutput(fos, "utf-8");
1246            out.startDocument(null, true);
1247
1248            out.startTag(null, TAG_POLICY_LIST);
1249            writeIntAttribute(out, ATTR_VERSION, VERSION_LATEST);
1250            writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
1251
1252            // write all known network policies
1253            for (NetworkPolicy policy : mNetworkPolicy.values()) {
1254                final NetworkTemplate template = policy.template;
1255
1256                out.startTag(null, TAG_NETWORK_POLICY);
1257                writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
1258                final String subscriberId = template.getSubscriberId();
1259                if (subscriberId != null) {
1260                    out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
1261                }
1262                final String networkId = template.getNetworkId();
1263                if (networkId != null) {
1264                    out.attribute(null, ATTR_NETWORK_ID, networkId);
1265                }
1266                writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
1267                out.attribute(null, ATTR_CYCLE_TIMEZONE, policy.cycleTimezone);
1268                writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
1269                writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
1270                writeLongAttribute(out, ATTR_LAST_WARNING_SNOOZE, policy.lastWarningSnooze);
1271                writeLongAttribute(out, ATTR_LAST_LIMIT_SNOOZE, policy.lastLimitSnooze);
1272                writeBooleanAttribute(out, ATTR_METERED, policy.metered);
1273                writeBooleanAttribute(out, ATTR_INFERRED, policy.inferred);
1274                out.endTag(null, TAG_NETWORK_POLICY);
1275            }
1276
1277            // write all known uid policies
1278            for (int i = 0; i < mAppPolicy.size(); i++) {
1279                final int appId = mAppPolicy.keyAt(i);
1280                final int policy = mAppPolicy.valueAt(i);
1281
1282                // skip writing empty policies
1283                if (policy == POLICY_NONE) continue;
1284
1285                out.startTag(null, TAG_APP_POLICY);
1286                writeIntAttribute(out, ATTR_APP_ID, appId);
1287                writeIntAttribute(out, ATTR_POLICY, policy);
1288                out.endTag(null, TAG_APP_POLICY);
1289            }
1290
1291            out.endTag(null, TAG_POLICY_LIST);
1292            out.endDocument();
1293
1294            mPolicyFile.finishWrite(fos);
1295        } catch (IOException e) {
1296            if (fos != null) {
1297                mPolicyFile.failWrite(fos);
1298            }
1299        }
1300    }
1301
1302    @Override
1303    public void setAppPolicy(int appId, int policy) {
1304        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1305
1306        if (!UserId.isApp(appId)) {
1307            throw new IllegalArgumentException("cannot apply policy to appId " + appId);
1308        }
1309
1310        setAppPolicyUnchecked(appId, policy, true);
1311    }
1312
1313    private void setAppPolicyUnchecked(int appId, int policy, boolean persist) {
1314        final int oldPolicy;
1315        synchronized (mRulesLock) {
1316            oldPolicy = getAppPolicy(appId);
1317            mAppPolicy.put(appId, policy);
1318
1319            // uid policy changed, recompute rules and persist policy.
1320            updateRulesForAppLocked(appId);
1321            if (persist) {
1322                writePolicyLocked();
1323            }
1324        }
1325    }
1326
1327    @Override
1328    public int getAppPolicy(int appId) {
1329        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1330
1331        synchronized (mRulesLock) {
1332            return mAppPolicy.get(appId, POLICY_NONE);
1333        }
1334    }
1335
1336    @Override
1337    public int[] getAppsWithPolicy(int policy) {
1338        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1339
1340        int[] appIds = new int[0];
1341        synchronized (mRulesLock) {
1342            for (int i = 0; i < mAppPolicy.size(); i++) {
1343                final int appId = mAppPolicy.keyAt(i);
1344                final int appPolicy = mAppPolicy.valueAt(i);
1345                if (appPolicy == policy) {
1346                    appIds = appendInt(appIds, appId);
1347                }
1348            }
1349        }
1350        return appIds;
1351    }
1352
1353    @Override
1354    public void registerListener(INetworkPolicyListener listener) {
1355        // TODO: create permission for observing network policy
1356        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1357
1358        mListeners.register(listener);
1359
1360        // TODO: consider dispatching existing rules to new listeners
1361    }
1362
1363    @Override
1364    public void unregisterListener(INetworkPolicyListener listener) {
1365        // TODO: create permission for observing network policy
1366        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1367
1368        mListeners.unregister(listener);
1369    }
1370
1371    @Override
1372    public void setNetworkPolicies(NetworkPolicy[] policies) {
1373        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1374
1375        maybeRefreshTrustedTime();
1376        synchronized (mRulesLock) {
1377            mNetworkPolicy.clear();
1378            for (NetworkPolicy policy : policies) {
1379                mNetworkPolicy.put(policy.template, policy);
1380            }
1381
1382            updateNetworkEnabledLocked();
1383            updateNetworkRulesLocked();
1384            updateNotificationsLocked();
1385            writePolicyLocked();
1386        }
1387    }
1388
1389    private void addNetworkPolicyLocked(NetworkPolicy policy) {
1390        mNetworkPolicy.put(policy.template, policy);
1391
1392        updateNetworkEnabledLocked();
1393        updateNetworkRulesLocked();
1394        updateNotificationsLocked();
1395        writePolicyLocked();
1396    }
1397
1398    @Override
1399    public NetworkPolicy[] getNetworkPolicies() {
1400        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1401        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
1402
1403        synchronized (mRulesLock) {
1404            return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]);
1405        }
1406    }
1407
1408    @Override
1409    public void snoozeLimit(NetworkTemplate template) {
1410        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1411
1412        final long token = Binder.clearCallingIdentity();
1413        try {
1414            performSnooze(template, TYPE_LIMIT);
1415        } finally {
1416            Binder.restoreCallingIdentity(token);
1417        }
1418    }
1419
1420    private void performSnooze(NetworkTemplate template, int type) {
1421        maybeRefreshTrustedTime();
1422        final long currentTime = currentTimeMillis();
1423        synchronized (mRulesLock) {
1424            // find and snooze local policy that matches
1425            final NetworkPolicy policy = mNetworkPolicy.get(template);
1426            if (policy == null) {
1427                throw new IllegalArgumentException("unable to find policy for " + template);
1428            }
1429
1430            switch (type) {
1431                case TYPE_WARNING:
1432                    policy.lastWarningSnooze = currentTime;
1433                    break;
1434                case TYPE_LIMIT:
1435                    policy.lastLimitSnooze = currentTime;
1436                    break;
1437                default:
1438                    throw new IllegalArgumentException("unexpected type");
1439            }
1440
1441            updateNetworkEnabledLocked();
1442            updateNetworkRulesLocked();
1443            updateNotificationsLocked();
1444            writePolicyLocked();
1445        }
1446    }
1447
1448    @Override
1449    public void setRestrictBackground(boolean restrictBackground) {
1450        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1451
1452        maybeRefreshTrustedTime();
1453        synchronized (mRulesLock) {
1454            mRestrictBackground = restrictBackground;
1455            updateRulesForRestrictBackgroundLocked();
1456            updateNotificationsLocked();
1457            writePolicyLocked();
1458        }
1459
1460        mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED, restrictBackground ? 1 : 0, 0)
1461                .sendToTarget();
1462    }
1463
1464    @Override
1465    public boolean getRestrictBackground() {
1466        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1467
1468        synchronized (mRulesLock) {
1469            return mRestrictBackground;
1470        }
1471    }
1472
1473    private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) {
1474        for (NetworkPolicy policy : mNetworkPolicy.values()) {
1475            if (policy.template.matches(ident)) {
1476                return policy;
1477            }
1478        }
1479        return null;
1480    }
1481
1482    @Override
1483    public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) {
1484        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
1485
1486        // only returns usage summary, so we don't require caller to have
1487        // READ_NETWORK_USAGE_HISTORY.
1488        final long token = Binder.clearCallingIdentity();
1489        try {
1490            return getNetworkQuotaInfoUnchecked(state);
1491        } finally {
1492            Binder.restoreCallingIdentity(token);
1493        }
1494    }
1495
1496    private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) {
1497        final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
1498
1499        final NetworkPolicy policy;
1500        synchronized (mRulesLock) {
1501            policy = findPolicyForNetworkLocked(ident);
1502        }
1503
1504        if (policy == null || !policy.hasCycle()) {
1505            // missing policy means we can't derive useful quota info
1506            return null;
1507        }
1508
1509        final long currentTime = currentTimeMillis();
1510
1511        // find total bytes used under policy
1512        final long start = computeLastCycleBoundary(currentTime, policy);
1513        final long end = currentTime;
1514        final long totalBytes = getTotalBytes(policy.template, start, end);
1515
1516        // report soft and hard limits under policy
1517        final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes
1518                : NetworkQuotaInfo.NO_LIMIT;
1519        final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes
1520                : NetworkQuotaInfo.NO_LIMIT;
1521
1522        return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes);
1523    }
1524
1525    @Override
1526    public boolean isNetworkMetered(NetworkState state) {
1527        final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
1528
1529        // roaming networks are always considered metered
1530        if (ident.getRoaming()) {
1531            return true;
1532        }
1533
1534        final NetworkPolicy policy;
1535        synchronized (mRulesLock) {
1536            policy = findPolicyForNetworkLocked(ident);
1537        }
1538
1539        if (policy != null) {
1540            return policy.metered;
1541        } else {
1542            final int type = state.networkInfo.getType();
1543            if (isNetworkTypeMobile(type) || type == TYPE_WIMAX) {
1544                return true;
1545            }
1546            return false;
1547        }
1548    }
1549
1550    @Override
1551    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
1552        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
1553
1554        final IndentingPrintWriter fout = new IndentingPrintWriter(writer, "  ");
1555
1556        final HashSet<String> argSet = new HashSet<String>();
1557        for (String arg : args) {
1558            argSet.add(arg);
1559        }
1560
1561        synchronized (mRulesLock) {
1562            if (argSet.contains("--unsnooze")) {
1563                for (NetworkPolicy policy : mNetworkPolicy.values()) {
1564                    policy.clearSnooze();
1565                }
1566
1567                updateNetworkEnabledLocked();
1568                updateNetworkRulesLocked();
1569                updateNotificationsLocked();
1570                writePolicyLocked();
1571
1572                fout.println("Cleared snooze timestamps");
1573                return;
1574            }
1575
1576            fout.print("Restrict background: "); fout.println(mRestrictBackground);
1577            fout.println("Network policies:");
1578            fout.increaseIndent();
1579            for (NetworkPolicy policy : mNetworkPolicy.values()) {
1580                fout.println(policy.toString());
1581            }
1582            fout.decreaseIndent();
1583
1584            fout.println("Policy for apps:");
1585            fout.increaseIndent();
1586            int size = mAppPolicy.size();
1587            for (int i = 0; i < size; i++) {
1588                final int appId = mAppPolicy.keyAt(i);
1589                final int policy = mAppPolicy.valueAt(i);
1590                fout.print("appId=");
1591                fout.print(appId);
1592                fout.print(" policy=");
1593                dumpPolicy(fout, policy);
1594                fout.println();
1595            }
1596            fout.decreaseIndent();
1597
1598            final SparseBooleanArray knownUids = new SparseBooleanArray();
1599            collectKeys(mUidForeground, knownUids);
1600            collectKeys(mUidRules, knownUids);
1601
1602            fout.println("Status for known UIDs:");
1603            fout.increaseIndent();
1604            size = knownUids.size();
1605            for (int i = 0; i < size; i++) {
1606                final int uid = knownUids.keyAt(i);
1607                fout.print("UID=");
1608                fout.print(uid);
1609
1610                fout.print(" foreground=");
1611                final int foregroundIndex = mUidPidForeground.indexOfKey(uid);
1612                if (foregroundIndex < 0) {
1613                    fout.print("UNKNOWN");
1614                } else {
1615                    dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex));
1616                }
1617
1618                fout.print(" rules=");
1619                final int rulesIndex = mUidRules.indexOfKey(uid);
1620                if (rulesIndex < 0) {
1621                    fout.print("UNKNOWN");
1622                } else {
1623                    dumpRules(fout, mUidRules.valueAt(rulesIndex));
1624                }
1625
1626                fout.println();
1627            }
1628            fout.decreaseIndent();
1629        }
1630    }
1631
1632    @Override
1633    public boolean isUidForeground(int uid) {
1634        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1635
1636        synchronized (mRulesLock) {
1637            // only really in foreground when screen is also on
1638            return mUidForeground.get(uid, false) && mScreenOn;
1639        }
1640    }
1641
1642    /**
1643     * Foreground for PID changed; recompute foreground at UID level. If
1644     * changed, will trigger {@link #updateRulesForUidLocked(int)}.
1645     */
1646    private void computeUidForegroundLocked(int uid) {
1647        final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
1648
1649        // current pid is dropping foreground; examine other pids
1650        boolean uidForeground = false;
1651        final int size = pidForeground.size();
1652        for (int i = 0; i < size; i++) {
1653            if (pidForeground.valueAt(i)) {
1654                uidForeground = true;
1655                break;
1656            }
1657        }
1658
1659        final boolean oldUidForeground = mUidForeground.get(uid, false);
1660        if (oldUidForeground != uidForeground) {
1661            // foreground changed, push updated rules
1662            mUidForeground.put(uid, uidForeground);
1663            updateRulesForUidLocked(uid);
1664        }
1665    }
1666
1667    private void updateScreenOn() {
1668        synchronized (mRulesLock) {
1669            try {
1670                mScreenOn = mPowerManager.isScreenOn();
1671            } catch (RemoteException e) {
1672                // ignored; service lives in system_server
1673            }
1674            updateRulesForScreenLocked();
1675        }
1676    }
1677
1678    /**
1679     * Update rules that might be changed by {@link #mScreenOn} value.
1680     */
1681    private void updateRulesForScreenLocked() {
1682        // only update rules for anyone with foreground activities
1683        final int size = mUidForeground.size();
1684        for (int i = 0; i < size; i++) {
1685            if (mUidForeground.valueAt(i)) {
1686                final int uid = mUidForeground.keyAt(i);
1687                updateRulesForUidLocked(uid);
1688            }
1689        }
1690    }
1691
1692    /**
1693     * Update rules that might be changed by {@link #mRestrictBackground} value.
1694     */
1695    private void updateRulesForRestrictBackgroundLocked() {
1696        // update rules for all installed applications
1697        final PackageManager pm = mContext.getPackageManager();
1698        final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
1699        for (ApplicationInfo app : apps) {
1700            final int appId = UserId.getAppId(app.uid);
1701            updateRulesForAppLocked(appId);
1702        }
1703
1704        // limit data usage for some internal system services
1705        updateRulesForUidLocked(android.os.Process.MEDIA_UID);
1706        updateRulesForUidLocked(android.os.Process.DRM_UID);
1707    }
1708
1709    private void updateRulesForAppLocked(int appId) {
1710        for (UserInfo user : mContext.getPackageManager().getUsers()) {
1711            final int uid = UserId.getUid(user.id, appId);
1712            updateRulesForUidLocked(uid);
1713        }
1714    }
1715
1716    private static boolean isUidValidForRules(int uid) {
1717        // allow rules on specific system services, and any apps
1718        if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID
1719                || UserId.isApp(uid)) {
1720            return true;
1721        }
1722
1723        return false;
1724    }
1725
1726    private void updateRulesForUidLocked(int uid) {
1727        if (!isUidValidForRules(uid)) return;
1728
1729        final int appId = UserId.getAppId(uid);
1730        final int appPolicy = getAppPolicy(appId);
1731        final boolean uidForeground = isUidForeground(uid);
1732
1733        // derive active rules based on policy and active state
1734        int uidRules = RULE_ALLOW_ALL;
1735        if (!uidForeground && (appPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
1736            // uid in background, and policy says to block metered data
1737            uidRules = RULE_REJECT_METERED;
1738        }
1739        if (!uidForeground && mRestrictBackground) {
1740            // uid in background, and global background disabled
1741            uidRules = RULE_REJECT_METERED;
1742        }
1743
1744        // TODO: only dispatch when rules actually change
1745
1746        if (uidRules == RULE_ALLOW_ALL) {
1747            mUidRules.delete(uid);
1748        } else {
1749            mUidRules.put(uid, uidRules);
1750        }
1751
1752        final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0;
1753        setUidNetworkRules(uid, rejectMetered);
1754
1755        // dispatch changed rule to existing listeners
1756        mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
1757
1758        try {
1759            // adjust stats accounting based on foreground status
1760            mNetworkStats.setUidForeground(uid, uidForeground);
1761        } catch (RemoteException e) {
1762            // ignored; service lives in system_server
1763        }
1764    }
1765
1766    private Handler.Callback mHandlerCallback = new Handler.Callback() {
1767        @Override
1768        public boolean handleMessage(Message msg) {
1769            switch (msg.what) {
1770                case MSG_RULES_CHANGED: {
1771                    final int uid = msg.arg1;
1772                    final int uidRules = msg.arg2;
1773                    final int length = mListeners.beginBroadcast();
1774                    for (int i = 0; i < length; i++) {
1775                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
1776                        if (listener != null) {
1777                            try {
1778                                listener.onUidRulesChanged(uid, uidRules);
1779                            } catch (RemoteException e) {
1780                            }
1781                        }
1782                    }
1783                    mListeners.finishBroadcast();
1784                    return true;
1785                }
1786                case MSG_METERED_IFACES_CHANGED: {
1787                    final String[] meteredIfaces = (String[]) msg.obj;
1788                    final int length = mListeners.beginBroadcast();
1789                    for (int i = 0; i < length; i++) {
1790                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
1791                        if (listener != null) {
1792                            try {
1793                                listener.onMeteredIfacesChanged(meteredIfaces);
1794                            } catch (RemoteException e) {
1795                            }
1796                        }
1797                    }
1798                    mListeners.finishBroadcast();
1799                    return true;
1800                }
1801                case MSG_FOREGROUND_ACTIVITIES_CHANGED: {
1802                    final int pid = msg.arg1;
1803                    final int uid = msg.arg2;
1804                    final boolean foregroundActivities = (Boolean) msg.obj;
1805
1806                    synchronized (mRulesLock) {
1807                        // because a uid can have multiple pids running inside, we need to
1808                        // remember all pid states and summarize foreground at uid level.
1809
1810                        // record foreground for this specific pid
1811                        SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
1812                        if (pidForeground == null) {
1813                            pidForeground = new SparseBooleanArray(2);
1814                            mUidPidForeground.put(uid, pidForeground);
1815                        }
1816                        pidForeground.put(pid, foregroundActivities);
1817                        computeUidForegroundLocked(uid);
1818                    }
1819                    return true;
1820                }
1821                case MSG_PROCESS_DIED: {
1822                    final int pid = msg.arg1;
1823                    final int uid = msg.arg2;
1824
1825                    synchronized (mRulesLock) {
1826                        // clear records and recompute, when they exist
1827                        final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
1828                        if (pidForeground != null) {
1829                            pidForeground.delete(pid);
1830                            computeUidForegroundLocked(uid);
1831                        }
1832                    }
1833                    return true;
1834                }
1835                case MSG_LIMIT_REACHED: {
1836                    final String iface = (String) msg.obj;
1837
1838                    maybeRefreshTrustedTime();
1839                    synchronized (mRulesLock) {
1840                        if (mMeteredIfaces.contains(iface)) {
1841                            try {
1842                                // force stats update to make sure we have
1843                                // numbers that caused alert to trigger.
1844                                mNetworkStats.forceUpdate();
1845                            } catch (RemoteException e) {
1846                                // ignored; service lives in system_server
1847                            }
1848
1849                            updateNetworkEnabledLocked();
1850                            updateNotificationsLocked();
1851                        }
1852                    }
1853                    return true;
1854                }
1855                case MSG_RESTRICT_BACKGROUND_CHANGED: {
1856                    final boolean restrictBackground = msg.arg1 != 0;
1857                    final int length = mListeners.beginBroadcast();
1858                    for (int i = 0; i < length; i++) {
1859                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
1860                        if (listener != null) {
1861                            try {
1862                                listener.onRestrictBackgroundChanged(restrictBackground);
1863                            } catch (RemoteException e) {
1864                            }
1865                        }
1866                    }
1867                    mListeners.finishBroadcast();
1868                    return true;
1869                }
1870                case MSG_ADVISE_PERSIST_THRESHOLD: {
1871                    final long lowestRule = (Long) msg.obj;
1872                    try {
1873                        // make sure stats are recorded frequently enough; we aim
1874                        // for 2MB threshold for 2GB/month rules.
1875                        final long persistThreshold = lowestRule / 1000;
1876                        mNetworkStats.advisePersistThreshold(persistThreshold);
1877                    } catch (RemoteException e) {
1878                        // ignored; service lives in system_server
1879                    }
1880                    return true;
1881                }
1882                case MSG_SCREEN_ON_CHANGED: {
1883                    updateScreenOn();
1884                    return true;
1885                }
1886                default: {
1887                    return false;
1888                }
1889            }
1890        }
1891    };
1892
1893    private void setInterfaceQuota(String iface, long quotaBytes) {
1894        try {
1895            mNetworkManager.setInterfaceQuota(iface, quotaBytes);
1896        } catch (IllegalStateException e) {
1897            Log.wtf(TAG, "problem setting interface quota", e);
1898        } catch (RemoteException e) {
1899            // ignored; service lives in system_server
1900        }
1901    }
1902
1903    private void removeInterfaceQuota(String iface) {
1904        try {
1905            mNetworkManager.removeInterfaceQuota(iface);
1906        } catch (IllegalStateException e) {
1907            Log.wtf(TAG, "problem removing interface quota", e);
1908        } catch (RemoteException e) {
1909            // ignored; service lives in system_server
1910        }
1911    }
1912
1913    private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
1914        try {
1915            mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
1916        } catch (IllegalStateException e) {
1917            Log.wtf(TAG, "problem setting uid rules", e);
1918        } catch (RemoteException e) {
1919            // ignored; service lives in system_server
1920        }
1921    }
1922
1923    /**
1924     * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}.
1925     */
1926    private void setPolicyDataEnable(int networkType, boolean enabled) {
1927        try {
1928            mConnManager.setPolicyDataEnable(networkType, enabled);
1929        } catch (RemoteException e) {
1930            // ignored; service lives in system_server
1931        }
1932    }
1933
1934    private long getTotalBytes(NetworkTemplate template, long start, long end) {
1935        try {
1936            return mNetworkStats.getNetworkTotalBytes(template, start, end);
1937        } catch (RuntimeException e) {
1938            Slog.w(TAG, "problem reading network stats: " + e);
1939            return 0;
1940        } catch (RemoteException e) {
1941            // ignored; service lives in system_server
1942            return 0;
1943        }
1944    }
1945
1946    private boolean isBandwidthControlEnabled() {
1947        final long token = Binder.clearCallingIdentity();
1948        try {
1949            return mNetworkManager.isBandwidthControlEnabled();
1950        } catch (RemoteException e) {
1951            // ignored; service lives in system_server
1952            return false;
1953        } finally {
1954            Binder.restoreCallingIdentity(token);
1955        }
1956    }
1957
1958    /**
1959     * Try refreshing {@link #mTime} when stale.
1960     */
1961    private void maybeRefreshTrustedTime() {
1962        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
1963            mTime.forceRefresh();
1964        }
1965    }
1966
1967    private long currentTimeMillis() {
1968        return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
1969    }
1970
1971    private static Intent buildAllowBackgroundDataIntent() {
1972        return new Intent(ACTION_ALLOW_BACKGROUND);
1973    }
1974
1975    private static Intent buildSnoozeWarningIntent(NetworkTemplate template) {
1976        final Intent intent = new Intent(ACTION_SNOOZE_WARNING);
1977        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
1978        return intent;
1979    }
1980
1981    private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
1982        final Intent intent = new Intent();
1983        intent.setComponent(new ComponentName(
1984                "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity"));
1985        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1986        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
1987        return intent;
1988    }
1989
1990    private static Intent buildViewDataUsageIntent(NetworkTemplate template) {
1991        final Intent intent = new Intent();
1992        intent.setComponent(new ComponentName(
1993                "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
1994        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1995        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
1996        return intent;
1997    }
1998
1999    // @VisibleForTesting
2000    public void addIdleHandler(IdleHandler handler) {
2001        mHandler.getLooper().getQueue().addIdleHandler(handler);
2002    }
2003
2004    private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
2005        final int size = source.size();
2006        for (int i = 0; i < size; i++) {
2007            target.put(source.keyAt(i), true);
2008        }
2009    }
2010
2011    private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) {
2012        final int size = source.size();
2013        for (int i = 0; i < size; i++) {
2014            target.put(source.keyAt(i), true);
2015        }
2016    }
2017
2018    private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) {
2019        fout.print("[");
2020        final int size = value.size();
2021        for (int i = 0; i < size; i++) {
2022            fout.print(value.keyAt(i) + "=" + value.valueAt(i));
2023            if (i < size - 1) fout.print(",");
2024        }
2025        fout.print("]");
2026    }
2027
2028    public static class XmlUtils {
2029        public static int readIntAttribute(XmlPullParser in, String name) throws IOException {
2030            final String value = in.getAttributeValue(null, name);
2031            try {
2032                return Integer.parseInt(value);
2033            } catch (NumberFormatException e) {
2034                throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
2035            }
2036        }
2037
2038        public static void writeIntAttribute(XmlSerializer out, String name, int value)
2039                throws IOException {
2040            out.attribute(null, name, Integer.toString(value));
2041        }
2042
2043        public static long readLongAttribute(XmlPullParser in, String name) throws IOException {
2044            final String value = in.getAttributeValue(null, name);
2045            try {
2046                return Long.parseLong(value);
2047            } catch (NumberFormatException e) {
2048                throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
2049            }
2050        }
2051
2052        public static void writeLongAttribute(XmlSerializer out, String name, long value)
2053                throws IOException {
2054            out.attribute(null, name, Long.toString(value));
2055        }
2056
2057        public static boolean readBooleanAttribute(XmlPullParser in, String name) {
2058            final String value = in.getAttributeValue(null, name);
2059            return Boolean.parseBoolean(value);
2060        }
2061
2062        public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value)
2063                throws IOException {
2064            out.attribute(null, name, Boolean.toString(value));
2065        }
2066    }
2067}
2068