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