NetworkPolicyManagerService.java revision 163e6443f27884a9bfcb9a48ef606dc635852c23
1d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/* 2d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project 3d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * 4d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * you may not use this file except in compliance with the License. 6d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * You may obtain a copy of the License at 7d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * 8d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * 10d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 11d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * See the License for the specific language governing permissions and 14d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * limitations under the License. 15d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */ 16d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 17d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeypackage com.android.server.net; 18d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 19f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkeyimport static android.Manifest.permission.ACCESS_NETWORK_STATE; 2021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.CONNECTIVITY_INTERNAL; 211b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.Manifest.permission.DUMP; 2221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.MANAGE_NETWORK_POLICY; 23497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; 2422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport static android.Manifest.permission.READ_PHONE_STATE; 2502e21d6a5b5117d494777a36783909854854f751Jeff Sharkeyimport static android.content.Intent.ACTION_PACKAGE_ADDED; 26b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.ACTION_UID_REMOVED; 27b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.EXTRA_UID; 28961e30458319cfd50e1892ba7dd14a1d0ebe4cc7Jeff Sharkeyimport static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; 298e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_ETHERNET; 301b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_MOBILE; 318e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_WIFI; 328e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_WIMAX; 3322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport static android.net.NetworkPolicy.LIMIT_DISABLED; 3441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkeyimport static android.net.NetworkPolicy.SNOOZE_NEVER; 35497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static android.net.NetworkPolicy.WARNING_DISABLED; 3614711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkeyimport static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE; 37d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_NONE; 38fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; 39c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; 40fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport static android.net.NetworkPolicyManager.RULE_REJECT_METERED; 41cd2ca4038a027315832c38c68be5076000bc4b53Jeff Sharkeyimport static android.net.NetworkPolicyManager.computeLastCycleBoundary; 421b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.net.NetworkPolicyManager.dumpPolicy; 431b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.net.NetworkPolicyManager.dumpRules; 44497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static android.net.NetworkPolicyManager.isUidValidForPolicy; 458e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_ETHERNET; 461b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER; 471b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_4G; 488e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_ALL; 498e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_WIFI; 504e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkeyimport static android.net.NetworkTemplate.buildTemplateMobileAll; 5121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.text.format.DateUtils.DAY_IN_MILLIS; 5221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull; 53961e30458319cfd50e1892ba7dd14a1d0ebe4cc7Jeff Sharkeyimport static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; 544664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkeyimport static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readBooleanAttribute; 554664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkeyimport static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readIntAttribute; 564664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkeyimport static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readLongAttribute; 574664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkeyimport static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeBooleanAttribute; 584664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkeyimport static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeIntAttribute; 594664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkeyimport static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeLongAttribute; 60497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED; 6121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 6221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.START_TAG; 63d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 64a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IActivityManager; 65497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.INotificationManager; 66a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IProcessObserver; 67497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.Notification; 68497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.PendingIntent; 69a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.BroadcastReceiver; 7041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkeyimport android.content.ComponentName; 71d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.content.Context; 72a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.Intent; 73a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.IntentFilter; 74b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.content.pm.ApplicationInfo; 75b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.content.pm.PackageManager; 76497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.content.res.Resources; 77c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.ConnectivityManager; 7821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.IConnectivityManager; 7941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkeyimport android.net.INetworkManagementEventObserver; 80c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.INetworkPolicyListener; 81d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.net.INetworkPolicyManager; 8275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.INetworkStatsService; 831b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkIdentity; 8421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkPolicy; 85f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkeyimport android.net.NetworkQuotaInfo; 8621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkState; 871b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkTemplate; 88f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkeyimport android.os.Binder; 8921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Environment; 9021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Handler; 9121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.HandlerThread; 9250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharmaimport android.os.INetworkManagementService; 93a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.IPowerManager; 944414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkeyimport android.os.Message; 95163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport android.os.MessageQueue.IdleHandler; 96c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.os.RemoteCallbackList; 97a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.RemoteException; 983a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkeyimport android.provider.Settings; 9922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport android.telephony.TelephonyManager; 100497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.text.format.Formatter; 10122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport android.text.format.Time; 102b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkeyimport android.util.Log; 10321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.NtpTrustedTime; 104a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.util.Slog; 105d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseArray; 106d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseBooleanArray; 107d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseIntArray; 10821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.TrustedTime; 10921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.Xml; 110d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 111497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport com.android.internal.R; 11221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.android.internal.os.AtomicFile; 11321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.android.internal.util.FastXmlSerializer; 1148e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkeyimport com.android.internal.util.Objects; 11521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.google.android.collect.Lists; 11621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.google.android.collect.Maps; 117fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport com.google.android.collect.Sets; 11821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 11921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlPullParser; 12021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlPullParserException; 12121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlSerializer; 12221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 12321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.File; 1241b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.FileDescriptor; 12521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileInputStream; 12621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileNotFoundException; 12721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileOutputStream; 12821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.IOException; 1291b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.PrintWriter; 13021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.net.ProtocolException; 13121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.ArrayList; 13221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.Arrays; 13321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.HashMap; 134fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport java.util.HashSet; 135b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport java.util.List; 13647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport java.util.Map; 13721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 13821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport libcore.io.IoUtils; 1391b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 140d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/** 1418e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * Service that maintains low-level network policy rules, using 1428e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * {@link NetworkStatsService} statistics to drive those rules. 143c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * <p> 144c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * Derives active rules by combining a given policy with other system status, 145c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * and delivers to listeners, such as {@link ConnectivityManager}, for 146c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * enforcement. 147d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */ 148d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeypublic class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 149d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey private static final String TAG = "NetworkPolicy"; 150d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey private static final boolean LOGD = true; 15122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private static final boolean LOGV = false; 152d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 15341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private static final int VERSION_INIT = 1; 15441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private static final int VERSION_ADDED_SNOOZE = 2; 1554664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3; 15621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 15722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private static final long KB_IN_BYTES = 1024; 15822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private static final long MB_IN_BYTES = KB_IN_BYTES * 1024; 15922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private static final long GB_IN_BYTES = MB_IN_BYTES * 1024; 16022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 16141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // @VisibleForTesting 16241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public static final int TYPE_WARNING = 0x1; 16341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public static final int TYPE_LIMIT = 0x2; 16441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public static final int TYPE_LIMIT_SNOOZED = 0x3; 165497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 16621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String TAG_POLICY_LIST = "policy-list"; 16721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String TAG_NETWORK_POLICY = "network-policy"; 16821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String TAG_UID_POLICY = "uid-policy"; 16921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 17021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_VERSION = "version"; 1714664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground"; 17221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate"; 17321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_SUBSCRIBER_ID = "subscriberId"; 17421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_CYCLE_DAY = "cycleDay"; 17521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_WARNING_BYTES = "warningBytes"; 17621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_LIMIT_BYTES = "limitBytes"; 17741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private static final String ATTR_LAST_SNOOZE = "lastSnooze"; 17821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_UID = "uid"; 17921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final String ATTR_POLICY = "policy"; 18021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 1813a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground"; 1823a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 1833a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey // @VisibleForTesting 1843a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey public static final String ACTION_ALLOW_BACKGROUND = 1853a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey "com.android.server.action.ACTION_ALLOW_BACKGROUND"; 1863a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 18721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS; 18821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 1896f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey private static final int MSG_RULES_CHANGED = 1; 1906f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey private static final int MSG_METERED_IFACES_CHANGED = 2; 1916f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey private static final int MSG_FOREGROUND_ACTIVITIES_CHANGED = 3; 1926f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey private static final int MSG_PROCESS_DIED = 4; 1934414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 19475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final Context mContext; 19575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final IActivityManager mActivityManager; 19675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final IPowerManager mPowerManager; 19775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final INetworkStatsService mNetworkStats; 19841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private final INetworkManagementService mNetworkManager; 19921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private final TrustedTime mTime; 20021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 20121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private IConnectivityManager mConnManager; 202497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private INotificationManager mNotifManager; 203a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 20475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final Object mRulesLock = new Object(); 205a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 2063a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private volatile boolean mScreenOn; 2073a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private volatile boolean mRestrictBackground; 208d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 2098e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private final boolean mSuppressDefaultPolicy; 2108e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 21141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Defined network policies. */ 21241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap(); 21341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Currently active network rules for ifaces. */ 21402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap(); 21522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 21641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Defined UID policies. */ 217a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private SparseIntArray mUidPolicy = new SparseIntArray(); 21841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Currently derived rules for each UID. */ 219c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey private SparseIntArray mUidRules = new SparseIntArray(); 220d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 221fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey /** Set of ifaces that are metered. */ 222fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey private HashSet<String> mMeteredIfaces = Sets.newHashSet(); 22341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Set of over-limit templates that have been notified. */ 22441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet(); 225fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey 2268e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey /** Set of currently active {@link Notification} tags. */ 2278e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private HashSet<String> mActiveNotifs = Sets.newHashSet(); 2288e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey /** Current values from {@link #setPolicyDataEnable(int, boolean)}. */ 2298e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private SparseBooleanArray mActiveNetworkEnabled = new SparseBooleanArray(); 2308e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 231d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey /** Foreground at both UID and PID granularity. */ 232a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private SparseBooleanArray mUidForeground = new SparseBooleanArray(); 233a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray< 234a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey SparseBooleanArray>(); 235d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 236c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList< 237c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey INetworkPolicyListener>(); 238c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 23921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private final HandlerThread mHandlerThread; 24021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private final Handler mHandler; 24121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 24221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private final AtomicFile mPolicyFile; 243d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 244c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // TODO: keep whitelist of system-critical services that should never have 245c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // rules enforced, such as system, phone, and radio UIDs. 246c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 24741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: migrate notifications to SystemUI 24841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 24975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 25050fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma IPowerManager powerManager, INetworkStatsService networkStats, 25150fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma INetworkManagementService networkManagement) { 252b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey this(context, activityManager, powerManager, networkStats, networkManagement, 2538e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey NtpTrustedTime.getInstance(context), getSystemDir(), false); 25421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 25521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 25621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static File getSystemDir() { 25721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey return new File(Environment.getDataDirectory(), "system"); 25821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 25921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 26021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 26150fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma IPowerManager powerManager, INetworkStatsService networkStats, 2628e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey INetworkManagementService networkManagement, TrustedTime time, File systemDir, 2638e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey boolean suppressDefaultPolicy) { 264a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mContext = checkNotNull(context, "missing context"); 265a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mActivityManager = checkNotNull(activityManager, "missing activityManager"); 266a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mPowerManager = checkNotNull(powerManager, "missing powerManager"); 26775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey mNetworkStats = checkNotNull(networkStats, "missing networkStats"); 26841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkManager = checkNotNull(networkManagement, "missing networkManagement"); 26921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mTime = checkNotNull(time, "missing TrustedTime"); 27021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 27121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mHandlerThread = new HandlerThread(TAG); 27221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mHandlerThread.start(); 2734414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback); 27421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 2758e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey mSuppressDefaultPolicy = suppressDefaultPolicy; 2768e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 27721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); 27821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 27921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 28021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey public void bindConnectivityManager(IConnectivityManager connManager) { 28121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mConnManager = checkNotNull(connManager, "missing IConnectivityManager"); 282a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 283d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 284497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey public void bindNotificationManager(INotificationManager notifManager) { 285497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mNotifManager = checkNotNull(notifManager, "missing INotificationManager"); 286497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 287497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 288a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey public void systemReady() { 28921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey synchronized (mRulesLock) { 29021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // read policy from disk 29121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey readPolicyLocked(); 2924664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey 2934664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey if (mRestrictBackground) { 2944664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey updateRulesForRestrictBackgroundLocked(); 2953a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey updateNotificationsLocked(); 2964664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 29721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 298d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 299a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey updateScreenOn(); 300d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 301a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey try { 302a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mActivityManager.registerProcessObserver(mProcessObserver); 30341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkManager.registerObserver(mAlertObserver); 30441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } catch (RemoteException e) { 305b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; both services live in system_server 30641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 30741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 308a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // TODO: traverse existing processes to know foreground state, or have 309a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // activitymanager dispatch current state when new observer attached. 310d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 311a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey final IntentFilter screenFilter = new IntentFilter(); 312a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey screenFilter.addAction(Intent.ACTION_SCREEN_ON); 313a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey screenFilter.addAction(Intent.ACTION_SCREEN_OFF); 31441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler); 315d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 31621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // watch for network interfaces to be claimed 317961e30458319cfd50e1892ba7dd14a1d0ebe4cc7Jeff Sharkey final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE); 318b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); 319b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey 32002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // listen for package/uid changes to update policy 32102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey final IntentFilter packageFilter = new IntentFilter(); 32202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey packageFilter.addAction(ACTION_PACKAGE_ADDED); 32302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey packageFilter.addAction(ACTION_UID_REMOVED); 32402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler); 32521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 326b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // listen for stats update events 327497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED); 328497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mContext.registerReceiver( 329497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler); 330497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 3313a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey // listen for restrict background changes from notifications 3323a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND); 3333a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler); 3343a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 335a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 336d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 337a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private IProcessObserver mProcessObserver = new IProcessObserver.Stub() { 338a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey @Override 339a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) { 3406f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey mHandler.obtainMessage(MSG_FOREGROUND_ACTIVITIES_CHANGED, 3416f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey pid, uid, foregroundActivities).sendToTarget(); 342d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 343d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 344a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey @Override 345a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey public void onProcessDied(int pid, int uid) { 3466f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey mHandler.obtainMessage(MSG_PROCESS_DIED, pid, uid).sendToTarget(); 347a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 348a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey }; 349a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 350a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { 351a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey @Override 352a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey public void onReceive(Context context, Intent intent) { 353a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 354a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // screen-related broadcasts are protected by system, no need 355a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // for permissions check. 356a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey updateScreenOn(); 357a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 358a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 359a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey }; 360d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 36102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() { 362b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey @Override 363b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey public void onReceive(Context context, Intent intent) { 36402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // on background handler thread, and PACKAGE_ADDED and UID_REMOVED 36502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // are protected broadcasts. 36602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey 36702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey final String action = intent.getAction(); 368b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey final int uid = intent.getIntExtra(EXTRA_UID, 0); 369b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey synchronized (mRulesLock) { 37002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey if (ACTION_PACKAGE_ADDED.equals(action)) { 37102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // update rules for UID, since it might be subject to 37202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // global background data policy. 37302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid); 37402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey updateRulesForUidLocked(uid); 37502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey 37602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey } else if (ACTION_UID_REMOVED.equals(action)) { 37702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // remove any policy and update rules to clean up. 37802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid); 37902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey mUidPolicy.delete(uid); 38002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey updateRulesForUidLocked(uid); 38102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey writePolicyLocked(); 38202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey } 383b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey } 384b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey } 385b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey }; 386b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey 38721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey /** 388497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Receiver that watches for {@link INetworkStatsService} updates, which we 389497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * use to check against {@link NetworkPolicy#warningBytes}. 390497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 391497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() { 392497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey @Override 393497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey public void onReceive(Context context, Intent intent) { 394497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // on background handler thread, and verified 395497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // READ_NETWORK_USAGE_HISTORY permission above. 396497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 397497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey synchronized (mRulesLock) { 3988e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey updateNetworkEnabledLocked(); 399497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey updateNotificationsLocked(); 400497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 401497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 402497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey }; 403497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 404497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 4053a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey * Receiver that watches for {@link Notification} control of 4063a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey * {@link #mRestrictBackground}. 4073a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey */ 4083a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() { 4093a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey @Override 4103a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey public void onReceive(Context context, Intent intent) { 4113a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey // on background handler thread, and verified MANAGE_NETWORK_POLICY 4123a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey // permission above. 4133a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 4143a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey setRestrictBackground(false); 4153a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 4163a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey }; 4173a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 4183a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey /** 41941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey * Observer that watches for {@link INetworkManagementService} alerts. 42041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey */ 42141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() { 42241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey @Override 42341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void limitReached(String limitName, String iface) { 42441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // only someone like NMS should be calling us 42541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 42641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 42741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mRulesLock) { 4288e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey if (mMeteredIfaces.contains(iface) && !LIMIT_GLOBAL_ALERT.equals(limitName)) { 42941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey try { 43041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // force stats update to make sure we have numbers that 43141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // caused alert to trigger. 43241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkStats.forceUpdate(); 43341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } catch (RemoteException e) { 434b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 43541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 43641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 4378e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey updateNetworkEnabledLocked(); 43841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey updateNotificationsLocked(); 43941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 44041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 44141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 44241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey }; 44341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 44441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** 445497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Check {@link NetworkPolicy} against current {@link INetworkStatsService} 446497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * to show visible notifications as needed. 447497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 448497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private void updateNotificationsLocked() { 449497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (LOGV) Slog.v(TAG, "updateNotificationsLocked()"); 450497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 4518e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // keep track of previously active notifications 4528e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final HashSet<String> beforeNotifs = Sets.newHashSet(); 4538e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey beforeNotifs.addAll(mActiveNotifs); 4548e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey mActiveNotifs.clear(); 455497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 456497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // TODO: when switching to kernel notifications, compute next future 457497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // cycle boundary to recompute notifications. 458497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 45902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // examine stats for each active policy 4608e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long currentTime = currentTimeMillis(true); 4618e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 4628e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // ignore policies that aren't relevant to user 4638e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (!isTemplateRelevant(policy.template)) continue; 4648e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 465497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final long start = computeLastCycleBoundary(currentTime, policy); 466497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final long end = currentTime; 4678e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long totalBytes = getTotalBytes(policy.template, start, end); 468497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 46950e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey if (policy.isOverLimit(totalBytes)) { 47041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (policy.lastSnooze >= start) { 47141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes); 47241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } else { 47341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey enqueueNotification(policy, TYPE_LIMIT, totalBytes); 47441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey notifyOverLimitLocked(policy.template); 47541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 47641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 477497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } else { 47841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey notifyUnderLimitLocked(policy.template); 479497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 48041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) { 48141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey enqueueNotification(policy, TYPE_WARNING, totalBytes); 482497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 483497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 48402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey } 48502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey 4863a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey // ongoing notification when restricting background data 4873a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey if (mRestrictBackground) { 4883a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND); 4893a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 4908e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 4918e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // cancel stale notifications that we didn't renew above 4928e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey for (String tag : beforeNotifs) { 4938e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (!mActiveNotifs.contains(tag)) { 4948e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey cancelNotification(tag); 4958e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 4968e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 4978e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 4988e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 4998e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey /** 5008e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * Test if given {@link NetworkTemplate} is relevant to user based on 5018e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * current device state, such as when {@link #getActiveSubscriberId()} 5028e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * matches. This is regardless of data connection status. 5038e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey */ 5048e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private boolean isTemplateRelevant(NetworkTemplate template) { 5058e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey switch (template.getMatchRule()) { 5068e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_3G_LOWER: 5078e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_4G: 5088e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_ALL: 5098e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // mobile templates are relevant when subscriberid is active 5108e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey return Objects.equal(getActiveSubscriberId(), template.getSubscriberId()); 5118e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 5128e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey return true; 513497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 514497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 515497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 51641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey * Notify that given {@link NetworkTemplate} is over 51741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user. 51841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey */ 51941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private void notifyOverLimitLocked(NetworkTemplate template) { 52041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mOverLimitNotified.contains(template)) { 52141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.startActivity(buildNetworkOverLimitIntent(template)); 52241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mOverLimitNotified.add(template); 52341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 52441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 52541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 52641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private void notifyUnderLimitLocked(NetworkTemplate template) { 52741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mOverLimitNotified.remove(template); 52841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 52941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 53041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** 531497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Build unique tag that identifies an active {@link NetworkPolicy} 532497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * notification of a specific type, like {@link #TYPE_LIMIT}. 533497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 534497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private String buildNotificationTag(NetworkPolicy policy, int type) { 5351b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey return TAG + ":" + policy.template.hashCode() + ":" + type; 536497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 537497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 538497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 539497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Show notification for combined {@link NetworkPolicy} and specific type, 540497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * like {@link #TYPE_LIMIT}. Okay to call multiple times. 541497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 54241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) { 543497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String tag = buildNotificationTag(policy, type); 544497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final Notification.Builder builder = new Notification.Builder(mContext); 545497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setOnlyAlertOnce(true); 546497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setOngoing(true); 547497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 548497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final Resources res = mContext.getResources(); 549497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey switch (type) { 550497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey case TYPE_WARNING: { 55141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final CharSequence title = res.getText(R.string.data_usage_warning_title); 5528ca953da93eb8679574abba535f75f72d50016f2Jeff Sharkey final CharSequence body = res.getString(R.string.data_usage_warning_body); 553497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 55450e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey builder.setSmallIcon(R.drawable.stat_notify_error); 555497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setTicker(title); 556497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setContentTitle(title); 557497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setContentText(body); 55814711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey 55941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final Intent intent = buildViewDataUsageIntent(policy.template); 56014711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey builder.setContentIntent(PendingIntent.getActivity( 56114711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 562497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 563497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 564497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey case TYPE_LIMIT: { 56541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final CharSequence body = res.getText(R.string.data_usage_limit_body); 56641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 56741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final CharSequence title; 5681b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey switch (policy.template.getMatchRule()) { 5691b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey case MATCH_MOBILE_3G_LOWER: 57041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey title = res.getText(R.string.data_usage_3g_limit_title); 571497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 5721b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey case MATCH_MOBILE_4G: 57341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey title = res.getText(R.string.data_usage_4g_limit_title); 574497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 5758e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_ALL: 57641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey title = res.getText(R.string.data_usage_mobile_limit_title); 577497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 5788e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_WIFI: 5798e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey title = res.getText(R.string.data_usage_wifi_limit_title); 5808e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 5818e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey default: 5828e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey title = null; 5838e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 584497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 585497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 58650e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey builder.setSmallIcon(R.drawable.stat_notify_disabled); 587497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setTicker(title); 588497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setContentTitle(title); 589497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setContentText(body); 59014711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey 59141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final Intent intent = buildNetworkOverLimitIntent(policy.template); 59241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey builder.setContentIntent(PendingIntent.getActivity( 59341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 59441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey break; 59541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 59641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey case TYPE_LIMIT_SNOOZED: { 59741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final long overBytes = totalBytes - policy.limitBytes; 59841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body, 59941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey Formatter.formatFileSize(mContext, overBytes)); 60041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 60141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final CharSequence title; 60241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey switch (policy.template.getMatchRule()) { 60341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey case MATCH_MOBILE_3G_LOWER: 60441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey title = res.getText(R.string.data_usage_3g_limit_snoozed_title); 60541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey break; 60641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey case MATCH_MOBILE_4G: 60741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey title = res.getText(R.string.data_usage_4g_limit_snoozed_title); 60841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey break; 6098e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_ALL: 61041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey title = res.getText(R.string.data_usage_mobile_limit_snoozed_title); 61141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey break; 6128e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_WIFI: 6138e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey title = res.getText(R.string.data_usage_wifi_limit_snoozed_title); 6148e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 6158e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey default: 6168e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey title = null; 6178e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 61841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 61941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 62050e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey builder.setSmallIcon(R.drawable.stat_notify_error); 62141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey builder.setTicker(title); 62241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey builder.setContentTitle(title); 62341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey builder.setContentText(body); 62441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 62541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final Intent intent = buildViewDataUsageIntent(policy.template); 62614711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey builder.setContentIntent(PendingIntent.getActivity( 62714711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 628497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 629497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 630497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 631497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 632497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // TODO: move to NotificationManager once we can mock it 633497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey try { 634497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String packageName = mContext.getPackageName(); 635497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final int[] idReceived = new int[1]; 636497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mNotifManager.enqueueNotificationWithTag( 637497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey packageName, tag, 0x0, builder.getNotification(), idReceived); 6388e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey mActiveNotifs.add(tag); 639497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } catch (RemoteException e) { 640b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 641497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 642497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 643497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 644497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 6453a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey * Show ongoing notification to reflect that {@link #mRestrictBackground} 6463a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey * has been enabled. 6473a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey */ 6483a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private void enqueueRestrictedNotification(String tag) { 6493a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final Resources res = mContext.getResources(); 6503a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final Notification.Builder builder = new Notification.Builder(mContext); 6513a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 6523a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final CharSequence title = res.getText(R.string.data_usage_restricted_title); 6533a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final CharSequence body = res.getString(R.string.data_usage_restricted_body); 6543a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 6553a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey builder.setOnlyAlertOnce(true); 6563a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey builder.setOngoing(true); 65750e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey builder.setSmallIcon(R.drawable.stat_notify_error); 6583a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey builder.setTicker(title); 6593a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey builder.setContentTitle(title); 6603a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey builder.setContentText(body); 6613a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 6623a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final Intent intent = buildAllowBackgroundDataIntent(); 6633a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey builder.setContentIntent( 6643a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 6653a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 6663a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey // TODO: move to NotificationManager once we can mock it 6673a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey try { 6683a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final String packageName = mContext.getPackageName(); 6693a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final int[] idReceived = new int[1]; 6703a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mNotifManager.enqueueNotificationWithTag(packageName, tag, 6713a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 0x0, builder.getNotification(), idReceived); 6728e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey mActiveNotifs.add(tag); 6733a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } catch (RemoteException e) { 674b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 6753a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 6763a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 6773a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 6783a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private void cancelNotification(String tag) { 679497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // TODO: move to NotificationManager once we can mock it 680497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey try { 681497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String packageName = mContext.getPackageName(); 6823a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mNotifManager.cancelNotificationWithTag( 6833a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey packageName, tag, 0x0); 684497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } catch (RemoteException e) { 685b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 686497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 687497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 688497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 689497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 69021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * Receiver that watches for {@link IConnectivityManager} to claim network 69122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey * interfaces. Used to apply {@link NetworkPolicy} to matching networks. 69221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey */ 693b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey private BroadcastReceiver mConnReceiver = new BroadcastReceiver() { 69421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey @Override 69521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey public void onReceive(Context context, Intent intent) { 69621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // on background handler thread, and verified CONNECTIVITY_INTERNAL 69721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // permission above. 69821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey synchronized (mRulesLock) { 69922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey ensureActiveMobilePolicyLocked(); 7008e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey updateNetworkEnabledLocked(); 70102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey updateNetworkRulesLocked(); 70202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey updateNotificationsLocked(); 70321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 70421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 70521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey }; 70621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 70721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey /** 7088e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * Proactively control network data connections when they exceed 7098e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * {@link NetworkPolicy#limitBytes}. 7108e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey */ 7118e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private void updateNetworkEnabledLocked() { 7128e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()"); 7138e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 7148e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // TODO: reset any policy-disabled networks when any policy is removed 7158e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // completely, which is currently rare case. 7168e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 7178e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long currentTime = currentTimeMillis(true); 7188e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 7198e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // shortcut when policy has no limit 7208e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (policy.limitBytes == LIMIT_DISABLED) { 7218e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey setNetworkTemplateEnabled(policy.template, true); 7228e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey continue; 7238e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 7248e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 7258e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long start = computeLastCycleBoundary(currentTime, policy); 7268e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long end = currentTime; 7278e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long totalBytes = getTotalBytes(policy.template, start, end); 7288e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 7298e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // disable data connection when over limit and not snoozed 73050e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey final boolean overLimit = policy.isOverLimit(totalBytes) && policy.lastSnooze < start; 7318e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey final boolean enabled = !overLimit; 7328e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey 7338e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey setNetworkTemplateEnabled(policy.template, enabled); 7348e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 7358e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 7368e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 7378e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey /** 7388e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)} 7398e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * for the given {@link NetworkTemplate}. 7408e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey */ 7418e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) { 7428e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey switch (template.getMatchRule()) { 7438e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_3G_LOWER: 7448e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_4G: 7458e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_ALL: 7468e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // TODO: offer more granular control over radio states once 7478e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // 4965893 is available. 7488e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (Objects.equal(getActiveSubscriberId(), template.getSubscriberId())) { 7498e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey setPolicyDataEnable(TYPE_MOBILE, enabled); 7508e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey setPolicyDataEnable(TYPE_WIMAX, enabled); 7518e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 7528e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 7538e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_WIFI: 7548e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey setPolicyDataEnable(TYPE_WIFI, enabled); 7558e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 7568e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_ETHERNET: 7578e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey setPolicyDataEnable(TYPE_ETHERNET, enabled); 7588e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 7598e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey default: 7608e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey throw new IllegalArgumentException("unexpected template"); 7618e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 7628e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 7638e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 7648e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey /** 76521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * Examine all connected {@link NetworkState}, looking for 76621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * {@link NetworkPolicy} that need to be enforced. When matches found, set 76721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * remaining quota based on usage cycle and historical stats. 76821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey */ 76902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey private void updateNetworkRulesLocked() { 77022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); 77121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 77221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final NetworkState[] states; 77321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey try { 77421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey states = mConnManager.getAllNetworkState(); 77521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (RemoteException e) { 776b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 77721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey return; 77821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 77921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 78021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // first, derive identity for all connected networks, which can be used 78121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // to match against templates. 78221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final HashMap<NetworkIdentity, String> networks = Maps.newHashMap(); 78321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey for (NetworkState state : states) { 78421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // stash identity and iface away for later use 78521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (state.networkInfo.isConnected()) { 78621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String iface = state.linkProperties.getInterfaceName(); 78721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); 78821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey networks.put(ident, iface); 78921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 79021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 79121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 79221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // build list of rules and ifaces to enforce them against 79302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey mNetworkRules.clear(); 79421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final ArrayList<String> ifaceList = Lists.newArrayList(); 79541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 79621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 79721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // collect all active ifaces that match this template 79821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey ifaceList.clear(); 79947eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey for (Map.Entry<NetworkIdentity, String> entry : networks.entrySet()) { 80047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey final NetworkIdentity ident = entry.getKey(); 8011b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey if (policy.template.matches(ident)) { 80247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey final String iface = entry.getValue(); 80321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey ifaceList.add(iface); 80421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 80521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 80621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 80721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (ifaceList.size() > 0) { 80821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]); 80902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey mNetworkRules.put(policy, ifaces); 81021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 81121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 81221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 813b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final HashSet<String> newMeteredIfaces = Sets.newHashSet(); 814fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey 81521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // apply each policy that we found ifaces for; compute remaining data 81621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // based on current cycle and historical stats, and push to kernel. 8178e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long currentTime = currentTimeMillis(true); 81802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey for (NetworkPolicy policy : mNetworkRules.keySet()) { 81902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey final String[] ifaces = mNetworkRules.get(policy); 82021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 82121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long start = computeLastCycleBoundary(currentTime, policy); 82221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long end = currentTime; 8238e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long totalBytes = getTotalBytes(policy.template, start, end); 82421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 82521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (LOGD) { 82621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces " 82722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey + Arrays.toString(ifaces)); 82822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 82922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 83041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED; 8313a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey if (hasLimit) { 8328e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long quotaBytes; 8338e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (policy.lastSnooze >= start) { 8348e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // snoozing past quota, but we still need to restrict apps, 8358e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // so push really high quota. 8368e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey quotaBytes = Long.MAX_VALUE; 8378e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } else { 8388e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // remaining "quota" bytes are based on total usage in 8398e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // current cycle. kernel doesn't like 0-byte rules, so we 8408e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // set 1-byte quota and disable the radio later. 8418e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey quotaBytes = Math.max(1, policy.limitBytes - totalBytes); 8428e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 84350fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma 844b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (ifaces.length > 1) { 845b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // TODO: switch to shared quota once NMS supports 846b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey Slog.w(TAG, "shared quota unsupported; generating rule for each iface"); 847b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 848fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey 849fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey for (String iface : ifaces) { 850b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey removeInterfaceQuota(iface); 8518e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey setInterfaceQuota(iface, quotaBytes); 8528e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey newMeteredIfaces.add(iface); 85341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 85441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 85522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 856fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey 857b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // remove quota on any trailing interfaces 858b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey for (String iface : mMeteredIfaces) { 859b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (!newMeteredIfaces.contains(iface)) { 860b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey removeInterfaceQuota(iface); 86150fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 86250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 863b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mMeteredIfaces = newMeteredIfaces; 864b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 865b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]); 866b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget(); 86750fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 86850fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma 86922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey /** 87022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we 87122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey * have at least a default mobile policy defined. 87222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey */ 87322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private void ensureActiveMobilePolicyLocked() { 87422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()"); 8758e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (mSuppressDefaultPolicy) return; 8768e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 87722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final String subscriberId = getActiveSubscriberId(); 8781b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final NetworkIdentity probeIdent = new NetworkIdentity( 8795dc0c26cffbbc62ff84f9f4c8a451e68e2c05d2dJeff Sharkey TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false); 88022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 88122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey // examine to see if any policy is defined for active mobile 88222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey boolean mobileDefined = false; 88341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 8841b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey if (policy.template.matches(probeIdent)) { 88522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mobileDefined = true; 88621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 88722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 88821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 88922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (!mobileDefined) { 89022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey Slog.i(TAG, "no policy for active mobile network; generating default policy"); 89121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 89202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // build default mobile policy, and assume usage cycle starts today 89302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey final long warningBytes = mContext.getResources().getInteger( 89402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey com.android.internal.R.integer.config_networkPolicyDefaultWarning) 89502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey * MB_IN_BYTES; 89622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 89722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final Time time = new Time(Time.TIMEZONE_UTC); 89822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey time.setToNow(); 89922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final int cycleDay = time.monthDay; 90022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 9014e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey final NetworkTemplate template = buildTemplateMobileAll(subscriberId); 90241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkPolicy.put(template, new NetworkPolicy( 90341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey template, cycleDay, warningBytes, LIMIT_DISABLED, SNOOZE_NEVER)); 904fcc79771f092f34505b1accb80365cbcaa379667Jeff Sharkey writePolicyLocked(); 90521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 90621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 90721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 90821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void readPolicyLocked() { 90922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (LOGV) Slog.v(TAG, "readPolicyLocked()"); 91021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 91121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // clear any existing policy and read from disk 91222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mNetworkPolicy.clear(); 91321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mUidPolicy.clear(); 91421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 91521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey FileInputStream fis = null; 91621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey try { 91721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey fis = mPolicyFile.openRead(); 91821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final XmlPullParser in = Xml.newPullParser(); 91921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey in.setInput(fis, null); 92021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 92121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey int type; 92241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey int version = VERSION_INIT; 92321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey while ((type = in.next()) != END_DOCUMENT) { 92421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String tag = in.getName(); 92521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (type == START_TAG) { 92621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (TAG_POLICY_LIST.equals(tag)) { 92721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey version = readIntAttribute(in, ATTR_VERSION); 9284664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) { 9294664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey mRestrictBackground = readBooleanAttribute( 9304664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey in, ATTR_RESTRICT_BACKGROUND); 9314664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } else { 9323a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mRestrictBackground = false; 9334664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 93421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 93521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } else if (TAG_NETWORK_POLICY.equals(tag)) { 93621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE); 93721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID); 93821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY); 93921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES); 94021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES); 94141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final long lastSnooze; 94241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (version >= VERSION_ADDED_SNOOZE) { 94341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey lastSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE); 94441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } else { 94541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey lastSnooze = SNOOZE_NEVER; 94641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 94721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 9481b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final NetworkTemplate template = new NetworkTemplate( 9491b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey networkTemplate, subscriberId); 95041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkPolicy.put(template, new NetworkPolicy( 95141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey template, cycleDay, warningBytes, limitBytes, lastSnooze)); 95221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 95321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } else if (TAG_UID_POLICY.equals(tag)) { 95421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int uid = readIntAttribute(in, ATTR_UID); 95521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int policy = readIntAttribute(in, ATTR_POLICY); 95621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 957497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (isUidValidForPolicy(mContext, uid)) { 958497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey setUidPolicyUnchecked(uid, policy, false); 959497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } else { 960497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring"); 961497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 96221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 96321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 96421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 96521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 96621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (FileNotFoundException e) { 96721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // missing policy is okay, probably first boot 9683a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey upgradeLegacyBackgroundData(); 96921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (IOException e) { 970b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey Log.wtf(TAG, "problem reading network policy", e); 97121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (XmlPullParserException e) { 972b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey Log.wtf(TAG, "problem reading network policy", e); 97321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } finally { 97421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey IoUtils.closeQuietly(fis); 97521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 97621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 97721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 9783a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey /** 9793a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey * Upgrade legacy background data flags, notifying listeners of one last 9803a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey * change to always-true. 9813a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey */ 9823a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private void upgradeLegacyBackgroundData() { 9833a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mRestrictBackground = Settings.Secure.getInt( 9843a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1; 9853a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 9863a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey // kick off one last broadcast if restricted 9873a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey if (mRestrictBackground) { 9883a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final Intent broadcast = new Intent( 9893a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED); 9903a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mContext.sendBroadcast(broadcast); 9913a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 9923a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 9933a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 99421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void writePolicyLocked() { 99522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (LOGV) Slog.v(TAG, "writePolicyLocked()"); 99621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 99721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey FileOutputStream fos = null; 99821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey try { 99921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey fos = mPolicyFile.startWrite(); 100021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 100121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey XmlSerializer out = new FastXmlSerializer(); 100221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.setOutput(fos, "utf-8"); 100321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.startDocument(null, true); 100421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 100521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.startTag(null, TAG_POLICY_LIST); 10064664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_RESTRICT_BACKGROUND); 10074664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground); 100821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 100921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // write all known network policies 101041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 10111b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final NetworkTemplate template = policy.template; 10121b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 101321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.startTag(null, TAG_NETWORK_POLICY); 10141b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule()); 10151b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final String subscriberId = template.getSubscriberId(); 10161b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey if (subscriberId != null) { 10171b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId); 101821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 101921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay); 102021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes); 102121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes); 102241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey writeLongAttribute(out, ATTR_LAST_SNOOZE, policy.lastSnooze); 102321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.endTag(null, TAG_NETWORK_POLICY); 102421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 102521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 102621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // write all known uid policies 102721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey for (int i = 0; i < mUidPolicy.size(); i++) { 102821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int uid = mUidPolicy.keyAt(i); 102921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int policy = mUidPolicy.valueAt(i); 103021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 1031497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // skip writing empty policies 1032497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (policy == POLICY_NONE) continue; 1033497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 103421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.startTag(null, TAG_UID_POLICY); 103521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeIntAttribute(out, ATTR_UID, uid); 103621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeIntAttribute(out, ATTR_POLICY, policy); 103721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.endTag(null, TAG_UID_POLICY); 103821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 103921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 104021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.endTag(null, TAG_POLICY_LIST); 104121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.endDocument(); 104221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 104321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mPolicyFile.finishWrite(fos); 104421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (IOException e) { 104521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (fos != null) { 104621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mPolicyFile.failWrite(fos); 104721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 104821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 104921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 105021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 1051d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey @Override 1052d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey public void setUidPolicy(int uid, int policy) { 105321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1054a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 1055497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (!isUidValidForPolicy(mContext, uid)) { 1056497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey throw new IllegalArgumentException("cannot apply policy to UID " + uid); 1057497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 1058497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 1059497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey setUidPolicyUnchecked(uid, policy, true); 1060497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 1061497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 1062497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private void setUidPolicyUnchecked(int uid, int policy, boolean persist) { 1063c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey final int oldPolicy; 1064a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 1065c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey oldPolicy = getUidPolicy(uid); 1066a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mUidPolicy.put(uid, policy); 1067c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 106821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // uid policy changed, recompute rules and persist policy. 106921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateRulesForUidLocked(uid); 1070497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (persist) { 1071497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey writePolicyLocked(); 1072497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 107321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 1074d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 1075d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1076d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey @Override 1077d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey public int getUidPolicy(int uid) { 107821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 107921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 1080a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 1081a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey return mUidPolicy.get(uid, POLICY_NONE); 1082a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 1083d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 1084d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1085c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey @Override 1086c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey public void registerListener(INetworkPolicyListener listener) { 10871a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey // TODO: create permission for observing network policy 10881a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 10891a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey 1090c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey mListeners.register(listener); 1091c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 10924414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey // TODO: consider dispatching existing rules to new listeners 1093c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey } 1094c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 1095c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey @Override 1096c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey public void unregisterListener(INetworkPolicyListener listener) { 10971a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey // TODO: create permission for observing network policy 10981a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 10991a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey 1100c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey mListeners.unregister(listener); 1101c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey } 1102c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 11031b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey @Override 110422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey public void setNetworkPolicies(NetworkPolicy[] policies) { 110521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 110621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 110721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey synchronized (mRulesLock) { 110822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mNetworkPolicy.clear(); 110922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey for (NetworkPolicy policy : policies) { 111041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkPolicy.put(policy.template, policy); 111122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 111221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 11138e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey updateNetworkEnabledLocked(); 111402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey updateNetworkRulesLocked(); 1115497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey updateNotificationsLocked(); 111621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writePolicyLocked(); 111721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 111821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 111921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 112021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey @Override 112122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey public NetworkPolicy[] getNetworkPolicies() { 112221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 112322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG); 112421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 112521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey synchronized (mRulesLock) { 112641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]); 112741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 112841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 112941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 113041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey @Override 113141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void snoozePolicy(NetworkTemplate template) { 113241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 113341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 11348e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long currentTime = currentTimeMillis(true); 113541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mRulesLock) { 113641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // find and snooze local policy that matches 113741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final NetworkPolicy policy = mNetworkPolicy.get(template); 113841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (policy == null) { 113941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalArgumentException("unable to find policy for " + template); 114041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 114141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 114241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey policy.lastSnooze = currentTime; 114341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 11448e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey updateNetworkEnabledLocked(); 114541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey updateNetworkRulesLocked(); 114641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey updateNotificationsLocked(); 114741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey writePolicyLocked(); 114821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 114921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 115021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 115121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey @Override 11524664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public void setRestrictBackground(boolean restrictBackground) { 11534664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 11544664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey 11554664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey synchronized (mRulesLock) { 11564664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey mRestrictBackground = restrictBackground; 11574664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey updateRulesForRestrictBackgroundLocked(); 11583a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey updateNotificationsLocked(); 1159f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey writePolicyLocked(); 11604664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 11614664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 11624664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey 11634664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey @Override 11644664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public boolean getRestrictBackground() { 11654664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 11664664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey 11674664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey synchronized (mRulesLock) { 11684664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey return mRestrictBackground; 11694664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 11704664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 11714664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey 1172f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) { 1173f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 1174f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey if (policy.template.matches(ident)) { 1175f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey return policy; 1176f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1177f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1178f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey return null; 1179f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1180f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1181f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey @Override 1182f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) { 1183f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 1184f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1185f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey // only returns usage summary, so we don't require caller to have 1186f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey // READ_NETWORK_USAGE_HISTORY. 1187f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final long token = Binder.clearCallingIdentity(); 1188f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey try { 1189f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey return getNetworkQuotaInfoUnchecked(state); 1190f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } finally { 1191f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey Binder.restoreCallingIdentity(token); 1192f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1193f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1194f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1195f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) { 1196f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); 1197f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1198f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final NetworkPolicy policy; 1199f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey synchronized (mRulesLock) { 1200f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey policy = findPolicyForNetworkLocked(ident); 1201f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1202f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1203f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey if (policy == null) { 1204f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey // missing policy means we can't derive useful quota info 1205f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey return null; 1206f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1207f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 12088e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long currentTime = currentTimeMillis(false); 1209f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1210b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // find total bytes used under policy 1211f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final long start = computeLastCycleBoundary(currentTime, policy); 1212f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final long end = currentTime; 12138e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long totalBytes = getTotalBytes(policy.template, start, end); 1214f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1215f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey // report soft and hard limits under policy 1216f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes 1217f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey : NetworkQuotaInfo.NO_LIMIT; 1218f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes 1219f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey : NetworkQuotaInfo.NO_LIMIT; 1220f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1221f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes); 1222f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1223f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 12244664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey @Override 12251b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 122675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey mContext.enforceCallingOrSelfPermission(DUMP, TAG); 12271b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 122841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final HashSet<String> argSet = new HashSet<String>(); 122941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey for (String arg : args) { 123041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey argSet.add(arg); 123141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 123241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 12331b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey synchronized (mRulesLock) { 123441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (argSet.contains("unsnooze")) { 123541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 123641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey policy.lastSnooze = SNOOZE_NEVER; 123741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 123841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey writePolicyLocked(); 123941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey fout.println("Wiped snooze timestamps"); 124041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey return; 124141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 124241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 12434664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey fout.print("Restrict background: "); fout.println(mRestrictBackground); 124421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey fout.println("Network policies:"); 124541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 124622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey fout.print(" "); fout.println(policy.toString()); 124721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 124821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 12491b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.println("Policy status for known UIDs:"); 12501b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 12511b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final SparseBooleanArray knownUids = new SparseBooleanArray(); 12521b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey collectKeys(mUidPolicy, knownUids); 12531b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey collectKeys(mUidForeground, knownUids); 12541b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey collectKeys(mUidRules, knownUids); 12551b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 12561b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int size = knownUids.size(); 12571b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey for (int i = 0; i < size; i++) { 12581b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int uid = knownUids.keyAt(i); 12591b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(" UID="); 12601b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(uid); 12611b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 12621b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(" policy="); 12631b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int policyIndex = mUidPolicy.indexOfKey(uid); 12641b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey if (policyIndex < 0) { 12651b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("UNKNOWN"); 12661b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } else { 12671b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey dumpPolicy(fout, mUidPolicy.valueAt(policyIndex)); 12681b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 12691b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 12701b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(" foreground="); 12711b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int foregroundIndex = mUidPidForeground.indexOfKey(uid); 12721b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey if (foregroundIndex < 0) { 12731b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("UNKNOWN"); 12741b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } else { 12751b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex)); 12761b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 12771b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 12781b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(" rules="); 12791b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int rulesIndex = mUidRules.indexOfKey(uid); 12801b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey if (rulesIndex < 0) { 12811b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("UNKNOWN"); 12821b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } else { 12831b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey dumpRules(fout, mUidRules.valueAt(rulesIndex)); 12841b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 12851b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 12861b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.println(); 12871b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 12881b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 12891b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 12909599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 12919599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 12929599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public boolean isUidForeground(int uid) { 1293497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1294497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 12959599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey synchronized (mRulesLock) { 12969599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey // only really in foreground when screen is also on 12979599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return mUidForeground.get(uid, false) && mScreenOn; 12989599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1299c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey } 1300c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 1301d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey /** 1302d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Foreground for PID changed; recompute foreground at UID level. If 130321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * changed, will trigger {@link #updateRulesForUidLocked(int)}. 1304d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */ 130521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void computeUidForegroundLocked(int uid) { 1306d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 1307d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1308d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey // current pid is dropping foreground; examine other pids 1309d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey boolean uidForeground = false; 1310d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey final int size = pidForeground.size(); 1311d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey for (int i = 0; i < size; i++) { 1312d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey if (pidForeground.valueAt(i)) { 1313d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey uidForeground = true; 1314d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey break; 1315d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 1316d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 1317d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1318d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey final boolean oldUidForeground = mUidForeground.get(uid, false); 1319d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey if (oldUidForeground != uidForeground) { 1320d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey // foreground changed, push updated rules 1321d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey mUidForeground.put(uid, uidForeground); 132221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateRulesForUidLocked(uid); 1323a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 1324a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 1325a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 1326a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private void updateScreenOn() { 1327a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 1328a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey try { 1329a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mScreenOn = mPowerManager.isScreenOn(); 1330a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } catch (RemoteException e) { 1331b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 1332a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 133321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateRulesForScreenLocked(); 1334d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 1335d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 1336d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1337a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey /** 1338a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey * Update rules that might be changed by {@link #mScreenOn} value. 1339a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey */ 134021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void updateRulesForScreenLocked() { 1341a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // only update rules for anyone with foreground activities 1342a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey final int size = mUidForeground.size(); 1343a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey for (int i = 0; i < size; i++) { 1344a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey if (mUidForeground.valueAt(i)) { 1345a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey final int uid = mUidForeground.keyAt(i); 134621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateRulesForUidLocked(uid); 1347a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 1348a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 1349a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 1350a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 1351b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey /** 13524664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey * Update rules that might be changed by {@link #mRestrictBackground} value. 1353b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey */ 13544664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey private void updateRulesForRestrictBackgroundLocked() { 1355b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // update rules for all installed applications 1356b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final PackageManager pm = mContext.getPackageManager(); 1357b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final List<ApplicationInfo> apps = pm.getInstalledApplications(0); 1358b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey for (ApplicationInfo app : apps) { 1359b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey updateRulesForUidLocked(app.uid); 1360b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1361b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1362b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // and catch system UIDs 1363b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // TODO: keep in sync with android_filesystem_config.h 1364b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey for (int uid = 1000; uid <= 1025; uid++) { 1365b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey updateRulesForUidLocked(uid); 1366b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1367b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey for (int uid = 2000; uid <= 2002; uid++) { 1368b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey updateRulesForUidLocked(uid); 1369b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1370b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey for (int uid = 3000; uid <= 3007; uid++) { 1371b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey updateRulesForUidLocked(uid); 1372b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1373b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey for (int uid = 9998; uid <= 9999; uid++) { 1374b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey updateRulesForUidLocked(uid); 1375b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1376b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1377b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 137821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void updateRulesForUidLocked(int uid) { 1379d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey final int uidPolicy = getUidPolicy(uid); 13809599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final boolean uidForeground = isUidForeground(uid); 1381d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1382c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // derive active rules based on policy and active state 1383c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey int uidRules = RULE_ALLOW_ALL; 1384fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { 1385fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey // uid in background, and policy says to block metered data 1386fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey uidRules = RULE_REJECT_METERED; 1387d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 13884664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey if (!uidForeground && mRestrictBackground) { 1389b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // uid in background, and global background disabled 1390b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey uidRules = RULE_REJECT_METERED; 1391b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1392d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1393c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // TODO: only dispatch when rules actually change 1394c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 1395350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (uidRules == RULE_ALLOW_ALL) { 1396350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey mUidRules.delete(uid); 1397350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } else { 1398350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey mUidRules.put(uid, uidRules); 1399350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 1400c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 1401fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0; 140250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma setUidNetworkRules(uid, rejectMetered); 1403497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 1404c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // dispatch changed rule to existing listeners 14054414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget(); 1406b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey 1407b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey try { 1408b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey // adjust stats accounting based on foreground status 1409b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey mNetworkStats.setUidForeground(uid, uidForeground); 1410b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } catch (RemoteException e) { 1411b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 1412b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 14134414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14144414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 14154414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey private Handler.Callback mHandlerCallback = new Handler.Callback() { 14164414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey /** {@inheritDoc} */ 14174414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey public boolean handleMessage(Message msg) { 14184414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey switch (msg.what) { 14194414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey case MSG_RULES_CHANGED: { 14204414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int uid = msg.arg1; 14214414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int uidRules = msg.arg2; 14224414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int length = mListeners.beginBroadcast(); 14234414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey for (int i = 0; i < length; i++) { 14244414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 14254414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey if (listener != null) { 14264414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey try { 14274414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey listener.onUidRulesChanged(uid, uidRules); 14284414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } catch (RemoteException e) { 14294414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14304414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14314414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14324414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mListeners.finishBroadcast(); 14334414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey return true; 14344414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14354414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey case MSG_METERED_IFACES_CHANGED: { 14364414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final String[] meteredIfaces = (String[]) msg.obj; 14374414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int length = mListeners.beginBroadcast(); 14384414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey for (int i = 0; i < length; i++) { 14394414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 14404414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey if (listener != null) { 14414414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey try { 14424414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey listener.onMeteredIfacesChanged(meteredIfaces); 14434414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } catch (RemoteException e) { 14444414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14454414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14464414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14474414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mListeners.finishBroadcast(); 14484414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey return true; 14494414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14506f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey case MSG_FOREGROUND_ACTIVITIES_CHANGED: { 14516f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey final int pid = msg.arg1; 14526f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey final int uid = msg.arg2; 14536f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey final boolean foregroundActivities = (Boolean) msg.obj; 14546f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey 14556f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey synchronized (mRulesLock) { 14566f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey // because a uid can have multiple pids running inside, we need to 14576f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey // remember all pid states and summarize foreground at uid level. 14586f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey 14596f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey // record foreground for this specific pid 14606f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 14616f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey if (pidForeground == null) { 14626f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey pidForeground = new SparseBooleanArray(2); 14636f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey mUidPidForeground.put(uid, pidForeground); 14646f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey } 14656f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey pidForeground.put(pid, foregroundActivities); 14666f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey computeUidForegroundLocked(uid); 14676f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey } 14686f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey return true; 14696f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey } 14706f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey case MSG_PROCESS_DIED: { 14716f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey final int pid = msg.arg1; 14726f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey final int uid = msg.arg2; 14736f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey 14746f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey synchronized (mRulesLock) { 14756f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey // clear records and recompute, when they exist 14766f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 14776f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey if (pidForeground != null) { 14786f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey pidForeground.delete(pid); 14796f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey computeUidForegroundLocked(uid); 14806f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey } 14816f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey } 14826f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey return true; 14836f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey } 14844414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey default: { 14854414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey return false; 1486af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey } 1487af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey } 1488af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey } 14894414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey }; 149022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 149141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private void setInterfaceQuota(String iface, long quotaBytes) { 1492b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 149341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkManager.setInterfaceQuota(iface, quotaBytes); 1494b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (IllegalStateException e) { 1495b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey Log.wtf(TAG, "problem setting interface quota", e); 1496b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (RemoteException e) { 1497b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 1498b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1499b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1500b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1501b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey private void removeInterfaceQuota(String iface) { 1502b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 150341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkManager.removeInterfaceQuota(iface); 1504b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (IllegalStateException e) { 1505b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey Log.wtf(TAG, "problem removing interface quota", e); 1506b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (RemoteException e) { 1507b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 150841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 150941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 151041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 1511b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1512b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 151341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces); 1514b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (IllegalStateException e) { 1515b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey Log.wtf(TAG, "problem setting uid rules", e); 1516b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (RemoteException e) { 1517b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 1518b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1519b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1520b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 15218e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey /** 15228e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}, 15238e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * dispatching only when actually changed. 15248e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey */ 15258e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private void setPolicyDataEnable(int networkType, boolean enabled) { 15268e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey synchronized (mActiveNetworkEnabled) { 15278e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final boolean prevEnabled = mActiveNetworkEnabled.get(networkType, true); 15288e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (prevEnabled == enabled) return; 15298e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 15308e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey try { 15318e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey mConnManager.setPolicyDataEnable(networkType, enabled); 15328e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } catch (RemoteException e) { 1533b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 15348e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 15358e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 15368e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey mActiveNetworkEnabled.put(networkType, enabled); 15378e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 15388e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 15398e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 154022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private String getActiveSubscriberId() { 154122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService( 154222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey Context.TELEPHONY_SERVICE); 154322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey return telephony.getSubscriberId(); 154422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 154522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 15468e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private long getTotalBytes(NetworkTemplate template, long start, long end) { 15478e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey try { 154850e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey return mNetworkStats.getSummaryForNetwork(template, start, end).getTotalBytes(); 15498e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } catch (RemoteException e) { 1550b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 1551b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey return 0; 15528e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 15538e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 15548e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 15558e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private long currentTimeMillis(boolean allowRefresh) { 15568e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // try refreshing time source when stale 15578e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE && allowRefresh) { 15588e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey mTime.forceRefresh(); 15598e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 15608e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 15618e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis(); 15628e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 15638e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 15643a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private static Intent buildAllowBackgroundDataIntent() { 15653a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey return new Intent(ACTION_ALLOW_BACKGROUND); 15663a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 15673a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 156841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) { 156941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final Intent intent = new Intent(); 157041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey intent.setComponent(new ComponentName( 157141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity")); 157241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 157341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); 157441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey return intent; 157541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 157641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 157741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private static Intent buildViewDataUsageIntent(NetworkTemplate template) { 157841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final Intent intent = new Intent(); 157941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey intent.setComponent(new ComponentName( 158041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity")); 158141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 158241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); 158341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey return intent; 158441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 158541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 1586163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey // @VisibleForTesting 1587163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey public void addIdleHandler(IdleHandler handler) { 1588163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey mHandler.getLooper().getQueue().addIdleHandler(handler); 1589163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 1590163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 15911b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey private static void collectKeys(SparseIntArray source, SparseBooleanArray target) { 15921b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int size = source.size(); 15931b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey for (int i = 0; i < size; i++) { 15941b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey target.put(source.keyAt(i), true); 15951b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 15961b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 15971b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 15981b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) { 15991b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int size = source.size(); 16001b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey for (int i = 0; i < size; i++) { 16011b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey target.put(source.keyAt(i), true); 16021b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 16031b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 16041b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 16051b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) { 16061b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("["); 16071b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int size = value.size(); 16081b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey for (int i = 0; i < size; i++) { 16091b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(value.keyAt(i) + "=" + value.valueAt(i)); 16101b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey if (i < size - 1) fout.print(","); 16111b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 16121b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("]"); 16131b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 161421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 16154664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static class XmlUtils { 16164664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static int readIntAttribute(XmlPullParser in, String name) throws IOException { 16174664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey final String value = in.getAttributeValue(null, name); 16184664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey try { 16194664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey return Integer.parseInt(value); 16204664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } catch (NumberFormatException e) { 16214664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 16224664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 162321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 162421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 16254664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static void writeIntAttribute(XmlSerializer out, String name, int value) 16264664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey throws IOException { 16274664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey out.attribute(null, name, Integer.toString(value)); 162821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 162921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 16304664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static long readLongAttribute(XmlPullParser in, String name) throws IOException { 16314664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey final String value = in.getAttributeValue(null, name); 16324664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey try { 16334664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey return Long.parseLong(value); 16344664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } catch (NumberFormatException e) { 16354664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey throw new ProtocolException("problem parsing " + name + "=" + value + " as long"); 16364664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 16374664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 163821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 16394664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static void writeLongAttribute(XmlSerializer out, String name, long value) 16404664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey throws IOException { 16414664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey out.attribute(null, name, Long.toString(value)); 16424664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 164321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 16444664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static boolean readBooleanAttribute(XmlPullParser in, String name) { 16454664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey final String value = in.getAttributeValue(null, name); 16464664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey return Boolean.parseBoolean(value); 16474664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 16484664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey 16494664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value) 16504664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey throws IOException { 16514664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey out.attribute(null, name, Boolean.toString(value)); 16524664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 16534664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 1654d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey} 1655