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