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