NetworkPolicyManagerService.java revision f0ceede8fff5df24e5c98701d81c2b71eb138aa9
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
19f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkeyimport static android.Manifest.permission.ACCESS_NETWORK_STATE;
2021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.CONNECTIVITY_INTERNAL;
211b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.Manifest.permission.DUMP;
22d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport static android.Manifest.permission.MANAGE_APP_TOKENS;
2321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.MANAGE_NETWORK_POLICY;
24497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
2522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport static android.Manifest.permission.READ_PHONE_STATE;
2602e21d6a5b5117d494777a36783909854854f751Jeff Sharkeyimport static android.content.Intent.ACTION_PACKAGE_ADDED;
27b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.ACTION_UID_REMOVED;
28b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.EXTRA_UID;
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;
484664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkeyimport static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readBooleanAttribute;
494664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkeyimport static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readIntAttribute;
504664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkeyimport static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readLongAttribute;
514664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkeyimport static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeBooleanAttribute;
524664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkeyimport static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeIntAttribute;
534664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkeyimport static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeLongAttribute;
54497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
5521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
5621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.START_TAG;
57d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
58a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IActivityManager;
59497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.INotificationManager;
60a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IProcessObserver;
61497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.Notification;
62497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.PendingIntent;
63a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.BroadcastReceiver;
6441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkeyimport android.content.ComponentName;
65d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.content.Context;
66a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.Intent;
67a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.IntentFilter;
68b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.content.pm.ApplicationInfo;
69b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.content.pm.PackageManager;
70497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.content.res.Resources;
71c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.ConnectivityManager;
7221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.IConnectivityManager;
7341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkeyimport android.net.INetworkManagementEventObserver;
74c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.INetworkPolicyListener;
75d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.net.INetworkPolicyManager;
7675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.INetworkStatsService;
771b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkIdentity;
7821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkPolicy;
79f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkeyimport android.net.NetworkQuotaInfo;
8021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkState;
8121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkStats;
821b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkTemplate;
83f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkeyimport android.os.Binder;
8421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Environment;
8521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Handler;
8621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.HandlerThread;
8750fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharmaimport android.os.INetworkManagementService;
88a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.IPowerManager;
894414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkeyimport android.os.Message;
90c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.os.RemoteCallbackList;
91a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.RemoteException;
9222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport android.telephony.TelephonyManager;
93497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.text.format.Formatter;
9422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport android.text.format.Time;
9521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.NtpTrustedTime;
96a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.util.Slog;
97d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseArray;
98d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseBooleanArray;
99d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseIntArray;
10021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.TrustedTime;
10121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.Xml;
102d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
103497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport com.android.internal.R;
10421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.android.internal.os.AtomicFile;
10521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.android.internal.util.FastXmlSerializer;
10621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.google.android.collect.Lists;
10721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.google.android.collect.Maps;
108fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport com.google.android.collect.Sets;
10921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
11021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlPullParser;
11121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlPullParserException;
11221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlSerializer;
11321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
11421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.File;
1151b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.FileDescriptor;
11621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileInputStream;
11721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileNotFoundException;
11821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileOutputStream;
11921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.IOException;
1201b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.PrintWriter;
12121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.net.ProtocolException;
12221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.ArrayList;
12321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.Arrays;
12421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.HashMap;
125fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport java.util.HashSet;
126b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport java.util.List;
12721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
12821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport libcore.io.IoUtils;
1291b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
130d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/**
131d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Service that maintains low-level network policy rules and collects usage
132d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * statistics to drive those rules.
133c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * <p>
134c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * Derives active rules by combining a given policy with other system status,
135c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * and delivers to listeners, such as {@link ConnectivityManager}, for
136c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * enforcement.
137d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */
138d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeypublic class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
139d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    private static final String TAG = "NetworkPolicy";
140d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    private static final boolean LOGD = true;
14122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private static final boolean LOGV = false;
142d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
14341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static final int VERSION_INIT = 1;
14441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static final int VERSION_ADDED_SNOOZE = 2;
1454664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3;
14621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
14722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private static final long KB_IN_BYTES = 1024;
14822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
14922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
15022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
15141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    // @VisibleForTesting
15241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public static final int TYPE_WARNING = 0x1;
15341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public static final int TYPE_LIMIT = 0x2;
15441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public static final int TYPE_LIMIT_SNOOZED = 0x3;
155497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
15621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG_POLICY_LIST = "policy-list";
15721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG_NETWORK_POLICY = "network-policy";
15821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG_UID_POLICY = "uid-policy";
15921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
16021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_VERSION = "version";
1614664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
16221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
16321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
16421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_CYCLE_DAY = "cycleDay";
16521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_WARNING_BYTES = "warningBytes";
16621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_LIMIT_BYTES = "limitBytes";
16741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static final String ATTR_LAST_SNOOZE = "lastSnooze";
16821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_UID = "uid";
16921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_POLICY = "policy";
17021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
17121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
17221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1734414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    private static final int MSG_RULES_CHANGED = 0x1;
1744414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    private static final int MSG_METERED_IFACES_CHANGED = 0x2;
1754414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey
17675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Context mContext;
17775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final IActivityManager mActivityManager;
17875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final IPowerManager mPowerManager;
17975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final INetworkStatsService mNetworkStats;
18041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private final INetworkManagementService mNetworkManager;
18121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final TrustedTime mTime;
18221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
18321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private IConnectivityManager mConnManager;
184497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private INotificationManager mNotifManager;
185a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
18675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Object mRulesLock = new Object();
187a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
188c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    private boolean mScreenOn;
1894664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    private boolean mRestrictBackground;
190d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
19141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Defined network policies. */
19241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap();
19341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Currently active network rules for ifaces. */
19402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey    private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap();
19522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
19641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Defined UID policies. */
197a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private SparseIntArray mUidPolicy = new SparseIntArray();
19841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Currently derived rules for each UID. */
199c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    private SparseIntArray mUidRules = new SparseIntArray();
200d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
201fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey    /** Set of ifaces that are metered. */
202fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey    private HashSet<String> mMeteredIfaces = Sets.newHashSet();
20341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Set of over-limit templates that have been notified. */
20441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet();
205fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey
206d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    /** Foreground at both UID and PID granularity. */
207a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private SparseBooleanArray mUidForeground = new SparseBooleanArray();
208a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
209a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            SparseBooleanArray>();
210d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
211c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
212c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            INetworkPolicyListener>();
213c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
21421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final HandlerThread mHandlerThread;
21521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final Handler mHandler;
21621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
21721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final AtomicFile mPolicyFile;
218d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
219c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    // TODO: keep whitelist of system-critical services that should never have
220c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    // rules enforced, such as system, phone, and radio UIDs.
221c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
22241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    // TODO: migrate notifications to SystemUI
22341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
22475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
22550fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            IPowerManager powerManager, INetworkStatsService networkStats,
22650fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            INetworkManagementService networkManagement) {
227b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        this(context, activityManager, powerManager, networkStats, networkManagement,
228104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey                NtpTrustedTime.getInstance(context), getSystemDir());
22921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
23021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
23121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static File getSystemDir() {
23221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        return new File(Environment.getDataDirectory(), "system");
23321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
23421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
23521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
23650fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            IPowerManager powerManager, INetworkStatsService networkStats,
23750fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            INetworkManagementService networkManagement,
23850fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            TrustedTime time, File systemDir) {
239a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mContext = checkNotNull(context, "missing context");
240a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mActivityManager = checkNotNull(activityManager, "missing activityManager");
241a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mPowerManager = checkNotNull(powerManager, "missing powerManager");
24275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mNetworkStats = checkNotNull(networkStats, "missing networkStats");
24341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
24421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mTime = checkNotNull(time, "missing TrustedTime");
24521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
24621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mHandlerThread = new HandlerThread(TAG);
24721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mHandlerThread.start();
2484414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey        mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
24921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
25021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
25121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
25221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
25321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public void bindConnectivityManager(IConnectivityManager connManager) {
25421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
255a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
256d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
257497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    public void bindNotificationManager(INotificationManager notifManager) {
258497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        mNotifManager = checkNotNull(notifManager, "missing INotificationManager");
259497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
260497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
261a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    public void systemReady() {
26221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mRulesLock) {
26321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // read policy from disk
26421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            readPolicyLocked();
2654664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey
2664664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            if (mRestrictBackground) {
2674664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                updateRulesForRestrictBackgroundLocked();
2684664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            }
26921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
270d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
271a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        updateScreenOn();
272d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
273a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        try {
274a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            mActivityManager.registerProcessObserver(mProcessObserver);
275a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        } catch (RemoteException e) {
276a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // ouch, no foregroundActivities updates means some processes may
277a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // never get network access.
278a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            Slog.e(TAG, "unable to register IProcessObserver", e);
279a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
280d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
28141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        try {
28241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.registerObserver(mAlertObserver);
28341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (RemoteException e) {
28441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            // ouch, no alert updates means we fall back to
28541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            // ACTION_NETWORK_STATS_UPDATED broadcasts.
28641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            Slog.e(TAG, "unable to register INetworkManagementEventObserver", e);
28741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
28841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
289a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // TODO: traverse existing processes to know foreground state, or have
290a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // activitymanager dispatch current state when new observer attached.
291d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
292a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        final IntentFilter screenFilter = new IntentFilter();
293a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
294a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
29541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler);
296d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
29721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // watch for network interfaces to be claimed
298b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
299b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
300b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
30102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        // listen for package/uid changes to update policy
30202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        final IntentFilter packageFilter = new IntentFilter();
30302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        packageFilter.addAction(ACTION_PACKAGE_ADDED);
30402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        packageFilter.addAction(ACTION_UID_REMOVED);
30502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
30621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
307b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // listen for stats update events
308497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
309497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        mContext.registerReceiver(
310497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
311497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
312a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
313d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
314a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
315a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
316a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
317a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // only someone like AMS should only be calling us
31875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
319a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
320a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            synchronized (mRulesLock) {
321a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // because a uid can have multiple pids running inside, we need to
322a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // remember all pid states and summarize foreground at uid level.
323a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
324a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // record foreground for this specific pid
325a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
326a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                if (pidForeground == null) {
327a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    pidForeground = new SparseBooleanArray(2);
328a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    mUidPidForeground.put(uid, pidForeground);
329a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                }
330a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                pidForeground.put(pid, foregroundActivities);
33121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                computeUidForegroundLocked(uid);
332a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
333d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
334d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
335a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
336a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onProcessDied(int pid, int uid) {
337a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // only someone like AMS should only be calling us
33875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
339a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
340a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            synchronized (mRulesLock) {
341a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // clear records and recompute, when they exist
342a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
343a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                if (pidForeground != null) {
344a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    pidForeground.delete(pid);
34521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    computeUidForegroundLocked(uid);
346a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                }
347a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
348a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
349a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    };
350a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
351a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
352a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
353a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onReceive(Context context, Intent intent) {
354a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            synchronized (mRulesLock) {
355a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // screen-related broadcasts are protected by system, no need
356a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // for permissions check.
357a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                updateScreenOn();
358a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
359a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
360a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    };
361d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
36202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey    private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
363b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        @Override
364b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        public void onReceive(Context context, Intent intent) {
36502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            // on background handler thread, and PACKAGE_ADDED and UID_REMOVED
36602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            // are protected broadcasts.
36702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey
36802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            final String action = intent.getAction();
369b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            final int uid = intent.getIntExtra(EXTRA_UID, 0);
370b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            synchronized (mRulesLock) {
37102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                if (ACTION_PACKAGE_ADDED.equals(action)) {
37202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    // update rules for UID, since it might be subject to
37302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    // global background data policy.
37402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
37502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    updateRulesForUidLocked(uid);
37602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey
37702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                } else if (ACTION_UID_REMOVED.equals(action)) {
37802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    // remove any policy and update rules to clean up.
37902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
38002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    mUidPolicy.delete(uid);
38102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    updateRulesForUidLocked(uid);
38202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    writePolicyLocked();
38302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                }
384b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            }
385b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        }
386b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    };
387b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
38821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    /**
389497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Receiver that watches for {@link INetworkStatsService} updates, which we
390497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * use to check against {@link NetworkPolicy#warningBytes}.
391497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
392497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() {
393497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        @Override
394497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        public void onReceive(Context context, Intent intent) {
395497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            // on background handler thread, and verified
396497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            // READ_NETWORK_USAGE_HISTORY permission above.
397497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
398497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            synchronized (mRulesLock) {
399497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                updateNotificationsLocked();
400497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
401497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
402497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    };
403497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
404497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
40541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     * Observer that watches for {@link INetworkManagementService} alerts.
40641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     */
40741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
40841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        @Override
40941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        public void limitReached(String limitName, String iface) {
41041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            // only someone like NMS should be calling us
41141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
41241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
41341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            synchronized (mRulesLock) {
41441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                if (mMeteredIfaces.contains(iface)) {
41541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    try {
41641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        // force stats update to make sure we have numbers that
41741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        // caused alert to trigger.
41841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        mNetworkStats.forceUpdate();
41941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    } catch (RemoteException e) {
42041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        Slog.w(TAG, "problem updating network stats");
42141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    }
42241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
42341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    updateNotificationsLocked();
42441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
42541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
42641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
42741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    };
42841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
42941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /**
430497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
431497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * to show visible notifications as needed.
432497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
433497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private void updateNotificationsLocked() {
434497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        if (LOGV) Slog.v(TAG, "updateNotificationsLocked()");
435497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
436497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // try refreshing time source when stale
437497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
438497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            mTime.forceRefresh();
439497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
440497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
441497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
442497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                : System.currentTimeMillis();
443497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
444497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // TODO: when switching to kernel notifications, compute next future
445497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // cycle boundary to recompute notifications.
446497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
44702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        // examine stats for each active policy
44802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        for (NetworkPolicy policy : mNetworkRules.keySet()) {
449497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final long start = computeLastCycleBoundary(currentTime, policy);
450497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final long end = currentTime;
451497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
45241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final long totalBytes;
453497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            try {
454497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
4551b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                        policy.template, start, end);
456d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                final NetworkStats.Entry entry = stats.getValues(0, null);
45741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                totalBytes = entry.rxBytes + entry.txBytes;
458497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            } catch (RemoteException e) {
4591b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                Slog.w(TAG, "problem reading summary for template " + policy.template);
460497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                continue;
461497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
462497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
46341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (policy.limitBytes != LIMIT_DISABLED && totalBytes >= policy.limitBytes) {
464497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                cancelNotification(policy, TYPE_WARNING);
46541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
46641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                if (policy.lastSnooze >= start) {
46741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    cancelNotification(policy, TYPE_LIMIT);
46841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
46941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                } else {
47041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    cancelNotification(policy, TYPE_LIMIT_SNOOZED);
47141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    enqueueNotification(policy, TYPE_LIMIT, totalBytes);
47241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    notifyOverLimitLocked(policy.template);
47341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
47441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
475497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            } else {
476497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                cancelNotification(policy, TYPE_LIMIT);
47741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                cancelNotification(policy, TYPE_LIMIT_SNOOZED);
47841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                notifyUnderLimitLocked(policy.template);
479497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
48041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) {
48141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    enqueueNotification(policy, TYPE_WARNING, totalBytes);
482497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                } else {
483497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                    cancelNotification(policy, TYPE_WARNING);
484497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                }
485497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
48602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        }
48702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey
48802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        // clear notifications for non-active policies
48941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        for (NetworkPolicy policy : mNetworkPolicy.values()) {
49002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            if (!mNetworkRules.containsKey(policy)) {
49102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                cancelNotification(policy, TYPE_WARNING);
49202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                cancelNotification(policy, TYPE_LIMIT);
49341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                cancelNotification(policy, TYPE_LIMIT_SNOOZED);
49441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                notifyUnderLimitLocked(policy.template);
49502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            }
496497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
497497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
498497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
499497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
50041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     * Notify that given {@link NetworkTemplate} is over
50141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
50241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     */
50341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void notifyOverLimitLocked(NetworkTemplate template) {
50441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (!mOverLimitNotified.contains(template)) {
50541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mContext.startActivity(buildNetworkOverLimitIntent(template));
50641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mOverLimitNotified.add(template);
50741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
50841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
50941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
51041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void notifyUnderLimitLocked(NetworkTemplate template) {
51141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mOverLimitNotified.remove(template);
51241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
51341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
51441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /**
515497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Build unique tag that identifies an active {@link NetworkPolicy}
516497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * notification of a specific type, like {@link #TYPE_LIMIT}.
517497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
518497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private String buildNotificationTag(NetworkPolicy policy, int type) {
5191b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return TAG + ":" + policy.template.hashCode() + ":" + type;
520497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
521497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
522497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
523497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Show notification for combined {@link NetworkPolicy} and specific type,
524497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * like {@link #TYPE_LIMIT}. Okay to call multiple times.
525497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
52641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
527497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final String tag = buildNotificationTag(policy, type);
528497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final Notification.Builder builder = new Notification.Builder(mContext);
529497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        builder.setOnlyAlertOnce(true);
530497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        builder.setOngoing(true);
531497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
532497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final Resources res = mContext.getResources();
533497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        switch (type) {
534497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            case TYPE_WARNING: {
53541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence title = res.getText(R.string.data_usage_warning_title);
53641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence body = res.getString(R.string.data_usage_warning_body,
537497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        Formatter.formatFileSize(mContext, policy.warningBytes));
538497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
539497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setSmallIcon(R.drawable.ic_menu_info_details);
540497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setTicker(title);
541497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setContentTitle(title);
542497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setContentText(body);
54314711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey
54441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final Intent intent = buildViewDataUsageIntent(policy.template);
54514711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey                builder.setContentIntent(PendingIntent.getActivity(
54614711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
547497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                break;
548497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
549497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            case TYPE_LIMIT: {
55041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence body = res.getText(R.string.data_usage_limit_body);
55141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
55241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence title;
5531b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                switch (policy.template.getMatchRule()) {
5541b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    case MATCH_MOBILE_3G_LOWER:
55541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_3g_limit_title);
556497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        break;
5571b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    case MATCH_MOBILE_4G:
55841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_4g_limit_title);
559497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        break;
560497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                    default:
56141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_mobile_limit_title);
562497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        break;
563497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                }
564497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
565497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setSmallIcon(com.android.internal.R.drawable.ic_menu_block);
566497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setTicker(title);
567497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setContentTitle(title);
568497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setContentText(body);
56914711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey
57041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final Intent intent = buildNetworkOverLimitIntent(policy.template);
57141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setContentIntent(PendingIntent.getActivity(
57241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
57341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                break;
57441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
57541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            case TYPE_LIMIT_SNOOZED: {
57641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final long overBytes = totalBytes - policy.limitBytes;
57741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body,
57841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        Formatter.formatFileSize(mContext, overBytes));
57941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
58041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence title;
58141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                switch (policy.template.getMatchRule()) {
58241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    case MATCH_MOBILE_3G_LOWER:
58341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_3g_limit_snoozed_title);
58441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        break;
58541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    case MATCH_MOBILE_4G:
58641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_4g_limit_snoozed_title);
58741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        break;
58841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    default:
58941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_mobile_limit_snoozed_title);
59041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        break;
59141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
59241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
59341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setSmallIcon(R.drawable.ic_menu_info_details);
59441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setTicker(title);
59541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setContentTitle(title);
59641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setContentText(body);
59741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
59841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final Intent intent = buildViewDataUsageIntent(policy.template);
59914711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey                builder.setContentIntent(PendingIntent.getActivity(
60014711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
601497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                break;
602497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
603497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
604497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
605497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // TODO: move to NotificationManager once we can mock it
606497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        try {
607497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final String packageName = mContext.getPackageName();
608497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final int[] idReceived = new int[1];
609497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            mNotifManager.enqueueNotificationWithTag(
610497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                    packageName, tag, 0x0, builder.getNotification(), idReceived);
611497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        } catch (RemoteException e) {
612497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            Slog.w(TAG, "problem during enqueueNotification: " + e);
613497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
614497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
615497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
616497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
617497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Cancel any notification for combined {@link NetworkPolicy} and specific
618497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * type, like {@link #TYPE_LIMIT}.
619497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
620497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private void cancelNotification(NetworkPolicy policy, int type) {
621497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final String tag = buildNotificationTag(policy, type);
622497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
623497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // TODO: move to NotificationManager once we can mock it
624497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        try {
625497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final String packageName = mContext.getPackageName();
626497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            mNotifManager.cancelNotificationWithTag(packageName, tag, 0x0);
627497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        } catch (RemoteException e) {
628497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            Slog.w(TAG, "problem during enqueueNotification: " + e);
629497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
630497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
631497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
632497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
63321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * Receiver that watches for {@link IConnectivityManager} to claim network
63422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey     * interfaces. Used to apply {@link NetworkPolicy} to matching networks.
63521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     */
636b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
63721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        @Override
63821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        public void onReceive(Context context, Intent intent) {
63921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
64021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // permission above.
64121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            synchronized (mRulesLock) {
64222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey                ensureActiveMobilePolicyLocked();
64302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                updateNetworkRulesLocked();
64402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                updateNotificationsLocked();
64521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
64621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
64721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    };
64821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
64921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    /**
65021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * Examine all connected {@link NetworkState}, looking for
65121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * {@link NetworkPolicy} that need to be enforced. When matches found, set
65221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * remaining quota based on usage cycle and historical stats.
65321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     */
65402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey    private void updateNetworkRulesLocked() {
65522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
65621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
65721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final NetworkState[] states;
65821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
65921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            states = mConnManager.getAllNetworkState();
66021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (RemoteException e) {
66121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            Slog.w(TAG, "problem reading network state");
66221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return;
66321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
66421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
66521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // first, derive identity for all connected networks, which can be used
66621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // to match against templates.
66721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final HashMap<NetworkIdentity, String> networks = Maps.newHashMap();
66821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        for (NetworkState state : states) {
66921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // stash identity and iface away for later use
67021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (state.networkInfo.isConnected()) {
67121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final String iface = state.linkProperties.getInterfaceName();
67221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
67321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                networks.put(ident, iface);
67421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
67521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
67621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
67721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // build list of rules and ifaces to enforce them against
67802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        mNetworkRules.clear();
67921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final ArrayList<String> ifaceList = Lists.newArrayList();
68041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        for (NetworkPolicy policy : mNetworkPolicy.values()) {
68121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
68221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // collect all active ifaces that match this template
68321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            ifaceList.clear();
68421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            for (NetworkIdentity ident : networks.keySet()) {
6851b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                if (policy.template.matches(ident)) {
68621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    final String iface = networks.get(ident);
68721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    ifaceList.add(iface);
68821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
68921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
69021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
69121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (ifaceList.size() > 0) {
69221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]);
69302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                mNetworkRules.put(policy, ifaces);
69421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
69521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
69621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
69721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // try refreshing time source when stale
69821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
69921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            mTime.forceRefresh();
70021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
70121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
70221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
70321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                : System.currentTimeMillis();
70421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
705b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        final HashSet<String> newMeteredIfaces = Sets.newHashSet();
706fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey
70721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // apply each policy that we found ifaces for; compute remaining data
70821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // based on current cycle and historical stats, and push to kernel.
70902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        for (NetworkPolicy policy : mNetworkRules.keySet()) {
71002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            final String[] ifaces = mNetworkRules.get(policy);
71121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
71221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final long start = computeLastCycleBoundary(currentTime, policy);
71321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final long end = currentTime;
71421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
71521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final NetworkStats stats;
71622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            final long total;
71721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            try {
7181b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                stats = mNetworkStats.getSummaryForNetwork(policy.template, start, end);
719d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                final NetworkStats.Entry entry = stats.getValues(0, null);
720d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                total = entry.rxBytes + entry.txBytes;
72121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            } catch (RemoteException e) {
7221b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                Slog.w(TAG, "problem reading summary for template " + policy.template);
72321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                continue;
72421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
72521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
72621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (LOGD) {
72721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
72822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey                        + Arrays.toString(ifaces));
72922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            }
73022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
73141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
73241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final boolean hasWarning = policy.warningBytes != WARNING_DISABLED;
73322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
73441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (hasLimit || hasWarning) {
73541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final long quotaBytes;
73641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                if (hasLimit) {
73741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    // remaining "quota" is based on usage in current cycle
73841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    quotaBytes = Math.max(0, policy.limitBytes - total);
73941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                } else {
74041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    // to track warning alert later, use a high quota
74141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    quotaBytes = Long.MAX_VALUE;
74241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
74350fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma
744b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                if (ifaces.length > 1) {
745b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    // TODO: switch to shared quota once NMS supports
746b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    Slog.w(TAG, "shared quota unsupported; generating rule for each iface");
747b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                }
748fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey
749fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey                for (String iface : ifaces) {
750b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    removeInterfaceQuota(iface);
75141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    if (quotaBytes > 0) {
75241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        setInterfaceQuota(iface, quotaBytes);
75341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        newMeteredIfaces.add(iface);
75441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    }
75541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
75641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
75741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
75841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (hasWarning) {
75941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final long alertBytes = Math.max(0, policy.warningBytes - total);
76041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                for (String iface : ifaces) {
76141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    removeInterfaceAlert(iface);
76241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    if (alertBytes > 0) {
76341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        setInterfaceAlert(iface, alertBytes);
76441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    }
765fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey                }
76622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            }
76722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        }
768fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey
769b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // remove quota on any trailing interfaces
770b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        for (String iface : mMeteredIfaces) {
771b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            if (!newMeteredIfaces.contains(iface)) {
772b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                removeInterfaceQuota(iface);
77350fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            }
77450fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma        }
775b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        mMeteredIfaces = newMeteredIfaces;
776b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
777b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
778b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
77950fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma    }
78050fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma
78122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    /**
78222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey     * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
78322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey     * have at least a default mobile policy defined.
78422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey     */
78522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private void ensureActiveMobilePolicyLocked() {
78622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
78722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        final String subscriberId = getActiveSubscriberId();
7881b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        final NetworkIdentity probeIdent = new NetworkIdentity(
7895dc0c26cffbbc62ff84f9f4c8a451e68e2c05d2dJeff Sharkey                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false);
79022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
79122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        // examine to see if any policy is defined for active mobile
79222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        boolean mobileDefined = false;
79341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        for (NetworkPolicy policy : mNetworkPolicy.values()) {
7941b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            if (policy.template.matches(probeIdent)) {
79522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey                mobileDefined = true;
79621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
79722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        }
79821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
79922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (!mobileDefined) {
80022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            Slog.i(TAG, "no policy for active mobile network; generating default policy");
80121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
80202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            // build default mobile policy, and assume usage cycle starts today
80302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            final long warningBytes = mContext.getResources().getInteger(
80402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    com.android.internal.R.integer.config_networkPolicyDefaultWarning)
80502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                    * MB_IN_BYTES;
80622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
80722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            final Time time = new Time(Time.TIMEZONE_UTC);
80822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            time.setToNow();
80922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            final int cycleDay = time.monthDay;
81022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
8114e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
81241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkPolicy.put(template, new NetworkPolicy(
81341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    template, cycleDay, warningBytes, LIMIT_DISABLED, SNOOZE_NEVER));
814fcc79771f092f34505b1accb80365cbcaa379667Jeff Sharkey            writePolicyLocked();
81521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
81621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
81721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
81821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void readPolicyLocked() {
81922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (LOGV) Slog.v(TAG, "readPolicyLocked()");
82021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
82121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // clear any existing policy and read from disk
82222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        mNetworkPolicy.clear();
82321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mUidPolicy.clear();
82421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
82521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        FileInputStream fis = null;
82621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
82721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            fis = mPolicyFile.openRead();
82821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final XmlPullParser in = Xml.newPullParser();
82921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            in.setInput(fis, null);
83021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
83121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            int type;
83241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            int version = VERSION_INIT;
83321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            while ((type = in.next()) != END_DOCUMENT) {
83421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final String tag = in.getName();
83521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                if (type == START_TAG) {
83621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    if (TAG_POLICY_LIST.equals(tag)) {
83721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        version = readIntAttribute(in, ATTR_VERSION);
8384664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                        if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) {
8394664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                            mRestrictBackground = readBooleanAttribute(
8404664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                                    in, ATTR_RESTRICT_BACKGROUND);
8414664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                        } else {
8424664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                            try {
8434664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                                mRestrictBackground = !mConnManager.getBackgroundDataSetting();
8444664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                            } catch (RemoteException e) {
8454664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                                mRestrictBackground = false;
8464664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                            }
8474664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                        }
84821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
84921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    } else if (TAG_NETWORK_POLICY.equals(tag)) {
85021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
85121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
85221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
85321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
85421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
85541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        final long lastSnooze;
85641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        if (version >= VERSION_ADDED_SNOOZE) {
85741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                            lastSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
85841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        } else {
85941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                            lastSnooze = SNOOZE_NEVER;
86041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        }
86121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
8621b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                        final NetworkTemplate template = new NetworkTemplate(
8631b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                                networkTemplate, subscriberId);
86441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        mNetworkPolicy.put(template, new NetworkPolicy(
86541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                                template, cycleDay, warningBytes, limitBytes, lastSnooze));
86621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
86721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    } else if (TAG_UID_POLICY.equals(tag)) {
86821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int uid = readIntAttribute(in, ATTR_UID);
86921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int policy = readIntAttribute(in, ATTR_POLICY);
87021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
871497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        if (isUidValidForPolicy(mContext, uid)) {
872497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                            setUidPolicyUnchecked(uid, policy, false);
873497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        } else {
874497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                            Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
875497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        }
87621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    }
87721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
87821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
87921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
88021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (FileNotFoundException e) {
88121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // missing policy is okay, probably first boot
88221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (IOException e) {
88321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            Slog.e(TAG, "problem reading network stats", e);
88421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (XmlPullParserException e) {
88521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            Slog.e(TAG, "problem reading network stats", e);
88621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } finally {
88721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            IoUtils.closeQuietly(fis);
88821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
88921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
89021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
89121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void writePolicyLocked() {
89222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (LOGV) Slog.v(TAG, "writePolicyLocked()");
89321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
89421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        FileOutputStream fos = null;
89521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
89621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            fos = mPolicyFile.startWrite();
89721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
89821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            XmlSerializer out = new FastXmlSerializer();
89921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.setOutput(fos, "utf-8");
90021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.startDocument(null, true);
90121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
90221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.startTag(null, TAG_POLICY_LIST);
9034664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_RESTRICT_BACKGROUND);
9044664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
90521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
90621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // write all known network policies
90741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            for (NetworkPolicy policy : mNetworkPolicy.values()) {
9081b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                final NetworkTemplate template = policy.template;
9091b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
91021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.startTag(null, TAG_NETWORK_POLICY);
9111b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
9121b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                final String subscriberId = template.getSubscriberId();
9131b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                if (subscriberId != null) {
9141b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
91521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
91621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
91721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
91821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
91941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                writeLongAttribute(out, ATTR_LAST_SNOOZE, policy.lastSnooze);
92021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.endTag(null, TAG_NETWORK_POLICY);
92121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
92221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
92321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // write all known uid policies
92421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            for (int i = 0; i < mUidPolicy.size(); i++) {
92521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final int uid = mUidPolicy.keyAt(i);
92621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final int policy = mUidPolicy.valueAt(i);
92721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
928497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                // skip writing empty policies
929497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                if (policy == POLICY_NONE) continue;
930497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
93121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.startTag(null, TAG_UID_POLICY);
93221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeIntAttribute(out, ATTR_UID, uid);
93321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeIntAttribute(out, ATTR_POLICY, policy);
93421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.endTag(null, TAG_UID_POLICY);
93521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
93621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
93721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.endTag(null, TAG_POLICY_LIST);
93821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.endDocument();
93921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
94021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            mPolicyFile.finishWrite(fos);
94121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (IOException e) {
94221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (fos != null) {
94321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                mPolicyFile.failWrite(fos);
94421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
94521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
94621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
94721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
948d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    @Override
949d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    public void setUidPolicy(int uid, int policy) {
95021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
951a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
952497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        if (!isUidValidForPolicy(mContext, uid)) {
953497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
954497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
955497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
956497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        setUidPolicyUnchecked(uid, policy, true);
957497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
958497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
959497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private void setUidPolicyUnchecked(int uid, int policy, boolean persist) {
960c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        final int oldPolicy;
961a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
962c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            oldPolicy = getUidPolicy(uid);
963a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            mUidPolicy.put(uid, policy);
964c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
96521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // uid policy changed, recompute rules and persist policy.
96621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            updateRulesForUidLocked(uid);
967497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            if (persist) {
968497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                writePolicyLocked();
969497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
97021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
971d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
972d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
973d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    @Override
974d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    public int getUidPolicy(int uid) {
97521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
97621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
977a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
978a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            return mUidPolicy.get(uid, POLICY_NONE);
979a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
980d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
981d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
982c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    @Override
983c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    public void registerListener(INetworkPolicyListener listener) {
9841a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey        // TODO: create permission for observing network policy
9851a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
9861a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey
987c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mListeners.register(listener);
988c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
9894414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey        // TODO: consider dispatching existing rules to new listeners
990c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
991c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
992c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    @Override
993c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    public void unregisterListener(INetworkPolicyListener listener) {
9941a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey        // TODO: create permission for observing network policy
9951a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
9961a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey
997c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mListeners.unregister(listener);
998c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
999c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
10001b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    @Override
100122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    public void setNetworkPolicies(NetworkPolicy[] policies) {
100221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
100321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
100421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mRulesLock) {
100522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            mNetworkPolicy.clear();
100622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            for (NetworkPolicy policy : policies) {
100741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                mNetworkPolicy.put(policy.template, policy);
100822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            }
100921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
101002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            updateNetworkRulesLocked();
1011497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            updateNotificationsLocked();
101221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            writePolicyLocked();
101321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
101421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
101521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
101621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
101722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    public NetworkPolicy[] getNetworkPolicies() {
101821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
101922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
102021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
102121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mRulesLock) {
102241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]);
102341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
102441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
102541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
102641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    @Override
102741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public void snoozePolicy(NetworkTemplate template) {
102841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
102941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
103041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // try refreshing time source when stale
103141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
103241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mTime.forceRefresh();
103341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
103441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
103541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
103641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                : System.currentTimeMillis();
103741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
103841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        synchronized (mRulesLock) {
103941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            // find and snooze local policy that matches
104041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final NetworkPolicy policy = mNetworkPolicy.get(template);
104141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (policy == null) {
104241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                throw new IllegalArgumentException("unable to find policy for " + template);
104341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
104441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
104541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            policy.lastSnooze = currentTime;
104641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
104741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            updateNetworkRulesLocked();
104841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            updateNotificationsLocked();
104941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            writePolicyLocked();
105021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
105121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
105221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
105321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
10544664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    public void setRestrictBackground(boolean restrictBackground) {
10554664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
10564664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey
10574664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        synchronized (mRulesLock) {
10584664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            mRestrictBackground = restrictBackground;
10594664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            updateRulesForRestrictBackgroundLocked();
1060f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            writePolicyLocked();
10614664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        }
10624664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    }
10634664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey
10644664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    @Override
10654664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    public boolean getRestrictBackground() {
10664664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
10674664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey
10684664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        synchronized (mRulesLock) {
10694664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            return mRestrictBackground;
10704664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        }
10714664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    }
10724664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey
1073f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) {
1074f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        for (NetworkPolicy policy : mNetworkPolicy.values()) {
1075f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            if (policy.template.matches(ident)) {
1076f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey                return policy;
1077f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            }
1078f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        }
1079f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        return null;
1080f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    }
1081f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1082f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    @Override
1083f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) {
1084f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
1085f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1086f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        // only returns usage summary, so we don't require caller to have
1087f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        // READ_NETWORK_USAGE_HISTORY.
1088f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final long token = Binder.clearCallingIdentity();
1089f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        try {
1090f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            return getNetworkQuotaInfoUnchecked(state);
1091f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        } finally {
1092f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            Binder.restoreCallingIdentity(token);
1093f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        }
1094f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    }
1095f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1096f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) {
1097f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
1098f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1099f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final NetworkPolicy policy;
1100f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        synchronized (mRulesLock) {
1101f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            policy = findPolicyForNetworkLocked(ident);
1102f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        }
1103f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1104f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        if (policy == null) {
1105f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            // missing policy means we can't derive useful quota info
1106f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            return null;
1107f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        }
1108f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1109f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
1110f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey                : System.currentTimeMillis();
1111f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1112f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final long start = computeLastCycleBoundary(currentTime, policy);
1113f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final long end = currentTime;
1114f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1115f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        // find total bytes used under policy
1116f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        long totalBytes = 0;
1117f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        try {
1118f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
1119f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey                    policy.template, start, end);
1120f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            final NetworkStats.Entry entry = stats.getValues(0, null);
1121f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            totalBytes = entry.rxBytes + entry.txBytes;
1122f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        } catch (RemoteException e) {
1123f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            Slog.w(TAG, "problem reading summary for template " + policy.template);
1124f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        }
1125f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1126f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        // report soft and hard limits under policy
1127f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes
1128f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey                : NetworkQuotaInfo.NO_LIMIT;
1129f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes
1130f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey                : NetworkQuotaInfo.NO_LIMIT;
1131f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1132f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes);
1133f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    }
1134f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
11354664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    @Override
11361b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
113775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
11381b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
113941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        final HashSet<String> argSet = new HashSet<String>();
114041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        for (String arg : args) {
114141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            argSet.add(arg);
114241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
114341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
11441b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        synchronized (mRulesLock) {
114541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (argSet.contains("unsnooze")) {
114641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                for (NetworkPolicy policy : mNetworkPolicy.values()) {
114741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    policy.lastSnooze = SNOOZE_NEVER;
114841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
114941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                writePolicyLocked();
115041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                fout.println("Wiped snooze timestamps");
115141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                return;
115241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
115341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
11544664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            fout.print("Restrict background: "); fout.println(mRestrictBackground);
115521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            fout.println("Network policies:");
115641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            for (NetworkPolicy policy : mNetworkPolicy.values()) {
115722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey                fout.print("  "); fout.println(policy.toString());
115821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
115921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
11601b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            fout.println("Policy status for known UIDs:");
11611b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
11621b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            final SparseBooleanArray knownUids = new SparseBooleanArray();
11631b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidPolicy, knownUids);
11641b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidForeground, knownUids);
11651b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidRules, knownUids);
11661b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
11671b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            final int size = knownUids.size();
11681b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            for (int i = 0; i < size; i++) {
11691b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int uid = knownUids.keyAt(i);
11701b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print("  UID=");
11711b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(uid);
11721b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
11731b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" policy=");
11741b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int policyIndex = mUidPolicy.indexOfKey(uid);
11751b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (policyIndex < 0) {
11761b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
11771b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
11781b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpPolicy(fout, mUidPolicy.valueAt(policyIndex));
11791b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
11801b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
11811b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" foreground=");
11821b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int foregroundIndex = mUidPidForeground.indexOfKey(uid);
11831b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (foregroundIndex < 0) {
11841b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
11851b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
11861b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex));
11871b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
11881b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
11891b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" rules=");
11901b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int rulesIndex = mUidRules.indexOfKey(uid);
11911b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (rulesIndex < 0) {
11921b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
11931b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
11941b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpRules(fout, mUidRules.valueAt(rulesIndex));
11951b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
11961b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
11971b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.println();
11981b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            }
11991b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
12001b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
12019599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey
12029599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey    @Override
12039599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey    public boolean isUidForeground(int uid) {
1204497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1205497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
12069599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        synchronized (mRulesLock) {
12079599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey            // only really in foreground when screen is also on
12089599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey            return mUidForeground.get(uid, false) && mScreenOn;
12099599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        }
1210c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
1211c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
1212d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    /**
1213d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey     * Foreground for PID changed; recompute foreground at UID level. If
121421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * changed, will trigger {@link #updateRulesForUidLocked(int)}.
1215d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey     */
121621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void computeUidForegroundLocked(int uid) {
1217d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
1218d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1219d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        // current pid is dropping foreground; examine other pids
1220d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        boolean uidForeground = false;
1221d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final int size = pidForeground.size();
1222d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        for (int i = 0; i < size; i++) {
1223d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            if (pidForeground.valueAt(i)) {
1224d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey                uidForeground = true;
1225d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey                break;
1226d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            }
1227d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
1228d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1229d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final boolean oldUidForeground = mUidForeground.get(uid, false);
1230d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        if (oldUidForeground != uidForeground) {
1231d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            // foreground changed, push updated rules
1232d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            mUidForeground.put(uid, uidForeground);
123321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            updateRulesForUidLocked(uid);
1234a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
1235a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
1236a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
1237a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private void updateScreenOn() {
1238a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
1239a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            try {
1240a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                mScreenOn = mPowerManager.isScreenOn();
1241a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            } catch (RemoteException e) {
1242a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
124321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            updateRulesForScreenLocked();
1244d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
1245d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
1246d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1247a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    /**
1248a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey     * Update rules that might be changed by {@link #mScreenOn} value.
1249a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey     */
125021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void updateRulesForScreenLocked() {
1251a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // only update rules for anyone with foreground activities
1252a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        final int size = mUidForeground.size();
1253a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        for (int i = 0; i < size; i++) {
1254a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            if (mUidForeground.valueAt(i)) {
1255a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                final int uid = mUidForeground.keyAt(i);
125621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                updateRulesForUidLocked(uid);
1257a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
1258a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
1259a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
1260a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
1261b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    /**
12624664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey     * Update rules that might be changed by {@link #mRestrictBackground} value.
1263b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey     */
12644664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    private void updateRulesForRestrictBackgroundLocked() {
1265b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // update rules for all installed applications
1266b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        final PackageManager pm = mContext.getPackageManager();
1267b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
1268b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        for (ApplicationInfo app : apps) {
1269b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            updateRulesForUidLocked(app.uid);
1270b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1271b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1272b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // and catch system UIDs
1273b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // TODO: keep in sync with android_filesystem_config.h
1274b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        for (int uid = 1000; uid <= 1025; uid++) {
1275b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            updateRulesForUidLocked(uid);
1276b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1277b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        for (int uid = 2000; uid <= 2002; uid++) {
1278b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            updateRulesForUidLocked(uid);
1279b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1280b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        for (int uid = 3000; uid <= 3007; uid++) {
1281b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            updateRulesForUidLocked(uid);
1282b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1283b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        for (int uid = 9998; uid <= 9999; uid++) {
1284b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            updateRulesForUidLocked(uid);
1285b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1286b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
1287b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
128821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void updateRulesForUidLocked(int uid) {
1289d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final int uidPolicy = getUidPolicy(uid);
12909599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        final boolean uidForeground = isUidForeground(uid);
1291d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1292c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // derive active rules based on policy and active state
1293c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        int uidRules = RULE_ALLOW_ALL;
1294fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey        if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
1295fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey            // uid in background, and policy says to block metered data
1296fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey            uidRules = RULE_REJECT_METERED;
1297d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
12984664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        if (!uidForeground && mRestrictBackground) {
1299b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            // uid in background, and global background disabled
1300b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            uidRules = RULE_REJECT_METERED;
1301b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1302d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1303c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // TODO: only dispatch when rules actually change
1304c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
1305350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        if (uidRules == RULE_ALLOW_ALL) {
1306350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            mUidRules.delete(uid);
1307350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        } else {
1308350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            mUidRules.put(uid, uidRules);
1309350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        }
1310c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
1311fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey        final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0;
131250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma        setUidNetworkRules(uid, rejectMetered);
1313497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
1314c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // dispatch changed rule to existing listeners
13154414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey        mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
13164414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    }
13174414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey
13184414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    private Handler.Callback mHandlerCallback = new Handler.Callback() {
13194414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey        /** {@inheritDoc} */
13204414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey        public boolean handleMessage(Message msg) {
13214414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey            switch (msg.what) {
13224414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                case MSG_RULES_CHANGED: {
13234414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final int uid = msg.arg1;
13244414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final int uidRules = msg.arg2;
13254414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final int length = mListeners.beginBroadcast();
13264414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    for (int i = 0; i < length; i++) {
13274414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
13284414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        if (listener != null) {
13294414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            try {
13304414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                                listener.onUidRulesChanged(uid, uidRules);
13314414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            } catch (RemoteException e) {
13324414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            }
13334414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        }
13344414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    }
13354414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    mListeners.finishBroadcast();
13364414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    return true;
13374414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                }
13384414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                case MSG_METERED_IFACES_CHANGED: {
13394414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final String[] meteredIfaces = (String[]) msg.obj;
13404414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final int length = mListeners.beginBroadcast();
13414414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    for (int i = 0; i < length; i++) {
13424414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
13434414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        if (listener != null) {
13444414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            try {
13454414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                                listener.onMeteredIfacesChanged(meteredIfaces);
13464414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            } catch (RemoteException e) {
13474414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            }
13484414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        }
13494414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    }
13504414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    mListeners.finishBroadcast();
13514414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    return true;
13524414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                }
13534414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                default: {
13544414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    return false;
1355af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey                }
1356af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey            }
1357af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey        }
13584414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    };
135922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
136041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void setInterfaceQuota(String iface, long quotaBytes) {
1361b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        try {
136241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.setInterfaceQuota(iface, quotaBytes);
1363b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (IllegalStateException e) {
1364b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            Slog.e(TAG, "problem setting interface quota", e);
1365b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (RemoteException e) {
1366b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            Slog.e(TAG, "problem setting interface quota", e);
1367b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1368b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
1369b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1370b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    private void removeInterfaceQuota(String iface) {
1371b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        try {
137241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.removeInterfaceQuota(iface);
1373b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (IllegalStateException e) {
1374b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            Slog.e(TAG, "problem removing interface quota", e);
1375b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (RemoteException e) {
1376b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            Slog.e(TAG, "problem removing interface quota", e);
1377b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1378b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
1379b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
138041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void setInterfaceAlert(String iface, long alertBytes) {
138141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        try {
138241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.setInterfaceAlert(iface, alertBytes);
138341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (IllegalStateException e) {
138441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            Slog.e(TAG, "problem setting interface alert", e);
138541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (RemoteException e) {
138641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            Slog.e(TAG, "problem setting interface alert", e);
138741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
138841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
138941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
139041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void removeInterfaceAlert(String iface) {
139141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        try {
139241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.removeInterfaceAlert(iface);
139341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (IllegalStateException e) {
139441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            Slog.e(TAG, "problem removing interface alert", e);
139541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (RemoteException e) {
139641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            Slog.e(TAG, "problem removing interface alert", e);
139741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
139841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
139941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
1400b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
1401b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        try {
140241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
1403b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (IllegalStateException e) {
1404b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            Slog.e(TAG, "problem setting uid rules", e);
1405b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (RemoteException e) {
1406b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            Slog.e(TAG, "problem setting uid rules", e);
1407b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1408b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
1409b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
141022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private String getActiveSubscriberId() {
141122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService(
141222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey                Context.TELEPHONY_SERVICE);
141322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        return telephony.getSubscriberId();
141422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    }
141522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
141641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
141741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        final Intent intent = new Intent();
141841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.setComponent(new ComponentName(
141941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity"));
142041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
142141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
142241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        return intent;
142341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
142441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
142541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static Intent buildViewDataUsageIntent(NetworkTemplate template) {
142641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        final Intent intent = new Intent();
142741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.setComponent(new ComponentName(
142841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
142941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
143041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
143141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        return intent;
143241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
143341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
14341b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
14351b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = source.size();
14361b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
14371b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            target.put(source.keyAt(i), true);
14381b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
14391b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
14401b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
14411b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) {
14421b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = source.size();
14431b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
14441b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            target.put(source.keyAt(i), true);
14451b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
14461b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
14471b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
14481b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) {
14491b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        fout.print("[");
14501b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = value.size();
14511b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
14521b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            fout.print(value.keyAt(i) + "=" + value.valueAt(i));
14531b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            if (i < size - 1) fout.print(",");
14541b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
14551b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        fout.print("]");
14561b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
145721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
14584664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    public static class XmlUtils {
14594664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        public static int readIntAttribute(XmlPullParser in, String name) throws IOException {
14604664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            final String value = in.getAttributeValue(null, name);
14614664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            try {
14624664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                return Integer.parseInt(value);
14634664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            } catch (NumberFormatException e) {
14644664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
14654664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            }
146621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
146721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
14684664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        public static void writeIntAttribute(XmlSerializer out, String name, int value)
14694664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                throws IOException {
14704664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            out.attribute(null, name, Integer.toString(value));
147121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
147221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
14734664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        public static long readLongAttribute(XmlPullParser in, String name) throws IOException {
14744664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            final String value = in.getAttributeValue(null, name);
14754664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            try {
14764664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                return Long.parseLong(value);
14774664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            } catch (NumberFormatException e) {
14784664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
14794664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            }
14804664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        }
148121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
14824664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        public static void writeLongAttribute(XmlSerializer out, String name, long value)
14834664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                throws IOException {
14844664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            out.attribute(null, name, Long.toString(value));
14854664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        }
148621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
14874664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        public static boolean readBooleanAttribute(XmlPullParser in, String name) {
14884664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            final String value = in.getAttributeValue(null, name);
14894664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            return Boolean.parseBoolean(value);
14904664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        }
14914664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey
14924664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value)
14934664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                throws IOException {
14944664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            out.attribute(null, name, Boolean.toString(value));
14954664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        }
14964664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    }
1497d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey}
1498