NetworkPolicyManagerService.java revision 41ff7ec82422a5b6d00892afdb3232bc0e53d851
1d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/*
2d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project
3d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey *
4d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * you may not use this file except in compliance with the License.
6d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * You may obtain a copy of the License at
7d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey *
8d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey *
10d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * See the License for the specific language governing permissions and
14d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * limitations under the License.
15d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */
16d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
17d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeypackage com.android.server.net;
18d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.CONNECTIVITY_INTERNAL;
201b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.Manifest.permission.DUMP;
21d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport static android.Manifest.permission.MANAGE_APP_TOKENS;
2221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.MANAGE_NETWORK_POLICY;
23497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
2422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport static android.Manifest.permission.READ_PHONE_STATE;
2502e21d6a5b5117d494777a36783909854854f751Jeff Sharkeyimport static android.content.Intent.ACTION_PACKAGE_ADDED;
26b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.ACTION_UID_REMOVED;
27b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.EXTRA_UID;
284e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkeyimport static android.net.ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED;
2921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
301b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_MOBILE;
3122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport static android.net.NetworkPolicy.LIMIT_DISABLED;
3241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkeyimport static android.net.NetworkPolicy.SNOOZE_NEVER;
33497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static android.net.NetworkPolicy.WARNING_DISABLED;
3414711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkeyimport static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
35d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_NONE;
36fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
37c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
38fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
39cd2ca4038a027315832c38c68be5076000bc4b53Jeff Sharkeyimport static android.net.NetworkPolicyManager.computeLastCycleBoundary;
401b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.net.NetworkPolicyManager.dumpPolicy;
411b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.net.NetworkPolicyManager.dumpRules;
42497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static android.net.NetworkPolicyManager.isUidValidForPolicy;
431b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
441b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_4G;
454e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkeyimport static android.net.NetworkTemplate.buildTemplateMobileAll;
4621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.text.format.DateUtils.DAY_IN_MILLIS;
4721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull;
48497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
4921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
5021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.START_TAG;
51d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
52a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IActivityManager;
53497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.INotificationManager;
54a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IProcessObserver;
55497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.Notification;
56497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.PendingIntent;
57a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.BroadcastReceiver;
5841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkeyimport android.content.ComponentName;
59d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.content.Context;
60a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.Intent;
61a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.IntentFilter;
62b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.content.pm.ApplicationInfo;
63b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.content.pm.PackageManager;
64497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.content.res.Resources;
65c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.ConnectivityManager;
6621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.IConnectivityManager;
6741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkeyimport android.net.INetworkManagementEventObserver;
68c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.INetworkPolicyListener;
69d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.net.INetworkPolicyManager;
7075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.INetworkStatsService;
711b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkIdentity;
7221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkPolicy;
7321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkState;
7421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkStats;
751b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkTemplate;
7621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Environment;
7721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Handler;
7821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.HandlerThread;
7950fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharmaimport android.os.INetworkManagementService;
80a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.IPowerManager;
814414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkeyimport android.os.Message;
82c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.os.RemoteCallbackList;
83a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.RemoteException;
8422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport android.telephony.TelephonyManager;
85497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.text.format.Formatter;
8622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport android.text.format.Time;
8721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.NtpTrustedTime;
88a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.util.Slog;
89d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseArray;
90d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseBooleanArray;
91d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseIntArray;
9221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.TrustedTime;
9321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.Xml;
94d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
95497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport com.android.internal.R;
9621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.android.internal.os.AtomicFile;
9721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.android.internal.util.FastXmlSerializer;
9821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.google.android.collect.Lists;
9921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.google.android.collect.Maps;
100fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport com.google.android.collect.Sets;
10121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
10221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlPullParser;
10321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlPullParserException;
10421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlSerializer;
10521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
10621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.File;
1071b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.FileDescriptor;
10821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileInputStream;
10921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileNotFoundException;
11021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileOutputStream;
11121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.IOException;
1121b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.PrintWriter;
11321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.net.ProtocolException;
11421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.ArrayList;
11521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.Arrays;
11621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.HashMap;
117fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport java.util.HashSet;
118b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport java.util.List;
11921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
12021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport libcore.io.IoUtils;
1211b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
122d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/**
123d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Service that maintains low-level network policy rules and collects usage
124d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * statistics to drive those rules.
125c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * <p>
126c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * Derives active rules by combining a given policy with other system status,
127c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * and delivers to listeners, such as {@link ConnectivityManager}, for
128c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * enforcement.
129d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */
130d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeypublic class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
131d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    private static final String TAG = "NetworkPolicy";
132d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    private static final boolean LOGD = true;
13322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private static final boolean LOGV = false;
134d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
13541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static final int VERSION_INIT = 1;
13641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static final int VERSION_ADDED_SNOOZE = 2;
13721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
13822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private static final long KB_IN_BYTES = 1024;
13922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
14022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
14122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
14241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    // @VisibleForTesting
14341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public static final int TYPE_WARNING = 0x1;
14441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public static final int TYPE_LIMIT = 0x2;
14541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public static final int TYPE_LIMIT_SNOOZED = 0x3;
146497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
14721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG_POLICY_LIST = "policy-list";
14821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG_NETWORK_POLICY = "network-policy";
14921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG_UID_POLICY = "uid-policy";
15021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
15121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_VERSION = "version";
15221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
15321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
15421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_CYCLE_DAY = "cycleDay";
15521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_WARNING_BYTES = "warningBytes";
15621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_LIMIT_BYTES = "limitBytes";
15741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static final String ATTR_LAST_SNOOZE = "lastSnooze";
15821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_UID = "uid";
15921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_POLICY = "policy";
16021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
16121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
16221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1634414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    private static final int MSG_RULES_CHANGED = 0x1;
1644414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    private static final int MSG_METERED_IFACES_CHANGED = 0x2;
1654414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey
16675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Context mContext;
16775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final IActivityManager mActivityManager;
16875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final IPowerManager mPowerManager;
16975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final INetworkStatsService mNetworkStats;
17041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private final INetworkManagementService mNetworkManager;
17121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final TrustedTime mTime;
17221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
17321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private IConnectivityManager mConnManager;
174497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private INotificationManager mNotifManager;
175a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
17675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Object mRulesLock = new Object();
177a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
178c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    private boolean mScreenOn;
179b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    private boolean mBackgroundData;
180d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
18141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Defined network policies. */
18241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap();
18341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Currently active network rules for ifaces. */
18402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey    private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap();
18522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
18641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Defined UID policies. */
187a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private SparseIntArray mUidPolicy = new SparseIntArray();
18841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Currently derived rules for each UID. */
189c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    private SparseIntArray mUidRules = new SparseIntArray();
190d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
191fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey    /** Set of ifaces that are metered. */
192fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey    private HashSet<String> mMeteredIfaces = Sets.newHashSet();
19341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Set of over-limit templates that have been notified. */
19441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet();
195fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey
196d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    /** Foreground at both UID and PID granularity. */
197a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private SparseBooleanArray mUidForeground = new SparseBooleanArray();
198a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
199a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            SparseBooleanArray>();
200d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
201c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
202c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            INetworkPolicyListener>();
203c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
20421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final HandlerThread mHandlerThread;
20521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final Handler mHandler;
20621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
20721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final AtomicFile mPolicyFile;
208d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
209c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    // TODO: keep whitelist of system-critical services that should never have
210c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    // rules enforced, such as system, phone, and radio UIDs.
211c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
21241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    // TODO: migrate notifications to SystemUI
21341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
21475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
21550fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            IPowerManager powerManager, INetworkStatsService networkStats,
21650fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            INetworkManagementService networkManagement) {
217b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        this(context, activityManager, powerManager, networkStats, networkManagement,
218104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey                NtpTrustedTime.getInstance(context), getSystemDir());
21921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
22021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
22121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static File getSystemDir() {
22221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        return new File(Environment.getDataDirectory(), "system");
22321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
22421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
22521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
22650fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            IPowerManager powerManager, INetworkStatsService networkStats,
22750fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            INetworkManagementService networkManagement,
22850fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            TrustedTime time, File systemDir) {
229a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mContext = checkNotNull(context, "missing context");
230a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mActivityManager = checkNotNull(activityManager, "missing activityManager");
231a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mPowerManager = checkNotNull(powerManager, "missing powerManager");
23275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mNetworkStats = checkNotNull(networkStats, "missing networkStats");
23341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
23421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mTime = checkNotNull(time, "missing TrustedTime");
23521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
23621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mHandlerThread = new HandlerThread(TAG);
23721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mHandlerThread.start();
2384414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey        mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
23921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
24021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
24121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
24221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
24321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public void bindConnectivityManager(IConnectivityManager connManager) {
24421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
245a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
246d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
247497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    public void bindNotificationManager(INotificationManager notifManager) {
248497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        mNotifManager = checkNotNull(notifManager, "missing INotificationManager");
249497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
250497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
251a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    public void systemReady() {
25221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mRulesLock) {
25321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // read policy from disk
25421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            readPolicyLocked();
25521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
256d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
257a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        updateScreenOn();
258b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        updateBackgroundData(true);
259d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
260a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        try {
261a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            mActivityManager.registerProcessObserver(mProcessObserver);
262a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        } catch (RemoteException e) {
263a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // ouch, no foregroundActivities updates means some processes may
264a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // never get network access.
265a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            Slog.e(TAG, "unable to register IProcessObserver", e);
266a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
267d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
26841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        try {
26941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.registerObserver(mAlertObserver);
27041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (RemoteException e) {
27141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            // ouch, no alert updates means we fall back to
27241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            // ACTION_NETWORK_STATS_UPDATED broadcasts.
27341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            Slog.e(TAG, "unable to register INetworkManagementEventObserver", e);
27441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
27541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
276a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // TODO: traverse existing processes to know foreground state, or have
277a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // activitymanager dispatch current state when new observer attached.
278d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
279a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        final IntentFilter screenFilter = new IntentFilter();
280a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
281a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
28241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler);
283d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
28421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // watch for network interfaces to be claimed
285b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
286b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
287b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
28802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        // listen for package/uid changes to update policy
28902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        final IntentFilter packageFilter = new IntentFilter();
29002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        packageFilter.addAction(ACTION_PACKAGE_ADDED);
29102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        packageFilter.addAction(ACTION_UID_REMOVED);
29202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
29321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
294b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // listen for stats update events
295497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
296497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        mContext.registerReceiver(
297497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
298497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
299b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // listen for changes to background data flag
300b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        final IntentFilter bgFilter = new IntentFilter(ACTION_BACKGROUND_DATA_SETTING_CHANGED);
301b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        mContext.registerReceiver(mBgReceiver, bgFilter, CONNECTIVITY_INTERNAL, mHandler);
302b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
303a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
304d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
305a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
306a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
307a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
308a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // only someone like AMS should only be calling us
30975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
310a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
311a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            synchronized (mRulesLock) {
312a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // because a uid can have multiple pids running inside, we need to
313a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // remember all pid states and summarize foreground at uid level.
314a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
315a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // record foreground for this specific pid
316a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
317a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                if (pidForeground == null) {
318a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    pidForeground = new SparseBooleanArray(2);
319a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    mUidPidForeground.put(uid, pidForeground);
320a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                }
321a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                pidForeground.put(pid, foregroundActivities);
32221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                computeUidForegroundLocked(uid);
323a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
324d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
325d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
326a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
327a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onProcessDied(int pid, int uid) {
328a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // only someone like AMS should only be calling us
32975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
330a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
331a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            synchronized (mRulesLock) {
332a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // clear records and recompute, when they exist
333a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
334a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                if (pidForeground != null) {
335a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    pidForeground.delete(pid);
33621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    computeUidForegroundLocked(uid);
337a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                }
338a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
339a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
340a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    };
341a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
342a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
343a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
344a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onReceive(Context context, Intent intent) {
345a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            synchronized (mRulesLock) {
346a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // screen-related broadcasts are protected by system, no need
347a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // for permissions check.
348a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                updateScreenOn();
349a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
350a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
351a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    };
352d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
35302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey    private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
354b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        @Override
355b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        public void onReceive(Context context, Intent intent) {
35602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            // on background handler thread, and PACKAGE_ADDED and UID_REMOVED
35702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            // are protected broadcasts.
35802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey
35902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            final String action = intent.getAction();
360b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            final int uid = intent.getIntExtra(EXTRA_UID, 0);
361b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            synchronized (mRulesLock) {
36202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                if (ACTION_PACKAGE_ADDED.equals(action)) {
36302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    // update rules for UID, since it might be subject to
36402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    // global background data policy.
36502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
36602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    updateRulesForUidLocked(uid);
36702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey
36802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                } else if (ACTION_UID_REMOVED.equals(action)) {
36902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    // remove any policy and update rules to clean up.
37002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
37102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    mUidPolicy.delete(uid);
37202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    updateRulesForUidLocked(uid);
37302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    writePolicyLocked();
37402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                }
375b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            }
376b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        }
377b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    };
378b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
37921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    /**
380497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Receiver that watches for {@link INetworkStatsService} updates, which we
381497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * use to check against {@link NetworkPolicy#warningBytes}.
382497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
383497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() {
384497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        @Override
385497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        public void onReceive(Context context, Intent intent) {
386497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            // on background handler thread, and verified
387497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            // READ_NETWORK_USAGE_HISTORY permission above.
388497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
389497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            synchronized (mRulesLock) {
390497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                updateNotificationsLocked();
391497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
392497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
393497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    };
394497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
395497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
396b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey     * Receiver that watches for
397b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey     * {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}.
398b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey     */
399b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    private BroadcastReceiver mBgReceiver = new BroadcastReceiver() {
400b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        @Override
401b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        public void onReceive(Context context, Intent intent) {
402b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
403b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            // permission above.
404b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
405b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            synchronized (mRulesLock) {
406b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                updateBackgroundData(false);
407b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
408b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
409b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    };
410b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
411b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    /**
41241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     * Observer that watches for {@link INetworkManagementService} alerts.
41341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     */
41441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
41541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        @Override
41641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        public void limitReached(String limitName, String iface) {
41741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            // only someone like NMS should be calling us
41841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
41941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
42041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            synchronized (mRulesLock) {
42141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                if (mMeteredIfaces.contains(iface)) {
42241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    try {
42341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        // force stats update to make sure we have numbers that
42441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        // caused alert to trigger.
42541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        mNetworkStats.forceUpdate();
42641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    } catch (RemoteException e) {
42741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        Slog.w(TAG, "problem updating network stats");
42841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    }
42941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
43041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    updateNotificationsLocked();
43141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
43241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
43341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
43441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    };
43541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
43641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /**
437497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
438497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * to show visible notifications as needed.
439497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
440497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private void updateNotificationsLocked() {
441497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        if (LOGV) Slog.v(TAG, "updateNotificationsLocked()");
442497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
443497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // try refreshing time source when stale
444497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
445497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            mTime.forceRefresh();
446497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
447497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
448497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
449497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                : System.currentTimeMillis();
450497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
451497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // TODO: when switching to kernel notifications, compute next future
452497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // cycle boundary to recompute notifications.
453497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
45402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        // examine stats for each active policy
45502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        for (NetworkPolicy policy : mNetworkRules.keySet()) {
456497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final long start = computeLastCycleBoundary(currentTime, policy);
457497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final long end = currentTime;
458497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
45941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final long totalBytes;
460497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            try {
461497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
4621b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                        policy.template, start, end);
463d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                final NetworkStats.Entry entry = stats.getValues(0, null);
46441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                totalBytes = entry.rxBytes + entry.txBytes;
465497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            } catch (RemoteException e) {
4661b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                Slog.w(TAG, "problem reading summary for template " + policy.template);
467497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                continue;
468497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
469497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
47041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (policy.limitBytes != LIMIT_DISABLED && totalBytes >= policy.limitBytes) {
471497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                cancelNotification(policy, TYPE_WARNING);
47241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
47341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                if (policy.lastSnooze >= start) {
47441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    cancelNotification(policy, TYPE_LIMIT);
47541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
47641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                } else {
47741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    cancelNotification(policy, TYPE_LIMIT_SNOOZED);
47841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    enqueueNotification(policy, TYPE_LIMIT, totalBytes);
47941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    notifyOverLimitLocked(policy.template);
48041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
48141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
482497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            } else {
483497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                cancelNotification(policy, TYPE_LIMIT);
48441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                cancelNotification(policy, TYPE_LIMIT_SNOOZED);
48541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                notifyUnderLimitLocked(policy.template);
486497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
48741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) {
48841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    enqueueNotification(policy, TYPE_WARNING, totalBytes);
489497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                } else {
490497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                    cancelNotification(policy, TYPE_WARNING);
491497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                }
492497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
49302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        }
49402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey
49502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        // clear notifications for non-active policies
49641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        for (NetworkPolicy policy : mNetworkPolicy.values()) {
49702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            if (!mNetworkRules.containsKey(policy)) {
49802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                cancelNotification(policy, TYPE_WARNING);
49902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                cancelNotification(policy, TYPE_LIMIT);
50041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                cancelNotification(policy, TYPE_LIMIT_SNOOZED);
50141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                notifyUnderLimitLocked(policy.template);
50202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            }
503497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
504497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
505497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
506497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
50741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     * Notify that given {@link NetworkTemplate} is over
50841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
50941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     */
51041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void notifyOverLimitLocked(NetworkTemplate template) {
51141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (!mOverLimitNotified.contains(template)) {
51241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mContext.startActivity(buildNetworkOverLimitIntent(template));
51341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mOverLimitNotified.add(template);
51441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
51541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
51641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
51741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void notifyUnderLimitLocked(NetworkTemplate template) {
51841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mOverLimitNotified.remove(template);
51941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
52041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
52141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /**
522497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Build unique tag that identifies an active {@link NetworkPolicy}
523497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * notification of a specific type, like {@link #TYPE_LIMIT}.
524497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
525497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private String buildNotificationTag(NetworkPolicy policy, int type) {
5261b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return TAG + ":" + policy.template.hashCode() + ":" + type;
527497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
528497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
529497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
530497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Show notification for combined {@link NetworkPolicy} and specific type,
531497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * like {@link #TYPE_LIMIT}. Okay to call multiple times.
532497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
53341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
534497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final String tag = buildNotificationTag(policy, type);
535497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final Notification.Builder builder = new Notification.Builder(mContext);
536497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        builder.setOnlyAlertOnce(true);
537497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        builder.setOngoing(true);
538497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
539497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final Resources res = mContext.getResources();
540497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        switch (type) {
541497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            case TYPE_WARNING: {
54241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence title = res.getText(R.string.data_usage_warning_title);
54341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence body = res.getString(R.string.data_usage_warning_body,
544497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        Formatter.formatFileSize(mContext, policy.warningBytes));
545497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
546497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setSmallIcon(R.drawable.ic_menu_info_details);
547497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setTicker(title);
548497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setContentTitle(title);
549497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setContentText(body);
55014711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey
55141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final Intent intent = buildViewDataUsageIntent(policy.template);
55214711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey                builder.setContentIntent(PendingIntent.getActivity(
55314711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
554497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                break;
555497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
556497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            case TYPE_LIMIT: {
55741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence body = res.getText(R.string.data_usage_limit_body);
55841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
55941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence title;
5601b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                switch (policy.template.getMatchRule()) {
5611b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    case MATCH_MOBILE_3G_LOWER:
56241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_3g_limit_title);
563497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        break;
5641b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    case MATCH_MOBILE_4G:
56541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_4g_limit_title);
566497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        break;
567497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                    default:
56841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_mobile_limit_title);
569497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        break;
570497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                }
571497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
572497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setSmallIcon(com.android.internal.R.drawable.ic_menu_block);
573497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setTicker(title);
574497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setContentTitle(title);
575497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setContentText(body);
57614711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey
57741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final Intent intent = buildNetworkOverLimitIntent(policy.template);
57841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setContentIntent(PendingIntent.getActivity(
57941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
58041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                break;
58141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
58241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            case TYPE_LIMIT_SNOOZED: {
58341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final long overBytes = totalBytes - policy.limitBytes;
58441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body,
58541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        Formatter.formatFileSize(mContext, overBytes));
58641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
58741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence title;
58841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                switch (policy.template.getMatchRule()) {
58941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    case MATCH_MOBILE_3G_LOWER:
59041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_3g_limit_snoozed_title);
59141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        break;
59241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    case MATCH_MOBILE_4G:
59341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_4g_limit_snoozed_title);
59441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        break;
59541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    default:
59641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_mobile_limit_snoozed_title);
59741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        break;
59841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
59941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
60041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setSmallIcon(R.drawable.ic_menu_info_details);
60141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setTicker(title);
60241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setContentTitle(title);
60341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setContentText(body);
60441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
60541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final Intent intent = buildViewDataUsageIntent(policy.template);
60614711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey                builder.setContentIntent(PendingIntent.getActivity(
60714711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
608497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                break;
609497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
610497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
611497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
612497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // TODO: move to NotificationManager once we can mock it
613497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        try {
614497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final String packageName = mContext.getPackageName();
615497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final int[] idReceived = new int[1];
616497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            mNotifManager.enqueueNotificationWithTag(
617497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                    packageName, tag, 0x0, builder.getNotification(), idReceived);
618497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        } catch (RemoteException e) {
619497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            Slog.w(TAG, "problem during enqueueNotification: " + e);
620497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
621497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
622497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
623497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
624497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Cancel any notification for combined {@link NetworkPolicy} and specific
625497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * type, like {@link #TYPE_LIMIT}.
626497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
627497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private void cancelNotification(NetworkPolicy policy, int type) {
628497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final String tag = buildNotificationTag(policy, type);
629497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
630497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // TODO: move to NotificationManager once we can mock it
631497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        try {
632497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final String packageName = mContext.getPackageName();
633497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            mNotifManager.cancelNotificationWithTag(packageName, tag, 0x0);
634497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        } catch (RemoteException e) {
635497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            Slog.w(TAG, "problem during enqueueNotification: " + e);
636497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
637497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
638497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
639497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
64021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * Receiver that watches for {@link IConnectivityManager} to claim network
64122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey     * interfaces. Used to apply {@link NetworkPolicy} to matching networks.
64221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     */
643b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
64421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        @Override
64521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        public void onReceive(Context context, Intent intent) {
64621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
64721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // permission above.
64821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            synchronized (mRulesLock) {
64922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey                ensureActiveMobilePolicyLocked();
65002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                updateNetworkRulesLocked();
65102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                updateNotificationsLocked();
65221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
65321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
65421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    };
65521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
65621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    /**
65721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * Examine all connected {@link NetworkState}, looking for
65821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * {@link NetworkPolicy} that need to be enforced. When matches found, set
65921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * remaining quota based on usage cycle and historical stats.
66021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     */
66102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey    private void updateNetworkRulesLocked() {
66222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
66321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
66421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final NetworkState[] states;
66521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
66621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            states = mConnManager.getAllNetworkState();
66721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (RemoteException e) {
66821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            Slog.w(TAG, "problem reading network state");
66921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return;
67021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
67121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
67221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // first, derive identity for all connected networks, which can be used
67321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // to match against templates.
67421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final HashMap<NetworkIdentity, String> networks = Maps.newHashMap();
67521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        for (NetworkState state : states) {
67621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // stash identity and iface away for later use
67721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (state.networkInfo.isConnected()) {
67821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final String iface = state.linkProperties.getInterfaceName();
67921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
68021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                networks.put(ident, iface);
68121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
68221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
68321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
68421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // build list of rules and ifaces to enforce them against
68502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        mNetworkRules.clear();
68621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final ArrayList<String> ifaceList = Lists.newArrayList();
68741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        for (NetworkPolicy policy : mNetworkPolicy.values()) {
68821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
68921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // collect all active ifaces that match this template
69021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            ifaceList.clear();
69121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            for (NetworkIdentity ident : networks.keySet()) {
6921b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                if (policy.template.matches(ident)) {
69321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    final String iface = networks.get(ident);
69421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    ifaceList.add(iface);
69521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
69621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
69721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
69821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (ifaceList.size() > 0) {
69921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]);
70002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                mNetworkRules.put(policy, ifaces);
70121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
70221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
70321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
70421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // try refreshing time source when stale
70521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
70621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            mTime.forceRefresh();
70721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
70821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
70921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
71021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                : System.currentTimeMillis();
71121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
712b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        final HashSet<String> newMeteredIfaces = Sets.newHashSet();
713fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey
71421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // apply each policy that we found ifaces for; compute remaining data
71521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // based on current cycle and historical stats, and push to kernel.
71602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        for (NetworkPolicy policy : mNetworkRules.keySet()) {
71702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            final String[] ifaces = mNetworkRules.get(policy);
71821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
71921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final long start = computeLastCycleBoundary(currentTime, policy);
72021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final long end = currentTime;
72121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
72221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final NetworkStats stats;
72322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            final long total;
72421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            try {
7251b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                stats = mNetworkStats.getSummaryForNetwork(policy.template, start, end);
726d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                final NetworkStats.Entry entry = stats.getValues(0, null);
727d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                total = entry.rxBytes + entry.txBytes;
72821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            } catch (RemoteException e) {
7291b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                Slog.w(TAG, "problem reading summary for template " + policy.template);
73021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                continue;
73121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
73221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
73321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (LOGD) {
73421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
73522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey                        + Arrays.toString(ifaces));
73622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            }
73722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
73841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
73941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final boolean hasWarning = policy.warningBytes != WARNING_DISABLED;
74022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
74141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (hasLimit || hasWarning) {
74241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final long quotaBytes;
74341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                if (hasLimit) {
74441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    // remaining "quota" is based on usage in current cycle
74541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    quotaBytes = Math.max(0, policy.limitBytes - total);
74641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                } else {
74741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    // to track warning alert later, use a high quota
74841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    quotaBytes = Long.MAX_VALUE;
74941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
75050fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma
751b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                if (ifaces.length > 1) {
752b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    // TODO: switch to shared quota once NMS supports
753b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    Slog.w(TAG, "shared quota unsupported; generating rule for each iface");
754b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                }
755fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey
756fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey                for (String iface : ifaces) {
757b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    removeInterfaceQuota(iface);
75841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    if (quotaBytes > 0) {
75941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        setInterfaceQuota(iface, quotaBytes);
76041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        newMeteredIfaces.add(iface);
76141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    }
76241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
76341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
76441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
76541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (hasWarning) {
76641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final long alertBytes = Math.max(0, policy.warningBytes - total);
76741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                for (String iface : ifaces) {
76841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    removeInterfaceAlert(iface);
76941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    if (alertBytes > 0) {
77041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        setInterfaceAlert(iface, alertBytes);
77141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    }
772fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey                }
77322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            }
77422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        }
775fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey
776b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // remove quota on any trailing interfaces
777b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        for (String iface : mMeteredIfaces) {
778b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            if (!newMeteredIfaces.contains(iface)) {
779b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                removeInterfaceQuota(iface);
78050fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            }
78150fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma        }
782b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        mMeteredIfaces = newMeteredIfaces;
783b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
784b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
785b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
78650fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma    }
78750fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma
78822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    /**
78922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey     * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
79022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey     * have at least a default mobile policy defined.
79122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey     */
79222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private void ensureActiveMobilePolicyLocked() {
79322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
79422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        final String subscriberId = getActiveSubscriberId();
7951b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        final NetworkIdentity probeIdent = new NetworkIdentity(
7965dc0c26cffbbc62ff84f9f4c8a451e68e2c05d2dJeff Sharkey                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false);
79722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
79822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        // examine to see if any policy is defined for active mobile
79922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        boolean mobileDefined = false;
80041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        for (NetworkPolicy policy : mNetworkPolicy.values()) {
8011b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            if (policy.template.matches(probeIdent)) {
80222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey                mobileDefined = true;
80321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
80422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        }
80521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
80622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (!mobileDefined) {
80722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            Slog.i(TAG, "no policy for active mobile network; generating default policy");
80821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
80902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            // build default mobile policy, and assume usage cycle starts today
81002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            final long warningBytes = mContext.getResources().getInteger(
81102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    com.android.internal.R.integer.config_networkPolicyDefaultWarning)
81202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    * MB_IN_BYTES;
81322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
81422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            final Time time = new Time(Time.TIMEZONE_UTC);
81522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            time.setToNow();
81622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            final int cycleDay = time.monthDay;
81722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
8184e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
81941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkPolicy.put(template, new NetworkPolicy(
82041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    template, cycleDay, warningBytes, LIMIT_DISABLED, SNOOZE_NEVER));
821fcc79771f092f34505b1accb80365cbcaa379667Jeff Sharkey            writePolicyLocked();
82221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
82321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
82421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
82521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void readPolicyLocked() {
82622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (LOGV) Slog.v(TAG, "readPolicyLocked()");
82721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
82821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // clear any existing policy and read from disk
82922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        mNetworkPolicy.clear();
83021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mUidPolicy.clear();
83121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
83221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        FileInputStream fis = null;
83321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
83421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            fis = mPolicyFile.openRead();
83521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final XmlPullParser in = Xml.newPullParser();
83621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            in.setInput(fis, null);
83721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
83821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            int type;
83941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            int version = VERSION_INIT;
84021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            while ((type = in.next()) != END_DOCUMENT) {
84121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final String tag = in.getName();
84221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                if (type == START_TAG) {
84321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    if (TAG_POLICY_LIST.equals(tag)) {
84421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        version = readIntAttribute(in, ATTR_VERSION);
84521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
84621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    } else if (TAG_NETWORK_POLICY.equals(tag)) {
84721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
84821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
84921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
85021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
85121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
85241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        final long lastSnooze;
85341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        if (version >= VERSION_ADDED_SNOOZE) {
85441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                            lastSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
85541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        } else {
85641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                            lastSnooze = SNOOZE_NEVER;
85741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        }
85821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
8591b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                        final NetworkTemplate template = new NetworkTemplate(
8601b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                                networkTemplate, subscriberId);
86141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        mNetworkPolicy.put(template, new NetworkPolicy(
86241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                                template, cycleDay, warningBytes, limitBytes, lastSnooze));
86321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
86421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    } else if (TAG_UID_POLICY.equals(tag)) {
86521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int uid = readIntAttribute(in, ATTR_UID);
86621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int policy = readIntAttribute(in, ATTR_POLICY);
86721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
868497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        if (isUidValidForPolicy(mContext, uid)) {
869497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                            setUidPolicyUnchecked(uid, policy, false);
870497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        } else {
871497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                            Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
872497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        }
87321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    }
87421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
87521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
87621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
87721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (FileNotFoundException e) {
87821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // missing policy is okay, probably first boot
87921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (IOException e) {
88021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            Slog.e(TAG, "problem reading network stats", e);
88121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (XmlPullParserException e) {
88221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            Slog.e(TAG, "problem reading network stats", e);
88321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } finally {
88421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            IoUtils.closeQuietly(fis);
88521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
88621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
88721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
88821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void writePolicyLocked() {
88922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (LOGV) Slog.v(TAG, "writePolicyLocked()");
89021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
89121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        FileOutputStream fos = null;
89221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
89321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            fos = mPolicyFile.startWrite();
89421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
89521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            XmlSerializer out = new FastXmlSerializer();
89621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.setOutput(fos, "utf-8");
89721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.startDocument(null, true);
89821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
89921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.startTag(null, TAG_POLICY_LIST);
90041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_SNOOZE);
90121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
90221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // write all known network policies
90341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            for (NetworkPolicy policy : mNetworkPolicy.values()) {
9041b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                final NetworkTemplate template = policy.template;
9051b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
90621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.startTag(null, TAG_NETWORK_POLICY);
9071b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
9081b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                final String subscriberId = template.getSubscriberId();
9091b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                if (subscriberId != null) {
9101b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
91121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
91221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
91321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
91421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
91541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                writeLongAttribute(out, ATTR_LAST_SNOOZE, policy.lastSnooze);
91621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.endTag(null, TAG_NETWORK_POLICY);
91721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
91821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
91921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // write all known uid policies
92021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            for (int i = 0; i < mUidPolicy.size(); i++) {
92121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final int uid = mUidPolicy.keyAt(i);
92221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final int policy = mUidPolicy.valueAt(i);
92321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
924497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                // skip writing empty policies
925497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                if (policy == POLICY_NONE) continue;
926497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
92721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.startTag(null, TAG_UID_POLICY);
92821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeIntAttribute(out, ATTR_UID, uid);
92921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeIntAttribute(out, ATTR_POLICY, policy);
93021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.endTag(null, TAG_UID_POLICY);
93121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
93221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
93321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.endTag(null, TAG_POLICY_LIST);
93421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.endDocument();
93521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
93621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            mPolicyFile.finishWrite(fos);
93721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (IOException e) {
93821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (fos != null) {
93921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                mPolicyFile.failWrite(fos);
94021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
94121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
94221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
94321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
944d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    @Override
945d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    public void setUidPolicy(int uid, int policy) {
94621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
947a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
948497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        if (!isUidValidForPolicy(mContext, uid)) {
949497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
950497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
951497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
952497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        setUidPolicyUnchecked(uid, policy, true);
953497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
954497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
955497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private void setUidPolicyUnchecked(int uid, int policy, boolean persist) {
956c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        final int oldPolicy;
957a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
958c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            oldPolicy = getUidPolicy(uid);
959a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            mUidPolicy.put(uid, policy);
960c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
96121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // uid policy changed, recompute rules and persist policy.
96221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            updateRulesForUidLocked(uid);
963497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            if (persist) {
964497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                writePolicyLocked();
965497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
96621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
967d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
968d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
969d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    @Override
970d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    public int getUidPolicy(int uid) {
97121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
97221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
973a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
974a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            return mUidPolicy.get(uid, POLICY_NONE);
975a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
976d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
977d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
978c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    @Override
979c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    public void registerListener(INetworkPolicyListener listener) {
9801a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey        // TODO: create permission for observing network policy
9811a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
9821a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey
983c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mListeners.register(listener);
984c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
9854414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey        // TODO: consider dispatching existing rules to new listeners
986c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
987c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
988c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    @Override
989c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    public void unregisterListener(INetworkPolicyListener listener) {
9901a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey        // TODO: create permission for observing network policy
9911a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
9921a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey
993c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mListeners.unregister(listener);
994c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
995c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
9961b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    @Override
99722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    public void setNetworkPolicies(NetworkPolicy[] policies) {
99821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
99921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
100021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mRulesLock) {
100122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            mNetworkPolicy.clear();
100222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            for (NetworkPolicy policy : policies) {
100341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                mNetworkPolicy.put(policy.template, policy);
100422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            }
100521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
100602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            updateNetworkRulesLocked();
1007497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            updateNotificationsLocked();
100821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            writePolicyLocked();
100921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
101021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
101121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
101221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
101322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    public NetworkPolicy[] getNetworkPolicies() {
101421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
101522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
101621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
101721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mRulesLock) {
101841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]);
101941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
102041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
102141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
102241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    @Override
102341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public void snoozePolicy(NetworkTemplate template) {
102441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
102541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
102641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // try refreshing time source when stale
102741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
102841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mTime.forceRefresh();
102941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
103041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
103141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
103241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                : System.currentTimeMillis();
103341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
103441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        synchronized (mRulesLock) {
103541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            // find and snooze local policy that matches
103641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final NetworkPolicy policy = mNetworkPolicy.get(template);
103741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (policy == null) {
103841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                throw new IllegalArgumentException("unable to find policy for " + template);
103941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
104041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
104141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            policy.lastSnooze = currentTime;
104241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
104341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            updateNetworkRulesLocked();
104441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            updateNotificationsLocked();
104541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            writePolicyLocked();
104621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
104721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
104821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
104921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
10501b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
105175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
10521b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
105341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        final HashSet<String> argSet = new HashSet<String>();
105441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        for (String arg : args) {
105541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            argSet.add(arg);
105641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
105741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
10581b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        synchronized (mRulesLock) {
105941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (argSet.contains("unsnooze")) {
106041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                for (NetworkPolicy policy : mNetworkPolicy.values()) {
106141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    policy.lastSnooze = SNOOZE_NEVER;
106241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
106341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                writePolicyLocked();
106441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                fout.println("Wiped snooze timestamps");
106541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                return;
106641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
106741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
106821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            fout.println("Network policies:");
106941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            for (NetworkPolicy policy : mNetworkPolicy.values()) {
107022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey                fout.print("  "); fout.println(policy.toString());
107121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
107221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
10731b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            fout.println("Policy status for known UIDs:");
10741b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
10751b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            final SparseBooleanArray knownUids = new SparseBooleanArray();
10761b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidPolicy, knownUids);
10771b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidForeground, knownUids);
10781b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidRules, knownUids);
10791b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
10801b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            final int size = knownUids.size();
10811b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            for (int i = 0; i < size; i++) {
10821b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int uid = knownUids.keyAt(i);
10831b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print("  UID=");
10841b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(uid);
10851b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
10861b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" policy=");
10871b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int policyIndex = mUidPolicy.indexOfKey(uid);
10881b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (policyIndex < 0) {
10891b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
10901b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
10911b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpPolicy(fout, mUidPolicy.valueAt(policyIndex));
10921b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
10931b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
10941b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" foreground=");
10951b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int foregroundIndex = mUidPidForeground.indexOfKey(uid);
10961b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (foregroundIndex < 0) {
10971b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
10981b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
10991b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex));
11001b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
11011b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
11021b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" rules=");
11031b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int rulesIndex = mUidRules.indexOfKey(uid);
11041b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (rulesIndex < 0) {
11051b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
11061b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
11071b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpRules(fout, mUidRules.valueAt(rulesIndex));
11081b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
11091b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
11101b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.println();
11111b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            }
11121b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
11131b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
11149599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey
11159599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey    @Override
11169599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey    public boolean isUidForeground(int uid) {
1117497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1118497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
11199599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        synchronized (mRulesLock) {
11209599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey            // only really in foreground when screen is also on
11219599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey            return mUidForeground.get(uid, false) && mScreenOn;
11229599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        }
1123c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
1124c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
1125d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    /**
1126d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey     * Foreground for PID changed; recompute foreground at UID level. If
112721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * changed, will trigger {@link #updateRulesForUidLocked(int)}.
1128d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey     */
112921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void computeUidForegroundLocked(int uid) {
1130d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
1131d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1132d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        // current pid is dropping foreground; examine other pids
1133d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        boolean uidForeground = false;
1134d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final int size = pidForeground.size();
1135d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        for (int i = 0; i < size; i++) {
1136d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            if (pidForeground.valueAt(i)) {
1137d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey                uidForeground = true;
1138d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey                break;
1139d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            }
1140d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
1141d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1142d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final boolean oldUidForeground = mUidForeground.get(uid, false);
1143d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        if (oldUidForeground != uidForeground) {
1144d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            // foreground changed, push updated rules
1145d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            mUidForeground.put(uid, uidForeground);
114621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            updateRulesForUidLocked(uid);
1147a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
1148a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
1149a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
1150a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private void updateScreenOn() {
1151a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
1152a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            try {
1153a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                mScreenOn = mPowerManager.isScreenOn();
1154a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            } catch (RemoteException e) {
1155a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
115621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            updateRulesForScreenLocked();
1157d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
1158d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
1159d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1160b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    private void updateBackgroundData(boolean systemReady) {
1161b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        synchronized (mRulesLock) {
1162b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            try {
1163b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                mBackgroundData = mConnManager.getBackgroundDataSetting();
1164b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            } catch (RemoteException e) {
1165b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
1166b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            if (systemReady && mBackgroundData) {
1167b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                // typical behavior of background enabled during systemReady;
1168b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                // no need to clear rules for all UIDs.
1169b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            } else {
1170b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                updateRulesForBackgroundDataLocked();
1171b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
1172b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1173b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
1174b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1175a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    /**
1176a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey     * Update rules that might be changed by {@link #mScreenOn} value.
1177a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey     */
117821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void updateRulesForScreenLocked() {
1179a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // only update rules for anyone with foreground activities
1180a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        final int size = mUidForeground.size();
1181a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        for (int i = 0; i < size; i++) {
1182a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            if (mUidForeground.valueAt(i)) {
1183a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                final int uid = mUidForeground.keyAt(i);
118421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                updateRulesForUidLocked(uid);
1185a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
1186a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
1187a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
1188a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
1189b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    /**
1190b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey     * Update rules that might be changed by {@link #mBackgroundData} value.
1191b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey     */
1192b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    private void updateRulesForBackgroundDataLocked() {
1193b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // update rules for all installed applications
1194b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        final PackageManager pm = mContext.getPackageManager();
1195b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
1196b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        for (ApplicationInfo app : apps) {
1197b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            updateRulesForUidLocked(app.uid);
1198b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1199b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1200b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // and catch system UIDs
1201b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // TODO: keep in sync with android_filesystem_config.h
1202b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        for (int uid = 1000; uid <= 1025; uid++) {
1203b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            updateRulesForUidLocked(uid);
1204b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1205b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        for (int uid = 2000; uid <= 2002; uid++) {
1206b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            updateRulesForUidLocked(uid);
1207b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1208b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        for (int uid = 3000; uid <= 3007; uid++) {
1209b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            updateRulesForUidLocked(uid);
1210b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1211b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        for (int uid = 9998; uid <= 9999; uid++) {
1212b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            updateRulesForUidLocked(uid);
1213b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1214b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
1215b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
121621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void updateRulesForUidLocked(int uid) {
1217d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final int uidPolicy = getUidPolicy(uid);
12189599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        final boolean uidForeground = isUidForeground(uid);
1219d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1220c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // derive active rules based on policy and active state
1221c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        int uidRules = RULE_ALLOW_ALL;
1222fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey        if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
1223fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey            // uid in background, and policy says to block metered data
1224fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey            uidRules = RULE_REJECT_METERED;
1225d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
1226b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        if (!uidForeground && !mBackgroundData) {
1227b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            // uid in background, and global background disabled
1228b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            uidRules = RULE_REJECT_METERED;
1229b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1230d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1231c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // TODO: only dispatch when rules actually change
1232c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
1233350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        if (uidRules == RULE_ALLOW_ALL) {
1234350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            mUidRules.delete(uid);
1235350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        } else {
1236350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            mUidRules.put(uid, uidRules);
1237350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        }
1238c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
1239fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey        final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0;
124050fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma        setUidNetworkRules(uid, rejectMetered);
1241497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
1242c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // dispatch changed rule to existing listeners
12434414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey        mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
12444414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    }
12454414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey
12464414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    private Handler.Callback mHandlerCallback = new Handler.Callback() {
12474414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey        /** {@inheritDoc} */
12484414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey        public boolean handleMessage(Message msg) {
12494414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey            switch (msg.what) {
12504414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                case MSG_RULES_CHANGED: {
12514414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final int uid = msg.arg1;
12524414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final int uidRules = msg.arg2;
12534414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final int length = mListeners.beginBroadcast();
12544414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    for (int i = 0; i < length; i++) {
12554414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
12564414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        if (listener != null) {
12574414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            try {
12584414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                                listener.onUidRulesChanged(uid, uidRules);
12594414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            } catch (RemoteException e) {
12604414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            }
12614414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        }
12624414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    }
12634414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    mListeners.finishBroadcast();
12644414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    return true;
12654414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                }
12664414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                case MSG_METERED_IFACES_CHANGED: {
12674414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final String[] meteredIfaces = (String[]) msg.obj;
12684414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final int length = mListeners.beginBroadcast();
12694414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    for (int i = 0; i < length; i++) {
12704414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
12714414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        if (listener != null) {
12724414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            try {
12734414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                                listener.onMeteredIfacesChanged(meteredIfaces);
12744414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            } catch (RemoteException e) {
12754414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            }
12764414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        }
12774414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    }
12784414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    mListeners.finishBroadcast();
12794414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    return true;
12804414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                }
12814414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                default: {
12824414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    return false;
1283af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey                }
1284af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey            }
1285af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey        }
12864414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    };
128722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
128841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void setInterfaceQuota(String iface, long quotaBytes) {
1289b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        try {
129041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.setInterfaceQuota(iface, quotaBytes);
1291b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (IllegalStateException e) {
1292b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            Slog.e(TAG, "problem setting interface quota", e);
1293b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (RemoteException e) {
1294b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            Slog.e(TAG, "problem setting interface quota", e);
1295b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1296b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
1297b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1298b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    private void removeInterfaceQuota(String iface) {
1299b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        try {
130041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.removeInterfaceQuota(iface);
1301b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (IllegalStateException e) {
1302b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            Slog.e(TAG, "problem removing interface quota", e);
1303b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (RemoteException e) {
1304b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            Slog.e(TAG, "problem removing interface quota", e);
1305b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1306b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
1307b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
130841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void setInterfaceAlert(String iface, long alertBytes) {
130941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        try {
131041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.setInterfaceAlert(iface, alertBytes);
131141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (IllegalStateException e) {
131241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            Slog.e(TAG, "problem setting interface alert", e);
131341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (RemoteException e) {
131441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            Slog.e(TAG, "problem setting interface alert", e);
131541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
131641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
131741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
131841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void removeInterfaceAlert(String iface) {
131941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        try {
132041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.removeInterfaceAlert(iface);
132141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (IllegalStateException e) {
132241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            Slog.e(TAG, "problem removing interface alert", e);
132341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (RemoteException e) {
132441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            Slog.e(TAG, "problem removing interface alert", e);
132541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
132641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
132741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
1328b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
1329b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        try {
133041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
1331b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (IllegalStateException e) {
1332b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            Slog.e(TAG, "problem setting uid rules", e);
1333b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (RemoteException e) {
1334b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            Slog.e(TAG, "problem setting uid rules", e);
1335b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1336b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
1337b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
133822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private String getActiveSubscriberId() {
133922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService(
134022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey                Context.TELEPHONY_SERVICE);
134122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        return telephony.getSubscriberId();
134222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    }
134322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
134441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
134541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        final Intent intent = new Intent();
134641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.setComponent(new ComponentName(
134741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity"));
134841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
134941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
135041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        return intent;
135141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
135241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
135341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static Intent buildViewDataUsageIntent(NetworkTemplate template) {
135441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        final Intent intent = new Intent();
135541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.setComponent(new ComponentName(
135641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
135741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
135841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
135941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        return intent;
136041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
136141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
13621b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
13631b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = source.size();
13641b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
13651b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            target.put(source.keyAt(i), true);
13661b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
13671b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
13681b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
13691b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) {
13701b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = source.size();
13711b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
13721b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            target.put(source.keyAt(i), true);
13731b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
13741b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
13751b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
13761b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) {
13771b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        fout.print("[");
13781b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = value.size();
13791b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
13801b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            fout.print(value.keyAt(i) + "=" + value.valueAt(i));
13811b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            if (i < size - 1) fout.print(",");
13821b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
13831b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        fout.print("]");
13841b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
138521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
138621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static int readIntAttribute(XmlPullParser in, String name) throws IOException {
138721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final String value = in.getAttributeValue(null, name);
138821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
138921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return Integer.parseInt(value);
139021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (NumberFormatException e) {
139121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
139221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
139321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
139421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
139521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static long readLongAttribute(XmlPullParser in, String name) throws IOException {
139621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final String value = in.getAttributeValue(null, name);
139721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
139821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return Long.parseLong(value);
139921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (NumberFormatException e) {
140041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
140121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
140221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
140321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
140421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static void writeIntAttribute(XmlSerializer out, String name, int value)
140521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            throws IOException {
140621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        out.attribute(null, name, Integer.toString(value));
140721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
140821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
140921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static void writeLongAttribute(XmlSerializer out, String name, long value)
141021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            throws IOException {
141121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        out.attribute(null, name, Long.toString(value));
141221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
141321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1414d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey}
1415