diff --git a/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java b/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java index 40756a0a5c3..3e1a951d72f 100644 --- a/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java @@ -132,7 +132,7 @@ public class AppBatteryPreferenceController extends BasePreferenceController if (isBatteryStatsAvailable()) { final UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - final BatteryEntry entry = new BatteryEntry(mContext, /* handler */null, userManager, + final BatteryEntry entry = new BatteryEntry(mContext, userManager, mUidBatteryConsumer, /* isHidden */ false, mUidBatteryConsumer.getUid(), /* packages */ null, mPackageName); Log.i(TAG, "Battery consumer available, launch : " diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java index a6c48a48d6b..86259d5c170 100644 --- a/src/com/android/settings/fuelgauge/BatteryUtils.java +++ b/src/com/android/settings/fuelgauge/BatteryUtils.java @@ -23,7 +23,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryStatsManager; import android.os.BatteryUsageStats; @@ -200,24 +199,6 @@ public class BatteryUtils { : uid < 0 || isHiddenSystemModule(packages); } - /** - * Returns true if the specified device power component should be excluded from the summary - * battery consumption list. - */ - public boolean shouldHideDevicePowerComponent(BatteryConsumer consumer, - @BatteryConsumer.PowerComponent int powerComponentId) { - switch (powerComponentId) { - case BatteryConsumer.POWER_COMPONENT_IDLE: - case BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO: - case BatteryConsumer.POWER_COMPONENT_SCREEN: - case BatteryConsumer.POWER_COMPONENT_BLUETOOTH: - case BatteryConsumer.POWER_COMPONENT_WIFI: - return true; - default: - return false; - } - } - /** * Returns true if one the specified packages belongs to a hidden system module. */ diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryAppListPreferenceController.java deleted file mode 100644 index 92b27e8c9ec..00000000000 --- a/src/com/android/settings/fuelgauge/batteryusage/BatteryAppListPreferenceController.java +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.fuelgauge.batteryusage; - -import android.app.Activity; -import android.content.Context; -import android.content.pm.PackageManager; -import android.graphics.drawable.Drawable; -import android.os.AggregateBatteryConsumer; -import android.os.BatteryConsumer; -import android.os.BatteryUsageStats; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.Process; -import android.os.UidBatteryConsumer; -import android.os.UserBatteryConsumer; -import android.os.UserHandle; -import android.os.UserManager; -import android.text.TextUtils; -import android.text.format.DateUtils; -import android.util.ArrayMap; -import android.util.Log; -import android.util.SparseArray; - -import androidx.annotation.VisibleForTesting; -import androidx.preference.Preference; -import androidx.preference.PreferenceGroup; -import androidx.preference.PreferenceScreen; - -import com.android.internal.os.PowerProfile; -import com.android.settings.R; -import com.android.settings.SettingsActivity; -import com.android.settings.core.InstrumentedPreferenceFragment; -import com.android.settings.core.PreferenceControllerMixin; -import com.android.settings.fuelgauge.AdvancedPowerUsageDetail; -import com.android.settings.fuelgauge.BatteryUtils; -import com.android.settingslib.core.AbstractPreferenceController; -import com.android.settingslib.core.lifecycle.Lifecycle; -import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnDestroy; -import com.android.settingslib.core.lifecycle.events.OnPause; -import com.android.settingslib.utils.StringUtil; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; - -/** - * Controller that update the battery header view - */ -public class BatteryAppListPreferenceController extends AbstractPreferenceController - implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy { - private static final String TAG = "BatteryAppListPreferenceController"; - @VisibleForTesting - static final boolean USE_FAKE_DATA = false; - private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 20; - private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10; - private static final String MEDIASERVER_PACKAGE_NAME = "mediaserver"; - private static final String NOT_AVAILABLE = "not_available"; - - @VisibleForTesting - PreferenceGroup mAppListGroup; - private BatteryUsageStats mBatteryUsageStats; - private ArrayMap mPreferenceCache; - @VisibleForTesting - BatteryUtils mBatteryUtils; - private final UserManager mUserManager; - private final PackageManager mPackageManager; - private final SettingsActivity mActivity; - private final InstrumentedPreferenceFragment mFragment; - private final String mPreferenceKey; - - private Context mPrefContext; - - /** - * Battery attribution list configuration. - */ - public interface Config { - /** - * Returns true if the attribution list should be shown. - */ - boolean shouldShowBatteryAttributionList(Context context); - } - - @VisibleForTesting - static Config sConfig = new Config() { - @Override - public boolean shouldShowBatteryAttributionList(Context context) { - if (USE_FAKE_DATA) { - return true; - } - - PowerProfile powerProfile = new PowerProfile(context); - // Cheap hack to try to figure out if the power_profile.xml was populated. - final double averagePowerForOrdinal = powerProfile.getAveragePowerForOrdinal( - PowerProfile.POWER_GROUP_DISPLAY_SCREEN_FULL, 0); - final boolean shouldShowBatteryAttributionList = - averagePowerForOrdinal >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP; - if (!shouldShowBatteryAttributionList) { - Log.w(TAG, "shouldShowBatteryAttributionList(): " + averagePowerForOrdinal); - } - return shouldShowBatteryAttributionList; - } - }; - - private final Handler mHandler = new Handler(Looper.getMainLooper()) { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case BatteryEntry.MSG_UPDATE_NAME_ICON: - BatteryEntry entry = (BatteryEntry) msg.obj; - PowerGaugePreference pgp = mAppListGroup.findPreference(entry.getKey()); - if (pgp != null) { - final int userId = UserHandle.getUserId(entry.getUid()); - final UserHandle userHandle = new UserHandle(userId); - pgp.setIcon(mUserManager.getBadgedIconForUser(entry.getIcon(), userHandle)); - pgp.setTitle(entry.mName); - if (entry.isAppEntry()) { - pgp.setContentDescription(entry.mName); - } - } - break; - case BatteryEntry.MSG_REPORT_FULLY_DRAWN: - Activity activity = mActivity; - if (activity != null) { - activity.reportFullyDrawn(); - } - break; - } - super.handleMessage(msg); - } - }; - - public BatteryAppListPreferenceController(Context context, String preferenceKey, - Lifecycle lifecycle, SettingsActivity activity, - InstrumentedPreferenceFragment fragment) { - super(context); - - if (lifecycle != null) { - lifecycle.addObserver(this); - } - - mPreferenceKey = preferenceKey; - mBatteryUtils = BatteryUtils.getInstance(context); - mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - mPackageManager = context.getPackageManager(); - mActivity = activity; - mFragment = fragment; - } - - @Override - public void onPause() { - BatteryEntry.stopRequestQueue(); - mHandler.removeMessages(BatteryEntry.MSG_UPDATE_NAME_ICON); - } - - @Override - public void onDestroy() { - if (mActivity.isChangingConfigurations()) { - BatteryEntry.clearUidCache(); - } - } - - @Override - public void displayPreference(PreferenceScreen screen) { - super.displayPreference(screen); - mPrefContext = screen.getContext(); - mAppListGroup = screen.findPreference(mPreferenceKey); - mAppListGroup.setTitle(mPrefContext.getString(R.string.power_usage_list_summary)); - } - - @Override - public boolean isAvailable() { - return true; - } - - @Override - public String getPreferenceKey() { - return mPreferenceKey; - } - - @Override - public boolean handlePreferenceTreeClick(Preference preference) { - if (preference instanceof PowerGaugePreference) { - PowerGaugePreference pgp = (PowerGaugePreference) preference; - BatteryEntry entry = pgp.getInfo(); - AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, - mFragment, entry, pgp.getPercent(), /*isValidToShowSummary=*/ true); - return true; - } - return false; - } - - /** - * Refreshes the list of battery consumers using the supplied BatteryUsageStats. - */ - public void refreshAppListGroup(BatteryUsageStats batteryUsageStats, boolean showAllApps) { - if (!isAvailable()) { - return; - } - - mBatteryUsageStats = USE_FAKE_DATA ? getFakeStats() : batteryUsageStats; - mAppListGroup.setTitle(R.string.power_usage_list_summary); - - boolean addedSome = false; - - cacheRemoveAllPrefs(mAppListGroup); - mAppListGroup.setOrderingAsAdded(false); - - if (sConfig.shouldShowBatteryAttributionList(mContext)) { - final int dischargePercentage = getDischargePercentage(batteryUsageStats); - final List usageList = - getCoalescedUsageList(showAllApps, /*loadDataInBackground=*/ true); - final double totalPower = batteryUsageStats.getConsumedPower(); - final int numSippers = usageList.size(); - for (int i = 0; i < numSippers; i++) { - final BatteryEntry entry = usageList.get(i); - - final double percentOfTotal = mBatteryUtils.calculateBatteryPercent( - entry.getConsumedPower(), totalPower, dischargePercentage); - - if (((int) (percentOfTotal + .5)) < 1) { - continue; - } - - final int uid = entry.getUid(); - final UserHandle userHandle = new UserHandle(UserHandle.getUserId(uid)); - final Drawable badgedIcon = mUserManager.getBadgedIconForUser(entry.getIcon(), - userHandle); - final CharSequence contentDescription = mUserManager.getBadgedLabelForUser( - entry.getLabel(), userHandle); - - final String key = entry.getKey(); - PowerGaugePreference pref = (PowerGaugePreference) getCachedPreference(key); - if (pref == null) { - pref = new PowerGaugePreference(mPrefContext, badgedIcon, - contentDescription, entry); - pref.setKey(key); - } - entry.mPercent = percentOfTotal; - pref.setTitle(entry.getLabel()); - pref.setOrder(i + 1); - pref.setPercent(percentOfTotal); - pref.shouldShowAnomalyIcon(false); - pref.setEnabled(uid != BatteryUtils.UID_TETHERING - && uid != BatteryUtils.UID_REMOVED_APPS); - setUsageSummary(pref, entry); - addedSome = true; - mAppListGroup.addPreference(pref); - if (mAppListGroup.getPreferenceCount() - getCachedCount() - > (MAX_ITEMS_TO_LIST + 1)) { - break; - } - } - } - if (!addedSome) { - addNotAvailableMessage(); - } - removeCachedPrefs(mAppListGroup); - - BatteryEntry.startRequestQueue(); - } - - /** - * Gets the BatteryEntry list by using the supplied BatteryUsageStats. - */ - public List getBatteryEntryList( - BatteryUsageStats batteryUsageStats, boolean showAllApps) { - mBatteryUsageStats = USE_FAKE_DATA ? getFakeStats() : batteryUsageStats; - if (!sConfig.shouldShowBatteryAttributionList(mContext)) { - return null; - } - final int dischargePercentage = getDischargePercentage(batteryUsageStats); - final List usageList = - getCoalescedUsageList(showAllApps, /*loadDataInBackground=*/ false); - final double totalPower = batteryUsageStats.getConsumedPower(); - for (int i = 0; i < usageList.size(); i++) { - final BatteryEntry entry = usageList.get(i); - final double percentOfTotal = mBatteryUtils.calculateBatteryPercent( - entry.getConsumedPower(), totalPower, dischargePercentage); - entry.mPercent = percentOfTotal; - } - return usageList; - } - - private int getDischargePercentage(BatteryUsageStats batteryUsageStats) { - int dischargePercentage = batteryUsageStats.getDischargePercentage(); - if (dischargePercentage < 0) { - dischargePercentage = 0; - } - return dischargePercentage; - } - - /** - * We want to coalesce some UIDs. For example, dex2oat runs under a shared gid that - * exists for all users of the same app. We detect this case and merge the power use - * for dex2oat to the device OWNER's use of the app. - * - * @return A sorted list of apps using power. - */ - private List getCoalescedUsageList( - boolean showAllApps, boolean loadDataInBackground) { - final SparseArray batteryEntryList = new SparseArray<>(); - - final ArrayList results = new ArrayList<>(); - final List uidBatteryConsumers = - mBatteryUsageStats.getUidBatteryConsumers(); - - // Sort to have all apps with "real" UIDs first, followed by apps that are supposed - // to be combined with the real ones. - uidBatteryConsumers.sort(Comparator.comparingInt( - consumer -> consumer.getUid() == getRealUid(consumer) ? 0 : 1)); - - for (int i = 0, size = uidBatteryConsumers.size(); i < size; i++) { - final UidBatteryConsumer consumer = uidBatteryConsumers.get(i); - final int uid = getRealUid(consumer); - - final String[] packages = mPackageManager.getPackagesForUid(uid); - if (mBatteryUtils.shouldHideUidBatteryConsumerUnconditionally(consumer, packages)) { - continue; - } - - final boolean isHidden = mBatteryUtils.shouldHideUidBatteryConsumer(consumer, packages); - if (isHidden && !showAllApps) { - continue; - } - - final int index = batteryEntryList.indexOfKey(uid); - if (index < 0) { - // New entry. - batteryEntryList.put(uid, new BatteryEntry(mContext, mHandler, mUserManager, - consumer, isHidden, uid, packages, null, loadDataInBackground)); - } else { - // Combine BatterySippers if we already have one with this UID. - final BatteryEntry existingSipper = batteryEntryList.valueAt(index); - existingSipper.add(consumer); - } - } - - final BatteryConsumer deviceConsumer = mBatteryUsageStats.getAggregateBatteryConsumer( - BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE); - final BatteryConsumer appsConsumer = mBatteryUsageStats.getAggregateBatteryConsumer( - BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS); - - for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT; - componentId++) { - if (!showAllApps - && mBatteryUtils.shouldHideDevicePowerComponent(deviceConsumer, componentId)) { - continue; - } - - results.add(new BatteryEntry(mContext, componentId, - deviceConsumer.getConsumedPower(componentId), - appsConsumer.getConsumedPower(componentId), - deviceConsumer.getUsageDurationMillis(componentId))); - } - - for (int componentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID; - componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID - + deviceConsumer.getCustomPowerComponentCount(); - componentId++) { - if (!showAllApps) { - continue; - } - - results.add(new BatteryEntry(mContext, componentId, - deviceConsumer.getCustomPowerComponentName(componentId), - deviceConsumer.getConsumedPowerForCustomComponent(componentId), - appsConsumer.getConsumedPowerForCustomComponent(componentId))); - } - - if (showAllApps) { - final List userBatteryConsumers = - mBatteryUsageStats.getUserBatteryConsumers(); - for (int i = 0, size = userBatteryConsumers.size(); i < size; i++) { - final UserBatteryConsumer consumer = userBatteryConsumers.get(i); - results.add(new BatteryEntry(mContext, mHandler, mUserManager, - consumer, /* isHidden */ true, Process.INVALID_UID, null, null, - loadDataInBackground)); - } - } - - final int numUidSippers = batteryEntryList.size(); - - for (int i = 0; i < numUidSippers; i++) { - results.add(batteryEntryList.valueAt(i)); - } - - // The sort order must have changed, so re-sort based on total power use. - results.sort(BatteryEntry.COMPARATOR); - return results; - } - - private int getRealUid(UidBatteryConsumer consumer) { - int realUid = consumer.getUid(); - - // Check if this UID is a shared GID. If so, we combine it with the OWNER's - // actual app UID. - if (isSharedGid(consumer.getUid())) { - realUid = UserHandle.getUid(UserHandle.USER_SYSTEM, - UserHandle.getAppIdFromSharedAppGid(consumer.getUid())); - } - - // Check if this UID is a system UID (mediaserver, logd, nfc, drm, etc). - if (isSystemUid(realUid) - && !MEDIASERVER_PACKAGE_NAME.equals(consumer.getPackageWithHighestDrain())) { - // Use the system UID for all UIDs running in their own sandbox that - // are not apps. We exclude mediaserver because we already are expected to - // report that as a separate item. - realUid = Process.SYSTEM_UID; - } - return realUid; - } - - @VisibleForTesting - void setUsageSummary(Preference preference, BatteryEntry entry) { - if (BatteryEntry.isSystemUid(entry.getUid())) { - return; - } - // Only show summary when usage time is longer than one minute - final long usageTimeMs = entry.getTimeInForegroundMs(); - if (usageTimeMs >= DateUtils.MINUTE_IN_MILLIS) { - final CharSequence timeSequence = - StringUtil.formatElapsedTime(mContext, usageTimeMs, false, false); - preference.setSummary( - entry.isHidden() - ? timeSequence - : TextUtils.expandTemplate(mContext.getText(R.string.battery_used_for), - timeSequence)); - } - } - - private void cacheRemoveAllPrefs(PreferenceGroup group) { - mPreferenceCache = new ArrayMap<>(); - final int n = group.getPreferenceCount(); - for (int i = 0; i < n; i++) { - Preference p = group.getPreference(i); - if (TextUtils.isEmpty(p.getKey())) { - continue; - } - mPreferenceCache.put(p.getKey(), p); - } - } - - private static boolean isSharedGid(int uid) { - return UserHandle.getAppIdFromSharedAppGid(uid) > 0; - } - - private static boolean isSystemUid(int uid) { - final int appUid = UserHandle.getAppId(uid); - return appUid >= Process.SYSTEM_UID && appUid < Process.FIRST_APPLICATION_UID; - } - - private BatteryUsageStats getFakeStats() { - BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(new String[0]) - .setDischargePercentage(100); - - float use = 500; - final AggregateBatteryConsumer.Builder appsBatteryConsumerBuilder = - builder.getAggregateBatteryConsumerBuilder( - BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS); - final AggregateBatteryConsumer.Builder deviceBatteryConsumerBuilder = - builder.getAggregateBatteryConsumerBuilder( - BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE); - for (@BatteryConsumer.PowerComponent int componentId : new int[]{ - BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY, - BatteryConsumer.POWER_COMPONENT_BLUETOOTH, - BatteryConsumer.POWER_COMPONENT_CAMERA, - BatteryConsumer.POWER_COMPONENT_FLASHLIGHT, - BatteryConsumer.POWER_COMPONENT_IDLE, - BatteryConsumer.POWER_COMPONENT_MEMORY, - BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, - BatteryConsumer.POWER_COMPONENT_PHONE, - BatteryConsumer.POWER_COMPONENT_SCREEN, - BatteryConsumer.POWER_COMPONENT_WIFI, - }) { - appsBatteryConsumerBuilder.setConsumedPower(componentId, use); - deviceBatteryConsumerBuilder.setConsumedPower(componentId, use * 2); - use += 5; - } - - use = 450; - for (int i = 0; i < 100; i++) { - builder.getOrCreateUidBatteryConsumerBuilder(Process.FIRST_APPLICATION_UID + i) - .setTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND, 10000 + i * 1000) - .setTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND, 20000 + i * 2000) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, use); - use += 1; - } - - // Simulate dex2oat process. - builder.getOrCreateUidBatteryConsumerBuilder(Process.FIRST_APPLICATION_UID) - .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CPU, 100000) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 1000.0) - .setPackageWithHighestDrain("dex2oat"); - - builder.getOrCreateUidBatteryConsumerBuilder(Process.FIRST_APPLICATION_UID + 1) - .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CPU, 100000) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 1000.0) - .setPackageWithHighestDrain("dex2oat"); - - builder.getOrCreateUidBatteryConsumerBuilder(UserHandle.getSharedAppGid(Process.LOG_UID)) - .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CPU, 100000) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 900.0); - - return builder.build(); - } - - private Preference getCachedPreference(String key) { - return mPreferenceCache != null ? mPreferenceCache.remove(key) : null; - } - - private void removeCachedPrefs(PreferenceGroup group) { - for (Preference p : mPreferenceCache.values()) { - group.removePreference(p); - } - mPreferenceCache = null; - } - - private int getCachedCount() { - return mPreferenceCache != null ? mPreferenceCache.size() : 0; - } - - private void addNotAvailableMessage() { - Preference notAvailable = getCachedPreference(NOT_AVAILABLE); - if (notAvailable == null) { - notAvailable = new Preference(mPrefContext); - notAvailable.setKey(NOT_AVAILABLE); - notAvailable.setTitle(R.string.power_usage_not_available); - notAvailable.setSelectable(false); - mAppListGroup.addPreference(notAvailable); - } - } -} diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java index d4d7a00fdc2..3fb75c36c56 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java +++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java @@ -337,10 +337,8 @@ public class BatteryDiffEntry { mAppIcon = nameAndIcon.mIcon; } - final BatteryEntry.NameAndIcon nameAndIcon = - BatteryEntry.loadNameAndIcon( - mContext, uid, /*handler=*/ null, /*batteryEntry=*/ null, - packageName, mAppLabel, mAppIcon); + final BatteryEntry.NameAndIcon nameAndIcon = BatteryEntry.loadNameAndIcon( + mContext, uid, /*batteryEntry=*/ null, packageName, mAppLabel, mAppIcon); // Clears BatteryEntry internal cache since we will have another one. BatteryEntry.clearUidCache(); if (nameAndIcon != null) { diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java index ccb2fb786eb..af67610d2ec 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java +++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java @@ -26,7 +26,6 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; import android.graphics.drawable.Drawable; import android.os.BatteryConsumer; -import android.os.Handler; import android.os.Process; import android.os.RemoteException; import android.os.UidBatteryConsumer; @@ -80,78 +79,9 @@ public class BatteryEntry { static final HashMap sUidCache = new HashMap<>(); static final ArrayList sRequestQueue = new ArrayList(); - static Handler sHandler; static Locale sCurrentLocale = null; - private static class NameAndIconLoader extends Thread { - private boolean mAbort = false; - - NameAndIconLoader() { - super("BatteryUsage Icon Loader"); - } - - public void abort() { - mAbort = true; - } - - @Override - public void run() { - while (true) { - BatteryEntry be; - synchronized (sRequestQueue) { - if (sRequestQueue.isEmpty() || mAbort) { - if (sHandler != null) { - sHandler.sendEmptyMessage(MSG_REPORT_FULLY_DRAWN); - } - return; - } - be = sRequestQueue.remove(0); - } - final NameAndIcon nameAndIcon = - BatteryEntry.loadNameAndIcon( - be.mContext, be.getUid(), sHandler, be, - be.mDefaultPackageName, be.mName, be.mIcon); - if (nameAndIcon != null) { - be.mIcon = nameAndIcon.mIcon; - be.mName = nameAndIcon.mName; - be.mDefaultPackageName = nameAndIcon.mPackageName; - } - } - } - } - - private static NameAndIconLoader sRequestThread; - - /** Starts the request queue. */ - public static void startRequestQueue() { - if (sHandler != null) { - synchronized (sRequestQueue) { - if (!sRequestQueue.isEmpty()) { - if (sRequestThread != null) { - sRequestThread.abort(); - } - sRequestThread = new NameAndIconLoader(); - sRequestThread.setPriority(Thread.MIN_PRIORITY); - sRequestThread.start(); - sRequestQueue.notify(); - } - } - } - } - - /** Stops the request queue. */ - public static void stopRequestQueue() { - synchronized (sRequestQueue) { - if (sRequestThread != null) { - sRequestThread.abort(); - sRequestThread = null; - sRequestQueue.clear(); - sHandler = null; - } - } - } - /** Clears the UID cache. */ public static void clearUidCache() { sUidCache.clear(); @@ -185,16 +115,14 @@ public class BatteryEntry { Drawable mIcon; } - public BatteryEntry(Context context, Handler handler, UserManager um, - BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages, - String packageName) { - this(context, handler, um, batteryConsumer, isHidden, uid, packages, packageName, true); + public BatteryEntry(Context context, UserManager um, BatteryConsumer batteryConsumer, + boolean isHidden, int uid, String[] packages, String packageName) { + this(context, um, batteryConsumer, isHidden, uid, packages, packageName, true); } - public BatteryEntry(Context context, Handler handler, UserManager um, - BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages, - String packageName, boolean loadDataInBackground) { - sHandler = handler; + public BatteryEntry(Context context, UserManager um, BatteryConsumer batteryConsumer, + boolean isHidden, int uid, String[] packages, String packageName, + boolean loadDataInBackground) { mContext = context; mBatteryConsumer = batteryConsumer; mIsHidden = isHidden; @@ -332,20 +260,12 @@ public class BatteryEntry { } else { mIcon = mContext.getPackageManager().getDefaultActivityIcon(); } - - // Avoids post the loading icon and label in the background request. - if (sHandler != null && loadDataInBackground) { - synchronized (sRequestQueue) { - sRequestQueue.add(this); - } - } } /** Loads the app label and icon image and stores into the cache. */ public static NameAndIcon loadNameAndIcon( Context context, int uid, - Handler handler, BatteryEntry batteryEntry, String defaultPackageName, String name, @@ -432,9 +352,6 @@ public class BatteryEntry { utd.mPackageName = defaultPackageName; sUidCache.put(uidString, utd); - if (handler != null) { - handler.sendMessage(handler.obtainMessage(MSG_UPDATE_NAME_ICON, batteryEntry)); - } return new NameAndIcon(name, defaultPackageName, icon, /*iconId=*/ 0); } diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoader.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoader.java index 9a9edf28c75..c944eca7efc 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoader.java +++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoader.java @@ -24,13 +24,15 @@ import android.util.Log; import androidx.annotation.VisibleForTesting; import java.util.List; +import java.util.function.Supplier; /** Load battery usage data in the background. */ public final class BatteryUsageDataLoader { private static final String TAG = "BatteryUsageDataLoader"; + // For testing only. @VisibleForTesting - static BatteryAppListPreferenceController sController; + static Supplier> sFakeBatteryEntryListSupplier; private BatteryUsageDataLoader() { } @@ -47,10 +49,9 @@ public final class BatteryUsageDataLoader { final long start = System.currentTimeMillis(); final BatteryUsageStats batteryUsageStats = DataProcessor.getBatteryUsageStats(context); final List batteryEntryList = - DataProcessor.generateBatteryEntryListFromBatteryUsageStats( - context, - batteryUsageStats, - sController); + sFakeBatteryEntryListSupplier != null ? sFakeBatteryEntryListSupplier.get() + : DataProcessor.generateBatteryEntryListFromBatteryUsageStats(context, + batteryUsageStats); if (batteryEntryList == null || batteryEntryList.isEmpty()) { Log.w(TAG, "getBatteryEntryList() returns null or empty content"); } diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java index 4b0a58fa77a..14d6ea912db 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java +++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java @@ -21,22 +21,29 @@ import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.utcToLoca import android.app.settings.SettingsEnums; import android.content.ContentValues; import android.content.Context; +import android.content.pm.PackageManager; import android.os.AsyncTask; +import android.os.BatteryConsumer; import android.os.BatteryStatsManager; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; import android.os.Handler; import android.os.Looper; +import android.os.Process; +import android.os.UidBatteryConsumer; +import android.os.UserBatteryConsumer; import android.os.UserHandle; import android.os.UserManager; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArraySet; import android.util.Log; +import android.util.SparseArray; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.os.PowerProfile; import com.android.settings.Utils; import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.overlay.FeatureFactory; @@ -48,6 +55,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -62,12 +70,14 @@ import java.util.stream.Collectors; public final class DataProcessor { private static final boolean DEBUG = false; private static final String TAG = "DataProcessor"; + private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10; private static final int MIN_DAILY_DATA_SIZE = 2; private static final int MIN_TIMESTAMP_DATA_SIZE = 2; private static final int MAX_DIFF_SECONDS_OF_UPPER_TIMESTAMP = 5; // Maximum total time value for each hourly slot cumulative data at most 2 hours. private static final float TOTAL_HOURLY_TIME_THRESHOLD = DateUtils.HOUR_IN_MILLIS * 2; private static final long MIN_TIME_SLOT = DateUtils.HOUR_IN_MILLIS * 2; + private static final String MEDIASERVER_PACKAGE_NAME = "mediaserver"; private static final Map EMPTY_BATTERY_MAP = new HashMap<>(); private static final BatteryHistEntry EMPTY_BATTERY_HIST_ENTRY = new BatteryHistEntry(new ContentValues()); @@ -188,24 +198,26 @@ public final class DataProcessor { @Nullable public static List generateBatteryEntryListFromBatteryUsageStats( final Context context, - @Nullable final BatteryUsageStats batteryUsageStats, - @Nullable BatteryAppListPreferenceController batteryAppListPreferenceController) { + @Nullable final BatteryUsageStats batteryUsageStats) { if (batteryUsageStats == null) { Log.w(TAG, "batteryUsageStats is null content"); return null; } - // Loads the battery consuming data. - final BatteryAppListPreferenceController controller = - batteryAppListPreferenceController == null - ? new BatteryAppListPreferenceController( - context, - /*preferenceKey=*/ null, - /*lifecycle=*/ null, - /*activity*=*/ null, - /*fragment=*/ null) - : batteryAppListPreferenceController; - - return controller.getBatteryEntryList(batteryUsageStats, /*showAllApps=*/ true); + if (!shouldShowBatteryAttributionList(context)) { + return null; + } + final BatteryUtils batteryUtils = BatteryUtils.getInstance(context); + final int dischargePercentage = Math.max(0, batteryUsageStats.getDischargePercentage()); + final List usageList = getCoalescedUsageList( + context, batteryUtils, batteryUsageStats, /*loadDataInBackground=*/ false); + final double totalPower = batteryUsageStats.getConsumedPower(); + for (int i = 0; i < usageList.size(); i++) { + final BatteryEntry entry = usageList.get(i); + final double percentOfTotal = batteryUtils.calculateBatteryPercent( + entry.getConsumedPower(), totalPower, dischargePercentage); + entry.mPercent = percentOfTotal; + } + return usageList; } /** @@ -534,10 +546,7 @@ public final class DataProcessor { try { final BatteryUsageStats batteryUsageStats = getBatteryUsageStats(context); final List batteryEntryList = - generateBatteryEntryListFromBatteryUsageStats( - context, - batteryUsageStats, - /*batteryAppListPreferenceController=*/ null); + generateBatteryEntryListFromBatteryUsageStats(context, batteryUsageStats); batteryDiffData = generateBatteryDiffData(context, batteryEntryList, batteryUsageStats); closeBatteryUsageStats(batteryUsageStats); } catch (RuntimeException e) { @@ -1100,6 +1109,136 @@ public final class DataProcessor { } } + private static boolean shouldShowBatteryAttributionList(final Context context) { + final PowerProfile powerProfile = new PowerProfile(context); + // Cheap hack to try to figure out if the power_profile.xml was populated. + final double averagePowerForOrdinal = powerProfile.getAveragePowerForOrdinal( + PowerProfile.POWER_GROUP_DISPLAY_SCREEN_FULL, 0); + final boolean shouldShowBatteryAttributionList = + averagePowerForOrdinal >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP; + if (!shouldShowBatteryAttributionList) { + Log.w(TAG, "shouldShowBatteryAttributionList(): " + averagePowerForOrdinal); + } + return shouldShowBatteryAttributionList; + } + + /** + * We want to coalesce some UIDs. For example, dex2oat runs under a shared gid that + * exists for all users of the same app. We detect this case and merge the power use + * for dex2oat to the device OWNER's use of the app. + * + * @return A sorted list of apps using power. + */ + private static List getCoalescedUsageList(final Context context, + final BatteryUtils batteryUtils, + final BatteryUsageStats batteryUsageStats, + final boolean loadDataInBackground) { + final PackageManager packageManager = context.getPackageManager(); + final UserManager userManager = context.getSystemService(UserManager.class); + final SparseArray batteryEntryList = new SparseArray<>(); + final ArrayList results = new ArrayList<>(); + final List uidBatteryConsumers = + batteryUsageStats.getUidBatteryConsumers(); + + // Sort to have all apps with "real" UIDs first, followed by apps that are supposed + // to be combined with the real ones. + uidBatteryConsumers.sort(Comparator.comparingInt( + consumer -> consumer.getUid() == getRealUid(consumer) ? 0 : 1)); + + for (int i = 0, size = uidBatteryConsumers.size(); i < size; i++) { + final UidBatteryConsumer consumer = uidBatteryConsumers.get(i); + final int uid = getRealUid(consumer); + + final String[] packages = packageManager.getPackagesForUid(uid); + if (batteryUtils.shouldHideUidBatteryConsumerUnconditionally(consumer, packages)) { + continue; + } + + final boolean isHidden = batteryUtils.shouldHideUidBatteryConsumer(consumer, packages); + final int index = batteryEntryList.indexOfKey(uid); + if (index < 0) { + // New entry. + batteryEntryList.put(uid, new BatteryEntry(context, userManager, consumer, + isHidden, uid, packages, null, loadDataInBackground)); + } else { + // Combine BatterySippers if we already have one with this UID. + final BatteryEntry existingSipper = batteryEntryList.valueAt(index); + existingSipper.add(consumer); + } + } + + final BatteryConsumer deviceConsumer = batteryUsageStats.getAggregateBatteryConsumer( + BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE); + final BatteryConsumer appsConsumer = batteryUsageStats.getAggregateBatteryConsumer( + BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS); + + for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT; + componentId++) { + results.add(new BatteryEntry(context, componentId, + deviceConsumer.getConsumedPower(componentId), + appsConsumer.getConsumedPower(componentId), + deviceConsumer.getUsageDurationMillis(componentId))); + } + + for (int componentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID; + componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + + deviceConsumer.getCustomPowerComponentCount(); + componentId++) { + results.add(new BatteryEntry(context, componentId, + deviceConsumer.getCustomPowerComponentName(componentId), + deviceConsumer.getConsumedPowerForCustomComponent(componentId), + appsConsumer.getConsumedPowerForCustomComponent(componentId))); + } + + final List userBatteryConsumers = + batteryUsageStats.getUserBatteryConsumers(); + for (int i = 0, size = userBatteryConsumers.size(); i < size; i++) { + final UserBatteryConsumer consumer = userBatteryConsumers.get(i); + results.add(new BatteryEntry(context, userManager, consumer, /* isHidden */ true, + Process.INVALID_UID, null, null, loadDataInBackground)); + } + + final int numUidSippers = batteryEntryList.size(); + + for (int i = 0; i < numUidSippers; i++) { + results.add(batteryEntryList.valueAt(i)); + } + + // The sort order must have changed, so re-sort based on total power use. + results.sort(BatteryEntry.COMPARATOR); + return results; + } + + private static int getRealUid(final UidBatteryConsumer consumer) { + int realUid = consumer.getUid(); + + // Check if this UID is a shared GID. If so, we combine it with the OWNER's + // actual app UID. + if (isSharedGid(consumer.getUid())) { + realUid = UserHandle.getUid(UserHandle.USER_SYSTEM, + UserHandle.getAppIdFromSharedAppGid(consumer.getUid())); + } + + // Check if this UID is a system UID (mediaserver, logd, nfc, drm, etc). + if (isSystemUid(realUid) + && !MEDIASERVER_PACKAGE_NAME.equals(consumer.getPackageWithHighestDrain())) { + // Use the system UID for all UIDs running in their own sandbox that + // are not apps. We exclude mediaserver because we already are expected to + // report that as a separate item. + realUid = Process.SYSTEM_UID; + } + return realUid; + } + + private static boolean isSharedGid(final int uid) { + return UserHandle.getAppIdFromSharedAppGid(uid) > 0; + } + + private static boolean isSystemUid(final int uid) { + final int appUid = UserHandle.getAppId(uid); + return appUid >= Process.SYSTEM_UID && appUid < Process.FIRST_APPLICATION_UID; + } + private static boolean isUsageMapValid( final Map> batteryUsageMap, final List hourlyBatteryLevelsPerDay) { diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java index 5a110a54c93..f3fe4620b84 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java @@ -216,41 +216,6 @@ public class BatteryUtilsTest { assertThat(time).isEqualTo(0); } - @Test - public void testShouldHideSystemConsumer_TypeIdle_ReturnTrue() { - assertThat(mBatteryUtils.shouldHideDevicePowerComponent(mAggregateBatteryConsumer, - BatteryConsumer.POWER_COMPONENT_IDLE)).isTrue(); - } - - @Test - public void testShouldHideSystemConsumer_TypeMobileRadio_ReturnTrue() { - assertThat(mBatteryUtils.shouldHideDevicePowerComponent(mAggregateBatteryConsumer, - BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)).isTrue(); - } - - @Test - public void testShouldHideSystemConsumer_TypeScreen_ReturnTrue() { - assertThat(mBatteryUtils.shouldHideDevicePowerComponent(mAggregateBatteryConsumer, - BatteryConsumer.POWER_COMPONENT_SCREEN)).isTrue(); - } - - @Test - public void testShouldHideSystemConsumer_TypeBluetooth_ReturnTrue() { - assertThat(mBatteryUtils.shouldHideDevicePowerComponent(mAggregateBatteryConsumer, - BatteryConsumer.POWER_COMPONENT_BLUETOOTH)).isTrue(); } - - @Test - public void testShouldHideSystemConsumer_TypeWifi_ReturnTrue() { - assertThat(mBatteryUtils.shouldHideDevicePowerComponent(mAggregateBatteryConsumer, - BatteryConsumer.POWER_COMPONENT_WIFI)).isTrue(); - } - - @Test - public void testShouldHideSystemConsumer_OtherType_ReturnFalse() { - assertThat(mBatteryUtils.shouldHideDevicePowerComponent(mAggregateBatteryConsumer, - BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)).isFalse(); - } - @Test public void testCalculateBatteryPercent() { assertThat(mBatteryUtils.calculateBatteryPercent(BATTERY_SYSTEM_USAGE, TOTAL_BATTERY_USAGE, diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryAppListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryAppListPreferenceControllerTest.java deleted file mode 100644 index e003c151d2c..00000000000 --- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryAppListPreferenceControllerTest.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.fuelgauge.batteryusage; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.os.Process; -import android.os.UserManager; -import android.text.format.DateUtils; - -import androidx.preference.PreferenceGroup; - -import com.android.settings.R; -import com.android.settings.SettingsActivity; -import com.android.settings.core.InstrumentedPreferenceFragment; -import com.android.settings.fuelgauge.BatteryUtils; -import com.android.settings.testutils.FakeFeatureFactory; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -@RunWith(RobolectricTestRunner.class) -public class BatteryAppListPreferenceControllerTest { - - private static final String KEY_APP_LIST = "app_list"; - - @Mock - private SettingsActivity mSettingsActivity; - @Mock - private PreferenceGroup mAppListGroup; - @Mock - private InstrumentedPreferenceFragment mFragment; - @Mock - private BatteryUtils mBatteryUtils; - @Mock - private PackageManager mPackageManager; - @Mock - private UserManager mUserManager; - @Mock - private BatteryEntry mBatteryEntry; - - private Context mContext; - private PowerGaugePreference mPreference; - private BatteryAppListPreferenceController mPreferenceController; - private FakeFeatureFactory mFeatureFactory; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mFeatureFactory = FakeFeatureFactory.setupForTest(); - mContext = spy(RuntimeEnvironment.application); - final Resources resources = spy(mContext.getResources()); - when(mContext.getResources()).thenReturn(resources); - when(mContext.getPackageManager()).thenReturn(mPackageManager); - when(mContext.getApplicationContext()).thenReturn(mContext); - when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); - when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{}); - - mPreference = new PowerGaugePreference(mContext); - - mPreferenceController = new BatteryAppListPreferenceController(mContext, KEY_APP_LIST, null, - mSettingsActivity, mFragment); - mPreferenceController.mBatteryUtils = mBatteryUtils; - mPreferenceController.mAppListGroup = mAppListGroup; - - BatteryAppListPreferenceController.sConfig = - new BatteryAppListPreferenceController.Config() { - @Override - public boolean shouldShowBatteryAttributionList(Context context) { - return true; - } - }; - } - - @Test - public void testSetUsageSummary_timeLessThanOneMinute_doNotSetSummary() { - when(mBatteryEntry.getTimeInForegroundMs()).thenReturn(59 * DateUtils.SECOND_IN_MILLIS); - - mPreferenceController.setUsageSummary(mPreference, mBatteryEntry); - assertThat(mPreference.getSummary()).isNull(); - } - - @Test - public void testSetUsageSummary_systemProcessUid_doNotSetSummary() { - when(mBatteryEntry.getTimeInForegroundMs()).thenReturn(DateUtils.MINUTE_IN_MILLIS); - when(mBatteryEntry.getUid()).thenReturn(Process.SYSTEM_UID); - - mPreferenceController.setUsageSummary(mPreference, mBatteryEntry); - assertThat(mPreference.getSummary()).isNull(); - } - - @Test - public void testSetUsageSummary_timeMoreThanOneMinute_normalApp_setScreenSummary() { - when(mBatteryEntry.getTimeInForegroundMs()).thenReturn(2 * DateUtils.MINUTE_IN_MILLIS); - doReturn(mContext.getText(R.string.battery_used_for)).when(mFragment).getText( - R.string.battery_used_for); - doReturn(mContext).when(mFragment).getContext(); - - mPreferenceController.setUsageSummary(mPreference, mBatteryEntry); - - assertThat(mPreference.getSummary().toString()).isEqualTo("Used for 2 min"); - } - - @Test - public void testSetUsageSummary_timeMoreThanOneMinute_hiddenApp_setUsedSummary() { - when(mBatteryEntry.getTimeInForegroundMs()).thenReturn(2 * DateUtils.MINUTE_IN_MILLIS); - when(mBatteryEntry.isHidden()).thenReturn(true); - - doReturn(mContext).when(mFragment).getContext(); - - mPreferenceController.setUsageSummary(mPreference, mBatteryEntry); - - assertThat(mPreference.getSummary().toString()).isEqualTo("2 min"); - } - - @Test - public void testNeverUseFakeData() { - assertThat(BatteryAppListPreferenceController.USE_FAKE_DATA).isFalse(); - } -} diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryEntryTest.java index ffc6d9a02e6..90fa572b36c 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryEntryTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryEntryTest.java @@ -30,7 +30,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.BatteryConsumer; -import android.os.Handler; import android.os.Process; import android.os.UidBatteryConsumer; import android.os.UserBatteryConsumer; @@ -70,8 +69,6 @@ public class BatteryEntryTest { private Context mMockContext; private Context mContext; @Mock - private Handler mMockHandler; - @Mock private PackageManager mMockPackageManager; @Mock private UserManager mMockUserManager; @@ -102,7 +99,7 @@ public class BatteryEntryTest { UidBatteryConsumer consumer = mock(UidBatteryConsumer.class); when(consumer.getUid()).thenReturn(APP_UID); when(consumer.getPackageWithHighestDrain()).thenReturn(highDrainPackage); - return new BatteryEntry(mMockContext, mMockHandler, mMockUserManager, + return new BatteryEntry(mMockContext, mMockUserManager, consumer, false, APP_UID, packages, packageName); } @@ -117,7 +114,7 @@ public class BatteryEntryTest { private BatteryEntry createUserBatteryConsumer(int userId) { UserBatteryConsumer consumer = mock(UserBatteryConsumer.class); when(consumer.getUserId()).thenReturn(userId); - return new BatteryEntry(mMockContext, mMockHandler, mMockUserManager, + return new BatteryEntry(mMockContext, mMockUserManager, consumer, false, 0, null, null); } @@ -182,7 +179,7 @@ public class BatteryEntryTest { when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND)) .thenReturn(100L); - final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mMockHandler, + final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mMockUserManager, mUidBatteryConsumer, false, 0, null, null); assertThat(entry.getTimeInForegroundMs()).isEqualTo(100L); @@ -201,7 +198,7 @@ public class BatteryEntryTest { when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND)) .thenReturn(100L); - final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mMockHandler, + final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mMockUserManager, mUidBatteryConsumer, false, 0, null, null); assertThat(entry.getTimeInBackgroundMs()).isEqualTo(100L); @@ -217,8 +214,6 @@ public class BatteryEntryTest { @Test public void testUidCache_switchLocale_shouldCleanCache() { - BatteryEntry.stopRequestQueue(); - Locale.setDefault(new Locale("en_US")); BatteryEntry.sUidCache.put(Integer.toString(APP_UID), null); assertThat(BatteryEntry.sUidCache).isNotEmpty(); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoaderTest.java index e6bba8de0b7..9c0604d9f13 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoaderTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoaderTest.java @@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -59,8 +58,6 @@ public final class BatteryUsageDataLoaderTest { @Mock private BatteryUsageStats mBatteryUsageStats; @Mock - private BatteryAppListPreferenceController mMockBatteryAppListController; - @Mock private BatteryEntry mMockBatteryEntry; @Captor private ArgumentCaptor mStatsQueryCaptor; @@ -69,7 +66,6 @@ public final class BatteryUsageDataLoaderTest { public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); - BatteryUsageDataLoader.sController = mMockBatteryAppListController; doReturn(mContext).when(mContext).getApplicationContext(); doReturn(mBatteryStatsManager).when(mContext).getSystemService( Context.BATTERY_STATS_SERVICE); @@ -84,8 +80,7 @@ public final class BatteryUsageDataLoaderTest { batteryEntryList.add(mMockBatteryEntry); when(mBatteryStatsManager.getBatteryUsageStats(mStatsQueryCaptor.capture())) .thenReturn(mBatteryUsageStats); - when(mMockBatteryAppListController.getBatteryEntryList(mBatteryUsageStats, true)) - .thenReturn(batteryEntryList); + BatteryUsageDataLoader.sFakeBatteryEntryListSupplier = () -> batteryEntryList; BatteryUsageDataLoader.loadUsageData(mContext); @@ -93,24 +88,6 @@ public final class BatteryUsageDataLoaderTest { assertThat(queryFlags & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY) .isNotEqualTo(0); - verify(mMockBatteryAppListController) - .getBatteryEntryList(mBatteryUsageStats, /*showAllApps=*/ true); - verify(mMockContentResolver).insert(any(), any()); - } - - @Test - public void loadUsageData_nullBatteryUsageStats_notLoadBatteryEntryData() { - when(mBatteryStatsManager.getBatteryUsageStats(mStatsQueryCaptor.capture())) - .thenReturn(null); - - BatteryUsageDataLoader.loadUsageData(mContext); - - final int queryFlags = mStatsQueryCaptor.getValue().getFlags(); - assertThat(queryFlags - & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY) - .isNotEqualTo(0); - verify(mMockBatteryAppListController, never()) - .getBatteryEntryList(mBatteryUsageStats, /*showAllApps=*/ true); verify(mMockContentResolver).insert(any(), any()); } @@ -118,8 +95,7 @@ public final class BatteryUsageDataLoaderTest { public void loadUsageData_nullBatteryEntryList_insertFakeDataIntoProvider() { when(mBatteryStatsManager.getBatteryUsageStats(mStatsQueryCaptor.capture())) .thenReturn(mBatteryUsageStats); - when(mMockBatteryAppListController.getBatteryEntryList(mBatteryUsageStats, true)) - .thenReturn(null); + BatteryUsageDataLoader.sFakeBatteryEntryListSupplier = () -> null; BatteryUsageDataLoader.loadUsageData(mContext); @@ -130,8 +106,7 @@ public final class BatteryUsageDataLoaderTest { public void loadUsageData_emptyBatteryEntryList_insertFakeDataIntoProvider() { when(mBatteryStatsManager.getBatteryUsageStats(mStatsQueryCaptor.capture())) .thenReturn(mBatteryUsageStats); - when(mMockBatteryAppListController.getBatteryEntryList(mBatteryUsageStats, true)) - .thenReturn(new ArrayList()); + BatteryUsageDataLoader.sFakeBatteryEntryListSupplier = () -> new ArrayList(); BatteryUsageDataLoader.loadUsageData(mContext);