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