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; 1937e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey private static final int MSG_LIMIT_REACHED = 5; 1944414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 19575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final Context mContext; 19675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final IActivityManager mActivityManager; 19775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final IPowerManager mPowerManager; 19875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final INetworkStatsService mNetworkStats; 19941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private final INetworkManagementService mNetworkManager; 20021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private final TrustedTime mTime; 20121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 20221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private IConnectivityManager mConnManager; 203497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private INotificationManager mNotifManager; 204a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 20575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private final Object mRulesLock = new Object(); 206a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 2073a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private volatile boolean mScreenOn; 2083a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private volatile boolean mRestrictBackground; 209d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 2108e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private final boolean mSuppressDefaultPolicy; 2118e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 21241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Defined network policies. */ 21341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap(); 21441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Currently active network rules for ifaces. */ 21502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap(); 21622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 21741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Defined UID policies. */ 218a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private SparseIntArray mUidPolicy = new SparseIntArray(); 21941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Currently derived rules for each UID. */ 220c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey private SparseIntArray mUidRules = new SparseIntArray(); 221d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 222fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey /** Set of ifaces that are metered. */ 223fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey private HashSet<String> mMeteredIfaces = Sets.newHashSet(); 22441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Set of over-limit templates that have been notified. */ 22541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet(); 226fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey 2278e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey /** Set of currently active {@link Notification} tags. */ 2288e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private HashSet<String> mActiveNotifs = Sets.newHashSet(); 2298e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 230d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey /** Foreground at both UID and PID granularity. */ 231a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private SparseBooleanArray mUidForeground = new SparseBooleanArray(); 232a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray< 233a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey SparseBooleanArray>(); 234d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 235c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList< 236c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey INetworkPolicyListener>(); 237c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 23821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private final HandlerThread mHandlerThread; 23921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private final Handler mHandler; 24021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 24121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private final AtomicFile mPolicyFile; 242d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 243c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // TODO: keep whitelist of system-critical services that should never have 244c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // rules enforced, such as system, phone, and radio UIDs. 245c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 24641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: migrate notifications to SystemUI 24741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 24875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 24950fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma IPowerManager powerManager, INetworkStatsService networkStats, 25050fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma INetworkManagementService networkManagement) { 251b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey this(context, activityManager, powerManager, networkStats, networkManagement, 2528e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey NtpTrustedTime.getInstance(context), getSystemDir(), false); 25321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 25421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 25521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private static File getSystemDir() { 25621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey return new File(Environment.getDataDirectory(), "system"); 25721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 25821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 25921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 26050fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma IPowerManager powerManager, INetworkStatsService networkStats, 2618e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey INetworkManagementService networkManagement, TrustedTime time, File systemDir, 2628e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey boolean suppressDefaultPolicy) { 263a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mContext = checkNotNull(context, "missing context"); 264a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mActivityManager = checkNotNull(activityManager, "missing activityManager"); 265a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mPowerManager = checkNotNull(powerManager, "missing powerManager"); 26675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey mNetworkStats = checkNotNull(networkStats, "missing networkStats"); 26741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkManager = checkNotNull(networkManagement, "missing networkManagement"); 26821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mTime = checkNotNull(time, "missing TrustedTime"); 26921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 27021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mHandlerThread = new HandlerThread(TAG); 27121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mHandlerThread.start(); 2724414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback); 27321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 2748e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey mSuppressDefaultPolicy = suppressDefaultPolicy; 2758e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 27621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); 27721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 27821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 27921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey public void bindConnectivityManager(IConnectivityManager connManager) { 28021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mConnManager = checkNotNull(connManager, "missing IConnectivityManager"); 281a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 282d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 283497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey public void bindNotificationManager(INotificationManager notifManager) { 284497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mNotifManager = checkNotNull(notifManager, "missing INotificationManager"); 285497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 286497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 287a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey public void systemReady() { 28821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey synchronized (mRulesLock) { 28921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // read policy from disk 29021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey readPolicyLocked(); 2914664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey 2924664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey if (mRestrictBackground) { 2934664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey updateRulesForRestrictBackgroundLocked(); 2943a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey updateNotificationsLocked(); 2954664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 29621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 297d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 298a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey updateScreenOn(); 299d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 300a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey try { 301a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mActivityManager.registerProcessObserver(mProcessObserver); 30241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkManager.registerObserver(mAlertObserver); 30341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } catch (RemoteException e) { 304b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; both services live in system_server 30541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 30641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 307a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // TODO: traverse existing processes to know foreground state, or have 308a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // activitymanager dispatch current state when new observer attached. 309d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 310a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey final IntentFilter screenFilter = new IntentFilter(); 311a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey screenFilter.addAction(Intent.ACTION_SCREEN_ON); 312a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey screenFilter.addAction(Intent.ACTION_SCREEN_OFF); 31341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler); 314d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 31521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // watch for network interfaces to be claimed 316961e30458319cfd50e1892ba7dd14a1d0ebe4cc7Jeff Sharkey final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE); 317b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); 318b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey 31902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // listen for package/uid changes to update policy 32002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey final IntentFilter packageFilter = new IntentFilter(); 32102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey packageFilter.addAction(ACTION_PACKAGE_ADDED); 32202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey packageFilter.addAction(ACTION_UID_REMOVED); 32302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler); 32421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 325b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // listen for stats update events 326497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED); 327497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mContext.registerReceiver( 328497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler); 329497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 3303a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey // listen for restrict background changes from notifications 3313a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND); 3323a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler); 3333a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 334a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 335d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 336a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private IProcessObserver mProcessObserver = new IProcessObserver.Stub() { 337a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey @Override 338a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) { 3396f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey mHandler.obtainMessage(MSG_FOREGROUND_ACTIVITIES_CHANGED, 3406f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey pid, uid, foregroundActivities).sendToTarget(); 341d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 342d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 343a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey @Override 344a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey public void onProcessDied(int pid, int uid) { 3456f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey mHandler.obtainMessage(MSG_PROCESS_DIED, pid, uid).sendToTarget(); 346a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 347a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey }; 348a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 349a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { 350a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey @Override 351a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey public void onReceive(Context context, Intent intent) { 352a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 353a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // screen-related broadcasts are protected by system, no need 354a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // for permissions check. 355a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey updateScreenOn(); 356a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 357a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 358a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey }; 359d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 36002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() { 361b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey @Override 362b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey public void onReceive(Context context, Intent intent) { 36302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // on background handler thread, and PACKAGE_ADDED and UID_REMOVED 36402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // are protected broadcasts. 36502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey 36602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey final String action = intent.getAction(); 367b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey final int uid = intent.getIntExtra(EXTRA_UID, 0); 368b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey synchronized (mRulesLock) { 36902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey if (ACTION_PACKAGE_ADDED.equals(action)) { 37002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // update rules for UID, since it might be subject to 37102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // global background data policy. 37202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid); 37302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey updateRulesForUidLocked(uid); 37402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey 37502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey } else if (ACTION_UID_REMOVED.equals(action)) { 37602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // remove any policy and update rules to clean up. 37702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid); 37802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey mUidPolicy.delete(uid); 37902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey updateRulesForUidLocked(uid); 38002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey writePolicyLocked(); 38102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey } 382b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey } 383b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey } 384b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey }; 385b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey 38621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey /** 387497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Receiver that watches for {@link INetworkStatsService} updates, which we 388497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * use to check against {@link NetworkPolicy#warningBytes}. 389497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 390497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() { 391497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey @Override 392497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey public void onReceive(Context context, Intent intent) { 393497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // on background handler thread, and verified 394497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // READ_NETWORK_USAGE_HISTORY permission above. 395497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 396684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey maybeRefreshTrustedTime(); 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 4277e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey if (!LIMIT_GLOBAL_ALERT.equals(limitName)) { 4287e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey mHandler.obtainMessage(MSG_LIMIT_REACHED, iface).sendToTarget(); 42941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 43041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 43141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey }; 43241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 43341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** 434497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Check {@link NetworkPolicy} against current {@link INetworkStatsService} 435497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * to show visible notifications as needed. 436497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 437497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private void updateNotificationsLocked() { 438497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (LOGV) Slog.v(TAG, "updateNotificationsLocked()"); 439497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 4408e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // keep track of previously active notifications 4418e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final HashSet<String> beforeNotifs = Sets.newHashSet(); 4428e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey beforeNotifs.addAll(mActiveNotifs); 4438e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey mActiveNotifs.clear(); 444497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 445497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // TODO: when switching to kernel notifications, compute next future 446497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // cycle boundary to recompute notifications. 447497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 44802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // examine stats for each active policy 449684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey final long currentTime = currentTimeMillis(); 4508e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 4518e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // ignore policies that aren't relevant to user 4528e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (!isTemplateRelevant(policy.template)) continue; 4538e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 454497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final long start = computeLastCycleBoundary(currentTime, policy); 455497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final long end = currentTime; 4568e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long totalBytes = getTotalBytes(policy.template, start, end); 457497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 45850e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey if (policy.isOverLimit(totalBytes)) { 45941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (policy.lastSnooze >= start) { 46041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes); 46141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } else { 46241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey enqueueNotification(policy, TYPE_LIMIT, totalBytes); 46341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey notifyOverLimitLocked(policy.template); 46441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 46541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 466497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } else { 46741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey notifyUnderLimitLocked(policy.template); 468497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 46941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) { 47041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey enqueueNotification(policy, TYPE_WARNING, totalBytes); 471497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 472497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 47302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey } 47402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey 4753a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey // ongoing notification when restricting background data 4763a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey if (mRestrictBackground) { 4773a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND); 4783a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 4798e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 4808e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // cancel stale notifications that we didn't renew above 4818e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey for (String tag : beforeNotifs) { 4828e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (!mActiveNotifs.contains(tag)) { 4838e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey cancelNotification(tag); 4848e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 4858e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 4868e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 4878e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 4888e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey /** 4898e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * Test if given {@link NetworkTemplate} is relevant to user based on 4908e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * current device state, such as when {@link #getActiveSubscriberId()} 4918e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * matches. This is regardless of data connection status. 4928e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey */ 4938e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private boolean isTemplateRelevant(NetworkTemplate template) { 4948e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey switch (template.getMatchRule()) { 4958e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_3G_LOWER: 4968e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_4G: 4978e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_ALL: 4988e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // mobile templates are relevant when subscriberid is active 4998e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey return Objects.equal(getActiveSubscriberId(), template.getSubscriberId()); 5008e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 5018e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey return true; 502497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 503497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 504497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 50541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey * Notify that given {@link NetworkTemplate} is over 50641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user. 50741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey */ 50841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private void notifyOverLimitLocked(NetworkTemplate template) { 50941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mOverLimitNotified.contains(template)) { 51041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.startActivity(buildNetworkOverLimitIntent(template)); 51141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mOverLimitNotified.add(template); 51241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 51341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 51441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 51541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private void notifyUnderLimitLocked(NetworkTemplate template) { 51641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mOverLimitNotified.remove(template); 51741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 51841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 51941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** 520497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Build unique tag that identifies an active {@link NetworkPolicy} 521497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * notification of a specific type, like {@link #TYPE_LIMIT}. 522497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 523497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private String buildNotificationTag(NetworkPolicy policy, int type) { 5241b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey return TAG + ":" + policy.template.hashCode() + ":" + type; 525497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 526497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 527497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 528497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * Show notification for combined {@link NetworkPolicy} and specific type, 529497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey * like {@link #TYPE_LIMIT}. Okay to call multiple times. 530497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey */ 53141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) { 532497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String tag = buildNotificationTag(policy, type); 533497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final Notification.Builder builder = new Notification.Builder(mContext); 534497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setOnlyAlertOnce(true); 535497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setOngoing(true); 536497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 537497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final Resources res = mContext.getResources(); 538497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey switch (type) { 539497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey case TYPE_WARNING: { 54041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final CharSequence title = res.getText(R.string.data_usage_warning_title); 5418ca953da93eb8679574abba535f75f72d50016f2Jeff Sharkey final CharSequence body = res.getString(R.string.data_usage_warning_body); 542497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 54350e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey builder.setSmallIcon(R.drawable.stat_notify_error); 544497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setTicker(title); 545497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setContentTitle(title); 546497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setContentText(body); 54714711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey 54841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final Intent intent = buildViewDataUsageIntent(policy.template); 54914711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey builder.setContentIntent(PendingIntent.getActivity( 55014711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 551497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 552497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 553497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey case TYPE_LIMIT: { 55441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final CharSequence body = res.getText(R.string.data_usage_limit_body); 55541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 55641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final CharSequence title; 5571b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey switch (policy.template.getMatchRule()) { 5581b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey case MATCH_MOBILE_3G_LOWER: 55941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey title = res.getText(R.string.data_usage_3g_limit_title); 560497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 5611b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey case MATCH_MOBILE_4G: 56241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey title = res.getText(R.string.data_usage_4g_limit_title); 563497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 5648e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_ALL: 56541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey title = res.getText(R.string.data_usage_mobile_limit_title); 566497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 5678e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_WIFI: 5688e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey title = res.getText(R.string.data_usage_wifi_limit_title); 5698e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 5708e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey default: 5718e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey title = null; 5728e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 573497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 574497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 57550e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey builder.setSmallIcon(R.drawable.stat_notify_disabled); 576497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setTicker(title); 577497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setContentTitle(title); 578497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey builder.setContentText(body); 57914711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey 58041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final Intent intent = buildNetworkOverLimitIntent(policy.template); 58141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey builder.setContentIntent(PendingIntent.getActivity( 58241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 58341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey break; 58441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 58541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey case TYPE_LIMIT_SNOOZED: { 58641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final long overBytes = totalBytes - policy.limitBytes; 58741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body, 58841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey Formatter.formatFileSize(mContext, overBytes)); 58941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 59041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final CharSequence title; 59141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey switch (policy.template.getMatchRule()) { 59241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey case MATCH_MOBILE_3G_LOWER: 59341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey title = res.getText(R.string.data_usage_3g_limit_snoozed_title); 59441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey break; 59541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey case MATCH_MOBILE_4G: 59641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey title = res.getText(R.string.data_usage_4g_limit_snoozed_title); 59741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey break; 5988e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_ALL: 59941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey title = res.getText(R.string.data_usage_mobile_limit_snoozed_title); 60041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey break; 6018e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_WIFI: 6028e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey title = res.getText(R.string.data_usage_wifi_limit_snoozed_title); 6038e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 6048e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey default: 6058e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey title = null; 6068e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 60741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 60841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 60950e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey builder.setSmallIcon(R.drawable.stat_notify_error); 61041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey builder.setTicker(title); 61141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey builder.setContentTitle(title); 61241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey builder.setContentText(body); 61341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 61441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final Intent intent = buildViewDataUsageIntent(policy.template); 61514711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey builder.setContentIntent(PendingIntent.getActivity( 61614711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 617497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey break; 618497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 619497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 620497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 621497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // TODO: move to NotificationManager once we can mock it 622497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey try { 623497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String packageName = mContext.getPackageName(); 624497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final int[] idReceived = new int[1]; 625497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mNotifManager.enqueueNotificationWithTag( 626497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey packageName, tag, 0x0, builder.getNotification(), idReceived); 6278e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey mActiveNotifs.add(tag); 628497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } catch (RemoteException e) { 629b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 630497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 631497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 632497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 633497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 6343a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey * Show ongoing notification to reflect that {@link #mRestrictBackground} 6353a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey * has been enabled. 6363a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey */ 6373a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private void enqueueRestrictedNotification(String tag) { 6383a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final Resources res = mContext.getResources(); 6393a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final Notification.Builder builder = new Notification.Builder(mContext); 6403a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 6413a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final CharSequence title = res.getText(R.string.data_usage_restricted_title); 6423a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final CharSequence body = res.getString(R.string.data_usage_restricted_body); 6433a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 6443a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey builder.setOnlyAlertOnce(true); 6453a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey builder.setOngoing(true); 64650e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey builder.setSmallIcon(R.drawable.stat_notify_error); 6473a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey builder.setTicker(title); 6483a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey builder.setContentTitle(title); 6493a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey builder.setContentText(body); 6503a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 6513a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final Intent intent = buildAllowBackgroundDataIntent(); 6523a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey builder.setContentIntent( 6533a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 6543a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 6553a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey // TODO: move to NotificationManager once we can mock it 6563a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey try { 6573a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final String packageName = mContext.getPackageName(); 6583a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final int[] idReceived = new int[1]; 6593a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mNotifManager.enqueueNotificationWithTag(packageName, tag, 6603a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 0x0, builder.getNotification(), idReceived); 6618e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey mActiveNotifs.add(tag); 6623a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } catch (RemoteException e) { 663b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 6643a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 6653a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 6663a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 6673a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private void cancelNotification(String tag) { 668497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // TODO: move to NotificationManager once we can mock it 669497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey try { 670497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey final String packageName = mContext.getPackageName(); 6713a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mNotifManager.cancelNotificationWithTag( 6723a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey packageName, tag, 0x0); 673497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } catch (RemoteException e) { 674b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 675497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 676497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 677497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 678497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey /** 67921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * Receiver that watches for {@link IConnectivityManager} to claim network 68022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey * interfaces. Used to apply {@link NetworkPolicy} to matching networks. 68121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey */ 682b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey private BroadcastReceiver mConnReceiver = new BroadcastReceiver() { 68321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey @Override 68421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey public void onReceive(Context context, Intent intent) { 68521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // on background handler thread, and verified CONNECTIVITY_INTERNAL 68621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // permission above. 687684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey 688684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey maybeRefreshTrustedTime(); 68921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey synchronized (mRulesLock) { 69022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey ensureActiveMobilePolicyLocked(); 6918e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey updateNetworkEnabledLocked(); 69202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey updateNetworkRulesLocked(); 69302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey updateNotificationsLocked(); 69421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 69521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 69621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey }; 69721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 69821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey /** 6998e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * Proactively control network data connections when they exceed 7008e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * {@link NetworkPolicy#limitBytes}. 7018e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey */ 7028e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private void updateNetworkEnabledLocked() { 7038e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()"); 7048e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 7058e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // TODO: reset any policy-disabled networks when any policy is removed 7068e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // completely, which is currently rare case. 7078e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 708684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey final long currentTime = currentTimeMillis(); 7098e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 7108e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // shortcut when policy has no limit 7118e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (policy.limitBytes == LIMIT_DISABLED) { 7128e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey setNetworkTemplateEnabled(policy.template, true); 7138e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey continue; 7148e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 7158e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 7168e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long start = computeLastCycleBoundary(currentTime, policy); 7178e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long end = currentTime; 7188e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long totalBytes = getTotalBytes(policy.template, start, end); 7198e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 7208e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // disable data connection when over limit and not snoozed 72150e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey final boolean overLimit = policy.isOverLimit(totalBytes) && policy.lastSnooze < start; 7228e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey final boolean enabled = !overLimit; 7238e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey 7248e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey setNetworkTemplateEnabled(policy.template, enabled); 7258e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 7268e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 7278e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 7288e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey /** 7298e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)} 7308e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * for the given {@link NetworkTemplate}. 7318e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey */ 7328e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) { 7338e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey switch (template.getMatchRule()) { 7348e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_3G_LOWER: 7358e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_4G: 7368e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_MOBILE_ALL: 7378e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // TODO: offer more granular control over radio states once 7388e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // 4965893 is available. 7398e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (Objects.equal(getActiveSubscriberId(), template.getSubscriberId())) { 7408e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey setPolicyDataEnable(TYPE_MOBILE, enabled); 7418e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey setPolicyDataEnable(TYPE_WIMAX, enabled); 7428e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 7438e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 7448e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_WIFI: 7458e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey setPolicyDataEnable(TYPE_WIFI, enabled); 7468e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 7478e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey case MATCH_ETHERNET: 7488e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey setPolicyDataEnable(TYPE_ETHERNET, enabled); 7498e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey break; 7508e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey default: 7518e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey throw new IllegalArgumentException("unexpected template"); 7528e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 7538e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 7548e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 7558e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey /** 75621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * Examine all connected {@link NetworkState}, looking for 75721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * {@link NetworkPolicy} that need to be enforced. When matches found, set 75821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * remaining quota based on usage cycle and historical stats. 75921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey */ 76002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey private void updateNetworkRulesLocked() { 76122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); 76221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 76321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final NetworkState[] states; 76421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey try { 76521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey states = mConnManager.getAllNetworkState(); 76621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (RemoteException e) { 767b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 76821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey return; 76921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 77021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 77121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // first, derive identity for all connected networks, which can be used 77221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // to match against templates. 77321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final HashMap<NetworkIdentity, String> networks = Maps.newHashMap(); 77421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey for (NetworkState state : states) { 77521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // stash identity and iface away for later use 77621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (state.networkInfo.isConnected()) { 77721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String iface = state.linkProperties.getInterfaceName(); 77821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); 77921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey networks.put(ident, iface); 78021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 78121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 78221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 78321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // build list of rules and ifaces to enforce them against 78402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey mNetworkRules.clear(); 78521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final ArrayList<String> ifaceList = Lists.newArrayList(); 78641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 78721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 78821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // collect all active ifaces that match this template 78921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey ifaceList.clear(); 79047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey for (Map.Entry<NetworkIdentity, String> entry : networks.entrySet()) { 79147eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey final NetworkIdentity ident = entry.getKey(); 7921b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey if (policy.template.matches(ident)) { 79347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey final String iface = entry.getValue(); 79421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey ifaceList.add(iface); 79521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 79621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 79721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 79821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (ifaceList.size() > 0) { 79921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]); 80002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey mNetworkRules.put(policy, ifaces); 80121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 80221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 80321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 804b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final HashSet<String> newMeteredIfaces = Sets.newHashSet(); 805fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey 80621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // apply each policy that we found ifaces for; compute remaining data 80721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // based on current cycle and historical stats, and push to kernel. 808684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey final long currentTime = currentTimeMillis(); 80902e21d6a5b5117d494777a36783909854854f751Jeff Sharkey for (NetworkPolicy policy : mNetworkRules.keySet()) { 81002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey final String[] ifaces = mNetworkRules.get(policy); 81121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 81221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long start = computeLastCycleBoundary(currentTime, policy); 81321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long end = currentTime; 8148e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long totalBytes = getTotalBytes(policy.template, start, end); 81521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 81621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (LOGD) { 81721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces " 81822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey + Arrays.toString(ifaces)); 81922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 82022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 82141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED; 8223a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey if (hasLimit) { 8238e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long quotaBytes; 8248e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (policy.lastSnooze >= start) { 8258e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // snoozing past quota, but we still need to restrict apps, 8268e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // so push really high quota. 8278e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey quotaBytes = Long.MAX_VALUE; 8288e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } else { 8298e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // remaining "quota" bytes are based on total usage in 8308e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // current cycle. kernel doesn't like 0-byte rules, so we 8318e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey // set 1-byte quota and disable the radio later. 8328e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey quotaBytes = Math.max(1, policy.limitBytes - totalBytes); 8338e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 83450fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma 835b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (ifaces.length > 1) { 836b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // TODO: switch to shared quota once NMS supports 837b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey Slog.w(TAG, "shared quota unsupported; generating rule for each iface"); 838b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 839fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey 840fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey for (String iface : ifaces) { 841b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey removeInterfaceQuota(iface); 8428e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey setInterfaceQuota(iface, quotaBytes); 8438e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey newMeteredIfaces.add(iface); 84441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 84541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 84622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 847fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey 848b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // remove quota on any trailing interfaces 849b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey for (String iface : mMeteredIfaces) { 850b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (!newMeteredIfaces.contains(iface)) { 851b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey removeInterfaceQuota(iface); 85250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 85350fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 854b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mMeteredIfaces = newMeteredIfaces; 855b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 856b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]); 857b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget(); 85850fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 85950fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma 86022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey /** 86122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we 86222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey * have at least a default mobile policy defined. 86322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey */ 86422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private void ensureActiveMobilePolicyLocked() { 86522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()"); 8668e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey if (mSuppressDefaultPolicy) return; 8678e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 86822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final String subscriberId = getActiveSubscriberId(); 8691b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final NetworkIdentity probeIdent = new NetworkIdentity( 8705dc0c26cffbbc62ff84f9f4c8a451e68e2c05d2dJeff Sharkey TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false); 87122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 87222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey // examine to see if any policy is defined for active mobile 87322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey boolean mobileDefined = false; 87441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 8751b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey if (policy.template.matches(probeIdent)) { 87622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mobileDefined = true; 87721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 87822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 87921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 88022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (!mobileDefined) { 88122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey Slog.i(TAG, "no policy for active mobile network; generating default policy"); 88221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 88302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey // build default mobile policy, and assume usage cycle starts today 88402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey final long warningBytes = mContext.getResources().getInteger( 88502e21d6a5b5117d494777a36783909854854f751Jeff Sharkey com.android.internal.R.integer.config_networkPolicyDefaultWarning) 88602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey * MB_IN_BYTES; 88722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 88822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final Time time = new Time(Time.TIMEZONE_UTC); 88922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey time.setToNow(); 89022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final int cycleDay = time.monthDay; 89122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 8924e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey final NetworkTemplate template = buildTemplateMobileAll(subscriberId); 89341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkPolicy.put(template, new NetworkPolicy( 89441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey template, cycleDay, warningBytes, LIMIT_DISABLED, SNOOZE_NEVER)); 895fcc79771f092f34505b1accb80365cbcaa379667Jeff Sharkey writePolicyLocked(); 89621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 89721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 89821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 89921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void readPolicyLocked() { 90022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (LOGV) Slog.v(TAG, "readPolicyLocked()"); 90121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 90221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // clear any existing policy and read from disk 90322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mNetworkPolicy.clear(); 90421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mUidPolicy.clear(); 90521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 90621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey FileInputStream fis = null; 90721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey try { 90821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey fis = mPolicyFile.openRead(); 90921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final XmlPullParser in = Xml.newPullParser(); 91021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey in.setInput(fis, null); 91121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 91221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey int type; 91341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey int version = VERSION_INIT; 91421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey while ((type = in.next()) != END_DOCUMENT) { 91521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String tag = in.getName(); 91621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (type == START_TAG) { 91721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (TAG_POLICY_LIST.equals(tag)) { 91821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey version = readIntAttribute(in, ATTR_VERSION); 9194664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) { 9204664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey mRestrictBackground = readBooleanAttribute( 9214664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey in, ATTR_RESTRICT_BACKGROUND); 9224664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } else { 9233a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mRestrictBackground = false; 9244664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 92521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 92621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } else if (TAG_NETWORK_POLICY.equals(tag)) { 92721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE); 92821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID); 92921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY); 93021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES); 93121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES); 93241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final long lastSnooze; 93341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (version >= VERSION_ADDED_SNOOZE) { 93441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey lastSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE); 93541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } else { 93641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey lastSnooze = SNOOZE_NEVER; 93741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 93821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 9391b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final NetworkTemplate template = new NetworkTemplate( 9401b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey networkTemplate, subscriberId); 94141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkPolicy.put(template, new NetworkPolicy( 94241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey template, cycleDay, warningBytes, limitBytes, lastSnooze)); 94321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 94421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } else if (TAG_UID_POLICY.equals(tag)) { 94521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int uid = readIntAttribute(in, ATTR_UID); 94621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int policy = readIntAttribute(in, ATTR_POLICY); 94721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 948497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (isUidValidForPolicy(mContext, uid)) { 949497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey setUidPolicyUnchecked(uid, policy, false); 950497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } else { 951497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring"); 952497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 95321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 95421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 95521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 95621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 95721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (FileNotFoundException e) { 95821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // missing policy is okay, probably first boot 9593a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey upgradeLegacyBackgroundData(); 96021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (IOException e) { 961b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey Log.wtf(TAG, "problem reading network policy", e); 96221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (XmlPullParserException e) { 963b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey Log.wtf(TAG, "problem reading network policy", e); 96421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } finally { 96521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey IoUtils.closeQuietly(fis); 96621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 96721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 96821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 9693a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey /** 9703a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey * Upgrade legacy background data flags, notifying listeners of one last 9713a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey * change to always-true. 9723a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey */ 9733a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private void upgradeLegacyBackgroundData() { 9743a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mRestrictBackground = Settings.Secure.getInt( 9753a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1; 9763a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 9773a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey // kick off one last broadcast if restricted 9783a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey if (mRestrictBackground) { 9793a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey final Intent broadcast = new Intent( 9803a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED); 9813a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey mContext.sendBroadcast(broadcast); 9823a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 9833a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 9843a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 98521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void writePolicyLocked() { 98622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey if (LOGV) Slog.v(TAG, "writePolicyLocked()"); 98721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 98821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey FileOutputStream fos = null; 98921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey try { 99021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey fos = mPolicyFile.startWrite(); 99121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 99221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey XmlSerializer out = new FastXmlSerializer(); 99321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.setOutput(fos, "utf-8"); 99421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.startDocument(null, true); 99521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 99621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.startTag(null, TAG_POLICY_LIST); 9974664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_RESTRICT_BACKGROUND); 9984664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground); 99921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 100021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // write all known network policies 100141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 10021b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final NetworkTemplate template = policy.template; 10031b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 100421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.startTag(null, TAG_NETWORK_POLICY); 10051b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule()); 10061b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final String subscriberId = template.getSubscriberId(); 10071b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey if (subscriberId != null) { 10081b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId); 100921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 101021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay); 101121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes); 101221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes); 101341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey writeLongAttribute(out, ATTR_LAST_SNOOZE, policy.lastSnooze); 101421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.endTag(null, TAG_NETWORK_POLICY); 101521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 101621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 101721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // write all known uid policies 101821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey for (int i = 0; i < mUidPolicy.size(); i++) { 101921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int uid = mUidPolicy.keyAt(i); 102021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey final int policy = mUidPolicy.valueAt(i); 102121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 1022497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey // skip writing empty policies 1023497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (policy == POLICY_NONE) continue; 1024497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 102521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.startTag(null, TAG_UID_POLICY); 102621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeIntAttribute(out, ATTR_UID, uid); 102721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writeIntAttribute(out, ATTR_POLICY, policy); 102821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.endTag(null, TAG_UID_POLICY); 102921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 103021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 103121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.endTag(null, TAG_POLICY_LIST); 103221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey out.endDocument(); 103321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 103421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mPolicyFile.finishWrite(fos); 103521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } catch (IOException e) { 103621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey if (fos != null) { 103721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mPolicyFile.failWrite(fos); 103821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 103921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 104021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 104121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 1042d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey @Override 1043d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey public void setUidPolicy(int uid, int policy) { 104421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1045a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 1046497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (!isUidValidForPolicy(mContext, uid)) { 1047497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey throw new IllegalArgumentException("cannot apply policy to UID " + uid); 1048497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 1049497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 1050497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey setUidPolicyUnchecked(uid, policy, true); 1051497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 1052497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 1053497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey private void setUidPolicyUnchecked(int uid, int policy, boolean persist) { 1054c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey final int oldPolicy; 1055a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 1056c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey oldPolicy = getUidPolicy(uid); 1057a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mUidPolicy.put(uid, policy); 1058c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 105921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey // uid policy changed, recompute rules and persist policy. 106021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateRulesForUidLocked(uid); 1061497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey if (persist) { 1062497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey writePolicyLocked(); 1063497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey } 106421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 1065d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 1066d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1067d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey @Override 1068d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey public int getUidPolicy(int uid) { 106921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 107021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 1071a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 1072a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey return mUidPolicy.get(uid, POLICY_NONE); 1073a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 1074d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 1075d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1076c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey @Override 1077c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey public void registerListener(INetworkPolicyListener listener) { 10781a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey // TODO: create permission for observing network policy 10791a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 10801a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey 1081c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey mListeners.register(listener); 1082c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 10834414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey // TODO: consider dispatching existing rules to new listeners 1084c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey } 1085c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 1086c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey @Override 1087c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey public void unregisterListener(INetworkPolicyListener listener) { 10881a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey // TODO: create permission for observing network policy 10891a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 10901a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey 1091c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey mListeners.unregister(listener); 1092c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey } 1093c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 10941b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey @Override 109522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey public void setNetworkPolicies(NetworkPolicy[] policies) { 109621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 109721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 1098684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey maybeRefreshTrustedTime(); 109921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey synchronized (mRulesLock) { 110022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mNetworkPolicy.clear(); 110122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey for (NetworkPolicy policy : policies) { 110241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkPolicy.put(policy.template, policy); 110322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 110421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 11058e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey updateNetworkEnabledLocked(); 110602e21d6a5b5117d494777a36783909854854f751Jeff Sharkey updateNetworkRulesLocked(); 1107497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey updateNotificationsLocked(); 110821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey writePolicyLocked(); 110921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 111021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 111121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 111221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey @Override 111322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey public NetworkPolicy[] getNetworkPolicies() { 111421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 111522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG); 111621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 111721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey synchronized (mRulesLock) { 111841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]); 111941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 112041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 112141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 112241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey @Override 112341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void snoozePolicy(NetworkTemplate template) { 112441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 112541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 1126684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey maybeRefreshTrustedTime(); 1127684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey final long currentTime = currentTimeMillis(); 112841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mRulesLock) { 112941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // find and snooze local policy that matches 113041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final NetworkPolicy policy = mNetworkPolicy.get(template); 113141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (policy == null) { 113241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalArgumentException("unable to find policy for " + template); 113341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 113441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 113541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey policy.lastSnooze = currentTime; 113641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 11378e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey updateNetworkEnabledLocked(); 113841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey updateNetworkRulesLocked(); 113941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey updateNotificationsLocked(); 114041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey writePolicyLocked(); 114121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 114221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 114321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 114421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey @Override 11454664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public void setRestrictBackground(boolean restrictBackground) { 11464664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 11474664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey 1148684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey maybeRefreshTrustedTime(); 11494664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey synchronized (mRulesLock) { 11504664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey mRestrictBackground = restrictBackground; 11514664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey updateRulesForRestrictBackgroundLocked(); 11523a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey updateNotificationsLocked(); 1153f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey writePolicyLocked(); 11544664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 11554664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 11564664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey 11574664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey @Override 11584664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public boolean getRestrictBackground() { 11594664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 11604664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey 11614664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey synchronized (mRulesLock) { 11624664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey return mRestrictBackground; 11634664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 11644664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 11654664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey 1166f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) { 1167f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 1168f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey if (policy.template.matches(ident)) { 1169f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey return policy; 1170f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1171f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1172f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey return null; 1173f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1174f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1175f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey @Override 1176f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) { 1177f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 1178f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1179f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey // only returns usage summary, so we don't require caller to have 1180f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey // READ_NETWORK_USAGE_HISTORY. 1181f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final long token = Binder.clearCallingIdentity(); 1182f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey try { 1183f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey return getNetworkQuotaInfoUnchecked(state); 1184f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } finally { 1185f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey Binder.restoreCallingIdentity(token); 1186f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1187f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1188f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1189f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) { 1190f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); 1191f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1192f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final NetworkPolicy policy; 1193f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey synchronized (mRulesLock) { 1194f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey policy = findPolicyForNetworkLocked(ident); 1195f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1196f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1197f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey if (policy == null) { 1198f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey // missing policy means we can't derive useful quota info 1199f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey return null; 1200f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1201f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1202684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey final long currentTime = currentTimeMillis(); 1203f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1204b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // find total bytes used under policy 1205f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final long start = computeLastCycleBoundary(currentTime, policy); 1206f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final long end = currentTime; 12078e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey final long totalBytes = getTotalBytes(policy.template, start, end); 1208f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1209f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey // report soft and hard limits under policy 1210f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes 1211f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey : NetworkQuotaInfo.NO_LIMIT; 1212f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes 1213f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey : NetworkQuotaInfo.NO_LIMIT; 1214f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 1215f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes); 1216f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey } 1217f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey 12184664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey @Override 12191b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 122075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey mContext.enforceCallingOrSelfPermission(DUMP, TAG); 12211b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 122241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final HashSet<String> argSet = new HashSet<String>(); 122341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey for (String arg : args) { 122441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey argSet.add(arg); 122541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 122641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 12271b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey synchronized (mRulesLock) { 122841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (argSet.contains("unsnooze")) { 122941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 123041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey policy.lastSnooze = SNOOZE_NEVER; 123141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 123241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey writePolicyLocked(); 123341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey fout.println("Wiped snooze timestamps"); 123441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey return; 123541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 123641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 12374664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey fout.print("Restrict background: "); fout.println(mRestrictBackground); 123821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey fout.println("Network policies:"); 123941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey for (NetworkPolicy policy : mNetworkPolicy.values()) { 124022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey fout.print(" "); fout.println(policy.toString()); 124121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 124221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 12431b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.println("Policy status for known UIDs:"); 12441b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 12451b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final SparseBooleanArray knownUids = new SparseBooleanArray(); 12461b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey collectKeys(mUidPolicy, knownUids); 12471b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey collectKeys(mUidForeground, knownUids); 12481b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey collectKeys(mUidRules, knownUids); 12491b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 12501b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int size = knownUids.size(); 12511b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey for (int i = 0; i < size; i++) { 12521b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int uid = knownUids.keyAt(i); 12531b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(" UID="); 12541b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(uid); 12551b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 12561b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(" policy="); 12571b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int policyIndex = mUidPolicy.indexOfKey(uid); 12581b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey if (policyIndex < 0) { 12591b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("UNKNOWN"); 12601b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } else { 12611b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey dumpPolicy(fout, mUidPolicy.valueAt(policyIndex)); 12621b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 12631b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 12641b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(" foreground="); 12651b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int foregroundIndex = mUidPidForeground.indexOfKey(uid); 12661b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey if (foregroundIndex < 0) { 12671b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("UNKNOWN"); 12681b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } else { 12691b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex)); 12701b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 12711b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 12721b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(" rules="); 12731b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int rulesIndex = mUidRules.indexOfKey(uid); 12741b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey if (rulesIndex < 0) { 12751b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("UNKNOWN"); 12761b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } else { 12771b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey dumpRules(fout, mUidRules.valueAt(rulesIndex)); 12781b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 12791b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 12801b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.println(); 12811b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 12821b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 12831b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 12849599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 12859599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 12869599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public boolean isUidForeground(int uid) { 1287497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1288497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 12899599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey synchronized (mRulesLock) { 12909599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey // only really in foreground when screen is also on 12919599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return mUidForeground.get(uid, false) && mScreenOn; 12929599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1293c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey } 1294c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 1295d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey /** 1296d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Foreground for PID changed; recompute foreground at UID level. If 129721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * changed, will trigger {@link #updateRulesForUidLocked(int)}. 1298d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */ 129921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void computeUidForegroundLocked(int uid) { 1300d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 1301d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1302d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey // current pid is dropping foreground; examine other pids 1303d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey boolean uidForeground = false; 1304d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey final int size = pidForeground.size(); 1305d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey for (int i = 0; i < size; i++) { 1306d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey if (pidForeground.valueAt(i)) { 1307d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey uidForeground = true; 1308d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey break; 1309d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 1310d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 1311d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1312d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey final boolean oldUidForeground = mUidForeground.get(uid, false); 1313d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey if (oldUidForeground != uidForeground) { 1314d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey // foreground changed, push updated rules 1315d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey mUidForeground.put(uid, uidForeground); 131621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateRulesForUidLocked(uid); 1317a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 1318a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 1319a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 1320a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey private void updateScreenOn() { 1321a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey synchronized (mRulesLock) { 1322a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey try { 1323a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey mScreenOn = mPowerManager.isScreenOn(); 1324a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } catch (RemoteException e) { 1325b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 1326a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 132721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateRulesForScreenLocked(); 1328d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 1329d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 1330d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1331a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey /** 1332a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey * Update rules that might be changed by {@link #mScreenOn} value. 1333a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey */ 133421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void updateRulesForScreenLocked() { 1335a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey // only update rules for anyone with foreground activities 1336a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey final int size = mUidForeground.size(); 1337a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey for (int i = 0; i < size; i++) { 1338a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey if (mUidForeground.valueAt(i)) { 1339a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey final int uid = mUidForeground.keyAt(i); 134021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey updateRulesForUidLocked(uid); 1341a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 1342a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 1343a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey } 1344a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey 1345b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey /** 13464664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey * Update rules that might be changed by {@link #mRestrictBackground} value. 1347b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey */ 13484664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey private void updateRulesForRestrictBackgroundLocked() { 1349b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // update rules for all installed applications 1350b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final PackageManager pm = mContext.getPackageManager(); 1351b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final List<ApplicationInfo> apps = pm.getInstalledApplications(0); 1352b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey for (ApplicationInfo app : apps) { 1353b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey updateRulesForUidLocked(app.uid); 1354b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1355b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1356b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // and catch system UIDs 1357b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // TODO: keep in sync with android_filesystem_config.h 1358b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey for (int uid = 1000; uid <= 1025; uid++) { 1359b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey updateRulesForUidLocked(uid); 1360b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1361b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey for (int uid = 2000; uid <= 2002; uid++) { 1362b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey updateRulesForUidLocked(uid); 1363b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1364b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey for (int uid = 3000; uid <= 3007; uid++) { 1365b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey updateRulesForUidLocked(uid); 1366b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1367b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey for (int uid = 9998; uid <= 9999; uid++) { 1368b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey updateRulesForUidLocked(uid); 1369b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1370b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1371b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 137221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey private void updateRulesForUidLocked(int uid) { 1373d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey final int uidPolicy = getUidPolicy(uid); 13749599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final boolean uidForeground = isUidForeground(uid); 1375d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1376c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // derive active rules based on policy and active state 1377c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey int uidRules = RULE_ALLOW_ALL; 1378fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { 1379fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey // uid in background, and policy says to block metered data 1380fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey uidRules = RULE_REJECT_METERED; 1381d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey } 13824664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey if (!uidForeground && mRestrictBackground) { 1383b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // uid in background, and global background disabled 1384b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey uidRules = RULE_REJECT_METERED; 1385b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1386d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey 1387c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // TODO: only dispatch when rules actually change 1388c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 1389350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (uidRules == RULE_ALLOW_ALL) { 1390350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey mUidRules.delete(uid); 1391350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } else { 1392350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey mUidRules.put(uid, uidRules); 1393350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 1394c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey 1395fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0; 139650fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma setUidNetworkRules(uid, rejectMetered); 1397497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey 1398c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey // dispatch changed rule to existing listeners 13994414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget(); 1400b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey 1401b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey try { 1402b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey // adjust stats accounting based on foreground status 1403b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey mNetworkStats.setUidForeground(uid, uidForeground); 1404b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } catch (RemoteException e) { 1405b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 1406b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 14074414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14084414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 14094414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey private Handler.Callback mHandlerCallback = new Handler.Callback() { 14104414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey /** {@inheritDoc} */ 14114414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey public boolean handleMessage(Message msg) { 14124414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey switch (msg.what) { 14134414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey case MSG_RULES_CHANGED: { 14144414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int uid = msg.arg1; 14154414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int uidRules = msg.arg2; 14164414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int length = mListeners.beginBroadcast(); 14174414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey for (int i = 0; i < length; i++) { 14184414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 14194414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey if (listener != null) { 14204414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey try { 14214414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey listener.onUidRulesChanged(uid, uidRules); 14224414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } catch (RemoteException e) { 14234414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14244414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14254414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14264414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mListeners.finishBroadcast(); 14274414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey return true; 14284414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14294414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey case MSG_METERED_IFACES_CHANGED: { 14304414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final String[] meteredIfaces = (String[]) msg.obj; 14314414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int length = mListeners.beginBroadcast(); 14324414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey for (int i = 0; i < length; i++) { 14334414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 14344414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey if (listener != null) { 14354414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey try { 14364414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey listener.onMeteredIfacesChanged(meteredIfaces); 14374414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } catch (RemoteException e) { 14384414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14394414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14404414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14414414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey mListeners.finishBroadcast(); 14424414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey return true; 14434414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14446f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey case MSG_FOREGROUND_ACTIVITIES_CHANGED: { 14456f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey final int pid = msg.arg1; 14466f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey final int uid = msg.arg2; 14476f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey final boolean foregroundActivities = (Boolean) msg.obj; 14486f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey 14496f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey synchronized (mRulesLock) { 14506f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey // because a uid can have multiple pids running inside, we need to 14516f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey // remember all pid states and summarize foreground at uid level. 14526f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey 14536f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey // record foreground for this specific pid 14546f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 14556f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey if (pidForeground == null) { 14566f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey pidForeground = new SparseBooleanArray(2); 14576f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey mUidPidForeground.put(uid, pidForeground); 14586f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey } 14596f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey pidForeground.put(pid, foregroundActivities); 14606f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey computeUidForegroundLocked(uid); 14616f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey } 14626f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey return true; 14636f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey } 14646f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey case MSG_PROCESS_DIED: { 14656f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey final int pid = msg.arg1; 14666f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey final int uid = msg.arg2; 14676f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey 14686f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey synchronized (mRulesLock) { 14696f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey // clear records and recompute, when they exist 14706f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 14716f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey if (pidForeground != null) { 14726f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey pidForeground.delete(pid); 14736f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey computeUidForegroundLocked(uid); 14746f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey } 14756f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey } 14766f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey return true; 14776f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey } 14787e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey case MSG_LIMIT_REACHED: { 14797e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey final String iface = (String) msg.obj; 14807e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey 1481684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey maybeRefreshTrustedTime(); 14827e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey synchronized (mRulesLock) { 14837e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey if (mMeteredIfaces.contains(iface)) { 14847e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey try { 14857e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey // force stats update to make sure we have 14867e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey // numbers that caused alert to trigger. 14877e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey mNetworkStats.forceUpdate(); 14887e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey } catch (RemoteException e) { 14897e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey // ignored; service lives in system_server 14907e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey } 14917e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey 14927e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey updateNetworkEnabledLocked(); 14937e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey updateNotificationsLocked(); 14947e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey } 14957e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey } 14967e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey return true; 14977e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey } 14984414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey default: { 14994414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey return false; 1500af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey } 1501af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey } 1502af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey } 15034414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey }; 150422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 150541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private void setInterfaceQuota(String iface, long quotaBytes) { 1506b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 150741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkManager.setInterfaceQuota(iface, quotaBytes); 1508b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (IllegalStateException e) { 1509b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey Log.wtf(TAG, "problem setting interface quota", e); 1510b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (RemoteException e) { 1511b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 1512b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1513b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1514b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1515b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey private void removeInterfaceQuota(String iface) { 1516b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 151741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkManager.removeInterfaceQuota(iface); 1518b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (IllegalStateException e) { 1519b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey Log.wtf(TAG, "problem removing interface quota", e); 1520b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (RemoteException e) { 1521b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 152241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 152341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 152441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 1525b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1526b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 152741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces); 1528b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (IllegalStateException e) { 1529b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey Log.wtf(TAG, "problem setting uid rules", e); 1530b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (RemoteException e) { 1531b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 1532b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1533b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1534b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 15358e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey /** 15363f3115b27733a822104385284b1ec1f39d91f839Jeff Sharkey * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}. 15378e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey */ 15388e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private void setPolicyDataEnable(int networkType, boolean enabled) { 15393f3115b27733a822104385284b1ec1f39d91f839Jeff Sharkey try { 15403f3115b27733a822104385284b1ec1f39d91f839Jeff Sharkey mConnManager.setPolicyDataEnable(networkType, enabled); 15413f3115b27733a822104385284b1ec1f39d91f839Jeff Sharkey } catch (RemoteException e) { 15423f3115b27733a822104385284b1ec1f39d91f839Jeff Sharkey // ignored; service lives in system_server 15438e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 15448e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 15458e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 154622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey private String getActiveSubscriberId() { 154722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService( 154822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey Context.TELEPHONY_SERVICE); 154922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey return telephony.getSubscriberId(); 155022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey } 155122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey 15528e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey private long getTotalBytes(NetworkTemplate template, long start, long end) { 15538e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey try { 155450e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey return mNetworkStats.getSummaryForNetwork(template, start, end).getTotalBytes(); 15558e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } catch (RemoteException e) { 1556b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey // ignored; service lives in system_server 1557b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey return 0; 15588e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 15598e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 15608e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 1561684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey /** 1562684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey * Try refreshing {@link #mTime} when stale. 1563684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey */ 1564684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey private void maybeRefreshTrustedTime() { 1565684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) { 15668e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey mTime.forceRefresh(); 15678e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 1568684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey } 15698e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 1570684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey private long currentTimeMillis() { 15718e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis(); 15728e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey } 15738e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey 15743a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey private static Intent buildAllowBackgroundDataIntent() { 15753a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey return new Intent(ACTION_ALLOW_BACKGROUND); 15763a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey } 15773a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey 157841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) { 157941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final Intent intent = new Intent(); 158041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey intent.setComponent(new ComponentName( 158141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity")); 158241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 158341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); 158441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey return intent; 158541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 158641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 158741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private static Intent buildViewDataUsageIntent(NetworkTemplate template) { 158841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final Intent intent = new Intent(); 158941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey intent.setComponent(new ComponentName( 159041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity")); 159141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 159241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); 159341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey return intent; 159441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 159541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 1596163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey // @VisibleForTesting 1597163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey public void addIdleHandler(IdleHandler handler) { 1598163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey mHandler.getLooper().getQueue().addIdleHandler(handler); 1599163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 1600163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 16011b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey private static void collectKeys(SparseIntArray source, SparseBooleanArray target) { 16021b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int size = source.size(); 16031b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey for (int i = 0; i < size; i++) { 16041b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey target.put(source.keyAt(i), true); 16051b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 16061b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 16071b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 16081b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) { 16091b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int size = source.size(); 16101b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey for (int i = 0; i < size; i++) { 16111b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey target.put(source.keyAt(i), true); 16121b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 16131b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 16141b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey 16151b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) { 16161b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("["); 16171b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey final int size = value.size(); 16181b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey for (int i = 0; i < size; i++) { 16191b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print(value.keyAt(i) + "=" + value.valueAt(i)); 16201b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey if (i < size - 1) fout.print(","); 16211b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 16221b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey fout.print("]"); 16231b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey } 162421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 16254664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static class XmlUtils { 16264664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static int readIntAttribute(XmlPullParser in, String name) throws IOException { 16274664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey final String value = in.getAttributeValue(null, name); 16284664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey try { 16294664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey return Integer.parseInt(value); 16304664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } catch (NumberFormatException e) { 16314664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 16324664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 163321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 163421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 16354664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static void writeIntAttribute(XmlSerializer out, String name, int value) 16364664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey throws IOException { 16374664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey out.attribute(null, name, Integer.toString(value)); 163821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey } 163921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 16404664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static long readLongAttribute(XmlPullParser in, String name) throws IOException { 16414664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey final String value = in.getAttributeValue(null, name); 16424664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey try { 16434664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey return Long.parseLong(value); 16444664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } catch (NumberFormatException e) { 16454664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey throw new ProtocolException("problem parsing " + name + "=" + value + " as long"); 16464664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 16474664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 164821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 16494664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static void writeLongAttribute(XmlSerializer out, String name, long value) 16504664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey throws IOException { 16514664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey out.attribute(null, name, Long.toString(value)); 16524664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 165321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey 16544664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static boolean readBooleanAttribute(XmlPullParser in, String name) { 16554664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey final String value = in.getAttributeValue(null, name); 16564664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey return Boolean.parseBoolean(value); 16574664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 16584664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey 16594664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value) 16604664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey throws IOException { 16614664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey out.attribute(null, name, Boolean.toString(value)); 16624664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 16634664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey } 1664d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey} 1665