1 /* 2 * Copyright (C) 2017 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 package com.android.settings.fuelgauge; 17 18 import android.app.AppOpsManager; 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.IntentFilter; 22 import android.content.pm.ApplicationInfo; 23 import android.content.pm.PackageInfo; 24 import android.content.pm.PackageManager; 25 import android.content.pm.ResolveInfo; 26 import android.os.BatteryConsumer; 27 import android.os.BatteryManager; 28 import android.os.BatteryStats; 29 import android.os.BatteryStatsManager; 30 import android.os.BatteryUsageStats; 31 import android.os.BatteryUsageStatsQuery; 32 import android.os.Build; 33 import android.os.Process; 34 import android.os.SystemClock; 35 import android.os.UidBatteryConsumer; 36 import android.os.UserHandle; 37 import android.provider.Settings; 38 import android.util.Log; 39 40 import androidx.annotation.IntDef; 41 import androidx.annotation.Nullable; 42 import androidx.annotation.VisibleForTesting; 43 import androidx.annotation.WorkerThread; 44 45 import com.android.internal.util.ArrayUtils; 46 import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper; 47 import com.android.settings.fuelgauge.batterytip.AnomalyInfo; 48 import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager; 49 import com.android.settings.fuelgauge.batterytip.StatsManagerConfig; 50 import com.android.settings.overlay.FeatureFactory; 51 import com.android.settingslib.applications.AppUtils; 52 import com.android.settingslib.fuelgauge.Estimate; 53 import com.android.settingslib.fuelgauge.EstimateKt; 54 import com.android.settingslib.fuelgauge.PowerAllowlistBackend; 55 import com.android.settingslib.utils.PowerUtil; 56 import com.android.settingslib.utils.ThreadUtils; 57 58 import java.lang.annotation.Retention; 59 import java.lang.annotation.RetentionPolicy; 60 import java.time.Duration; 61 import java.time.Instant; 62 import java.util.List; 63 64 /** 65 * Utils for battery operation 66 */ 67 public class BatteryUtils { 68 public static final int UID_NULL = -1; 69 public static final int SDK_NULL = -1; 70 /** Special UID value for data usage by removed apps. */ 71 public static final int UID_REMOVED_APPS = -4; 72 /** Special UID value for data usage by tethering. */ 73 public static final int UID_TETHERING = -5; 74 /** Special UID for aggregated other users. */ 75 public static final long UID_OTHER_USERS = Long.MIN_VALUE; 76 77 /** Flag to check if the dock defender mode has been temporarily bypassed */ 78 public static final String SETTINGS_GLOBAL_DOCK_DEFENDER_BYPASS = "dock_defender_bypass"; 79 80 public static final String BYPASS_DOCK_DEFENDER_ACTION = "battery.dock.defender.bypass"; 81 82 @Retention(RetentionPolicy.SOURCE) 83 @IntDef({StatusType.SCREEN_USAGE, 84 StatusType.FOREGROUND, 85 StatusType.BACKGROUND, 86 StatusType.ALL 87 }) 88 public @interface StatusType { 89 int SCREEN_USAGE = 0; 90 int FOREGROUND = 1; 91 int BACKGROUND = 2; 92 int ALL = 3; 93 } 94 95 @Retention(RetentionPolicy.SOURCE) 96 @IntDef({DockDefenderMode.FUTURE_BYPASS, 97 DockDefenderMode.ACTIVE, 98 DockDefenderMode.TEMPORARILY_BYPASSED, 99 DockDefenderMode.DISABLED}) 100 public @interface DockDefenderMode { 101 int FUTURE_BYPASS = 0; 102 int ACTIVE = 1; 103 int TEMPORARILY_BYPASSED = 2; 104 int DISABLED = 3; 105 } 106 107 private static final String TAG = "BatteryUtils"; 108 109 private static BatteryUtils sInstance; 110 private PackageManager mPackageManager; 111 112 private AppOpsManager mAppOpsManager; 113 private Context mContext; 114 @VisibleForTesting 115 PowerUsageFeatureProvider mPowerUsageFeatureProvider; 116 getInstance(Context context)117 public static BatteryUtils getInstance(Context context) { 118 if (sInstance == null || sInstance.isDataCorrupted()) { 119 sInstance = new BatteryUtils(context.getApplicationContext()); 120 } 121 return sInstance; 122 } 123 124 @VisibleForTesting BatteryUtils(Context context)125 public BatteryUtils(Context context) { 126 mContext = context; 127 mPackageManager = context.getPackageManager(); 128 mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 129 mPowerUsageFeatureProvider = FeatureFactory.getFactory(context) 130 .getPowerUsageFeatureProvider(context); 131 } 132 getProcessTimeMs(@tatusType int type, @Nullable BatteryStats.Uid uid, int which)133 public long getProcessTimeMs(@StatusType int type, @Nullable BatteryStats.Uid uid, 134 int which) { 135 if (uid == null) { 136 return 0; 137 } 138 139 switch (type) { 140 case StatusType.SCREEN_USAGE: 141 return getScreenUsageTimeMs(uid, which); 142 case StatusType.FOREGROUND: 143 return getProcessForegroundTimeMs(uid, which); 144 case StatusType.BACKGROUND: 145 return getProcessBackgroundTimeMs(uid, which); 146 case StatusType.ALL: 147 return getProcessForegroundTimeMs(uid, which) 148 + getProcessBackgroundTimeMs(uid, which); 149 } 150 return 0; 151 } 152 getScreenUsageTimeMs(BatteryStats.Uid uid, int which, long rawRealTimeUs)153 private long getScreenUsageTimeMs(BatteryStats.Uid uid, int which, long rawRealTimeUs) { 154 final int foregroundTypes[] = {BatteryStats.Uid.PROCESS_STATE_TOP}; 155 Log.v(TAG, "package: " + mPackageManager.getNameForUid(uid.getUid())); 156 157 long timeUs = 0; 158 for (int type : foregroundTypes) { 159 final long localTime = uid.getProcessStateTime(type, rawRealTimeUs, which); 160 Log.v(TAG, "type: " + type + " time(us): " + localTime); 161 timeUs += localTime; 162 } 163 Log.v(TAG, "foreground time(us): " + timeUs); 164 165 // Return the min value of STATE_TOP time and foreground activity time, since both of these 166 // time have some errors 167 return PowerUtil.convertUsToMs( 168 Math.min(timeUs, getForegroundActivityTotalTimeUs(uid, rawRealTimeUs))); 169 } 170 getScreenUsageTimeMs(BatteryStats.Uid uid, int which)171 private long getScreenUsageTimeMs(BatteryStats.Uid uid, int which) { 172 final long rawRealTimeUs = PowerUtil.convertMsToUs(SystemClock.elapsedRealtime()); 173 return getScreenUsageTimeMs(uid, which, rawRealTimeUs); 174 } 175 getProcessBackgroundTimeMs(BatteryStats.Uid uid, int which)176 private long getProcessBackgroundTimeMs(BatteryStats.Uid uid, int which) { 177 final long rawRealTimeUs = PowerUtil.convertMsToUs(SystemClock.elapsedRealtime()); 178 final long timeUs = uid.getProcessStateTime( 179 BatteryStats.Uid.PROCESS_STATE_BACKGROUND, rawRealTimeUs, which); 180 181 Log.v(TAG, "package: " + mPackageManager.getNameForUid(uid.getUid())); 182 Log.v(TAG, "background time(us): " + timeUs); 183 return PowerUtil.convertUsToMs(timeUs); 184 } 185 getProcessForegroundTimeMs(BatteryStats.Uid uid, int which)186 private long getProcessForegroundTimeMs(BatteryStats.Uid uid, int which) { 187 final long rawRealTimeUs = PowerUtil.convertMsToUs(SystemClock.elapsedRealtime()); 188 return getScreenUsageTimeMs(uid, which, rawRealTimeUs) 189 + PowerUtil.convertUsToMs(getForegroundServiceTotalTimeUs(uid, rawRealTimeUs)); 190 } 191 192 /** 193 * Returns true if the specified battery consumer should be excluded from the summary 194 * battery consumption list. 195 */ shouldHideUidBatteryConsumer(UidBatteryConsumer consumer)196 public boolean shouldHideUidBatteryConsumer(UidBatteryConsumer consumer) { 197 return shouldHideUidBatteryConsumer(consumer, 198 mPackageManager.getPackagesForUid(consumer.getUid())); 199 } 200 201 /** 202 * Returns true if the specified battery consumer should be excluded from the summary 203 * battery consumption list. 204 */ shouldHideUidBatteryConsumer(UidBatteryConsumer consumer, String[] packages)205 public boolean shouldHideUidBatteryConsumer(UidBatteryConsumer consumer, String[] packages) { 206 return mPowerUsageFeatureProvider.isTypeSystem(consumer.getUid(), packages) 207 || shouldHideUidBatteryConsumerUnconditionally(consumer, packages); 208 } 209 210 /** 211 * Returns true if the specified battery consumer should be excluded from 212 * battery consumption lists, either short or full. 213 */ shouldHideUidBatteryConsumerUnconditionally(UidBatteryConsumer consumer, String[] packages)214 public boolean shouldHideUidBatteryConsumerUnconditionally(UidBatteryConsumer consumer, 215 String[] packages) { 216 final int uid = consumer.getUid(); 217 return uid == UID_TETHERING 218 ? false 219 : uid < 0 || isHiddenSystemModule(packages); 220 } 221 222 /** 223 * Returns true if the specified device power component should be excluded from the summary 224 * battery consumption list. 225 */ shouldHideDevicePowerComponent(BatteryConsumer consumer, @BatteryConsumer.PowerComponent int powerComponentId)226 public boolean shouldHideDevicePowerComponent(BatteryConsumer consumer, 227 @BatteryConsumer.PowerComponent int powerComponentId) { 228 switch (powerComponentId) { 229 case BatteryConsumer.POWER_COMPONENT_IDLE: 230 case BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO: 231 case BatteryConsumer.POWER_COMPONENT_SCREEN: 232 case BatteryConsumer.POWER_COMPONENT_BLUETOOTH: 233 case BatteryConsumer.POWER_COMPONENT_WIFI: 234 return true; 235 default: 236 return false; 237 } 238 } 239 240 /** 241 * Returns true if one the specified packages belongs to a hidden system module. 242 */ isHiddenSystemModule(String[] packages)243 public boolean isHiddenSystemModule(String[] packages) { 244 if (packages != null) { 245 for (int i = 0, length = packages.length; i < length; i++) { 246 if (AppUtils.isHiddenSystemModule(mContext, packages[i])) { 247 return true; 248 } 249 } 250 } 251 return false; 252 } 253 254 /** 255 * Calculate the power usage percentage for an app 256 * 257 * @param powerUsageMah power used by the app 258 * @param totalPowerMah total power used in the system 259 * @param dischargeAmount The discharge amount calculated by {@link BatteryStats} 260 * @return A percentage value scaled by {@paramref dischargeAmount} 261 * @see BatteryStats#getDischargeAmount(int) 262 */ calculateBatteryPercent(double powerUsageMah, double totalPowerMah, int dischargeAmount)263 public double calculateBatteryPercent(double powerUsageMah, double totalPowerMah, 264 int dischargeAmount) { 265 if (totalPowerMah == 0) { 266 return 0; 267 } 268 269 return (powerUsageMah / totalPowerMah) * dischargeAmount; 270 } 271 272 /** 273 * Find the package name for a {@link android.os.BatteryStats.Uid} 274 * 275 * @param uid id to get the package name 276 * @return the package name. If there are multiple packages related to 277 * given id, return the first one. Or return null if there are no known 278 * packages with the given id 279 * @see PackageManager#getPackagesForUid(int) 280 */ getPackageName(int uid)281 public String getPackageName(int uid) { 282 final String[] packageNames = mPackageManager.getPackagesForUid(uid); 283 284 return ArrayUtils.isEmpty(packageNames) ? null : packageNames[0]; 285 } 286 287 /** 288 * Find the targetSdkVersion for package with name {@code packageName} 289 * 290 * @return the targetSdkVersion, or {@link #SDK_NULL} if {@code packageName} doesn't exist 291 */ getTargetSdkVersion(final String packageName)292 public int getTargetSdkVersion(final String packageName) { 293 try { 294 ApplicationInfo info = mPackageManager.getApplicationInfo(packageName, 295 PackageManager.GET_META_DATA); 296 297 return info.targetSdkVersion; 298 } catch (PackageManager.NameNotFoundException e) { 299 Log.e(TAG, "Cannot find package: " + packageName, e); 300 } 301 302 return SDK_NULL; 303 } 304 305 /** 306 * Check whether background restriction is enabled 307 */ isBackgroundRestrictionEnabled(final int targetSdkVersion, final int uid, final String packageName)308 public boolean isBackgroundRestrictionEnabled(final int targetSdkVersion, final int uid, 309 final String packageName) { 310 if (targetSdkVersion >= Build.VERSION_CODES.O) { 311 return true; 312 } 313 final int mode = mAppOpsManager 314 .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, packageName); 315 return mode == AppOpsManager.MODE_IGNORED || mode == AppOpsManager.MODE_ERRORED; 316 } 317 318 /** 319 * Calculate the time since last full charge, including the device off time 320 * 321 * @param batteryUsageStats class that contains the data 322 * @param currentTimeMs current wall time 323 * @return time in millis 324 */ calculateLastFullChargeTime(BatteryUsageStats batteryUsageStats, long currentTimeMs)325 public long calculateLastFullChargeTime(BatteryUsageStats batteryUsageStats, 326 long currentTimeMs) { 327 return currentTimeMs - batteryUsageStats.getStatsStartTimestamp(); 328 } 329 logRuntime(String tag, String message, long startTime)330 public static void logRuntime(String tag, String message, long startTime) { 331 Log.d(tag, message + ": " + (System.currentTimeMillis() - startTime) + "ms"); 332 } 333 334 /** 335 * Return {@code true} if battery is overheated and charging. 336 */ isBatteryDefenderOn(BatteryInfo batteryInfo)337 public static boolean isBatteryDefenderOn(BatteryInfo batteryInfo) { 338 return batteryInfo.isOverheated && !batteryInfo.discharging; 339 } 340 341 /** 342 * Find package uid from package name 343 * 344 * @param packageName used to find the uid 345 * @return uid for packageName, or {@link #UID_NULL} if exception happens or 346 * {@code packageName} is null 347 */ getPackageUid(String packageName)348 public int getPackageUid(String packageName) { 349 try { 350 return packageName == null ? UID_NULL : mPackageManager.getPackageUid(packageName, 351 PackageManager.GET_META_DATA); 352 } catch (PackageManager.NameNotFoundException e) { 353 return UID_NULL; 354 } 355 } 356 setForceAppStandby(int uid, String packageName, int mode)357 public void setForceAppStandby(int uid, String packageName, 358 int mode) { 359 final boolean isPreOApp = isPreOApp(packageName); 360 if (isPreOApp) { 361 // Control whether app could run in the background if it is pre O app 362 mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, packageName, mode); 363 } 364 // Control whether app could run jobs in the background 365 mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName, mode); 366 367 ThreadUtils.postOnBackgroundThread(() -> { 368 final BatteryDatabaseManager batteryDatabaseManager = BatteryDatabaseManager 369 .getInstance(mContext); 370 if (mode == AppOpsManager.MODE_IGNORED) { 371 batteryDatabaseManager.insertAction(AnomalyDatabaseHelper.ActionType.RESTRICTION, 372 uid, packageName, System.currentTimeMillis()); 373 } else if (mode == AppOpsManager.MODE_ALLOWED) { 374 batteryDatabaseManager.deleteAction(AnomalyDatabaseHelper.ActionType.RESTRICTION, 375 uid, packageName); 376 } 377 }); 378 } 379 isForceAppStandbyEnabled(int uid, String packageName)380 public boolean isForceAppStandbyEnabled(int uid, String packageName) { 381 return mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, 382 packageName) == AppOpsManager.MODE_IGNORED; 383 } 384 clearForceAppStandby(String packageName)385 public boolean clearForceAppStandby(String packageName) { 386 final int uid = getPackageUid(packageName); 387 if (uid != UID_NULL && isForceAppStandbyEnabled(uid, packageName)) { 388 setForceAppStandby(uid, packageName, AppOpsManager.MODE_ALLOWED); 389 return true; 390 } else { 391 return false; 392 } 393 } 394 395 @WorkerThread getBatteryInfo(final String tag)396 public BatteryInfo getBatteryInfo(final String tag) { 397 final BatteryStatsManager systemService = mContext.getSystemService( 398 BatteryStatsManager.class); 399 BatteryUsageStats batteryUsageStats; 400 try { 401 batteryUsageStats = systemService.getBatteryUsageStats( 402 new BatteryUsageStatsQuery.Builder().includeBatteryHistory().build()); 403 } catch (RuntimeException e) { 404 Log.e(TAG, "getBatteryInfo() error from getBatteryUsageStats()", e); 405 // Use default BatteryUsageStats. 406 batteryUsageStats = new BatteryUsageStats.Builder(new String[0]).build(); 407 } 408 409 final long startTime = System.currentTimeMillis(); 410 411 // Stuff we always need to get BatteryInfo 412 final Intent batteryBroadcast = mContext.registerReceiver(null, 413 new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); 414 415 final long elapsedRealtimeUs = PowerUtil.convertMsToUs( 416 SystemClock.elapsedRealtime()); 417 418 BatteryInfo batteryInfo; 419 Estimate estimate = getEnhancedEstimate(); 420 421 // couldn't get estimate from cache or provider, use fallback 422 if (estimate == null) { 423 estimate = new Estimate( 424 batteryUsageStats.getBatteryTimeRemainingMs(), 425 false /* isBasedOnUsage */, 426 EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN); 427 } 428 429 BatteryUtils.logRuntime(tag, "BatteryInfoLoader post query", startTime); 430 batteryInfo = BatteryInfo.getBatteryInfo(mContext, batteryBroadcast, 431 batteryUsageStats, estimate, elapsedRealtimeUs, false /* shortString */); 432 BatteryUtils.logRuntime(tag, "BatteryInfoLoader.loadInBackground", startTime); 433 434 try { 435 batteryUsageStats.close(); 436 } catch (Exception e) { 437 Log.e(TAG, "BatteryUsageStats.close() failed", e); 438 } 439 return batteryInfo; 440 } 441 442 @VisibleForTesting getEnhancedEstimate()443 Estimate getEnhancedEstimate() { 444 Estimate estimate = null; 445 // Get enhanced prediction if available 446 if (Duration.between(Estimate.getLastCacheUpdateTime(mContext), Instant.now()) 447 .compareTo(Duration.ofSeconds(10)) < 0) { 448 estimate = Estimate.getCachedEstimateIfAvailable(mContext); 449 } else if (mPowerUsageFeatureProvider != null && 450 mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(mContext)) { 451 estimate = mPowerUsageFeatureProvider.getEnhancedBatteryPrediction(mContext); 452 if (estimate != null) { 453 Estimate.storeCachedEstimate(mContext, estimate); 454 } 455 } 456 return estimate; 457 } 458 isDataCorrupted()459 private boolean isDataCorrupted() { 460 return mPackageManager == null || mAppOpsManager == null; 461 } 462 463 @VisibleForTesting getForegroundActivityTotalTimeUs(BatteryStats.Uid uid, long rawRealtimeUs)464 long getForegroundActivityTotalTimeUs(BatteryStats.Uid uid, long rawRealtimeUs) { 465 final BatteryStats.Timer timer = uid.getForegroundActivityTimer(); 466 if (timer != null) { 467 return timer.getTotalTimeLocked(rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED); 468 } 469 470 return 0; 471 } 472 473 @VisibleForTesting getForegroundServiceTotalTimeUs(BatteryStats.Uid uid, long rawRealtimeUs)474 long getForegroundServiceTotalTimeUs(BatteryStats.Uid uid, long rawRealtimeUs) { 475 final BatteryStats.Timer timer = uid.getForegroundServiceTimer(); 476 if (timer != null) { 477 return timer.getTotalTimeLocked(rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED); 478 } 479 480 return 0; 481 } 482 isPreOApp(final String packageName)483 public boolean isPreOApp(final String packageName) { 484 try { 485 ApplicationInfo info = mPackageManager.getApplicationInfo(packageName, 486 PackageManager.GET_META_DATA); 487 488 return info.targetSdkVersion < Build.VERSION_CODES.O; 489 } catch (PackageManager.NameNotFoundException e) { 490 Log.e(TAG, "Cannot find package: " + packageName, e); 491 } 492 493 return false; 494 } 495 isPreOApp(final String[] packageNames)496 public boolean isPreOApp(final String[] packageNames) { 497 if (ArrayUtils.isEmpty(packageNames)) { 498 return false; 499 } 500 501 for (String packageName : packageNames) { 502 if (isPreOApp(packageName)) { 503 return true; 504 } 505 } 506 507 return false; 508 } 509 510 /** 511 * Return {@code true} if we should hide anomaly app represented by {@code uid} 512 */ shouldHideAnomaly(PowerAllowlistBackend powerAllowlistBackend, int uid, AnomalyInfo anomalyInfo)513 public boolean shouldHideAnomaly(PowerAllowlistBackend powerAllowlistBackend, int uid, 514 AnomalyInfo anomalyInfo) { 515 final String[] packageNames = mPackageManager.getPackagesForUid(uid); 516 if (ArrayUtils.isEmpty(packageNames)) { 517 // Don't show it if app has been uninstalled 518 return true; 519 } 520 521 return isSystemUid(uid) || powerAllowlistBackend.isAllowlisted(packageNames) 522 || (isSystemApp(mPackageManager, packageNames) && !hasLauncherEntry(packageNames)) 523 || (isExcessiveBackgroundAnomaly(anomalyInfo) && !isPreOApp(packageNames)); 524 } 525 isExcessiveBackgroundAnomaly(AnomalyInfo anomalyInfo)526 private boolean isExcessiveBackgroundAnomaly(AnomalyInfo anomalyInfo) { 527 return anomalyInfo.anomalyType 528 == StatsManagerConfig.AnomalyType.EXCESSIVE_BACKGROUND_SERVICE; 529 } 530 isSystemUid(int uid)531 private boolean isSystemUid(int uid) { 532 final int appUid = UserHandle.getAppId(uid); 533 return appUid >= Process.ROOT_UID && appUid < Process.FIRST_APPLICATION_UID; 534 } 535 isSystemApp(PackageManager packageManager, String[] packageNames)536 private boolean isSystemApp(PackageManager packageManager, String[] packageNames) { 537 for (String packageName : packageNames) { 538 try { 539 final ApplicationInfo info = packageManager.getApplicationInfo(packageName, 540 0 /* flags */); 541 if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { 542 return true; 543 } 544 } catch (PackageManager.NameNotFoundException e) { 545 Log.e(TAG, "Package not found: " + packageName, e); 546 } 547 } 548 549 return false; 550 } 551 hasLauncherEntry(String[] packageNames)552 private boolean hasLauncherEntry(String[] packageNames) { 553 final Intent launchIntent = new Intent(Intent.ACTION_MAIN, null); 554 launchIntent.addCategory(Intent.CATEGORY_LAUNCHER); 555 556 // If we do not specify MATCH_DIRECT_BOOT_AWARE or 557 // MATCH_DIRECT_BOOT_UNAWARE, system will derive and update the flags 558 // according to the user's lock state. When the user is locked, 559 // components 560 // with ComponentInfo#directBootAware == false will be filtered. We should 561 // explicitly include both direct boot aware and unaware components here. 562 final List<ResolveInfo> resolveInfos = mPackageManager.queryIntentActivities(launchIntent, 563 PackageManager.MATCH_DISABLED_COMPONENTS 564 | PackageManager.MATCH_DIRECT_BOOT_AWARE 565 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE 566 | PackageManager.MATCH_SYSTEM_ONLY); 567 for (int i = 0, size = resolveInfos.size(); i < size; i++) { 568 final ResolveInfo resolveInfo = resolveInfos.get(i); 569 if (ArrayUtils.contains(packageNames, resolveInfo.activityInfo.packageName)) { 570 return true; 571 } 572 } 573 574 return false; 575 } 576 577 /** 578 * Return version number of an app represented by {@code packageName}, and return -1 if not 579 * found. 580 */ getAppLongVersionCode(String packageName)581 public long getAppLongVersionCode(String packageName) { 582 try { 583 final PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, 584 0 /* flags */); 585 return packageInfo.getLongVersionCode(); 586 } catch (PackageManager.NameNotFoundException e) { 587 Log.e(TAG, "Cannot find package: " + packageName, e); 588 } 589 590 return -1L; 591 } 592 593 /** Gets the current dock defender mode */ getCurrentDockDefenderMode(Context context, BatteryInfo batteryInfo)594 public static int getCurrentDockDefenderMode(Context context, BatteryInfo batteryInfo) { 595 if (batteryInfo.pluggedStatus == BatteryManager.BATTERY_PLUGGED_DOCK) { 596 if (Settings.Global.getInt(context.getContentResolver(), 597 SETTINGS_GLOBAL_DOCK_DEFENDER_BYPASS, 0) == 1) { 598 return DockDefenderMode.TEMPORARILY_BYPASSED; 599 } else if (batteryInfo.isOverheated && FeatureFactory.getFactory(context) 600 .getPowerUsageFeatureProvider(context) 601 .isExtraDefend()) { 602 return DockDefenderMode.ACTIVE; 603 } else if (!batteryInfo.isOverheated) { 604 return DockDefenderMode.FUTURE_BYPASS; 605 } 606 } 607 return DockDefenderMode.DISABLED; 608 } 609 } 610