NetworkPolicyManagerService.java revision 1b6519bd87a59a10e9928e5772a17976692611da
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.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
26import static android.content.Intent.ACTION_PACKAGE_ADDED;
27import static android.content.Intent.ACTION_UID_REMOVED;
28import static android.content.Intent.ACTION_USER_ADDED;
29import static android.content.Intent.ACTION_USER_REMOVED;
30import static android.content.Intent.EXTRA_UID;
31import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
32import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
33import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
34import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
35import static android.net.ConnectivityManager.TYPE_MOBILE;
36import static android.net.ConnectivityManager.TYPE_WIMAX;
37import static android.net.ConnectivityManager.isNetworkTypeMobile;
38import static android.net.NetworkPolicy.CYCLE_NONE;
39import static android.net.NetworkPolicy.LIMIT_DISABLED;
40import static android.net.NetworkPolicy.SNOOZE_NEVER;
41import static android.net.NetworkPolicy.WARNING_DISABLED;
42import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
43import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
44import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
45import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
46import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
47import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
48import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
49import static android.net.NetworkPolicyManager.POLICY_NONE;
50import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
51import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
52import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
53import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
54import static android.net.NetworkPolicyManager.RULE_UNKNOWN;
55import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
56import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
57import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
58import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
59import static android.net.NetworkTemplate.MATCH_WIFI;
60import static android.net.NetworkTemplate.buildTemplateMobileAll;
61import static android.net.TrafficStats.MB_IN_BYTES;
62import static android.net.wifi.WifiManager.CHANGE_REASON_ADDED;
63import static android.net.wifi.WifiManager.CHANGE_REASON_REMOVED;
64import static android.net.wifi.WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION;
65import static android.net.wifi.WifiManager.EXTRA_CHANGE_REASON;
66import static android.net.wifi.WifiManager.EXTRA_NETWORK_INFO;
67import static android.net.wifi.WifiManager.EXTRA_WIFI_CONFIGURATION;
68import static android.net.wifi.WifiManager.EXTRA_WIFI_INFO;
69import static android.text.format.DateUtils.DAY_IN_MILLIS;
70
71import static com.android.internal.util.ArrayUtils.appendInt;
72import static com.android.internal.util.Preconditions.checkNotNull;
73import static com.android.internal.util.XmlUtils.readBooleanAttribute;
74import static com.android.internal.util.XmlUtils.readIntAttribute;
75import static com.android.internal.util.XmlUtils.readLongAttribute;
76import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
77import static com.android.internal.util.XmlUtils.writeIntAttribute;
78import static com.android.internal.util.XmlUtils.writeLongAttribute;
79import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
80import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
81
82import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
83import static org.xmlpull.v1.XmlPullParser.END_TAG;
84import static org.xmlpull.v1.XmlPullParser.START_TAG;
85
86import android.Manifest;
87import android.app.ActivityManager;
88import android.app.AppGlobals;
89import android.app.AppOpsManager;
90import android.app.IActivityManager;
91import android.app.INotificationManager;
92import android.app.IUidObserver;
93import android.app.Notification;
94import android.app.PendingIntent;
95import android.app.usage.UsageStatsManagerInternal;
96import android.content.BroadcastReceiver;
97import android.content.ComponentName;
98import android.content.Context;
99import android.content.Intent;
100import android.content.IntentFilter;
101import android.content.pm.ApplicationInfo;
102import android.content.pm.IPackageManager;
103import android.content.pm.PackageManager;
104import android.content.pm.PackageManager.NameNotFoundException;
105import android.content.pm.UserInfo;
106import android.content.res.Resources;
107import android.net.ConnectivityManager;
108import android.net.IConnectivityManager;
109import android.net.INetworkManagementEventObserver;
110import android.net.INetworkPolicyListener;
111import android.net.INetworkPolicyManager;
112import android.net.INetworkStatsService;
113import android.net.LinkProperties;
114import android.net.NetworkIdentity;
115import android.net.NetworkInfo;
116import android.net.NetworkPolicy;
117import android.net.NetworkPolicyManager;
118import android.net.NetworkQuotaInfo;
119import android.net.NetworkState;
120import android.net.NetworkTemplate;
121import android.net.wifi.WifiConfiguration;
122import android.net.wifi.WifiInfo;
123import android.net.wifi.WifiManager;
124import android.os.Binder;
125import android.os.Environment;
126import android.os.Handler;
127import android.os.HandlerThread;
128import android.os.IDeviceIdleController;
129import android.os.INetworkManagementService;
130import android.os.IPowerManager;
131import android.os.Message;
132import android.os.MessageQueue.IdleHandler;
133import android.os.PowerManager;
134import android.os.PowerManagerInternal;
135import android.os.RemoteCallbackList;
136import android.os.RemoteException;
137import android.os.ResultReceiver;
138import android.os.ServiceManager;
139import android.os.UserHandle;
140import android.os.UserManager;
141import android.provider.Settings;
142import android.telephony.SubscriptionManager;
143import android.telephony.TelephonyManager;
144import android.text.format.Formatter;
145import android.text.format.Time;
146import android.util.ArrayMap;
147import android.util.ArraySet;
148import android.util.AtomicFile;
149import android.util.DebugUtils;
150import android.util.Log;
151import android.util.NtpTrustedTime;
152import android.util.Pair;
153import android.util.Slog;
154import android.util.SparseBooleanArray;
155import android.util.SparseIntArray;
156import android.util.TrustedTime;
157import android.util.Xml;
158
159import com.android.internal.R;
160import com.android.internal.annotations.VisibleForTesting;
161import com.android.internal.content.PackageMonitor;
162import com.android.internal.util.ArrayUtils;
163import com.android.internal.util.FastXmlSerializer;
164import com.android.internal.util.IndentingPrintWriter;
165import com.android.server.DeviceIdleController;
166import com.android.server.EventLogTags;
167import com.android.server.LocalServices;
168import com.android.server.SystemConfig;
169
170import libcore.io.IoUtils;
171
172import com.google.android.collect.Lists;
173
174import org.xmlpull.v1.XmlPullParser;
175import org.xmlpull.v1.XmlPullParserException;
176import org.xmlpull.v1.XmlSerializer;
177
178import java.io.File;
179import java.io.FileDescriptor;
180import java.io.FileInputStream;
181import java.io.FileNotFoundException;
182import java.io.FileOutputStream;
183import java.io.IOException;
184import java.io.PrintWriter;
185import java.nio.charset.StandardCharsets;
186import java.util.ArrayList;
187import java.util.Arrays;
188import java.util.List;
189
190/**
191 * Service that maintains low-level network policy rules, using
192 * {@link NetworkStatsService} statistics to drive those rules.
193 * <p>
194 * Derives active rules by combining a given policy with other system status,
195 * and delivers to listeners, such as {@link ConnectivityManager}, for
196 * enforcement.
197 */
198public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
199    static final String TAG = "NetworkPolicy";
200    private static final boolean LOGD = false;
201    private static final boolean LOGV = false;
202
203    private static final int VERSION_INIT = 1;
204    private static final int VERSION_ADDED_SNOOZE = 2;
205    private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3;
206    private static final int VERSION_ADDED_METERED = 4;
207    private static final int VERSION_SPLIT_SNOOZE = 5;
208    private static final int VERSION_ADDED_TIMEZONE = 6;
209    private static final int VERSION_ADDED_INFERRED = 7;
210    private static final int VERSION_SWITCH_APP_ID = 8;
211    private static final int VERSION_ADDED_NETWORK_ID = 9;
212    private static final int VERSION_SWITCH_UID = 10;
213    private static final int VERSION_LATEST = VERSION_SWITCH_UID;
214
215    @VisibleForTesting
216    public static final int TYPE_WARNING = 0x1;
217    @VisibleForTesting
218    public static final int TYPE_LIMIT = 0x2;
219    @VisibleForTesting
220    public static final int TYPE_LIMIT_SNOOZED = 0x3;
221
222    private static final String TAG_POLICY_LIST = "policy-list";
223    private static final String TAG_NETWORK_POLICY = "network-policy";
224    private static final String TAG_UID_POLICY = "uid-policy";
225    private static final String TAG_APP_POLICY = "app-policy";
226    private static final String TAG_WHITELIST = "whitelist";
227    private static final String TAG_RESTRICT_BACKGROUND = "restrict-background";
228    private static final String TAG_REVOKED_RESTRICT_BACKGROUND = "revoked-restrict-background";
229
230    private static final String ATTR_VERSION = "version";
231    private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
232    private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
233    private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
234    private static final String ATTR_NETWORK_ID = "networkId";
235    private static final String ATTR_CYCLE_DAY = "cycleDay";
236    private static final String ATTR_CYCLE_TIMEZONE = "cycleTimezone";
237    private static final String ATTR_WARNING_BYTES = "warningBytes";
238    private static final String ATTR_LIMIT_BYTES = "limitBytes";
239    private static final String ATTR_LAST_SNOOZE = "lastSnooze";
240    private static final String ATTR_LAST_WARNING_SNOOZE = "lastWarningSnooze";
241    private static final String ATTR_LAST_LIMIT_SNOOZE = "lastLimitSnooze";
242    private static final String ATTR_METERED = "metered";
243    private static final String ATTR_INFERRED = "inferred";
244    private static final String ATTR_UID = "uid";
245    private static final String ATTR_APP_ID = "appId";
246    private static final String ATTR_POLICY = "policy";
247
248    private static final String ACTION_ALLOW_BACKGROUND =
249            "com.android.server.net.action.ALLOW_BACKGROUND";
250    private static final String ACTION_SNOOZE_WARNING =
251            "com.android.server.net.action.SNOOZE_WARNING";
252
253    private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
254
255    private static final int MSG_RULES_CHANGED = 1;
256    private static final int MSG_METERED_IFACES_CHANGED = 2;
257    private static final int MSG_LIMIT_REACHED = 5;
258    private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6;
259    private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7;
260    private static final int MSG_SCREEN_ON_CHANGED = 8;
261    private static final int MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED = 9;
262    private static final int MSG_UPDATE_INTERFACE_QUOTA = 10;
263    private static final int MSG_REMOVE_INTERFACE_QUOTA = 11;
264
265    private final Context mContext;
266    private final IActivityManager mActivityManager;
267    private final IPowerManager mPowerManager;
268    private final INetworkStatsService mNetworkStats;
269    private final INetworkManagementService mNetworkManager;
270    private UsageStatsManagerInternal mUsageStats;
271    private final TrustedTime mTime;
272    private final UserManager mUserManager;
273
274    private IConnectivityManager mConnManager;
275    private INotificationManager mNotifManager;
276    private PowerManagerInternal mPowerManagerInternal;
277    private IDeviceIdleController mDeviceIdleController;
278
279    final Object mRulesLock = new Object();
280
281    volatile boolean mSystemReady;
282    volatile boolean mScreenOn;
283    volatile boolean mRestrictBackground;
284    volatile boolean mRestrictPower;
285    volatile boolean mDeviceIdleMode;
286
287    private final boolean mSuppressDefaultPolicy;
288
289    /** Defined network policies. */
290    final ArrayMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = new ArrayMap<>();
291    /** Currently active network rules for ifaces. */
292    final ArrayMap<NetworkPolicy, String[]> mNetworkRules = new ArrayMap<>();
293
294    /** Defined UID policies. */
295    final SparseIntArray mUidPolicy = new SparseIntArray();
296    /** Currently derived rules for each UID. */
297    final SparseIntArray mUidRules = new SparseIntArray();
298
299    final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
300    final SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
301    final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
302
303    /** Set of states for the child firewall chains. True if the chain is active. */
304    final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
305
306    /**
307     * UIDs that have been white-listed to always be able to have network access
308     * in power save mode, except device idle (doze) still applies.
309     * TODO: An int array might be sufficient
310     */
311    private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
312
313    /**
314     * UIDs that have been white-listed to always be able to have network access
315     * in power save mode.
316     * TODO: An int array might be sufficient
317     */
318    private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray();
319
320    private final SparseBooleanArray mPowerSaveTempWhitelistAppIds = new SparseBooleanArray();
321
322    /**
323     * UIDs that have been white-listed to avoid restricted background.
324     */
325    private final SparseBooleanArray mRestrictBackgroundWhitelistUids = new SparseBooleanArray();
326
327    /**
328     * UIDs that have been initially white-listed by system to avoid restricted background.
329     */
330    private final SparseBooleanArray mDefaultRestrictBackgroundWhitelistUids =
331            new SparseBooleanArray();
332
333    /**
334     * UIDs that have been initially white-listed by system to avoid restricted background,
335     * but later revoked by user.
336     */
337    private final SparseBooleanArray mRestrictBackgroundWhitelistRevokedUids =
338            new SparseBooleanArray();
339
340    /** Set of ifaces that are metered. */
341    private ArraySet<String> mMeteredIfaces = new ArraySet<>();
342    /** Set of over-limit templates that have been notified. */
343    private final ArraySet<NetworkTemplate> mOverLimitNotified = new ArraySet<>();
344
345    /** Set of currently active {@link Notification} tags. */
346    private final ArraySet<String> mActiveNotifs = new ArraySet<String>();
347
348    /** Foreground at UID granularity. */
349    final SparseIntArray mUidState = new SparseIntArray();
350
351    /** Higher priority listener before general event dispatch */
352    private INetworkPolicyListener mConnectivityListener;
353
354    private final RemoteCallbackList<INetworkPolicyListener>
355            mListeners = new RemoteCallbackList<>();
356
357    final Handler mHandler;
358
359    private final AtomicFile mPolicyFile;
360
361    private final AppOpsManager mAppOps;
362
363    private final MyPackageMonitor mPackageMonitor;
364    private final IPackageManager mIPm;
365
366
367    // TODO: keep whitelist of system-critical services that should never have
368    // rules enforced, such as system, phone, and radio UIDs.
369
370    // TODO: migrate notifications to SystemUI
371
372    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
373            IPowerManager powerManager, INetworkStatsService networkStats,
374            INetworkManagementService networkManagement) {
375        this(context, activityManager, powerManager, networkStats, networkManagement,
376                NtpTrustedTime.getInstance(context), getSystemDir(), false);
377    }
378
379    private static File getSystemDir() {
380        return new File(Environment.getDataDirectory(), "system");
381    }
382
383    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
384            IPowerManager powerManager, INetworkStatsService networkStats,
385            INetworkManagementService networkManagement, TrustedTime time, File systemDir,
386            boolean suppressDefaultPolicy) {
387        mContext = checkNotNull(context, "missing context");
388        mActivityManager = checkNotNull(activityManager, "missing activityManager");
389        mPowerManager = checkNotNull(powerManager, "missing powerManager");
390        mNetworkStats = checkNotNull(networkStats, "missing networkStats");
391        mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
392        mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService(
393                Context.DEVICE_IDLE_CONTROLLER));
394        mTime = checkNotNull(time, "missing TrustedTime");
395        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
396        mIPm = AppGlobals.getPackageManager();
397
398        HandlerThread thread = new HandlerThread(TAG);
399        thread.start();
400        mHandler = new Handler(thread.getLooper(), mHandlerCallback);
401
402        mSuppressDefaultPolicy = suppressDefaultPolicy;
403
404        mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
405
406        mAppOps = context.getSystemService(AppOpsManager.class);
407
408        mPackageMonitor = new MyPackageMonitor();
409    }
410
411    public void bindConnectivityManager(IConnectivityManager connManager) {
412        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
413    }
414
415    public void bindNotificationManager(INotificationManager notifManager) {
416        mNotifManager = checkNotNull(notifManager, "missing INotificationManager");
417    }
418
419    void updatePowerSaveWhitelistLocked() {
420        try {
421            int[] whitelist = mDeviceIdleController.getAppIdWhitelistExceptIdle();
422            mPowerSaveWhitelistExceptIdleAppIds.clear();
423            if (whitelist != null) {
424                for (int uid : whitelist) {
425                    mPowerSaveWhitelistExceptIdleAppIds.put(uid, true);
426                }
427            }
428            whitelist = mDeviceIdleController.getAppIdWhitelist();
429            mPowerSaveWhitelistAppIds.clear();
430            if (whitelist != null) {
431                for (int uid : whitelist) {
432                    mPowerSaveWhitelistAppIds.put(uid, true);
433                }
434            }
435        } catch (RemoteException e) {
436        }
437    }
438
439    /**
440     * Whitelists pre-defined apps for restrict background, but only if the user didn't already
441     * revoke the whitelist.
442     *
443     * @return whether any uid has been added to {@link #mRestrictBackgroundWhitelistUids}.
444     */
445    boolean addDefaultRestrictBackgroundWhitelistUids() {
446        final SystemConfig sysConfig = SystemConfig.getInstance();
447        final PackageManager pm = mContext.getPackageManager();
448        final List<UserInfo> users = mUserManager.getUsers();
449        final int numberUsers = users.size();
450
451        final ArraySet<String> allowDataUsage = sysConfig.getAllowInDataUsageSave();
452        boolean changed = false;
453        for (int i = 0; i < allowDataUsage.size(); i++) {
454            final String pkg = allowDataUsage.valueAt(i);
455            if (LOGD)
456                Slog.d(TAG, "checking restricted background whitelisting for package " + pkg);
457            final ApplicationInfo app;
458            try {
459                app = pm.getApplicationInfo(pkg, PackageManager.MATCH_SYSTEM_ONLY);
460            } catch (PackageManager.NameNotFoundException e) {
461                // Should not happen
462                Slog.wtf(TAG, "No ApplicationInfo for package " + pkg);
463                continue;
464            }
465            if (!app.isPrivilegedApp()) {
466                Slog.w(TAG, "getAllowInDataUsageSave() returned non-privileged app: " + pkg);
467                continue;
468            }
469            for (int j = 0; j < numberUsers; j++) {
470                final UserInfo user = users.get(j);
471                final int uid = UserHandle.getUid(user.id, app.uid);
472                mDefaultRestrictBackgroundWhitelistUids.append(uid, true);
473                if (LOGD) Slog.d(TAG, "revoked whistelist status for uid " + uid + ": "
474                        + mRestrictBackgroundWhitelistRevokedUids.get(uid));
475                if (!mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
476                    Slog.i(TAG, "adding default package " + pkg + " (uid " + uid + " for user "
477                            + user.id + ") to restrict background whitelist");
478                    mRestrictBackgroundWhitelistUids.append(uid, true);
479                    changed = true;
480                }
481            }
482        }
483        return changed;
484    }
485
486    void updatePowerSaveTempWhitelistLocked() {
487        try {
488            // Clear the states of the current whitelist
489            final int N = mPowerSaveTempWhitelistAppIds.size();
490            for (int i = 0; i < N; i++) {
491                mPowerSaveTempWhitelistAppIds.setValueAt(i, false);
492            }
493            // Update the states with the new whitelist
494            final int[] whitelist = mDeviceIdleController.getAppIdTempWhitelist();
495            if (whitelist != null) {
496                for (int uid : whitelist) {
497                    mPowerSaveTempWhitelistAppIds.put(uid, true);
498                }
499            }
500        } catch (RemoteException e) {
501        }
502    }
503
504    /**
505     * Remove unnecessary entries in the temp whitelist
506     */
507    void purgePowerSaveTempWhitelistLocked() {
508        final int N = mPowerSaveTempWhitelistAppIds.size();
509        for (int i = N - 1; i >= 0; i--) {
510            if (mPowerSaveTempWhitelistAppIds.valueAt(i) == false) {
511                mPowerSaveTempWhitelistAppIds.removeAt(i);
512            }
513        }
514    }
515
516    public void systemReady() {
517        if (!isBandwidthControlEnabled()) {
518            Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy");
519            return;
520        }
521
522        mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
523
524        mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
525
526        synchronized (mRulesLock) {
527            updatePowerSaveWhitelistLocked();
528            mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
529            mPowerManagerInternal.registerLowPowerModeObserver(
530                    new PowerManagerInternal.LowPowerModeListener() {
531                @Override
532                public void onLowPowerModeChanged(boolean enabled) {
533                    if (LOGD) Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
534                    synchronized (mRulesLock) {
535                        if (mRestrictPower != enabled) {
536                            mRestrictPower = enabled;
537                            updateRulesForRestrictPowerLocked();
538                            updateRulesForGlobalChangeLocked(true);
539                        }
540                    }
541                }
542            });
543            mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
544            mSystemReady = true;
545
546            // read policy from disk
547            readPolicyLocked();
548
549            if (addDefaultRestrictBackgroundWhitelistUids()) {
550                writePolicyLocked();
551            }
552
553            updateRulesForGlobalChangeLocked(false);
554            updateNotificationsLocked();
555        }
556
557        updateScreenOn();
558
559        try {
560            mActivityManager.registerUidObserver(mUidObserver,
561                    ActivityManager.UID_OBSERVER_PROCSTATE|ActivityManager.UID_OBSERVER_GONE);
562            mNetworkManager.registerObserver(mAlertObserver);
563        } catch (RemoteException e) {
564            // ignored; both services live in system_server
565        }
566
567        // TODO: traverse existing processes to know foreground state, or have
568        // activitymanager dispatch current state when new observer attached.
569
570        final IntentFilter screenFilter = new IntentFilter();
571        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
572        screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
573        mContext.registerReceiver(mScreenReceiver, screenFilter);
574
575        // listen for changes to power save whitelist
576        final IntentFilter whitelistFilter = new IntentFilter(
577                PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
578        mContext.registerReceiver(mPowerSaveWhitelistReceiver, whitelistFilter, null, mHandler);
579
580        DeviceIdleController.LocalService deviceIdleService
581                = LocalServices.getService(DeviceIdleController.LocalService.class);
582        deviceIdleService.setNetworkPolicyTempWhitelistCallback(mTempPowerSaveChangedCallback);
583
584        // watch for network interfaces to be claimed
585        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
586        mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
587
588        // listen for package changes to update policy
589        final IntentFilter packageFilter = new IntentFilter();
590        packageFilter.addAction(ACTION_PACKAGE_ADDED);
591        packageFilter.addDataScheme("package");
592        mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
593
594        // listen for UID changes to update policy
595        mContext.registerReceiver(
596                mUidRemovedReceiver, new IntentFilter(ACTION_UID_REMOVED), null, mHandler);
597
598        // listen for user changes to update policy
599        final IntentFilter userFilter = new IntentFilter();
600        userFilter.addAction(ACTION_USER_ADDED);
601        userFilter.addAction(ACTION_USER_REMOVED);
602        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
603
604        // listen for stats update events
605        final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
606        mContext.registerReceiver(
607                mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
608
609        // listen for restrict background changes from notifications
610        final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
611        mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler);
612
613        // listen for snooze warning from notifications
614        final IntentFilter snoozeWarningFilter = new IntentFilter(ACTION_SNOOZE_WARNING);
615        mContext.registerReceiver(mSnoozeWarningReceiver, snoozeWarningFilter,
616                MANAGE_NETWORK_POLICY, mHandler);
617
618        // listen for configured wifi networks to be removed
619        final IntentFilter wifiConfigFilter = new IntentFilter(CONFIGURED_NETWORKS_CHANGED_ACTION);
620        mContext.registerReceiver(mWifiConfigReceiver, wifiConfigFilter, null, mHandler);
621
622        // listen for wifi state changes to catch metered hint
623        final IntentFilter wifiStateFilter = new IntentFilter(
624                WifiManager.NETWORK_STATE_CHANGED_ACTION);
625        mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler);
626
627        mUsageStats.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
628
629    }
630
631    final private IUidObserver mUidObserver = new IUidObserver.Stub() {
632        @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
633            synchronized (mRulesLock) {
634                updateUidStateLocked(uid, procState);
635            }
636        }
637
638        @Override public void onUidGone(int uid) throws RemoteException {
639            synchronized (mRulesLock) {
640                removeUidStateLocked(uid);
641            }
642        }
643
644        @Override public void onUidActive(int uid) throws RemoteException {
645        }
646
647        @Override public void onUidIdle(int uid) throws RemoteException {
648        }
649    };
650
651    final private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() {
652        @Override
653        public void onReceive(Context context, Intent intent) {
654            // on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected
655            synchronized (mRulesLock) {
656                updatePowerSaveWhitelistLocked();
657                updateRulesForGlobalChangeLocked(false);
658            }
659        }
660    };
661
662    final private Runnable mTempPowerSaveChangedCallback = new Runnable() {
663        @Override
664        public void run() {
665            synchronized (mRulesLock) {
666                updatePowerSaveTempWhitelistLocked();
667                updateRulesForTempWhitelistChangeLocked();
668                purgePowerSaveTempWhitelistLocked();
669            }
670        }
671    };
672
673    final private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
674        @Override
675        public void onReceive(Context context, Intent intent) {
676            // screen-related broadcasts are protected by system, no need
677            // for permissions check.
678            mHandler.obtainMessage(MSG_SCREEN_ON_CHANGED).sendToTarget();
679        }
680    };
681
682    final private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
683        @Override
684        public void onReceive(Context context, Intent intent) {
685            // on background handler thread, and PACKAGE_ADDED is protected
686
687            final String action = intent.getAction();
688            final int uid = intent.getIntExtra(EXTRA_UID, -1);
689            if (uid == -1) return;
690
691            if (ACTION_PACKAGE_ADDED.equals(action)) {
692                // update rules for UID, since it might be subject to
693                // global background data policy
694                if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
695                synchronized (mRulesLock) {
696                    updateRestrictionRulesForUidLocked(uid);
697                }
698            }
699        }
700    };
701
702    final private BroadcastReceiver mUidRemovedReceiver = new BroadcastReceiver() {
703        @Override
704        public void onReceive(Context context, Intent intent) {
705            // on background handler thread, and UID_REMOVED is protected
706
707            final int uid = intent.getIntExtra(EXTRA_UID, -1);
708            if (uid == -1) return;
709
710            // remove any policy and update rules to clean up
711            if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
712            synchronized (mRulesLock) {
713                mUidPolicy.delete(uid);
714                updateRuleForRestrictBackgroundLocked(uid);
715                writePolicyLocked();
716            }
717        }
718    };
719
720    final private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
721        @Override
722        public void onReceive(Context context, Intent intent) {
723            // on background handler thread, and USER_ADDED and USER_REMOVED
724            // broadcasts are protected
725
726            final String action = intent.getAction();
727            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
728            if (userId == -1) return;
729
730            switch (action) {
731                case ACTION_USER_REMOVED:
732                case ACTION_USER_ADDED:
733                    synchronized (mRulesLock) {
734                        // Remove any persistable state for the given user; both cleaning up after a
735                        // USER_REMOVED, and one last sanity check during USER_ADDED
736                        removeUserStateLocked(userId);
737                        // Update global restrict for new user
738                        updateRulesForGlobalChangeLocked(true);
739                    }
740                    break;
741            }
742        }
743    };
744
745    /**
746     * Receiver that watches for {@link INetworkStatsService} updates, which we
747     * use to check against {@link NetworkPolicy#warningBytes}.
748     */
749    final private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() {
750        @Override
751        public void onReceive(Context context, Intent intent) {
752            // on background handler thread, and verified
753            // READ_NETWORK_USAGE_HISTORY permission above.
754
755            maybeRefreshTrustedTime();
756            synchronized (mRulesLock) {
757                updateNetworkEnabledLocked();
758                updateNotificationsLocked();
759            }
760        }
761    };
762
763    /**
764     * Receiver that watches for {@link Notification} control of
765     * {@link #mRestrictBackground}.
766     */
767    final private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() {
768        @Override
769        public void onReceive(Context context, Intent intent) {
770            // on background handler thread, and verified MANAGE_NETWORK_POLICY
771            // permission above.
772
773            setRestrictBackground(false);
774        }
775    };
776
777    /**
778     * Receiver that watches for {@link Notification} control of
779     * {@link NetworkPolicy#lastWarningSnooze}.
780     */
781    final private BroadcastReceiver mSnoozeWarningReceiver = new BroadcastReceiver() {
782        @Override
783        public void onReceive(Context context, Intent intent) {
784            // on background handler thread, and verified MANAGE_NETWORK_POLICY
785            // permission above.
786
787            final NetworkTemplate template = intent.getParcelableExtra(EXTRA_NETWORK_TEMPLATE);
788            performSnooze(template, TYPE_WARNING);
789        }
790    };
791
792    /**
793     * Receiver that watches for {@link WifiConfiguration} to be changed.
794     */
795    final private BroadcastReceiver mWifiConfigReceiver = new BroadcastReceiver() {
796        @Override
797        public void onReceive(Context context, Intent intent) {
798            // on background handler thread, and verified CONNECTIVITY_INTERNAL
799            // permission above.
800
801            final int reason = intent.getIntExtra(EXTRA_CHANGE_REASON, CHANGE_REASON_ADDED);
802            if (reason == CHANGE_REASON_REMOVED) {
803                final WifiConfiguration config = intent.getParcelableExtra(
804                        EXTRA_WIFI_CONFIGURATION);
805                if (config.SSID != null) {
806                    final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(config.SSID);
807                    synchronized (mRulesLock) {
808                        if (mNetworkPolicy.containsKey(template)) {
809                            mNetworkPolicy.remove(template);
810                            writePolicyLocked();
811                        }
812                    }
813                }
814            }
815        }
816    };
817
818    /**
819     * Receiver that watches {@link WifiInfo} state changes to infer metered
820     * state. Ignores hints when policy is user-defined.
821     */
822    final private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
823        @Override
824        public void onReceive(Context context, Intent intent) {
825            // on background handler thread, and verified CONNECTIVITY_INTERNAL
826            // permission above.
827
828            // ignore when not connected
829            final NetworkInfo netInfo = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
830            if (!netInfo.isConnected()) return;
831
832            final WifiInfo info = intent.getParcelableExtra(EXTRA_WIFI_INFO);
833            final boolean meteredHint = info.getMeteredHint();
834
835            final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(info.getSSID());
836            synchronized (mRulesLock) {
837                NetworkPolicy policy = mNetworkPolicy.get(template);
838                if (policy == null && meteredHint) {
839                    // policy doesn't exist, and AP is hinting that it's
840                    // metered: create an inferred policy.
841                    policy = newWifiPolicy(template, meteredHint);
842                    addNetworkPolicyLocked(policy);
843
844                } else if (policy != null && policy.inferred) {
845                    // policy exists, and was inferred: update its current
846                    // metered state.
847                    policy.metered = meteredHint;
848
849                    // since this is inferred for each wifi session, just update
850                    // rules without persisting.
851                    updateNetworkRulesLocked();
852                }
853            }
854        }
855    };
856
857    static NetworkPolicy newWifiPolicy(NetworkTemplate template, boolean metered) {
858        return new NetworkPolicy(template, CYCLE_NONE, Time.TIMEZONE_UTC,
859                WARNING_DISABLED, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER,
860                metered, true);
861    }
862
863    /**
864     * Observer that watches for {@link INetworkManagementService} alerts.
865     */
866    final private INetworkManagementEventObserver mAlertObserver
867            = new BaseNetworkObserver() {
868        @Override
869        public void limitReached(String limitName, String iface) {
870            // only someone like NMS should be calling us
871            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
872
873            if (!LIMIT_GLOBAL_ALERT.equals(limitName)) {
874                mHandler.obtainMessage(MSG_LIMIT_REACHED, iface).sendToTarget();
875            }
876        }
877    };
878
879    /**
880     * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
881     * to show visible notifications as needed.
882     */
883    void updateNotificationsLocked() {
884        if (LOGV) Slog.v(TAG, "updateNotificationsLocked()");
885
886        // keep track of previously active notifications
887        final ArraySet<String> beforeNotifs = new ArraySet<String>(mActiveNotifs);
888        mActiveNotifs.clear();
889
890        // TODO: when switching to kernel notifications, compute next future
891        // cycle boundary to recompute notifications.
892
893        // examine stats for each active policy
894        final long currentTime = currentTimeMillis();
895        for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
896            final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
897            // ignore policies that aren't relevant to user
898            if (!isTemplateRelevant(policy.template)) continue;
899            if (!policy.hasCycle()) continue;
900
901            final long start = computeLastCycleBoundary(currentTime, policy);
902            final long end = currentTime;
903            final long totalBytes = getTotalBytes(policy.template, start, end);
904
905            if (policy.isOverLimit(totalBytes)) {
906                if (policy.lastLimitSnooze >= start) {
907                    enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
908                } else {
909                    enqueueNotification(policy, TYPE_LIMIT, totalBytes);
910                    notifyOverLimitLocked(policy.template);
911                }
912
913            } else {
914                notifyUnderLimitLocked(policy.template);
915
916                if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start) {
917                    enqueueNotification(policy, TYPE_WARNING, totalBytes);
918                }
919            }
920        }
921
922        // cancel stale notifications that we didn't renew above
923        for (int i = beforeNotifs.size()-1; i >= 0; i--) {
924            final String tag = beforeNotifs.valueAt(i);
925            if (!mActiveNotifs.contains(tag)) {
926                cancelNotification(tag);
927            }
928        }
929    }
930
931    /**
932     * Test if given {@link NetworkTemplate} is relevant to user based on
933     * current device state, such as when
934     * {@link TelephonyManager#getSubscriberId()} matches. This is regardless of
935     * data connection status.
936     */
937    private boolean isTemplateRelevant(NetworkTemplate template) {
938        if (template.isMatchRuleMobile()) {
939            final TelephonyManager tele = TelephonyManager.from(mContext);
940            final SubscriptionManager sub = SubscriptionManager.from(mContext);
941
942            // Mobile template is relevant when any active subscriber matches
943            final int[] subIds = sub.getActiveSubscriptionIdList();
944            for (int subId : subIds) {
945                final String subscriberId = tele.getSubscriberId(subId);
946                final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
947                        TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
948                if (template.matches(probeIdent)) {
949                    return true;
950                }
951            }
952            return false;
953        } else {
954            return true;
955        }
956    }
957
958    /**
959     * Notify that given {@link NetworkTemplate} is over
960     * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
961     */
962    private void notifyOverLimitLocked(NetworkTemplate template) {
963        if (!mOverLimitNotified.contains(template)) {
964            mContext.startActivity(buildNetworkOverLimitIntent(template));
965            mOverLimitNotified.add(template);
966        }
967    }
968
969    private void notifyUnderLimitLocked(NetworkTemplate template) {
970        mOverLimitNotified.remove(template);
971    }
972
973    /**
974     * Build unique tag that identifies an active {@link NetworkPolicy}
975     * notification of a specific type, like {@link #TYPE_LIMIT}.
976     */
977    private String buildNotificationTag(NetworkPolicy policy, int type) {
978        return TAG + ":" + policy.template.hashCode() + ":" + type;
979    }
980
981    /**
982     * Show notification for combined {@link NetworkPolicy} and specific type,
983     * like {@link #TYPE_LIMIT}. Okay to call multiple times.
984     */
985    private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
986        final String tag = buildNotificationTag(policy, type);
987        final Notification.Builder builder = new Notification.Builder(mContext);
988        builder.setOnlyAlertOnce(true);
989        builder.setWhen(0L);
990        builder.setColor(mContext.getColor(
991                com.android.internal.R.color.system_notification_accent_color));
992
993        final Resources res = mContext.getResources();
994        switch (type) {
995            case TYPE_WARNING: {
996                final CharSequence title = res.getText(R.string.data_usage_warning_title);
997                final CharSequence body = res.getString(R.string.data_usage_warning_body);
998
999                builder.setSmallIcon(R.drawable.stat_notify_error);
1000                builder.setTicker(title);
1001                builder.setContentTitle(title);
1002                builder.setContentText(body);
1003
1004                final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template);
1005                builder.setDeleteIntent(PendingIntent.getBroadcast(
1006                        mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
1007
1008                final Intent viewIntent = buildViewDataUsageIntent(policy.template);
1009                builder.setContentIntent(PendingIntent.getActivity(
1010                        mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT));
1011
1012                break;
1013            }
1014            case TYPE_LIMIT: {
1015                final CharSequence body = res.getText(R.string.data_usage_limit_body);
1016
1017                final CharSequence title;
1018                int icon = R.drawable.stat_notify_disabled_data;
1019                switch (policy.template.getMatchRule()) {
1020                    case MATCH_MOBILE_3G_LOWER:
1021                        title = res.getText(R.string.data_usage_3g_limit_title);
1022                        break;
1023                    case MATCH_MOBILE_4G:
1024                        title = res.getText(R.string.data_usage_4g_limit_title);
1025                        break;
1026                    case MATCH_MOBILE_ALL:
1027                        title = res.getText(R.string.data_usage_mobile_limit_title);
1028                        break;
1029                    case MATCH_WIFI:
1030                        title = res.getText(R.string.data_usage_wifi_limit_title);
1031                        icon = R.drawable.stat_notify_error;
1032                        break;
1033                    default:
1034                        title = null;
1035                        break;
1036                }
1037
1038                builder.setOngoing(true);
1039                builder.setSmallIcon(icon);
1040                builder.setTicker(title);
1041                builder.setContentTitle(title);
1042                builder.setContentText(body);
1043
1044                final Intent intent = buildNetworkOverLimitIntent(policy.template);
1045                builder.setContentIntent(PendingIntent.getActivity(
1046                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
1047                break;
1048            }
1049            case TYPE_LIMIT_SNOOZED: {
1050                final long overBytes = totalBytes - policy.limitBytes;
1051                final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body,
1052                        Formatter.formatFileSize(mContext, overBytes));
1053
1054                final CharSequence title;
1055                switch (policy.template.getMatchRule()) {
1056                    case MATCH_MOBILE_3G_LOWER:
1057                        title = res.getText(R.string.data_usage_3g_limit_snoozed_title);
1058                        break;
1059                    case MATCH_MOBILE_4G:
1060                        title = res.getText(R.string.data_usage_4g_limit_snoozed_title);
1061                        break;
1062                    case MATCH_MOBILE_ALL:
1063                        title = res.getText(R.string.data_usage_mobile_limit_snoozed_title);
1064                        break;
1065                    case MATCH_WIFI:
1066                        title = res.getText(R.string.data_usage_wifi_limit_snoozed_title);
1067                        break;
1068                    default:
1069                        title = null;
1070                        break;
1071                }
1072
1073                builder.setOngoing(true);
1074                builder.setSmallIcon(R.drawable.stat_notify_error);
1075                builder.setTicker(title);
1076                builder.setContentTitle(title);
1077                builder.setContentText(body);
1078
1079                final Intent intent = buildViewDataUsageIntent(policy.template);
1080                builder.setContentIntent(PendingIntent.getActivity(
1081                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
1082                break;
1083            }
1084        }
1085
1086        // TODO: move to NotificationManager once we can mock it
1087        try {
1088            final String packageName = mContext.getPackageName();
1089            final int[] idReceived = new int[1];
1090            mNotifManager.enqueueNotificationWithTag(
1091                    packageName, packageName, tag, 0x0, builder.getNotification(), idReceived,
1092                    UserHandle.USER_ALL);
1093            mActiveNotifs.add(tag);
1094        } catch (RemoteException e) {
1095            // ignored; service lives in system_server
1096        }
1097    }
1098
1099    private void cancelNotification(String tag) {
1100        // TODO: move to NotificationManager once we can mock it
1101        try {
1102            final String packageName = mContext.getPackageName();
1103            mNotifManager.cancelNotificationWithTag(
1104                    packageName, tag, 0x0, UserHandle.USER_ALL);
1105        } catch (RemoteException e) {
1106            // ignored; service lives in system_server
1107        }
1108    }
1109
1110    /**
1111     * Receiver that watches for {@link IConnectivityManager} to claim network
1112     * interfaces. Used to apply {@link NetworkPolicy} to matching networks.
1113     */
1114    private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
1115        @Override
1116        public void onReceive(Context context, Intent intent) {
1117            // on background handler thread, and verified CONNECTIVITY_INTERNAL
1118            // permission above.
1119
1120            maybeRefreshTrustedTime();
1121            synchronized (mRulesLock) {
1122                ensureActiveMobilePolicyLocked();
1123                normalizePoliciesLocked();
1124                updateNetworkEnabledLocked();
1125                updateNetworkRulesLocked();
1126                updateNotificationsLocked();
1127            }
1128        }
1129    };
1130
1131    /**
1132     * Proactively control network data connections when they exceed
1133     * {@link NetworkPolicy#limitBytes}.
1134     */
1135    void updateNetworkEnabledLocked() {
1136        if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()");
1137
1138        // TODO: reset any policy-disabled networks when any policy is removed
1139        // completely, which is currently rare case.
1140
1141        final long currentTime = currentTimeMillis();
1142        for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
1143            final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
1144            // shortcut when policy has no limit
1145            if (policy.limitBytes == LIMIT_DISABLED || !policy.hasCycle()) {
1146                setNetworkTemplateEnabled(policy.template, true);
1147                continue;
1148            }
1149
1150            final long start = computeLastCycleBoundary(currentTime, policy);
1151            final long end = currentTime;
1152            final long totalBytes = getTotalBytes(policy.template, start, end);
1153
1154            // disable data connection when over limit and not snoozed
1155            final boolean overLimitWithoutSnooze = policy.isOverLimit(totalBytes)
1156                    && policy.lastLimitSnooze < start;
1157            final boolean networkEnabled = !overLimitWithoutSnooze;
1158
1159            setNetworkTemplateEnabled(policy.template, networkEnabled);
1160        }
1161    }
1162
1163    /**
1164     * Proactively disable networks that match the given
1165     * {@link NetworkTemplate}.
1166     */
1167    private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
1168        // TODO: reach into ConnectivityManager to proactively disable bringing
1169        // up this network, since we know that traffic will be blocked.
1170    }
1171
1172    /**
1173     * Examine all connected {@link NetworkState}, looking for
1174     * {@link NetworkPolicy} that need to be enforced. When matches found, set
1175     * remaining quota based on usage cycle and historical stats.
1176     */
1177    void updateNetworkRulesLocked() {
1178        if (LOGV) Slog.v(TAG, "updateNetworkRulesLocked()");
1179
1180        final NetworkState[] states;
1181        try {
1182            states = mConnManager.getAllNetworkState();
1183        } catch (RemoteException e) {
1184            // ignored; service lives in system_server
1185            return;
1186        }
1187
1188        // First, generate identities of all connected networks so we can
1189        // quickly compare them against all defined policies below.
1190        final ArrayList<Pair<String, NetworkIdentity>> connIdents = new ArrayList<>(states.length);
1191        final ArraySet<String> connIfaces = new ArraySet<String>(states.length);
1192        for (NetworkState state : states) {
1193            if (state.networkInfo != null && state.networkInfo.isConnected()) {
1194                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
1195
1196                final String baseIface = state.linkProperties.getInterfaceName();
1197                if (baseIface != null) {
1198                    connIdents.add(Pair.create(baseIface, ident));
1199                }
1200
1201                // Stacked interfaces are considered to have same identity as
1202                // their parent network.
1203                final List<LinkProperties> stackedLinks = state.linkProperties.getStackedLinks();
1204                for (LinkProperties stackedLink : stackedLinks) {
1205                    final String stackedIface = stackedLink.getInterfaceName();
1206                    if (stackedIface != null) {
1207                        connIdents.add(Pair.create(stackedIface, ident));
1208                    }
1209                }
1210            }
1211        }
1212
1213        // Apply policies against all connected interfaces found above
1214        mNetworkRules.clear();
1215        final ArrayList<String> ifaceList = Lists.newArrayList();
1216        for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
1217            final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
1218
1219            ifaceList.clear();
1220            for (int j = connIdents.size() - 1; j >= 0; j--) {
1221                final Pair<String, NetworkIdentity> ident = connIdents.get(j);
1222                if (policy.template.matches(ident.second)) {
1223                    ifaceList.add(ident.first);
1224                }
1225            }
1226
1227            if (ifaceList.size() > 0) {
1228                final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]);
1229                mNetworkRules.put(policy, ifaces);
1230            }
1231        }
1232
1233        long lowestRule = Long.MAX_VALUE;
1234        final ArraySet<String> newMeteredIfaces = new ArraySet<String>(states.length);
1235
1236        // apply each policy that we found ifaces for; compute remaining data
1237        // based on current cycle and historical stats, and push to kernel.
1238        final long currentTime = currentTimeMillis();
1239        for (int i = mNetworkRules.size()-1; i >= 0; i--) {
1240            final NetworkPolicy policy = mNetworkRules.keyAt(i);
1241            final String[] ifaces = mNetworkRules.valueAt(i);
1242
1243            final long start;
1244            final long totalBytes;
1245            if (policy.hasCycle()) {
1246                start = computeLastCycleBoundary(currentTime, policy);
1247                totalBytes = getTotalBytes(policy.template, start, currentTime);
1248            } else {
1249                start = Long.MAX_VALUE;
1250                totalBytes = 0;
1251            }
1252
1253            if (LOGD) {
1254                Slog.d(TAG, "applying policy " + policy + " to ifaces " + Arrays.toString(ifaces));
1255            }
1256
1257            final boolean hasWarning = policy.warningBytes != LIMIT_DISABLED;
1258            final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
1259            if (hasLimit || policy.metered) {
1260                final long quotaBytes;
1261                if (!hasLimit) {
1262                    // metered network, but no policy limit; we still need to
1263                    // restrict apps, so push really high quota.
1264                    quotaBytes = Long.MAX_VALUE;
1265                } else if (policy.lastLimitSnooze >= start) {
1266                    // snoozing past quota, but we still need to restrict apps,
1267                    // so push really high quota.
1268                    quotaBytes = Long.MAX_VALUE;
1269                } else {
1270                    // remaining "quota" bytes are based on total usage in
1271                    // current cycle. kernel doesn't like 0-byte rules, so we
1272                    // set 1-byte quota and disable the radio later.
1273                    quotaBytes = Math.max(1, policy.limitBytes - totalBytes);
1274                }
1275
1276                if (ifaces.length > 1) {
1277                    // TODO: switch to shared quota once NMS supports
1278                    Slog.w(TAG, "shared quota unsupported; generating rule for each iface");
1279                }
1280
1281                for (String iface : ifaces) {
1282                    // long quotaBytes split up into two ints to fit in message
1283                    mHandler.obtainMessage(MSG_UPDATE_INTERFACE_QUOTA,
1284                            (int) (quotaBytes >> 32), (int) (quotaBytes & 0xFFFFFFFF), iface)
1285                            .sendToTarget();
1286                    newMeteredIfaces.add(iface);
1287                }
1288            }
1289
1290            // keep track of lowest warning or limit of active policies
1291            if (hasWarning && policy.warningBytes < lowestRule) {
1292                lowestRule = policy.warningBytes;
1293            }
1294            if (hasLimit && policy.limitBytes < lowestRule) {
1295                lowestRule = policy.limitBytes;
1296            }
1297        }
1298
1299        for (int i = connIfaces.size()-1; i >= 0; i--) {
1300            String iface = connIfaces.valueAt(i);
1301            // long quotaBytes split up into two ints to fit in message
1302            mHandler.obtainMessage(MSG_UPDATE_INTERFACE_QUOTA,
1303                    (int) (Long.MAX_VALUE >> 32), (int) (Long.MAX_VALUE & 0xFFFFFFFF), iface)
1304                    .sendToTarget();
1305            newMeteredIfaces.add(iface);
1306        }
1307
1308        mHandler.obtainMessage(MSG_ADVISE_PERSIST_THRESHOLD, lowestRule).sendToTarget();
1309
1310        // remove quota on any trailing interfaces
1311        for (int i = mMeteredIfaces.size() - 1; i >= 0; i--) {
1312            final String iface = mMeteredIfaces.valueAt(i);
1313            if (!newMeteredIfaces.contains(iface)) {
1314                mHandler.obtainMessage(MSG_REMOVE_INTERFACE_QUOTA, iface)
1315                        .sendToTarget();
1316            }
1317        }
1318        mMeteredIfaces = newMeteredIfaces;
1319
1320        final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
1321        mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
1322    }
1323
1324    /**
1325     * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
1326     * have at least a default mobile policy defined.
1327     */
1328    private void ensureActiveMobilePolicyLocked() {
1329        if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
1330        if (mSuppressDefaultPolicy) return;
1331
1332        final TelephonyManager tele = TelephonyManager.from(mContext);
1333        final SubscriptionManager sub = SubscriptionManager.from(mContext);
1334
1335        final int[] subIds = sub.getActiveSubscriptionIdList();
1336        for (int subId : subIds) {
1337            final String subscriberId = tele.getSubscriberId(subId);
1338            ensureActiveMobilePolicyLocked(subscriberId);
1339        }
1340    }
1341
1342    private void ensureActiveMobilePolicyLocked(String subscriberId) {
1343        // Poke around to see if we already have a policy
1344        final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
1345                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
1346        for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
1347            final NetworkTemplate template = mNetworkPolicy.keyAt(i);
1348            if (template.matches(probeIdent)) {
1349                if (LOGD) {
1350                    Slog.d(TAG, "Found template " + template + " which matches subscriber "
1351                            + NetworkIdentity.scrubSubscriberId(subscriberId));
1352                }
1353                return;
1354            }
1355        }
1356
1357        Slog.i(TAG, "No policy for subscriber " + NetworkIdentity.scrubSubscriberId(subscriberId)
1358                + "; generating default policy");
1359
1360        // Build default mobile policy, and assume usage cycle starts today
1361        final long warningBytes = mContext.getResources().getInteger(
1362                com.android.internal.R.integer.config_networkPolicyDefaultWarning) * MB_IN_BYTES;
1363
1364        final Time time = new Time();
1365        time.setToNow();
1366
1367        final int cycleDay = time.monthDay;
1368        final String cycleTimezone = time.timezone;
1369
1370        final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
1371        final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone,
1372                warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true);
1373        addNetworkPolicyLocked(policy);
1374    }
1375
1376    private void readPolicyLocked() {
1377        if (LOGV) Slog.v(TAG, "readPolicyLocked()");
1378
1379        // clear any existing policy and read from disk
1380        mNetworkPolicy.clear();
1381        mUidPolicy.clear();
1382
1383        FileInputStream fis = null;
1384        try {
1385            fis = mPolicyFile.openRead();
1386            final XmlPullParser in = Xml.newPullParser();
1387            in.setInput(fis, StandardCharsets.UTF_8.name());
1388
1389            int type;
1390            int version = VERSION_INIT;
1391            boolean insideWhitelist = false;
1392            while ((type = in.next()) != END_DOCUMENT) {
1393                final String tag = in.getName();
1394                if (type == START_TAG) {
1395                    if (TAG_POLICY_LIST.equals(tag)) {
1396                        final boolean oldValue = mRestrictBackground;
1397                        version = readIntAttribute(in, ATTR_VERSION);
1398                        if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) {
1399                            mRestrictBackground = readBooleanAttribute(
1400                                    in, ATTR_RESTRICT_BACKGROUND);
1401                        } else {
1402                            mRestrictBackground = false;
1403                        }
1404                        if (mRestrictBackground != oldValue) {
1405                            // Some early services may have read the default value,
1406                            // so notify them that it's changed
1407                            mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED,
1408                                    mRestrictBackground ? 1 : 0, 0).sendToTarget();
1409                        }
1410
1411                    } else if (TAG_NETWORK_POLICY.equals(tag)) {
1412                        final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
1413                        final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
1414                        final String networkId;
1415                        if (version >= VERSION_ADDED_NETWORK_ID) {
1416                            networkId = in.getAttributeValue(null, ATTR_NETWORK_ID);
1417                        } else {
1418                            networkId = null;
1419                        }
1420                        final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
1421                        final String cycleTimezone;
1422                        if (version >= VERSION_ADDED_TIMEZONE) {
1423                            cycleTimezone = in.getAttributeValue(null, ATTR_CYCLE_TIMEZONE);
1424                        } else {
1425                            cycleTimezone = Time.TIMEZONE_UTC;
1426                        }
1427                        final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
1428                        final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
1429                        final long lastLimitSnooze;
1430                        if (version >= VERSION_SPLIT_SNOOZE) {
1431                            lastLimitSnooze = readLongAttribute(in, ATTR_LAST_LIMIT_SNOOZE);
1432                        } else if (version >= VERSION_ADDED_SNOOZE) {
1433                            lastLimitSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
1434                        } else {
1435                            lastLimitSnooze = SNOOZE_NEVER;
1436                        }
1437                        final boolean metered;
1438                        if (version >= VERSION_ADDED_METERED) {
1439                            metered = readBooleanAttribute(in, ATTR_METERED);
1440                        } else {
1441                            switch (networkTemplate) {
1442                                case MATCH_MOBILE_3G_LOWER:
1443                                case MATCH_MOBILE_4G:
1444                                case MATCH_MOBILE_ALL:
1445                                    metered = true;
1446                                    break;
1447                                default:
1448                                    metered = false;
1449                            }
1450                        }
1451                        final long lastWarningSnooze;
1452                        if (version >= VERSION_SPLIT_SNOOZE) {
1453                            lastWarningSnooze = readLongAttribute(in, ATTR_LAST_WARNING_SNOOZE);
1454                        } else {
1455                            lastWarningSnooze = SNOOZE_NEVER;
1456                        }
1457                        final boolean inferred;
1458                        if (version >= VERSION_ADDED_INFERRED) {
1459                            inferred = readBooleanAttribute(in, ATTR_INFERRED);
1460                        } else {
1461                            inferred = false;
1462                        }
1463
1464                        final NetworkTemplate template = new NetworkTemplate(networkTemplate,
1465                                subscriberId, networkId);
1466                        if (template.isPersistable()) {
1467                            mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay,
1468                                    cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
1469                                    lastLimitSnooze, metered, inferred));
1470                        }
1471
1472                    } else if (TAG_UID_POLICY.equals(tag)) {
1473                        final int uid = readIntAttribute(in, ATTR_UID);
1474                        final int policy = readIntAttribute(in, ATTR_POLICY);
1475
1476                        if (UserHandle.isApp(uid)) {
1477                            setUidPolicyUncheckedLocked(uid, policy, false);
1478                        } else {
1479                            Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
1480                        }
1481                    } else if (TAG_APP_POLICY.equals(tag)) {
1482                        final int appId = readIntAttribute(in, ATTR_APP_ID);
1483                        final int policy = readIntAttribute(in, ATTR_POLICY);
1484
1485                        // TODO: set for other users during upgrade
1486                        // app policy is deprecated so this is only used in pre system user split.
1487                        final int uid = UserHandle.getUid(UserHandle.USER_SYSTEM, appId);
1488                        if (UserHandle.isApp(uid)) {
1489                            setUidPolicyUncheckedLocked(uid, policy, false);
1490                        } else {
1491                            Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
1492                        }
1493                    } else if (TAG_WHITELIST.equals(tag)) {
1494                        insideWhitelist = true;
1495                    } else if (TAG_RESTRICT_BACKGROUND.equals(tag) && insideWhitelist) {
1496                        final int uid = readIntAttribute(in, ATTR_UID);
1497                        mRestrictBackgroundWhitelistUids.put(uid, true);
1498                    } else if (TAG_REVOKED_RESTRICT_BACKGROUND.equals(tag) && insideWhitelist) {
1499                        final int uid = readIntAttribute(in, ATTR_UID);
1500                        mRestrictBackgroundWhitelistRevokedUids.put(uid, true);
1501                    }
1502                } else if (type == END_TAG) {
1503                    if (TAG_WHITELIST.equals(tag)) {
1504                        insideWhitelist = false;
1505                    }
1506
1507                }
1508            }
1509
1510        } catch (FileNotFoundException e) {
1511            // missing policy is okay, probably first boot
1512            upgradeLegacyBackgroundData();
1513        } catch (IOException e) {
1514            Log.wtf(TAG, "problem reading network policy", e);
1515        } catch (XmlPullParserException e) {
1516            Log.wtf(TAG, "problem reading network policy", e);
1517        } finally {
1518            IoUtils.closeQuietly(fis);
1519        }
1520    }
1521
1522    /**
1523     * Upgrade legacy background data flags, notifying listeners of one last
1524     * change to always-true.
1525     */
1526    private void upgradeLegacyBackgroundData() {
1527        mRestrictBackground = Settings.Secure.getInt(
1528                mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1;
1529
1530        // kick off one last broadcast if restricted
1531        if (mRestrictBackground) {
1532            final Intent broadcast = new Intent(
1533                    ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
1534            mContext.sendBroadcastAsUser(broadcast, UserHandle.ALL);
1535        }
1536    }
1537
1538    void writePolicyLocked() {
1539        if (LOGV) Slog.v(TAG, "writePolicyLocked()");
1540
1541        FileOutputStream fos = null;
1542        try {
1543            fos = mPolicyFile.startWrite();
1544
1545            XmlSerializer out = new FastXmlSerializer();
1546            out.setOutput(fos, StandardCharsets.UTF_8.name());
1547            out.startDocument(null, true);
1548
1549            out.startTag(null, TAG_POLICY_LIST);
1550            writeIntAttribute(out, ATTR_VERSION, VERSION_LATEST);
1551            writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
1552
1553            // write all known network policies
1554            for (int i = 0; i < mNetworkPolicy.size(); i++) {
1555                final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
1556                final NetworkTemplate template = policy.template;
1557                if (!template.isPersistable()) continue;
1558
1559                out.startTag(null, TAG_NETWORK_POLICY);
1560                writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
1561                final String subscriberId = template.getSubscriberId();
1562                if (subscriberId != null) {
1563                    out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
1564                }
1565                final String networkId = template.getNetworkId();
1566                if (networkId != null) {
1567                    out.attribute(null, ATTR_NETWORK_ID, networkId);
1568                }
1569                writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
1570                out.attribute(null, ATTR_CYCLE_TIMEZONE, policy.cycleTimezone);
1571                writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
1572                writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
1573                writeLongAttribute(out, ATTR_LAST_WARNING_SNOOZE, policy.lastWarningSnooze);
1574                writeLongAttribute(out, ATTR_LAST_LIMIT_SNOOZE, policy.lastLimitSnooze);
1575                writeBooleanAttribute(out, ATTR_METERED, policy.metered);
1576                writeBooleanAttribute(out, ATTR_INFERRED, policy.inferred);
1577                out.endTag(null, TAG_NETWORK_POLICY);
1578            }
1579
1580            // write all known uid policies
1581            for (int i = 0; i < mUidPolicy.size(); i++) {
1582                final int uid = mUidPolicy.keyAt(i);
1583                final int policy = mUidPolicy.valueAt(i);
1584
1585                // skip writing empty policies
1586                if (policy == POLICY_NONE) continue;
1587
1588                out.startTag(null, TAG_UID_POLICY);
1589                writeIntAttribute(out, ATTR_UID, uid);
1590                writeIntAttribute(out, ATTR_POLICY, policy);
1591                out.endTag(null, TAG_UID_POLICY);
1592            }
1593
1594            out.endTag(null, TAG_POLICY_LIST);
1595
1596            // write all whitelists
1597            out.startTag(null, TAG_WHITELIST);
1598
1599            // restrict background whitelist
1600            int size = mRestrictBackgroundWhitelistUids.size();
1601            for (int i = 0; i < size; i++) {
1602                final int uid = mRestrictBackgroundWhitelistUids.keyAt(i);
1603                out.startTag(null, TAG_RESTRICT_BACKGROUND);
1604                writeIntAttribute(out, ATTR_UID, uid);
1605                out.endTag(null, TAG_RESTRICT_BACKGROUND);
1606            }
1607
1608            // revoked restrict background whitelist
1609            size = mRestrictBackgroundWhitelistRevokedUids.size();
1610            for (int i = 0; i < size; i++) {
1611                final int uid = mRestrictBackgroundWhitelistRevokedUids.keyAt(i);
1612                out.startTag(null, TAG_REVOKED_RESTRICT_BACKGROUND);
1613                writeIntAttribute(out, ATTR_UID, uid);
1614                out.endTag(null, TAG_REVOKED_RESTRICT_BACKGROUND);
1615            }
1616
1617            out.endTag(null, TAG_WHITELIST);
1618
1619            out.endDocument();
1620
1621            mPolicyFile.finishWrite(fos);
1622        } catch (IOException e) {
1623            if (fos != null) {
1624                mPolicyFile.failWrite(fos);
1625            }
1626        }
1627    }
1628
1629    @Override
1630    public void setUidPolicy(int uid, int policy) {
1631        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1632
1633        if (!UserHandle.isApp(uid)) {
1634            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
1635        }
1636
1637        synchronized (mRulesLock) {
1638            final long token = Binder.clearCallingIdentity();
1639            try {
1640                final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
1641                if (oldPolicy != policy) {
1642                    setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
1643                }
1644            } finally {
1645                Binder.restoreCallingIdentity(token);
1646            }
1647        }
1648    }
1649
1650    @Override
1651    public void addUidPolicy(int uid, int policy) {
1652        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1653
1654        if (!UserHandle.isApp(uid)) {
1655            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
1656        }
1657
1658        synchronized (mRulesLock) {
1659            final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
1660            policy |= oldPolicy;
1661            if (oldPolicy != policy) {
1662                setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
1663            }
1664        }
1665    }
1666
1667    @Override
1668    public void removeUidPolicy(int uid, int policy) {
1669        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1670
1671        if (!UserHandle.isApp(uid)) {
1672            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
1673        }
1674
1675        synchronized (mRulesLock) {
1676            final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
1677            policy = oldPolicy & ~policy;
1678            if (oldPolicy != policy) {
1679                setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
1680            }
1681        }
1682    }
1683
1684    private void setUidPolicyUncheckedLocked(int uid, int oldPolicy, int policy, boolean persist) {
1685        setUidPolicyUncheckedLocked(uid, policy, persist);
1686
1687        // Checks if app was added or removed to the blacklist.
1688        if ((oldPolicy == POLICY_NONE && policy == POLICY_REJECT_METERED_BACKGROUND)
1689                || (oldPolicy == POLICY_REJECT_METERED_BACKGROUND && policy == POLICY_NONE)) {
1690            mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, 1, null)
1691                    .sendToTarget();
1692        }
1693    }
1694
1695    private void setUidPolicyUncheckedLocked(int uid, int policy, boolean persist) {
1696        mUidPolicy.put(uid, policy);
1697
1698        // uid policy changed, recompute rules and persist policy.
1699        updateRuleForRestrictBackgroundLocked(uid);
1700        if (persist) {
1701            writePolicyLocked();
1702        }
1703    }
1704
1705    @Override
1706    public int getUidPolicy(int uid) {
1707        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1708
1709        synchronized (mRulesLock) {
1710            return mUidPolicy.get(uid, POLICY_NONE);
1711        }
1712    }
1713
1714    @Override
1715    public int[] getUidsWithPolicy(int policy) {
1716        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1717
1718        int[] uids = new int[0];
1719        synchronized (mRulesLock) {
1720            for (int i = 0; i < mUidPolicy.size(); i++) {
1721                final int uid = mUidPolicy.keyAt(i);
1722                final int uidPolicy = mUidPolicy.valueAt(i);
1723                if (uidPolicy == policy) {
1724                    uids = appendInt(uids, uid);
1725                }
1726            }
1727        }
1728        return uids;
1729    }
1730
1731    /**
1732     * Remove any persistable state associated with given {@link UserHandle}, persisting
1733     * if any changes are made.
1734     */
1735    void removeUserStateLocked(int userId) {
1736        if (LOGV) Slog.v(TAG, "removeUserStateLocked()");
1737        boolean writePolicy = false;
1738
1739        // Remove entries from restricted background UID whitelist
1740        int[] wlUids = new int[0];
1741        for (int i = 0; i < mRestrictBackgroundWhitelistUids.size(); i++) {
1742            final int uid = mRestrictBackgroundWhitelistUids.keyAt(i);
1743            if (UserHandle.getUserId(uid) == userId) {
1744                wlUids = appendInt(wlUids, uid);
1745            }
1746        }
1747
1748        if (wlUids.length > 0) {
1749            for (int uid : wlUids) {
1750                removeRestrictBackgroundWhitelistedUidLocked(uid, false, false);
1751            }
1752            writePolicy = true;
1753        }
1754        // Remove associated UID policies
1755        int[] uids = new int[0];
1756        for (int i = 0; i < mUidPolicy.size(); i++) {
1757            final int uid = mUidPolicy.keyAt(i);
1758            if (UserHandle.getUserId(uid) == userId) {
1759                uids = appendInt(uids, uid);
1760            }
1761        }
1762
1763        if (uids.length > 0) {
1764            for (int uid : uids) {
1765                mUidPolicy.delete(uid);
1766            }
1767            writePolicy = true;
1768        }
1769
1770        updateRulesForGlobalChangeLocked(true);
1771
1772        if (writePolicy) {
1773            writePolicyLocked();
1774        }
1775    }
1776
1777    @Override
1778    public void setConnectivityListener(INetworkPolicyListener listener) {
1779        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1780        if (mConnectivityListener != null) {
1781            throw new IllegalStateException("Connectivity listener already registered");
1782        }
1783        mConnectivityListener = listener;
1784    }
1785
1786    @Override
1787    public void registerListener(INetworkPolicyListener listener) {
1788        // TODO: create permission for observing network policy
1789        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1790        mListeners.register(listener);
1791    }
1792
1793    @Override
1794    public void unregisterListener(INetworkPolicyListener listener) {
1795        // TODO: create permission for observing network policy
1796        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1797        mListeners.unregister(listener);
1798    }
1799
1800    @Override
1801    public void setNetworkPolicies(NetworkPolicy[] policies) {
1802        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1803
1804        final long token = Binder.clearCallingIdentity();
1805        try {
1806            maybeRefreshTrustedTime();
1807            synchronized (mRulesLock) {
1808                normalizePoliciesLocked(policies);
1809                updateNetworkEnabledLocked();
1810                updateNetworkRulesLocked();
1811                updateNotificationsLocked();
1812                writePolicyLocked();
1813            }
1814        } finally {
1815            Binder.restoreCallingIdentity(token);
1816        }
1817    }
1818
1819    void addNetworkPolicyLocked(NetworkPolicy policy) {
1820        NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName());
1821        policies = ArrayUtils.appendElement(NetworkPolicy.class, policies, policy);
1822        setNetworkPolicies(policies);
1823    }
1824
1825    @Override
1826    public NetworkPolicy[] getNetworkPolicies(String callingPackage) {
1827        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1828        try {
1829            mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, TAG);
1830            // SKIP checking run-time OP_READ_PHONE_STATE since caller or self has PRIVILEGED
1831            // permission
1832        } catch (SecurityException e) {
1833            mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
1834
1835            if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
1836                    callingPackage) != AppOpsManager.MODE_ALLOWED) {
1837                return new NetworkPolicy[0];
1838            }
1839        }
1840
1841        synchronized (mRulesLock) {
1842            final int size = mNetworkPolicy.size();
1843            final NetworkPolicy[] policies = new NetworkPolicy[size];
1844            for (int i = 0; i < size; i++) {
1845                policies[i] = mNetworkPolicy.valueAt(i);
1846            }
1847            return policies;
1848        }
1849    }
1850
1851    private void normalizePoliciesLocked() {
1852        normalizePoliciesLocked(getNetworkPolicies(mContext.getOpPackageName()));
1853    }
1854
1855    private void normalizePoliciesLocked(NetworkPolicy[] policies) {
1856        final TelephonyManager tele = TelephonyManager.from(mContext);
1857        final String[] merged = tele.getMergedSubscriberIds();
1858
1859        mNetworkPolicy.clear();
1860        for (NetworkPolicy policy : policies) {
1861            // When two normalized templates conflict, prefer the most
1862            // restrictive policy
1863            policy.template = NetworkTemplate.normalize(policy.template, merged);
1864            final NetworkPolicy existing = mNetworkPolicy.get(policy.template);
1865            if (existing == null || existing.compareTo(policy) > 0) {
1866                if (existing != null) {
1867                    Slog.d(TAG, "Normalization replaced " + existing + " with " + policy);
1868                }
1869                mNetworkPolicy.put(policy.template, policy);
1870            }
1871        }
1872    }
1873
1874    @Override
1875    public void snoozeLimit(NetworkTemplate template) {
1876        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1877
1878        final long token = Binder.clearCallingIdentity();
1879        try {
1880            performSnooze(template, TYPE_LIMIT);
1881        } finally {
1882            Binder.restoreCallingIdentity(token);
1883        }
1884    }
1885
1886    void performSnooze(NetworkTemplate template, int type) {
1887        maybeRefreshTrustedTime();
1888        final long currentTime = currentTimeMillis();
1889        synchronized (mRulesLock) {
1890            // find and snooze local policy that matches
1891            final NetworkPolicy policy = mNetworkPolicy.get(template);
1892            if (policy == null) {
1893                throw new IllegalArgumentException("unable to find policy for " + template);
1894            }
1895
1896            switch (type) {
1897                case TYPE_WARNING:
1898                    policy.lastWarningSnooze = currentTime;
1899                    break;
1900                case TYPE_LIMIT:
1901                    policy.lastLimitSnooze = currentTime;
1902                    break;
1903                default:
1904                    throw new IllegalArgumentException("unexpected type");
1905            }
1906
1907            normalizePoliciesLocked();
1908            updateNetworkEnabledLocked();
1909            updateNetworkRulesLocked();
1910            updateNotificationsLocked();
1911            writePolicyLocked();
1912        }
1913    }
1914
1915    @Override
1916    public void onTetheringChanged(String iface, boolean tethering) {
1917        // No need to enforce permission because setRestrictBackground() will do it.
1918        if (LOGD) Log.d(TAG, "onTetherStateChanged(" + iface + ", " + tethering + ")");
1919        synchronized (mRulesLock) {
1920            if (mRestrictBackground && tethering) {
1921                Log.d(TAG, "Tethering on (" + iface +"); disable Data Saver");
1922                setRestrictBackground(false);
1923            }
1924        }
1925    }
1926
1927    @Override
1928    public void setRestrictBackground(boolean restrictBackground) {
1929        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1930        final long token = Binder.clearCallingIdentity();
1931        try {
1932            maybeRefreshTrustedTime();
1933            synchronized (mRulesLock) {
1934                if (restrictBackground == mRestrictBackground) {
1935                    // Ideally, UI should never allow this scenario...
1936                    Slog.w(TAG, "setRestrictBackground: already " + restrictBackground);
1937                    return;
1938                }
1939                setRestrictBackgroundLocked(restrictBackground);
1940            }
1941
1942        } finally {
1943            Binder.restoreCallingIdentity(token);
1944        }
1945
1946        mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED, restrictBackground ? 1 : 0, 0)
1947                .sendToTarget();
1948    }
1949
1950    private void setRestrictBackgroundLocked(boolean restrictBackground) {
1951        final boolean oldRestrictBackground = mRestrictBackground;
1952        mRestrictBackground = restrictBackground;
1953        // Must whitelist foreground apps before turning data saver mode on.
1954        // TODO: there is no need to iterate through all apps here, just those in the foreground,
1955        // so it could call AM to get the UIDs of such apps, and iterate through them instead.
1956        updateRulesForRestrictBackgroundLocked();
1957        try {
1958            if (!mNetworkManager.setDataSaverModeEnabled(mRestrictBackground)) {
1959                Slog.e(TAG, "Could not change Data Saver Mode on NMS to " + mRestrictBackground);
1960                mRestrictBackground = oldRestrictBackground;
1961                // TODO: if it knew the foreground apps (see TODO above), it could call
1962                // updateRulesForRestrictBackgroundLocked() again to restore state.
1963                return;
1964            }
1965        } catch (RemoteException e) {
1966            // ignored; service lives in system_server
1967        }
1968        updateNotificationsLocked();
1969        writePolicyLocked();
1970    }
1971
1972    @Override
1973    public void addRestrictBackgroundWhitelistedUid(int uid) {
1974        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1975        final boolean oldStatus;
1976        final boolean needFirewallRules;
1977        synchronized (mRulesLock) {
1978            oldStatus = mRestrictBackgroundWhitelistUids.get(uid);
1979            if (oldStatus) {
1980                if (LOGD) Slog.d(TAG, "uid " + uid + " is already whitelisted");
1981                return;
1982            }
1983            needFirewallRules = isUidValidForWhitelistRules(uid);
1984            Slog.i(TAG, "adding uid " + uid + " to restrict background whitelist");
1985            mRestrictBackgroundWhitelistUids.append(uid, true);
1986            if (mDefaultRestrictBackgroundWhitelistUids.get(uid)
1987                    && mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
1988                if (LOGD) Slog.d(TAG, "Removing uid " + uid
1989                        + " from revoked restrict background whitelist");
1990                mRestrictBackgroundWhitelistRevokedUids.delete(uid);
1991            }
1992            if (needFirewallRules) {
1993                // Only update firewall rules if necessary...
1994                updateRuleForRestrictBackgroundLocked(uid);
1995            }
1996            // ...but always persists the whitelist request.
1997            writePolicyLocked();
1998        }
1999        int changed = (mRestrictBackground && !oldStatus && needFirewallRules) ? 1 : 0;
2000        mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, changed,
2001                Boolean.TRUE).sendToTarget();
2002    }
2003
2004    @Override
2005    public void removeRestrictBackgroundWhitelistedUid(int uid) {
2006        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
2007        final boolean changed;
2008        synchronized (mRulesLock) {
2009            changed = removeRestrictBackgroundWhitelistedUidLocked(uid, false, true);
2010        }
2011        mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, changed ? 1 : 0,
2012                Boolean.FALSE).sendToTarget();
2013    }
2014
2015    /**
2016     * Removes a uid from the restricted background whitelist, returning whether its current
2017     * {@link ConnectivityManager.RestrictBackgroundStatus} changed.
2018     */
2019    private boolean removeRestrictBackgroundWhitelistedUidLocked(int uid, boolean uidDeleted,
2020            boolean updateNow) {
2021        final boolean oldStatus = mRestrictBackgroundWhitelistUids.get(uid);
2022        if (!oldStatus) {
2023            if (LOGD) Slog.d(TAG, "uid " + uid + " was not whitelisted before");
2024            return false;
2025        }
2026        final boolean needFirewallRules = uidDeleted || isUidValidForWhitelistRules(uid);
2027        Slog.i(TAG, "removing uid " + uid + " from restrict background whitelist");
2028        mRestrictBackgroundWhitelistUids.delete(uid);
2029        if (mDefaultRestrictBackgroundWhitelistUids.get(uid)
2030                && !mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
2031            if (LOGD) Slog.d(TAG, "Adding uid " + uid
2032                    + " to revoked restrict background whitelist");
2033            mRestrictBackgroundWhitelistRevokedUids.append(uid, true);
2034        }
2035        if (needFirewallRules) {
2036            // Only update firewall rules if necessary...
2037            updateRuleForRestrictBackgroundLocked(uid, uidDeleted);
2038        }
2039        if (updateNow) {
2040            // ...but always persists the whitelist request.
2041            writePolicyLocked();
2042        }
2043        // Status only changes if Data Saver is turned on (otherwise it is DISABLED, even if the
2044        // app was whitelisted before).
2045        return mRestrictBackground && needFirewallRules;
2046    }
2047
2048    @Override
2049    public int[] getRestrictBackgroundWhitelistedUids() {
2050        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
2051        synchronized (mRulesLock) {
2052            final int size = mRestrictBackgroundWhitelistUids.size();
2053            final int[] whitelist = new int[size];
2054            for (int i = 0; i < size; i++) {
2055                whitelist[i] = mRestrictBackgroundWhitelistUids.keyAt(i);
2056            }
2057            if (LOGV) {
2058                Slog.v(TAG, "getRestrictBackgroundWhitelistedUids(): "
2059                        + mRestrictBackgroundWhitelistUids);
2060            }
2061            return whitelist;
2062        }
2063    }
2064
2065    @Override
2066    public int getRestrictBackgroundByCaller() {
2067        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
2068        final int uid = Binder.getCallingUid();
2069
2070        synchronized (mRulesLock) {
2071            // Must clear identity because getUidPolicy() is restricted to system.
2072            final long token = Binder.clearCallingIdentity();
2073            final int policy;
2074            try {
2075                policy = getUidPolicy(uid);
2076            } finally {
2077                Binder.restoreCallingIdentity(token);
2078            }
2079            if (policy == POLICY_REJECT_METERED_BACKGROUND) {
2080                // App is blacklisted.
2081                return RESTRICT_BACKGROUND_STATUS_ENABLED;
2082            }
2083            if (!mRestrictBackground) {
2084                return RESTRICT_BACKGROUND_STATUS_DISABLED;
2085            }
2086            return mRestrictBackgroundWhitelistUids.get(uid)
2087                    ? RESTRICT_BACKGROUND_STATUS_WHITELISTED
2088                    : RESTRICT_BACKGROUND_STATUS_ENABLED;
2089        }
2090    }
2091
2092    @Override
2093    public boolean getRestrictBackground() {
2094        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
2095
2096        synchronized (mRulesLock) {
2097            return mRestrictBackground;
2098        }
2099    }
2100
2101    @Override
2102    public void setDeviceIdleMode(boolean enabled) {
2103        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
2104
2105        synchronized (mRulesLock) {
2106            if (mDeviceIdleMode != enabled) {
2107                mDeviceIdleMode = enabled;
2108                if (mSystemReady) {
2109                    // Device idle change means we need to rebuild rules for all
2110                    // known apps, so do a global refresh.
2111                    updateRulesForGlobalChangeLocked(false);
2112                }
2113                if (enabled) {
2114                    EventLogTags.writeDeviceIdleOnPhase("net");
2115                } else {
2116                    EventLogTags.writeDeviceIdleOffPhase("net");
2117                }
2118            }
2119        }
2120    }
2121
2122    private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) {
2123        for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
2124            NetworkPolicy policy = mNetworkPolicy.valueAt(i);
2125            if (policy.template.matches(ident)) {
2126                return policy;
2127            }
2128        }
2129        return null;
2130    }
2131
2132    @Override
2133    public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) {
2134        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
2135
2136        // only returns usage summary, so we don't require caller to have
2137        // READ_NETWORK_USAGE_HISTORY.
2138        final long token = Binder.clearCallingIdentity();
2139        try {
2140            return getNetworkQuotaInfoUnchecked(state);
2141        } finally {
2142            Binder.restoreCallingIdentity(token);
2143        }
2144    }
2145
2146    private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) {
2147        final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
2148
2149        final NetworkPolicy policy;
2150        synchronized (mRulesLock) {
2151            policy = findPolicyForNetworkLocked(ident);
2152        }
2153
2154        if (policy == null || !policy.hasCycle()) {
2155            // missing policy means we can't derive useful quota info
2156            return null;
2157        }
2158
2159        final long currentTime = currentTimeMillis();
2160
2161        // find total bytes used under policy
2162        final long start = computeLastCycleBoundary(currentTime, policy);
2163        final long end = currentTime;
2164        final long totalBytes = getTotalBytes(policy.template, start, end);
2165
2166        // report soft and hard limits under policy
2167        final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes
2168                : NetworkQuotaInfo.NO_LIMIT;
2169        final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes
2170                : NetworkQuotaInfo.NO_LIMIT;
2171
2172        return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes);
2173    }
2174
2175    @Override
2176    public boolean isNetworkMetered(NetworkState state) {
2177        if (state.networkInfo == null) {
2178            return false;
2179        }
2180
2181        final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
2182
2183        // roaming networks are always considered metered
2184        if (ident.getRoaming()) {
2185            return true;
2186        }
2187
2188        final NetworkPolicy policy;
2189        synchronized (mRulesLock) {
2190            policy = findPolicyForNetworkLocked(ident);
2191        }
2192
2193        if (policy != null) {
2194            return policy.metered;
2195        } else {
2196            final int type = state.networkInfo.getType();
2197            if (isNetworkTypeMobile(type) || type == TYPE_WIMAX) {
2198                return true;
2199            }
2200            return false;
2201        }
2202    }
2203
2204    @Override
2205    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
2206        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
2207
2208        final IndentingPrintWriter fout = new IndentingPrintWriter(writer, "  ");
2209
2210        final ArraySet<String> argSet = new ArraySet<String>(args.length);
2211        for (String arg : args) {
2212            argSet.add(arg);
2213        }
2214
2215        synchronized (mRulesLock) {
2216            if (argSet.contains("--unsnooze")) {
2217                for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
2218                    mNetworkPolicy.valueAt(i).clearSnooze();
2219                }
2220
2221                normalizePoliciesLocked();
2222                updateNetworkEnabledLocked();
2223                updateNetworkRulesLocked();
2224                updateNotificationsLocked();
2225                writePolicyLocked();
2226
2227                fout.println("Cleared snooze timestamps");
2228                return;
2229            }
2230
2231            fout.print("System ready: "); fout.println(mSystemReady);
2232            fout.print("Restrict background: "); fout.println(mRestrictBackground);
2233            fout.print("Restrict power: "); fout.println(mRestrictPower);
2234            fout.print("Device idle: "); fout.println(mDeviceIdleMode);
2235            fout.println("Network policies:");
2236            fout.increaseIndent();
2237            for (int i = 0; i < mNetworkPolicy.size(); i++) {
2238                fout.println(mNetworkPolicy.valueAt(i).toString());
2239            }
2240            fout.decreaseIndent();
2241
2242            fout.print("Metered ifaces: "); fout.println(String.valueOf(mMeteredIfaces));
2243
2244            fout.println("Policy for UIDs:");
2245            fout.increaseIndent();
2246            int size = mUidPolicy.size();
2247            for (int i = 0; i < size; i++) {
2248                final int uid = mUidPolicy.keyAt(i);
2249                final int policy = mUidPolicy.valueAt(i);
2250                fout.print("UID=");
2251                fout.print(uid);
2252                fout.print(" policy=");
2253                fout.print(DebugUtils.flagsToString(NetworkPolicyManager.class, "POLICY_", policy));
2254                fout.println();
2255            }
2256            fout.decreaseIndent();
2257
2258            size = mPowerSaveWhitelistExceptIdleAppIds.size();
2259            if (size > 0) {
2260                fout.println("Power save whitelist (except idle) app ids:");
2261                fout.increaseIndent();
2262                for (int i = 0; i < size; i++) {
2263                    fout.print("UID=");
2264                    fout.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
2265                    fout.print(": ");
2266                    fout.print(mPowerSaveWhitelistExceptIdleAppIds.valueAt(i));
2267                    fout.println();
2268                }
2269                fout.decreaseIndent();
2270            }
2271
2272            size = mPowerSaveWhitelistAppIds.size();
2273            if (size > 0) {
2274                fout.println("Power save whitelist app ids:");
2275                fout.increaseIndent();
2276                for (int i = 0; i < size; i++) {
2277                    fout.print("UID=");
2278                    fout.print(mPowerSaveWhitelistAppIds.keyAt(i));
2279                    fout.print(": ");
2280                    fout.print(mPowerSaveWhitelistAppIds.valueAt(i));
2281                    fout.println();
2282                }
2283                fout.decreaseIndent();
2284            }
2285
2286            size = mRestrictBackgroundWhitelistUids.size();
2287            if (size > 0) {
2288                fout.println("Restrict background whitelist uids:");
2289                fout.increaseIndent();
2290                for (int i = 0; i < size; i++) {
2291                    fout.print("UID=");
2292                    fout.print(mRestrictBackgroundWhitelistUids.keyAt(i));
2293                    fout.println();
2294                }
2295                fout.decreaseIndent();
2296            }
2297
2298            size = mDefaultRestrictBackgroundWhitelistUids.size();
2299            if (size > 0) {
2300                fout.println("Default restrict background whitelist uids:");
2301                fout.increaseIndent();
2302                for (int i = 0; i < size; i++) {
2303                    fout.print("UID=");
2304                    fout.print(mDefaultRestrictBackgroundWhitelistUids.keyAt(i));
2305                    fout.println();
2306                }
2307                fout.decreaseIndent();
2308            }
2309
2310            size = mRestrictBackgroundWhitelistRevokedUids.size();
2311            if (size > 0) {
2312                fout.println("Default restrict background whitelist uids revoked by users:");
2313                fout.increaseIndent();
2314                for (int i = 0; i < size; i++) {
2315                    fout.print("UID=");
2316                    fout.print(mRestrictBackgroundWhitelistRevokedUids.keyAt(i));
2317                    fout.println();
2318                }
2319                fout.decreaseIndent();
2320            }
2321
2322            final SparseBooleanArray knownUids = new SparseBooleanArray();
2323            collectKeys(mUidState, knownUids);
2324            collectKeys(mUidRules, knownUids);
2325
2326            fout.println("Status for known UIDs:");
2327            fout.increaseIndent();
2328            size = knownUids.size();
2329            for (int i = 0; i < size; i++) {
2330                final int uid = knownUids.keyAt(i);
2331                fout.print("UID=");
2332                fout.print(uid);
2333
2334                final int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
2335                fout.print(" state=");
2336                fout.print(state);
2337                if (state <= ActivityManager.PROCESS_STATE_TOP) {
2338                    fout.print(" (fg)");
2339                } else {
2340                    fout.print(state <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
2341                            ? " (fg svc)" : " (bg)");
2342                }
2343
2344                final int rule = mUidRules.get(uid, RULE_UNKNOWN);
2345                fout.print(" rule=");
2346                fout.print(ruleToString(rule));
2347
2348                fout.println();
2349            }
2350            fout.decreaseIndent();
2351        }
2352    }
2353
2354    private String ruleToString(int rule) {
2355        return DebugUtils.valueToString(NetworkPolicyManager.class, "RULE_", rule);
2356    }
2357
2358    @Override
2359    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
2360            String[] args, ResultReceiver resultReceiver) throws RemoteException {
2361        (new NetworkPolicyManagerShellCommand(mContext, this)).exec(
2362                this, in, out, err, args, resultReceiver);
2363    }
2364
2365    @Override
2366    public boolean isUidForeground(int uid) {
2367        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
2368
2369        synchronized (mRulesLock) {
2370            return isUidForegroundLocked(uid);
2371        }
2372    }
2373
2374    private boolean isUidForegroundLocked(int uid) {
2375        return isUidStateForegroundLocked(
2376                mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY));
2377    }
2378
2379    private boolean isUidForegroundOnRestrictBackgroundLocked(int uid) {
2380        final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
2381        return isProcStateAllowedWhileOnRestrictBackgroundLocked(procState);
2382    }
2383
2384    private boolean isUidStateForegroundLocked(int state) {
2385        // only really in foreground when screen is also on
2386        return mScreenOn && state <= ActivityManager.PROCESS_STATE_TOP;
2387    }
2388
2389    /**
2390     * Process state of UID changed; if needed, will trigger
2391     * {@link #updateRuleForRestrictBackgroundLocked(int)}.
2392     */
2393    private void updateUidStateLocked(int uid, int uidState) {
2394        final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
2395        if (oldUidState != uidState) {
2396            // state changed, push updated rules
2397            mUidState.put(uid, uidState);
2398            updateRestrictBackgroundRulesOnUidStatusChangedLocked(uid, oldUidState, uidState);
2399            if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
2400                    != isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {
2401                if (mDeviceIdleMode) {
2402                    updateRuleForDeviceIdleLocked(uid);
2403                }
2404                if (mRestrictPower) {
2405                    updateRuleForRestrictPowerLocked(uid);
2406                }
2407            }
2408            updateNetworkStats(uid, isUidStateForegroundLocked(uidState));
2409        }
2410    }
2411
2412    private void removeUidStateLocked(int uid) {
2413        final int index = mUidState.indexOfKey(uid);
2414        if (index >= 0) {
2415            final int oldUidState = mUidState.valueAt(index);
2416            mUidState.removeAt(index);
2417            if (oldUidState != ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
2418                updateRestrictBackgroundRulesOnUidStatusChangedLocked(uid, oldUidState,
2419                        ActivityManager.PROCESS_STATE_CACHED_EMPTY);
2420                if (mDeviceIdleMode) {
2421                    updateRuleForDeviceIdleLocked(uid);
2422                }
2423                if (mRestrictPower) {
2424                    updateRuleForRestrictPowerLocked(uid);
2425                }
2426                updateNetworkStats(uid, false);
2427            }
2428        }
2429    }
2430
2431    // adjust stats accounting based on foreground status
2432    private void updateNetworkStats(int uid, boolean uidForeground) {
2433        try {
2434            mNetworkStats.setUidForeground(uid, uidForeground);
2435        } catch (RemoteException e) {
2436            // ignored; service lives in system_server
2437        }
2438    }
2439
2440    private void updateRestrictBackgroundRulesOnUidStatusChangedLocked(int uid, int oldUidState,
2441            int newUidState) {
2442        final boolean oldForeground =
2443                isProcStateAllowedWhileOnRestrictBackgroundLocked(oldUidState);
2444        final boolean newForeground =
2445                isProcStateAllowedWhileOnRestrictBackgroundLocked(newUidState);
2446        if (oldForeground != newForeground) {
2447            updateRuleForRestrictBackgroundLocked(uid);
2448        }
2449    }
2450
2451    private void updateScreenOn() {
2452        synchronized (mRulesLock) {
2453            try {
2454                mScreenOn = mPowerManager.isInteractive();
2455            } catch (RemoteException e) {
2456                // ignored; service lives in system_server
2457            }
2458            updateRulesForScreenLocked();
2459        }
2460    }
2461
2462    /**
2463     * Update rules that might be changed by {@link #mScreenOn} value.
2464     */
2465    private void updateRulesForScreenLocked() {
2466        // only update rules for anyone with foreground activities
2467        final int size = mUidState.size();
2468        for (int i = 0; i < size; i++) {
2469            if (mUidState.valueAt(i) <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
2470                final int uid = mUidState.keyAt(i);
2471                updateRestrictionRulesForUidLocked(uid);
2472            }
2473        }
2474    }
2475
2476    static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(int procState) {
2477        return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
2478    }
2479
2480    static boolean isProcStateAllowedWhileOnRestrictBackgroundLocked(int procState) {
2481        return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
2482    }
2483
2484    void updateRulesForRestrictPowerLocked() {
2485        updateRulesForWhitelistedPowerSaveLocked(mRestrictPower, FIREWALL_CHAIN_POWERSAVE,
2486                mUidFirewallPowerSaveRules);
2487    }
2488
2489    void updateRuleForRestrictPowerLocked(int uid) {
2490        updateRulesForWhitelistedPowerSaveLocked(uid, mRestrictPower, FIREWALL_CHAIN_POWERSAVE);
2491    }
2492
2493    void updateRulesForDeviceIdleLocked() {
2494        updateRulesForWhitelistedPowerSaveLocked(mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE,
2495                mUidFirewallDozableRules);
2496    }
2497
2498    void updateRuleForDeviceIdleLocked(int uid) {
2499        updateRulesForWhitelistedPowerSaveLocked(uid, mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE);
2500    }
2501
2502    // NOTE: since both fw_dozable and fw_powersave uses the same map
2503    // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
2504    private void updateRulesForWhitelistedPowerSaveLocked(boolean enabled, int chain,
2505            SparseIntArray rules) {
2506        if (enabled) {
2507            // Sync the whitelists before enabling the chain.  We don't care about the rules if
2508            // we are disabling the chain.
2509            final SparseIntArray uidRules = rules;
2510            uidRules.clear();
2511            final List<UserInfo> users = mUserManager.getUsers();
2512            for (int ui = users.size() - 1; ui >= 0; ui--) {
2513                UserInfo user = users.get(ui);
2514                for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
2515                    if (mPowerSaveTempWhitelistAppIds.valueAt(i)) {
2516                        int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
2517                        int uid = UserHandle.getUid(user.id, appId);
2518                        uidRules.put(uid, FIREWALL_RULE_ALLOW);
2519                    }
2520                }
2521                for (int i = mPowerSaveWhitelistAppIds.size() - 1; i >= 0; i--) {
2522                    int appId = mPowerSaveWhitelistAppIds.keyAt(i);
2523                    int uid = UserHandle.getUid(user.id, appId);
2524                    uidRules.put(uid, FIREWALL_RULE_ALLOW);
2525                }
2526            }
2527            for (int i = mUidState.size() - 1; i >= 0; i--) {
2528                if (isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.valueAt(i))) {
2529                    uidRules.put(mUidState.keyAt(i), FIREWALL_RULE_ALLOW);
2530                }
2531            }
2532            setUidFirewallRules(chain, uidRules);
2533        }
2534
2535        enableFirewallChainLocked(chain, enabled);
2536    }
2537
2538    // NOTE: since both fw_dozable and fw_powersave uses the same map
2539    // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
2540    private void updateRulesForWhitelistedPowerSaveLocked(int uid, boolean enabled, int chain) {
2541        if (enabled) {
2542            int appId = UserHandle.getAppId(uid);
2543            if (mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId)
2544                    || isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.get(uid))) {
2545                setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
2546            } else {
2547                setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT);
2548            }
2549        }
2550    }
2551
2552    void updateRulesForAppIdleLocked() {
2553        final SparseIntArray uidRules = mUidFirewallStandbyRules;
2554        uidRules.clear();
2555
2556        // Fully update the app idle firewall chain.
2557        final List<UserInfo> users = mUserManager.getUsers();
2558        for (int ui = users.size() - 1; ui >= 0; ui--) {
2559            UserInfo user = users.get(ui);
2560            int[] idleUids = mUsageStats.getIdleUidsForUser(user.id);
2561            for (int uid : idleUids) {
2562                if (!mPowerSaveTempWhitelistAppIds.get(UserHandle.getAppId(uid), false)) {
2563                    // quick check: if this uid doesn't have INTERNET permission, it
2564                    // doesn't have network access anyway, so it is a waste to mess
2565                    // with it here.
2566                    if (hasInternetPermissions(uid)) {
2567                        uidRules.put(uid, FIREWALL_RULE_DENY);
2568                    }
2569                }
2570            }
2571        }
2572
2573        setUidFirewallRules(FIREWALL_CHAIN_STANDBY, uidRules);
2574    }
2575
2576    void updateRuleForAppIdleLocked(int uid) {
2577        if (!isUidValidForBlacklistRules(uid)) return;
2578
2579        int appId = UserHandle.getAppId(uid);
2580        if (!mPowerSaveTempWhitelistAppIds.get(appId) && isUidIdle(uid)) {
2581            setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DENY);
2582        } else {
2583            setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
2584        }
2585    }
2586
2587    void updateRulesForAppIdleParoleLocked() {
2588        boolean enableChain = !mUsageStats.isAppIdleParoleOn();
2589        enableFirewallChainLocked(FIREWALL_CHAIN_STANDBY, enableChain);
2590    }
2591
2592    /**
2593     * Update rules that might be changed by {@link #mRestrictBackground},
2594     * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
2595     */
2596    private void updateRulesForGlobalChangeLocked(boolean restrictedNetworksChanged) {
2597        long start;
2598        if (LOGD) start = System.currentTimeMillis();
2599
2600        updateRulesForDeviceIdleLocked();
2601        updateRulesForAppIdleLocked();
2602        updateRulesForRestrictPowerLocked();
2603        updateRulesForRestrictBackgroundLocked();
2604        setRestrictBackgroundLocked(mRestrictBackground);
2605
2606        // If the set of restricted networks may have changed, re-evaluate those.
2607        if (restrictedNetworksChanged) {
2608            normalizePoliciesLocked();
2609            updateNetworkRulesLocked();
2610        }
2611        if (LOGD) {
2612            final long delta = System.currentTimeMillis() - start;
2613            Slog.d(TAG, "updateRulesForGlobalChangeLocked(" + restrictedNetworksChanged + ") took "
2614                    + delta + "ms");
2615        }
2616    }
2617
2618    private void updateRulesForRestrictBackgroundLocked() {
2619        final PackageManager pm = mContext.getPackageManager();
2620
2621        // update rules for all installed applications
2622        final List<UserInfo> users = mUserManager.getUsers();
2623        final List<ApplicationInfo> apps = pm.getInstalledApplications(
2624                PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_DISABLED_COMPONENTS
2625                        | PackageManager.MATCH_DIRECT_BOOT_AWARE
2626                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
2627
2628        final int usersSize = users.size();
2629        final int appsSize = apps.size();
2630        for (int i = 0; i < usersSize; i++) {
2631            final UserInfo user = users.get(i);
2632            for (int j = 0; j < appsSize; j++) {
2633                final ApplicationInfo app = apps.get(j);
2634                final int uid = UserHandle.getUid(user.id, app.uid);
2635                updateRuleForRestrictBackgroundLocked(uid);
2636            }
2637        }
2638    }
2639
2640    private void updateRulesForTempWhitelistChangeLocked() {
2641        final List<UserInfo> users = mUserManager.getUsers();
2642        for (int i = 0; i < users.size(); i++) {
2643            final UserInfo user = users.get(i);
2644            for (int j = mPowerSaveTempWhitelistAppIds.size() - 1; j >= 0; j--) {
2645                int appId = mPowerSaveTempWhitelistAppIds.keyAt(j);
2646                int uid = UserHandle.getUid(user.id, appId);
2647                updateRuleForAppIdleLocked(uid);
2648                updateRuleForDeviceIdleLocked(uid);
2649                updateRuleForRestrictPowerLocked(uid);
2650            }
2651        }
2652    }
2653
2654    // TODO: the MEDIA / DRM restriction might not be needed anymore, in which case both
2655    // methods below could be merged into a isUidValidForRules() method.
2656    private boolean isUidValidForBlacklistRules(int uid) {
2657        // allow rules on specific system services, and any apps
2658        if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID
2659            || (UserHandle.isApp(uid) && hasInternetPermissions(uid))) {
2660            return true;
2661        }
2662
2663        return false;
2664    }
2665
2666    private boolean isUidValidForWhitelistRules(int uid) {
2667        return UserHandle.isApp(uid) && hasInternetPermissions(uid);
2668    }
2669
2670    private boolean isUidIdle(int uid) {
2671        final String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
2672        final int userId = UserHandle.getUserId(uid);
2673
2674        if (!ArrayUtils.isEmpty(packages)) {
2675            for (String packageName : packages) {
2676                if (!mUsageStats.isAppIdle(packageName, uid, userId)) {
2677                    return false;
2678                }
2679            }
2680        }
2681        return true;
2682    }
2683
2684    /**
2685     * Checks if an uid has INTERNET permissions.
2686     * <p>
2687     * Useful for the cases where the lack of network access can simplify the rules.
2688     */
2689    private boolean hasInternetPermissions(int uid) {
2690        try {
2691            if (mIPm.checkUidPermission(Manifest.permission.INTERNET, uid)
2692                    != PackageManager.PERMISSION_GRANTED) {
2693                return false;
2694            }
2695        } catch (RemoteException e) {
2696        }
2697        return true;
2698    }
2699
2700    /**
2701     * Applies network rules to bandwidth and firewall controllers based on uid policy.
2702     *
2703     * <p>There are currently 2 types of restriction rules:
2704     * <ul>
2705     * <li>Battery Saver Mode (also referred as power save).
2706     * <li>Data Saver Mode (formerly known as restrict background data).
2707     * </ul>
2708     */
2709    private void updateRestrictionRulesForUidLocked(int uid) {
2710        updateRuleForRestrictPowerLocked(uid);
2711        updateRuleForRestrictBackgroundLocked(uid);
2712    }
2713
2714    /**
2715     * Applies network rules to bandwidth controllers based on process state and user-defined
2716     * restrictions (blacklist / whitelist).
2717     *
2718     * <p>
2719     * {@code netd} defines 3 firewall chains that govern whether an app has access to metered
2720     * networks:
2721     * <ul>
2722     * <li>@{code bw_penalty_box}: UIDs added to this chain do not have access (blacklist).
2723     * <li>@{code bw_happy_box}: UIDs added to this chain have access (whitelist), unless they're
2724     *     also blacklisted.
2725     * <li>@{code bw_data_saver}: when enabled (through {@link #setRestrictBackground(boolean)}),
2726     *     no UIDs other those whitelisted will have access.
2727     * <ul>
2728     *
2729     * <p>The @{code bw_penalty_box} and @{code bw_happy_box} are primarily managed through the
2730     * {@link #setUidPolicy(int, int)} and {@link #addRestrictBackgroundWhitelistedUid(int)} /
2731     * {@link #removeRestrictBackgroundWhitelistedUid(int)} methods (for blacklist and whitelist
2732     * respectively): these methods set the proper internal state (blacklist / whitelist), then call
2733     * this ({@link #updateRuleForRestrictBackgroundLocked(int)}) to propagate the rules to
2734     * {@link INetworkManagementService}, but this method should also be called in events (like
2735     * Data Saver Mode flips or UID state changes) that might affect the foreground app, since the
2736     * following rules should also be applied:
2737     *
2738     * <ul>
2739     * <li>When Data Saver mode is on, the foreground app should be temporarily added to
2740     *     {@code bw_happy_box} before the @{code bw_data_saver} chain is enabled.
2741     * <li>If the foreground app is blacklisted by the user, it should be temporarily removed from
2742     *     {@code bw_penalty_box}.
2743     * <li>When the app leaves foreground state, the temporary changes above should be reverted.
2744     * </ul>
2745     *
2746     * <p>For optimization, the rules are only applied on user apps that have internet access
2747     * permission, since there is no need to change the {@code iptables} rule if the app does not
2748     * have permission to use the internet.
2749     *
2750     * <p>The {@link #mUidRules} map is used to define the transtion of states of an UID.
2751     */
2752    private void updateRuleForRestrictBackgroundLocked(int uid) {
2753        updateRuleForRestrictBackgroundLocked(uid, false);
2754    }
2755
2756    /**
2757     * Overloaded version of {@link #updateRuleForRestrictBackgroundLocked(int)} called when an
2758     * app is removed - it ignores the UID validity check.
2759     */
2760    private void updateRuleForRestrictBackgroundLocked(int uid, boolean uidDeleted) {
2761        if (!uidDeleted && !isUidValidForWhitelistRules(uid)) {
2762            if (LOGD) Slog.d(TAG, "no need to update restrict data rules for uid " + uid);
2763            return;
2764        }
2765
2766        final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
2767        final boolean isForeground = isUidForegroundOnRestrictBackgroundLocked(uid);
2768        final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
2769        final boolean isWhitelisted = mRestrictBackgroundWhitelistUids.get(uid);
2770
2771        int newRule = RULE_UNKNOWN;
2772        final int oldRule = mUidRules.get(uid, RULE_UNKNOWN);
2773
2774        // First step: define the new rule based on user restrictions and foreground state.
2775        if (isForeground) {
2776            if (isBlacklisted || (mRestrictBackground && !isWhitelisted)) {
2777                newRule = RULE_TEMPORARY_ALLOW_METERED;
2778            }
2779        } else {
2780            if (isBlacklisted) {
2781                newRule = RULE_REJECT_METERED;
2782            } else if (isWhitelisted) {
2783                newRule = RULE_ALLOW_METERED;
2784            }
2785        }
2786
2787        if (LOGV) {
2788            Log.v(TAG, "updateRuleForRestrictBackgroundLocked(" + uid + "):"
2789                    + " isForeground=" +isForeground + ", isBlacklisted: " + isBlacklisted
2790                    + ", isWhitelisted: " + isWhitelisted + ", newRule: " + ruleToString(newRule)
2791                    + ", oldRule: " + ruleToString(oldRule));
2792        }
2793
2794        if (newRule == RULE_UNKNOWN) {
2795            mUidRules.delete(uid);
2796        } else {
2797            mUidRules.put(uid, newRule);
2798        }
2799
2800        // Second step: apply bw changes based on change of state.
2801        if (newRule != oldRule) {
2802            if (newRule == RULE_TEMPORARY_ALLOW_METERED) {
2803                // Temporarily whitelist foreground app, removing from blacklist if necessary
2804                // (since bw_penalty_box prevails over bw_happy_box).
2805
2806                setMeteredNetworkWhitelist(uid, true);
2807                // TODO: if statement below is used to avoid an unnecessary call to netd / iptables,
2808                // but ideally it should be just:
2809                //    setMeteredNetworkBlacklist(uid, isBlacklisted);
2810                if (isBlacklisted) {
2811                    setMeteredNetworkBlacklist(uid, false);
2812                }
2813            } else if (oldRule == RULE_TEMPORARY_ALLOW_METERED) {
2814                // Remove temporary whitelist from app that is not on foreground anymore.
2815
2816                // TODO: if statements below are used to avoid unnecessary calls to netd / iptables,
2817                // but ideally they should be just:
2818                //    setMeteredNetworkWhitelist(uid, isWhitelisted);
2819                //    setMeteredNetworkBlacklist(uid, isBlacklisted);
2820                if (!isWhitelisted) {
2821                    setMeteredNetworkWhitelist(uid, false);
2822                }
2823                if (isBlacklisted) {
2824                    setMeteredNetworkBlacklist(uid, true);
2825                }
2826            } else if (newRule == RULE_REJECT_METERED || oldRule == RULE_REJECT_METERED) {
2827                // Flip state because app was explicitly added or removed to blacklist.
2828                setMeteredNetworkBlacklist(uid, isBlacklisted);
2829                if (oldRule == RULE_REJECT_METERED && isWhitelisted) {
2830                    // Since blacklist prevails over whitelist, we need to handle the special case
2831                    // where app is whitelisted and blacklisted at the same time (although such
2832                    // scenario should be blocked by the UI), then blacklist is removed.
2833                    setMeteredNetworkWhitelist(uid, isWhitelisted);
2834                }
2835            } else if (newRule == RULE_ALLOW_METERED || oldRule == RULE_ALLOW_METERED) {
2836                // Flip state because app was explicitly added or removed to whitelist.
2837                setMeteredNetworkWhitelist(uid, isWhitelisted);
2838            } else {
2839                // All scenarios should have been covered above
2840                Log.wtf(TAG, "Unexpected change of state for " + uid
2841                        + ": foreground=" + isForeground + ", whitelisted=" + isWhitelisted
2842                        + ", blacklisted=" + isBlacklisted + ", newRule="
2843                        + ruleToString(newRule) + ", oldRule=" + ruleToString(oldRule));
2844            }
2845
2846            // dispatch changed rule to existing listeners
2847            mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newRule).sendToTarget();
2848        }
2849    }
2850
2851    private class AppIdleStateChangeListener
2852            extends UsageStatsManagerInternal.AppIdleStateChangeListener {
2853
2854        @Override
2855        public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
2856            try {
2857                final int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
2858                        PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
2859                synchronized (mRulesLock) {
2860                    updateRuleForAppIdleLocked(uid);
2861                }
2862            } catch (NameNotFoundException nnfe) {
2863            }
2864        }
2865
2866        @Override
2867        public void onParoleStateChanged(boolean isParoleOn) {
2868            synchronized (mRulesLock) {
2869                updateRulesForAppIdleParoleLocked();
2870            }
2871        }
2872    }
2873
2874    private void dispatchUidRulesChanged(INetworkPolicyListener listener, int uid, int uidRules) {
2875        if (listener != null) {
2876            try {
2877                listener.onUidRulesChanged(uid, uidRules);
2878            } catch (RemoteException ignored) {
2879            }
2880        }
2881    }
2882
2883    private void dispatchMeteredIfacesChanged(INetworkPolicyListener listener,
2884            String[] meteredIfaces) {
2885        if (listener != null) {
2886            try {
2887                listener.onMeteredIfacesChanged(meteredIfaces);
2888            } catch (RemoteException ignored) {
2889            }
2890        }
2891    }
2892
2893    private void dispatchRestrictBackgroundChanged(INetworkPolicyListener listener,
2894            boolean restrictBackground) {
2895        if (listener != null) {
2896            try {
2897                listener.onRestrictBackgroundChanged(restrictBackground);
2898            } catch (RemoteException ignored) {
2899            }
2900        }
2901    }
2902
2903    private void dispatchRestrictBackgroundWhitelistChanged(INetworkPolicyListener listener,
2904            int uid, boolean whitelisted) {
2905        if (listener != null) {
2906            try {
2907                listener.onRestrictBackgroundWhitelistChanged(uid, whitelisted);
2908            } catch (RemoteException ignored) {
2909            }
2910        }
2911    }
2912
2913    private Handler.Callback mHandlerCallback = new Handler.Callback() {
2914        @Override
2915        public boolean handleMessage(Message msg) {
2916            switch (msg.what) {
2917                case MSG_RULES_CHANGED: {
2918                    final int uid = msg.arg1;
2919                    final int uidRules = msg.arg2;
2920                    dispatchUidRulesChanged(mConnectivityListener, uid, uidRules);
2921                    final int length = mListeners.beginBroadcast();
2922                    for (int i = 0; i < length; i++) {
2923                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
2924                        dispatchUidRulesChanged(listener, uid, uidRules);
2925                    }
2926                    mListeners.finishBroadcast();
2927                    return true;
2928                }
2929                case MSG_METERED_IFACES_CHANGED: {
2930                    final String[] meteredIfaces = (String[]) msg.obj;
2931                    dispatchMeteredIfacesChanged(mConnectivityListener, meteredIfaces);
2932                    final int length = mListeners.beginBroadcast();
2933                    for (int i = 0; i < length; i++) {
2934                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
2935                        dispatchMeteredIfacesChanged(listener, meteredIfaces);
2936                    }
2937                    mListeners.finishBroadcast();
2938                    return true;
2939                }
2940                case MSG_LIMIT_REACHED: {
2941                    final String iface = (String) msg.obj;
2942
2943                    maybeRefreshTrustedTime();
2944                    synchronized (mRulesLock) {
2945                        if (mMeteredIfaces.contains(iface)) {
2946                            try {
2947                                // force stats update to make sure we have
2948                                // numbers that caused alert to trigger.
2949                                mNetworkStats.forceUpdate();
2950                            } catch (RemoteException e) {
2951                                // ignored; service lives in system_server
2952                            }
2953
2954                            updateNetworkEnabledLocked();
2955                            updateNotificationsLocked();
2956                        }
2957                    }
2958                    return true;
2959                }
2960                case MSG_RESTRICT_BACKGROUND_CHANGED: {
2961                    final boolean restrictBackground = msg.arg1 != 0;
2962                    dispatchRestrictBackgroundChanged(mConnectivityListener, restrictBackground);
2963                    final int length = mListeners.beginBroadcast();
2964                    for (int i = 0; i < length; i++) {
2965                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
2966                        dispatchRestrictBackgroundChanged(listener, restrictBackground);
2967                    }
2968                    mListeners.finishBroadcast();
2969                    final Intent intent =
2970                            new Intent(ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED);
2971                    intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
2972                    mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
2973                    return true;
2974                }
2975                case MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED: {
2976                    // MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED can be called in 2 occasions:
2977                    // - when an app is whitelisted
2978                    // - when an app is blacklisted
2979                    //
2980                    // Whether the internal listeners (INetworkPolicyListener implementations) or
2981                    // app broadcast receivers are notified depend on the following rules:
2982                    //
2983                    // - App receivers are only notified when the app status changed (msg.arg2 = 1)
2984                    // - Listeners are only notified when app was whitelisted (msg.obj is not null),
2985                    //   since blacklist notifications are handled through MSG_RULES_CHANGED).
2986                    final int uid = msg.arg1;
2987                    final boolean changed = msg.arg2 == 1;
2988                    final Boolean whitelisted = (Boolean) msg.obj;
2989
2990                    // First notify internal listeners...
2991                    if (whitelisted != null) {
2992                        final boolean whitelistedBool = whitelisted.booleanValue();
2993                        dispatchRestrictBackgroundWhitelistChanged(mConnectivityListener, uid,
2994                                whitelistedBool);
2995                        final int length = mListeners.beginBroadcast();
2996                        for (int i = 0; i < length; i++) {
2997                            final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
2998                            dispatchRestrictBackgroundWhitelistChanged(listener, uid,
2999                                    whitelistedBool);
3000                        }
3001                        mListeners.finishBroadcast();
3002                    }
3003
3004                    final PackageManager pm = mContext.getPackageManager();
3005                    final String[] packages = pm.getPackagesForUid(uid);
3006                    if (changed && packages != null) {
3007                        // ...then notify apps listening to ACTION_RESTRICT_BACKGROUND_CHANGED
3008                        final int userId = UserHandle.getUserId(uid);
3009                        for (String packageName : packages) {
3010                            final Intent intent = new Intent(
3011                                    ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED);
3012                            intent.setPackage(packageName);
3013                            intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3014                            mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
3015                        }
3016                    }
3017                    return true;
3018                }
3019                case MSG_ADVISE_PERSIST_THRESHOLD: {
3020                    final long lowestRule = (Long) msg.obj;
3021                    try {
3022                        // make sure stats are recorded frequently enough; we aim
3023                        // for 2MB threshold for 2GB/month rules.
3024                        final long persistThreshold = lowestRule / 1000;
3025                        mNetworkStats.advisePersistThreshold(persistThreshold);
3026                    } catch (RemoteException e) {
3027                        // ignored; service lives in system_server
3028                    }
3029                    return true;
3030                }
3031                case MSG_SCREEN_ON_CHANGED: {
3032                    updateScreenOn();
3033                    return true;
3034                }
3035                case MSG_UPDATE_INTERFACE_QUOTA: {
3036                    removeInterfaceQuota((String) msg.obj);
3037                    // int params need to be stitched back into a long
3038                    setInterfaceQuota((String) msg.obj,
3039                            ((long) msg.arg1 << 32) | (msg.arg2 & 0xFFFFFFFFL));
3040                    return true;
3041                }
3042                case MSG_REMOVE_INTERFACE_QUOTA: {
3043                    removeInterfaceQuota((String) msg.obj);
3044                    return true;
3045                }
3046                default: {
3047                    return false;
3048                }
3049            }
3050        }
3051    };
3052
3053    private void setInterfaceQuota(String iface, long quotaBytes) {
3054        try {
3055            mNetworkManager.setInterfaceQuota(iface, quotaBytes);
3056        } catch (IllegalStateException e) {
3057            Log.wtf(TAG, "problem setting interface quota", e);
3058        } catch (RemoteException e) {
3059            // ignored; service lives in system_server
3060        }
3061    }
3062
3063    private void removeInterfaceQuota(String iface) {
3064        try {
3065            mNetworkManager.removeInterfaceQuota(iface);
3066        } catch (IllegalStateException e) {
3067            Log.wtf(TAG, "problem removing interface quota", e);
3068        } catch (RemoteException e) {
3069            // ignored; service lives in system_server
3070        }
3071    }
3072
3073    private void setMeteredNetworkBlacklist(int uid, boolean enable) {
3074        if (LOGV) Slog.v(TAG, "setMeteredNetworkBlacklist " + uid + ": " + enable);
3075        try {
3076            mNetworkManager.setUidMeteredNetworkBlacklist(uid, enable);
3077        } catch (IllegalStateException e) {
3078            Log.wtf(TAG, "problem setting blacklist (" + enable + ") rules for " + uid, e);
3079        } catch (RemoteException e) {
3080            // ignored; service lives in system_server
3081        }
3082    }
3083
3084    private void setMeteredNetworkWhitelist(int uid, boolean enable) {
3085        if (LOGV) Slog.v(TAG, "setMeteredNetworkWhitelist " + uid + ": " + enable);
3086        try {
3087            mNetworkManager.setUidMeteredNetworkWhitelist(uid, enable);
3088        } catch (IllegalStateException e) {
3089            Log.wtf(TAG, "problem setting whitelist (" + enable + ") rules for " + uid, e);
3090        } catch (RemoteException e) {
3091            // ignored; service lives in system_server
3092        }
3093    }
3094
3095    /**
3096     * Set uid rules on a particular firewall chain. This is going to synchronize the rules given
3097     * here to netd.  It will clean up dead rules and make sure the target chain only contains rules
3098     * specified here.
3099     */
3100    private void setUidFirewallRules(int chain, SparseIntArray uidRules) {
3101        try {
3102            int size = uidRules.size();
3103            int[] uids = new int[size];
3104            int[] rules = new int[size];
3105            for(int index = size - 1; index >= 0; --index) {
3106                uids[index] = uidRules.keyAt(index);
3107                rules[index] = uidRules.valueAt(index);
3108            }
3109            mNetworkManager.setFirewallUidRules(chain, uids, rules);
3110        } catch (IllegalStateException e) {
3111            Log.wtf(TAG, "problem setting firewall uid rules", e);
3112        } catch (RemoteException e) {
3113            // ignored; service lives in system_server
3114        }
3115    }
3116
3117    /**
3118     * Add or remove a uid to the firewall blacklist for all network ifaces.
3119     */
3120    private void setUidFirewallRule(int chain, int uid, int rule) {
3121        if (chain == FIREWALL_CHAIN_DOZABLE) {
3122            mUidFirewallDozableRules.put(uid, rule);
3123        } else if (chain == FIREWALL_CHAIN_STANDBY) {
3124            mUidFirewallStandbyRules.put(uid, rule);
3125        } else if (chain == FIREWALL_CHAIN_POWERSAVE) {
3126            mUidFirewallPowerSaveRules.put(uid, rule);
3127        }
3128
3129        try {
3130            mNetworkManager.setFirewallUidRule(chain, uid, rule);
3131        } catch (IllegalStateException e) {
3132            Log.wtf(TAG, "problem setting firewall uid rules", e);
3133        } catch (RemoteException e) {
3134            // ignored; service lives in system_server
3135        }
3136    }
3137
3138    /**
3139     * Add or remove a uid to the firewall blacklist for all network ifaces.
3140     */
3141    private void enableFirewallChainLocked(int chain, boolean enable) {
3142        if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
3143                mFirewallChainStates.get(chain) == enable) {
3144            // All is the same, nothing to do.
3145            return;
3146        }
3147        mFirewallChainStates.put(chain, enable);
3148        try {
3149            mNetworkManager.setFirewallChainEnabled(chain, enable);
3150        } catch (IllegalStateException e) {
3151            Log.wtf(TAG, "problem enable firewall chain", e);
3152        } catch (RemoteException e) {
3153            // ignored; service lives in system_server
3154        }
3155    }
3156
3157    private long getTotalBytes(NetworkTemplate template, long start, long end) {
3158        try {
3159            return mNetworkStats.getNetworkTotalBytes(template, start, end);
3160        } catch (RuntimeException e) {
3161            Slog.w(TAG, "problem reading network stats: " + e);
3162            return 0;
3163        } catch (RemoteException e) {
3164            // ignored; service lives in system_server
3165            return 0;
3166        }
3167    }
3168
3169    private boolean isBandwidthControlEnabled() {
3170        final long token = Binder.clearCallingIdentity();
3171        try {
3172            return mNetworkManager.isBandwidthControlEnabled();
3173        } catch (RemoteException e) {
3174            // ignored; service lives in system_server
3175            return false;
3176        } finally {
3177            Binder.restoreCallingIdentity(token);
3178        }
3179    }
3180
3181    /**
3182     * Try refreshing {@link #mTime} when stale.
3183     */
3184    void maybeRefreshTrustedTime() {
3185        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
3186            mTime.forceRefresh();
3187        }
3188    }
3189
3190    private long currentTimeMillis() {
3191        return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
3192    }
3193
3194    private static Intent buildAllowBackgroundDataIntent() {
3195        return new Intent(ACTION_ALLOW_BACKGROUND);
3196    }
3197
3198    private static Intent buildSnoozeWarningIntent(NetworkTemplate template) {
3199        final Intent intent = new Intent(ACTION_SNOOZE_WARNING);
3200        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
3201        return intent;
3202    }
3203
3204    private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
3205        final Intent intent = new Intent();
3206        intent.setComponent(new ComponentName(
3207                "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity"));
3208        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3209        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
3210        return intent;
3211    }
3212
3213    private static Intent buildViewDataUsageIntent(NetworkTemplate template) {
3214        final Intent intent = new Intent();
3215        intent.setComponent(new ComponentName(
3216                "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
3217        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3218        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
3219        return intent;
3220    }
3221
3222    @VisibleForTesting
3223    public void addIdleHandler(IdleHandler handler) {
3224        mHandler.getLooper().getQueue().addIdleHandler(handler);
3225    }
3226
3227    private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
3228        final int size = source.size();
3229        for (int i = 0; i < size; i++) {
3230            target.put(source.keyAt(i), true);
3231        }
3232    }
3233
3234    @Override
3235    public void factoryReset(String subscriber) {
3236        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
3237
3238        if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
3239            return;
3240        }
3241
3242        // Turn mobile data limit off
3243        NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName());
3244        NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(subscriber);
3245        for (NetworkPolicy policy : policies) {
3246            if (policy.template.equals(template)) {
3247                policy.limitBytes = NetworkPolicy.LIMIT_DISABLED;
3248                policy.inferred = false;
3249                policy.clearSnooze();
3250            }
3251        }
3252        setNetworkPolicies(policies);
3253
3254        // Turn restrict background data off
3255        setRestrictBackground(false);
3256
3257        if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_APPS_CONTROL)) {
3258            // Remove app's "restrict background data" flag
3259            for (int uid : getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) {
3260                setUidPolicy(uid, POLICY_NONE);
3261            }
3262        }
3263    }
3264
3265    private class MyPackageMonitor extends PackageMonitor {
3266
3267        @Override
3268        public void onPackageRemoved(String packageName, int uid) {
3269            if (LOGV) Slog.v(TAG, "onPackageRemoved: " + packageName + " ->" + uid);
3270            synchronized (mRulesLock) {
3271                removeRestrictBackgroundWhitelistedUidLocked(uid, true, true);
3272            }
3273        }
3274    }
3275}
3276