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