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