NetworkPolicyManagerService.java revision 4e814c348ce205fcc1a273427f95ef1d100ed60c
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.ACTION_BACKGROUND_DATA_SETTING_CHANGED; 28import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; 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.buildTemplateMobileAll; 46import static android.text.format.DateUtils.DAY_IN_MILLIS; 47import static com.android.internal.util.Preconditions.checkNotNull; 48import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED; 49import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 50import static org.xmlpull.v1.XmlPullParser.START_TAG; 51 52import android.app.IActivityManager; 53import android.app.INotificationManager; 54import android.app.IProcessObserver; 55import android.app.Notification; 56import android.app.PendingIntent; 57import android.content.BroadcastReceiver; 58import android.content.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 this(context, activityManager, powerManager, networkStats, networkManagement, 208 NtpTrustedTime.getInstance(context), getSystemDir()); 209 } 210 211 private static File getSystemDir() { 212 return new File(Environment.getDataDirectory(), "system"); 213 } 214 215 public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 216 IPowerManager powerManager, INetworkStatsService networkStats, 217 INetworkManagementService networkManagement, 218 TrustedTime time, File systemDir) { 219 mContext = checkNotNull(context, "missing context"); 220 mActivityManager = checkNotNull(activityManager, "missing activityManager"); 221 mPowerManager = checkNotNull(powerManager, "missing powerManager"); 222 mNetworkStats = checkNotNull(networkStats, "missing networkStats"); 223 mNetworkManagement = checkNotNull(networkManagement, "missing networkManagement"); 224 mTime = checkNotNull(time, "missing TrustedTime"); 225 226 mHandlerThread = new HandlerThread(TAG); 227 mHandlerThread.start(); 228 mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback); 229 230 mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); 231 } 232 233 public void bindConnectivityManager(IConnectivityManager connManager) { 234 mConnManager = checkNotNull(connManager, "missing IConnectivityManager"); 235 } 236 237 public void bindNotificationManager(INotificationManager notifManager) { 238 mNotifManager = checkNotNull(notifManager, "missing INotificationManager"); 239 } 240 241 public void systemReady() { 242 synchronized (mRulesLock) { 243 // read policy from disk 244 readPolicyLocked(); 245 updateNotificationsLocked(); 246 } 247 248 updateScreenOn(); 249 updateBackgroundData(true); 250 251 try { 252 mActivityManager.registerProcessObserver(mProcessObserver); 253 } catch (RemoteException e) { 254 // ouch, no foregroundActivities updates means some processes may 255 // never get network access. 256 Slog.e(TAG, "unable to register IProcessObserver", e); 257 } 258 259 // TODO: traverse existing processes to know foreground state, or have 260 // activitymanager dispatch current state when new observer attached. 261 262 final IntentFilter screenFilter = new IntentFilter(); 263 screenFilter.addAction(Intent.ACTION_SCREEN_ON); 264 screenFilter.addAction(Intent.ACTION_SCREEN_OFF); 265 mContext.registerReceiver(mScreenReceiver, screenFilter); 266 267 // watch for network interfaces to be claimed 268 final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION); 269 mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); 270 271 // listen for uid removal to clean policy 272 final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED); 273 mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler); 274 275 // listen for stats update events 276 final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED); 277 mContext.registerReceiver( 278 mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler); 279 280 // listen for changes to background data flag 281 final IntentFilter bgFilter = new IntentFilter(ACTION_BACKGROUND_DATA_SETTING_CHANGED); 282 mContext.registerReceiver(mBgReceiver, bgFilter, CONNECTIVITY_INTERNAL, mHandler); 283 284 } 285 286 private IProcessObserver mProcessObserver = new IProcessObserver.Stub() { 287 @Override 288 public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) { 289 // only someone like AMS should only be calling us 290 mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG); 291 292 synchronized (mRulesLock) { 293 // because a uid can have multiple pids running inside, we need to 294 // remember all pid states and summarize foreground at uid level. 295 296 // record foreground for this specific pid 297 SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 298 if (pidForeground == null) { 299 pidForeground = new SparseBooleanArray(2); 300 mUidPidForeground.put(uid, pidForeground); 301 } 302 pidForeground.put(pid, foregroundActivities); 303 computeUidForegroundLocked(uid); 304 } 305 } 306 307 @Override 308 public void onProcessDied(int pid, int uid) { 309 // only someone like AMS should only be calling us 310 mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG); 311 312 synchronized (mRulesLock) { 313 // clear records and recompute, when they exist 314 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 315 if (pidForeground != null) { 316 pidForeground.delete(pid); 317 computeUidForegroundLocked(uid); 318 } 319 } 320 } 321 }; 322 323 private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { 324 @Override 325 public void onReceive(Context context, Intent intent) { 326 synchronized (mRulesLock) { 327 // screen-related broadcasts are protected by system, no need 328 // for permissions check. 329 updateScreenOn(); 330 } 331 } 332 }; 333 334 private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() { 335 @Override 336 public void onReceive(Context context, Intent intent) { 337 // on background handler thread, and UID_REMOVED is protected 338 // broadcast. 339 final int uid = intent.getIntExtra(EXTRA_UID, 0); 340 synchronized (mRulesLock) { 341 // remove any policy and update rules to clean up 342 mUidPolicy.delete(uid); 343 updateRulesForUidLocked(uid); 344 writePolicyLocked(); 345 } 346 } 347 }; 348 349 /** 350 * Receiver that watches for {@link INetworkStatsService} updates, which we 351 * use to check against {@link NetworkPolicy#warningBytes}. 352 */ 353 private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() { 354 @Override 355 public void onReceive(Context context, Intent intent) { 356 // on background handler thread, and verified 357 // READ_NETWORK_USAGE_HISTORY permission above. 358 359 synchronized (mRulesLock) { 360 updateNotificationsLocked(); 361 } 362 } 363 }; 364 365 /** 366 * Receiver that watches for 367 * {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}. 368 */ 369 private BroadcastReceiver mBgReceiver = new BroadcastReceiver() { 370 @Override 371 public void onReceive(Context context, Intent intent) { 372 // on background handler thread, and verified CONNECTIVITY_INTERNAL 373 // permission above. 374 375 synchronized (mRulesLock) { 376 updateBackgroundData(false); 377 } 378 } 379 }; 380 381 /** 382 * Check {@link NetworkPolicy} against current {@link INetworkStatsService} 383 * to show visible notifications as needed. 384 */ 385 private void updateNotificationsLocked() { 386 if (LOGV) Slog.v(TAG, "updateNotificationsLocked()"); 387 388 // try refreshing time source when stale 389 if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) { 390 mTime.forceRefresh(); 391 } 392 393 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() 394 : System.currentTimeMillis(); 395 396 // TODO: when switching to kernel notifications, compute next future 397 // cycle boundary to recompute notifications. 398 399 // examine stats for each policy defined 400 for (NetworkPolicy policy : mNetworkPolicy) { 401 final long start = computeLastCycleBoundary(currentTime, policy); 402 final long end = currentTime; 403 404 final long total; 405 try { 406 final NetworkStats stats = mNetworkStats.getSummaryForNetwork( 407 policy.template, start, end); 408 final NetworkStats.Entry entry = stats.getValues(0, null); 409 total = entry.rxBytes + entry.txBytes; 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 final NetworkStats.Entry entry = stats.getValues(0, null); 610 total = entry.rxBytes + entry.txBytes; 611 } catch (RemoteException e) { 612 Slog.w(TAG, "problem reading summary for template " + policy.template); 613 continue; 614 } 615 616 if (LOGD) { 617 Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces " 618 + Arrays.toString(ifaces)); 619 } 620 621 // TODO: register for warning notification trigger through NMS 622 623 if (policy.limitBytes != NetworkPolicy.LIMIT_DISABLED) { 624 // remaining "quota" is based on usage in current cycle 625 final long quota = Math.max(0, policy.limitBytes - total); 626 627 if (ifaces.length > 1) { 628 // TODO: switch to shared quota once NMS supports 629 Slog.w(TAG, "shared quota unsupported; generating rule for each iface"); 630 } 631 632 for (String iface : ifaces) { 633 removeInterfaceQuota(iface); 634 setInterfaceQuota(iface, quota); 635 newMeteredIfaces.add(iface); 636 } 637 } 638 } 639 640 // remove quota on any trailing interfaces 641 for (String iface : mMeteredIfaces) { 642 if (!newMeteredIfaces.contains(iface)) { 643 removeInterfaceQuota(iface); 644 } 645 } 646 mMeteredIfaces = newMeteredIfaces; 647 648 final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]); 649 mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget(); 650 } 651 652 /** 653 * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we 654 * have at least a default mobile policy defined. 655 */ 656 private void ensureActiveMobilePolicyLocked() { 657 if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()"); 658 final String subscriberId = getActiveSubscriberId(); 659 final NetworkIdentity probeIdent = new NetworkIdentity( 660 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false); 661 662 // examine to see if any policy is defined for active mobile 663 boolean mobileDefined = false; 664 for (NetworkPolicy policy : mNetworkPolicy) { 665 if (policy.template.matches(probeIdent)) { 666 mobileDefined = true; 667 } 668 } 669 670 if (!mobileDefined) { 671 Slog.i(TAG, "no policy for active mobile network; generating default policy"); 672 673 // default mobile policy has combined 4GB warning, and assume usage 674 // cycle starts today today. 675 676 // TODO: move this policy definition to overlay or secure setting 677 final Time time = new Time(Time.TIMEZONE_UTC); 678 time.setToNow(); 679 final int cycleDay = time.monthDay; 680 681 final NetworkTemplate template = buildTemplateMobileAll(subscriberId); 682 mNetworkPolicy.add( 683 new NetworkPolicy(template, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED)); 684 writePolicyLocked(); 685 } 686 } 687 688 private void readPolicyLocked() { 689 if (LOGV) Slog.v(TAG, "readPolicyLocked()"); 690 691 // clear any existing policy and read from disk 692 mNetworkPolicy.clear(); 693 mUidPolicy.clear(); 694 695 FileInputStream fis = null; 696 try { 697 fis = mPolicyFile.openRead(); 698 final XmlPullParser in = Xml.newPullParser(); 699 in.setInput(fis, null); 700 701 int type; 702 int version = VERSION_CURRENT; 703 while ((type = in.next()) != END_DOCUMENT) { 704 final String tag = in.getName(); 705 if (type == START_TAG) { 706 if (TAG_POLICY_LIST.equals(tag)) { 707 version = readIntAttribute(in, ATTR_VERSION); 708 709 } else if (TAG_NETWORK_POLICY.equals(tag)) { 710 final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE); 711 final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID); 712 final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY); 713 final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES); 714 final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES); 715 716 final NetworkTemplate template = new NetworkTemplate( 717 networkTemplate, subscriberId); 718 mNetworkPolicy.add( 719 new NetworkPolicy(template, cycleDay, warningBytes, limitBytes)); 720 721 } else if (TAG_UID_POLICY.equals(tag)) { 722 final int uid = readIntAttribute(in, ATTR_UID); 723 final int policy = readIntAttribute(in, ATTR_POLICY); 724 725 if (isUidValidForPolicy(mContext, uid)) { 726 setUidPolicyUnchecked(uid, policy, false); 727 } else { 728 Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring"); 729 } 730 } 731 } 732 } 733 734 } catch (FileNotFoundException e) { 735 // missing policy is okay, probably first boot 736 } catch (IOException e) { 737 Slog.e(TAG, "problem reading network stats", e); 738 } catch (XmlPullParserException e) { 739 Slog.e(TAG, "problem reading network stats", e); 740 } finally { 741 IoUtils.closeQuietly(fis); 742 } 743 } 744 745 private void writePolicyLocked() { 746 if (LOGV) Slog.v(TAG, "writePolicyLocked()"); 747 748 FileOutputStream fos = null; 749 try { 750 fos = mPolicyFile.startWrite(); 751 752 XmlSerializer out = new FastXmlSerializer(); 753 out.setOutput(fos, "utf-8"); 754 out.startDocument(null, true); 755 756 out.startTag(null, TAG_POLICY_LIST); 757 writeIntAttribute(out, ATTR_VERSION, VERSION_CURRENT); 758 759 // write all known network policies 760 for (NetworkPolicy policy : mNetworkPolicy) { 761 final NetworkTemplate template = policy.template; 762 763 out.startTag(null, TAG_NETWORK_POLICY); 764 writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule()); 765 final String subscriberId = template.getSubscriberId(); 766 if (subscriberId != null) { 767 out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId); 768 } 769 writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay); 770 writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes); 771 writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes); 772 out.endTag(null, TAG_NETWORK_POLICY); 773 } 774 775 // write all known uid policies 776 for (int i = 0; i < mUidPolicy.size(); i++) { 777 final int uid = mUidPolicy.keyAt(i); 778 final int policy = mUidPolicy.valueAt(i); 779 780 // skip writing empty policies 781 if (policy == POLICY_NONE) continue; 782 783 out.startTag(null, TAG_UID_POLICY); 784 writeIntAttribute(out, ATTR_UID, uid); 785 writeIntAttribute(out, ATTR_POLICY, policy); 786 out.endTag(null, TAG_UID_POLICY); 787 } 788 789 out.endTag(null, TAG_POLICY_LIST); 790 out.endDocument(); 791 792 mPolicyFile.finishWrite(fos); 793 } catch (IOException e) { 794 if (fos != null) { 795 mPolicyFile.failWrite(fos); 796 } 797 } 798 } 799 800 @Override 801 public void setUidPolicy(int uid, int policy) { 802 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 803 804 if (!isUidValidForPolicy(mContext, uid)) { 805 throw new IllegalArgumentException("cannot apply policy to UID " + uid); 806 } 807 808 setUidPolicyUnchecked(uid, policy, true); 809 } 810 811 private void setUidPolicyUnchecked(int uid, int policy, boolean persist) { 812 final int oldPolicy; 813 synchronized (mRulesLock) { 814 oldPolicy = getUidPolicy(uid); 815 mUidPolicy.put(uid, policy); 816 817 // uid policy changed, recompute rules and persist policy. 818 updateRulesForUidLocked(uid); 819 if (persist) { 820 writePolicyLocked(); 821 } 822 } 823 } 824 825 @Override 826 public int getUidPolicy(int uid) { 827 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 828 829 synchronized (mRulesLock) { 830 return mUidPolicy.get(uid, POLICY_NONE); 831 } 832 } 833 834 @Override 835 public void registerListener(INetworkPolicyListener listener) { 836 // TODO: create permission for observing network policy 837 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 838 839 mListeners.register(listener); 840 841 // TODO: consider dispatching existing rules to new listeners 842 } 843 844 @Override 845 public void unregisterListener(INetworkPolicyListener listener) { 846 // TODO: create permission for observing network policy 847 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 848 849 mListeners.unregister(listener); 850 } 851 852 @Override 853 public void setNetworkPolicies(NetworkPolicy[] policies) { 854 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 855 856 synchronized (mRulesLock) { 857 mNetworkPolicy.clear(); 858 for (NetworkPolicy policy : policies) { 859 mNetworkPolicy.add(policy); 860 } 861 862 updateIfacesLocked(); 863 updateNotificationsLocked(); 864 writePolicyLocked(); 865 } 866 } 867 868 @Override 869 public NetworkPolicy[] getNetworkPolicies() { 870 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 871 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG); 872 873 synchronized (mRulesLock) { 874 return mNetworkPolicy.toArray(new NetworkPolicy[mNetworkPolicy.size()]); 875 } 876 } 877 878 @Override 879 protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 880 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 881 882 synchronized (mRulesLock) { 883 fout.println("Network policies:"); 884 for (NetworkPolicy policy : mNetworkPolicy) { 885 fout.print(" "); fout.println(policy.toString()); 886 } 887 888 fout.println("Policy status for known UIDs:"); 889 890 final SparseBooleanArray knownUids = new SparseBooleanArray(); 891 collectKeys(mUidPolicy, knownUids); 892 collectKeys(mUidForeground, knownUids); 893 collectKeys(mUidRules, knownUids); 894 895 final int size = knownUids.size(); 896 for (int i = 0; i < size; i++) { 897 final int uid = knownUids.keyAt(i); 898 fout.print(" UID="); 899 fout.print(uid); 900 901 fout.print(" policy="); 902 final int policyIndex = mUidPolicy.indexOfKey(uid); 903 if (policyIndex < 0) { 904 fout.print("UNKNOWN"); 905 } else { 906 dumpPolicy(fout, mUidPolicy.valueAt(policyIndex)); 907 } 908 909 fout.print(" foreground="); 910 final int foregroundIndex = mUidPidForeground.indexOfKey(uid); 911 if (foregroundIndex < 0) { 912 fout.print("UNKNOWN"); 913 } else { 914 dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex)); 915 } 916 917 fout.print(" rules="); 918 final int rulesIndex = mUidRules.indexOfKey(uid); 919 if (rulesIndex < 0) { 920 fout.print("UNKNOWN"); 921 } else { 922 dumpRules(fout, mUidRules.valueAt(rulesIndex)); 923 } 924 925 fout.println(); 926 } 927 } 928 } 929 930 @Override 931 public boolean isUidForeground(int uid) { 932 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 933 934 synchronized (mRulesLock) { 935 // only really in foreground when screen is also on 936 return mUidForeground.get(uid, false) && mScreenOn; 937 } 938 } 939 940 /** 941 * Foreground for PID changed; recompute foreground at UID level. If 942 * changed, will trigger {@link #updateRulesForUidLocked(int)}. 943 */ 944 private void computeUidForegroundLocked(int uid) { 945 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 946 947 // current pid is dropping foreground; examine other pids 948 boolean uidForeground = false; 949 final int size = pidForeground.size(); 950 for (int i = 0; i < size; i++) { 951 if (pidForeground.valueAt(i)) { 952 uidForeground = true; 953 break; 954 } 955 } 956 957 final boolean oldUidForeground = mUidForeground.get(uid, false); 958 if (oldUidForeground != uidForeground) { 959 // foreground changed, push updated rules 960 mUidForeground.put(uid, uidForeground); 961 updateRulesForUidLocked(uid); 962 } 963 } 964 965 private void updateScreenOn() { 966 synchronized (mRulesLock) { 967 try { 968 mScreenOn = mPowerManager.isScreenOn(); 969 } catch (RemoteException e) { 970 } 971 updateRulesForScreenLocked(); 972 } 973 } 974 975 private void updateBackgroundData(boolean systemReady) { 976 synchronized (mRulesLock) { 977 try { 978 mBackgroundData = mConnManager.getBackgroundDataSetting(); 979 } catch (RemoteException e) { 980 } 981 if (systemReady && mBackgroundData) { 982 // typical behavior of background enabled during systemReady; 983 // no need to clear rules for all UIDs. 984 } else { 985 updateRulesForBackgroundDataLocked(); 986 } 987 } 988 } 989 990 /** 991 * Update rules that might be changed by {@link #mScreenOn} value. 992 */ 993 private void updateRulesForScreenLocked() { 994 // only update rules for anyone with foreground activities 995 final int size = mUidForeground.size(); 996 for (int i = 0; i < size; i++) { 997 if (mUidForeground.valueAt(i)) { 998 final int uid = mUidForeground.keyAt(i); 999 updateRulesForUidLocked(uid); 1000 } 1001 } 1002 } 1003 1004 /** 1005 * Update rules that might be changed by {@link #mBackgroundData} value. 1006 */ 1007 private void updateRulesForBackgroundDataLocked() { 1008 // update rules for all installed applications 1009 final PackageManager pm = mContext.getPackageManager(); 1010 final List<ApplicationInfo> apps = pm.getInstalledApplications(0); 1011 for (ApplicationInfo app : apps) { 1012 updateRulesForUidLocked(app.uid); 1013 } 1014 1015 // and catch system UIDs 1016 // TODO: keep in sync with android_filesystem_config.h 1017 for (int uid = 1000; uid <= 1025; uid++) { 1018 updateRulesForUidLocked(uid); 1019 } 1020 for (int uid = 2000; uid <= 2002; uid++) { 1021 updateRulesForUidLocked(uid); 1022 } 1023 for (int uid = 3000; uid <= 3007; uid++) { 1024 updateRulesForUidLocked(uid); 1025 } 1026 for (int uid = 9998; uid <= 9999; uid++) { 1027 updateRulesForUidLocked(uid); 1028 } 1029 } 1030 1031 private void updateRulesForUidLocked(int uid) { 1032 final int uidPolicy = getUidPolicy(uid); 1033 final boolean uidForeground = isUidForeground(uid); 1034 1035 // derive active rules based on policy and active state 1036 int uidRules = RULE_ALLOW_ALL; 1037 if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { 1038 // uid in background, and policy says to block metered data 1039 uidRules = RULE_REJECT_METERED; 1040 } 1041 if (!uidForeground && !mBackgroundData) { 1042 // uid in background, and global background disabled 1043 uidRules = RULE_REJECT_METERED; 1044 } 1045 1046 // TODO: only dispatch when rules actually change 1047 1048 if (uidRules == RULE_ALLOW_ALL) { 1049 mUidRules.delete(uid); 1050 } else { 1051 mUidRules.put(uid, uidRules); 1052 } 1053 1054 final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0; 1055 setUidNetworkRules(uid, rejectMetered); 1056 1057 // dispatch changed rule to existing listeners 1058 mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget(); 1059 } 1060 1061 private Handler.Callback mHandlerCallback = new Handler.Callback() { 1062 /** {@inheritDoc} */ 1063 public boolean handleMessage(Message msg) { 1064 switch (msg.what) { 1065 case MSG_RULES_CHANGED: { 1066 final int uid = msg.arg1; 1067 final int uidRules = msg.arg2; 1068 final int length = mListeners.beginBroadcast(); 1069 for (int i = 0; i < length; i++) { 1070 final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 1071 if (listener != null) { 1072 try { 1073 listener.onUidRulesChanged(uid, uidRules); 1074 } catch (RemoteException e) { 1075 } 1076 } 1077 } 1078 mListeners.finishBroadcast(); 1079 return true; 1080 } 1081 case MSG_METERED_IFACES_CHANGED: { 1082 final String[] meteredIfaces = (String[]) msg.obj; 1083 final int length = mListeners.beginBroadcast(); 1084 for (int i = 0; i < length; i++) { 1085 final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 1086 if (listener != null) { 1087 try { 1088 listener.onMeteredIfacesChanged(meteredIfaces); 1089 } catch (RemoteException e) { 1090 } 1091 } 1092 } 1093 mListeners.finishBroadcast(); 1094 return true; 1095 } 1096 default: { 1097 return false; 1098 } 1099 } 1100 } 1101 }; 1102 1103 private void setInterfaceQuota(String iface, long quota) { 1104 try { 1105 mNetworkManagement.setInterfaceQuota(iface, quota); 1106 } catch (IllegalStateException e) { 1107 Slog.e(TAG, "problem setting interface quota", e); 1108 } catch (RemoteException e) { 1109 Slog.e(TAG, "problem setting interface quota", e); 1110 } 1111 } 1112 1113 private void removeInterfaceQuota(String iface) { 1114 try { 1115 mNetworkManagement.removeInterfaceQuota(iface); 1116 } catch (IllegalStateException e) { 1117 Slog.e(TAG, "problem removing interface quota", e); 1118 } catch (RemoteException e) { 1119 Slog.e(TAG, "problem removing interface quota", e); 1120 } 1121 } 1122 1123 private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1124 try { 1125 mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces); 1126 } catch (IllegalStateException e) { 1127 Slog.e(TAG, "problem setting uid rules", e); 1128 } catch (RemoteException e) { 1129 Slog.e(TAG, "problem setting uid rules", e); 1130 } 1131 } 1132 1133 private String getActiveSubscriberId() { 1134 final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService( 1135 Context.TELEPHONY_SERVICE); 1136 return telephony.getSubscriberId(); 1137 } 1138 1139 private static void collectKeys(SparseIntArray source, SparseBooleanArray target) { 1140 final int size = source.size(); 1141 for (int i = 0; i < size; i++) { 1142 target.put(source.keyAt(i), true); 1143 } 1144 } 1145 1146 private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) { 1147 final int size = source.size(); 1148 for (int i = 0; i < size; i++) { 1149 target.put(source.keyAt(i), true); 1150 } 1151 } 1152 1153 private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) { 1154 fout.print("["); 1155 final int size = value.size(); 1156 for (int i = 0; i < size; i++) { 1157 fout.print(value.keyAt(i) + "=" + value.valueAt(i)); 1158 if (i < size - 1) fout.print(","); 1159 } 1160 fout.print("]"); 1161 } 1162 1163 private static int readIntAttribute(XmlPullParser in, String name) throws IOException { 1164 final String value = in.getAttributeValue(null, name); 1165 try { 1166 return Integer.parseInt(value); 1167 } catch (NumberFormatException e) { 1168 throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 1169 } 1170 } 1171 1172 private static long readLongAttribute(XmlPullParser in, String name) throws IOException { 1173 final String value = in.getAttributeValue(null, name); 1174 try { 1175 return Long.parseLong(value); 1176 } catch (NumberFormatException e) { 1177 throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 1178 } 1179 } 1180 1181 private static void writeIntAttribute(XmlSerializer out, String name, int value) 1182 throws IOException { 1183 out.attribute(null, name, Integer.toString(value)); 1184 } 1185 1186 private static void writeLongAttribute(XmlSerializer out, String name, long value) 1187 throws IOException { 1188 out.attribute(null, name, Long.toString(value)); 1189 } 1190 1191} 1192