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