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