NetworkPolicyManagerService.java revision af11d4859582a9736aa204562f0beac5a7d60934
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 if (subscriberId == null) { 389 if (LOGV) Slog.v(TAG, "no active mobile network, ignoring policy check"); 390 return; 391 } 392 393 // examine to see if any policy is defined for active mobile 394 boolean mobileDefined = false; 395 for (NetworkPolicy policy : mNetworkPolicy) { 396 if (isNetworkTemplateMobile(policy.networkTemplate) 397 && Objects.equal(subscriberId, policy.subscriberId)) { 398 mobileDefined = true; 399 } 400 } 401 402 if (!mobileDefined) { 403 Slog.i(TAG, "no policy for active mobile network; generating default policy"); 404 405 // default mobile policy has combined 4GB warning, and assume usage 406 // cycle starts today today. 407 408 // TODO: move this policy definition to overlay or secure setting 409 final Time time = new Time(Time.TIMEZONE_UTC); 410 time.setToNow(); 411 final int cycleDay = time.monthDay; 412 413 mNetworkPolicy.add(new NetworkPolicy( 414 TEMPLATE_MOBILE_ALL, subscriberId, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED)); 415 } 416 } 417 418 private void readPolicyLocked() { 419 if (LOGV) Slog.v(TAG, "readPolicyLocked()"); 420 421 // clear any existing policy and read from disk 422 mNetworkPolicy.clear(); 423 mUidPolicy.clear(); 424 425 FileInputStream fis = null; 426 try { 427 fis = mPolicyFile.openRead(); 428 final XmlPullParser in = Xml.newPullParser(); 429 in.setInput(fis, null); 430 431 int type; 432 int version = VERSION_CURRENT; 433 while ((type = in.next()) != END_DOCUMENT) { 434 final String tag = in.getName(); 435 if (type == START_TAG) { 436 if (TAG_POLICY_LIST.equals(tag)) { 437 version = readIntAttribute(in, ATTR_VERSION); 438 439 } else if (TAG_NETWORK_POLICY.equals(tag)) { 440 final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE); 441 final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID); 442 final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY); 443 final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES); 444 final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES); 445 446 mNetworkPolicy.add(new NetworkPolicy( 447 networkTemplate, subscriberId, cycleDay, warningBytes, limitBytes)); 448 449 } else if (TAG_UID_POLICY.equals(tag)) { 450 final int uid = readIntAttribute(in, ATTR_UID); 451 final int policy = readIntAttribute(in, ATTR_POLICY); 452 453 mUidPolicy.put(uid, policy); 454 } 455 } 456 } 457 458 } catch (FileNotFoundException e) { 459 // missing policy is okay, probably first boot 460 } catch (IOException e) { 461 Slog.e(TAG, "problem reading network stats", e); 462 } catch (XmlPullParserException e) { 463 Slog.e(TAG, "problem reading network stats", e); 464 } finally { 465 IoUtils.closeQuietly(fis); 466 } 467 } 468 469 private void writePolicyLocked() { 470 if (LOGV) Slog.v(TAG, "writePolicyLocked()"); 471 472 FileOutputStream fos = null; 473 try { 474 fos = mPolicyFile.startWrite(); 475 476 XmlSerializer out = new FastXmlSerializer(); 477 out.setOutput(fos, "utf-8"); 478 out.startDocument(null, true); 479 480 out.startTag(null, TAG_POLICY_LIST); 481 writeIntAttribute(out, ATTR_VERSION, VERSION_CURRENT); 482 483 // write all known network policies 484 for (NetworkPolicy policy : mNetworkPolicy) { 485 out.startTag(null, TAG_NETWORK_POLICY); 486 writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, policy.networkTemplate); 487 if (policy.subscriberId != null) { 488 out.attribute(null, ATTR_SUBSCRIBER_ID, policy.subscriberId); 489 } 490 writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay); 491 writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes); 492 writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes); 493 out.endTag(null, TAG_NETWORK_POLICY); 494 } 495 496 // write all known uid policies 497 for (int i = 0; i < mUidPolicy.size(); i++) { 498 final int uid = mUidPolicy.keyAt(i); 499 final int policy = mUidPolicy.valueAt(i); 500 501 out.startTag(null, TAG_UID_POLICY); 502 writeIntAttribute(out, ATTR_UID, uid); 503 writeIntAttribute(out, ATTR_POLICY, policy); 504 out.endTag(null, TAG_UID_POLICY); 505 } 506 507 out.endTag(null, TAG_POLICY_LIST); 508 out.endDocument(); 509 510 mPolicyFile.finishWrite(fos); 511 } catch (IOException e) { 512 if (fos != null) { 513 mPolicyFile.failWrite(fos); 514 } 515 } 516 } 517 518 @Override 519 public void setUidPolicy(int uid, int policy) { 520 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 521 522 final int oldPolicy; 523 synchronized (mRulesLock) { 524 oldPolicy = getUidPolicy(uid); 525 mUidPolicy.put(uid, policy); 526 527 // uid policy changed, recompute rules and persist policy. 528 updateRulesForUidLocked(uid); 529 writePolicyLocked(); 530 } 531 } 532 533 @Override 534 public int getUidPolicy(int uid) { 535 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 536 537 synchronized (mRulesLock) { 538 return mUidPolicy.get(uid, POLICY_NONE); 539 } 540 } 541 542 @Override 543 public void registerListener(INetworkPolicyListener listener) { 544 mListeners.register(listener); 545 546 synchronized (mRulesLock) { 547 // dispatch any existing rules to new listeners 548 final int size = mUidRules.size(); 549 for (int i = 0; i < size; i++) { 550 final int uid = mUidRules.keyAt(i); 551 final int uidRules = mUidRules.valueAt(i); 552 if (uidRules != RULE_ALLOW_ALL) { 553 try { 554 listener.onRulesChanged(uid, uidRules); 555 } catch (RemoteException e) { 556 } 557 } 558 } 559 } 560 } 561 562 @Override 563 public void unregisterListener(INetworkPolicyListener listener) { 564 mListeners.unregister(listener); 565 } 566 567 @Override 568 public void setNetworkPolicies(NetworkPolicy[] policies) { 569 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 570 571 synchronized (mRulesLock) { 572 mNetworkPolicy.clear(); 573 for (NetworkPolicy policy : policies) { 574 mNetworkPolicy.add(policy); 575 } 576 577 updateIfacesLocked(); 578 writePolicyLocked(); 579 } 580 } 581 582 @Override 583 public NetworkPolicy[] getNetworkPolicies() { 584 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 585 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG); 586 587 synchronized (mRulesLock) { 588 return mNetworkPolicy.toArray(new NetworkPolicy[mNetworkPolicy.size()]); 589 } 590 } 591 592 @Override 593 protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 594 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 595 596 synchronized (mRulesLock) { 597 fout.println("Network policies:"); 598 for (NetworkPolicy policy : mNetworkPolicy) { 599 fout.print(" "); fout.println(policy.toString()); 600 } 601 602 fout.println("Policy status for known UIDs:"); 603 604 final SparseBooleanArray knownUids = new SparseBooleanArray(); 605 collectKeys(mUidPolicy, knownUids); 606 collectKeys(mUidForeground, knownUids); 607 collectKeys(mUidRules, knownUids); 608 609 final int size = knownUids.size(); 610 for (int i = 0; i < size; i++) { 611 final int uid = knownUids.keyAt(i); 612 fout.print(" UID="); 613 fout.print(uid); 614 615 fout.print(" policy="); 616 final int policyIndex = mUidPolicy.indexOfKey(uid); 617 if (policyIndex < 0) { 618 fout.print("UNKNOWN"); 619 } else { 620 dumpPolicy(fout, mUidPolicy.valueAt(policyIndex)); 621 } 622 623 fout.print(" foreground="); 624 final int foregroundIndex = mUidPidForeground.indexOfKey(uid); 625 if (foregroundIndex < 0) { 626 fout.print("UNKNOWN"); 627 } else { 628 dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex)); 629 } 630 631 fout.print(" rules="); 632 final int rulesIndex = mUidRules.indexOfKey(uid); 633 if (rulesIndex < 0) { 634 fout.print("UNKNOWN"); 635 } else { 636 dumpRules(fout, mUidRules.valueAt(rulesIndex)); 637 } 638 639 fout.println(); 640 } 641 } 642 } 643 644 @Override 645 public boolean isUidForeground(int uid) { 646 synchronized (mRulesLock) { 647 // only really in foreground when screen is also on 648 return mUidForeground.get(uid, false) && mScreenOn; 649 } 650 } 651 652 /** 653 * Foreground for PID changed; recompute foreground at UID level. If 654 * changed, will trigger {@link #updateRulesForUidLocked(int)}. 655 */ 656 private void computeUidForegroundLocked(int uid) { 657 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); 658 659 // current pid is dropping foreground; examine other pids 660 boolean uidForeground = false; 661 final int size = pidForeground.size(); 662 for (int i = 0; i < size; i++) { 663 if (pidForeground.valueAt(i)) { 664 uidForeground = true; 665 break; 666 } 667 } 668 669 final boolean oldUidForeground = mUidForeground.get(uid, false); 670 if (oldUidForeground != uidForeground) { 671 // foreground changed, push updated rules 672 mUidForeground.put(uid, uidForeground); 673 updateRulesForUidLocked(uid); 674 } 675 } 676 677 private void updateScreenOn() { 678 synchronized (mRulesLock) { 679 try { 680 mScreenOn = mPowerManager.isScreenOn(); 681 } catch (RemoteException e) { 682 } 683 updateRulesForScreenLocked(); 684 } 685 } 686 687 /** 688 * Update rules that might be changed by {@link #mScreenOn} value. 689 */ 690 private void updateRulesForScreenLocked() { 691 // only update rules for anyone with foreground activities 692 final int size = mUidForeground.size(); 693 for (int i = 0; i < size; i++) { 694 if (mUidForeground.valueAt(i)) { 695 final int uid = mUidForeground.keyAt(i); 696 updateRulesForUidLocked(uid); 697 } 698 } 699 } 700 701 private void updateRulesForUidLocked(int uid) { 702 final int uidPolicy = getUidPolicy(uid); 703 final boolean uidForeground = isUidForeground(uid); 704 705 // derive active rules based on policy and active state 706 int uidRules = RULE_ALLOW_ALL; 707 if (!uidForeground && (uidPolicy & POLICY_REJECT_PAID_BACKGROUND) != 0) { 708 // uid in background, and policy says to block paid data 709 uidRules = RULE_REJECT_PAID; 710 } 711 712 // TODO: only dispatch when rules actually change 713 714 // record rule locally to dispatch to new listeners 715 mUidRules.put(uid, uidRules); 716 717 // dispatch changed rule to existing listeners 718 final int length = mListeners.beginBroadcast(); 719 for (int i = 0; i < length; i++) { 720 final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); 721 if (listener != null) { 722 try { 723 listener.onRulesChanged(uid, uidRules); 724 } catch (RemoteException e) { 725 } 726 } 727 } 728 mListeners.finishBroadcast(); 729 } 730 731 private String getActiveSubscriberId() { 732 final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService( 733 Context.TELEPHONY_SERVICE); 734 return telephony.getSubscriberId(); 735 } 736 737 private static void collectKeys(SparseIntArray source, SparseBooleanArray target) { 738 final int size = source.size(); 739 for (int i = 0; i < size; i++) { 740 target.put(source.keyAt(i), true); 741 } 742 } 743 744 private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) { 745 final int size = source.size(); 746 for (int i = 0; i < size; i++) { 747 target.put(source.keyAt(i), true); 748 } 749 } 750 751 private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) { 752 fout.print("["); 753 final int size = value.size(); 754 for (int i = 0; i < size; i++) { 755 fout.print(value.keyAt(i) + "=" + value.valueAt(i)); 756 if (i < size - 1) fout.print(","); 757 } 758 fout.print("]"); 759 } 760 761 private static int readIntAttribute(XmlPullParser in, String name) throws IOException { 762 final String value = in.getAttributeValue(null, name); 763 try { 764 return Integer.parseInt(value); 765 } catch (NumberFormatException e) { 766 throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 767 } 768 } 769 770 private static long readLongAttribute(XmlPullParser in, String name) throws IOException { 771 final String value = in.getAttributeValue(null, name); 772 try { 773 return Long.parseLong(value); 774 } catch (NumberFormatException e) { 775 throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 776 } 777 } 778 779 private static void writeIntAttribute(XmlSerializer out, String name, int value) 780 throws IOException { 781 out.attribute(null, name, Integer.toString(value)); 782 } 783 784 private static void writeLongAttribute(XmlSerializer out, String name, long value) 785 throws IOException { 786 out.attribute(null, name, Long.toString(value)); 787 } 788 789} 790