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