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