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