NetworkPolicyManagerService.java revision 7c5befa4a7ccd6e7e91ffdd93264b717259ec863
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.TYPE_MOBILE;
33import static android.net.ConnectivityManager.TYPE_WIMAX;
34import static android.net.ConnectivityManager.isNetworkTypeMobile;
35import static android.net.NetworkPolicy.CYCLE_NONE;
36import static android.net.NetworkPolicy.LIMIT_DISABLED;
37import static android.net.NetworkPolicy.SNOOZE_NEVER;
38import static android.net.NetworkPolicy.WARNING_DISABLED;
39import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
40import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
41import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
42import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
43import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
44import static android.net.NetworkPolicyManager.POLICY_ALLOW_BACKGROUND_BATTERY_SAVE;
45import static android.net.NetworkPolicyManager.POLICY_NONE;
46import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
47import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
48import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
49import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
50import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
51import static android.net.NetworkPolicyManager.dumpPolicy;
52import static android.net.NetworkPolicyManager.dumpRules;
53import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
54import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
55import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
56import static android.net.NetworkTemplate.MATCH_WIFI;
57import static android.net.NetworkTemplate.buildTemplateMobileAll;
58import static android.net.TrafficStats.MB_IN_BYTES;
59import static android.net.wifi.WifiManager.CHANGE_REASON_ADDED;
60import static android.net.wifi.WifiManager.CHANGE_REASON_REMOVED;
61import static android.net.wifi.WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION;
62import static android.net.wifi.WifiManager.EXTRA_CHANGE_REASON;
63import static android.net.wifi.WifiManager.EXTRA_NETWORK_INFO;
64import static android.net.wifi.WifiManager.EXTRA_WIFI_CONFIGURATION;
65import static android.net.wifi.WifiManager.EXTRA_WIFI_INFO;
66import static android.text.format.DateUtils.DAY_IN_MILLIS;
67import static com.android.internal.util.ArrayUtils.appendInt;
68import static com.android.internal.util.Preconditions.checkNotNull;
69import static com.android.internal.util.XmlUtils.readBooleanAttribute;
70import static com.android.internal.util.XmlUtils.readIntAttribute;
71import static com.android.internal.util.XmlUtils.readLongAttribute;
72import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
73import static com.android.internal.util.XmlUtils.writeIntAttribute;
74import static com.android.internal.util.XmlUtils.writeLongAttribute;
75import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
76import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
77import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
78import static org.xmlpull.v1.XmlPullParser.START_TAG;
79
80import android.Manifest;
81import android.app.ActivityManager;
82import android.app.AppGlobals;
83import android.app.AppOpsManager;
84import android.app.IActivityManager;
85import android.app.INotificationManager;
86import android.app.IUidObserver;
87import android.app.Notification;
88import android.app.PendingIntent;
89import android.app.usage.UsageStatsManagerInternal;
90import android.content.BroadcastReceiver;
91import android.content.ComponentName;
92import android.content.Context;
93import android.content.Intent;
94import android.content.IntentFilter;
95import android.content.pm.ApplicationInfo;
96import android.content.pm.IPackageManager;
97import android.content.pm.PackageManager;
98import android.content.pm.PackageManager.NameNotFoundException;
99import android.content.pm.UserInfo;
100import android.content.res.Resources;
101import android.net.ConnectivityManager;
102import android.net.IConnectivityManager;
103import android.net.INetworkManagementEventObserver;
104import android.net.INetworkPolicyListener;
105import android.net.INetworkPolicyManager;
106import android.net.INetworkStatsService;
107import android.net.LinkProperties;
108import android.net.NetworkIdentity;
109import android.net.NetworkInfo;
110import android.net.NetworkPolicy;
111import android.net.NetworkQuotaInfo;
112import android.net.NetworkState;
113import android.net.NetworkTemplate;
114import android.net.wifi.WifiConfiguration;
115import android.net.wifi.WifiInfo;
116import android.net.wifi.WifiManager;
117import android.os.Binder;
118import android.os.Environment;
119import android.os.Handler;
120import android.os.HandlerThread;
121import android.os.IDeviceIdleController;
122import android.os.INetworkManagementService;
123import android.os.IPowerManager;
124import android.os.Message;
125import android.os.MessageQueue.IdleHandler;
126import android.os.PowerManager;
127import android.os.PowerManagerInternal;
128import android.os.RemoteCallbackList;
129import android.os.RemoteException;
130import android.os.ServiceManager;
131import android.os.UserHandle;
132import android.os.UserManager;
133import android.provider.Settings;
134import android.telephony.SubscriptionManager;
135import android.telephony.TelephonyManager;
136import android.text.format.Formatter;
137import android.text.format.Time;
138import android.util.ArrayMap;
139import android.util.ArraySet;
140import android.util.AtomicFile;
141import android.util.Log;
142import android.util.NtpTrustedTime;
143import android.util.Pair;
144import android.util.Slog;
145import android.util.SparseBooleanArray;
146import android.util.SparseIntArray;
147import android.util.TrustedTime;
148import android.util.Xml;
149
150import com.android.server.EventLogTags;
151import libcore.io.IoUtils;
152
153import com.android.internal.R;
154import com.android.internal.annotations.VisibleForTesting;
155import com.android.internal.util.ArrayUtils;
156import com.android.internal.util.FastXmlSerializer;
157import com.android.internal.util.IndentingPrintWriter;
158import com.android.server.LocalServices;
159import com.google.android.collect.Lists;
160
161import org.xmlpull.v1.XmlPullParser;
162import org.xmlpull.v1.XmlPullParserException;
163import org.xmlpull.v1.XmlSerializer;
164
165import java.io.File;
166import java.io.FileDescriptor;
167import java.io.FileInputStream;
168import java.io.FileNotFoundException;
169import java.io.FileOutputStream;
170import java.io.IOException;
171import java.io.PrintWriter;
172import java.nio.charset.StandardCharsets;
173import java.util.ArrayList;
174import java.util.Arrays;
175import java.util.List;
176
177/**
178 * Service that maintains low-level network policy rules, using
179 * {@link NetworkStatsService} statistics to drive those rules.
180 * <p>
181 * Derives active rules by combining a given policy with other system status,
182 * and delivers to listeners, such as {@link ConnectivityManager}, for
183 * enforcement.
184 */
185public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
186    private static final String TAG = "NetworkPolicy";
187    private static final boolean LOGD = false;
188    private static final boolean LOGV = false;
189
190    private static final int VERSION_INIT = 1;
191    private static final int VERSION_ADDED_SNOOZE = 2;
192    private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3;
193    private static final int VERSION_ADDED_METERED = 4;
194    private static final int VERSION_SPLIT_SNOOZE = 5;
195    private static final int VERSION_ADDED_TIMEZONE = 6;
196    private static final int VERSION_ADDED_INFERRED = 7;
197    private static final int VERSION_SWITCH_APP_ID = 8;
198    private static final int VERSION_ADDED_NETWORK_ID = 9;
199    private static final int VERSION_SWITCH_UID = 10;
200    private static final int VERSION_LATEST = VERSION_SWITCH_UID;
201
202    @VisibleForTesting
203    public static final int TYPE_WARNING = 0x1;
204    @VisibleForTesting
205    public static final int TYPE_LIMIT = 0x2;
206    @VisibleForTesting
207    public static final int TYPE_LIMIT_SNOOZED = 0x3;
208
209    private static final String TAG_POLICY_LIST = "policy-list";
210    private static final String TAG_NETWORK_POLICY = "network-policy";
211    private static final String TAG_UID_POLICY = "uid-policy";
212    private static final String TAG_APP_POLICY = "app-policy";
213
214    private static final String ATTR_VERSION = "version";
215    private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
216    private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
217    private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
218    private static final String ATTR_NETWORK_ID = "networkId";
219    private static final String ATTR_CYCLE_DAY = "cycleDay";
220    private static final String ATTR_CYCLE_TIMEZONE = "cycleTimezone";
221    private static final String ATTR_WARNING_BYTES = "warningBytes";
222    private static final String ATTR_LIMIT_BYTES = "limitBytes";
223    private static final String ATTR_LAST_SNOOZE = "lastSnooze";
224    private static final String ATTR_LAST_WARNING_SNOOZE = "lastWarningSnooze";
225    private static final String ATTR_LAST_LIMIT_SNOOZE = "lastLimitSnooze";
226    private static final String ATTR_METERED = "metered";
227    private static final String ATTR_INFERRED = "inferred";
228    private static final String ATTR_UID = "uid";
229    private static final String ATTR_APP_ID = "appId";
230    private static final String ATTR_POLICY = "policy";
231
232    private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground";
233
234    private static final String ACTION_ALLOW_BACKGROUND =
235            "com.android.server.net.action.ALLOW_BACKGROUND";
236    private static final String ACTION_SNOOZE_WARNING =
237            "com.android.server.net.action.SNOOZE_WARNING";
238
239    private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
240
241    private static final int MSG_RULES_CHANGED = 1;
242    private static final int MSG_METERED_IFACES_CHANGED = 2;
243    private static final int MSG_LIMIT_REACHED = 5;
244    private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6;
245    private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7;
246    private static final int MSG_SCREEN_ON_CHANGED = 8;
247
248    private final Context mContext;
249    private final IActivityManager mActivityManager;
250    private final IPowerManager mPowerManager;
251    private final INetworkStatsService mNetworkStats;
252    private final INetworkManagementService mNetworkManager;
253    private UsageStatsManagerInternal mUsageStats;
254    private final TrustedTime mTime;
255    private final UserManager mUserManager;
256
257    private IConnectivityManager mConnManager;
258    private INotificationManager mNotifManager;
259    private PowerManagerInternal mPowerManagerInternal;
260    private IDeviceIdleController mDeviceIdleController;
261
262    final Object mRulesLock = new Object();
263
264    volatile boolean mSystemReady;
265    volatile boolean mScreenOn;
266    volatile boolean mRestrictBackground;
267    volatile boolean mRestrictPower;
268    volatile boolean mDeviceIdleMode;
269
270    private final boolean mSuppressDefaultPolicy;
271
272    /** Defined network policies. */
273    final ArrayMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = new ArrayMap<>();
274    /** Currently active network rules for ifaces. */
275    final ArrayMap<NetworkPolicy, String[]> mNetworkRules = new ArrayMap<>();
276
277    /** Defined UID policies. */
278    final SparseIntArray mUidPolicy = new SparseIntArray();
279    /** Currently derived rules for each UID. */
280    final SparseIntArray mUidRules = new SparseIntArray();
281    /** Set of states for the child firewall chains. True if the chain is active. */
282    final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
283
284    /**
285     * UIDs that have been white-listed to always be able to have network access
286     * in power save mode.
287     * TODO: An int array might be sufficient
288     */
289    private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray();
290
291    private final SparseBooleanArray mPowerSaveTempWhitelistAppIds = new SparseBooleanArray();
292
293    /** Set of ifaces that are metered. */
294    private ArraySet<String> mMeteredIfaces = new ArraySet<>();
295    /** Set of over-limit templates that have been notified. */
296    private final ArraySet<NetworkTemplate> mOverLimitNotified = new ArraySet<>();
297
298    /** Set of currently active {@link Notification} tags. */
299    private final ArraySet<String> mActiveNotifs = new ArraySet<String>();
300
301    /** Foreground at UID granularity. */
302    final SparseIntArray mUidState = new SparseIntArray();
303
304    /** The current maximum process state that we are considering to be foreground. */
305    private int mCurForegroundState = ActivityManager.PROCESS_STATE_TOP;
306
307    private final RemoteCallbackList<INetworkPolicyListener>
308            mListeners = new RemoteCallbackList<>();
309
310    final Handler mHandler;
311
312    private final AtomicFile mPolicyFile;
313
314    private final AppOpsManager mAppOps;
315
316    // TODO: keep whitelist of system-critical services that should never have
317    // rules enforced, such as system, phone, and radio UIDs.
318
319    // TODO: migrate notifications to SystemUI
320
321    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
322            IPowerManager powerManager, INetworkStatsService networkStats,
323            INetworkManagementService networkManagement) {
324        this(context, activityManager, powerManager, networkStats, networkManagement,
325                NtpTrustedTime.getInstance(context), getSystemDir(), false);
326    }
327
328    private static File getSystemDir() {
329        return new File(Environment.getDataDirectory(), "system");
330    }
331
332    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
333            IPowerManager powerManager, INetworkStatsService networkStats,
334            INetworkManagementService networkManagement, TrustedTime time, File systemDir,
335            boolean suppressDefaultPolicy) {
336        mContext = checkNotNull(context, "missing context");
337        mActivityManager = checkNotNull(activityManager, "missing activityManager");
338        mPowerManager = checkNotNull(powerManager, "missing powerManager");
339        mNetworkStats = checkNotNull(networkStats, "missing networkStats");
340        mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
341        mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService(
342                Context.DEVICE_IDLE_CONTROLLER));
343        mTime = checkNotNull(time, "missing TrustedTime");
344        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
345
346        HandlerThread thread = new HandlerThread(TAG);
347        thread.start();
348        mHandler = new Handler(thread.getLooper(), mHandlerCallback);
349
350        mSuppressDefaultPolicy = suppressDefaultPolicy;
351
352        mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
353
354        mAppOps = context.getSystemService(AppOpsManager.class);
355    }
356
357    public void bindConnectivityManager(IConnectivityManager connManager) {
358        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
359    }
360
361    public void bindNotificationManager(INotificationManager notifManager) {
362        mNotifManager = checkNotNull(notifManager, "missing INotificationManager");
363    }
364
365    void updatePowerSaveWhitelistLocked() {
366        try {
367            final int[] whitelist = mDeviceIdleController.getAppIdWhitelist();
368            mPowerSaveWhitelistAppIds.clear();
369            if (whitelist != null) {
370                for (int uid : whitelist) {
371                    mPowerSaveWhitelistAppIds.put(uid, true);
372                }
373            }
374        } catch (RemoteException e) {
375        }
376    }
377
378    void updatePowerSaveTempWhitelistLocked() {
379        try {
380            // Clear the states of the current whitelist
381            final int N = mPowerSaveTempWhitelistAppIds.size();
382            for (int i = 0; i < N; i++) {
383                mPowerSaveTempWhitelistAppIds.setValueAt(i, false);
384            }
385            // Update the states with the new whitelist
386            final int[] whitelist = mDeviceIdleController.getAppIdTempWhitelist();
387            if (whitelist != null) {
388                for (int uid : whitelist) {
389                    mPowerSaveTempWhitelistAppIds.put(uid, true);
390                }
391            }
392        } catch (RemoteException e) {
393        }
394    }
395
396    /**
397     * Remove unnecessary entries in the temp whitelist
398     */
399    void purgePowerSaveTempWhitelistLocked() {
400        final int N = mPowerSaveTempWhitelistAppIds.size();
401        for (int i = N - 1; i >= 0; i--) {
402            if (mPowerSaveTempWhitelistAppIds.valueAt(i) == false) {
403                mPowerSaveTempWhitelistAppIds.removeAt(i);
404            }
405        }
406    }
407
408    public void systemReady() {
409        if (!isBandwidthControlEnabled()) {
410            Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy");
411            return;
412        }
413
414        mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
415
416        synchronized (mRulesLock) {
417            updatePowerSaveWhitelistLocked();
418            mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
419            mPowerManagerInternal.registerLowPowerModeObserver(
420                    new PowerManagerInternal.LowPowerModeListener() {
421                @Override
422                public void onLowPowerModeChanged(boolean enabled) {
423                    synchronized (mRulesLock) {
424                        if (mRestrictPower != enabled) {
425                            mRestrictPower = enabled;
426                            updateRulesForGlobalChangeLocked(true);
427                            updateRulesForTempWhitelistChangeLocked();
428                        }
429                    }
430                }
431            });
432            mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
433            mSystemReady = true;
434
435            // read policy from disk
436            readPolicyLocked();
437
438            if (mRestrictBackground || mRestrictPower || mDeviceIdleMode) {
439                updateRulesForGlobalChangeLocked(true);
440                updateRulesForTempWhitelistChangeLocked();
441                updateNotificationsLocked();
442            }
443        }
444
445        updateScreenOn();
446
447        try {
448            mActivityManager.registerUidObserver(mUidObserver);
449            mNetworkManager.registerObserver(mAlertObserver);
450        } catch (RemoteException e) {
451            // ignored; both services live in system_server
452        }
453
454        // TODO: traverse existing processes to know foreground state, or have
455        // activitymanager dispatch current state when new observer attached.
456
457        final IntentFilter screenFilter = new IntentFilter();
458        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
459        screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
460        mContext.registerReceiver(mScreenReceiver, screenFilter);
461
462        // listen for changes to power save whitelist
463        final IntentFilter whitelistFilter = new IntentFilter(
464                PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
465        whitelistFilter.addAction(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
466        mContext.registerReceiver(mPowerSaveWhitelistReceiver, whitelistFilter, null, mHandler);
467
468        // watch for network interfaces to be claimed
469        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
470        mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
471
472        // listen for package changes to update policy
473        final IntentFilter packageFilter = new IntentFilter();
474        packageFilter.addAction(ACTION_PACKAGE_ADDED);
475        packageFilter.addDataScheme("package");
476        mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
477
478        // listen for UID changes to update policy
479        mContext.registerReceiver(
480                mUidRemovedReceiver, new IntentFilter(ACTION_UID_REMOVED), null, mHandler);
481
482        // listen for user changes to update policy
483        final IntentFilter userFilter = new IntentFilter();
484        userFilter.addAction(ACTION_USER_ADDED);
485        userFilter.addAction(ACTION_USER_REMOVED);
486        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
487
488        // listen for stats update events
489        final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
490        mContext.registerReceiver(
491                mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
492
493        // listen for restrict background changes from notifications
494        final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
495        mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler);
496
497        // listen for snooze warning from notifications
498        final IntentFilter snoozeWarningFilter = new IntentFilter(ACTION_SNOOZE_WARNING);
499        mContext.registerReceiver(mSnoozeWarningReceiver, snoozeWarningFilter,
500                MANAGE_NETWORK_POLICY, mHandler);
501
502        // listen for configured wifi networks to be removed
503        final IntentFilter wifiConfigFilter = new IntentFilter(CONFIGURED_NETWORKS_CHANGED_ACTION);
504        mContext.registerReceiver(mWifiConfigReceiver, wifiConfigFilter, null, mHandler);
505
506        // listen for wifi state changes to catch metered hint
507        final IntentFilter wifiStateFilter = new IntentFilter(
508                WifiManager.NETWORK_STATE_CHANGED_ACTION);
509        mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler);
510
511        mUsageStats.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
512
513    }
514
515    private IUidObserver mUidObserver = new IUidObserver.Stub() {
516        @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
517            synchronized (mRulesLock) {
518                updateUidStateLocked(uid, procState);
519            }
520        }
521
522        @Override public void onUidGone(int uid) throws RemoteException {
523            synchronized (mRulesLock) {
524                removeUidStateLocked(uid);
525            }
526        }
527    };
528
529    private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() {
530        @Override
531        public void onReceive(Context context, Intent intent) {
532            // on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected
533            synchronized (mRulesLock) {
534                if (PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED.equals(intent.getAction())) {
535                    updatePowerSaveWhitelistLocked();
536                    updateRulesForGlobalChangeLocked(false);
537                } else {
538                    updatePowerSaveTempWhitelistLocked();
539                    updateRulesForTempWhitelistChangeLocked();
540                    purgePowerSaveTempWhitelistLocked();
541                }
542            }
543        }
544    };
545
546    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
547        @Override
548        public void onReceive(Context context, Intent intent) {
549            // screen-related broadcasts are protected by system, no need
550            // for permissions check.
551            mHandler.obtainMessage(MSG_SCREEN_ON_CHANGED).sendToTarget();
552        }
553    };
554
555    private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
556        @Override
557        public void onReceive(Context context, Intent intent) {
558            // on background handler thread, and PACKAGE_ADDED is protected
559
560            final String action = intent.getAction();
561            final int uid = intent.getIntExtra(EXTRA_UID, -1);
562            if (uid == -1) return;
563
564            if (ACTION_PACKAGE_ADDED.equals(action)) {
565                // update rules for UID, since it might be subject to
566                // global background data policy
567                if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
568                synchronized (mRulesLock) {
569                    updateRulesForUidLocked(uid);
570                }
571            }
572        }
573    };
574
575    private BroadcastReceiver mUidRemovedReceiver = new BroadcastReceiver() {
576        @Override
577        public void onReceive(Context context, Intent intent) {
578            // on background handler thread, and UID_REMOVED is protected
579
580            final int uid = intent.getIntExtra(EXTRA_UID, -1);
581            if (uid == -1) return;
582
583            // remove any policy and update rules to clean up
584            if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
585            synchronized (mRulesLock) {
586                mUidPolicy.delete(uid);
587                updateRulesForUidLocked(uid);
588                writePolicyLocked();
589            }
590        }
591    };
592
593    private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
594        @Override
595        public void onReceive(Context context, Intent intent) {
596            // on background handler thread, and USER_ADDED and USER_REMOVED
597            // broadcasts are protected
598
599            final String action = intent.getAction();
600            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
601            if (userId == -1) return;
602
603            switch (action) {
604                case ACTION_USER_REMOVED:
605                case ACTION_USER_ADDED:
606                    synchronized (mRulesLock) {
607                        // Remove any policies for given user; both cleaning up after a
608                        // USER_REMOVED, and one last sanity check during USER_ADDED
609                        removePoliciesForUserLocked(userId);
610                        // Update global restrict for new user
611                        updateRulesForGlobalChangeLocked(true);
612                    }
613                    break;
614            }
615        }
616    };
617
618    /**
619     * Receiver that watches for {@link INetworkStatsService} updates, which we
620     * use to check against {@link NetworkPolicy#warningBytes}.
621     */
622    private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() {
623        @Override
624        public void onReceive(Context context, Intent intent) {
625            // on background handler thread, and verified
626            // READ_NETWORK_USAGE_HISTORY permission above.
627
628            maybeRefreshTrustedTime();
629            synchronized (mRulesLock) {
630                updateNetworkEnabledLocked();
631                updateNotificationsLocked();
632            }
633        }
634    };
635
636    /**
637     * Receiver that watches for {@link Notification} control of
638     * {@link #mRestrictBackground}.
639     */
640    private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() {
641        @Override
642        public void onReceive(Context context, Intent intent) {
643            // on background handler thread, and verified MANAGE_NETWORK_POLICY
644            // permission above.
645
646            setRestrictBackground(false);
647        }
648    };
649
650    /**
651     * Receiver that watches for {@link Notification} control of
652     * {@link NetworkPolicy#lastWarningSnooze}.
653     */
654    private BroadcastReceiver mSnoozeWarningReceiver = new BroadcastReceiver() {
655        @Override
656        public void onReceive(Context context, Intent intent) {
657            // on background handler thread, and verified MANAGE_NETWORK_POLICY
658            // permission above.
659
660            final NetworkTemplate template = intent.getParcelableExtra(EXTRA_NETWORK_TEMPLATE);
661            performSnooze(template, TYPE_WARNING);
662        }
663    };
664
665    /**
666     * Receiver that watches for {@link WifiConfiguration} to be changed.
667     */
668    private BroadcastReceiver mWifiConfigReceiver = new BroadcastReceiver() {
669        @Override
670        public void onReceive(Context context, Intent intent) {
671            // on background handler thread, and verified CONNECTIVITY_INTERNAL
672            // permission above.
673
674            final int reason = intent.getIntExtra(EXTRA_CHANGE_REASON, CHANGE_REASON_ADDED);
675            if (reason == CHANGE_REASON_REMOVED) {
676                final WifiConfiguration config = intent.getParcelableExtra(
677                        EXTRA_WIFI_CONFIGURATION);
678                if (config.SSID != null) {
679                    final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(config.SSID);
680                    synchronized (mRulesLock) {
681                        if (mNetworkPolicy.containsKey(template)) {
682                            mNetworkPolicy.remove(template);
683                            writePolicyLocked();
684                        }
685                    }
686                }
687            }
688        }
689    };
690
691    /**
692     * Receiver that watches {@link WifiInfo} state changes to infer metered
693     * state. Ignores hints when policy is user-defined.
694     */
695    private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
696        @Override
697        public void onReceive(Context context, Intent intent) {
698            // on background handler thread, and verified CONNECTIVITY_INTERNAL
699            // permission above.
700
701            // ignore when not connected
702            final NetworkInfo netInfo = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
703            if (!netInfo.isConnected()) return;
704
705            final WifiInfo info = intent.getParcelableExtra(EXTRA_WIFI_INFO);
706            final boolean meteredHint = info.getMeteredHint();
707
708            final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(info.getSSID());
709            synchronized (mRulesLock) {
710                NetworkPolicy policy = mNetworkPolicy.get(template);
711                if (policy == null && meteredHint) {
712                    // policy doesn't exist, and AP is hinting that it's
713                    // metered: create an inferred policy.
714                    policy = new NetworkPolicy(template, CYCLE_NONE, Time.TIMEZONE_UTC,
715                            WARNING_DISABLED, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER,
716                            meteredHint, true);
717                    addNetworkPolicyLocked(policy);
718
719                } else if (policy != null && policy.inferred) {
720                    // policy exists, and was inferred: update its current
721                    // metered state.
722                    policy.metered = meteredHint;
723
724                    // since this is inferred for each wifi session, just update
725                    // rules without persisting.
726                    updateNetworkRulesLocked();
727                }
728            }
729        }
730    };
731
732    /**
733     * Observer that watches for {@link INetworkManagementService} alerts.
734     */
735    private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
736        @Override
737        public void limitReached(String limitName, String iface) {
738            // only someone like NMS should be calling us
739            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
740
741            if (!LIMIT_GLOBAL_ALERT.equals(limitName)) {
742                mHandler.obtainMessage(MSG_LIMIT_REACHED, iface).sendToTarget();
743            }
744        }
745    };
746
747    /**
748     * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
749     * to show visible notifications as needed.
750     */
751    void updateNotificationsLocked() {
752        if (LOGV) Slog.v(TAG, "updateNotificationsLocked()");
753
754        // keep track of previously active notifications
755        final ArraySet<String> beforeNotifs = new ArraySet<String>(mActiveNotifs);
756        mActiveNotifs.clear();
757
758        // TODO: when switching to kernel notifications, compute next future
759        // cycle boundary to recompute notifications.
760
761        // examine stats for each active policy
762        final long currentTime = currentTimeMillis();
763        for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
764            final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
765            // ignore policies that aren't relevant to user
766            if (!isTemplateRelevant(policy.template)) continue;
767            if (!policy.hasCycle()) continue;
768
769            final long start = computeLastCycleBoundary(currentTime, policy);
770            final long end = currentTime;
771            final long totalBytes = getTotalBytes(policy.template, start, end);
772
773            if (policy.isOverLimit(totalBytes)) {
774                if (policy.lastLimitSnooze >= start) {
775                    enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
776                } else {
777                    enqueueNotification(policy, TYPE_LIMIT, totalBytes);
778                    notifyOverLimitLocked(policy.template);
779                }
780
781            } else {
782                notifyUnderLimitLocked(policy.template);
783
784                if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start) {
785                    enqueueNotification(policy, TYPE_WARNING, totalBytes);
786                }
787            }
788        }
789
790        // ongoing notification when restricting background data
791        if (mRestrictBackground) {
792            enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND);
793        }
794
795        // cancel stale notifications that we didn't renew above
796        for (int i = beforeNotifs.size()-1; i >= 0; i--) {
797            final String tag = beforeNotifs.valueAt(i);
798            if (!mActiveNotifs.contains(tag)) {
799                cancelNotification(tag);
800            }
801        }
802    }
803
804    /**
805     * Test if given {@link NetworkTemplate} is relevant to user based on
806     * current device state, such as when
807     * {@link TelephonyManager#getSubscriberId()} matches. This is regardless of
808     * data connection status.
809     */
810    private boolean isTemplateRelevant(NetworkTemplate template) {
811        if (template.isMatchRuleMobile()) {
812            final TelephonyManager tele = TelephonyManager.from(mContext);
813            final SubscriptionManager sub = SubscriptionManager.from(mContext);
814
815            // Mobile template is relevant when any active subscriber matches
816            final int[] subIds = sub.getActiveSubscriptionIdList();
817            for (int subId : subIds) {
818                final String subscriberId = tele.getSubscriberId(subId);
819                final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
820                        TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
821                if (template.matches(probeIdent)) {
822                    return true;
823                }
824            }
825            return false;
826        } else {
827            return true;
828        }
829    }
830
831    /**
832     * Notify that given {@link NetworkTemplate} is over
833     * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
834     */
835    private void notifyOverLimitLocked(NetworkTemplate template) {
836        if (!mOverLimitNotified.contains(template)) {
837            mContext.startActivity(buildNetworkOverLimitIntent(template));
838            mOverLimitNotified.add(template);
839        }
840    }
841
842    private void notifyUnderLimitLocked(NetworkTemplate template) {
843        mOverLimitNotified.remove(template);
844    }
845
846    /**
847     * Build unique tag that identifies an active {@link NetworkPolicy}
848     * notification of a specific type, like {@link #TYPE_LIMIT}.
849     */
850    private String buildNotificationTag(NetworkPolicy policy, int type) {
851        return TAG + ":" + policy.template.hashCode() + ":" + type;
852    }
853
854    /**
855     * Show notification for combined {@link NetworkPolicy} and specific type,
856     * like {@link #TYPE_LIMIT}. Okay to call multiple times.
857     */
858    private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
859        final String tag = buildNotificationTag(policy, type);
860        final Notification.Builder builder = new Notification.Builder(mContext);
861        builder.setOnlyAlertOnce(true);
862        builder.setWhen(0L);
863        builder.setColor(mContext.getColor(
864                com.android.internal.R.color.system_notification_accent_color));
865
866        final Resources res = mContext.getResources();
867        switch (type) {
868            case TYPE_WARNING: {
869                final CharSequence title = res.getText(R.string.data_usage_warning_title);
870                final CharSequence body = res.getString(R.string.data_usage_warning_body);
871
872                builder.setSmallIcon(R.drawable.stat_notify_error);
873                builder.setTicker(title);
874                builder.setContentTitle(title);
875                builder.setContentText(body);
876
877                final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template);
878                builder.setDeleteIntent(PendingIntent.getBroadcast(
879                        mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
880
881                final Intent viewIntent = buildViewDataUsageIntent(policy.template);
882                builder.setContentIntent(PendingIntent.getActivity(
883                        mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT));
884
885                break;
886            }
887            case TYPE_LIMIT: {
888                final CharSequence body = res.getText(R.string.data_usage_limit_body);
889
890                final CharSequence title;
891                int icon = R.drawable.stat_notify_disabled_data;
892                switch (policy.template.getMatchRule()) {
893                    case MATCH_MOBILE_3G_LOWER:
894                        title = res.getText(R.string.data_usage_3g_limit_title);
895                        break;
896                    case MATCH_MOBILE_4G:
897                        title = res.getText(R.string.data_usage_4g_limit_title);
898                        break;
899                    case MATCH_MOBILE_ALL:
900                        title = res.getText(R.string.data_usage_mobile_limit_title);
901                        break;
902                    case MATCH_WIFI:
903                        title = res.getText(R.string.data_usage_wifi_limit_title);
904                        icon = R.drawable.stat_notify_error;
905                        break;
906                    default:
907                        title = null;
908                        break;
909                }
910
911                builder.setOngoing(true);
912                builder.setSmallIcon(icon);
913                builder.setTicker(title);
914                builder.setContentTitle(title);
915                builder.setContentText(body);
916
917                final Intent intent = buildNetworkOverLimitIntent(policy.template);
918                builder.setContentIntent(PendingIntent.getActivity(
919                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
920                break;
921            }
922            case TYPE_LIMIT_SNOOZED: {
923                final long overBytes = totalBytes - policy.limitBytes;
924                final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body,
925                        Formatter.formatFileSize(mContext, overBytes));
926
927                final CharSequence title;
928                switch (policy.template.getMatchRule()) {
929                    case MATCH_MOBILE_3G_LOWER:
930                        title = res.getText(R.string.data_usage_3g_limit_snoozed_title);
931                        break;
932                    case MATCH_MOBILE_4G:
933                        title = res.getText(R.string.data_usage_4g_limit_snoozed_title);
934                        break;
935                    case MATCH_MOBILE_ALL:
936                        title = res.getText(R.string.data_usage_mobile_limit_snoozed_title);
937                        break;
938                    case MATCH_WIFI:
939                        title = res.getText(R.string.data_usage_wifi_limit_snoozed_title);
940                        break;
941                    default:
942                        title = null;
943                        break;
944                }
945
946                builder.setOngoing(true);
947                builder.setSmallIcon(R.drawable.stat_notify_error);
948                builder.setTicker(title);
949                builder.setContentTitle(title);
950                builder.setContentText(body);
951
952                final Intent intent = buildViewDataUsageIntent(policy.template);
953                builder.setContentIntent(PendingIntent.getActivity(
954                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
955                break;
956            }
957        }
958
959        // TODO: move to NotificationManager once we can mock it
960        // XXX what to do about multi-user?
961        try {
962            final String packageName = mContext.getPackageName();
963            final int[] idReceived = new int[1];
964            mNotifManager.enqueueNotificationWithTag(
965                    packageName, packageName, tag, 0x0, builder.getNotification(), idReceived,
966                    UserHandle.USER_OWNER);
967            mActiveNotifs.add(tag);
968        } catch (RemoteException e) {
969            // ignored; service lives in system_server
970        }
971    }
972
973    /**
974     * Show ongoing notification to reflect that {@link #mRestrictBackground}
975     * has been enabled.
976     */
977    private void enqueueRestrictedNotification(String tag) {
978        final Resources res = mContext.getResources();
979        final Notification.Builder builder = new Notification.Builder(mContext);
980
981        final CharSequence title = res.getText(R.string.data_usage_restricted_title);
982        final CharSequence body = res.getString(R.string.data_usage_restricted_body);
983
984        builder.setOnlyAlertOnce(true);
985        builder.setOngoing(true);
986        builder.setSmallIcon(R.drawable.stat_notify_error);
987        builder.setTicker(title);
988        builder.setContentTitle(title);
989        builder.setContentText(body);
990        builder.setColor(mContext.getColor(
991                com.android.internal.R.color.system_notification_accent_color));
992
993        final Intent intent = buildAllowBackgroundDataIntent();
994        builder.setContentIntent(
995                PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
996
997        // TODO: move to NotificationManager once we can mock it
998        // XXX what to do about multi-user?
999        try {
1000            final String packageName = mContext.getPackageName();
1001            final int[] idReceived = new int[1];
1002            mNotifManager.enqueueNotificationWithTag(packageName, packageName, tag,
1003                    0x0, builder.getNotification(), idReceived, UserHandle.USER_OWNER);
1004            mActiveNotifs.add(tag);
1005        } catch (RemoteException e) {
1006            // ignored; service lives in system_server
1007        }
1008    }
1009
1010    private void cancelNotification(String tag) {
1011        // TODO: move to NotificationManager once we can mock it
1012        // XXX what to do about multi-user?
1013        try {
1014            final String packageName = mContext.getPackageName();
1015            mNotifManager.cancelNotificationWithTag(
1016                    packageName, tag, 0x0, UserHandle.USER_OWNER);
1017        } catch (RemoteException e) {
1018            // ignored; service lives in system_server
1019        }
1020    }
1021
1022    /**
1023     * Receiver that watches for {@link IConnectivityManager} to claim network
1024     * interfaces. Used to apply {@link NetworkPolicy} to matching networks.
1025     */
1026    private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
1027        @Override
1028        public void onReceive(Context context, Intent intent) {
1029            // on background handler thread, and verified CONNECTIVITY_INTERNAL
1030            // permission above.
1031
1032            maybeRefreshTrustedTime();
1033            synchronized (mRulesLock) {
1034                ensureActiveMobilePolicyLocked();
1035                normalizePoliciesLocked();
1036                updateNetworkEnabledLocked();
1037                updateNetworkRulesLocked();
1038                updateNotificationsLocked();
1039            }
1040        }
1041    };
1042
1043    /**
1044     * Proactively control network data connections when they exceed
1045     * {@link NetworkPolicy#limitBytes}.
1046     */
1047    void updateNetworkEnabledLocked() {
1048        if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()");
1049
1050        // TODO: reset any policy-disabled networks when any policy is removed
1051        // completely, which is currently rare case.
1052
1053        final long currentTime = currentTimeMillis();
1054        for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
1055            final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
1056            // shortcut when policy has no limit
1057            if (policy.limitBytes == LIMIT_DISABLED || !policy.hasCycle()) {
1058                setNetworkTemplateEnabled(policy.template, true);
1059                continue;
1060            }
1061
1062            final long start = computeLastCycleBoundary(currentTime, policy);
1063            final long end = currentTime;
1064            final long totalBytes = getTotalBytes(policy.template, start, end);
1065
1066            // disable data connection when over limit and not snoozed
1067            final boolean overLimitWithoutSnooze = policy.isOverLimit(totalBytes)
1068                    && policy.lastLimitSnooze < start;
1069            final boolean networkEnabled = !overLimitWithoutSnooze;
1070
1071            setNetworkTemplateEnabled(policy.template, networkEnabled);
1072        }
1073    }
1074
1075    /**
1076     * Proactively disable networks that match the given
1077     * {@link NetworkTemplate}.
1078     */
1079    private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
1080        // TODO: reach into ConnectivityManager to proactively disable bringing
1081        // up this network, since we know that traffic will be blocked.
1082    }
1083
1084    /**
1085     * Examine all connected {@link NetworkState}, looking for
1086     * {@link NetworkPolicy} that need to be enforced. When matches found, set
1087     * remaining quota based on usage cycle and historical stats.
1088     */
1089    void updateNetworkRulesLocked() {
1090        if (LOGV) Slog.v(TAG, "updateNetworkRulesLocked()");
1091
1092        final NetworkState[] states;
1093        try {
1094            states = mConnManager.getAllNetworkState();
1095        } catch (RemoteException e) {
1096            // ignored; service lives in system_server
1097            return;
1098        }
1099
1100        // If we are in restrict power mode, we want to treat all interfaces
1101        // as metered, to restrict access to the network by uid.  However, we
1102        // will not have a bandwidth limit.  Also only do this if restrict
1103        // background data use is *not* enabled, since that takes precendence
1104        // use over those networks can have a cost associated with it).
1105        final boolean powerSave = mRestrictPower && !mRestrictBackground;
1106
1107        // First, generate identities of all connected networks so we can
1108        // quickly compare them against all defined policies below.
1109        final ArrayList<Pair<String, NetworkIdentity>> connIdents = new ArrayList<>(states.length);
1110        final ArraySet<String> connIfaces = new ArraySet<String>(states.length);
1111        for (NetworkState state : states) {
1112            if (state.networkInfo.isConnected()) {
1113                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
1114
1115                final String baseIface = state.linkProperties.getInterfaceName();
1116                if (baseIface != null) {
1117                    connIdents.add(Pair.create(baseIface, ident));
1118                    if (powerSave) {
1119                        connIfaces.add(baseIface);
1120                    }
1121                }
1122
1123                // Stacked interfaces are considered to have same identity as
1124                // their parent network.
1125                final List<LinkProperties> stackedLinks = state.linkProperties.getStackedLinks();
1126                for (LinkProperties stackedLink : stackedLinks) {
1127                    final String stackedIface = stackedLink.getInterfaceName();
1128                    if (stackedIface != null) {
1129                        connIdents.add(Pair.create(stackedIface, ident));
1130                        if (powerSave) {
1131                            connIfaces.add(stackedIface);
1132                        }
1133                    }
1134                }
1135            }
1136        }
1137
1138        // Apply policies against all connected interfaces found above
1139        mNetworkRules.clear();
1140        final ArrayList<String> ifaceList = Lists.newArrayList();
1141        for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
1142            final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
1143
1144            ifaceList.clear();
1145            for (int j = connIdents.size() - 1; j >= 0; j--) {
1146                final Pair<String, NetworkIdentity> ident = connIdents.get(j);
1147                if (policy.template.matches(ident.second)) {
1148                    ifaceList.add(ident.first);
1149                }
1150            }
1151
1152            if (ifaceList.size() > 0) {
1153                final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]);
1154                mNetworkRules.put(policy, ifaces);
1155            }
1156        }
1157
1158        long lowestRule = Long.MAX_VALUE;
1159        final ArraySet<String> newMeteredIfaces = new ArraySet<String>(states.length);
1160
1161        // apply each policy that we found ifaces for; compute remaining data
1162        // based on current cycle and historical stats, and push to kernel.
1163        final long currentTime = currentTimeMillis();
1164        for (int i = mNetworkRules.size()-1; i >= 0; i--) {
1165            final NetworkPolicy policy = mNetworkRules.keyAt(i);
1166            final String[] ifaces = mNetworkRules.valueAt(i);
1167
1168            final long start;
1169            final long totalBytes;
1170            if (policy.hasCycle()) {
1171                start = computeLastCycleBoundary(currentTime, policy);
1172                totalBytes = getTotalBytes(policy.template, start, currentTime);
1173            } else {
1174                start = Long.MAX_VALUE;
1175                totalBytes = 0;
1176            }
1177
1178            if (LOGD) {
1179                Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
1180                        + Arrays.toString(ifaces));
1181            }
1182
1183            final boolean hasWarning = policy.warningBytes != LIMIT_DISABLED;
1184            final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
1185            if (hasLimit || policy.metered) {
1186                final long quotaBytes;
1187                if (!hasLimit) {
1188                    // metered network, but no policy limit; we still need to
1189                    // restrict apps, so push really high quota.
1190                    quotaBytes = Long.MAX_VALUE;
1191                } else if (policy.lastLimitSnooze >= start) {
1192                    // snoozing past quota, but we still need to restrict apps,
1193                    // so push really high quota.
1194                    quotaBytes = Long.MAX_VALUE;
1195                } else {
1196                    // remaining "quota" bytes are based on total usage in
1197                    // current cycle. kernel doesn't like 0-byte rules, so we
1198                    // set 1-byte quota and disable the radio later.
1199                    quotaBytes = Math.max(1, policy.limitBytes - totalBytes);
1200                }
1201
1202                if (ifaces.length > 1) {
1203                    // TODO: switch to shared quota once NMS supports
1204                    Slog.w(TAG, "shared quota unsupported; generating rule for each iface");
1205                }
1206
1207                for (String iface : ifaces) {
1208                    removeInterfaceQuota(iface);
1209                    setInterfaceQuota(iface, quotaBytes);
1210                    newMeteredIfaces.add(iface);
1211                    if (powerSave) {
1212                        connIfaces.remove(iface);
1213                    }
1214                }
1215            }
1216
1217            // keep track of lowest warning or limit of active policies
1218            if (hasWarning && policy.warningBytes < lowestRule) {
1219                lowestRule = policy.warningBytes;
1220            }
1221            if (hasLimit && policy.limitBytes < lowestRule) {
1222                lowestRule = policy.limitBytes;
1223            }
1224        }
1225
1226        for (int i = connIfaces.size()-1; i >= 0; i--) {
1227            String iface = connIfaces.valueAt(i);
1228            removeInterfaceQuota(iface);
1229            setInterfaceQuota(iface, Long.MAX_VALUE);
1230            newMeteredIfaces.add(iface);
1231        }
1232
1233        mHandler.obtainMessage(MSG_ADVISE_PERSIST_THRESHOLD, lowestRule).sendToTarget();
1234
1235        // remove quota on any trailing interfaces
1236        for (int i = mMeteredIfaces.size() - 1; i >= 0; i--) {
1237            final String iface = mMeteredIfaces.valueAt(i);
1238            if (!newMeteredIfaces.contains(iface)) {
1239                removeInterfaceQuota(iface);
1240            }
1241        }
1242        mMeteredIfaces = newMeteredIfaces;
1243
1244        final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
1245        mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
1246    }
1247
1248    /**
1249     * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
1250     * have at least a default mobile policy defined.
1251     */
1252    private void ensureActiveMobilePolicyLocked() {
1253        if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
1254        if (mSuppressDefaultPolicy) return;
1255
1256        final TelephonyManager tele = TelephonyManager.from(mContext);
1257        final SubscriptionManager sub = SubscriptionManager.from(mContext);
1258
1259        final int[] subIds = sub.getActiveSubscriptionIdList();
1260        for (int subId : subIds) {
1261            final String subscriberId = tele.getSubscriberId(subId);
1262            ensureActiveMobilePolicyLocked(subscriberId);
1263        }
1264    }
1265
1266    private void ensureActiveMobilePolicyLocked(String subscriberId) {
1267        // Poke around to see if we already have a policy
1268        final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
1269                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
1270        for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
1271            final NetworkTemplate template = mNetworkPolicy.keyAt(i);
1272            if (template.matches(probeIdent)) {
1273                if (LOGD) {
1274                    Slog.d(TAG, "Found template " + template + " which matches subscriber "
1275                            + NetworkIdentity.scrubSubscriberId(subscriberId));
1276                }
1277                return;
1278            }
1279        }
1280
1281        Slog.i(TAG, "No policy for subscriber " + NetworkIdentity.scrubSubscriberId(subscriberId)
1282                + "; generating default policy");
1283
1284        // Build default mobile policy, and assume usage cycle starts today
1285        final long warningBytes = mContext.getResources().getInteger(
1286                com.android.internal.R.integer.config_networkPolicyDefaultWarning) * MB_IN_BYTES;
1287
1288        final Time time = new Time();
1289        time.setToNow();
1290
1291        final int cycleDay = time.monthDay;
1292        final String cycleTimezone = time.timezone;
1293
1294        final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
1295        final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone,
1296                warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true);
1297        addNetworkPolicyLocked(policy);
1298    }
1299
1300    private void readPolicyLocked() {
1301        if (LOGV) Slog.v(TAG, "readPolicyLocked()");
1302
1303        // clear any existing policy and read from disk
1304        mNetworkPolicy.clear();
1305        mUidPolicy.clear();
1306
1307        FileInputStream fis = null;
1308        try {
1309            fis = mPolicyFile.openRead();
1310            final XmlPullParser in = Xml.newPullParser();
1311            in.setInput(fis, StandardCharsets.UTF_8.name());
1312
1313            int type;
1314            int version = VERSION_INIT;
1315            while ((type = in.next()) != END_DOCUMENT) {
1316                final String tag = in.getName();
1317                if (type == START_TAG) {
1318                    if (TAG_POLICY_LIST.equals(tag)) {
1319                        version = readIntAttribute(in, ATTR_VERSION);
1320                        if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) {
1321                            mRestrictBackground = readBooleanAttribute(
1322                                    in, ATTR_RESTRICT_BACKGROUND);
1323                        } else {
1324                            mRestrictBackground = false;
1325                        }
1326
1327                    } else if (TAG_NETWORK_POLICY.equals(tag)) {
1328                        final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
1329                        final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
1330                        final String networkId;
1331                        if (version >= VERSION_ADDED_NETWORK_ID) {
1332                            networkId = in.getAttributeValue(null, ATTR_NETWORK_ID);
1333                        } else {
1334                            networkId = null;
1335                        }
1336                        final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
1337                        final String cycleTimezone;
1338                        if (version >= VERSION_ADDED_TIMEZONE) {
1339                            cycleTimezone = in.getAttributeValue(null, ATTR_CYCLE_TIMEZONE);
1340                        } else {
1341                            cycleTimezone = Time.TIMEZONE_UTC;
1342                        }
1343                        final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
1344                        final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
1345                        final long lastLimitSnooze;
1346                        if (version >= VERSION_SPLIT_SNOOZE) {
1347                            lastLimitSnooze = readLongAttribute(in, ATTR_LAST_LIMIT_SNOOZE);
1348                        } else if (version >= VERSION_ADDED_SNOOZE) {
1349                            lastLimitSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
1350                        } else {
1351                            lastLimitSnooze = SNOOZE_NEVER;
1352                        }
1353                        final boolean metered;
1354                        if (version >= VERSION_ADDED_METERED) {
1355                            metered = readBooleanAttribute(in, ATTR_METERED);
1356                        } else {
1357                            switch (networkTemplate) {
1358                                case MATCH_MOBILE_3G_LOWER:
1359                                case MATCH_MOBILE_4G:
1360                                case MATCH_MOBILE_ALL:
1361                                    metered = true;
1362                                    break;
1363                                default:
1364                                    metered = false;
1365                            }
1366                        }
1367                        final long lastWarningSnooze;
1368                        if (version >= VERSION_SPLIT_SNOOZE) {
1369                            lastWarningSnooze = readLongAttribute(in, ATTR_LAST_WARNING_SNOOZE);
1370                        } else {
1371                            lastWarningSnooze = SNOOZE_NEVER;
1372                        }
1373                        final boolean inferred;
1374                        if (version >= VERSION_ADDED_INFERRED) {
1375                            inferred = readBooleanAttribute(in, ATTR_INFERRED);
1376                        } else {
1377                            inferred = false;
1378                        }
1379
1380                        final NetworkTemplate template = new NetworkTemplate(networkTemplate,
1381                                subscriberId, networkId);
1382                        mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay,
1383                                cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
1384                                lastLimitSnooze, metered, inferred));
1385
1386                    } else if (TAG_UID_POLICY.equals(tag)) {
1387                        final int uid = readIntAttribute(in, ATTR_UID);
1388                        final int policy = readIntAttribute(in, ATTR_POLICY);
1389
1390                        if (UserHandle.isApp(uid)) {
1391                            setUidPolicyUncheckedLocked(uid, policy, false);
1392                        } else {
1393                            Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
1394                        }
1395                    } else if (TAG_APP_POLICY.equals(tag)) {
1396                        final int appId = readIntAttribute(in, ATTR_APP_ID);
1397                        final int policy = readIntAttribute(in, ATTR_POLICY);
1398
1399                        // TODO: set for other users during upgrade
1400                        final int uid = UserHandle.getUid(UserHandle.USER_OWNER, appId);
1401                        if (UserHandle.isApp(uid)) {
1402                            setUidPolicyUncheckedLocked(uid, policy, false);
1403                        } else {
1404                            Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
1405                        }
1406                    }
1407                }
1408            }
1409
1410        } catch (FileNotFoundException e) {
1411            // missing policy is okay, probably first boot
1412            upgradeLegacyBackgroundData();
1413        } catch (IOException e) {
1414            Log.wtf(TAG, "problem reading network policy", e);
1415        } catch (XmlPullParserException e) {
1416            Log.wtf(TAG, "problem reading network policy", e);
1417        } finally {
1418            IoUtils.closeQuietly(fis);
1419        }
1420    }
1421
1422    /**
1423     * Upgrade legacy background data flags, notifying listeners of one last
1424     * change to always-true.
1425     */
1426    private void upgradeLegacyBackgroundData() {
1427        mRestrictBackground = Settings.Secure.getInt(
1428                mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1;
1429
1430        // kick off one last broadcast if restricted
1431        if (mRestrictBackground) {
1432            final Intent broadcast = new Intent(
1433                    ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
1434            mContext.sendBroadcastAsUser(broadcast, UserHandle.ALL);
1435        }
1436    }
1437
1438    void writePolicyLocked() {
1439        if (LOGV) Slog.v(TAG, "writePolicyLocked()");
1440
1441        FileOutputStream fos = null;
1442        try {
1443            fos = mPolicyFile.startWrite();
1444
1445            XmlSerializer out = new FastXmlSerializer();
1446            out.setOutput(fos, StandardCharsets.UTF_8.name());
1447            out.startDocument(null, true);
1448
1449            out.startTag(null, TAG_POLICY_LIST);
1450            writeIntAttribute(out, ATTR_VERSION, VERSION_LATEST);
1451            writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
1452
1453            // write all known network policies
1454            for (int i = 0; i < mNetworkPolicy.size(); i++) {
1455                final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
1456                final NetworkTemplate template = policy.template;
1457
1458                out.startTag(null, TAG_NETWORK_POLICY);
1459                writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
1460                final String subscriberId = template.getSubscriberId();
1461                if (subscriberId != null) {
1462                    out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
1463                }
1464                final String networkId = template.getNetworkId();
1465                if (networkId != null) {
1466                    out.attribute(null, ATTR_NETWORK_ID, networkId);
1467                }
1468                writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
1469                out.attribute(null, ATTR_CYCLE_TIMEZONE, policy.cycleTimezone);
1470                writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
1471                writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
1472                writeLongAttribute(out, ATTR_LAST_WARNING_SNOOZE, policy.lastWarningSnooze);
1473                writeLongAttribute(out, ATTR_LAST_LIMIT_SNOOZE, policy.lastLimitSnooze);
1474                writeBooleanAttribute(out, ATTR_METERED, policy.metered);
1475                writeBooleanAttribute(out, ATTR_INFERRED, policy.inferred);
1476                out.endTag(null, TAG_NETWORK_POLICY);
1477            }
1478
1479            // write all known uid policies
1480            for (int i = 0; i < mUidPolicy.size(); i++) {
1481                final int uid = mUidPolicy.keyAt(i);
1482                final int policy = mUidPolicy.valueAt(i);
1483
1484                // skip writing empty policies
1485                if (policy == POLICY_NONE) continue;
1486
1487                out.startTag(null, TAG_UID_POLICY);
1488                writeIntAttribute(out, ATTR_UID, uid);
1489                writeIntAttribute(out, ATTR_POLICY, policy);
1490                out.endTag(null, TAG_UID_POLICY);
1491            }
1492
1493            out.endTag(null, TAG_POLICY_LIST);
1494            out.endDocument();
1495
1496            mPolicyFile.finishWrite(fos);
1497        } catch (IOException e) {
1498            if (fos != null) {
1499                mPolicyFile.failWrite(fos);
1500            }
1501        }
1502    }
1503
1504    @Override
1505    public void setUidPolicy(int uid, int policy) {
1506        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1507
1508        if (!UserHandle.isApp(uid)) {
1509            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
1510        }
1511
1512        synchronized (mRulesLock) {
1513            final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
1514            if (oldPolicy != policy) {
1515                setUidPolicyUncheckedLocked(uid, policy, true);
1516            }
1517        }
1518    }
1519
1520    @Override
1521    public void addUidPolicy(int uid, int policy) {
1522        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1523
1524        if (!UserHandle.isApp(uid)) {
1525            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
1526        }
1527
1528        synchronized (mRulesLock) {
1529            final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
1530            policy |= oldPolicy;
1531            if (oldPolicy != policy) {
1532                setUidPolicyUncheckedLocked(uid, policy, true);
1533            }
1534        }
1535    }
1536
1537    @Override
1538    public void removeUidPolicy(int uid, int policy) {
1539        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1540
1541        if (!UserHandle.isApp(uid)) {
1542            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
1543        }
1544
1545        synchronized (mRulesLock) {
1546            final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
1547            policy = oldPolicy & ~policy;
1548            if (oldPolicy != policy) {
1549                setUidPolicyUncheckedLocked(uid, policy, true);
1550            }
1551        }
1552    }
1553
1554    private void setUidPolicyUncheckedLocked(int uid, int policy, boolean persist) {
1555        mUidPolicy.put(uid, policy);
1556
1557        // uid policy changed, recompute rules and persist policy.
1558        updateRulesForUidLocked(uid);
1559        if (persist) {
1560            writePolicyLocked();
1561        }
1562    }
1563
1564    @Override
1565    public int getUidPolicy(int uid) {
1566        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1567
1568        synchronized (mRulesLock) {
1569            return mUidPolicy.get(uid, POLICY_NONE);
1570        }
1571    }
1572
1573    @Override
1574    public int[] getUidsWithPolicy(int policy) {
1575        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1576
1577        int[] uids = new int[0];
1578        synchronized (mRulesLock) {
1579            for (int i = 0; i < mUidPolicy.size(); i++) {
1580                final int uid = mUidPolicy.keyAt(i);
1581                final int uidPolicy = mUidPolicy.valueAt(i);
1582                if (uidPolicy == policy) {
1583                    uids = appendInt(uids, uid);
1584                }
1585            }
1586        }
1587        return uids;
1588    }
1589
1590    /**
1591     * Remove any policies associated with given {@link UserHandle}, persisting
1592     * if any changes are made.
1593     */
1594    void removePoliciesForUserLocked(int userId) {
1595        if (LOGV) Slog.v(TAG, "removePoliciesForUserLocked()");
1596
1597        int[] uids = new int[0];
1598        for (int i = 0; i < mUidPolicy.size(); i++) {
1599            final int uid = mUidPolicy.keyAt(i);
1600            if (UserHandle.getUserId(uid) == userId) {
1601                uids = appendInt(uids, uid);
1602            }
1603        }
1604
1605        if (uids.length > 0) {
1606            for (int uid : uids) {
1607                mUidPolicy.delete(uid);
1608                updateRulesForUidLocked(uid);
1609            }
1610            writePolicyLocked();
1611        }
1612    }
1613
1614    @Override
1615    public void registerListener(INetworkPolicyListener listener) {
1616        // TODO: create permission for observing network policy
1617        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1618
1619        mListeners.register(listener);
1620
1621        // TODO: consider dispatching existing rules to new listeners
1622    }
1623
1624    @Override
1625    public void unregisterListener(INetworkPolicyListener listener) {
1626        // TODO: create permission for observing network policy
1627        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1628
1629        mListeners.unregister(listener);
1630    }
1631
1632    @Override
1633    public void setNetworkPolicies(NetworkPolicy[] policies) {
1634        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1635
1636        maybeRefreshTrustedTime();
1637        synchronized (mRulesLock) {
1638            normalizePoliciesLocked(policies);
1639            updateNetworkEnabledLocked();
1640            updateNetworkRulesLocked();
1641            updateNotificationsLocked();
1642            writePolicyLocked();
1643        }
1644    }
1645
1646    void addNetworkPolicyLocked(NetworkPolicy policy) {
1647        NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName());
1648        policies = ArrayUtils.appendElement(NetworkPolicy.class, policies, policy);
1649        setNetworkPolicies(policies);
1650    }
1651
1652    @Override
1653    public NetworkPolicy[] getNetworkPolicies(String callingPackage) {
1654        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1655        try {
1656            mContext.enforceCallingPermission(READ_PRIVILEGED_PHONE_STATE, TAG);
1657            // SKIP checking run-time OP_READ_PHONE_STATE since using PRIVILEGED
1658        } catch (SecurityException e) {
1659            mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
1660
1661            if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
1662                    callingPackage) != AppOpsManager.MODE_ALLOWED) {
1663                return new NetworkPolicy[0];
1664            }
1665        }
1666
1667        synchronized (mRulesLock) {
1668            final int size = mNetworkPolicy.size();
1669            final NetworkPolicy[] policies = new NetworkPolicy[size];
1670            for (int i = 0; i < size; i++) {
1671                policies[i] = mNetworkPolicy.valueAt(i);
1672            }
1673            return policies;
1674        }
1675    }
1676
1677    private void normalizePoliciesLocked() {
1678        normalizePoliciesLocked(getNetworkPolicies(mContext.getOpPackageName()));
1679    }
1680
1681    private void normalizePoliciesLocked(NetworkPolicy[] policies) {
1682        final TelephonyManager tele = TelephonyManager.from(mContext);
1683        final String[] merged = tele.getMergedSubscriberIds();
1684
1685        mNetworkPolicy.clear();
1686        for (NetworkPolicy policy : policies) {
1687            // When two normalized templates conflict, prefer the most
1688            // restrictive policy
1689            policy.template = NetworkTemplate.normalize(policy.template, merged);
1690            final NetworkPolicy existing = mNetworkPolicy.get(policy.template);
1691            if (existing == null || existing.compareTo(policy) > 0) {
1692                if (existing != null) {
1693                    Slog.d(TAG, "Normalization replaced " + existing + " with " + policy);
1694                }
1695                mNetworkPolicy.put(policy.template, policy);
1696            }
1697        }
1698    }
1699
1700    @Override
1701    public void snoozeLimit(NetworkTemplate template) {
1702        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1703
1704        final long token = Binder.clearCallingIdentity();
1705        try {
1706            performSnooze(template, TYPE_LIMIT);
1707        } finally {
1708            Binder.restoreCallingIdentity(token);
1709        }
1710    }
1711
1712    void performSnooze(NetworkTemplate template, int type) {
1713        maybeRefreshTrustedTime();
1714        final long currentTime = currentTimeMillis();
1715        synchronized (mRulesLock) {
1716            // find and snooze local policy that matches
1717            final NetworkPolicy policy = mNetworkPolicy.get(template);
1718            if (policy == null) {
1719                throw new IllegalArgumentException("unable to find policy for " + template);
1720            }
1721
1722            switch (type) {
1723                case TYPE_WARNING:
1724                    policy.lastWarningSnooze = currentTime;
1725                    break;
1726                case TYPE_LIMIT:
1727                    policy.lastLimitSnooze = currentTime;
1728                    break;
1729                default:
1730                    throw new IllegalArgumentException("unexpected type");
1731            }
1732
1733            normalizePoliciesLocked();
1734            updateNetworkEnabledLocked();
1735            updateNetworkRulesLocked();
1736            updateNotificationsLocked();
1737            writePolicyLocked();
1738        }
1739    }
1740
1741    @Override
1742    public void setRestrictBackground(boolean restrictBackground) {
1743        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1744
1745        maybeRefreshTrustedTime();
1746        synchronized (mRulesLock) {
1747            mRestrictBackground = restrictBackground;
1748            updateRulesForGlobalChangeLocked(false);
1749            updateNotificationsLocked();
1750            writePolicyLocked();
1751        }
1752
1753        mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED, restrictBackground ? 1 : 0, 0)
1754                .sendToTarget();
1755    }
1756
1757    @Override
1758    public boolean getRestrictBackground() {
1759        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1760
1761        synchronized (mRulesLock) {
1762            return mRestrictBackground;
1763        }
1764    }
1765
1766    @Override
1767    public void setDeviceIdleMode(boolean enabled) {
1768        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1769
1770        synchronized (mRulesLock) {
1771            if (mDeviceIdleMode != enabled) {
1772                mDeviceIdleMode = enabled;
1773                if (mSystemReady) {
1774                    updateRulesForDeviceIdleLocked();
1775                }
1776                if (enabled) {
1777                    EventLogTags.writeDeviceIdleOnPhase("net");
1778                } else {
1779                    EventLogTags.writeDeviceIdleOffPhase("net");
1780                }
1781            }
1782        }
1783    }
1784
1785    private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) {
1786        for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
1787            NetworkPolicy policy = mNetworkPolicy.valueAt(i);
1788            if (policy.template.matches(ident)) {
1789                return policy;
1790            }
1791        }
1792        return null;
1793    }
1794
1795    @Override
1796    public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) {
1797        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
1798
1799        // only returns usage summary, so we don't require caller to have
1800        // READ_NETWORK_USAGE_HISTORY.
1801        final long token = Binder.clearCallingIdentity();
1802        try {
1803            return getNetworkQuotaInfoUnchecked(state);
1804        } finally {
1805            Binder.restoreCallingIdentity(token);
1806        }
1807    }
1808
1809    private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) {
1810        final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
1811
1812        final NetworkPolicy policy;
1813        synchronized (mRulesLock) {
1814            policy = findPolicyForNetworkLocked(ident);
1815        }
1816
1817        if (policy == null || !policy.hasCycle()) {
1818            // missing policy means we can't derive useful quota info
1819            return null;
1820        }
1821
1822        final long currentTime = currentTimeMillis();
1823
1824        // find total bytes used under policy
1825        final long start = computeLastCycleBoundary(currentTime, policy);
1826        final long end = currentTime;
1827        final long totalBytes = getTotalBytes(policy.template, start, end);
1828
1829        // report soft and hard limits under policy
1830        final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes
1831                : NetworkQuotaInfo.NO_LIMIT;
1832        final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes
1833                : NetworkQuotaInfo.NO_LIMIT;
1834
1835        return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes);
1836    }
1837
1838    @Override
1839    public boolean isNetworkMetered(NetworkState state) {
1840        final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
1841
1842        // roaming networks are always considered metered
1843        if (ident.getRoaming()) {
1844            return true;
1845        }
1846
1847        final NetworkPolicy policy;
1848        synchronized (mRulesLock) {
1849            policy = findPolicyForNetworkLocked(ident);
1850        }
1851
1852        if (policy != null) {
1853            return policy.metered;
1854        } else {
1855            final int type = state.networkInfo.getType();
1856            if (isNetworkTypeMobile(type) || type == TYPE_WIMAX) {
1857                return true;
1858            }
1859            return false;
1860        }
1861    }
1862
1863    @Override
1864    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
1865        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
1866
1867        final IndentingPrintWriter fout = new IndentingPrintWriter(writer, "  ");
1868
1869        final ArraySet<String> argSet = new ArraySet<String>(args.length);
1870        for (String arg : args) {
1871            argSet.add(arg);
1872        }
1873
1874        synchronized (mRulesLock) {
1875            if (argSet.contains("--unsnooze")) {
1876                for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
1877                    mNetworkPolicy.valueAt(i).clearSnooze();
1878                }
1879
1880                normalizePoliciesLocked();
1881                updateNetworkEnabledLocked();
1882                updateNetworkRulesLocked();
1883                updateNotificationsLocked();
1884                writePolicyLocked();
1885
1886                fout.println("Cleared snooze timestamps");
1887                return;
1888            }
1889
1890            fout.print("System ready: "); fout.println(mSystemReady);
1891            fout.print("Restrict background: "); fout.println(mRestrictBackground);
1892            fout.print("Restrict power: "); fout.println(mRestrictPower);
1893            fout.print("Device idle: "); fout.println(mDeviceIdleMode);
1894            fout.print("Current foreground state: "); fout.println(mCurForegroundState);
1895            fout.println("Network policies:");
1896            fout.increaseIndent();
1897            for (int i = 0; i < mNetworkPolicy.size(); i++) {
1898                fout.println(mNetworkPolicy.valueAt(i).toString());
1899            }
1900            fout.decreaseIndent();
1901
1902            fout.print("Metered ifaces: "); fout.println(String.valueOf(mMeteredIfaces));
1903
1904            fout.println("Policy for UIDs:");
1905            fout.increaseIndent();
1906            int size = mUidPolicy.size();
1907            for (int i = 0; i < size; i++) {
1908                final int uid = mUidPolicy.keyAt(i);
1909                final int policy = mUidPolicy.valueAt(i);
1910                fout.print("UID=");
1911                fout.print(uid);
1912                fout.print(" policy=");
1913                dumpPolicy(fout, policy);
1914                fout.println();
1915            }
1916            fout.decreaseIndent();
1917
1918            size = mPowerSaveWhitelistAppIds.size();
1919            if (size > 0) {
1920                fout.println("Power save whitelist app ids:");
1921                fout.increaseIndent();
1922                for (int i = 0; i < size; i++) {
1923                    fout.print("UID=");
1924                    fout.print(mPowerSaveWhitelistAppIds.keyAt(i));
1925                    fout.print(": ");
1926                    fout.print(mPowerSaveWhitelistAppIds.valueAt(i));
1927                    fout.println();
1928                }
1929                fout.decreaseIndent();
1930            }
1931
1932            final SparseBooleanArray knownUids = new SparseBooleanArray();
1933            collectKeys(mUidState, knownUids);
1934            collectKeys(mUidRules, knownUids);
1935
1936            fout.println("Status for known UIDs:");
1937            fout.increaseIndent();
1938            size = knownUids.size();
1939            for (int i = 0; i < size; i++) {
1940                final int uid = knownUids.keyAt(i);
1941                fout.print("UID=");
1942                fout.print(uid);
1943
1944                int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
1945                fout.print(" state=");
1946                fout.print(state);
1947                fout.print(state <= mCurForegroundState ? " (fg)" : " (bg)");
1948
1949                fout.print(" rules=");
1950                final int rulesIndex = mUidRules.indexOfKey(uid);
1951                if (rulesIndex < 0) {
1952                    fout.print("UNKNOWN");
1953                } else {
1954                    dumpRules(fout, mUidRules.valueAt(rulesIndex));
1955                }
1956
1957                fout.println();
1958            }
1959            fout.decreaseIndent();
1960        }
1961    }
1962
1963    @Override
1964    public boolean isUidForeground(int uid) {
1965        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1966
1967        synchronized (mRulesLock) {
1968            return isUidForegroundLocked(uid);
1969        }
1970    }
1971
1972    boolean isUidForegroundLocked(int uid) {
1973        // only really in foreground when screen is also on
1974        return mScreenOn && mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY)
1975                <= mCurForegroundState;
1976    }
1977
1978    /**
1979     * Process state of UID changed; if needed, will trigger
1980     * {@link #updateRulesForUidLocked(int)}.
1981     */
1982    void updateUidStateLocked(int uid, int uidState) {
1983        final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
1984        if (oldUidState != uidState) {
1985            // state changed, push updated rules
1986            mUidState.put(uid, uidState);
1987            updateRulesForUidStateChangeLocked(uid, oldUidState, uidState);
1988        }
1989    }
1990
1991    void removeUidStateLocked(int uid) {
1992        final int index = mUidState.indexOfKey(uid);
1993        if (index >= 0) {
1994            final int oldUidState = mUidState.valueAt(index);
1995            mUidState.removeAt(index);
1996            if (oldUidState != ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
1997                updateRulesForUidStateChangeLocked(uid, oldUidState,
1998                        ActivityManager.PROCESS_STATE_CACHED_EMPTY);
1999            }
2000        }
2001    }
2002
2003    void updateRulesForUidStateChangeLocked(int uid, int oldUidState, int newUidState) {
2004        final boolean oldForeground = oldUidState <= mCurForegroundState;
2005        final boolean newForeground = newUidState <= mCurForegroundState;
2006        if (oldForeground != newForeground) {
2007            updateRulesForUidLocked(uid);
2008        }
2009    }
2010
2011    private void updateScreenOn() {
2012        synchronized (mRulesLock) {
2013            try {
2014                mScreenOn = mPowerManager.isInteractive();
2015            } catch (RemoteException e) {
2016                // ignored; service lives in system_server
2017            }
2018            updateRulesForScreenLocked();
2019        }
2020    }
2021
2022    /**
2023     * Update rules that might be changed by {@link #mScreenOn} value.
2024     */
2025    private void updateRulesForScreenLocked() {
2026        // only update rules for anyone with foreground activities
2027        final int size = mUidState.size();
2028        for (int i = 0; i < size; i++) {
2029            if (mUidState.valueAt(i) <= mCurForegroundState) {
2030                final int uid = mUidState.keyAt(i);
2031                updateRulesForUidLocked(uid);
2032            }
2033        }
2034    }
2035
2036    void updateRulesForDeviceIdleLocked() {
2037        if (mDeviceIdleMode) {
2038            // sync the whitelists before enable dozable chain.  We don't care about the rules if
2039            // we are disabling the chain.
2040            SparseIntArray uidRules = new SparseIntArray();
2041            final List<UserInfo> users = mUserManager.getUsers();
2042            for (UserInfo user : users) {
2043                for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
2044                    int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
2045                    int uid = UserHandle.getUid(user.id, appId);
2046                    uidRules.put(uid, FIREWALL_RULE_ALLOW);
2047                }
2048                for (int i = mPowerSaveWhitelistAppIds.size() - 1; i >= 0; i--) {
2049                    int appId = mPowerSaveWhitelistAppIds.keyAt(i);
2050                    int uid = UserHandle.getUid(user.id, appId);
2051                    uidRules.put(uid, FIREWALL_RULE_ALLOW);
2052                }
2053            }
2054            setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules);
2055        }
2056        enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode);
2057    }
2058
2059    void updateRulesForAppIdleParoleLocked() {
2060        boolean enableChain = !mUsageStats.isAppIdleParoleOn();
2061        enableFirewallChainLocked(FIREWALL_CHAIN_STANDBY, enableChain);
2062    }
2063
2064    /**
2065     * Update rules that might be changed by {@link #mRestrictBackground},
2066     * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
2067     */
2068    void updateRulesForGlobalChangeLocked(boolean restrictedNetworksChanged) {
2069        final PackageManager pm = mContext.getPackageManager();
2070
2071        // If we are in restrict power mode, we allow all important apps
2072        // to have data access.  Otherwise, we restrict data access to only
2073        // the top apps.
2074        mCurForegroundState = (!mRestrictBackground && mRestrictPower)
2075                ? ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
2076                : ActivityManager.PROCESS_STATE_TOP;
2077
2078        updateRulesForDeviceIdleLocked();
2079
2080        // update rules for all installed applications
2081        final List<UserInfo> users = mUserManager.getUsers();
2082        final List<ApplicationInfo> apps = pm.getInstalledApplications(
2083                PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
2084
2085        for (UserInfo user : users) {
2086            for (ApplicationInfo app : apps) {
2087                final int uid = UserHandle.getUid(user.id, app.uid);
2088                updateRulesForUidLocked(uid);
2089            }
2090        }
2091
2092        // limit data usage for some internal system services
2093        updateRulesForUidLocked(android.os.Process.MEDIA_UID);
2094        updateRulesForUidLocked(android.os.Process.DRM_UID);
2095
2096        // If the set of restricted networks may have changed, re-evaluate those.
2097        if (restrictedNetworksChanged) {
2098            normalizePoliciesLocked();
2099            updateNetworkRulesLocked();
2100        }
2101    }
2102
2103    void updateRulesForTempWhitelistChangeLocked() {
2104        final List<UserInfo> users = mUserManager.getUsers();
2105        for (UserInfo user : users) {
2106            for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
2107                int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
2108                boolean isAllow = mPowerSaveTempWhitelistAppIds.valueAt(i);
2109                int uid = UserHandle.getUid(user.id, appId);
2110                updateRulesForUidLocked(uid);
2111                setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, !isAllow);
2112            }
2113        }
2114    }
2115
2116    private static boolean isUidValidForRules(int uid) {
2117        // allow rules on specific system services, and any apps
2118        if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID
2119                || UserHandle.isApp(uid)) {
2120            return true;
2121        }
2122
2123        return false;
2124    }
2125
2126    private boolean isUidIdle(int uid) {
2127        final String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
2128        final int userId = UserHandle.getUserId(uid);
2129
2130        for (String packageName : packages) {
2131            if (!mUsageStats.isAppIdle(packageName, userId)) {
2132                return false;
2133            }
2134        }
2135        return true;
2136    }
2137
2138    /**
2139     * Applies network rules to bandwidth and firewall controllers based on uid policy.
2140     * @param uid The uid for which to apply the latest policy
2141     */
2142    void updateRulesForUidLocked(int uid) {
2143        if (!isUidValidForRules(uid)) return;
2144
2145        // quick check: if this uid doesn't have INTERNET permission, it doesn't have
2146        // network access anyway, so it is a waste to mess with it here.
2147        final IPackageManager ipm = AppGlobals.getPackageManager();
2148        try {
2149            if (ipm.checkUidPermission(Manifest.permission.INTERNET, uid)
2150                    != PackageManager.PERMISSION_GRANTED) {
2151                return;
2152            }
2153        } catch (RemoteException e) {
2154        }
2155
2156        final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
2157        final boolean uidForeground = isUidForegroundLocked(uid);
2158        final boolean uidIdle = isUidIdle(uid);
2159
2160        // derive active rules based on policy and active state
2161
2162        int appId = UserHandle.getAppId(uid);
2163        int uidRules = RULE_ALLOW_ALL;
2164        if (uidIdle && !mPowerSaveWhitelistAppIds.get(appId)
2165                && !mPowerSaveTempWhitelistAppIds.get(appId)) {
2166            uidRules = RULE_REJECT_ALL;
2167        } else if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
2168            // uid in background, and policy says to block metered data
2169            uidRules = RULE_REJECT_METERED;
2170        } else if (mRestrictBackground) {
2171            if (!uidForeground) {
2172                // uid in background, and global background disabled
2173                uidRules = RULE_REJECT_METERED;
2174            }
2175        } else if (mRestrictPower) {
2176            final boolean whitelisted = mPowerSaveWhitelistAppIds.get(appId)
2177                    || mPowerSaveTempWhitelistAppIds.get(appId);
2178            if (!whitelisted && !uidForeground
2179                    && (uidPolicy & POLICY_ALLOW_BACKGROUND_BATTERY_SAVE) == 0) {
2180                // uid is in background, restrict power use mode is on (so we want to
2181                // restrict all background network access), and this uid is not on the
2182                // white list of those allowed background access.
2183                uidRules = RULE_REJECT_METERED;
2184            }
2185        }
2186
2187        final int oldRules = mUidRules.get(uid);
2188
2189        if (uidRules == RULE_ALLOW_ALL) {
2190            mUidRules.delete(uid);
2191        } else {
2192            mUidRules.put(uid, uidRules);
2193        }
2194
2195        // Update bandwidth rules if necessary
2196        final boolean oldRejectMetered = (oldRules & RULE_REJECT_METERED) != 0;
2197        final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0;
2198        if (oldRejectMetered != rejectMetered) {
2199            setUidNetworkRules(uid, rejectMetered);
2200        }
2201
2202        // Update firewall rules if necessary
2203        final boolean oldFirewallReject = (oldRules & RULE_REJECT_ALL) != 0;
2204        final boolean firewallReject = (uidRules & RULE_REJECT_ALL) != 0;
2205        if (oldFirewallReject != firewallReject) {
2206            setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, firewallReject);
2207        }
2208
2209        // dispatch changed rule to existing listeners
2210        if (oldRules != uidRules) {
2211            mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
2212        }
2213
2214        try {
2215            // adjust stats accounting based on foreground status
2216            mNetworkStats.setUidForeground(uid, uidForeground);
2217        } catch (RemoteException e) {
2218            // ignored; service lives in system_server
2219        }
2220    }
2221
2222    private class AppIdleStateChangeListener
2223            extends UsageStatsManagerInternal.AppIdleStateChangeListener {
2224
2225        @Override
2226        public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
2227            try {
2228                int uid = mContext.getPackageManager().getPackageUid(packageName, userId);
2229                synchronized (mRulesLock) {
2230                    updateRulesForUidLocked(uid);
2231                }
2232            } catch (NameNotFoundException nnfe) {
2233            }
2234        }
2235
2236        @Override
2237        public void onParoleStateChanged(boolean isParoleOn) {
2238            synchronized (mRulesLock) {
2239                updateRulesForAppIdleParoleLocked();
2240            }
2241        }
2242    }
2243
2244    private Handler.Callback mHandlerCallback = new Handler.Callback() {
2245        @Override
2246        public boolean handleMessage(Message msg) {
2247            switch (msg.what) {
2248                case MSG_RULES_CHANGED: {
2249                    final int uid = msg.arg1;
2250                    final int uidRules = msg.arg2;
2251                    final int length = mListeners.beginBroadcast();
2252                    for (int i = 0; i < length; i++) {
2253                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
2254                        if (listener != null) {
2255                            try {
2256                                listener.onUidRulesChanged(uid, uidRules);
2257                            } catch (RemoteException e) {
2258                            }
2259                        }
2260                    }
2261                    mListeners.finishBroadcast();
2262                    return true;
2263                }
2264                case MSG_METERED_IFACES_CHANGED: {
2265                    final String[] meteredIfaces = (String[]) msg.obj;
2266                    final int length = mListeners.beginBroadcast();
2267                    for (int i = 0; i < length; i++) {
2268                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
2269                        if (listener != null) {
2270                            try {
2271                                listener.onMeteredIfacesChanged(meteredIfaces);
2272                            } catch (RemoteException e) {
2273                            }
2274                        }
2275                    }
2276                    mListeners.finishBroadcast();
2277                    return true;
2278                }
2279                case MSG_LIMIT_REACHED: {
2280                    final String iface = (String) msg.obj;
2281
2282                    maybeRefreshTrustedTime();
2283                    synchronized (mRulesLock) {
2284                        if (mMeteredIfaces.contains(iface)) {
2285                            try {
2286                                // force stats update to make sure we have
2287                                // numbers that caused alert to trigger.
2288                                mNetworkStats.forceUpdate();
2289                            } catch (RemoteException e) {
2290                                // ignored; service lives in system_server
2291                            }
2292
2293                            updateNetworkEnabledLocked();
2294                            updateNotificationsLocked();
2295                        }
2296                    }
2297                    return true;
2298                }
2299                case MSG_RESTRICT_BACKGROUND_CHANGED: {
2300                    final boolean restrictBackground = msg.arg1 != 0;
2301                    final int length = mListeners.beginBroadcast();
2302                    for (int i = 0; i < length; i++) {
2303                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
2304                        if (listener != null) {
2305                            try {
2306                                listener.onRestrictBackgroundChanged(restrictBackground);
2307                            } catch (RemoteException e) {
2308                            }
2309                        }
2310                    }
2311                    mListeners.finishBroadcast();
2312                    return true;
2313                }
2314                case MSG_ADVISE_PERSIST_THRESHOLD: {
2315                    final long lowestRule = (Long) msg.obj;
2316                    try {
2317                        // make sure stats are recorded frequently enough; we aim
2318                        // for 2MB threshold for 2GB/month rules.
2319                        final long persistThreshold = lowestRule / 1000;
2320                        mNetworkStats.advisePersistThreshold(persistThreshold);
2321                    } catch (RemoteException e) {
2322                        // ignored; service lives in system_server
2323                    }
2324                    return true;
2325                }
2326                case MSG_SCREEN_ON_CHANGED: {
2327                    updateScreenOn();
2328                    return true;
2329                }
2330                default: {
2331                    return false;
2332                }
2333            }
2334        }
2335    };
2336
2337    private void setInterfaceQuota(String iface, long quotaBytes) {
2338        try {
2339            mNetworkManager.setInterfaceQuota(iface, quotaBytes);
2340        } catch (IllegalStateException e) {
2341            Log.wtf(TAG, "problem setting interface quota", e);
2342        } catch (RemoteException e) {
2343            // ignored; service lives in system_server
2344        }
2345    }
2346
2347    private void removeInterfaceQuota(String iface) {
2348        try {
2349            mNetworkManager.removeInterfaceQuota(iface);
2350        } catch (IllegalStateException e) {
2351            Log.wtf(TAG, "problem removing interface quota", e);
2352        } catch (RemoteException e) {
2353            // ignored; service lives in system_server
2354        }
2355    }
2356
2357    private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
2358        try {
2359            mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
2360        } catch (IllegalStateException e) {
2361            Log.wtf(TAG, "problem setting uid rules", e);
2362        } catch (RemoteException e) {
2363            // ignored; service lives in system_server
2364        }
2365    }
2366
2367    /**
2368     * Set uid rules on a particular firewall chain. This is going to synchronize the rules given
2369     * here to netd.  It will clean up dead rules and make sure the target chain only contains rules
2370     * specified here.
2371     */
2372    private void setUidFirewallRules(int chain, SparseIntArray uidRules) {
2373        try {
2374            int size = uidRules.size();
2375            int[] uids = new int[size];
2376            int[] rules = new int[size];
2377            for(int index = size - 1; index >= 0; --index) {
2378                uids[index] = uidRules.keyAt(index);
2379                rules[index] = uidRules.valueAt(index);
2380            }
2381            mNetworkManager.setFirewallUidRules(chain, uids, rules);
2382        } catch (IllegalStateException e) {
2383            Log.wtf(TAG, "problem setting firewall uid rules", e);
2384        } catch (RemoteException e) {
2385            // ignored; service lives in system_server
2386        }
2387    }
2388
2389    /**
2390     * Add or remove a uid to the firewall blacklist for all network ifaces.
2391     */
2392    private void setUidFirewallRule(int chain, int uid, boolean rejectOnAll) {
2393        try {
2394            mNetworkManager.setFirewallUidRule(chain, uid,
2395                    rejectOnAll ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW);
2396        } catch (IllegalStateException e) {
2397            Log.wtf(TAG, "problem setting firewall uid rules", e);
2398        } catch (RemoteException e) {
2399            // ignored; service lives in system_server
2400        }
2401    }
2402
2403    /**
2404     * Add or remove a uid to the firewall blacklist for all network ifaces.
2405     */
2406    private void enableFirewallChainLocked(int chain, boolean enable) {
2407        if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
2408                mFirewallChainStates.get(chain) == enable) {
2409            // All is the same, nothing to do.
2410            return;
2411        }
2412        mFirewallChainStates.put(chain, enable);
2413        try {
2414            mNetworkManager.setFirewallChainEnabled(chain, enable);
2415        } catch (IllegalStateException e) {
2416            Log.wtf(TAG, "problem enable firewall chain", e);
2417        } catch (RemoteException e) {
2418            // ignored; service lives in system_server
2419        }
2420    }
2421
2422    private long getTotalBytes(NetworkTemplate template, long start, long end) {
2423        try {
2424            return mNetworkStats.getNetworkTotalBytes(template, start, end);
2425        } catch (RuntimeException e) {
2426            Slog.w(TAG, "problem reading network stats: " + e);
2427            return 0;
2428        } catch (RemoteException e) {
2429            // ignored; service lives in system_server
2430            return 0;
2431        }
2432    }
2433
2434    private boolean isBandwidthControlEnabled() {
2435        final long token = Binder.clearCallingIdentity();
2436        try {
2437            return mNetworkManager.isBandwidthControlEnabled();
2438        } catch (RemoteException e) {
2439            // ignored; service lives in system_server
2440            return false;
2441        } finally {
2442            Binder.restoreCallingIdentity(token);
2443        }
2444    }
2445
2446    /**
2447     * Try refreshing {@link #mTime} when stale.
2448     */
2449    void maybeRefreshTrustedTime() {
2450        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
2451            mTime.forceRefresh();
2452        }
2453    }
2454
2455    private long currentTimeMillis() {
2456        return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
2457    }
2458
2459    private static Intent buildAllowBackgroundDataIntent() {
2460        return new Intent(ACTION_ALLOW_BACKGROUND);
2461    }
2462
2463    private static Intent buildSnoozeWarningIntent(NetworkTemplate template) {
2464        final Intent intent = new Intent(ACTION_SNOOZE_WARNING);
2465        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
2466        return intent;
2467    }
2468
2469    private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
2470        final Intent intent = new Intent();
2471        intent.setComponent(new ComponentName(
2472                "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity"));
2473        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2474        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
2475        return intent;
2476    }
2477
2478    private static Intent buildViewDataUsageIntent(NetworkTemplate template) {
2479        final Intent intent = new Intent();
2480        intent.setComponent(new ComponentName(
2481                "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
2482        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2483        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
2484        return intent;
2485    }
2486
2487    @VisibleForTesting
2488    public void addIdleHandler(IdleHandler handler) {
2489        mHandler.getLooper().getQueue().addIdleHandler(handler);
2490    }
2491
2492    private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
2493        final int size = source.size();
2494        for (int i = 0; i < size; i++) {
2495            target.put(source.keyAt(i), true);
2496        }
2497    }
2498
2499    @Override
2500    public void factoryReset(String subscriber) {
2501        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2502
2503        if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
2504            return;
2505        }
2506
2507        // Turn mobile data limit off
2508        NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName());
2509        NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(subscriber);
2510        for (NetworkPolicy policy : policies) {
2511            if (policy.template.equals(template)) {
2512                policy.limitBytes = NetworkPolicy.LIMIT_DISABLED;
2513                policy.inferred = false;
2514                policy.clearSnooze();
2515            }
2516        }
2517        setNetworkPolicies(policies);
2518
2519        // Turn restrict background data off
2520        setRestrictBackground(false);
2521
2522        if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_APPS_CONTROL)) {
2523            // Remove app's "restrict background data" flag
2524            for (int uid : getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) {
2525                setUidPolicy(uid, POLICY_NONE);
2526            }
2527        }
2528    }
2529}
2530