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