NetworkPolicyManagerService.java revision 961e30458319cfd50e1892ba7dd14a1d0ebe4cc7
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_APP_TOKENS; 23import static android.Manifest.permission.MANAGE_NETWORK_POLICY; 24import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; 25import static android.Manifest.permission.READ_PHONE_STATE; 26import static android.content.Intent.ACTION_PACKAGE_ADDED; 27import static android.content.Intent.ACTION_UID_REMOVED; 28import static android.content.Intent.EXTRA_UID; 29import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; 30import static android.net.ConnectivityManager.TYPE_ETHERNET; 31import static android.net.ConnectivityManager.TYPE_MOBILE; 32import static android.net.ConnectivityManager.TYPE_WIFI; 33import static android.net.ConnectivityManager.TYPE_WIMAX; 34import static android.net.NetworkPolicy.LIMIT_DISABLED; 35import static android.net.NetworkPolicy.SNOOZE_NEVER; 36import static android.net.NetworkPolicy.WARNING_DISABLED; 37import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE; 38import static android.net.NetworkPolicyManager.POLICY_NONE; 39import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; 40import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; 41import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; 42import static android.net.NetworkPolicyManager.computeLastCycleBoundary; 43import static android.net.NetworkPolicyManager.dumpPolicy; 44import static android.net.NetworkPolicyManager.dumpRules; 45import static android.net.NetworkPolicyManager.isUidValidForPolicy; 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.text.format.DateUtils.DAY_IN_MILLIS; 53import static com.android.internal.util.Preconditions.checkNotNull; 54import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; 55import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readBooleanAttribute; 56import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readIntAttribute; 57import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readLongAttribute; 58import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeBooleanAttribute; 59import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeIntAttribute; 60import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeLongAttribute; 61import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED; 62import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 63import static org.xmlpull.v1.XmlPullParser.START_TAG; 64 65import android.app.IActivityManager; 66import android.app.INotificationManager; 67import android.app.IProcessObserver; 68import android.app.Notification; 69import android.app.PendingIntent; 70import android.content.BroadcastReceiver; 71import android.content.ComponentName; 72import android.content.Context; 73import android.content.Intent; 74import android.content.IntentFilter; 75import android.content.pm.ApplicationInfo; 76import android.content.pm.PackageManager; 77import android.content.res.Resources; 78import android.net.ConnectivityManager; 79import android.net.IConnectivityManager; 80import android.net.INetworkManagementEventObserver; 81import android.net.INetworkPolicyListener; 82import android.net.INetworkPolicyManager; 83import android.net.INetworkStatsService; 84import android.net.NetworkIdentity; 85import android.net.NetworkPolicy; 86import android.net.NetworkQuotaInfo; 87import android.net.NetworkState; 88import android.net.NetworkStats; 89import android.net.NetworkTemplate; 90import android.os.Binder; 91import android.os.Environment; 92import android.os.Handler; 93import android.os.HandlerThread; 94import android.os.INetworkManagementService; 95import android.os.IPowerManager; 96import android.os.Message; 97import android.os.RemoteCallbackList; 98import android.os.RemoteException; 99import android.provider.Settings; 100import android.telephony.TelephonyManager; 101import android.text.format.Formatter; 102import android.text.format.Time; 103import android.util.NtpTrustedTime; 104import android.util.Slog; 105import android.util.SparseArray; 106import android.util.SparseBooleanArray; 107import android.util.SparseIntArray; 108import android.util.TrustedTime; 109import android.util.Xml; 110 111import com.android.internal.R; 112import com.android.internal.os.AtomicFile; 113import com.android.internal.util.FastXmlSerializer; 114import com.android.internal.util.Objects; 115import com.google.android.collect.Lists; 116import com.google.android.collect.Maps; 117import com.google.android.collect.Sets; 118 119import org.xmlpull.v1.XmlPullParser; 120import org.xmlpull.v1.XmlPullParserException; 121import org.xmlpull.v1.XmlSerializer; 122 123import java.io.File; 124import java.io.FileDescriptor; 125import java.io.FileInputStream; 126import java.io.FileNotFoundException; 127import java.io.FileOutputStream; 128import java.io.IOException; 129import java.io.PrintWriter; 130import java.net.ProtocolException; 131import java.util.ArrayList; 132import java.util.Arrays; 133import java.util.HashMap; 134import java.util.HashSet; 135import java.util.List; 136import java.util.Map; 137 138import libcore.io.IoUtils; 139 140/** 141 * Service that maintains low-level network policy rules, using 142 * {@link NetworkStatsService} statistics to drive those rules. 143 * <p> 144 * Derives active rules by combining a given policy with other system status, 145 * and delivers to listeners, such as {@link ConnectivityManager}, for 146 * enforcement. 147 */ 148public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 149 private static final String TAG = "NetworkPolicy"; 150 private static final boolean LOGD = true; 151 private static final boolean LOGV = false; 152 153 private static final int VERSION_INIT = 1; 154 private static final int VERSION_ADDED_SNOOZE = 2; 155 private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3; 156 157 private static final long KB_IN_BYTES = 1024; 158 private static final long MB_IN_BYTES = KB_IN_BYTES * 1024; 159 private static final long GB_IN_BYTES = MB_IN_BYTES * 1024; 160 161 // @VisibleForTesting 162 public static final int TYPE_WARNING = 0x1; 163 public static final int TYPE_LIMIT = 0x2; 164 public static final int TYPE_LIMIT_SNOOZED = 0x3; 165 166 private static final String TAG_POLICY_LIST = "policy-list"; 167 private static final String TAG_NETWORK_POLICY = "network-policy"; 168 private static final String TAG_UID_POLICY = "uid-policy"; 169 170 private static final String ATTR_VERSION = "version"; 171 private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground"; 172 private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate"; 173 private static final String ATTR_SUBSCRIBER_ID = "subscriberId"; 174 private static final String ATTR_CYCLE_DAY = "cycleDay"; 175 private static final String ATTR_WARNING_BYTES = "warningBytes"; 176 private static final String ATTR_LIMIT_BYTES = "limitBytes"; 177 private static final String ATTR_LAST_SNOOZE = "lastSnooze"; 178 private static final String ATTR_UID = "uid"; 179 private static final String ATTR_POLICY = "policy"; 180 181 private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground"; 182 183 // @VisibleForTesting 184 public static final String ACTION_ALLOW_BACKGROUND = 185 "com.android.server.action.ACTION_ALLOW_BACKGROUND"; 186 187 private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS; 188 189 private static final int MSG_RULES_CHANGED = 0x1; 190 private static final int MSG_METERED_IFACES_CHANGED = 0x2; 191 192 private final Context mContext; 193 private final IActivityManager mActivityManager; 194 private final IPowerManager mPowerManager; 195 private final INetworkStatsService mNetworkStats; 196 private final INetworkManagementService mNetworkManager; 197 private final TrustedTime mTime; 198 199 private IConnectivityManager mConnManager; 200 private INotificationManager mNotifManager; 201 202 private final Object mRulesLock = new Object(); 203 204 private volatile boolean mScreenOn; 205 private volatile boolean mRestrictBackground; 206 207 private final boolean mSuppressDefaultPolicy; 208 209 /** Defined network policies. */ 210 private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap(); 211 /** Currently active network rules for ifaces. */ 212 private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap(); 213 214 /** Defined UID policies. */ 215 private SparseIntArray mUidPolicy = new SparseIntArray(); 216 /** Currently derived rules for each UID. */ 217 private SparseIntArray mUidRules = new SparseIntArray(); 218 219 /** Set of ifaces that are metered. */ 220 private HashSet<String> mMeteredIfaces = Sets.newHashSet(); 221 /** Set of over-limit templates that have been notified. */ 222 private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet(); 223 224 /** Set of currently active {@link Notification} tags. */ 225 private HashSet<String> mActiveNotifs = Sets.newHashSet(); 226 /** Current values from {@link #setPolicyDataEnable(int, boolean)}. */ 227 private SparseBooleanArray mActiveNetworkEnabled = new SparseBooleanArray(); 228 229 /** Foreground at both UID and PID granularity. */ 230 private SparseBooleanArray mUidForeground = new SparseBooleanArray(); 231 private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray< 232 SparseBooleanArray>(); 233 234 private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList< 235 INetworkPolicyListener>(); 236 237 private final HandlerThread mHandlerThread; 238 private final Handler mHandler; 239 240 private final AtomicFile mPolicyFile; 241 242 // TODO: keep whitelist of system-critical services that should never have 243 // rules enforced, such as system, phone, and radio UIDs. 244 245 // TODO: migrate notifications to SystemUI 246 247 public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 248 IPowerManager powerManager, INetworkStatsService networkStats, 249 INetworkManagementService networkManagement) { 250 this(context, activityManager, powerManager, networkStats, networkManagement, 251 NtpTrustedTime.getInstance(context), getSystemDir(), false); 252 } 253 254 private static File getSystemDir() { 255 return new File(Environment.getDataDirectory(), "system"); 256 } 257 258 public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 259 IPowerManager powerManager, INetworkStatsService networkStats, 260 INetworkManagementService networkManagement, TrustedTime time, File systemDir, 261 boolean suppressDefaultPolicy) { 262 mContext = checkNotNull(context, "missing context"); 263 mActivityManager = checkNotNull(activityManager, "missing activityManager"); 264 mPowerManager = checkNotNull(powerManager, "missing powerManager"); 265 mNetworkStats = checkNotNull(networkStats, "missing networkStats"); 266 mNetworkManager = checkNotNull(networkManagement, "missing networkManagement"); 267 mTime = checkNotNull(time, "missing TrustedTime"); 268 269 mHandlerThread = new HandlerThread(TAG); 270 mHandlerThread.start(); 271 mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback); 272 273 mSuppressDefaultPolicy = suppressDefaultPolicy; 274 275 mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); 276 } 277 278 public void bindConnectivityManager(IConnectivityManager connManager) { 279 mConnManager = checkNotNull(connManager, "missing IConnectivityManager"); 280 } 281 282 public void bindNotificationManager(INotificationManager notifManager) { 283 mNotifManager = checkNotNull(notifManager, "missing INotificationManager"); 284 } 285 286 public void systemReady() { 287 synchronized (mRulesLock) { 288 // read policy from disk 289 readPolicyLocked(); 290 291 if (mRestrictBackground) { 292 updateRulesForRestrictBackgroundLocked(); 293 updateNotificationsLocked(); 294 } 295 } 296 297 updateScreenOn(); 298 299 try { 300 mActivityManager.registerProcessObserver(mProcessObserver); 301 } catch (RemoteException e) { 302 // ouch, no foregroundActivities updates means some processes may 303 // never get network access. 304 Slog.e(TAG, "unable to register IProcessObserver", e); 305 } 306 307 try { 308 mNetworkManager.registerObserver(mAlertObserver); 309 } catch (RemoteException e) { 310 // ouch, no alert updates means we fall back to 311 // ACTION_NETWORK_STATS_UPDATED broadcasts. 312 Slog.e(TAG, "unable to register INetworkManagementEventObserver", e); 313 } 314 315 // TODO: traverse existing processes to know foreground state, or have 316 // activitymanager dispatch current state when new observer attached. 317 318 final IntentFilter screenFilter = new IntentFilter(); 319 screenFilter.addAction(Intent.ACTION_SCREEN_ON); 320 screenFilter.addAction(Intent.ACTION_SCREEN_OFF); 321 mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler); 322 323 // watch for network interfaces to be claimed 324 final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE); 325 mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); 326 327 // listen for package/uid changes to update policy 328 final IntentFilter packageFilter = new IntentFilter(); 329 packageFilter.addAction(ACTION_PACKAGE_ADDED); 330 packageFilter.addAction(ACTION_UID_REMOVED); 331 mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler); 332 333 // listen for stats update events 334 final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED); 335 mContext.registerReceiver( 336 mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler); 337 338 // listen for restrict background changes from notifications 339 final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND); 340 mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler); 341 342 } 343 344 private IProcessObserver mProcessObserver = new IProcessObserver.Stub() { 345 @Override 346 public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) { 347 // only someone like AMS should only be calling us 348 mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG); 349 350 synchronized (mRulesLock) { 351 // because a uid can have multiple pids running inside, we need to 352 // remember all pid states and summarize foreground at uid level. 353 354 // record foreground for this specific pid 355 SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 356 if (pidForeground == null) { 357 pidForeground = new SparseBooleanArray(2); 358 mUidPidForeground.put(uid, pidForeground); 359 } 360 pidForeground.put(pid, foregroundActivities); 361 computeUidForegroundLocked(uid); 362 } 363 } 364 365 @Override 366 public void onProcessDied(int pid, int uid) { 367 // only someone like AMS should only be calling us 368 mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG); 369 370 synchronized (mRulesLock) { 371 // clear records and recompute, when they exist 372 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 373 if (pidForeground != null) { 374 pidForeground.delete(pid); 375 computeUidForegroundLocked(uid); 376 } 377 } 378 } 379 }; 380 381 private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { 382 @Override 383 public void onReceive(Context context, Intent intent) { 384 synchronized (mRulesLock) { 385 // screen-related broadcasts are protected by system, no need 386 // for permissions check. 387 updateScreenOn(); 388 } 389 } 390 }; 391 392 private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() { 393 @Override 394 public void onReceive(Context context, Intent intent) { 395 // on background handler thread, and PACKAGE_ADDED and UID_REMOVED 396 // are protected broadcasts. 397 398 final String action = intent.getAction(); 399 final int uid = intent.getIntExtra(EXTRA_UID, 0); 400 synchronized (mRulesLock) { 401 if (ACTION_PACKAGE_ADDED.equals(action)) { 402 // update rules for UID, since it might be subject to 403 // global background data policy. 404 if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid); 405 updateRulesForUidLocked(uid); 406 407 } else if (ACTION_UID_REMOVED.equals(action)) { 408 // remove any policy and update rules to clean up. 409 if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid); 410 mUidPolicy.delete(uid); 411 updateRulesForUidLocked(uid); 412 writePolicyLocked(); 413 } 414 } 415 } 416 }; 417 418 /** 419 * Receiver that watches for {@link INetworkStatsService} updates, which we 420 * use to check against {@link NetworkPolicy#warningBytes}. 421 */ 422 private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() { 423 @Override 424 public void onReceive(Context context, Intent intent) { 425 // on background handler thread, and verified 426 // READ_NETWORK_USAGE_HISTORY permission above. 427 428 synchronized (mRulesLock) { 429 updateNetworkEnabledLocked(); 430 updateNotificationsLocked(); 431 } 432 } 433 }; 434 435 /** 436 * Receiver that watches for {@link Notification} control of 437 * {@link #mRestrictBackground}. 438 */ 439 private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() { 440 @Override 441 public void onReceive(Context context, Intent intent) { 442 // on background handler thread, and verified MANAGE_NETWORK_POLICY 443 // permission above. 444 445 setRestrictBackground(false); 446 } 447 }; 448 449 /** 450 * Observer that watches for {@link INetworkManagementService} alerts. 451 */ 452 private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() { 453 @Override 454 public void limitReached(String limitName, String iface) { 455 // only someone like NMS should be calling us 456 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 457 458 synchronized (mRulesLock) { 459 if (mMeteredIfaces.contains(iface) && !LIMIT_GLOBAL_ALERT.equals(limitName)) { 460 try { 461 // force stats update to make sure we have numbers that 462 // caused alert to trigger. 463 mNetworkStats.forceUpdate(); 464 } catch (RemoteException e) { 465 Slog.w(TAG, "problem updating network stats"); 466 } 467 468 updateNetworkEnabledLocked(); 469 updateNotificationsLocked(); 470 } 471 } 472 } 473 }; 474 475 /** 476 * Check {@link NetworkPolicy} against current {@link INetworkStatsService} 477 * to show visible notifications as needed. 478 */ 479 private void updateNotificationsLocked() { 480 if (LOGV) Slog.v(TAG, "updateNotificationsLocked()"); 481 482 // keep track of previously active notifications 483 final HashSet<String> beforeNotifs = Sets.newHashSet(); 484 beforeNotifs.addAll(mActiveNotifs); 485 mActiveNotifs.clear(); 486 487 // TODO: when switching to kernel notifications, compute next future 488 // cycle boundary to recompute notifications. 489 490 // examine stats for each active policy 491 final long currentTime = currentTimeMillis(true); 492 for (NetworkPolicy policy : mNetworkPolicy.values()) { 493 // ignore policies that aren't relevant to user 494 if (!isTemplateRelevant(policy.template)) continue; 495 496 final long start = computeLastCycleBoundary(currentTime, policy); 497 final long end = currentTime; 498 499 final long totalBytes = getTotalBytes(policy.template, start, end); 500 if (totalBytes == UNKNOWN_BYTES) continue; 501 502 if (policy.limitBytes != LIMIT_DISABLED && totalBytes >= policy.limitBytes) { 503 if (policy.lastSnooze >= start) { 504 enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes); 505 } else { 506 enqueueNotification(policy, TYPE_LIMIT, totalBytes); 507 notifyOverLimitLocked(policy.template); 508 } 509 510 } else { 511 notifyUnderLimitLocked(policy.template); 512 513 if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) { 514 enqueueNotification(policy, TYPE_WARNING, totalBytes); 515 } 516 } 517 } 518 519 // ongoing notification when restricting background data 520 if (mRestrictBackground) { 521 enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND); 522 } 523 524 // cancel stale notifications that we didn't renew above 525 for (String tag : beforeNotifs) { 526 if (!mActiveNotifs.contains(tag)) { 527 cancelNotification(tag); 528 } 529 } 530 } 531 532 /** 533 * Test if given {@link NetworkTemplate} is relevant to user based on 534 * current device state, such as when {@link #getActiveSubscriberId()} 535 * matches. This is regardless of data connection status. 536 */ 537 private boolean isTemplateRelevant(NetworkTemplate template) { 538 switch (template.getMatchRule()) { 539 case MATCH_MOBILE_3G_LOWER: 540 case MATCH_MOBILE_4G: 541 case MATCH_MOBILE_ALL: 542 // mobile templates are relevant when subscriberid is active 543 return Objects.equal(getActiveSubscriberId(), template.getSubscriberId()); 544 } 545 return true; 546 } 547 548 /** 549 * Notify that given {@link NetworkTemplate} is over 550 * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user. 551 */ 552 private void notifyOverLimitLocked(NetworkTemplate template) { 553 if (!mOverLimitNotified.contains(template)) { 554 mContext.startActivity(buildNetworkOverLimitIntent(template)); 555 mOverLimitNotified.add(template); 556 } 557 } 558 559 private void notifyUnderLimitLocked(NetworkTemplate template) { 560 mOverLimitNotified.remove(template); 561 } 562 563 /** 564 * Build unique tag that identifies an active {@link NetworkPolicy} 565 * notification of a specific type, like {@link #TYPE_LIMIT}. 566 */ 567 private String buildNotificationTag(NetworkPolicy policy, int type) { 568 return TAG + ":" + policy.template.hashCode() + ":" + type; 569 } 570 571 /** 572 * Show notification for combined {@link NetworkPolicy} and specific type, 573 * like {@link #TYPE_LIMIT}. Okay to call multiple times. 574 */ 575 private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) { 576 final String tag = buildNotificationTag(policy, type); 577 final Notification.Builder builder = new Notification.Builder(mContext); 578 builder.setOnlyAlertOnce(true); 579 builder.setOngoing(true); 580 581 final Resources res = mContext.getResources(); 582 switch (type) { 583 case TYPE_WARNING: { 584 final CharSequence title = res.getText(R.string.data_usage_warning_title); 585 final CharSequence body = res.getString(R.string.data_usage_warning_body, 586 Formatter.formatFileSize(mContext, policy.warningBytes)); 587 588 builder.setSmallIcon(R.drawable.ic_menu_info_details); 589 builder.setTicker(title); 590 builder.setContentTitle(title); 591 builder.setContentText(body); 592 593 final Intent intent = buildViewDataUsageIntent(policy.template); 594 builder.setContentIntent(PendingIntent.getActivity( 595 mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 596 break; 597 } 598 case TYPE_LIMIT: { 599 final CharSequence body = res.getText(R.string.data_usage_limit_body); 600 601 final CharSequence title; 602 switch (policy.template.getMatchRule()) { 603 case MATCH_MOBILE_3G_LOWER: 604 title = res.getText(R.string.data_usage_3g_limit_title); 605 break; 606 case MATCH_MOBILE_4G: 607 title = res.getText(R.string.data_usage_4g_limit_title); 608 break; 609 case MATCH_MOBILE_ALL: 610 title = res.getText(R.string.data_usage_mobile_limit_title); 611 break; 612 case MATCH_WIFI: 613 title = res.getText(R.string.data_usage_wifi_limit_title); 614 break; 615 default: 616 title = null; 617 break; 618 } 619 620 builder.setSmallIcon(com.android.internal.R.drawable.ic_menu_block); 621 builder.setTicker(title); 622 builder.setContentTitle(title); 623 builder.setContentText(body); 624 625 final Intent intent = buildNetworkOverLimitIntent(policy.template); 626 builder.setContentIntent(PendingIntent.getActivity( 627 mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 628 break; 629 } 630 case TYPE_LIMIT_SNOOZED: { 631 final long overBytes = totalBytes - policy.limitBytes; 632 final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body, 633 Formatter.formatFileSize(mContext, overBytes)); 634 635 final CharSequence title; 636 switch (policy.template.getMatchRule()) { 637 case MATCH_MOBILE_3G_LOWER: 638 title = res.getText(R.string.data_usage_3g_limit_snoozed_title); 639 break; 640 case MATCH_MOBILE_4G: 641 title = res.getText(R.string.data_usage_4g_limit_snoozed_title); 642 break; 643 case MATCH_MOBILE_ALL: 644 title = res.getText(R.string.data_usage_mobile_limit_snoozed_title); 645 break; 646 case MATCH_WIFI: 647 title = res.getText(R.string.data_usage_wifi_limit_snoozed_title); 648 break; 649 default: 650 title = null; 651 break; 652 } 653 654 builder.setSmallIcon(R.drawable.ic_menu_info_details); 655 builder.setTicker(title); 656 builder.setContentTitle(title); 657 builder.setContentText(body); 658 659 final Intent intent = buildViewDataUsageIntent(policy.template); 660 builder.setContentIntent(PendingIntent.getActivity( 661 mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 662 break; 663 } 664 } 665 666 // TODO: move to NotificationManager once we can mock it 667 try { 668 final String packageName = mContext.getPackageName(); 669 final int[] idReceived = new int[1]; 670 mNotifManager.enqueueNotificationWithTag( 671 packageName, tag, 0x0, builder.getNotification(), idReceived); 672 mActiveNotifs.add(tag); 673 } catch (RemoteException e) { 674 Slog.w(TAG, "problem during enqueueNotification: " + e); 675 } 676 } 677 678 /** 679 * Show ongoing notification to reflect that {@link #mRestrictBackground} 680 * has been enabled. 681 */ 682 private void enqueueRestrictedNotification(String tag) { 683 final Resources res = mContext.getResources(); 684 final Notification.Builder builder = new Notification.Builder(mContext); 685 686 final CharSequence title = res.getText(R.string.data_usage_restricted_title); 687 final CharSequence body = res.getString(R.string.data_usage_restricted_body); 688 689 builder.setOnlyAlertOnce(true); 690 builder.setOngoing(true); 691 builder.setSmallIcon(R.drawable.ic_menu_info_details); 692 builder.setTicker(title); 693 builder.setContentTitle(title); 694 builder.setContentText(body); 695 696 final Intent intent = buildAllowBackgroundDataIntent(); 697 builder.setContentIntent( 698 PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); 699 700 // TODO: move to NotificationManager once we can mock it 701 try { 702 final String packageName = mContext.getPackageName(); 703 final int[] idReceived = new int[1]; 704 mNotifManager.enqueueNotificationWithTag(packageName, tag, 705 0x0, builder.getNotification(), idReceived); 706 mActiveNotifs.add(tag); 707 } catch (RemoteException e) { 708 Slog.w(TAG, "problem during enqueueNotification: " + e); 709 } 710 } 711 712 private void cancelNotification(String tag) { 713 // TODO: move to NotificationManager once we can mock it 714 try { 715 final String packageName = mContext.getPackageName(); 716 mNotifManager.cancelNotificationWithTag( 717 packageName, tag, 0x0); 718 } catch (RemoteException e) { 719 Slog.w(TAG, "problem during enqueueNotification: " + e); 720 } 721 } 722 723 /** 724 * Receiver that watches for {@link IConnectivityManager} to claim network 725 * interfaces. Used to apply {@link NetworkPolicy} to matching networks. 726 */ 727 private BroadcastReceiver mConnReceiver = new BroadcastReceiver() { 728 @Override 729 public void onReceive(Context context, Intent intent) { 730 // on background handler thread, and verified CONNECTIVITY_INTERNAL 731 // permission above. 732 synchronized (mRulesLock) { 733 ensureActiveMobilePolicyLocked(); 734 updateNetworkEnabledLocked(); 735 updateNetworkRulesLocked(); 736 updateNotificationsLocked(); 737 } 738 } 739 }; 740 741 /** 742 * Proactively control network data connections when they exceed 743 * {@link NetworkPolicy#limitBytes}. 744 */ 745 private void updateNetworkEnabledLocked() { 746 if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()"); 747 748 // TODO: reset any policy-disabled networks when any policy is removed 749 // completely, which is currently rare case. 750 751 final long currentTime = currentTimeMillis(true); 752 for (NetworkPolicy policy : mNetworkPolicy.values()) { 753 // shortcut when policy has no limit 754 if (policy.limitBytes == LIMIT_DISABLED) { 755 setNetworkTemplateEnabled(policy.template, true); 756 continue; 757 } 758 759 final long start = computeLastCycleBoundary(currentTime, policy); 760 final long end = currentTime; 761 762 final long totalBytes = getTotalBytes(policy.template, start, end); 763 if (totalBytes == UNKNOWN_BYTES) continue; 764 765 // disable data connection when over limit and not snoozed 766 final boolean overLimit = policy.limitBytes != LIMIT_DISABLED 767 && totalBytes > policy.limitBytes && policy.lastSnooze < start; 768 final boolean enabled = !overLimit; 769 770 setNetworkTemplateEnabled(policy.template, enabled); 771 } 772 } 773 774 /** 775 * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)} 776 * for the given {@link NetworkTemplate}. 777 */ 778 private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) { 779 switch (template.getMatchRule()) { 780 case MATCH_MOBILE_3G_LOWER: 781 case MATCH_MOBILE_4G: 782 case MATCH_MOBILE_ALL: 783 // TODO: offer more granular control over radio states once 784 // 4965893 is available. 785 if (Objects.equal(getActiveSubscriberId(), template.getSubscriberId())) { 786 setPolicyDataEnable(TYPE_MOBILE, enabled); 787 setPolicyDataEnable(TYPE_WIMAX, enabled); 788 } 789 break; 790 case MATCH_WIFI: 791 setPolicyDataEnable(TYPE_WIFI, enabled); 792 break; 793 case MATCH_ETHERNET: 794 setPolicyDataEnable(TYPE_ETHERNET, enabled); 795 break; 796 default: 797 throw new IllegalArgumentException("unexpected template"); 798 } 799 } 800 801 /** 802 * Examine all connected {@link NetworkState}, looking for 803 * {@link NetworkPolicy} that need to be enforced. When matches found, set 804 * remaining quota based on usage cycle and historical stats. 805 */ 806 private void updateNetworkRulesLocked() { 807 if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); 808 809 final NetworkState[] states; 810 try { 811 states = mConnManager.getAllNetworkState(); 812 } catch (RemoteException e) { 813 Slog.w(TAG, "problem reading network state"); 814 return; 815 } 816 817 // first, derive identity for all connected networks, which can be used 818 // to match against templates. 819 final HashMap<NetworkIdentity, String> networks = Maps.newHashMap(); 820 for (NetworkState state : states) { 821 // stash identity and iface away for later use 822 if (state.networkInfo.isConnected()) { 823 final String iface = state.linkProperties.getInterfaceName(); 824 final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); 825 networks.put(ident, iface); 826 } 827 } 828 829 // build list of rules and ifaces to enforce them against 830 mNetworkRules.clear(); 831 final ArrayList<String> ifaceList = Lists.newArrayList(); 832 for (NetworkPolicy policy : mNetworkPolicy.values()) { 833 834 // collect all active ifaces that match this template 835 ifaceList.clear(); 836 for (Map.Entry<NetworkIdentity, String> entry : networks.entrySet()) { 837 final NetworkIdentity ident = entry.getKey(); 838 if (policy.template.matches(ident)) { 839 final String iface = entry.getValue(); 840 ifaceList.add(iface); 841 } 842 } 843 844 if (ifaceList.size() > 0) { 845 final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]); 846 mNetworkRules.put(policy, ifaces); 847 } 848 } 849 850 final HashSet<String> newMeteredIfaces = Sets.newHashSet(); 851 852 // apply each policy that we found ifaces for; compute remaining data 853 // based on current cycle and historical stats, and push to kernel. 854 final long currentTime = currentTimeMillis(true); 855 for (NetworkPolicy policy : mNetworkRules.keySet()) { 856 final String[] ifaces = mNetworkRules.get(policy); 857 858 final long start = computeLastCycleBoundary(currentTime, policy); 859 final long end = currentTime; 860 861 final long totalBytes = getTotalBytes(policy.template, start, end); 862 if (totalBytes == UNKNOWN_BYTES) continue; 863 864 if (LOGD) { 865 Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces " 866 + Arrays.toString(ifaces)); 867 } 868 869 final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED; 870 if (hasLimit) { 871 final long quotaBytes; 872 if (policy.lastSnooze >= start) { 873 // snoozing past quota, but we still need to restrict apps, 874 // so push really high quota. 875 quotaBytes = Long.MAX_VALUE; 876 } else { 877 // remaining "quota" bytes are based on total usage in 878 // current cycle. kernel doesn't like 0-byte rules, so we 879 // set 1-byte quota and disable the radio later. 880 quotaBytes = Math.max(1, policy.limitBytes - totalBytes); 881 } 882 883 if (ifaces.length > 1) { 884 // TODO: switch to shared quota once NMS supports 885 Slog.w(TAG, "shared quota unsupported; generating rule for each iface"); 886 } 887 888 for (String iface : ifaces) { 889 removeInterfaceQuota(iface); 890 setInterfaceQuota(iface, quotaBytes); 891 newMeteredIfaces.add(iface); 892 } 893 } 894 } 895 896 // remove quota on any trailing interfaces 897 for (String iface : mMeteredIfaces) { 898 if (!newMeteredIfaces.contains(iface)) { 899 removeInterfaceQuota(iface); 900 } 901 } 902 mMeteredIfaces = newMeteredIfaces; 903 904 final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]); 905 mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget(); 906 } 907 908 /** 909 * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we 910 * have at least a default mobile policy defined. 911 */ 912 private void ensureActiveMobilePolicyLocked() { 913 if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()"); 914 if (mSuppressDefaultPolicy) return; 915 916 final String subscriberId = getActiveSubscriberId(); 917 final NetworkIdentity probeIdent = new NetworkIdentity( 918 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false); 919 920 // examine to see if any policy is defined for active mobile 921 boolean mobileDefined = false; 922 for (NetworkPolicy policy : mNetworkPolicy.values()) { 923 if (policy.template.matches(probeIdent)) { 924 mobileDefined = true; 925 } 926 } 927 928 if (!mobileDefined) { 929 Slog.i(TAG, "no policy for active mobile network; generating default policy"); 930 931 // build default mobile policy, and assume usage cycle starts today 932 final long warningBytes = mContext.getResources().getInteger( 933 com.android.internal.R.integer.config_networkPolicyDefaultWarning) 934 * MB_IN_BYTES; 935 936 final Time time = new Time(Time.TIMEZONE_UTC); 937 time.setToNow(); 938 final int cycleDay = time.monthDay; 939 940 final NetworkTemplate template = buildTemplateMobileAll(subscriberId); 941 mNetworkPolicy.put(template, new NetworkPolicy( 942 template, cycleDay, warningBytes, LIMIT_DISABLED, SNOOZE_NEVER)); 943 writePolicyLocked(); 944 } 945 } 946 947 private void readPolicyLocked() { 948 if (LOGV) Slog.v(TAG, "readPolicyLocked()"); 949 950 // clear any existing policy and read from disk 951 mNetworkPolicy.clear(); 952 mUidPolicy.clear(); 953 954 FileInputStream fis = null; 955 try { 956 fis = mPolicyFile.openRead(); 957 final XmlPullParser in = Xml.newPullParser(); 958 in.setInput(fis, null); 959 960 int type; 961 int version = VERSION_INIT; 962 while ((type = in.next()) != END_DOCUMENT) { 963 final String tag = in.getName(); 964 if (type == START_TAG) { 965 if (TAG_POLICY_LIST.equals(tag)) { 966 version = readIntAttribute(in, ATTR_VERSION); 967 if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) { 968 mRestrictBackground = readBooleanAttribute( 969 in, ATTR_RESTRICT_BACKGROUND); 970 } else { 971 mRestrictBackground = false; 972 } 973 974 } else if (TAG_NETWORK_POLICY.equals(tag)) { 975 final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE); 976 final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID); 977 final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY); 978 final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES); 979 final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES); 980 final long lastSnooze; 981 if (version >= VERSION_ADDED_SNOOZE) { 982 lastSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE); 983 } else { 984 lastSnooze = SNOOZE_NEVER; 985 } 986 987 final NetworkTemplate template = new NetworkTemplate( 988 networkTemplate, subscriberId); 989 mNetworkPolicy.put(template, new NetworkPolicy( 990 template, cycleDay, warningBytes, limitBytes, lastSnooze)); 991 992 } else if (TAG_UID_POLICY.equals(tag)) { 993 final int uid = readIntAttribute(in, ATTR_UID); 994 final int policy = readIntAttribute(in, ATTR_POLICY); 995 996 if (isUidValidForPolicy(mContext, uid)) { 997 setUidPolicyUnchecked(uid, policy, false); 998 } else { 999 Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring"); 1000 } 1001 } 1002 } 1003 } 1004 1005 } catch (FileNotFoundException e) { 1006 // missing policy is okay, probably first boot 1007 upgradeLegacyBackgroundData(); 1008 } catch (IOException e) { 1009 Slog.e(TAG, "problem reading network stats", e); 1010 } catch (XmlPullParserException e) { 1011 Slog.e(TAG, "problem reading network stats", e); 1012 } finally { 1013 IoUtils.closeQuietly(fis); 1014 } 1015 } 1016 1017 /** 1018 * Upgrade legacy background data flags, notifying listeners of one last 1019 * change to always-true. 1020 */ 1021 private void upgradeLegacyBackgroundData() { 1022 mRestrictBackground = Settings.Secure.getInt( 1023 mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1; 1024 1025 // kick off one last broadcast if restricted 1026 if (mRestrictBackground) { 1027 final Intent broadcast = new Intent( 1028 ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED); 1029 mContext.sendBroadcast(broadcast); 1030 } 1031 } 1032 1033 private void writePolicyLocked() { 1034 if (LOGV) Slog.v(TAG, "writePolicyLocked()"); 1035 1036 FileOutputStream fos = null; 1037 try { 1038 fos = mPolicyFile.startWrite(); 1039 1040 XmlSerializer out = new FastXmlSerializer(); 1041 out.setOutput(fos, "utf-8"); 1042 out.startDocument(null, true); 1043 1044 out.startTag(null, TAG_POLICY_LIST); 1045 writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_RESTRICT_BACKGROUND); 1046 writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground); 1047 1048 // write all known network policies 1049 for (NetworkPolicy policy : mNetworkPolicy.values()) { 1050 final NetworkTemplate template = policy.template; 1051 1052 out.startTag(null, TAG_NETWORK_POLICY); 1053 writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule()); 1054 final String subscriberId = template.getSubscriberId(); 1055 if (subscriberId != null) { 1056 out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId); 1057 } 1058 writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay); 1059 writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes); 1060 writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes); 1061 writeLongAttribute(out, ATTR_LAST_SNOOZE, policy.lastSnooze); 1062 out.endTag(null, TAG_NETWORK_POLICY); 1063 } 1064 1065 // write all known uid policies 1066 for (int i = 0; i < mUidPolicy.size(); i++) { 1067 final int uid = mUidPolicy.keyAt(i); 1068 final int policy = mUidPolicy.valueAt(i); 1069 1070 // skip writing empty policies 1071 if (policy == POLICY_NONE) continue; 1072 1073 out.startTag(null, TAG_UID_POLICY); 1074 writeIntAttribute(out, ATTR_UID, uid); 1075 writeIntAttribute(out, ATTR_POLICY, policy); 1076 out.endTag(null, TAG_UID_POLICY); 1077 } 1078 1079 out.endTag(null, TAG_POLICY_LIST); 1080 out.endDocument(); 1081 1082 mPolicyFile.finishWrite(fos); 1083 } catch (IOException e) { 1084 if (fos != null) { 1085 mPolicyFile.failWrite(fos); 1086 } 1087 } 1088 } 1089 1090 @Override 1091 public void setUidPolicy(int uid, int policy) { 1092 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1093 1094 if (!isUidValidForPolicy(mContext, uid)) { 1095 throw new IllegalArgumentException("cannot apply policy to UID " + uid); 1096 } 1097 1098 setUidPolicyUnchecked(uid, policy, true); 1099 } 1100 1101 private void setUidPolicyUnchecked(int uid, int policy, boolean persist) { 1102 final int oldPolicy; 1103 synchronized (mRulesLock) { 1104 oldPolicy = getUidPolicy(uid); 1105 mUidPolicy.put(uid, policy); 1106 1107 // uid policy changed, recompute rules and persist policy. 1108 updateRulesForUidLocked(uid); 1109 if (persist) { 1110 writePolicyLocked(); 1111 } 1112 } 1113 } 1114 1115 @Override 1116 public int getUidPolicy(int uid) { 1117 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1118 1119 synchronized (mRulesLock) { 1120 return mUidPolicy.get(uid, POLICY_NONE); 1121 } 1122 } 1123 1124 @Override 1125 public void registerListener(INetworkPolicyListener listener) { 1126 // TODO: create permission for observing network policy 1127 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1128 1129 mListeners.register(listener); 1130 1131 // TODO: consider dispatching existing rules to new listeners 1132 } 1133 1134 @Override 1135 public void unregisterListener(INetworkPolicyListener listener) { 1136 // TODO: create permission for observing network policy 1137 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1138 1139 mListeners.unregister(listener); 1140 } 1141 1142 @Override 1143 public void setNetworkPolicies(NetworkPolicy[] policies) { 1144 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1145 1146 synchronized (mRulesLock) { 1147 mNetworkPolicy.clear(); 1148 for (NetworkPolicy policy : policies) { 1149 mNetworkPolicy.put(policy.template, policy); 1150 } 1151 1152 updateNetworkEnabledLocked(); 1153 updateNetworkRulesLocked(); 1154 updateNotificationsLocked(); 1155 writePolicyLocked(); 1156 } 1157 } 1158 1159 @Override 1160 public NetworkPolicy[] getNetworkPolicies() { 1161 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1162 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG); 1163 1164 synchronized (mRulesLock) { 1165 return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]); 1166 } 1167 } 1168 1169 @Override 1170 public void snoozePolicy(NetworkTemplate template) { 1171 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1172 1173 final long currentTime = currentTimeMillis(true); 1174 synchronized (mRulesLock) { 1175 // find and snooze local policy that matches 1176 final NetworkPolicy policy = mNetworkPolicy.get(template); 1177 if (policy == null) { 1178 throw new IllegalArgumentException("unable to find policy for " + template); 1179 } 1180 1181 policy.lastSnooze = currentTime; 1182 1183 updateNetworkEnabledLocked(); 1184 updateNetworkRulesLocked(); 1185 updateNotificationsLocked(); 1186 writePolicyLocked(); 1187 } 1188 } 1189 1190 @Override 1191 public void setRestrictBackground(boolean restrictBackground) { 1192 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1193 1194 synchronized (mRulesLock) { 1195 mRestrictBackground = restrictBackground; 1196 updateRulesForRestrictBackgroundLocked(); 1197 updateNotificationsLocked(); 1198 writePolicyLocked(); 1199 } 1200 } 1201 1202 @Override 1203 public boolean getRestrictBackground() { 1204 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1205 1206 synchronized (mRulesLock) { 1207 return mRestrictBackground; 1208 } 1209 } 1210 1211 private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) { 1212 for (NetworkPolicy policy : mNetworkPolicy.values()) { 1213 if (policy.template.matches(ident)) { 1214 return policy; 1215 } 1216 } 1217 return null; 1218 } 1219 1220 @Override 1221 public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) { 1222 mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 1223 1224 // only returns usage summary, so we don't require caller to have 1225 // READ_NETWORK_USAGE_HISTORY. 1226 final long token = Binder.clearCallingIdentity(); 1227 try { 1228 return getNetworkQuotaInfoUnchecked(state); 1229 } finally { 1230 Binder.restoreCallingIdentity(token); 1231 } 1232 } 1233 1234 private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) { 1235 final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); 1236 1237 final NetworkPolicy policy; 1238 synchronized (mRulesLock) { 1239 policy = findPolicyForNetworkLocked(ident); 1240 } 1241 1242 if (policy == null) { 1243 // missing policy means we can't derive useful quota info 1244 return null; 1245 } 1246 1247 final long currentTime = currentTimeMillis(false); 1248 1249 final long start = computeLastCycleBoundary(currentTime, policy); 1250 final long end = currentTime; 1251 1252 // find total bytes used under policy 1253 final long totalBytes = getTotalBytes(policy.template, start, end); 1254 if (totalBytes == UNKNOWN_BYTES) return null; 1255 1256 // report soft and hard limits under policy 1257 final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes 1258 : NetworkQuotaInfo.NO_LIMIT; 1259 final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes 1260 : NetworkQuotaInfo.NO_LIMIT; 1261 1262 return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes); 1263 } 1264 1265 @Override 1266 protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 1267 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 1268 1269 final HashSet<String> argSet = new HashSet<String>(); 1270 for (String arg : args) { 1271 argSet.add(arg); 1272 } 1273 1274 synchronized (mRulesLock) { 1275 if (argSet.contains("unsnooze")) { 1276 for (NetworkPolicy policy : mNetworkPolicy.values()) { 1277 policy.lastSnooze = SNOOZE_NEVER; 1278 } 1279 writePolicyLocked(); 1280 fout.println("Wiped snooze timestamps"); 1281 return; 1282 } 1283 1284 fout.print("Restrict background: "); fout.println(mRestrictBackground); 1285 fout.println("Network policies:"); 1286 for (NetworkPolicy policy : mNetworkPolicy.values()) { 1287 fout.print(" "); fout.println(policy.toString()); 1288 } 1289 1290 fout.println("Policy status for known UIDs:"); 1291 1292 final SparseBooleanArray knownUids = new SparseBooleanArray(); 1293 collectKeys(mUidPolicy, knownUids); 1294 collectKeys(mUidForeground, knownUids); 1295 collectKeys(mUidRules, knownUids); 1296 1297 final int size = knownUids.size(); 1298 for (int i = 0; i < size; i++) { 1299 final int uid = knownUids.keyAt(i); 1300 fout.print(" UID="); 1301 fout.print(uid); 1302 1303 fout.print(" policy="); 1304 final int policyIndex = mUidPolicy.indexOfKey(uid); 1305 if (policyIndex < 0) { 1306 fout.print("UNKNOWN"); 1307 } else { 1308 dumpPolicy(fout, mUidPolicy.valueAt(policyIndex)); 1309 } 1310 1311 fout.print(" foreground="); 1312 final int foregroundIndex = mUidPidForeground.indexOfKey(uid); 1313 if (foregroundIndex < 0) { 1314 fout.print("UNKNOWN"); 1315 } else { 1316 dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex)); 1317 } 1318 1319 fout.print(" rules="); 1320 final int rulesIndex = mUidRules.indexOfKey(uid); 1321 if (rulesIndex < 0) { 1322 fout.print("UNKNOWN"); 1323 } else { 1324 dumpRules(fout, mUidRules.valueAt(rulesIndex)); 1325 } 1326 1327 fout.println(); 1328 } 1329 } 1330 } 1331 1332 @Override 1333 public boolean isUidForeground(int uid) { 1334 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1335 1336 synchronized (mRulesLock) { 1337 // only really in foreground when screen is also on 1338 return mUidForeground.get(uid, false) && mScreenOn; 1339 } 1340 } 1341 1342 /** 1343 * Foreground for PID changed; recompute foreground at UID level. If 1344 * changed, will trigger {@link #updateRulesForUidLocked(int)}. 1345 */ 1346 private void computeUidForegroundLocked(int uid) { 1347 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 1348 1349 // current pid is dropping foreground; examine other pids 1350 boolean uidForeground = false; 1351 final int size = pidForeground.size(); 1352 for (int i = 0; i < size; i++) { 1353 if (pidForeground.valueAt(i)) { 1354 uidForeground = true; 1355 break; 1356 } 1357 } 1358 1359 final boolean oldUidForeground = mUidForeground.get(uid, false); 1360 if (oldUidForeground != uidForeground) { 1361 // foreground changed, push updated rules 1362 mUidForeground.put(uid, uidForeground); 1363 updateRulesForUidLocked(uid); 1364 } 1365 } 1366 1367 private void updateScreenOn() { 1368 synchronized (mRulesLock) { 1369 try { 1370 mScreenOn = mPowerManager.isScreenOn(); 1371 } catch (RemoteException e) { 1372 } 1373 updateRulesForScreenLocked(); 1374 } 1375 } 1376 1377 /** 1378 * Update rules that might be changed by {@link #mScreenOn} value. 1379 */ 1380 private void updateRulesForScreenLocked() { 1381 // only update rules for anyone with foreground activities 1382 final int size = mUidForeground.size(); 1383 for (int i = 0; i < size; i++) { 1384 if (mUidForeground.valueAt(i)) { 1385 final int uid = mUidForeground.keyAt(i); 1386 updateRulesForUidLocked(uid); 1387 } 1388 } 1389 } 1390 1391 /** 1392 * Update rules that might be changed by {@link #mRestrictBackground} value. 1393 */ 1394 private void updateRulesForRestrictBackgroundLocked() { 1395 // update rules for all installed applications 1396 final PackageManager pm = mContext.getPackageManager(); 1397 final List<ApplicationInfo> apps = pm.getInstalledApplications(0); 1398 for (ApplicationInfo app : apps) { 1399 updateRulesForUidLocked(app.uid); 1400 } 1401 1402 // and catch system UIDs 1403 // TODO: keep in sync with android_filesystem_config.h 1404 for (int uid = 1000; uid <= 1025; uid++) { 1405 updateRulesForUidLocked(uid); 1406 } 1407 for (int uid = 2000; uid <= 2002; uid++) { 1408 updateRulesForUidLocked(uid); 1409 } 1410 for (int uid = 3000; uid <= 3007; uid++) { 1411 updateRulesForUidLocked(uid); 1412 } 1413 for (int uid = 9998; uid <= 9999; uid++) { 1414 updateRulesForUidLocked(uid); 1415 } 1416 } 1417 1418 private void updateRulesForUidLocked(int uid) { 1419 final int uidPolicy = getUidPolicy(uid); 1420 final boolean uidForeground = isUidForeground(uid); 1421 1422 // derive active rules based on policy and active state 1423 int uidRules = RULE_ALLOW_ALL; 1424 if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { 1425 // uid in background, and policy says to block metered data 1426 uidRules = RULE_REJECT_METERED; 1427 } 1428 if (!uidForeground && mRestrictBackground) { 1429 // uid in background, and global background disabled 1430 uidRules = RULE_REJECT_METERED; 1431 } 1432 1433 // TODO: only dispatch when rules actually change 1434 1435 if (uidRules == RULE_ALLOW_ALL) { 1436 mUidRules.delete(uid); 1437 } else { 1438 mUidRules.put(uid, uidRules); 1439 } 1440 1441 final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0; 1442 setUidNetworkRules(uid, rejectMetered); 1443 1444 // dispatch changed rule to existing listeners 1445 mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget(); 1446 1447 try { 1448 // adjust stats accounting based on foreground status 1449 mNetworkStats.setUidForeground(uid, uidForeground); 1450 } catch (RemoteException e) { 1451 Slog.w(TAG, "problem dispatching foreground change"); 1452 } 1453 } 1454 1455 private Handler.Callback mHandlerCallback = new Handler.Callback() { 1456 /** {@inheritDoc} */ 1457 public boolean handleMessage(Message msg) { 1458 switch (msg.what) { 1459 case MSG_RULES_CHANGED: { 1460 final int uid = msg.arg1; 1461 final int uidRules = msg.arg2; 1462 final int length = mListeners.beginBroadcast(); 1463 for (int i = 0; i < length; i++) { 1464 final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 1465 if (listener != null) { 1466 try { 1467 listener.onUidRulesChanged(uid, uidRules); 1468 } catch (RemoteException e) { 1469 } 1470 } 1471 } 1472 mListeners.finishBroadcast(); 1473 return true; 1474 } 1475 case MSG_METERED_IFACES_CHANGED: { 1476 final String[] meteredIfaces = (String[]) msg.obj; 1477 final int length = mListeners.beginBroadcast(); 1478 for (int i = 0; i < length; i++) { 1479 final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 1480 if (listener != null) { 1481 try { 1482 listener.onMeteredIfacesChanged(meteredIfaces); 1483 } catch (RemoteException e) { 1484 } 1485 } 1486 } 1487 mListeners.finishBroadcast(); 1488 return true; 1489 } 1490 default: { 1491 return false; 1492 } 1493 } 1494 } 1495 }; 1496 1497 private void setInterfaceQuota(String iface, long quotaBytes) { 1498 try { 1499 mNetworkManager.setInterfaceQuota(iface, quotaBytes); 1500 } catch (IllegalStateException e) { 1501 Slog.e(TAG, "problem setting interface quota", e); 1502 } catch (RemoteException e) { 1503 Slog.e(TAG, "problem setting interface quota", e); 1504 } 1505 } 1506 1507 private void removeInterfaceQuota(String iface) { 1508 try { 1509 mNetworkManager.removeInterfaceQuota(iface); 1510 } catch (IllegalStateException e) { 1511 Slog.e(TAG, "problem removing interface quota", e); 1512 } catch (RemoteException e) { 1513 Slog.e(TAG, "problem removing interface quota", e); 1514 } 1515 } 1516 1517 private void setInterfaceAlert(String iface, long alertBytes) { 1518 try { 1519 mNetworkManager.setInterfaceAlert(iface, alertBytes); 1520 } catch (IllegalStateException e) { 1521 Slog.e(TAG, "problem setting interface alert", e); 1522 } catch (RemoteException e) { 1523 Slog.e(TAG, "problem setting interface alert", e); 1524 } 1525 } 1526 1527 private void removeInterfaceAlert(String iface) { 1528 try { 1529 mNetworkManager.removeInterfaceAlert(iface); 1530 } catch (IllegalStateException e) { 1531 Slog.e(TAG, "problem removing interface alert", e); 1532 } catch (RemoteException e) { 1533 Slog.e(TAG, "problem removing interface alert", e); 1534 } 1535 } 1536 1537 private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1538 try { 1539 mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces); 1540 } catch (IllegalStateException e) { 1541 Slog.e(TAG, "problem setting uid rules", e); 1542 } catch (RemoteException e) { 1543 Slog.e(TAG, "problem setting uid rules", e); 1544 } 1545 } 1546 1547 /** 1548 * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}, 1549 * dispatching only when actually changed. 1550 */ 1551 private void setPolicyDataEnable(int networkType, boolean enabled) { 1552 synchronized (mActiveNetworkEnabled) { 1553 final boolean prevEnabled = mActiveNetworkEnabled.get(networkType, true); 1554 if (prevEnabled == enabled) return; 1555 1556 try { 1557 mConnManager.setPolicyDataEnable(networkType, enabled); 1558 } catch (RemoteException e) { 1559 Slog.e(TAG, "problem setting network enabled", e); 1560 } 1561 1562 mActiveNetworkEnabled.put(networkType, enabled); 1563 } 1564 } 1565 1566 private String getActiveSubscriberId() { 1567 final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService( 1568 Context.TELEPHONY_SERVICE); 1569 return telephony.getSubscriberId(); 1570 } 1571 1572 private static final long UNKNOWN_BYTES = -1; 1573 1574 private long getTotalBytes(NetworkTemplate template, long start, long end) { 1575 try { 1576 final NetworkStats stats = mNetworkStats.getSummaryForNetwork( 1577 template, start, end); 1578 final NetworkStats.Entry entry = stats.getValues(0, null); 1579 return entry.rxBytes + entry.txBytes; 1580 } catch (RemoteException e) { 1581 Slog.w(TAG, "problem reading summary for template " + template); 1582 return UNKNOWN_BYTES; 1583 } 1584 } 1585 1586 private long currentTimeMillis(boolean allowRefresh) { 1587 // try refreshing time source when stale 1588 if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE && allowRefresh) { 1589 mTime.forceRefresh(); 1590 } 1591 1592 return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis(); 1593 } 1594 1595 private static Intent buildAllowBackgroundDataIntent() { 1596 return new Intent(ACTION_ALLOW_BACKGROUND); 1597 } 1598 1599 private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) { 1600 final Intent intent = new Intent(); 1601 intent.setComponent(new ComponentName( 1602 "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity")); 1603 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1604 intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); 1605 return intent; 1606 } 1607 1608 private static Intent buildViewDataUsageIntent(NetworkTemplate template) { 1609 final Intent intent = new Intent(); 1610 intent.setComponent(new ComponentName( 1611 "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity")); 1612 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1613 intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); 1614 return intent; 1615 } 1616 1617 private static void collectKeys(SparseIntArray source, SparseBooleanArray target) { 1618 final int size = source.size(); 1619 for (int i = 0; i < size; i++) { 1620 target.put(source.keyAt(i), true); 1621 } 1622 } 1623 1624 private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) { 1625 final int size = source.size(); 1626 for (int i = 0; i < size; i++) { 1627 target.put(source.keyAt(i), true); 1628 } 1629 } 1630 1631 private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) { 1632 fout.print("["); 1633 final int size = value.size(); 1634 for (int i = 0; i < size; i++) { 1635 fout.print(value.keyAt(i) + "=" + value.valueAt(i)); 1636 if (i < size - 1) fout.print(","); 1637 } 1638 fout.print("]"); 1639 } 1640 1641 public static class XmlUtils { 1642 public static int readIntAttribute(XmlPullParser in, String name) throws IOException { 1643 final String value = in.getAttributeValue(null, name); 1644 try { 1645 return Integer.parseInt(value); 1646 } catch (NumberFormatException e) { 1647 throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 1648 } 1649 } 1650 1651 public static void writeIntAttribute(XmlSerializer out, String name, int value) 1652 throws IOException { 1653 out.attribute(null, name, Integer.toString(value)); 1654 } 1655 1656 public static long readLongAttribute(XmlPullParser in, String name) throws IOException { 1657 final String value = in.getAttributeValue(null, name); 1658 try { 1659 return Long.parseLong(value); 1660 } catch (NumberFormatException e) { 1661 throw new ProtocolException("problem parsing " + name + "=" + value + " as long"); 1662 } 1663 } 1664 1665 public static void writeLongAttribute(XmlSerializer out, String name, long value) 1666 throws IOException { 1667 out.attribute(null, name, Long.toString(value)); 1668 } 1669 1670 public static boolean readBooleanAttribute(XmlPullParser in, String name) { 1671 final String value = in.getAttributeValue(null, name); 1672 return Boolean.parseBoolean(value); 1673 } 1674 1675 public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value) 1676 throws IOException { 1677 out.attribute(null, name, Boolean.toString(value)); 1678 } 1679 } 1680} 1681