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