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