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