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