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