NetworkPolicyManagerService.java revision 4414cea13908b8230640f84ef39603d68ff9c377
1d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/* 2d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project 3d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * 4d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * you may not use this file except in compliance with the License. 6d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * You may obtain a copy of the License at 7d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * 8d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * 10d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 11d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * See the License for the specific language governing permissions and 14d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * limitations under the License. 15d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */ 16d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 17d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeypackage com.android.server.net; 18d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.CONNECTIVITY_INTERNAL; 201b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.Manifest.permission.DUMP; 21d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport static android.Manifest.permission.MANAGE_APP_TOKENS; 2221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.MANAGE_NETWORK_POLICY; 23497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; 2422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport static android.Manifest.permission.READ_PHONE_STATE; 25b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.ACTION_UID_REMOVED; 26b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.EXTRA_UID; 2721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.net.ConnectivityManager.CONNECTIVITY_ACTION; 281b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_MOBILE; 2922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport static android.net.NetworkPolicy.LIMIT_DISABLED; 30497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static android.net.NetworkPolicy.WARNING_DISABLED; 3114711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkeyimport static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_LIMIT; 3214711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkeyimport static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_WARNING; 3314711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkeyimport static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE; 34d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_NONE; 35fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; 36c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; 37fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport static android.net.NetworkPolicyManager.RULE_REJECT_METERED; 38cd2ca4038a027315832c38c68be5076000bc4b53Jeff Sharkeyimport static android.net.NetworkPolicyManager.computeLastCycleBoundary; 391b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.net.NetworkPolicyManager.dumpPolicy; 401b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.net.NetworkPolicyManager.dumpRules; 41497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static android.net.NetworkPolicyManager.isUidValidForPolicy; 421b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER; 431b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_4G; 441b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_ALL; 4521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.text.format.DateUtils.DAY_IN_MILLIS; 4621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull; 47497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED; 4821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 4921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.START_TAG; 50d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 51a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IActivityManager; 52497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.INotificationManager; 53a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IProcessObserver; 54497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.Notification; 55497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.PendingIntent; 56a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.BroadcastReceiver; 57d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.content.Context; 58a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.Intent; 59a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.IntentFilter; 60497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.content.res.Resources; 61c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.ConnectivityManager; 6221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.IConnectivityManager; 63c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.INetworkPolicyListener; 64d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.net.INetworkPolicyManager; 6575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.INetworkStatsService; 661b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkIdentity; 6721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkPolicy; 6821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkState; 6921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkStats; 701b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkTemplate; 7121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Environment; 7221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Handler; 7321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.HandlerThread; 74a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.IPowerManager; 754414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkeyimport android.os.Message; 76c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.os.RemoteCallbackList; 77a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.RemoteException; 7822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport android.telephony.TelephonyManager; 79497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.text.format.Formatter; 8022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport android.text.format.Time; 8121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.NtpTrustedTime; 82a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.util.Slog; 83d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseArray; 84d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseBooleanArray; 85d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseIntArray; 8621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.TrustedTime; 8721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.Xml; 88d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 89497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport com.android.internal.R; 9021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.android.internal.os.AtomicFile; 9121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.android.internal.util.FastXmlSerializer; 9221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.google.android.collect.Lists; 9321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.google.android.collect.Maps; 94fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport com.google.android.collect.Sets; 9521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 9621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlPullParser; 9721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlPullParserException; 9821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlSerializer; 9921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 10021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.File; 1011b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.FileDescriptor; 10221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileInputStream; 10321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileNotFoundException; 10421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileOutputStream; 10521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.IOException; 1061b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.PrintWriter; 10721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.net.ProtocolException; 10821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.ArrayList; 10921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.Arrays; 11021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.HashMap; 111fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport java.util.HashSet; 11221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 11321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport libcore.io.IoUtils; 1141b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 115d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/** 116d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Service that maintains low-level network policy rules and collects usage 117d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * statistics to drive those rules. 118c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * <p> 119c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * Derives active rules by combining a given policy with other system status, 120c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * and delivers to listeners, such as {@link ConnectivityManager}, for 121c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * enforcement. 122d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */ 123d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeypublic class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 124d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey private static final String TAG = "NetworkPolicy"; 125d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey private static final boolean LOGD = true; 12622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private static final boolean LOGV = false; 127d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 12821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final int VERSION_CURRENT = 1; 12921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 13022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private static final long KB_IN_BYTES = 1024; 13122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private static final long MB_IN_BYTES = KB_IN_BYTES * 1024; 13222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private static final long GB_IN_BYTES = MB_IN_BYTES * 1024; 13322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 134497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private static final int TYPE_WARNING = 0x1; 135497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private static final int TYPE_LIMIT = 0x2; 136497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 13721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String TAG_POLICY_LIST = "policy-list"; 13821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String TAG_NETWORK_POLICY = "network-policy"; 13921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String TAG_UID_POLICY = "uid-policy"; 14021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 14121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_VERSION = "version"; 14221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate"; 14321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_SUBSCRIBER_ID = "subscriberId"; 14421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_CYCLE_DAY = "cycleDay"; 14521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_WARNING_BYTES = "warningBytes"; 14621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_LIMIT_BYTES = "limitBytes"; 14721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_UID = "uid"; 14821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_POLICY = "policy"; 14921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 15021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS; 15121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 1524414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey private static final int MSG_RULES_CHANGED = 0x1; 1534414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey private static final int MSG_METERED_IFACES_CHANGED = 0x2; 1544414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 15575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final Context mContext; 15675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final IActivityManager mActivityManager; 15775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final IPowerManager mPowerManager; 15875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final INetworkStatsService mNetworkStats; 15921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private final TrustedTime mTime; 16021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 16121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private IConnectivityManager mConnManager; 162497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private INotificationManager mNotifManager; 163a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 16475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final Object mRulesLock = new Object(); 165a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 166c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey private boolean mScreenOn; 167d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 16822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey /** Current policy for network templates. */ 16922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private ArrayList<NetworkPolicy> mNetworkPolicy = Lists.newArrayList(); 17022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 17122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey /** Current policy for each UID. */ 172a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private SparseIntArray mUidPolicy = new SparseIntArray(); 173c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey /** Current derived network rules for each UID. */ 174c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey private SparseIntArray mUidRules = new SparseIntArray(); 175d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 176fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey /** Set of ifaces that are metered. */ 177fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey private HashSet<String> mMeteredIfaces = Sets.newHashSet(); 178fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey 179d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey /** Foreground at both UID and PID granularity. */ 180a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private SparseBooleanArray mUidForeground = new SparseBooleanArray(); 181a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray< 182a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey SparseBooleanArray>(); 183d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 184c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList< 185c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey INetworkPolicyListener>(); 186c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 18721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private final HandlerThread mHandlerThread; 18821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private final Handler mHandler; 18921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 19021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private final AtomicFile mPolicyFile; 191d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 192c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // TODO: keep whitelist of system-critical services that should never have 193c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // rules enforced, such as system, phone, and radio UIDs. 194c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 19575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 19675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey IPowerManager powerManager, INetworkStatsService networkStats) { 19721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // TODO: move to using cached NtpTrustedTime 19821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey this(context, activityManager, powerManager, networkStats, new NtpTrustedTime(), 19921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey getSystemDir()); 20021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 20121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 20221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static File getSystemDir() { 20321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey return new File(Environment.getDataDirectory(), "system"); 20421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 20521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 20621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 20721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey IPowerManager powerManager, INetworkStatsService networkStats, TrustedTime time, 20821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey File systemDir) { 209a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mContext = checkNotNull(context, "missing context"); 210a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mActivityManager = checkNotNull(activityManager, "missing activityManager"); 211a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mPowerManager = checkNotNull(powerManager, "missing powerManager"); 21275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey mNetworkStats = checkNotNull(networkStats, "missing networkStats"); 21321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mTime = checkNotNull(time, "missing TrustedTime"); 21421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 21521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mHandlerThread = new HandlerThread(TAG); 21621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mHandlerThread.start(); 2174414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback); 21821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 21921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); 22021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 22121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 22221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey public void bindConnectivityManager(IConnectivityManager connManager) { 22321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mConnManager = checkNotNull(connManager, "missing IConnectivityManager"); 224a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 225d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 226497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey public void bindNotificationManager(INotificationManager notifManager) { 227497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mNotifManager = checkNotNull(notifManager, "missing INotificationManager"); 228497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 229497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 230a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey public void systemReady() { 23121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey synchronized (mRulesLock) { 23221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // read policy from disk 23321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey readPolicyLocked(); 234497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey updateNotificationsLocked(); 23521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 236d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 237a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey updateScreenOn(); 238d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 239a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey try { 240a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mActivityManager.registerProcessObserver(mProcessObserver); 241a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } catch (RemoteException e) { 242a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // ouch, no foregroundActivities updates means some processes may 243a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // never get network access. 244a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey Slog.e(TAG, "unable to register IProcessObserver", e); 245a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 246d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 247a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // TODO: traverse existing processes to know foreground state, or have 248a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // activitymanager dispatch current state when new observer attached. 249d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 250a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey final IntentFilter screenFilter = new IntentFilter(); 251a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey screenFilter.addAction(Intent.ACTION_SCREEN_ON); 252a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey screenFilter.addAction(Intent.ACTION_SCREEN_OFF); 253a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mContext.registerReceiver(mScreenReceiver, screenFilter); 254d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 25521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // watch for network interfaces to be claimed 256b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION); 257b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); 258b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey 259b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey // listen for uid removal to clean policy 260b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED); 261b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler); 26221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 263497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // listen for warning polling events; currently dispatched by 264497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED); 265497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mContext.registerReceiver( 266497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler); 267497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 268a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 269d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 270a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private IProcessObserver mProcessObserver = new IProcessObserver.Stub() { 271a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey @Override 272a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) { 273a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // only someone like AMS should only be calling us 27475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG); 275a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 276a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 277a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // because a uid can have multiple pids running inside, we need to 278a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // remember all pid states and summarize foreground at uid level. 279a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 280a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // record foreground for this specific pid 281a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 282a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey if (pidForeground == null) { 283a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey pidForeground = new SparseBooleanArray(2); 284a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mUidPidForeground.put(uid, pidForeground); 285a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 286a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey pidForeground.put(pid, foregroundActivities); 28721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey computeUidForegroundLocked(uid); 288a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 289d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 290d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 291a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey @Override 292a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey public void onProcessDied(int pid, int uid) { 293a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // only someone like AMS should only be calling us 29475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG); 295a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 296a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 297a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // clear records and recompute, when they exist 298a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 299a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey if (pidForeground != null) { 300a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey pidForeground.delete(pid); 30121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey computeUidForegroundLocked(uid); 302a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 303a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 304a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 305a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey }; 306a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 307a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { 308a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey @Override 309a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey public void onReceive(Context context, Intent intent) { 310a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 311a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // screen-related broadcasts are protected by system, no need 312a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // for permissions check. 313a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey updateScreenOn(); 314a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 315a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 316a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey }; 317d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 318b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() { 319b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey @Override 320b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey public void onReceive(Context context, Intent intent) { 321b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey // on background handler thread, and UID_REMOVED is protected 322b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey // broadcast. 323b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey final int uid = intent.getIntExtra(EXTRA_UID, 0); 324b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey synchronized (mRulesLock) { 325b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey // remove any policy and update rules to clean up 326b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey mUidPolicy.delete(uid); 327b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey updateRulesForUidLocked(uid); 328b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey writePolicyLocked(); 329b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey } 330b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey } 331b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey }; 332b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey 33321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey /** 334497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Receiver that watches for {@link INetworkStatsService} updates, which we 335497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * use to check against {@link NetworkPolicy#warningBytes}. 336497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 337497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() { 338497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey @Override 339497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey public void onReceive(Context context, Intent intent) { 340497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // on background handler thread, and verified 341497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // READ_NETWORK_USAGE_HISTORY permission above. 342497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 343497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey synchronized (mRulesLock) { 344497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey updateNotificationsLocked(); 345497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 346497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 347497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey }; 348497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 349497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 350497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Check {@link NetworkPolicy} against current {@link INetworkStatsService} 351497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * to show visible notifications as needed. 352497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 353497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private void updateNotificationsLocked() { 354497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (LOGV) Slog.v(TAG, "updateNotificationsLocked()"); 355497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 356497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // try refreshing time source when stale 357497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) { 358497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mTime.forceRefresh(); 359497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 360497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 361497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() 362497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey : System.currentTimeMillis(); 363497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 364497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // TODO: when switching to kernel notifications, compute next future 365497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // cycle boundary to recompute notifications. 366497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 367497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // examine stats for each policy defined 368497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy) { 369497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final long start = computeLastCycleBoundary(currentTime, policy); 370497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final long end = currentTime; 371497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 372497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final long total; 373497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey try { 374497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final NetworkStats stats = mNetworkStats.getSummaryForNetwork( 3751b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey policy.template, start, end); 376497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey total = stats.rx[0] + stats.tx[0]; 377497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } catch (RemoteException e) { 3781b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey Slog.w(TAG, "problem reading summary for template " + policy.template); 379497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey continue; 380497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 381497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 382497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (policy.limitBytes != LIMIT_DISABLED && total >= policy.limitBytes) { 383497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey cancelNotification(policy, TYPE_WARNING); 384497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey enqueueNotification(policy, TYPE_LIMIT); 385497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } else { 386497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey cancelNotification(policy, TYPE_LIMIT); 387497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 388497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (policy.warningBytes != WARNING_DISABLED && total >= policy.warningBytes) { 389497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey enqueueNotification(policy, TYPE_WARNING); 390497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } else { 391497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey cancelNotification(policy, TYPE_WARNING); 392497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 393497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 394497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 395497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 396497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 397497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 398497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Build unique tag that identifies an active {@link NetworkPolicy} 399497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * notification of a specific type, like {@link #TYPE_LIMIT}. 400497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 401497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private String buildNotificationTag(NetworkPolicy policy, int type) { 4021b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey return TAG + ":" + policy.template.hashCode() + ":" + type; 403497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 404497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 405497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 406497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Show notification for combined {@link NetworkPolicy} and specific type, 407497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * like {@link #TYPE_LIMIT}. Okay to call multiple times. 408497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 409497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private void enqueueNotification(NetworkPolicy policy, int type) { 410497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String tag = buildNotificationTag(policy, type); 411497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final Notification.Builder builder = new Notification.Builder(mContext); 412497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setOnlyAlertOnce(true); 413497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setOngoing(true); 414497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 415497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final Resources res = mContext.getResources(); 416497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey switch (type) { 417497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey case TYPE_WARNING: { 418497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String title = res.getString(R.string.data_usage_warning_title); 419497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String body = res.getString(R.string.data_usage_warning_body, 420497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey Formatter.formatFileSize(mContext, policy.warningBytes)); 421497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 422497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setSmallIcon(R.drawable.ic_menu_info_details); 423497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setTicker(title); 424497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setContentTitle(title); 425497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setContentText(body); 42614711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey 42714711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey final Intent intent = new Intent(ACTION_DATA_USAGE_WARNING); 42814711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey intent.addCategory(Intent.CATEGORY_DEFAULT); 4291b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.template.getMatchRule()); 43014711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey builder.setContentIntent(PendingIntent.getActivity( 43114711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 432497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 433497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 434497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey case TYPE_LIMIT: { 435497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String title; 436497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String body = res.getString(R.string.data_usage_limit_body); 4371b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey switch (policy.template.getMatchRule()) { 4381b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey case MATCH_MOBILE_3G_LOWER: 439497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey title = res.getString(R.string.data_usage_3g_limit_title); 440497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 4411b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey case MATCH_MOBILE_4G: 442497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey title = res.getString(R.string.data_usage_4g_limit_title); 443497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 444497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey default: 445497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey title = res.getString(R.string.data_usage_mobile_limit_title); 446497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 447497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 448497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 449497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setSmallIcon(com.android.internal.R.drawable.ic_menu_block); 450497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setTicker(title); 451497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setContentTitle(title); 452497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setContentText(body); 45314711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey 45414711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey final Intent intent = new Intent(ACTION_DATA_USAGE_LIMIT); 45514711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey intent.addCategory(Intent.CATEGORY_DEFAULT); 4561b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.template.getMatchRule()); 45714711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey builder.setContentIntent(PendingIntent.getActivity( 45814711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 459497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 460497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 461497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 462497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 463497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // TODO: move to NotificationManager once we can mock it 464497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey try { 465497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String packageName = mContext.getPackageName(); 466497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final int[] idReceived = new int[1]; 467497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mNotifManager.enqueueNotificationWithTag( 468497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey packageName, tag, 0x0, builder.getNotification(), idReceived); 469497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } catch (RemoteException e) { 470497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey Slog.w(TAG, "problem during enqueueNotification: " + e); 471497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 472497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 473497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 474497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 475497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Cancel any notification for combined {@link NetworkPolicy} and specific 476497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * type, like {@link #TYPE_LIMIT}. 477497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 478497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private void cancelNotification(NetworkPolicy policy, int type) { 479497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String tag = buildNotificationTag(policy, type); 480497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 481497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // TODO: move to NotificationManager once we can mock it 482497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey try { 483497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String packageName = mContext.getPackageName(); 484497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mNotifManager.cancelNotificationWithTag(packageName, tag, 0x0); 485497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } catch (RemoteException e) { 486497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey Slog.w(TAG, "problem during enqueueNotification: " + e); 487497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 488497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 489497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 490497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 49121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * Receiver that watches for {@link IConnectivityManager} to claim network 49222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey * interfaces. Used to apply {@link NetworkPolicy} to matching networks. 49321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey */ 494b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey private BroadcastReceiver mConnReceiver = new BroadcastReceiver() { 49521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey @Override 49621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey public void onReceive(Context context, Intent intent) { 49721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // on background handler thread, and verified CONNECTIVITY_INTERNAL 49821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // permission above. 49921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey synchronized (mRulesLock) { 50022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey ensureActiveMobilePolicyLocked(); 50121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateIfacesLocked(); 50221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 50321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 50421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey }; 50521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 50621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey /** 50721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * Examine all connected {@link NetworkState}, looking for 50821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * {@link NetworkPolicy} that need to be enforced. When matches found, set 50921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * remaining quota based on usage cycle and historical stats. 51021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey */ 51121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void updateIfacesLocked() { 51222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); 51321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 51421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final NetworkState[] states; 51521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey try { 51621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey states = mConnManager.getAllNetworkState(); 51721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (RemoteException e) { 51821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey Slog.w(TAG, "problem reading network state"); 51921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey return; 52021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 52121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 52221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // first, derive identity for all connected networks, which can be used 52321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // to match against templates. 52421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final HashMap<NetworkIdentity, String> networks = Maps.newHashMap(); 52521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey for (NetworkState state : states) { 52621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // stash identity and iface away for later use 52721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (state.networkInfo.isConnected()) { 52821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String iface = state.linkProperties.getInterfaceName(); 52921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); 53021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey networks.put(ident, iface); 53121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 53221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 53321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 53421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // build list of rules and ifaces to enforce them against 53522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final HashMap<NetworkPolicy, String[]> rules = Maps.newHashMap(); 53621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final ArrayList<String> ifaceList = Lists.newArrayList(); 53722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy) { 53821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 53921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // collect all active ifaces that match this template 54021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey ifaceList.clear(); 54121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey for (NetworkIdentity ident : networks.keySet()) { 5421b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey if (policy.template.matches(ident)) { 54321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String iface = networks.get(ident); 54421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey ifaceList.add(iface); 54521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 54621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 54721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 54821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (ifaceList.size() > 0) { 54921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]); 55022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey rules.put(policy, ifaces); 55121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 55221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 55321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 55421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // try refreshing time source when stale 55521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) { 55621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mTime.forceRefresh(); 55721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 55821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 55921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() 56021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey : System.currentTimeMillis(); 56121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 562fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey mMeteredIfaces.clear(); 563fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey 56421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // apply each policy that we found ifaces for; compute remaining data 56521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // based on current cycle and historical stats, and push to kernel. 56622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey for (NetworkPolicy policy : rules.keySet()) { 56721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String[] ifaces = rules.get(policy); 56821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 56921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long start = computeLastCycleBoundary(currentTime, policy); 57021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long end = currentTime; 57121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 57221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final NetworkStats stats; 57322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final long total; 57421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey try { 5751b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey stats = mNetworkStats.getSummaryForNetwork(policy.template, start, end); 57622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey total = stats.rx[0] + stats.tx[0]; 57721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (RemoteException e) { 5781b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey Slog.w(TAG, "problem reading summary for template " + policy.template); 57921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey continue; 58021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 58121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 58221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (LOGD) { 58321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces " 58422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey + Arrays.toString(ifaces)); 58522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 58622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 58722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey // TODO: register for warning notification trigger through NMS 58822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 58922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (policy.limitBytes != NetworkPolicy.LIMIT_DISABLED) { 59022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey // remaining "quota" is based on usage in current cycle 59122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final long quota = Math.max(0, policy.limitBytes - total); 592497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey //kernelSetIfacesQuota(ifaces, quota); 593fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey 594fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey for (String iface : ifaces) { 595fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey mMeteredIfaces.add(iface); 596fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey } 59722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 59822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 599fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey 600fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]); 6014414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget(); 60222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 60322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 60422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey /** 60522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we 60622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey * have at least a default mobile policy defined. 60722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey */ 60822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private void ensureActiveMobilePolicyLocked() { 60922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()"); 61022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final String subscriberId = getActiveSubscriberId(); 6111b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final NetworkIdentity probeIdent = new NetworkIdentity( 6125dc0c26cffbbc62ff84f9f4c8a451e68e2c05d2dJeff Sharkey TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false); 61322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 61422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey // examine to see if any policy is defined for active mobile 61522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey boolean mobileDefined = false; 61622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy) { 6171b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey if (policy.template.matches(probeIdent)) { 61822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mobileDefined = true; 61921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 62022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 62121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 62222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (!mobileDefined) { 62322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey Slog.i(TAG, "no policy for active mobile network; generating default policy"); 62421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 62522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey // default mobile policy has combined 4GB warning, and assume usage 62622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey // cycle starts today today. 62722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 62822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey // TODO: move this policy definition to overlay or secure setting 62922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final Time time = new Time(Time.TIMEZONE_UTC); 63022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey time.setToNow(); 63122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final int cycleDay = time.monthDay; 63222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 6331b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final NetworkTemplate template = new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId); 6341b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey mNetworkPolicy.add( 6351b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey new NetworkPolicy(template, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED)); 636fcc79771f092f34505b1accb80365cbcaa379667Jeff Sharkey writePolicyLocked(); 63721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 63821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 63921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 64021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void readPolicyLocked() { 64122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (LOGV) Slog.v(TAG, "readPolicyLocked()"); 64221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 64321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // clear any existing policy and read from disk 64422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mNetworkPolicy.clear(); 64521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mUidPolicy.clear(); 64621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 64721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey FileInputStream fis = null; 64821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey try { 64921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey fis = mPolicyFile.openRead(); 65021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final XmlPullParser in = Xml.newPullParser(); 65121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey in.setInput(fis, null); 65221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 65321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey int type; 65421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey int version = VERSION_CURRENT; 65521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey while ((type = in.next()) != END_DOCUMENT) { 65621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String tag = in.getName(); 65721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (type == START_TAG) { 65821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (TAG_POLICY_LIST.equals(tag)) { 65921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey version = readIntAttribute(in, ATTR_VERSION); 66021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 66121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } else if (TAG_NETWORK_POLICY.equals(tag)) { 66221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE); 66321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID); 66421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY); 66521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES); 66621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES); 66721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 6681b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final NetworkTemplate template = new NetworkTemplate( 6691b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey networkTemplate, subscriberId); 6701b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey mNetworkPolicy.add( 6711b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey new NetworkPolicy(template, cycleDay, warningBytes, limitBytes)); 67221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 67321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } else if (TAG_UID_POLICY.equals(tag)) { 67421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int uid = readIntAttribute(in, ATTR_UID); 67521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int policy = readIntAttribute(in, ATTR_POLICY); 67621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 677497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (isUidValidForPolicy(mContext, uid)) { 678497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey setUidPolicyUnchecked(uid, policy, false); 679497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } else { 680497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring"); 681497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 68221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 68321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 68421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 68521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 68621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (FileNotFoundException e) { 68721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // missing policy is okay, probably first boot 68821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (IOException e) { 68921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey Slog.e(TAG, "problem reading network stats", e); 69021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (XmlPullParserException e) { 69121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey Slog.e(TAG, "problem reading network stats", e); 69221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } finally { 69321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey IoUtils.closeQuietly(fis); 69421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 69521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 69621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 69721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void writePolicyLocked() { 69822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (LOGV) Slog.v(TAG, "writePolicyLocked()"); 69921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 70021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey FileOutputStream fos = null; 70121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey try { 70221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey fos = mPolicyFile.startWrite(); 70321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 70421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey XmlSerializer out = new FastXmlSerializer(); 70521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.setOutput(fos, "utf-8"); 70621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.startDocument(null, true); 70721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 70821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.startTag(null, TAG_POLICY_LIST); 70921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeIntAttribute(out, ATTR_VERSION, VERSION_CURRENT); 71021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 71121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // write all known network policies 71222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy) { 7131b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final NetworkTemplate template = policy.template; 7141b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 71521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.startTag(null, TAG_NETWORK_POLICY); 7161b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule()); 7171b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final String subscriberId = template.getSubscriberId(); 7181b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey if (subscriberId != null) { 7191b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId); 72021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 72121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay); 72221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes); 72321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes); 72421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.endTag(null, TAG_NETWORK_POLICY); 72521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 72621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 72721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // write all known uid policies 72821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey for (int i = 0; i < mUidPolicy.size(); i++) { 72921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int uid = mUidPolicy.keyAt(i); 73021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int policy = mUidPolicy.valueAt(i); 73121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 732497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // skip writing empty policies 733497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (policy == POLICY_NONE) continue; 734497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 73521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.startTag(null, TAG_UID_POLICY); 73621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeIntAttribute(out, ATTR_UID, uid); 73721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeIntAttribute(out, ATTR_POLICY, policy); 73821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.endTag(null, TAG_UID_POLICY); 73921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 74021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 74121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.endTag(null, TAG_POLICY_LIST); 74221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.endDocument(); 74321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 74421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mPolicyFile.finishWrite(fos); 74521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (IOException e) { 74621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (fos != null) { 74721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mPolicyFile.failWrite(fos); 74821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 74921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 75021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 75121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 752d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey @Override 753d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey public void setUidPolicy(int uid, int policy) { 75421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 755a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 756497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (!isUidValidForPolicy(mContext, uid)) { 757497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey throw new IllegalArgumentException("cannot apply policy to UID " + uid); 758497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 759497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 760497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey setUidPolicyUnchecked(uid, policy, true); 761497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 762497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 763497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private void setUidPolicyUnchecked(int uid, int policy, boolean persist) { 764c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey final int oldPolicy; 765a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 766c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey oldPolicy = getUidPolicy(uid); 767a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mUidPolicy.put(uid, policy); 768c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 76921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // uid policy changed, recompute rules and persist policy. 77021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateRulesForUidLocked(uid); 771497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (persist) { 772497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey writePolicyLocked(); 773497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 77421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 775d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 776d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 777d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey @Override 778d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey public int getUidPolicy(int uid) { 77921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 78021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 781a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 782a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey return mUidPolicy.get(uid, POLICY_NONE); 783a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 784d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 785d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 786c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey @Override 787c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey public void registerListener(INetworkPolicyListener listener) { 7881a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey // TODO: create permission for observing network policy 7891a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 7901a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey 791c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey mListeners.register(listener); 792c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 7934414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey // TODO: consider dispatching existing rules to new listeners 794c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey } 795c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 796c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey @Override 797c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey public void unregisterListener(INetworkPolicyListener listener) { 7981a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey // TODO: create permission for observing network policy 7991a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 8001a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey 801c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey mListeners.unregister(listener); 802c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey } 803c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 8041b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey @Override 80522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey public void setNetworkPolicies(NetworkPolicy[] policies) { 80621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 80721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 80821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey synchronized (mRulesLock) { 80922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mNetworkPolicy.clear(); 81022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey for (NetworkPolicy policy : policies) { 81122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mNetworkPolicy.add(policy); 81222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 81321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 81421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateIfacesLocked(); 815497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey updateNotificationsLocked(); 81621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writePolicyLocked(); 81721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 81821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 81921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 82021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey @Override 82122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey public NetworkPolicy[] getNetworkPolicies() { 82221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 82322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG); 82421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 82521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey synchronized (mRulesLock) { 82622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey return mNetworkPolicy.toArray(new NetworkPolicy[mNetworkPolicy.size()]); 82721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 82821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 82921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 83021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey @Override 8311b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 83275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey mContext.enforceCallingOrSelfPermission(DUMP, TAG); 8331b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 8341b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey synchronized (mRulesLock) { 83521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey fout.println("Network policies:"); 83622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy) { 83722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey fout.print(" "); fout.println(policy.toString()); 83821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 83921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 8401b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.println("Policy status for known UIDs:"); 8411b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 8421b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final SparseBooleanArray knownUids = new SparseBooleanArray(); 8431b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey collectKeys(mUidPolicy, knownUids); 8441b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey collectKeys(mUidForeground, knownUids); 8451b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey collectKeys(mUidRules, knownUids); 8461b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 8471b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int size = knownUids.size(); 8481b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey for (int i = 0; i < size; i++) { 8491b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int uid = knownUids.keyAt(i); 8501b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(" UID="); 8511b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(uid); 8521b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 8531b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(" policy="); 8541b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int policyIndex = mUidPolicy.indexOfKey(uid); 8551b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey if (policyIndex < 0) { 8561b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("UNKNOWN"); 8571b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } else { 8581b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey dumpPolicy(fout, mUidPolicy.valueAt(policyIndex)); 8591b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 8601b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 8611b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(" foreground="); 8621b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int foregroundIndex = mUidPidForeground.indexOfKey(uid); 8631b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey if (foregroundIndex < 0) { 8641b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("UNKNOWN"); 8651b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } else { 8661b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex)); 8671b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 8681b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 8691b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(" rules="); 8701b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int rulesIndex = mUidRules.indexOfKey(uid); 8711b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey if (rulesIndex < 0) { 8721b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("UNKNOWN"); 8731b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } else { 8741b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey dumpRules(fout, mUidRules.valueAt(rulesIndex)); 8751b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 8761b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 8771b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.println(); 8781b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 8791b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 8801b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 8819599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 8829599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 8839599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public boolean isUidForeground(int uid) { 884497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 885497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 8869599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey synchronized (mRulesLock) { 8879599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey // only really in foreground when screen is also on 8889599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return mUidForeground.get(uid, false) && mScreenOn; 8899599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 890c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey } 891c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 892d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey /** 893d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Foreground for PID changed; recompute foreground at UID level. If 89421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * changed, will trigger {@link #updateRulesForUidLocked(int)}. 895d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */ 89621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void computeUidForegroundLocked(int uid) { 897d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 898d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 899d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey // current pid is dropping foreground; examine other pids 900d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey boolean uidForeground = false; 901d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey final int size = pidForeground.size(); 902d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey for (int i = 0; i < size; i++) { 903d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey if (pidForeground.valueAt(i)) { 904d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey uidForeground = true; 905d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey break; 906d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 907d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 908d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 909d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey final boolean oldUidForeground = mUidForeground.get(uid, false); 910d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey if (oldUidForeground != uidForeground) { 911d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey // foreground changed, push updated rules 912d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey mUidForeground.put(uid, uidForeground); 91321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateRulesForUidLocked(uid); 914a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 915a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 916a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 917a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private void updateScreenOn() { 918a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 919a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey try { 920a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mScreenOn = mPowerManager.isScreenOn(); 921a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } catch (RemoteException e) { 922a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 92321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateRulesForScreenLocked(); 924d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 925d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 926d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 927a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey /** 928a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey * Update rules that might be changed by {@link #mScreenOn} value. 929a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey */ 93021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void updateRulesForScreenLocked() { 931a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // only update rules for anyone with foreground activities 932a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey final int size = mUidForeground.size(); 933a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey for (int i = 0; i < size; i++) { 934a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey if (mUidForeground.valueAt(i)) { 935a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey final int uid = mUidForeground.keyAt(i); 93621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateRulesForUidLocked(uid); 937a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 938a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 939a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 940a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 94121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void updateRulesForUidLocked(int uid) { 942d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey final int uidPolicy = getUidPolicy(uid); 9439599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final boolean uidForeground = isUidForeground(uid); 944d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 945c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // derive active rules based on policy and active state 946c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey int uidRules = RULE_ALLOW_ALL; 947fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { 948fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey // uid in background, and policy says to block metered data 949fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey uidRules = RULE_REJECT_METERED; 950d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 951d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 952c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // TODO: only dispatch when rules actually change 953c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 954c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // record rule locally to dispatch to new listeners 955c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey mUidRules.put(uid, uidRules); 956c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 957fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0; 958497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey //kernelSetUidRejectPaid(uid, rejectPaid); 959497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 960c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // dispatch changed rule to existing listeners 9614414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget(); 9624414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 9634414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 9644414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey private Handler.Callback mHandlerCallback = new Handler.Callback() { 9654414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey /** {@inheritDoc} */ 9664414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey public boolean handleMessage(Message msg) { 9674414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey switch (msg.what) { 9684414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey case MSG_RULES_CHANGED: { 9694414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int uid = msg.arg1; 9704414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int uidRules = msg.arg2; 9714414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int length = mListeners.beginBroadcast(); 9724414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey for (int i = 0; i < length; i++) { 9734414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 9744414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey if (listener != null) { 9754414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey try { 9764414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey listener.onUidRulesChanged(uid, uidRules); 9774414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } catch (RemoteException e) { 9784414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 9794414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 9804414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 9814414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mListeners.finishBroadcast(); 9824414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey return true; 9834414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 9844414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey case MSG_METERED_IFACES_CHANGED: { 9854414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final String[] meteredIfaces = (String[]) msg.obj; 9864414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int length = mListeners.beginBroadcast(); 9874414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey for (int i = 0; i < length; i++) { 9884414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 9894414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey if (listener != null) { 9904414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey try { 9914414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey listener.onMeteredIfacesChanged(meteredIfaces); 9924414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } catch (RemoteException e) { 9934414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 9944414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 9954414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 9964414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mListeners.finishBroadcast(); 9974414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey return true; 9984414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 9994414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey default: { 10004414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey return false; 1001af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey } 1002af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey } 1003af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey } 10044414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey }; 100522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 100622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private String getActiveSubscriberId() { 100722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService( 100822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey Context.TELEPHONY_SERVICE); 100922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey return telephony.getSubscriberId(); 101022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 101122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 10121b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey private static void collectKeys(SparseIntArray source, SparseBooleanArray target) { 10131b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int size = source.size(); 10141b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey for (int i = 0; i < size; i++) { 10151b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey target.put(source.keyAt(i), true); 10161b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 10171b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 10181b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 10191b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) { 10201b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int size = source.size(); 10211b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey for (int i = 0; i < size; i++) { 10221b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey target.put(source.keyAt(i), true); 10231b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 10241b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 10251b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 10261b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) { 10271b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("["); 10281b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int size = value.size(); 10291b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey for (int i = 0; i < size; i++) { 10301b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(value.keyAt(i) + "=" + value.valueAt(i)); 10311b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey if (i < size - 1) fout.print(","); 10321b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 10331b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("]"); 10341b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 103521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 103621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static int readIntAttribute(XmlPullParser in, String name) throws IOException { 103721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String value = in.getAttributeValue(null, name); 103821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey try { 103921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey return Integer.parseInt(value); 104021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (NumberFormatException e) { 104121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 104221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 104321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 104421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 104521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static long readLongAttribute(XmlPullParser in, String name) throws IOException { 104621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String value = in.getAttributeValue(null, name); 104721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey try { 104821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey return Long.parseLong(value); 104921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (NumberFormatException e) { 105021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 105121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 105221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 105321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 105421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static void writeIntAttribute(XmlSerializer out, String name, int value) 105521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey throws IOException { 105621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.attribute(null, name, Integer.toString(value)); 105721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 105821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 105921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static void writeLongAttribute(XmlSerializer out, String name, long value) 106021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey throws IOException { 106121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.attribute(null, name, Long.toString(value)); 106221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 106321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 1064d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey} 1065