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