1 /* 2 * Copyright (C) 2009 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 17 package com.android.internal.os; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.content.pm.PackageManager; 24 import android.content.res.Resources; 25 import android.hardware.SensorManager; 26 import android.os.BatteryStats; 27 import android.os.BatteryStats.Uid; 28 import android.os.Build; 29 import android.os.Bundle; 30 import android.os.MemoryFile; 31 import android.os.Parcel; 32 import android.os.ParcelFileDescriptor; 33 import android.os.Process; 34 import android.os.RemoteException; 35 import android.os.SELinux; 36 import android.os.ServiceManager; 37 import android.os.SystemClock; 38 import android.os.UserHandle; 39 import android.telephony.TelephonyManager; 40 import android.util.ArrayMap; 41 import android.util.Log; 42 import android.util.SparseArray; 43 44 import com.android.internal.annotations.VisibleForTesting; 45 import com.android.internal.app.IBatteryStats; 46 import com.android.internal.os.BatterySipper.DrainType; 47 import com.android.internal.util.ArrayUtils; 48 49 import java.io.File; 50 import java.io.FileInputStream; 51 import java.io.FileOutputStream; 52 import java.io.IOException; 53 import java.util.ArrayList; 54 import java.util.Collections; 55 import java.util.List; 56 57 /** 58 * A helper class for retrieving the power usage information for all applications and services. 59 * 60 * The caller must initialize this class as soon as activity object is ready to use (for example, in 61 * onAttach() for Fragment), call create() in onCreate() and call destroy() in onDestroy(). 62 * 63 * @deprecated Please use BatteryStatsManager.getBatteryUsageStats instead. 64 */ 65 @Deprecated 66 public class BatteryStatsHelper { 67 static final boolean DEBUG = false; 68 69 private static final String TAG = BatteryStatsHelper.class.getSimpleName(); 70 71 private static BatteryStats sStatsXfer; 72 private static Intent sBatteryBroadcastXfer; 73 private static ArrayMap<File, BatteryStats> sFileXfer = new ArrayMap<>(); 74 75 final private Context mContext; 76 final private boolean mCollectBatteryBroadcast; 77 final private boolean mWifiOnly; 78 79 private List<PowerCalculator> mPowerCalculators; 80 81 @UnsupportedAppUsage 82 private IBatteryStats mBatteryInfo; 83 private BatteryStats mStats; 84 private Intent mBatteryBroadcast; 85 @UnsupportedAppUsage 86 private PowerProfile mPowerProfile; 87 88 private String[] mSystemPackageArray; 89 private String[] mServicepackageArray; 90 private PackageManager mPackageManager; 91 92 /** 93 * List of apps using power. 94 */ 95 @UnsupportedAppUsage 96 private final List<BatterySipper> mUsageList = new ArrayList<>(); 97 98 private final List<BatterySipper> mMobilemsppList = new ArrayList<>(); 99 100 private int mStatsType = BatteryStats.STATS_SINCE_CHARGED; 101 102 long mRawRealtimeUs; 103 long mRawUptimeUs; 104 long mBatteryRealtimeUs; 105 long mBatteryUptimeUs; 106 long mBatteryTimeRemainingUs; 107 long mChargeTimeRemainingUs; 108 109 private long mStatsPeriod = 0; 110 111 // The largest entry by power. 112 private double mMaxPower = 1; 113 114 // The largest real entry by power (not undercounted or overcounted). 115 private double mMaxRealPower = 1; 116 117 // Total computed power. 118 private double mComputedPower; 119 private double mTotalPower; 120 private double mMinDrainedPower; 121 private double mMaxDrainedPower; 122 checkWifiOnly(Context context)123 public static boolean checkWifiOnly(Context context) { 124 final TelephonyManager tm = context.getSystemService(TelephonyManager.class); 125 if (tm == null) { 126 return false; 127 } 128 return !tm.isDataCapable(); 129 } 130 131 @UnsupportedAppUsage BatteryStatsHelper(Context context)132 public BatteryStatsHelper(Context context) { 133 this(context, true); 134 } 135 136 @UnsupportedAppUsage BatteryStatsHelper(Context context, boolean collectBatteryBroadcast)137 public BatteryStatsHelper(Context context, boolean collectBatteryBroadcast) { 138 this(context, collectBatteryBroadcast, checkWifiOnly(context)); 139 } 140 141 @UnsupportedAppUsage BatteryStatsHelper(Context context, boolean collectBatteryBroadcast, boolean wifiOnly)142 public BatteryStatsHelper(Context context, boolean collectBatteryBroadcast, boolean wifiOnly) { 143 mContext = context; 144 mCollectBatteryBroadcast = collectBatteryBroadcast; 145 mWifiOnly = wifiOnly; 146 mPackageManager = context.getPackageManager(); 147 148 final Resources resources = context.getResources(); 149 mSystemPackageArray = resources.getStringArray( 150 com.android.internal.R.array.config_batteryPackageTypeSystem); 151 mServicepackageArray = resources.getStringArray( 152 com.android.internal.R.array.config_batteryPackageTypeService); 153 } 154 storeStatsHistoryInFile(String fname)155 public void storeStatsHistoryInFile(String fname) { 156 synchronized (sFileXfer) { 157 File path = makeFilePath(mContext, fname); 158 sFileXfer.put(path, this.getStats()); 159 FileOutputStream fout = null; 160 try { 161 fout = new FileOutputStream(path); 162 Parcel hist = Parcel.obtain(); 163 getStats().writeToParcelWithoutUids(hist, 0); 164 byte[] histData = hist.marshall(); 165 fout.write(histData); 166 } catch (IOException e) { 167 Log.w(TAG, "Unable to write history to file", e); 168 } finally { 169 if (fout != null) { 170 try { 171 fout.close(); 172 } catch (IOException e) { 173 } 174 } 175 } 176 } 177 } 178 statsFromFile(Context context, String fname)179 public static BatteryStats statsFromFile(Context context, String fname) { 180 synchronized (sFileXfer) { 181 File path = makeFilePath(context, fname); 182 BatteryStats stats = sFileXfer.get(path); 183 if (stats != null) { 184 return stats; 185 } 186 FileInputStream fin = null; 187 try { 188 fin = new FileInputStream(path); 189 byte[] data = readFully(fin); 190 Parcel parcel = Parcel.obtain(); 191 parcel.unmarshall(data, 0, data.length); 192 parcel.setDataPosition(0); 193 return com.android.internal.os.BatteryStatsImpl.CREATOR.createFromParcel(parcel); 194 } catch (IOException e) { 195 Log.w(TAG, "Unable to read history to file", e); 196 } finally { 197 if (fin != null) { 198 try { 199 fin.close(); 200 } catch (IOException e) { 201 } 202 } 203 } 204 } 205 return getStats(IBatteryStats.Stub.asInterface( 206 ServiceManager.getService(BatteryStats.SERVICE_NAME)), true); 207 } 208 209 @UnsupportedAppUsage dropFile(Context context, String fname)210 public static void dropFile(Context context, String fname) { 211 makeFilePath(context, fname).delete(); 212 } 213 makeFilePath(Context context, String fname)214 private static File makeFilePath(Context context, String fname) { 215 return new File(context.getFilesDir(), fname); 216 } 217 218 /** Clears the current stats and forces recreating for future use. */ 219 @UnsupportedAppUsage clearStats()220 public void clearStats() { 221 mStats = null; 222 } 223 224 @UnsupportedAppUsage getStats()225 public BatteryStats getStats() { 226 return getStats(true /* updateAll */); 227 } 228 229 /** Retrieves stats from BatteryService, optionally getting updated numbers */ getStats(boolean updateAll)230 public BatteryStats getStats(boolean updateAll) { 231 if (mStats == null) { 232 load(updateAll); 233 } 234 return mStats; 235 } 236 237 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getBatteryBroadcast()238 public Intent getBatteryBroadcast() { 239 if (mBatteryBroadcast == null && mCollectBatteryBroadcast) { 240 load(); 241 } 242 return mBatteryBroadcast; 243 } 244 getPowerProfile()245 public PowerProfile getPowerProfile() { 246 return mPowerProfile; 247 } 248 create(BatteryStats stats)249 public void create(BatteryStats stats) { 250 mPowerProfile = new PowerProfile(mContext); 251 mStats = stats; 252 } 253 254 @UnsupportedAppUsage create(Bundle icicle)255 public void create(Bundle icicle) { 256 if (icicle != null) { 257 mStats = sStatsXfer; 258 mBatteryBroadcast = sBatteryBroadcastXfer; 259 } 260 mBatteryInfo = IBatteryStats.Stub.asInterface( 261 ServiceManager.getService(BatteryStats.SERVICE_NAME)); 262 mPowerProfile = new PowerProfile(mContext); 263 } 264 265 @UnsupportedAppUsage storeState()266 public void storeState() { 267 sStatsXfer = mStats; 268 sBatteryBroadcastXfer = mBatteryBroadcast; 269 } 270 makemAh(double power)271 public static String makemAh(double power) { 272 return PowerCalculator.formatCharge(power); 273 } 274 275 /** 276 * Refreshes the power usage list. 277 */ 278 @UnsupportedAppUsage refreshStats(int statsType, int asUser)279 public void refreshStats(int statsType, int asUser) { 280 SparseArray<UserHandle> users = new SparseArray<>(1); 281 users.put(asUser, new UserHandle(asUser)); 282 refreshStats(statsType, users); 283 } 284 285 /** 286 * Refreshes the power usage list. 287 */ 288 @UnsupportedAppUsage refreshStats(int statsType, List<UserHandle> asUsers)289 public void refreshStats(int statsType, List<UserHandle> asUsers) { 290 final int n = asUsers.size(); 291 SparseArray<UserHandle> users = new SparseArray<>(n); 292 for (int i = 0; i < n; ++i) { 293 UserHandle userHandle = asUsers.get(i); 294 users.put(userHandle.getIdentifier(), userHandle); 295 } 296 refreshStats(statsType, users); 297 } 298 299 /** 300 * Refreshes the power usage list. 301 */ 302 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) refreshStats(int statsType, SparseArray<UserHandle> asUsers)303 public void refreshStats(int statsType, SparseArray<UserHandle> asUsers) { 304 refreshStats(statsType, asUsers, SystemClock.elapsedRealtime() * 1000, 305 SystemClock.uptimeMillis() * 1000); 306 } 307 refreshStats(int statsType, SparseArray<UserHandle> asUsers, long rawRealtimeUs, long rawUptimeUs)308 public void refreshStats(int statsType, SparseArray<UserHandle> asUsers, long rawRealtimeUs, 309 long rawUptimeUs) { 310 if (statsType != BatteryStats.STATS_SINCE_CHARGED) { 311 Log.w(TAG, "refreshStats called for statsType " + statsType + " but only " 312 + "STATS_SINCE_CHARGED is supported. Using STATS_SINCE_CHARGED instead."); 313 } 314 315 // Initialize mStats if necessary. 316 getStats(); 317 318 mMaxPower = 0; 319 mMaxRealPower = 0; 320 mComputedPower = 0; 321 mTotalPower = 0; 322 323 mUsageList.clear(); 324 mMobilemsppList.clear(); 325 326 if (mStats == null) { 327 return; 328 } 329 330 if (mPowerCalculators == null) { 331 mPowerCalculators = new ArrayList<>(); 332 333 // Power calculators are applied in the order of registration 334 mPowerCalculators.add(new CpuPowerCalculator(mPowerProfile)); 335 mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile)); 336 mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile)); 337 if (!mWifiOnly) { 338 mPowerCalculators.add(new MobileRadioPowerCalculator(mPowerProfile)); 339 } 340 mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile)); 341 mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile)); 342 mPowerCalculators.add(new SensorPowerCalculator( 343 mContext.getSystemService(SensorManager.class))); 344 mPowerCalculators.add(new GnssPowerCalculator(mPowerProfile)); 345 mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile)); 346 mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile)); 347 mPowerCalculators.add(new MediaPowerCalculator(mPowerProfile)); 348 mPowerCalculators.add(new PhonePowerCalculator(mPowerProfile)); 349 mPowerCalculators.add(new ScreenPowerCalculator(mPowerProfile)); 350 mPowerCalculators.add(new AmbientDisplayPowerCalculator(mPowerProfile)); 351 mPowerCalculators.add(new SystemServicePowerCalculator(mPowerProfile)); 352 mPowerCalculators.add(new IdlePowerCalculator(mPowerProfile)); 353 mPowerCalculators.add(new CustomMeasuredPowerCalculator(mPowerProfile)); 354 355 mPowerCalculators.add(new UserPowerCalculator()); 356 } 357 358 for (int i = 0, size = mPowerCalculators.size(); i < size; i++) { 359 mPowerCalculators.get(i).reset(); 360 } 361 362 mStatsType = statsType; 363 mRawUptimeUs = rawUptimeUs; 364 mRawRealtimeUs = rawRealtimeUs; 365 mBatteryUptimeUs = mStats.getBatteryUptime(rawUptimeUs); 366 mBatteryRealtimeUs = mStats.getBatteryRealtime(rawRealtimeUs); 367 mBatteryTimeRemainingUs = mStats.computeBatteryTimeRemaining(rawRealtimeUs); 368 mChargeTimeRemainingUs = mStats.computeChargeTimeRemaining(rawRealtimeUs); 369 mStatsPeriod = mStats.computeBatteryRealtime(rawRealtimeUs, mStatsType); 370 371 if (DEBUG) { 372 Log.d(TAG, "Raw time: realtime=" + (rawRealtimeUs / 1000) + " uptime=" 373 + (rawUptimeUs / 1000)); 374 Log.d(TAG, "Battery time: realtime=" + (mBatteryRealtimeUs / 1000) + " uptime=" 375 + (mBatteryUptimeUs / 1000)); 376 Log.d(TAG, "Battery type time: realtime=" + (mStatsPeriod / 1000) + " uptime=" 377 + (mStats.computeBatteryUptime(rawRealtimeUs, mStatsType) / 1000)); 378 } 379 mMinDrainedPower = (mStats.getLowDischargeAmountSinceCharge() 380 * mPowerProfile.getBatteryCapacity()) / 100; 381 mMaxDrainedPower = (mStats.getHighDischargeAmountSinceCharge() 382 * mPowerProfile.getBatteryCapacity()) / 100; 383 384 // Create list of (almost all) sippers, calculate their usage, and put them in mUsageList. 385 processAppUsage(asUsers); 386 387 Collections.sort(mUsageList); 388 389 Collections.sort(mMobilemsppList, 390 (lhs, rhs) -> Double.compare(rhs.mobilemspp, lhs.mobilemspp)); 391 392 // At this point, we've sorted the list so we are guaranteed the max values are at the top. 393 // We have only added real powers so far. 394 if (!mUsageList.isEmpty()) { 395 mMaxRealPower = mMaxPower = mUsageList.get(0).totalPowerMah; 396 final int usageListCount = mUsageList.size(); 397 for (int i = 0; i < usageListCount; i++) { 398 mComputedPower += mUsageList.get(i).totalPowerMah; 399 } 400 } 401 402 if (DEBUG) { 403 Log.d(TAG, "Accuracy: total computed=" + PowerCalculator.formatCharge(mComputedPower) 404 + ", min discharge=" + PowerCalculator.formatCharge(mMinDrainedPower) 405 + ", max discharge=" + PowerCalculator.formatCharge(mMaxDrainedPower)); 406 } 407 408 mTotalPower = mComputedPower; 409 if (mStats.getLowDischargeAmountSinceCharge() > 1) { 410 if (mMinDrainedPower > mComputedPower) { 411 double amount = mMinDrainedPower - mComputedPower; 412 mTotalPower = mMinDrainedPower; 413 BatterySipper bs = new BatterySipper(DrainType.UNACCOUNTED, null, amount); 414 415 // Insert the BatterySipper in its sorted position. 416 int index = Collections.binarySearch(mUsageList, bs); 417 if (index < 0) { 418 index = -(index + 1); 419 } 420 mUsageList.add(index, bs); 421 mMaxPower = Math.max(mMaxPower, amount); 422 } else if (mMaxDrainedPower < mComputedPower) { 423 double amount = mComputedPower - mMaxDrainedPower; 424 425 // Insert the BatterySipper in its sorted position. 426 BatterySipper bs = new BatterySipper(DrainType.OVERCOUNTED, null, amount); 427 int index = Collections.binarySearch(mUsageList, bs); 428 if (index < 0) { 429 index = -(index + 1); 430 } 431 mUsageList.add(index, bs); 432 mMaxPower = Math.max(mMaxPower, amount); 433 } 434 } 435 436 // Smear it! 437 final double hiddenPowerMah = removeHiddenBatterySippers(mUsageList); 438 final double totalRemainingPower = getTotalPower() - hiddenPowerMah; 439 if (Math.abs(totalRemainingPower) > 1e-3) { 440 for (int i = 0, size = mUsageList.size(); i < size; i++) { 441 final BatterySipper sipper = mUsageList.get(i); 442 if (!sipper.shouldHide) { 443 sipper.proportionalSmearMah = hiddenPowerMah 444 * ((sipper.totalPowerMah + sipper.screenPowerMah) 445 / totalRemainingPower); 446 sipper.sumPower(); 447 } 448 } 449 } 450 } 451 processAppUsage(SparseArray<UserHandle> asUsers)452 private void processAppUsage(SparseArray<UserHandle> asUsers) { 453 final SparseArray<? extends Uid> uidStats = mStats.getUidStats(); 454 455 final ArrayList<BatterySipper> sippers = new ArrayList<>(uidStats.size()); 456 457 for (int iu = 0, size = uidStats.size(); iu < size; iu++) { 458 final Uid u = uidStats.valueAt(iu); 459 sippers.add(new BatterySipper(DrainType.APP, u, 0)); 460 } 461 462 for (int i = 0, size = mPowerCalculators.size(); i < size; i++) { 463 final PowerCalculator calculator = mPowerCalculators.get(i); 464 calculator.calculate(sippers, mStats, mRawRealtimeUs, mRawUptimeUs, mStatsType, 465 asUsers); 466 } 467 468 for (int i = sippers.size() - 1; i >= 0; i--) { 469 final BatterySipper sipper = sippers.get(i); 470 final double totalPower = sipper.sumPower(); 471 if (DEBUG && totalPower != 0) { 472 Log.d(TAG, String.format("UID %d: total power=%s", sipper.getUid(), 473 PowerCalculator.formatCharge(totalPower))); 474 } 475 476 // Add the sipper to the list if it is consuming power. 477 if (totalPower != 0 || sipper.getUid() == 0) { 478 if (sipper.drainType == DrainType.APP) { 479 sipper.computeMobilemspp(); 480 if (sipper.mobilemspp != 0) { 481 mMobilemsppList.add(sipper); 482 } 483 } 484 485 if (!sipper.isAggregated) { 486 mUsageList.add(sipper); 487 } 488 } 489 } 490 } 491 492 @UnsupportedAppUsage getUsageList()493 public List<BatterySipper> getUsageList() { 494 return mUsageList; 495 } 496 getMobilemsppList()497 public List<BatterySipper> getMobilemsppList() { 498 return mMobilemsppList; 499 } 500 getStatsPeriod()501 public long getStatsPeriod() { 502 return mStatsPeriod; 503 } 504 getStatsType()505 public int getStatsType() { 506 return mStatsType; 507 } 508 509 @UnsupportedAppUsage getMaxPower()510 public double getMaxPower() { 511 return mMaxPower; 512 } 513 getMaxRealPower()514 public double getMaxRealPower() { 515 return mMaxRealPower; 516 } 517 518 @UnsupportedAppUsage getTotalPower()519 public double getTotalPower() { 520 return mTotalPower; 521 } 522 getComputedPower()523 public double getComputedPower() { 524 return mComputedPower; 525 } 526 getMinDrainedPower()527 public double getMinDrainedPower() { 528 return mMinDrainedPower; 529 } 530 getMaxDrainedPower()531 public double getMaxDrainedPower() { 532 return mMaxDrainedPower; 533 } 534 readFully(FileInputStream stream)535 public static byte[] readFully(FileInputStream stream) throws java.io.IOException { 536 return readFully(stream, stream.available()); 537 } 538 readFully(FileInputStream stream, int avail)539 public static byte[] readFully(FileInputStream stream, int avail) throws java.io.IOException { 540 int pos = 0; 541 byte[] data = new byte[avail]; 542 while (true) { 543 int amt = stream.read(data, pos, data.length - pos); 544 //Log.i("foo", "Read " + amt + " bytes at " + pos 545 // + " of avail " + data.length); 546 if (amt <= 0) { 547 //Log.i("foo", "**** FINISHED READING: pos=" + pos 548 // + " len=" + data.length); 549 return data; 550 } 551 pos += amt; 552 avail = stream.available(); 553 if (avail > data.length - pos) { 554 byte[] newData = new byte[pos + avail]; 555 System.arraycopy(data, 0, newData, 0, pos); 556 data = newData; 557 } 558 } 559 } 560 561 /** 562 * Mark the {@link BatterySipper} that we should hide. 563 * 564 * @param sippers sipper list that need to check and remove 565 * @return the total power of the hidden items of {@link BatterySipper} 566 * for proportional smearing 567 */ removeHiddenBatterySippers(List<BatterySipper> sippers)568 public double removeHiddenBatterySippers(List<BatterySipper> sippers) { 569 double proportionalSmearPowerMah = 0; 570 for (int i = sippers.size() - 1; i >= 0; i--) { 571 final BatterySipper sipper = sippers.get(i); 572 sipper.shouldHide = shouldHideSipper(sipper); 573 if (sipper.shouldHide) { 574 if (sipper.drainType != DrainType.OVERCOUNTED 575 && sipper.drainType != DrainType.SCREEN 576 && sipper.drainType != DrainType.AMBIENT_DISPLAY 577 && sipper.drainType != DrainType.UNACCOUNTED 578 && sipper.drainType != DrainType.BLUETOOTH 579 && sipper.drainType != DrainType.WIFI 580 && sipper.drainType != DrainType.IDLE) { 581 // Don't add it if it is overcounted, unaccounted or screen 582 proportionalSmearPowerMah += sipper.totalPowerMah; 583 } 584 } 585 } 586 return proportionalSmearPowerMah; 587 } 588 589 /** 590 * Check whether we should hide the battery sipper. 591 */ shouldHideSipper(BatterySipper sipper)592 public boolean shouldHideSipper(BatterySipper sipper) { 593 final DrainType drainType = sipper.drainType; 594 595 return drainType == DrainType.IDLE 596 || drainType == DrainType.CELL 597 || drainType == DrainType.SCREEN 598 || drainType == DrainType.AMBIENT_DISPLAY 599 || drainType == DrainType.UNACCOUNTED 600 || drainType == DrainType.OVERCOUNTED 601 || isTypeService(sipper) 602 || isTypeSystem(sipper); 603 } 604 605 /** 606 * Check whether {@code sipper} is type service 607 */ isTypeService(BatterySipper sipper)608 public boolean isTypeService(BatterySipper sipper) { 609 final String[] packages = mPackageManager.getPackagesForUid(sipper.getUid()); 610 if (packages == null) { 611 return false; 612 } 613 614 for (String packageName : packages) { 615 if (ArrayUtils.contains(mServicepackageArray, packageName)) { 616 return true; 617 } 618 } 619 620 return false; 621 } 622 623 /** 624 * Check whether {@code sipper} is type system 625 */ isTypeSystem(BatterySipper sipper)626 public boolean isTypeSystem(BatterySipper sipper) { 627 final int uid = sipper.uidObj == null ? -1 : sipper.getUid(); 628 sipper.mPackages = mPackageManager.getPackagesForUid(uid); 629 // Classify all the sippers to type system if the range of uid is 0...FIRST_APPLICATION_UID 630 if (uid >= Process.ROOT_UID && uid < Process.FIRST_APPLICATION_UID) { 631 return true; 632 } else if (sipper.mPackages != null) { 633 for (final String packageName : sipper.mPackages) { 634 if (ArrayUtils.contains(mSystemPackageArray, packageName)) { 635 return true; 636 } 637 } 638 } 639 640 return false; 641 } 642 convertUsToMs(long timeUs)643 public long convertUsToMs(long timeUs) { 644 return timeUs / 1000; 645 } 646 convertMsToUs(long timeMs)647 public long convertMsToUs(long timeMs) { 648 return timeMs * 1000; 649 } 650 651 @VisibleForTesting setPackageManager(PackageManager packageManager)652 public void setPackageManager(PackageManager packageManager) { 653 mPackageManager = packageManager; 654 } 655 656 @VisibleForTesting setSystemPackageArray(String[] array)657 public void setSystemPackageArray(String[] array) { 658 mSystemPackageArray = array; 659 } 660 661 @VisibleForTesting setServicePackageArray(String[] array)662 public void setServicePackageArray(String[] array) { 663 mServicepackageArray = array; 664 } 665 666 @UnsupportedAppUsage load()667 private void load() { 668 load(true); 669 } 670 load(boolean updateAll)671 private void load(boolean updateAll) { 672 if (mBatteryInfo == null) { 673 return; 674 } 675 mStats = getStats(mBatteryInfo, updateAll); 676 if (mCollectBatteryBroadcast) { 677 mBatteryBroadcast = mContext.registerReceiver(null, 678 new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); 679 } 680 } 681 getStats(IBatteryStats service, boolean updateAll)682 private static BatteryStatsImpl getStats(IBatteryStats service, boolean updateAll) { 683 try { 684 ParcelFileDescriptor pfd = service.getStatisticsStream(updateAll); 685 if (pfd != null) { 686 if (false) { 687 Log.d(TAG, "selinux context: " 688 + SELinux.getFileContext(pfd.getFileDescriptor())); 689 } 690 try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) { 691 byte[] data = readFully(fis, MemoryFile.getSize(pfd.getFileDescriptor())); 692 Parcel parcel = Parcel.obtain(); 693 parcel.unmarshall(data, 0, data.length); 694 parcel.setDataPosition(0); 695 BatteryStatsImpl stats = com.android.internal.os.BatteryStatsImpl.CREATOR 696 .createFromParcel(parcel); 697 return stats; 698 } catch (IOException e) { 699 Log.w(TAG, "Unable to read statistics stream", e); 700 } 701 } 702 } catch (RemoteException e) { 703 Log.w(TAG, "RemoteException:", e); 704 } 705 return new BatteryStatsImpl(); 706 } 707 } 708