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