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