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