NetworkPolicyManagerService.java revision fcc79771f092f34505b1accb80365cbcaa379667
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_PHONE_STATE; 24import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; 25import static android.net.NetworkPolicy.LIMIT_DISABLED; 26import static android.net.NetworkPolicyManager.POLICY_NONE; 27import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND; 28import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; 29import static android.net.NetworkPolicyManager.RULE_REJECT_PAID; 30import static android.net.NetworkPolicyManager.computeLastCycleBoundary; 31import static android.net.NetworkPolicyManager.dumpPolicy; 32import static android.net.NetworkPolicyManager.dumpRules; 33import static android.net.TrafficStats.TEMPLATE_MOBILE_ALL; 34import static android.net.TrafficStats.isNetworkTemplateMobile; 35import static android.text.format.DateUtils.DAY_IN_MILLIS; 36import static com.android.internal.util.Preconditions.checkNotNull; 37import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 38import static org.xmlpull.v1.XmlPullParser.START_TAG; 39 40import android.app.IActivityManager; 41import android.app.IProcessObserver; 42import android.content.BroadcastReceiver; 43import android.content.Context; 44import android.content.Intent; 45import android.content.IntentFilter; 46import android.net.ConnectivityManager; 47import android.net.IConnectivityManager; 48import android.net.INetworkPolicyListener; 49import android.net.INetworkPolicyManager; 50import android.net.INetworkStatsService; 51import android.net.NetworkPolicy; 52import android.net.NetworkState; 53import android.net.NetworkStats; 54import android.os.Environment; 55import android.os.Handler; 56import android.os.HandlerThread; 57import android.os.IPowerManager; 58import android.os.RemoteCallbackList; 59import android.os.RemoteException; 60import android.telephony.TelephonyManager; 61import android.text.format.Time; 62import android.util.NtpTrustedTime; 63import android.util.Slog; 64import android.util.SparseArray; 65import android.util.SparseBooleanArray; 66import android.util.SparseIntArray; 67import android.util.TrustedTime; 68import android.util.Xml; 69 70import com.android.internal.os.AtomicFile; 71import com.android.internal.util.FastXmlSerializer; 72import com.android.internal.util.Objects; 73import com.google.android.collect.Lists; 74import com.google.android.collect.Maps; 75 76import org.xmlpull.v1.XmlPullParser; 77import org.xmlpull.v1.XmlPullParserException; 78import org.xmlpull.v1.XmlSerializer; 79 80import java.io.File; 81import java.io.FileDescriptor; 82import java.io.FileInputStream; 83import java.io.FileNotFoundException; 84import java.io.FileOutputStream; 85import java.io.IOException; 86import java.io.PrintWriter; 87import java.net.ProtocolException; 88import java.util.ArrayList; 89import java.util.Arrays; 90import java.util.HashMap; 91 92import libcore.io.IoUtils; 93 94/** 95 * Service that maintains low-level network policy rules and collects usage 96 * statistics to drive those rules. 97 * <p> 98 * Derives active rules by combining a given policy with other system status, 99 * and delivers to listeners, such as {@link ConnectivityManager}, for 100 * enforcement. 101 */ 102public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 103 private static final String TAG = "NetworkPolicy"; 104 private static final boolean LOGD = true; 105 private static final boolean LOGV = false; 106 107 private static final int VERSION_CURRENT = 1; 108 109 private static final long KB_IN_BYTES = 1024; 110 private static final long MB_IN_BYTES = KB_IN_BYTES * 1024; 111 private static final long GB_IN_BYTES = MB_IN_BYTES * 1024; 112 113 private static final String TAG_POLICY_LIST = "policy-list"; 114 private static final String TAG_NETWORK_POLICY = "network-policy"; 115 private static final String TAG_UID_POLICY = "uid-policy"; 116 117 private static final String ATTR_VERSION = "version"; 118 private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate"; 119 private static final String ATTR_SUBSCRIBER_ID = "subscriberId"; 120 private static final String ATTR_CYCLE_DAY = "cycleDay"; 121 private static final String ATTR_WARNING_BYTES = "warningBytes"; 122 private static final String ATTR_LIMIT_BYTES = "limitBytes"; 123 private static final String ATTR_UID = "uid"; 124 private static final String ATTR_POLICY = "policy"; 125 126 private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS; 127 128 private final Context mContext; 129 private final IActivityManager mActivityManager; 130 private final IPowerManager mPowerManager; 131 private final INetworkStatsService mNetworkStats; 132 private final TrustedTime mTime; 133 134 private IConnectivityManager mConnManager; 135 136 private final Object mRulesLock = new Object(); 137 138 private boolean mScreenOn; 139 140 /** Current policy for network templates. */ 141 private ArrayList<NetworkPolicy> mNetworkPolicy = Lists.newArrayList(); 142 143 /** Current policy for each UID. */ 144 private SparseIntArray mUidPolicy = new SparseIntArray(); 145 /** Current derived network rules for each UID. */ 146 private SparseIntArray mUidRules = new SparseIntArray(); 147 148 /** Foreground at both UID and PID granularity. */ 149 private SparseBooleanArray mUidForeground = new SparseBooleanArray(); 150 private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray< 151 SparseBooleanArray>(); 152 153 private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList< 154 INetworkPolicyListener>(); 155 156 private final HandlerThread mHandlerThread; 157 private final Handler mHandler; 158 159 private final AtomicFile mPolicyFile; 160 161 // TODO: keep whitelist of system-critical services that should never have 162 // rules enforced, such as system, phone, and radio UIDs. 163 164 public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 165 IPowerManager powerManager, INetworkStatsService networkStats) { 166 // TODO: move to using cached NtpTrustedTime 167 this(context, activityManager, powerManager, networkStats, new NtpTrustedTime(), 168 getSystemDir()); 169 } 170 171 private static File getSystemDir() { 172 return new File(Environment.getDataDirectory(), "system"); 173 } 174 175 public NetworkPolicyManagerService(Context context, IActivityManager activityManager, 176 IPowerManager powerManager, INetworkStatsService networkStats, TrustedTime time, 177 File systemDir) { 178 mContext = checkNotNull(context, "missing context"); 179 mActivityManager = checkNotNull(activityManager, "missing activityManager"); 180 mPowerManager = checkNotNull(powerManager, "missing powerManager"); 181 mNetworkStats = checkNotNull(networkStats, "missing networkStats"); 182 mTime = checkNotNull(time, "missing TrustedTime"); 183 184 mHandlerThread = new HandlerThread(TAG); 185 mHandlerThread.start(); 186 mHandler = new Handler(mHandlerThread.getLooper()); 187 188 mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); 189 } 190 191 public void bindConnectivityManager(IConnectivityManager connManager) { 192 mConnManager = checkNotNull(connManager, "missing IConnectivityManager"); 193 } 194 195 public void systemReady() { 196 synchronized (mRulesLock) { 197 // read policy from disk 198 readPolicyLocked(); 199 } 200 201 updateScreenOn(); 202 203 try { 204 mActivityManager.registerProcessObserver(mProcessObserver); 205 } catch (RemoteException e) { 206 // ouch, no foregroundActivities updates means some processes may 207 // never get network access. 208 Slog.e(TAG, "unable to register IProcessObserver", e); 209 } 210 211 // TODO: traverse existing processes to know foreground state, or have 212 // activitymanager dispatch current state when new observer attached. 213 214 final IntentFilter screenFilter = new IntentFilter(); 215 screenFilter.addAction(Intent.ACTION_SCREEN_ON); 216 screenFilter.addAction(Intent.ACTION_SCREEN_OFF); 217 mContext.registerReceiver(mScreenReceiver, screenFilter); 218 219 // watch for network interfaces to be claimed 220 final IntentFilter ifaceFilter = new IntentFilter(); 221 ifaceFilter.addAction(CONNECTIVITY_ACTION); 222 mContext.registerReceiver(mIfaceReceiver, ifaceFilter, CONNECTIVITY_INTERNAL, mHandler); 223 224 } 225 226 private IProcessObserver mProcessObserver = new IProcessObserver.Stub() { 227 @Override 228 public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) { 229 // only someone like AMS should only be calling us 230 mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG); 231 232 synchronized (mRulesLock) { 233 // because a uid can have multiple pids running inside, we need to 234 // remember all pid states and summarize foreground at uid level. 235 236 // record foreground for this specific pid 237 SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 238 if (pidForeground == null) { 239 pidForeground = new SparseBooleanArray(2); 240 mUidPidForeground.put(uid, pidForeground); 241 } 242 pidForeground.put(pid, foregroundActivities); 243 computeUidForegroundLocked(uid); 244 } 245 } 246 247 @Override 248 public void onProcessDied(int pid, int uid) { 249 // only someone like AMS should only be calling us 250 mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG); 251 252 synchronized (mRulesLock) { 253 // clear records and recompute, when they exist 254 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 255 if (pidForeground != null) { 256 pidForeground.delete(pid); 257 computeUidForegroundLocked(uid); 258 } 259 } 260 } 261 }; 262 263 private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { 264 @Override 265 public void onReceive(Context context, Intent intent) { 266 synchronized (mRulesLock) { 267 // screen-related broadcasts are protected by system, no need 268 // for permissions check. 269 updateScreenOn(); 270 } 271 } 272 }; 273 274 /** 275 * Receiver that watches for {@link IConnectivityManager} to claim network 276 * interfaces. Used to apply {@link NetworkPolicy} to matching networks. 277 */ 278 private BroadcastReceiver mIfaceReceiver = new BroadcastReceiver() { 279 @Override 280 public void onReceive(Context context, Intent intent) { 281 // on background handler thread, and verified CONNECTIVITY_INTERNAL 282 // permission above. 283 synchronized (mRulesLock) { 284 ensureActiveMobilePolicyLocked(); 285 updateIfacesLocked(); 286 } 287 } 288 }; 289 290 /** 291 * Examine all connected {@link NetworkState}, looking for 292 * {@link NetworkPolicy} that need to be enforced. When matches found, set 293 * remaining quota based on usage cycle and historical stats. 294 */ 295 private void updateIfacesLocked() { 296 if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); 297 298 final NetworkState[] states; 299 try { 300 states = mConnManager.getAllNetworkState(); 301 } catch (RemoteException e) { 302 Slog.w(TAG, "problem reading network state"); 303 return; 304 } 305 306 // first, derive identity for all connected networks, which can be used 307 // to match against templates. 308 final HashMap<NetworkIdentity, String> networks = Maps.newHashMap(); 309 for (NetworkState state : states) { 310 // stash identity and iface away for later use 311 if (state.networkInfo.isConnected()) { 312 final String iface = state.linkProperties.getInterfaceName(); 313 final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); 314 networks.put(ident, iface); 315 } 316 } 317 318 // build list of rules and ifaces to enforce them against 319 final HashMap<NetworkPolicy, String[]> rules = Maps.newHashMap(); 320 final ArrayList<String> ifaceList = Lists.newArrayList(); 321 for (NetworkPolicy policy : mNetworkPolicy) { 322 323 // collect all active ifaces that match this template 324 ifaceList.clear(); 325 for (NetworkIdentity ident : networks.keySet()) { 326 if (ident.matchesTemplate(policy.networkTemplate, policy.subscriberId)) { 327 final String iface = networks.get(ident); 328 ifaceList.add(iface); 329 } 330 } 331 332 if (ifaceList.size() > 0) { 333 final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]); 334 rules.put(policy, ifaces); 335 } 336 } 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 // apply each policy that we found ifaces for; compute remaining data 347 // based on current cycle and historical stats, and push to kernel. 348 for (NetworkPolicy policy : rules.keySet()) { 349 final String[] ifaces = rules.get(policy); 350 351 final long start = computeLastCycleBoundary(currentTime, policy); 352 final long end = currentTime; 353 354 final NetworkStats stats; 355 final long total; 356 try { 357 stats = mNetworkStats.getSummaryForNetwork( 358 start, end, policy.networkTemplate, policy.subscriberId); 359 total = stats.rx[0] + stats.tx[0]; 360 } catch (RemoteException e) { 361 Slog.w(TAG, "problem reading summary for template " + policy.networkTemplate); 362 continue; 363 } 364 365 if (LOGD) { 366 Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces " 367 + Arrays.toString(ifaces)); 368 } 369 370 // TODO: register for warning notification trigger through NMS 371 372 if (policy.limitBytes != NetworkPolicy.LIMIT_DISABLED) { 373 // remaining "quota" is based on usage in current cycle 374 final long quota = Math.max(0, policy.limitBytes - total); 375 376 // TODO: push quota rule down through NMS 377 } 378 } 379 } 380 381 /** 382 * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we 383 * have at least a default mobile policy defined. 384 */ 385 private void ensureActiveMobilePolicyLocked() { 386 if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()"); 387 final String subscriberId = getActiveSubscriberId(); 388 389 // examine to see if any policy is defined for active mobile 390 boolean mobileDefined = false; 391 for (NetworkPolicy policy : mNetworkPolicy) { 392 if (isNetworkTemplateMobile(policy.networkTemplate) 393 && Objects.equal(subscriberId, policy.subscriberId)) { 394 mobileDefined = true; 395 } 396 } 397 398 if (!mobileDefined) { 399 Slog.i(TAG, "no policy for active mobile network; generating default policy"); 400 401 // default mobile policy has combined 4GB warning, and assume usage 402 // cycle starts today today. 403 404 // TODO: move this policy definition to overlay or secure setting 405 final Time time = new Time(Time.TIMEZONE_UTC); 406 time.setToNow(); 407 final int cycleDay = time.monthDay; 408 409 mNetworkPolicy.add(new NetworkPolicy( 410 TEMPLATE_MOBILE_ALL, subscriberId, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED)); 411 writePolicyLocked(); 412 } 413 } 414 415 private void readPolicyLocked() { 416 if (LOGV) Slog.v(TAG, "readPolicyLocked()"); 417 418 // clear any existing policy and read from disk 419 mNetworkPolicy.clear(); 420 mUidPolicy.clear(); 421 422 FileInputStream fis = null; 423 try { 424 fis = mPolicyFile.openRead(); 425 final XmlPullParser in = Xml.newPullParser(); 426 in.setInput(fis, null); 427 428 int type; 429 int version = VERSION_CURRENT; 430 while ((type = in.next()) != END_DOCUMENT) { 431 final String tag = in.getName(); 432 if (type == START_TAG) { 433 if (TAG_POLICY_LIST.equals(tag)) { 434 version = readIntAttribute(in, ATTR_VERSION); 435 436 } else if (TAG_NETWORK_POLICY.equals(tag)) { 437 final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE); 438 final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID); 439 final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY); 440 final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES); 441 final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES); 442 443 mNetworkPolicy.add(new NetworkPolicy( 444 networkTemplate, subscriberId, cycleDay, warningBytes, limitBytes)); 445 446 } else if (TAG_UID_POLICY.equals(tag)) { 447 final int uid = readIntAttribute(in, ATTR_UID); 448 final int policy = readIntAttribute(in, ATTR_POLICY); 449 450 mUidPolicy.put(uid, policy); 451 } 452 } 453 } 454 455 } catch (FileNotFoundException e) { 456 // missing policy is okay, probably first boot 457 } catch (IOException e) { 458 Slog.e(TAG, "problem reading network stats", e); 459 } catch (XmlPullParserException e) { 460 Slog.e(TAG, "problem reading network stats", e); 461 } finally { 462 IoUtils.closeQuietly(fis); 463 } 464 } 465 466 private void writePolicyLocked() { 467 if (LOGV) Slog.v(TAG, "writePolicyLocked()"); 468 469 FileOutputStream fos = null; 470 try { 471 fos = mPolicyFile.startWrite(); 472 473 XmlSerializer out = new FastXmlSerializer(); 474 out.setOutput(fos, "utf-8"); 475 out.startDocument(null, true); 476 477 out.startTag(null, TAG_POLICY_LIST); 478 writeIntAttribute(out, ATTR_VERSION, VERSION_CURRENT); 479 480 // write all known network policies 481 for (NetworkPolicy policy : mNetworkPolicy) { 482 out.startTag(null, TAG_NETWORK_POLICY); 483 writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, policy.networkTemplate); 484 if (policy.subscriberId != null) { 485 out.attribute(null, ATTR_SUBSCRIBER_ID, policy.subscriberId); 486 } 487 writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay); 488 writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes); 489 writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes); 490 out.endTag(null, TAG_NETWORK_POLICY); 491 } 492 493 // write all known uid policies 494 for (int i = 0; i < mUidPolicy.size(); i++) { 495 final int uid = mUidPolicy.keyAt(i); 496 final int policy = mUidPolicy.valueAt(i); 497 498 out.startTag(null, TAG_UID_POLICY); 499 writeIntAttribute(out, ATTR_UID, uid); 500 writeIntAttribute(out, ATTR_POLICY, policy); 501 out.endTag(null, TAG_UID_POLICY); 502 } 503 504 out.endTag(null, TAG_POLICY_LIST); 505 out.endDocument(); 506 507 mPolicyFile.finishWrite(fos); 508 } catch (IOException e) { 509 if (fos != null) { 510 mPolicyFile.failWrite(fos); 511 } 512 } 513 } 514 515 @Override 516 public void setUidPolicy(int uid, int policy) { 517 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 518 519 final int oldPolicy; 520 synchronized (mRulesLock) { 521 oldPolicy = getUidPolicy(uid); 522 mUidPolicy.put(uid, policy); 523 524 // uid policy changed, recompute rules and persist policy. 525 updateRulesForUidLocked(uid); 526 writePolicyLocked(); 527 } 528 } 529 530 @Override 531 public int getUidPolicy(int uid) { 532 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 533 534 synchronized (mRulesLock) { 535 return mUidPolicy.get(uid, POLICY_NONE); 536 } 537 } 538 539 @Override 540 public void registerListener(INetworkPolicyListener listener) { 541 mListeners.register(listener); 542 543 synchronized (mRulesLock) { 544 // dispatch any existing rules to new listeners 545 final int size = mUidRules.size(); 546 for (int i = 0; i < size; i++) { 547 final int uid = mUidRules.keyAt(i); 548 final int uidRules = mUidRules.valueAt(i); 549 if (uidRules != RULE_ALLOW_ALL) { 550 try { 551 listener.onRulesChanged(uid, uidRules); 552 } catch (RemoteException e) { 553 } 554 } 555 } 556 } 557 } 558 559 @Override 560 public void unregisterListener(INetworkPolicyListener listener) { 561 mListeners.unregister(listener); 562 } 563 564 @Override 565 public void setNetworkPolicies(NetworkPolicy[] policies) { 566 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 567 568 synchronized (mRulesLock) { 569 mNetworkPolicy.clear(); 570 for (NetworkPolicy policy : policies) { 571 mNetworkPolicy.add(policy); 572 } 573 574 updateIfacesLocked(); 575 writePolicyLocked(); 576 } 577 } 578 579 @Override 580 public NetworkPolicy[] getNetworkPolicies() { 581 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 582 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG); 583 584 synchronized (mRulesLock) { 585 return mNetworkPolicy.toArray(new NetworkPolicy[mNetworkPolicy.size()]); 586 } 587 } 588 589 @Override 590 protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 591 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 592 593 synchronized (mRulesLock) { 594 fout.println("Network policies:"); 595 for (NetworkPolicy policy : mNetworkPolicy) { 596 fout.print(" "); fout.println(policy.toString()); 597 } 598 599 fout.println("Policy status for known UIDs:"); 600 601 final SparseBooleanArray knownUids = new SparseBooleanArray(); 602 collectKeys(mUidPolicy, knownUids); 603 collectKeys(mUidForeground, knownUids); 604 collectKeys(mUidRules, knownUids); 605 606 final int size = knownUids.size(); 607 for (int i = 0; i < size; i++) { 608 final int uid = knownUids.keyAt(i); 609 fout.print(" UID="); 610 fout.print(uid); 611 612 fout.print(" policy="); 613 final int policyIndex = mUidPolicy.indexOfKey(uid); 614 if (policyIndex < 0) { 615 fout.print("UNKNOWN"); 616 } else { 617 dumpPolicy(fout, mUidPolicy.valueAt(policyIndex)); 618 } 619 620 fout.print(" foreground="); 621 final int foregroundIndex = mUidPidForeground.indexOfKey(uid); 622 if (foregroundIndex < 0) { 623 fout.print("UNKNOWN"); 624 } else { 625 dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex)); 626 } 627 628 fout.print(" rules="); 629 final int rulesIndex = mUidRules.indexOfKey(uid); 630 if (rulesIndex < 0) { 631 fout.print("UNKNOWN"); 632 } else { 633 dumpRules(fout, mUidRules.valueAt(rulesIndex)); 634 } 635 636 fout.println(); 637 } 638 } 639 } 640 641 @Override 642 public boolean isUidForeground(int uid) { 643 synchronized (mRulesLock) { 644 // only really in foreground when screen is also on 645 return mUidForeground.get(uid, false) && mScreenOn; 646 } 647 } 648 649 /** 650 * Foreground for PID changed; recompute foreground at UID level. If 651 * changed, will trigger {@link #updateRulesForUidLocked(int)}. 652 */ 653 private void computeUidForegroundLocked(int uid) { 654 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 655 656 // current pid is dropping foreground; examine other pids 657 boolean uidForeground = false; 658 final int size = pidForeground.size(); 659 for (int i = 0; i < size; i++) { 660 if (pidForeground.valueAt(i)) { 661 uidForeground = true; 662 break; 663 } 664 } 665 666 final boolean oldUidForeground = mUidForeground.get(uid, false); 667 if (oldUidForeground != uidForeground) { 668 // foreground changed, push updated rules 669 mUidForeground.put(uid, uidForeground); 670 updateRulesForUidLocked(uid); 671 } 672 } 673 674 private void updateScreenOn() { 675 synchronized (mRulesLock) { 676 try { 677 mScreenOn = mPowerManager.isScreenOn(); 678 } catch (RemoteException e) { 679 } 680 updateRulesForScreenLocked(); 681 } 682 } 683 684 /** 685 * Update rules that might be changed by {@link #mScreenOn} value. 686 */ 687 private void updateRulesForScreenLocked() { 688 // only update rules for anyone with foreground activities 689 final int size = mUidForeground.size(); 690 for (int i = 0; i < size; i++) { 691 if (mUidForeground.valueAt(i)) { 692 final int uid = mUidForeground.keyAt(i); 693 updateRulesForUidLocked(uid); 694 } 695 } 696 } 697 698 private void updateRulesForUidLocked(int uid) { 699 final int uidPolicy = getUidPolicy(uid); 700 final boolean uidForeground = isUidForeground(uid); 701 702 // derive active rules based on policy and active state 703 int uidRules = RULE_ALLOW_ALL; 704 if (!uidForeground && (uidPolicy & POLICY_REJECT_PAID_BACKGROUND) != 0) { 705 // uid in background, and policy says to block paid data 706 uidRules = RULE_REJECT_PAID; 707 } 708 709 // TODO: only dispatch when rules actually change 710 711 // record rule locally to dispatch to new listeners 712 mUidRules.put(uid, uidRules); 713 714 // dispatch changed rule to existing listeners 715 final int length = mListeners.beginBroadcast(); 716 for (int i = 0; i < length; i++) { 717 final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 718 if (listener != null) { 719 try { 720 listener.onRulesChanged(uid, uidRules); 721 } catch (RemoteException e) { 722 } 723 } 724 } 725 mListeners.finishBroadcast(); 726 } 727 728 private String getActiveSubscriberId() { 729 final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService( 730 Context.TELEPHONY_SERVICE); 731 return telephony.getSubscriberId(); 732 } 733 734 private static void collectKeys(SparseIntArray source, SparseBooleanArray target) { 735 final int size = source.size(); 736 for (int i = 0; i < size; i++) { 737 target.put(source.keyAt(i), true); 738 } 739 } 740 741 private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) { 742 final int size = source.size(); 743 for (int i = 0; i < size; i++) { 744 target.put(source.keyAt(i), true); 745 } 746 } 747 748 private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) { 749 fout.print("["); 750 final int size = value.size(); 751 for (int i = 0; i < size; i++) { 752 fout.print(value.keyAt(i) + "=" + value.valueAt(i)); 753 if (i < size - 1) fout.print(","); 754 } 755 fout.print("]"); 756 } 757 758 private static int readIntAttribute(XmlPullParser in, String name) throws IOException { 759 final String value = in.getAttributeValue(null, name); 760 try { 761 return Integer.parseInt(value); 762 } catch (NumberFormatException e) { 763 throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 764 } 765 } 766 767 private static long readLongAttribute(XmlPullParser in, String name) throws IOException { 768 final String value = in.getAttributeValue(null, name); 769 try { 770 return Long.parseLong(value); 771 } catch (NumberFormatException e) { 772 throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 773 } 774 } 775 776 private static void writeIntAttribute(XmlSerializer out, String name, int value) 777 throws IOException { 778 out.attribute(null, name, Integer.toString(value)); 779 } 780 781 private static void writeLongAttribute(XmlSerializer out, String name, long value) 782 throws IOException { 783 out.attribute(null, name, Long.toString(value)); 784 } 785 786} 787