NetworkPolicyManagerService.java revision a93c2c117d502ee57dd27705a0b5efca4bf65011
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.net; 18 19import static android.Manifest.permission.ACCESS_NETWORK_STATE; 20import static android.Manifest.permission.CONNECTIVITY_INTERNAL; 21import static android.Manifest.permission.DUMP; 22import static android.Manifest.permission.MANAGE_NETWORK_POLICY; 23import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; 24import static android.Manifest.permission.READ_PHONE_STATE; 25import static android.content.Intent.ACTION_PACKAGE_ADDED; 26import static android.content.Intent.ACTION_UID_REMOVED; 27import static android.content.Intent.EXTRA_UID; 28import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; 29import static android.net.ConnectivityManager.TYPE_ETHERNET; 30import static android.net.ConnectivityManager.TYPE_MOBILE; 31import static android.net.ConnectivityManager.TYPE_WIFI; 32import static android.net.ConnectivityManager.TYPE_WIMAX; 33import static android.net.ConnectivityManager.isNetworkTypeMobile; 34import static android.net.NetworkPolicy.CYCLE_NONE; 35import static android.net.NetworkPolicy.LIMIT_DISABLED; 36import static android.net.NetworkPolicy.SNOOZE_NEVER; 37import static android.net.NetworkPolicy.WARNING_DISABLED; 38import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE; 39import static android.net.NetworkPolicyManager.POLICY_NONE; 40import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; 41import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; 42import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; 43import static android.net.NetworkPolicyManager.computeLastCycleBoundary; 44import static android.net.NetworkPolicyManager.dumpPolicy; 45import static android.net.NetworkPolicyManager.dumpRules; 46import static android.net.NetworkTemplate.MATCH_ETHERNET; 47import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER; 48import static android.net.NetworkTemplate.MATCH_MOBILE_4G; 49import static android.net.NetworkTemplate.MATCH_MOBILE_ALL; 50import static android.net.NetworkTemplate.MATCH_WIFI; 51import static android.net.NetworkTemplate.buildTemplateMobileAll; 52import static android.net.TrafficStats.MB_IN_BYTES; 53import static android.net.wifi.WifiInfo.removeDoubleQuotes; 54import static android.net.wifi.WifiManager.CHANGE_REASON_ADDED; 55import static android.net.wifi.WifiManager.CHANGE_REASON_REMOVED; 56import static android.net.wifi.WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION; 57import static android.net.wifi.WifiManager.EXTRA_CHANGE_REASON; 58import static android.net.wifi.WifiManager.EXTRA_NETWORK_INFO; 59import static android.net.wifi.WifiManager.EXTRA_WIFI_CONFIGURATION; 60import static android.net.wifi.WifiManager.EXTRA_WIFI_INFO; 61import static android.telephony.TelephonyManager.SIM_STATE_READY; 62import static android.text.format.DateUtils.DAY_IN_MILLIS; 63import static com.android.internal.util.ArrayUtils.appendInt; 64import static com.android.internal.util.Preconditions.checkNotNull; 65import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; 66import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readBooleanAttribute; 67import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readIntAttribute; 68import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readLongAttribute; 69import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeBooleanAttribute; 70import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeIntAttribute; 71import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeLongAttribute; 72import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED; 73import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 74import static org.xmlpull.v1.XmlPullParser.START_TAG; 75 76import android.app.IActivityManager; 77import android.app.INotificationManager; 78import android.app.IProcessObserver; 79import android.app.Notification; 80import android.app.PendingIntent; 81import android.content.BroadcastReceiver; 82import android.content.ComponentName; 83import android.content.Context; 84import android.content.Intent; 85import android.content.IntentFilter; 86import android.content.pm.ApplicationInfo; 87import android.content.pm.PackageManager; 88import android.content.pm.UserInfo; 89import android.content.res.Resources; 90import android.net.ConnectivityManager; 91import android.net.IConnectivityManager; 92import android.net.INetworkManagementEventObserver; 93import android.net.INetworkPolicyListener; 94import android.net.INetworkPolicyManager; 95import android.net.INetworkStatsService; 96import android.net.NetworkIdentity; 97import android.net.NetworkInfo; 98import android.net.NetworkPolicy; 99import android.net.NetworkQuotaInfo; 100import android.net.NetworkState; 101import android.net.NetworkTemplate; 102import android.net.wifi.WifiConfiguration; 103import android.net.wifi.WifiInfo; 104import android.net.wifi.WifiManager; 105import android.os.Binder; 106import android.os.Environment; 107import android.os.Handler; 108import android.os.HandlerThread; 109import android.os.INetworkManagementService; 110import android.os.IPowerManager; 111import android.os.Message; 112import android.os.MessageQueue.IdleHandler; 113import android.os.RemoteCallbackList; 114import android.os.RemoteException; 115import android.os.UserId; 116import android.provider.Settings; 117import android.telephony.TelephonyManager; 118import android.text.format.Formatter; 119import android.text.format.Time; 120import android.util.Log; 121import android.util.NtpTrustedTime; 122import android.util.Slog; 123import android.util.SparseArray; 124import android.util.SparseBooleanArray; 125import android.util.SparseIntArray; 126import android.util.TrustedTime; 127import android.util.Xml; 128 129import com.android.internal.R; 130import com.android.internal.os.AtomicFile; 131import com.android.internal.util.FastXmlSerializer; 132import com.android.internal.util.IndentingPrintWriter; 133import com.android.internal.util.Objects; 134import com.google.android.collect.Lists; 135import com.google.android.collect.Maps; 136import com.google.android.collect.Sets; 137 138import org.xmlpull.v1.XmlPullParser; 139import org.xmlpull.v1.XmlPullParserException; 140import org.xmlpull.v1.XmlSerializer; 141 142import java.io.File; 143import java.io.FileDescriptor; 144import java.io.FileInputStream; 145import java.io.FileNotFoundException; 146import java.io.FileOutputStream; 147import java.io.IOException; 148import java.io.PrintWriter; 149import java.net.ProtocolException; 150import java.util.ArrayList; 151import java.util.Arrays; 152import java.util.HashMap; 153import java.util.HashSet; 154import java.util.List; 155import java.util.Map; 156 157import libcore.io.IoUtils; 158 159/** 160 * Service that maintains low-level network policy rules, using 161 * {@link NetworkStatsService} statistics to drive those rules. 162 * <p> 163 * Derives active rules by combining a given policy with other system status, 164 * and delivers to listeners, such as {@link ConnectivityManager}, for 165 * enforcement. 166 */ 167public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 168 private static final String TAG = "NetworkPolicy"; 169 private static final boolean LOGD = false; 170 private static final boolean LOGV = false; 171 172 private static final int VERSION_INIT = 1; 173 private static final int VERSION_ADDED_SNOOZE = 2; 174 private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3; 175 private static final int VERSION_ADDED_METERED = 4; 176 private static final int VERSION_SPLIT_SNOOZE = 5; 177 private static final int VERSION_ADDED_TIMEZONE = 6; 178 private static final int VERSION_ADDED_INFERRED = 7; 179 private static final int VERSION_SWITCH_APP_ID = 8; 180 private static final int VERSION_ADDED_NETWORK_ID = 9; 181 private static final int VERSION_LATEST = VERSION_ADDED_NETWORK_ID; 182 183 // @VisibleForTesting 184 public static final int TYPE_WARNING = 0x1; 185 public static final int TYPE_LIMIT = 0x2; 186 public static final int TYPE_LIMIT_SNOOZED = 0x3; 187 188 private static final String TAG_POLICY_LIST = "policy-list"; 189 private static final String TAG_NETWORK_POLICY = "network-policy"; 190 private static final String TAG_UID_POLICY = "uid-policy"; 191 private static final String TAG_APP_POLICY = "app-policy"; 192 193 private static final String ATTR_VERSION = "version"; 194 private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground"; 195 private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate"; 196 private static final String ATTR_SUBSCRIBER_ID = "subscriberId"; 197 private static final String ATTR_NETWORK_ID = "networkId"; 198 private static final String ATTR_CYCLE_DAY = "cycleDay"; 199 private static final String ATTR_CYCLE_TIMEZONE = "cycleTimezone"; 200 private static final String ATTR_WARNING_BYTES = "warningBytes"; 201 private static final String ATTR_LIMIT_BYTES = "limitBytes"; 202 private static final String ATTR_LAST_SNOOZE = "lastSnooze"; 203 private static final String ATTR_LAST_WARNING_SNOOZE = "lastWarningSnooze"; 204 private static final String ATTR_LAST_LIMIT_SNOOZE = "lastLimitSnooze"; 205 private static final String ATTR_METERED = "metered"; 206 private static final String ATTR_INFERRED = "inferred"; 207 private static final String ATTR_UID = "uid"; 208 private static final String ATTR_APP_ID = "appId"; 209 private static final String ATTR_POLICY = "policy"; 210 211 private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground"; 212 213 // @VisibleForTesting 214 public static final String ACTION_ALLOW_BACKGROUND = 215 "com.android.server.net.action.ALLOW_BACKGROUND"; 216 public static final String ACTION_SNOOZE_WARNING = 217 "com.android.server.net.action.SNOOZE_WARNING"; 218 219 private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS; 220 221 private static final int MSG_RULES_CHANGED = 1; 222 private static final int MSG_METERED_IFACES_CHANGED = 2; 223 private static final int MSG_FOREGROUND_ACTIVITIES_CHANGED = 3; 224 private static final int MSG_PROCESS_DIED = 4; 225 private static final int MSG_LIMIT_REACHED = 5; 226 private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6; 227 private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7; 228 229 private final Context mContext; 230 private final IActivityManager mActivityManager; 231 private final IPowerManager mPowerManager; 232 private final INetworkStatsService mNetworkStats; 233 private final INetworkManagementService mNetworkManager; 234 private final TrustedTime mTime; 235 236 private IConnectivityManager mConnManager; 237 private INotificationManager mNotifManager; 238 239 private final Object mRulesLock = new Object(); 240 241 private volatile boolean mScreenOn; 242 private volatile boolean mRestrictBackground; 243 244 private final boolean mSuppressDefaultPolicy; 245 246 /** Defined network policies. */ 247 private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap(); 248 /** Currently active network rules for ifaces. */ 249 private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap(); 250 251 /** Defined app policies. */ 252 private SparseIntArray mAppPolicy = new SparseIntArray(); 253 /** Currently derived rules for each UID. */ 254 private SparseIntArray mUidRules = new SparseIntArray(); 255 256 /** Set of ifaces that are metered. */ 257 private HashSet<String> mMeteredIfaces = Sets.newHashSet(); 258 /** Set of over-limit templates that have been notified. */ 259 private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet(); 260 261 /** Set of currently active {@link Notification} tags. */ 262 private HashSet<String> mActiveNotifs = Sets.newHashSet(); 263 264 /** Foreground at both UID and PID granularity. */ 265 private SparseBooleanArray mUidForeground = new SparseBooleanArray(); 266 private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray< 267 SparseBooleanArray>(); 268 269 private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList< 270 INetworkPolicyListener>(); 271 272 private final HandlerThread mHandlerThread; 273 private final Handler mHandler; 274 275 private final AtomicFile mPolicyFile; 276 277 // TODO: keep whitelist of system-critical services that should never have 278 // rules enforced, such as system, phone, and radio UIDs. 279 280 // TODO: migrate notifications to SystemUI 281 282 public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 283 IPowerManager powerManager, INetworkStatsService networkStats, 284 INetworkManagementService networkManagement) { 285 this(context, activityManager, powerManager, networkStats, networkManagement, 286 NtpTrustedTime.getInstance(context), getSystemDir(), false); 287 } 288 289 private static File getSystemDir() { 290 return new File(Environment.getDataDirectory(), "system"); 291 } 292 293 public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 294 IPowerManager powerManager, INetworkStatsService networkStats, 295 INetworkManagementService networkManagement, TrustedTime time, File systemDir, 296 boolean suppressDefaultPolicy) { 297 mContext = checkNotNull(context, "missing context"); 298 mActivityManager = checkNotNull(activityManager, "missing activityManager"); 299 mPowerManager = checkNotNull(powerManager, "missing powerManager"); 300 mNetworkStats = checkNotNull(networkStats, "missing networkStats"); 301 mNetworkManager = checkNotNull(networkManagement, "missing networkManagement"); 302 mTime = checkNotNull(time, "missing TrustedTime"); 303 304 mHandlerThread = new HandlerThread(TAG); 305 mHandlerThread.start(); 306 mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback); 307 308 mSuppressDefaultPolicy = suppressDefaultPolicy; 309 310 mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); 311 } 312 313 public void bindConnectivityManager(IConnectivityManager connManager) { 314 mConnManager = checkNotNull(connManager, "missing IConnectivityManager"); 315 } 316 317 public void bindNotificationManager(INotificationManager notifManager) { 318 mNotifManager = checkNotNull(notifManager, "missing INotificationManager"); 319 } 320 321 public void systemReady() { 322 if (!isBandwidthControlEnabled()) { 323 Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy"); 324 return; 325 } 326 327 synchronized (mRulesLock) { 328 // read policy from disk 329 readPolicyLocked(); 330 331 if (mRestrictBackground) { 332 updateRulesForRestrictBackgroundLocked(); 333 updateNotificationsLocked(); 334 } 335 } 336 337 updateScreenOn(); 338 339 try { 340 mActivityManager.registerProcessObserver(mProcessObserver); 341 mNetworkManager.registerObserver(mAlertObserver); 342 } catch (RemoteException e) { 343 // ignored; both services live in system_server 344 } 345 346 // TODO: traverse existing processes to know foreground state, or have 347 // activitymanager dispatch current state when new observer attached. 348 349 final IntentFilter screenFilter = new IntentFilter(); 350 screenFilter.addAction(Intent.ACTION_SCREEN_ON); 351 screenFilter.addAction(Intent.ACTION_SCREEN_OFF); 352 mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler); 353 354 // watch for network interfaces to be claimed 355 final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE); 356 mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); 357 358 // listen for package/uid changes to update policy 359 final IntentFilter packageFilter = new IntentFilter(); 360 packageFilter.addAction(ACTION_PACKAGE_ADDED); 361 packageFilter.addAction(ACTION_UID_REMOVED); 362 mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler); 363 364 // listen for stats update events 365 final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED); 366 mContext.registerReceiver( 367 mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler); 368 369 // listen for restrict background changes from notifications 370 final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND); 371 mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler); 372 373 // listen for snooze warning from notifications 374 final IntentFilter snoozeWarningFilter = new IntentFilter(ACTION_SNOOZE_WARNING); 375 mContext.registerReceiver(mSnoozeWarningReceiver, snoozeWarningFilter, 376 MANAGE_NETWORK_POLICY, mHandler); 377 378 // listen for configured wifi networks to be removed 379 final IntentFilter wifiConfigFilter = new IntentFilter(CONFIGURED_NETWORKS_CHANGED_ACTION); 380 mContext.registerReceiver( 381 mWifiConfigReceiver, wifiConfigFilter, CONNECTIVITY_INTERNAL, mHandler); 382 383 // listen for wifi state changes to catch metered hint 384 final IntentFilter wifiStateFilter = new IntentFilter( 385 WifiManager.NETWORK_STATE_CHANGED_ACTION); 386 mContext.registerReceiver( 387 mWifiStateReceiver, wifiStateFilter, CONNECTIVITY_INTERNAL, mHandler); 388 389 } 390 391 private IProcessObserver mProcessObserver = new IProcessObserver.Stub() { 392 @Override 393 public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) { 394 mHandler.obtainMessage(MSG_FOREGROUND_ACTIVITIES_CHANGED, 395 pid, uid, foregroundActivities).sendToTarget(); 396 } 397 398 @Override 399 public void onImportanceChanged(int pid, int uid, int importance) { 400 } 401 402 @Override 403 public void onProcessDied(int pid, int uid) { 404 mHandler.obtainMessage(MSG_PROCESS_DIED, pid, uid).sendToTarget(); 405 } 406 }; 407 408 private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { 409 @Override 410 public void onReceive(Context context, Intent intent) { 411 synchronized (mRulesLock) { 412 // screen-related broadcasts are protected by system, no need 413 // for permissions check. 414 updateScreenOn(); 415 } 416 } 417 }; 418 419 private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() { 420 @Override 421 public void onReceive(Context context, Intent intent) { 422 // on background handler thread, and PACKAGE_ADDED and UID_REMOVED 423 // are protected broadcasts. 424 425 final String action = intent.getAction(); 426 final int uid = intent.getIntExtra(EXTRA_UID, 0); 427 final int appId = UserId.getAppId(uid); 428 synchronized (mRulesLock) { 429 if (ACTION_PACKAGE_ADDED.equals(action)) { 430 // NOTE: PACKAGE_ADDED is currently only sent once, and is 431 // not broadcast when users are added. 432 433 // update rules for UID, since it might be subject to 434 // global background data policy. 435 if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid); 436 updateRulesForAppLocked(appId); 437 438 } else if (ACTION_UID_REMOVED.equals(action)) { 439 // NOTE: UID_REMOVED is currently only sent once, and is not 440 // broadcast when users are removed. 441 442 // remove any policy and update rules to clean up. 443 if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid); 444 445 mAppPolicy.delete(appId); 446 updateRulesForAppLocked(appId); 447 writePolicyLocked(); 448 } 449 } 450 } 451 }; 452 453 /** 454 * Receiver that watches for {@link INetworkStatsService} updates, which we 455 * use to check against {@link NetworkPolicy#warningBytes}. 456 */ 457 private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() { 458 @Override 459 public void onReceive(Context context, Intent intent) { 460 // on background handler thread, and verified 461 // READ_NETWORK_USAGE_HISTORY permission above. 462 463 maybeRefreshTrustedTime(); 464 synchronized (mRulesLock) { 465 updateNetworkEnabledLocked(); 466 updateNotificationsLocked(); 467 } 468 } 469 }; 470 471 /** 472 * Receiver that watches for {@link Notification} control of 473 * {@link #mRestrictBackground}. 474 */ 475 private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() { 476 @Override 477 public void onReceive(Context context, Intent intent) { 478 // on background handler thread, and verified MANAGE_NETWORK_POLICY 479 // permission above. 480 481 setRestrictBackground(false); 482 } 483 }; 484 485 /** 486 * Receiver that watches for {@link Notification} control of 487 * {@link NetworkPolicy#lastWarningSnooze}. 488 */ 489 private BroadcastReceiver mSnoozeWarningReceiver = new BroadcastReceiver() { 490 @Override 491 public void onReceive(Context context, Intent intent) { 492 // on background handler thread, and verified MANAGE_NETWORK_POLICY 493 // permission above. 494 495 final NetworkTemplate template = intent.getParcelableExtra(EXTRA_NETWORK_TEMPLATE); 496 performSnooze(template, TYPE_WARNING); 497 } 498 }; 499 500 /** 501 * Receiver that watches for {@link WifiConfiguration} to be changed. 502 */ 503 private BroadcastReceiver mWifiConfigReceiver = new BroadcastReceiver() { 504 @Override 505 public void onReceive(Context context, Intent intent) { 506 // on background handler thread, and verified CONNECTIVITY_INTERNAL 507 // permission above. 508 509 final int reason = intent.getIntExtra(EXTRA_CHANGE_REASON, CHANGE_REASON_ADDED); 510 if (reason == CHANGE_REASON_REMOVED) { 511 final WifiConfiguration config = intent.getParcelableExtra( 512 EXTRA_WIFI_CONFIGURATION); 513 if (config.SSID != null) { 514 final NetworkTemplate template = NetworkTemplate.buildTemplateWifi( 515 removeDoubleQuotes(config.SSID)); 516 synchronized (mRulesLock) { 517 if (mNetworkPolicy.containsKey(template)) { 518 mNetworkPolicy.remove(template); 519 writePolicyLocked(); 520 } 521 } 522 } 523 } 524 } 525 }; 526 527 /** 528 * Receiver that watches {@link WifiInfo} state changes to infer metered 529 * state. Ignores hints when policy is user-defined. 530 */ 531 private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() { 532 @Override 533 public void onReceive(Context context, Intent intent) { 534 // on background handler thread, and verified CONNECTIVITY_INTERNAL 535 // permission above. 536 537 // ignore when not connected 538 final NetworkInfo netInfo = intent.getParcelableExtra(EXTRA_NETWORK_INFO); 539 if (!netInfo.isConnected()) return; 540 541 final WifiInfo info = intent.getParcelableExtra(EXTRA_WIFI_INFO); 542 final boolean meteredHint = info.getMeteredHint(); 543 544 final NetworkTemplate template = NetworkTemplate.buildTemplateWifi( 545 removeDoubleQuotes(info.getSSID())); 546 synchronized (mRulesLock) { 547 NetworkPolicy policy = mNetworkPolicy.get(template); 548 if (policy == null && meteredHint) { 549 // policy doesn't exist, and AP is hinting that it's 550 // metered: create an inferred policy. 551 policy = new NetworkPolicy(template, CYCLE_NONE, Time.TIMEZONE_UTC, 552 WARNING_DISABLED, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, 553 meteredHint, true); 554 addNetworkPolicyLocked(policy); 555 556 } else if (policy != null && policy.inferred) { 557 // policy exists, and was inferred: update its current 558 // metered state. 559 policy.metered = meteredHint; 560 561 // since this is inferred for each wifi session, just update 562 // rules without persisting. 563 updateNetworkRulesLocked(); 564 } 565 } 566 } 567 }; 568 569 /** 570 * Observer that watches for {@link INetworkManagementService} alerts. 571 */ 572 private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() { 573 @Override 574 public void limitReached(String limitName, String iface) { 575 // only someone like NMS should be calling us 576 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 577 578 if (!LIMIT_GLOBAL_ALERT.equals(limitName)) { 579 mHandler.obtainMessage(MSG_LIMIT_REACHED, iface).sendToTarget(); 580 } 581 } 582 }; 583 584 /** 585 * Check {@link NetworkPolicy} against current {@link INetworkStatsService} 586 * to show visible notifications as needed. 587 */ 588 private void updateNotificationsLocked() { 589 if (LOGV) Slog.v(TAG, "updateNotificationsLocked()"); 590 591 // keep track of previously active notifications 592 final HashSet<String> beforeNotifs = Sets.newHashSet(); 593 beforeNotifs.addAll(mActiveNotifs); 594 mActiveNotifs.clear(); 595 596 // TODO: when switching to kernel notifications, compute next future 597 // cycle boundary to recompute notifications. 598 599 // examine stats for each active policy 600 final long currentTime = currentTimeMillis(); 601 for (NetworkPolicy policy : mNetworkPolicy.values()) { 602 // ignore policies that aren't relevant to user 603 if (!isTemplateRelevant(policy.template)) continue; 604 if (!policy.hasCycle()) continue; 605 606 final long start = computeLastCycleBoundary(currentTime, policy); 607 final long end = currentTime; 608 final long totalBytes = getTotalBytes(policy.template, start, end); 609 610 if (policy.isOverLimit(totalBytes)) { 611 if (policy.lastLimitSnooze >= start) { 612 enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes); 613 } else { 614 enqueueNotification(policy, TYPE_LIMIT, totalBytes); 615 notifyOverLimitLocked(policy.template); 616 } 617 618 } else { 619 notifyUnderLimitLocked(policy.template); 620 621 if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start) { 622 enqueueNotification(policy, TYPE_WARNING, totalBytes); 623 } 624 } 625 } 626 627 // ongoing notification when restricting background data 628 if (mRestrictBackground) { 629 enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND); 630 } 631 632 // cancel stale notifications that we didn't renew above 633 for (String tag : beforeNotifs) { 634 if (!mActiveNotifs.contains(tag)) { 635 cancelNotification(tag); 636 } 637 } 638 } 639 640 /** 641 * Test if given {@link NetworkTemplate} is relevant to user based on 642 * current device state, such as when 643 * {@link TelephonyManager#getSubscriberId()} matches. This is regardless of 644 * data connection status. 645 */ 646 private boolean isTemplateRelevant(NetworkTemplate template) { 647 final TelephonyManager tele = TelephonyManager.from(mContext); 648 649 switch (template.getMatchRule()) { 650 case MATCH_MOBILE_3G_LOWER: 651 case MATCH_MOBILE_4G: 652 case MATCH_MOBILE_ALL: 653 // mobile templates are relevant when SIM is ready and 654 // subscriberId matches. 655 if (tele.getSimState() == SIM_STATE_READY) { 656 return Objects.equal(tele.getSubscriberId(), template.getSubscriberId()); 657 } else { 658 return false; 659 } 660 } 661 return true; 662 } 663 664 /** 665 * Notify that given {@link NetworkTemplate} is over 666 * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user. 667 */ 668 private void notifyOverLimitLocked(NetworkTemplate template) { 669 if (!mOverLimitNotified.contains(template)) { 670 mContext.startActivity(buildNetworkOverLimitIntent(template)); 671 mOverLimitNotified.add(template); 672 } 673 } 674 675 private void notifyUnderLimitLocked(NetworkTemplate template) { 676 mOverLimitNotified.remove(template); 677 } 678 679 /** 680 * Build unique tag that identifies an active {@link NetworkPolicy} 681 * notification of a specific type, like {@link #TYPE_LIMIT}. 682 */ 683 private String buildNotificationTag(NetworkPolicy policy, int type) { 684 return TAG + ":" + policy.template.hashCode() + ":" + type; 685 } 686 687 /** 688 * Show notification for combined {@link NetworkPolicy} and specific type, 689 * like {@link #TYPE_LIMIT}. Okay to call multiple times. 690 */ 691 private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) { 692 final String tag = buildNotificationTag(policy, type); 693 final Notification.Builder builder = new Notification.Builder(mContext); 694 builder.setOnlyAlertOnce(true); 695 builder.setWhen(0L); 696 697 final Resources res = mContext.getResources(); 698 switch (type) { 699 case TYPE_WARNING: { 700 final CharSequence title = res.getText(R.string.data_usage_warning_title); 701 final CharSequence body = res.getString(R.string.data_usage_warning_body); 702 703 builder.setSmallIcon(R.drawable.stat_notify_error); 704 builder.setTicker(title); 705 builder.setContentTitle(title); 706 builder.setContentText(body); 707 708 final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template); 709 builder.setDeleteIntent(PendingIntent.getBroadcast( 710 mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 711 712 final Intent viewIntent = buildViewDataUsageIntent(policy.template); 713 builder.setContentIntent(PendingIntent.getActivity( 714 mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 715 716 break; 717 } 718 case TYPE_LIMIT: { 719 final CharSequence body = res.getText(R.string.data_usage_limit_body); 720 721 final CharSequence title; 722 switch (policy.template.getMatchRule()) { 723 case MATCH_MOBILE_3G_LOWER: 724 title = res.getText(R.string.data_usage_3g_limit_title); 725 break; 726 case MATCH_MOBILE_4G: 727 title = res.getText(R.string.data_usage_4g_limit_title); 728 break; 729 case MATCH_MOBILE_ALL: 730 title = res.getText(R.string.data_usage_mobile_limit_title); 731 break; 732 case MATCH_WIFI: 733 title = res.getText(R.string.data_usage_wifi_limit_title); 734 break; 735 default: 736 title = null; 737 break; 738 } 739 740 builder.setOngoing(true); 741 builder.setSmallIcon(R.drawable.stat_notify_disabled); 742 builder.setTicker(title); 743 builder.setContentTitle(title); 744 builder.setContentText(body); 745 746 final Intent intent = buildNetworkOverLimitIntent(policy.template); 747 builder.setContentIntent(PendingIntent.getActivity( 748 mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 749 break; 750 } 751 case TYPE_LIMIT_SNOOZED: { 752 final long overBytes = totalBytes - policy.limitBytes; 753 final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body, 754 Formatter.formatFileSize(mContext, overBytes)); 755 756 final CharSequence title; 757 switch (policy.template.getMatchRule()) { 758 case MATCH_MOBILE_3G_LOWER: 759 title = res.getText(R.string.data_usage_3g_limit_snoozed_title); 760 break; 761 case MATCH_MOBILE_4G: 762 title = res.getText(R.string.data_usage_4g_limit_snoozed_title); 763 break; 764 case MATCH_MOBILE_ALL: 765 title = res.getText(R.string.data_usage_mobile_limit_snoozed_title); 766 break; 767 case MATCH_WIFI: 768 title = res.getText(R.string.data_usage_wifi_limit_snoozed_title); 769 break; 770 default: 771 title = null; 772 break; 773 } 774 775 builder.setOngoing(true); 776 builder.setSmallIcon(R.drawable.stat_notify_error); 777 builder.setTicker(title); 778 builder.setContentTitle(title); 779 builder.setContentText(body); 780 781 final Intent intent = buildViewDataUsageIntent(policy.template); 782 builder.setContentIntent(PendingIntent.getActivity( 783 mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 784 break; 785 } 786 } 787 788 // TODO: move to NotificationManager once we can mock it 789 try { 790 final String packageName = mContext.getPackageName(); 791 final int[] idReceived = new int[1]; 792 mNotifManager.enqueueNotificationWithTag( 793 packageName, tag, 0x0, builder.getNotification(), idReceived); 794 mActiveNotifs.add(tag); 795 } catch (RemoteException e) { 796 // ignored; service lives in system_server 797 } 798 } 799 800 /** 801 * Show ongoing notification to reflect that {@link #mRestrictBackground} 802 * has been enabled. 803 */ 804 private void enqueueRestrictedNotification(String tag) { 805 final Resources res = mContext.getResources(); 806 final Notification.Builder builder = new Notification.Builder(mContext); 807 808 final CharSequence title = res.getText(R.string.data_usage_restricted_title); 809 final CharSequence body = res.getString(R.string.data_usage_restricted_body); 810 811 builder.setOnlyAlertOnce(true); 812 builder.setOngoing(true); 813 builder.setSmallIcon(R.drawable.stat_notify_error); 814 builder.setTicker(title); 815 builder.setContentTitle(title); 816 builder.setContentText(body); 817 818 final Intent intent = buildAllowBackgroundDataIntent(); 819 builder.setContentIntent( 820 PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 821 822 // TODO: move to NotificationManager once we can mock it 823 try { 824 final String packageName = mContext.getPackageName(); 825 final int[] idReceived = new int[1]; 826 mNotifManager.enqueueNotificationWithTag(packageName, tag, 827 0x0, builder.getNotification(), idReceived); 828 mActiveNotifs.add(tag); 829 } catch (RemoteException e) { 830 // ignored; service lives in system_server 831 } 832 } 833 834 private void cancelNotification(String tag) { 835 // TODO: move to NotificationManager once we can mock it 836 try { 837 final String packageName = mContext.getPackageName(); 838 mNotifManager.cancelNotificationWithTag( 839 packageName, tag, 0x0); 840 } catch (RemoteException e) { 841 // ignored; service lives in system_server 842 } 843 } 844 845 /** 846 * Receiver that watches for {@link IConnectivityManager} to claim network 847 * interfaces. Used to apply {@link NetworkPolicy} to matching networks. 848 */ 849 private BroadcastReceiver mConnReceiver = new BroadcastReceiver() { 850 @Override 851 public void onReceive(Context context, Intent intent) { 852 // on background handler thread, and verified CONNECTIVITY_INTERNAL 853 // permission above. 854 855 maybeRefreshTrustedTime(); 856 synchronized (mRulesLock) { 857 ensureActiveMobilePolicyLocked(); 858 updateNetworkEnabledLocked(); 859 updateNetworkRulesLocked(); 860 updateNotificationsLocked(); 861 } 862 } 863 }; 864 865 /** 866 * Proactively control network data connections when they exceed 867 * {@link NetworkPolicy#limitBytes}. 868 */ 869 private void updateNetworkEnabledLocked() { 870 if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()"); 871 872 // TODO: reset any policy-disabled networks when any policy is removed 873 // completely, which is currently rare case. 874 875 final long currentTime = currentTimeMillis(); 876 for (NetworkPolicy policy : mNetworkPolicy.values()) { 877 // shortcut when policy has no limit 878 if (policy.limitBytes == LIMIT_DISABLED || !policy.hasCycle()) { 879 setNetworkTemplateEnabled(policy.template, true); 880 continue; 881 } 882 883 final long start = computeLastCycleBoundary(currentTime, policy); 884 final long end = currentTime; 885 final long totalBytes = getTotalBytes(policy.template, start, end); 886 887 // disable data connection when over limit and not snoozed 888 final boolean overLimitWithoutSnooze = policy.isOverLimit(totalBytes) 889 && policy.lastLimitSnooze < start; 890 final boolean networkEnabled = !overLimitWithoutSnooze; 891 892 setNetworkTemplateEnabled(policy.template, networkEnabled); 893 } 894 } 895 896 /** 897 * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)} 898 * for the given {@link NetworkTemplate}. 899 */ 900 private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) { 901 final TelephonyManager tele = TelephonyManager.from(mContext); 902 903 switch (template.getMatchRule()) { 904 case MATCH_MOBILE_3G_LOWER: 905 case MATCH_MOBILE_4G: 906 case MATCH_MOBILE_ALL: 907 // TODO: offer more granular control over radio states once 908 // 4965893 is available. 909 if (tele.getSimState() == SIM_STATE_READY 910 && Objects.equal(tele.getSubscriberId(), template.getSubscriberId())) { 911 setPolicyDataEnable(TYPE_MOBILE, enabled); 912 setPolicyDataEnable(TYPE_WIMAX, enabled); 913 } 914 break; 915 case MATCH_WIFI: 916 setPolicyDataEnable(TYPE_WIFI, enabled); 917 break; 918 case MATCH_ETHERNET: 919 setPolicyDataEnable(TYPE_ETHERNET, enabled); 920 break; 921 default: 922 throw new IllegalArgumentException("unexpected template"); 923 } 924 } 925 926 /** 927 * Examine all connected {@link NetworkState}, looking for 928 * {@link NetworkPolicy} that need to be enforced. When matches found, set 929 * remaining quota based on usage cycle and historical stats. 930 */ 931 private void updateNetworkRulesLocked() { 932 if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); 933 934 final NetworkState[] states; 935 try { 936 states = mConnManager.getAllNetworkState(); 937 } catch (RemoteException e) { 938 // ignored; service lives in system_server 939 return; 940 } 941 942 // first, derive identity for all connected networks, which can be used 943 // to match against templates. 944 final HashMap<NetworkIdentity, String> networks = Maps.newHashMap(); 945 for (NetworkState state : states) { 946 // stash identity and iface away for later use 947 if (state.networkInfo.isConnected()) { 948 final String iface = state.linkProperties.getInterfaceName(); 949 final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); 950 networks.put(ident, iface); 951 } 952 } 953 954 // build list of rules and ifaces to enforce them against 955 mNetworkRules.clear(); 956 final ArrayList<String> ifaceList = Lists.newArrayList(); 957 for (NetworkPolicy policy : mNetworkPolicy.values()) { 958 959 // collect all active ifaces that match this template 960 ifaceList.clear(); 961 for (Map.Entry<NetworkIdentity, String> entry : networks.entrySet()) { 962 final NetworkIdentity ident = entry.getKey(); 963 if (policy.template.matches(ident)) { 964 final String iface = entry.getValue(); 965 ifaceList.add(iface); 966 } 967 } 968 969 if (ifaceList.size() > 0) { 970 final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]); 971 mNetworkRules.put(policy, ifaces); 972 } 973 } 974 975 long lowestRule = Long.MAX_VALUE; 976 final HashSet<String> newMeteredIfaces = Sets.newHashSet(); 977 978 // apply each policy that we found ifaces for; compute remaining data 979 // based on current cycle and historical stats, and push to kernel. 980 final long currentTime = currentTimeMillis(); 981 for (NetworkPolicy policy : mNetworkRules.keySet()) { 982 final String[] ifaces = mNetworkRules.get(policy); 983 984 final long start; 985 final long totalBytes; 986 if (policy.hasCycle()) { 987 start = computeLastCycleBoundary(currentTime, policy); 988 totalBytes = getTotalBytes(policy.template, start, currentTime); 989 } else { 990 start = Long.MAX_VALUE; 991 totalBytes = 0; 992 } 993 994 if (LOGD) { 995 Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces " 996 + Arrays.toString(ifaces)); 997 } 998 999 final boolean hasWarning = policy.warningBytes != LIMIT_DISABLED; 1000 final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED; 1001 if (hasLimit || policy.metered) { 1002 final long quotaBytes; 1003 if (!hasLimit) { 1004 // metered network, but no policy limit; we still need to 1005 // restrict apps, so push really high quota. 1006 quotaBytes = Long.MAX_VALUE; 1007 } else if (policy.lastLimitSnooze >= start) { 1008 // snoozing past quota, but we still need to restrict apps, 1009 // so push really high quota. 1010 quotaBytes = Long.MAX_VALUE; 1011 } else { 1012 // remaining "quota" bytes are based on total usage in 1013 // current cycle. kernel doesn't like 0-byte rules, so we 1014 // set 1-byte quota and disable the radio later. 1015 quotaBytes = Math.max(1, policy.limitBytes - totalBytes); 1016 } 1017 1018 if (ifaces.length > 1) { 1019 // TODO: switch to shared quota once NMS supports 1020 Slog.w(TAG, "shared quota unsupported; generating rule for each iface"); 1021 } 1022 1023 for (String iface : ifaces) { 1024 removeInterfaceQuota(iface); 1025 setInterfaceQuota(iface, quotaBytes); 1026 newMeteredIfaces.add(iface); 1027 } 1028 } 1029 1030 // keep track of lowest warning or limit of active policies 1031 if (hasWarning && policy.warningBytes < lowestRule) { 1032 lowestRule = policy.warningBytes; 1033 } 1034 if (hasLimit && policy.limitBytes < lowestRule) { 1035 lowestRule = policy.limitBytes; 1036 } 1037 } 1038 1039 mHandler.obtainMessage(MSG_ADVISE_PERSIST_THRESHOLD, lowestRule).sendToTarget(); 1040 1041 // remove quota on any trailing interfaces 1042 for (String iface : mMeteredIfaces) { 1043 if (!newMeteredIfaces.contains(iface)) { 1044 removeInterfaceQuota(iface); 1045 } 1046 } 1047 mMeteredIfaces = newMeteredIfaces; 1048 1049 final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]); 1050 mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget(); 1051 } 1052 1053 /** 1054 * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we 1055 * have at least a default mobile policy defined. 1056 */ 1057 private void ensureActiveMobilePolicyLocked() { 1058 if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()"); 1059 if (mSuppressDefaultPolicy) return; 1060 1061 final TelephonyManager tele = TelephonyManager.from(mContext); 1062 1063 // avoid creating policy when SIM isn't ready 1064 if (tele.getSimState() != SIM_STATE_READY) return; 1065 1066 final String subscriberId = tele.getSubscriberId(); 1067 final NetworkIdentity probeIdent = new NetworkIdentity( 1068 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false); 1069 1070 // examine to see if any policy is defined for active mobile 1071 boolean mobileDefined = false; 1072 for (NetworkPolicy policy : mNetworkPolicy.values()) { 1073 if (policy.template.matches(probeIdent)) { 1074 mobileDefined = true; 1075 } 1076 } 1077 1078 if (!mobileDefined) { 1079 Slog.i(TAG, "no policy for active mobile network; generating default policy"); 1080 1081 // build default mobile policy, and assume usage cycle starts today 1082 final long warningBytes = mContext.getResources().getInteger( 1083 com.android.internal.R.integer.config_networkPolicyDefaultWarning) 1084 * MB_IN_BYTES; 1085 1086 final Time time = new Time(); 1087 time.setToNow(); 1088 1089 final int cycleDay = time.monthDay; 1090 final String cycleTimezone = time.timezone; 1091 1092 final NetworkTemplate template = buildTemplateMobileAll(subscriberId); 1093 final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone, 1094 warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true); 1095 addNetworkPolicyLocked(policy); 1096 } 1097 } 1098 1099 private void readPolicyLocked() { 1100 if (LOGV) Slog.v(TAG, "readPolicyLocked()"); 1101 1102 // clear any existing policy and read from disk 1103 mNetworkPolicy.clear(); 1104 mAppPolicy.clear(); 1105 1106 FileInputStream fis = null; 1107 try { 1108 fis = mPolicyFile.openRead(); 1109 final XmlPullParser in = Xml.newPullParser(); 1110 in.setInput(fis, null); 1111 1112 int type; 1113 int version = VERSION_INIT; 1114 while ((type = in.next()) != END_DOCUMENT) { 1115 final String tag = in.getName(); 1116 if (type == START_TAG) { 1117 if (TAG_POLICY_LIST.equals(tag)) { 1118 version = readIntAttribute(in, ATTR_VERSION); 1119 if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) { 1120 mRestrictBackground = readBooleanAttribute( 1121 in, ATTR_RESTRICT_BACKGROUND); 1122 } else { 1123 mRestrictBackground = false; 1124 } 1125 1126 } else if (TAG_NETWORK_POLICY.equals(tag)) { 1127 final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE); 1128 final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID); 1129 final String networkId; 1130 if (version >= VERSION_ADDED_NETWORK_ID) { 1131 networkId = in.getAttributeValue(null, ATTR_NETWORK_ID); 1132 } else { 1133 networkId = null; 1134 } 1135 final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY); 1136 final String cycleTimezone; 1137 if (version >= VERSION_ADDED_TIMEZONE) { 1138 cycleTimezone = in.getAttributeValue(null, ATTR_CYCLE_TIMEZONE); 1139 } else { 1140 cycleTimezone = Time.TIMEZONE_UTC; 1141 } 1142 final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES); 1143 final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES); 1144 final long lastLimitSnooze; 1145 if (version >= VERSION_SPLIT_SNOOZE) { 1146 lastLimitSnooze = readLongAttribute(in, ATTR_LAST_LIMIT_SNOOZE); 1147 } else if (version >= VERSION_ADDED_SNOOZE) { 1148 lastLimitSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE); 1149 } else { 1150 lastLimitSnooze = SNOOZE_NEVER; 1151 } 1152 final boolean metered; 1153 if (version >= VERSION_ADDED_METERED) { 1154 metered = readBooleanAttribute(in, ATTR_METERED); 1155 } else { 1156 switch (networkTemplate) { 1157 case MATCH_MOBILE_3G_LOWER: 1158 case MATCH_MOBILE_4G: 1159 case MATCH_MOBILE_ALL: 1160 metered = true; 1161 break; 1162 default: 1163 metered = false; 1164 } 1165 } 1166 final long lastWarningSnooze; 1167 if (version >= VERSION_SPLIT_SNOOZE) { 1168 lastWarningSnooze = readLongAttribute(in, ATTR_LAST_WARNING_SNOOZE); 1169 } else { 1170 lastWarningSnooze = SNOOZE_NEVER; 1171 } 1172 final boolean inferred; 1173 if (version >= VERSION_ADDED_INFERRED) { 1174 inferred = readBooleanAttribute(in, ATTR_INFERRED); 1175 } else { 1176 inferred = false; 1177 } 1178 1179 final NetworkTemplate template = new NetworkTemplate( 1180 networkTemplate, subscriberId, networkId); 1181 mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay, 1182 cycleTimezone, warningBytes, limitBytes, lastWarningSnooze, 1183 lastLimitSnooze, metered, inferred)); 1184 1185 } else if (TAG_UID_POLICY.equals(tag) && version < VERSION_SWITCH_APP_ID) { 1186 final int uid = readIntAttribute(in, ATTR_UID); 1187 final int policy = readIntAttribute(in, ATTR_POLICY); 1188 1189 final int appId = UserId.getAppId(uid); 1190 if (UserId.isApp(appId)) { 1191 setAppPolicyUnchecked(appId, policy, false); 1192 } else { 1193 Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring"); 1194 } 1195 } else if (TAG_APP_POLICY.equals(tag) && version >= VERSION_SWITCH_APP_ID) { 1196 final int appId = readIntAttribute(in, ATTR_APP_ID); 1197 final int policy = readIntAttribute(in, ATTR_POLICY); 1198 1199 if (UserId.isApp(appId)) { 1200 setAppPolicyUnchecked(appId, policy, false); 1201 } else { 1202 Slog.w(TAG, "unable to apply policy to appId " + appId + "; ignoring"); 1203 } 1204 } 1205 } 1206 } 1207 1208 } catch (FileNotFoundException e) { 1209 // missing policy is okay, probably first boot 1210 upgradeLegacyBackgroundData(); 1211 } catch (IOException e) { 1212 Log.wtf(TAG, "problem reading network policy", e); 1213 } catch (XmlPullParserException e) { 1214 Log.wtf(TAG, "problem reading network policy", e); 1215 } finally { 1216 IoUtils.closeQuietly(fis); 1217 } 1218 } 1219 1220 /** 1221 * Upgrade legacy background data flags, notifying listeners of one last 1222 * change to always-true. 1223 */ 1224 private void upgradeLegacyBackgroundData() { 1225 mRestrictBackground = Settings.Secure.getInt( 1226 mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1; 1227 1228 // kick off one last broadcast if restricted 1229 if (mRestrictBackground) { 1230 final Intent broadcast = new Intent( 1231 ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED); 1232 mContext.sendBroadcast(broadcast); 1233 } 1234 } 1235 1236 private void writePolicyLocked() { 1237 if (LOGV) Slog.v(TAG, "writePolicyLocked()"); 1238 1239 FileOutputStream fos = null; 1240 try { 1241 fos = mPolicyFile.startWrite(); 1242 1243 XmlSerializer out = new FastXmlSerializer(); 1244 out.setOutput(fos, "utf-8"); 1245 out.startDocument(null, true); 1246 1247 out.startTag(null, TAG_POLICY_LIST); 1248 writeIntAttribute(out, ATTR_VERSION, VERSION_LATEST); 1249 writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground); 1250 1251 // write all known network policies 1252 for (NetworkPolicy policy : mNetworkPolicy.values()) { 1253 final NetworkTemplate template = policy.template; 1254 1255 out.startTag(null, TAG_NETWORK_POLICY); 1256 writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule()); 1257 final String subscriberId = template.getSubscriberId(); 1258 if (subscriberId != null) { 1259 out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId); 1260 } 1261 final String networkId = template.getNetworkId(); 1262 if (networkId != null) { 1263 out.attribute(null, ATTR_NETWORK_ID, networkId); 1264 } 1265 writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay); 1266 out.attribute(null, ATTR_CYCLE_TIMEZONE, policy.cycleTimezone); 1267 writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes); 1268 writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes); 1269 writeLongAttribute(out, ATTR_LAST_WARNING_SNOOZE, policy.lastWarningSnooze); 1270 writeLongAttribute(out, ATTR_LAST_LIMIT_SNOOZE, policy.lastLimitSnooze); 1271 writeBooleanAttribute(out, ATTR_METERED, policy.metered); 1272 writeBooleanAttribute(out, ATTR_INFERRED, policy.inferred); 1273 out.endTag(null, TAG_NETWORK_POLICY); 1274 } 1275 1276 // write all known uid policies 1277 for (int i = 0; i < mAppPolicy.size(); i++) { 1278 final int appId = mAppPolicy.keyAt(i); 1279 final int policy = mAppPolicy.valueAt(i); 1280 1281 // skip writing empty policies 1282 if (policy == POLICY_NONE) continue; 1283 1284 out.startTag(null, TAG_APP_POLICY); 1285 writeIntAttribute(out, ATTR_APP_ID, appId); 1286 writeIntAttribute(out, ATTR_POLICY, policy); 1287 out.endTag(null, TAG_APP_POLICY); 1288 } 1289 1290 out.endTag(null, TAG_POLICY_LIST); 1291 out.endDocument(); 1292 1293 mPolicyFile.finishWrite(fos); 1294 } catch (IOException e) { 1295 if (fos != null) { 1296 mPolicyFile.failWrite(fos); 1297 } 1298 } 1299 } 1300 1301 @Override 1302 public void setAppPolicy(int appId, int policy) { 1303 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1304 1305 if (!UserId.isApp(appId)) { 1306 throw new IllegalArgumentException("cannot apply policy to appId " + appId); 1307 } 1308 1309 setAppPolicyUnchecked(appId, policy, true); 1310 } 1311 1312 private void setAppPolicyUnchecked(int appId, int policy, boolean persist) { 1313 final int oldPolicy; 1314 synchronized (mRulesLock) { 1315 oldPolicy = getAppPolicy(appId); 1316 mAppPolicy.put(appId, policy); 1317 1318 // uid policy changed, recompute rules and persist policy. 1319 updateRulesForAppLocked(appId); 1320 if (persist) { 1321 writePolicyLocked(); 1322 } 1323 } 1324 } 1325 1326 @Override 1327 public int getAppPolicy(int appId) { 1328 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1329 1330 synchronized (mRulesLock) { 1331 return mAppPolicy.get(appId, POLICY_NONE); 1332 } 1333 } 1334 1335 @Override 1336 public int[] getAppsWithPolicy(int policy) { 1337 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1338 1339 int[] appIds = new int[0]; 1340 synchronized (mRulesLock) { 1341 for (int i = 0; i < mAppPolicy.size(); i++) { 1342 final int appId = mAppPolicy.keyAt(i); 1343 final int appPolicy = mAppPolicy.valueAt(i); 1344 if (appPolicy == policy) { 1345 appIds = appendInt(appIds, appId); 1346 } 1347 } 1348 } 1349 return appIds; 1350 } 1351 1352 @Override 1353 public void registerListener(INetworkPolicyListener listener) { 1354 // TODO: create permission for observing network policy 1355 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1356 1357 mListeners.register(listener); 1358 1359 // TODO: consider dispatching existing rules to new listeners 1360 } 1361 1362 @Override 1363 public void unregisterListener(INetworkPolicyListener listener) { 1364 // TODO: create permission for observing network policy 1365 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1366 1367 mListeners.unregister(listener); 1368 } 1369 1370 @Override 1371 public void setNetworkPolicies(NetworkPolicy[] policies) { 1372 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1373 1374 maybeRefreshTrustedTime(); 1375 synchronized (mRulesLock) { 1376 mNetworkPolicy.clear(); 1377 for (NetworkPolicy policy : policies) { 1378 mNetworkPolicy.put(policy.template, policy); 1379 } 1380 1381 updateNetworkEnabledLocked(); 1382 updateNetworkRulesLocked(); 1383 updateNotificationsLocked(); 1384 writePolicyLocked(); 1385 } 1386 } 1387 1388 private void addNetworkPolicyLocked(NetworkPolicy policy) { 1389 mNetworkPolicy.put(policy.template, policy); 1390 1391 updateNetworkEnabledLocked(); 1392 updateNetworkRulesLocked(); 1393 updateNotificationsLocked(); 1394 writePolicyLocked(); 1395 } 1396 1397 @Override 1398 public NetworkPolicy[] getNetworkPolicies() { 1399 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1400 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG); 1401 1402 synchronized (mRulesLock) { 1403 return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]); 1404 } 1405 } 1406 1407 @Override 1408 public void snoozeLimit(NetworkTemplate template) { 1409 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1410 performSnooze(template, TYPE_LIMIT); 1411 } 1412 1413 private void performSnooze(NetworkTemplate template, int type) { 1414 maybeRefreshTrustedTime(); 1415 final long currentTime = currentTimeMillis(); 1416 synchronized (mRulesLock) { 1417 // find and snooze local policy that matches 1418 final NetworkPolicy policy = mNetworkPolicy.get(template); 1419 if (policy == null) { 1420 throw new IllegalArgumentException("unable to find policy for " + template); 1421 } 1422 1423 switch (type) { 1424 case TYPE_WARNING: 1425 policy.lastWarningSnooze = currentTime; 1426 break; 1427 case TYPE_LIMIT: 1428 policy.lastLimitSnooze = currentTime; 1429 break; 1430 default: 1431 throw new IllegalArgumentException("unexpected type"); 1432 } 1433 1434 updateNetworkEnabledLocked(); 1435 updateNetworkRulesLocked(); 1436 updateNotificationsLocked(); 1437 writePolicyLocked(); 1438 } 1439 } 1440 1441 @Override 1442 public void setRestrictBackground(boolean restrictBackground) { 1443 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1444 1445 maybeRefreshTrustedTime(); 1446 synchronized (mRulesLock) { 1447 mRestrictBackground = restrictBackground; 1448 updateRulesForRestrictBackgroundLocked(); 1449 updateNotificationsLocked(); 1450 writePolicyLocked(); 1451 } 1452 1453 mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED, restrictBackground ? 1 : 0, 0) 1454 .sendToTarget(); 1455 } 1456 1457 @Override 1458 public boolean getRestrictBackground() { 1459 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1460 1461 synchronized (mRulesLock) { 1462 return mRestrictBackground; 1463 } 1464 } 1465 1466 private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) { 1467 for (NetworkPolicy policy : mNetworkPolicy.values()) { 1468 if (policy.template.matches(ident)) { 1469 return policy; 1470 } 1471 } 1472 return null; 1473 } 1474 1475 @Override 1476 public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) { 1477 mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 1478 1479 // only returns usage summary, so we don't require caller to have 1480 // READ_NETWORK_USAGE_HISTORY. 1481 final long token = Binder.clearCallingIdentity(); 1482 try { 1483 return getNetworkQuotaInfoUnchecked(state); 1484 } finally { 1485 Binder.restoreCallingIdentity(token); 1486 } 1487 } 1488 1489 private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) { 1490 final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); 1491 1492 final NetworkPolicy policy; 1493 synchronized (mRulesLock) { 1494 policy = findPolicyForNetworkLocked(ident); 1495 } 1496 1497 if (policy == null || !policy.hasCycle()) { 1498 // missing policy means we can't derive useful quota info 1499 return null; 1500 } 1501 1502 final long currentTime = currentTimeMillis(); 1503 1504 // find total bytes used under policy 1505 final long start = computeLastCycleBoundary(currentTime, policy); 1506 final long end = currentTime; 1507 final long totalBytes = getTotalBytes(policy.template, start, end); 1508 1509 // report soft and hard limits under policy 1510 final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes 1511 : NetworkQuotaInfo.NO_LIMIT; 1512 final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes 1513 : NetworkQuotaInfo.NO_LIMIT; 1514 1515 return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes); 1516 } 1517 1518 @Override 1519 public boolean isNetworkMetered(NetworkState state) { 1520 final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); 1521 1522 // roaming networks are always considered metered 1523 if (ident.getRoaming()) { 1524 return true; 1525 } 1526 1527 final NetworkPolicy policy; 1528 synchronized (mRulesLock) { 1529 policy = findPolicyForNetworkLocked(ident); 1530 } 1531 1532 if (policy != null) { 1533 return policy.metered; 1534 } else { 1535 final int type = state.networkInfo.getType(); 1536 if (isNetworkTypeMobile(type) || type == TYPE_WIMAX) { 1537 return true; 1538 } 1539 return false; 1540 } 1541 } 1542 1543 @Override 1544 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1545 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 1546 1547 final IndentingPrintWriter fout = new IndentingPrintWriter(writer, " "); 1548 1549 final HashSet<String> argSet = new HashSet<String>(); 1550 for (String arg : args) { 1551 argSet.add(arg); 1552 } 1553 1554 synchronized (mRulesLock) { 1555 if (argSet.contains("--unsnooze")) { 1556 for (NetworkPolicy policy : mNetworkPolicy.values()) { 1557 policy.clearSnooze(); 1558 } 1559 1560 updateNetworkEnabledLocked(); 1561 updateNetworkRulesLocked(); 1562 updateNotificationsLocked(); 1563 writePolicyLocked(); 1564 1565 fout.println("Cleared snooze timestamps"); 1566 return; 1567 } 1568 1569 fout.print("Restrict background: "); fout.println(mRestrictBackground); 1570 fout.println("Network policies:"); 1571 fout.increaseIndent(); 1572 for (NetworkPolicy policy : mNetworkPolicy.values()) { 1573 fout.println(policy.toString()); 1574 } 1575 fout.decreaseIndent(); 1576 1577 fout.println("Policy for apps:"); 1578 fout.increaseIndent(); 1579 int size = mAppPolicy.size(); 1580 for (int i = 0; i < size; i++) { 1581 final int appId = mAppPolicy.keyAt(i); 1582 final int policy = mAppPolicy.valueAt(i); 1583 fout.print("appId="); 1584 fout.print(appId); 1585 fout.print(" policy="); 1586 dumpPolicy(fout, policy); 1587 fout.println(); 1588 } 1589 fout.decreaseIndent(); 1590 1591 final SparseBooleanArray knownUids = new SparseBooleanArray(); 1592 collectKeys(mUidForeground, knownUids); 1593 collectKeys(mUidRules, knownUids); 1594 1595 fout.println("Status for known UIDs:"); 1596 fout.increaseIndent(); 1597 size = knownUids.size(); 1598 for (int i = 0; i < size; i++) { 1599 final int uid = knownUids.keyAt(i); 1600 fout.print("UID="); 1601 fout.print(uid); 1602 1603 fout.print(" foreground="); 1604 final int foregroundIndex = mUidPidForeground.indexOfKey(uid); 1605 if (foregroundIndex < 0) { 1606 fout.print("UNKNOWN"); 1607 } else { 1608 dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex)); 1609 } 1610 1611 fout.print(" rules="); 1612 final int rulesIndex = mUidRules.indexOfKey(uid); 1613 if (rulesIndex < 0) { 1614 fout.print("UNKNOWN"); 1615 } else { 1616 dumpRules(fout, mUidRules.valueAt(rulesIndex)); 1617 } 1618 1619 fout.println(); 1620 } 1621 fout.decreaseIndent(); 1622 } 1623 } 1624 1625 @Override 1626 public boolean isUidForeground(int uid) { 1627 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1628 1629 synchronized (mRulesLock) { 1630 // only really in foreground when screen is also on 1631 return mUidForeground.get(uid, false) && mScreenOn; 1632 } 1633 } 1634 1635 /** 1636 * Foreground for PID changed; recompute foreground at UID level. If 1637 * changed, will trigger {@link #updateRulesForUidLocked(int)}. 1638 */ 1639 private void computeUidForegroundLocked(int uid) { 1640 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 1641 1642 // current pid is dropping foreground; examine other pids 1643 boolean uidForeground = false; 1644 final int size = pidForeground.size(); 1645 for (int i = 0; i < size; i++) { 1646 if (pidForeground.valueAt(i)) { 1647 uidForeground = true; 1648 break; 1649 } 1650 } 1651 1652 final boolean oldUidForeground = mUidForeground.get(uid, false); 1653 if (oldUidForeground != uidForeground) { 1654 // foreground changed, push updated rules 1655 mUidForeground.put(uid, uidForeground); 1656 updateRulesForUidLocked(uid); 1657 } 1658 } 1659 1660 private void updateScreenOn() { 1661 synchronized (mRulesLock) { 1662 try { 1663 mScreenOn = mPowerManager.isScreenOn(); 1664 } catch (RemoteException e) { 1665 // ignored; service lives in system_server 1666 } 1667 updateRulesForScreenLocked(); 1668 } 1669 } 1670 1671 /** 1672 * Update rules that might be changed by {@link #mScreenOn} value. 1673 */ 1674 private void updateRulesForScreenLocked() { 1675 // only update rules for anyone with foreground activities 1676 final int size = mUidForeground.size(); 1677 for (int i = 0; i < size; i++) { 1678 if (mUidForeground.valueAt(i)) { 1679 final int uid = mUidForeground.keyAt(i); 1680 updateRulesForUidLocked(uid); 1681 } 1682 } 1683 } 1684 1685 /** 1686 * Update rules that might be changed by {@link #mRestrictBackground} value. 1687 */ 1688 private void updateRulesForRestrictBackgroundLocked() { 1689 // update rules for all installed applications 1690 final PackageManager pm = mContext.getPackageManager(); 1691 final List<ApplicationInfo> apps = pm.getInstalledApplications(0); 1692 for (ApplicationInfo app : apps) { 1693 final int appId = UserId.getAppId(app.uid); 1694 updateRulesForAppLocked(appId); 1695 } 1696 1697 // limit data usage for some internal system services 1698 updateRulesForUidLocked(android.os.Process.MEDIA_UID); 1699 updateRulesForUidLocked(android.os.Process.DRM_UID); 1700 } 1701 1702 private void updateRulesForAppLocked(int appId) { 1703 for (UserInfo user : mContext.getPackageManager().getUsers()) { 1704 final int uid = UserId.getUid(user.id, appId); 1705 updateRulesForUidLocked(uid); 1706 } 1707 } 1708 1709 private static boolean isUidValidForRules(int uid) { 1710 // allow rules on specific system services, and any apps 1711 if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID 1712 || UserId.isApp(uid)) { 1713 return true; 1714 } 1715 1716 return false; 1717 } 1718 1719 private void updateRulesForUidLocked(int uid) { 1720 if (!isUidValidForRules(uid)) return; 1721 1722 final int appId = UserId.getAppId(uid); 1723 final int appPolicy = getAppPolicy(appId); 1724 final boolean uidForeground = isUidForeground(uid); 1725 1726 // derive active rules based on policy and active state 1727 int uidRules = RULE_ALLOW_ALL; 1728 if (!uidForeground && (appPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { 1729 // uid in background, and policy says to block metered data 1730 uidRules = RULE_REJECT_METERED; 1731 } 1732 if (!uidForeground && mRestrictBackground) { 1733 // uid in background, and global background disabled 1734 uidRules = RULE_REJECT_METERED; 1735 } 1736 1737 // TODO: only dispatch when rules actually change 1738 1739 if (uidRules == RULE_ALLOW_ALL) { 1740 mUidRules.delete(uid); 1741 } else { 1742 mUidRules.put(uid, uidRules); 1743 } 1744 1745 final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0; 1746 setUidNetworkRules(uid, rejectMetered); 1747 1748 // dispatch changed rule to existing listeners 1749 mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget(); 1750 1751 try { 1752 // adjust stats accounting based on foreground status 1753 mNetworkStats.setUidForeground(uid, uidForeground); 1754 } catch (RemoteException e) { 1755 // ignored; service lives in system_server 1756 } 1757 } 1758 1759 private Handler.Callback mHandlerCallback = new Handler.Callback() { 1760 @Override 1761 public boolean handleMessage(Message msg) { 1762 switch (msg.what) { 1763 case MSG_RULES_CHANGED: { 1764 final int uid = msg.arg1; 1765 final int uidRules = msg.arg2; 1766 final int length = mListeners.beginBroadcast(); 1767 for (int i = 0; i < length; i++) { 1768 final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 1769 if (listener != null) { 1770 try { 1771 listener.onUidRulesChanged(uid, uidRules); 1772 } catch (RemoteException e) { 1773 } 1774 } 1775 } 1776 mListeners.finishBroadcast(); 1777 return true; 1778 } 1779 case MSG_METERED_IFACES_CHANGED: { 1780 final String[] meteredIfaces = (String[]) msg.obj; 1781 final int length = mListeners.beginBroadcast(); 1782 for (int i = 0; i < length; i++) { 1783 final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 1784 if (listener != null) { 1785 try { 1786 listener.onMeteredIfacesChanged(meteredIfaces); 1787 } catch (RemoteException e) { 1788 } 1789 } 1790 } 1791 mListeners.finishBroadcast(); 1792 return true; 1793 } 1794 case MSG_FOREGROUND_ACTIVITIES_CHANGED: { 1795 final int pid = msg.arg1; 1796 final int uid = msg.arg2; 1797 final boolean foregroundActivities = (Boolean) msg.obj; 1798 1799 synchronized (mRulesLock) { 1800 // because a uid can have multiple pids running inside, we need to 1801 // remember all pid states and summarize foreground at uid level. 1802 1803 // record foreground for this specific pid 1804 SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 1805 if (pidForeground == null) { 1806 pidForeground = new SparseBooleanArray(2); 1807 mUidPidForeground.put(uid, pidForeground); 1808 } 1809 pidForeground.put(pid, foregroundActivities); 1810 computeUidForegroundLocked(uid); 1811 } 1812 return true; 1813 } 1814 case MSG_PROCESS_DIED: { 1815 final int pid = msg.arg1; 1816 final int uid = msg.arg2; 1817 1818 synchronized (mRulesLock) { 1819 // clear records and recompute, when they exist 1820 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 1821 if (pidForeground != null) { 1822 pidForeground.delete(pid); 1823 computeUidForegroundLocked(uid); 1824 } 1825 } 1826 return true; 1827 } 1828 case MSG_LIMIT_REACHED: { 1829 final String iface = (String) msg.obj; 1830 1831 maybeRefreshTrustedTime(); 1832 synchronized (mRulesLock) { 1833 if (mMeteredIfaces.contains(iface)) { 1834 try { 1835 // force stats update to make sure we have 1836 // numbers that caused alert to trigger. 1837 mNetworkStats.forceUpdate(); 1838 } catch (RemoteException e) { 1839 // ignored; service lives in system_server 1840 } 1841 1842 updateNetworkEnabledLocked(); 1843 updateNotificationsLocked(); 1844 } 1845 } 1846 return true; 1847 } 1848 case MSG_RESTRICT_BACKGROUND_CHANGED: { 1849 final boolean restrictBackground = msg.arg1 != 0; 1850 final int length = mListeners.beginBroadcast(); 1851 for (int i = 0; i < length; i++) { 1852 final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 1853 if (listener != null) { 1854 try { 1855 listener.onRestrictBackgroundChanged(restrictBackground); 1856 } catch (RemoteException e) { 1857 } 1858 } 1859 } 1860 mListeners.finishBroadcast(); 1861 return true; 1862 } 1863 case MSG_ADVISE_PERSIST_THRESHOLD: { 1864 final long lowestRule = (Long) msg.obj; 1865 try { 1866 // make sure stats are recorded frequently enough; we aim 1867 // for 2MB threshold for 2GB/month rules. 1868 final long persistThreshold = lowestRule / 1000; 1869 mNetworkStats.advisePersistThreshold(persistThreshold); 1870 } catch (RemoteException e) { 1871 // ignored; service lives in system_server 1872 } 1873 return true; 1874 } 1875 default: { 1876 return false; 1877 } 1878 } 1879 } 1880 }; 1881 1882 private void setInterfaceQuota(String iface, long quotaBytes) { 1883 try { 1884 mNetworkManager.setInterfaceQuota(iface, quotaBytes); 1885 } catch (IllegalStateException e) { 1886 Log.wtf(TAG, "problem setting interface quota", e); 1887 } catch (RemoteException e) { 1888 // ignored; service lives in system_server 1889 } 1890 } 1891 1892 private void removeInterfaceQuota(String iface) { 1893 try { 1894 mNetworkManager.removeInterfaceQuota(iface); 1895 } catch (IllegalStateException e) { 1896 Log.wtf(TAG, "problem removing interface quota", e); 1897 } catch (RemoteException e) { 1898 // ignored; service lives in system_server 1899 } 1900 } 1901 1902 private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1903 try { 1904 mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces); 1905 } catch (IllegalStateException e) { 1906 Log.wtf(TAG, "problem setting uid rules", e); 1907 } catch (RemoteException e) { 1908 // ignored; service lives in system_server 1909 } 1910 } 1911 1912 /** 1913 * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}. 1914 */ 1915 private void setPolicyDataEnable(int networkType, boolean enabled) { 1916 try { 1917 mConnManager.setPolicyDataEnable(networkType, enabled); 1918 } catch (RemoteException e) { 1919 // ignored; service lives in system_server 1920 } 1921 } 1922 1923 private long getTotalBytes(NetworkTemplate template, long start, long end) { 1924 try { 1925 return mNetworkStats.getNetworkTotalBytes(template, start, end); 1926 } catch (RuntimeException e) { 1927 Slog.w(TAG, "problem reading network stats: " + e); 1928 return 0; 1929 } catch (RemoteException e) { 1930 // ignored; service lives in system_server 1931 return 0; 1932 } 1933 } 1934 1935 private boolean isBandwidthControlEnabled() { 1936 final long token = Binder.clearCallingIdentity(); 1937 try { 1938 return mNetworkManager.isBandwidthControlEnabled(); 1939 } catch (RemoteException e) { 1940 // ignored; service lives in system_server 1941 return false; 1942 } finally { 1943 Binder.restoreCallingIdentity(token); 1944 } 1945 } 1946 1947 /** 1948 * Try refreshing {@link #mTime} when stale. 1949 */ 1950 private void maybeRefreshTrustedTime() { 1951 if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) { 1952 mTime.forceRefresh(); 1953 } 1954 } 1955 1956 private long currentTimeMillis() { 1957 return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis(); 1958 } 1959 1960 private static Intent buildAllowBackgroundDataIntent() { 1961 return new Intent(ACTION_ALLOW_BACKGROUND); 1962 } 1963 1964 private static Intent buildSnoozeWarningIntent(NetworkTemplate template) { 1965 final Intent intent = new Intent(ACTION_SNOOZE_WARNING); 1966 intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); 1967 return intent; 1968 } 1969 1970 private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) { 1971 final Intent intent = new Intent(); 1972 intent.setComponent(new ComponentName( 1973 "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity")); 1974 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1975 intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); 1976 return intent; 1977 } 1978 1979 private static Intent buildViewDataUsageIntent(NetworkTemplate template) { 1980 final Intent intent = new Intent(); 1981 intent.setComponent(new ComponentName( 1982 "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity")); 1983 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1984 intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); 1985 return intent; 1986 } 1987 1988 // @VisibleForTesting 1989 public void addIdleHandler(IdleHandler handler) { 1990 mHandler.getLooper().getQueue().addIdleHandler(handler); 1991 } 1992 1993 private static void collectKeys(SparseIntArray source, SparseBooleanArray target) { 1994 final int size = source.size(); 1995 for (int i = 0; i < size; i++) { 1996 target.put(source.keyAt(i), true); 1997 } 1998 } 1999 2000 private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) { 2001 final int size = source.size(); 2002 for (int i = 0; i < size; i++) { 2003 target.put(source.keyAt(i), true); 2004 } 2005 } 2006 2007 private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) { 2008 fout.print("["); 2009 final int size = value.size(); 2010 for (int i = 0; i < size; i++) { 2011 fout.print(value.keyAt(i) + "=" + value.valueAt(i)); 2012 if (i < size - 1) fout.print(","); 2013 } 2014 fout.print("]"); 2015 } 2016 2017 public static class XmlUtils { 2018 public static int readIntAttribute(XmlPullParser in, String name) throws IOException { 2019 final String value = in.getAttributeValue(null, name); 2020 try { 2021 return Integer.parseInt(value); 2022 } catch (NumberFormatException e) { 2023 throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 2024 } 2025 } 2026 2027 public static void writeIntAttribute(XmlSerializer out, String name, int value) 2028 throws IOException { 2029 out.attribute(null, name, Integer.toString(value)); 2030 } 2031 2032 public static long readLongAttribute(XmlPullParser in, String name) throws IOException { 2033 final String value = in.getAttributeValue(null, name); 2034 try { 2035 return Long.parseLong(value); 2036 } catch (NumberFormatException e) { 2037 throw new ProtocolException("problem parsing " + name + "=" + value + " as long"); 2038 } 2039 } 2040 2041 public static void writeLongAttribute(XmlSerializer out, String name, long value) 2042 throws IOException { 2043 out.attribute(null, name, Long.toString(value)); 2044 } 2045 2046 public static boolean readBooleanAttribute(XmlPullParser in, String name) { 2047 final String value = in.getAttributeValue(null, name); 2048 return Boolean.parseBoolean(value); 2049 } 2050 2051 public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value) 2052 throws IOException { 2053 out.attribute(null, name, Boolean.toString(value)); 2054 } 2055 } 2056} 2057