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