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