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