Merge "Fix missing time-in-foreground and time-in-background for some apps" into sc-dev

This commit is contained in:
Dmitri Plotnikov
2021-06-10 16:10:42 +00:00
committed by Android (Google) Code Review
4 changed files with 73 additions and 48 deletions

View File

@@ -118,7 +118,8 @@ public class AppBatteryPreferenceController extends BasePreferenceController
final UserManager userManager = final UserManager userManager =
(UserManager) mContext.getSystemService(Context.USER_SERVICE); (UserManager) mContext.getSystemService(Context.USER_SERVICE);
final BatteryEntry entry = new BatteryEntry(mContext, /* handler */null, userManager, final BatteryEntry entry = new BatteryEntry(mContext, /* handler */null, userManager,
mUidBatteryConsumer, /* isHidden */ false, /* packages */ null, mPackageName); mUidBatteryConsumer, /* isHidden */ false,
mUidBatteryConsumer.getUid(), /* packages */ null, mPackageName);
AdvancedPowerUsageDetail.startBatteryDetailPage(mParent.getActivity(), mParent, AdvancedPowerUsageDetail.startBatteryDetailPage(mParent.getActivity(), mParent,
entry, mBatteryPercent); entry, mBatteryPercent);
} else { } else {

View File

@@ -55,6 +55,7 @@ import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.utils.StringUtil; import com.android.settingslib.utils.StringUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator;
import java.util.List; import java.util.List;
/** /**
@@ -66,6 +67,7 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
static final boolean USE_FAKE_DATA = false; static final boolean USE_FAKE_DATA = false;
private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 20; 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 int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
private static final String MEDIASERVER_PACKAGE_NAME = "mediaserver";
private final String mPreferenceKey; private final String mPreferenceKey;
@VisibleForTesting @VisibleForTesting
@@ -303,27 +305,17 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
final ArrayList<BatteryEntry> results = new ArrayList<>(); final ArrayList<BatteryEntry> results = new ArrayList<>();
final List<UidBatteryConsumer> uidBatteryConsumers = final List<UidBatteryConsumer> uidBatteryConsumers =
mBatteryUsageStats.getUidBatteryConsumers(); 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++) { for (int i = 0, size = uidBatteryConsumers.size(); i < size; i++) {
final UidBatteryConsumer consumer = uidBatteryConsumers.get(i); final UidBatteryConsumer consumer = uidBatteryConsumers.get(i);
int realUid = consumer.getUid(); final int uid = getRealUid(consumer);
// Check if this UID is a shared GID. If so, we combine it with the OWNER's final String[] packages = mPackageManager.getPackagesForUid(uid);
// 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".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;
}
final String[] packages = mPackageManager.getPackagesForUid(consumer.getUid());
if (mBatteryUtils.shouldHideUidBatteryConsumerUnconditionally(consumer, packages)) { if (mBatteryUtils.shouldHideUidBatteryConsumerUnconditionally(consumer, packages)) {
continue; continue;
} }
@@ -333,11 +325,11 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
continue; continue;
} }
final int index = batteryEntryList.indexOfKey(realUid); final int index = batteryEntryList.indexOfKey(uid);
if (index < 0) { if (index < 0) {
// New entry. // New entry.
batteryEntryList.put(realUid, new BatteryEntry(mContext, mHandler, mUserManager, batteryEntryList.put(uid, new BatteryEntry(mContext, mHandler, mUserManager,
consumer, isHidden, packages, null, loadDataInBackground)); consumer, isHidden, uid, packages, null, loadDataInBackground));
} else { } else {
// Combine BatterySippers if we already have one with this UID. // Combine BatterySippers if we already have one with this UID.
final BatteryEntry existingSipper = batteryEntryList.valueAt(index); final BatteryEntry existingSipper = batteryEntryList.valueAt(index);
@@ -385,7 +377,8 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
for (int i = 0, size = userBatteryConsumers.size(); i < size; i++) { for (int i = 0, size = userBatteryConsumers.size(); i < size; i++) {
final UserBatteryConsumer consumer = userBatteryConsumers.get(i); final UserBatteryConsumer consumer = userBatteryConsumers.get(i);
results.add(new BatteryEntry(mContext, mHandler, mUserManager, results.add(new BatteryEntry(mContext, mHandler, mUserManager,
consumer, /* isHidden */ true, null, null, loadDataInBackground)); consumer, /* isHidden */ true, Process.INVALID_UID, null, null,
loadDataInBackground));
} }
} }
@@ -400,6 +393,27 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
return results; 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 @VisibleForTesting
void setUsageSummary(Preference preference, BatteryEntry entry) { void setUsageSummary(Preference preference, BatteryEntry entry) {
// Only show summary when usage time is longer than one minute // Only show summary when usage time is longer than one minute

View File

@@ -159,12 +159,15 @@ public class BatteryEntry {
private final Context mContext; private final Context mContext;
private final BatteryConsumer mBatteryConsumer; private final BatteryConsumer mBatteryConsumer;
private final int mUid;
private final boolean mIsHidden; private final boolean mIsHidden;
@ConvertUtils.ConsumerType @ConvertUtils.ConsumerType
private final int mConsumerType; private final int mConsumerType;
@BatteryConsumer.PowerComponent @BatteryConsumer.PowerComponent
private final int mPowerComponentId; private final int mPowerComponentId;
private long mUsageDurationMs; private long mUsageDurationMs;
private long mTimeInForegroundMs;
private long mTimeInBackgroundMs;
public String name; public String name;
public Drawable icon; public Drawable icon;
@@ -180,13 +183,13 @@ public class BatteryEntry {
} }
public BatteryEntry(Context context, Handler handler, UserManager um, public BatteryEntry(Context context, Handler handler, UserManager um,
@NonNull BatteryConsumer batteryConsumer, boolean isHidden, String[] packages, @NonNull BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages,
String packageName) { String packageName) {
this(context, handler, um, batteryConsumer, isHidden, packages, packageName, true); this(context, handler, um, batteryConsumer, isHidden, uid, packages, packageName, true);
} }
public BatteryEntry(Context context, Handler handler, UserManager um, public BatteryEntry(Context context, Handler handler, UserManager um,
@NonNull BatteryConsumer batteryConsumer, boolean isHidden, String[] packages, @NonNull BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages,
String packageName, boolean loadDataInBackground) { String packageName, boolean loadDataInBackground) {
sHandler = handler; sHandler = handler;
mContext = context; mContext = context;
@@ -196,11 +199,11 @@ public class BatteryEntry {
mPowerComponentId = -1; mPowerComponentId = -1;
if (batteryConsumer instanceof UidBatteryConsumer) { if (batteryConsumer instanceof UidBatteryConsumer) {
mUid = uid;
mConsumerType = ConvertUtils.CONSUMER_TYPE_UID_BATTERY; mConsumerType = ConvertUtils.CONSUMER_TYPE_UID_BATTERY;
mConsumedPower = batteryConsumer.getConsumedPower(); mConsumedPower = batteryConsumer.getConsumedPower();
UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer; UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer;
int uid = uidBatteryConsumer.getUid();
if (mDefaultPackageName == null) { if (mDefaultPackageName == null) {
// Apps should only have one package // Apps should only have one package
if (packages != null && packages.length == 1) { if (packages != null && packages.length == 1) {
@@ -222,7 +225,12 @@ public class BatteryEntry {
} }
} }
getQuickNameIconForUid(uid, packages, loadDataInBackground); getQuickNameIconForUid(uid, packages, loadDataInBackground);
mTimeInForegroundMs =
uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND);
mTimeInBackgroundMs =
uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND);
} else if (batteryConsumer instanceof UserBatteryConsumer) { } else if (batteryConsumer instanceof UserBatteryConsumer) {
mUid = Process.INVALID_UID;
mConsumerType = ConvertUtils.CONSUMER_TYPE_USER_BATTERY; mConsumerType = ConvertUtils.CONSUMER_TYPE_USER_BATTERY;
mConsumedPower = batteryConsumer.getConsumedPower(); mConsumedPower = batteryConsumer.getConsumedPower();
final NameAndIcon nameAndIcon = getNameAndIconFromUserId( final NameAndIcon nameAndIcon = getNameAndIconFromUserId(
@@ -239,6 +247,7 @@ public class BatteryEntry {
double appsPowerMah, long usageDurationMs) { double appsPowerMah, long usageDurationMs) {
mContext = context; mContext = context;
mBatteryConsumer = null; mBatteryConsumer = null;
mUid = Process.INVALID_UID;
mIsHidden = false; mIsHidden = false;
mPowerComponentId = powerComponentId; mPowerComponentId = powerComponentId;
mConsumedPower = mConsumedPower =
@@ -261,6 +270,7 @@ public class BatteryEntry {
double devicePowerMah, double appsPowerMah) { double devicePowerMah, double appsPowerMah) {
mContext = context; mContext = context;
mBatteryConsumer = null; mBatteryConsumer = null;
mUid = Process.INVALID_UID;
mIsHidden = false; mIsHidden = false;
mPowerComponentId = powerComponentId; mPowerComponentId = powerComponentId;
@@ -438,7 +448,7 @@ public class BatteryEntry {
*/ */
public String getKey() { public String getKey() {
if (mBatteryConsumer instanceof UidBatteryConsumer) { if (mBatteryConsumer instanceof UidBatteryConsumer) {
return Integer.toString(((UidBatteryConsumer) mBatteryConsumer).getUid()); return Integer.toString(mUid);
} else if (mBatteryConsumer instanceof UserBatteryConsumer) { } else if (mBatteryConsumer instanceof UserBatteryConsumer) {
return "U|" + ((UserBatteryConsumer) mBatteryConsumer).getUserId(); return "U|" + ((UserBatteryConsumer) mBatteryConsumer).getUserId();
} else { } else {
@@ -482,11 +492,7 @@ public class BatteryEntry {
* Returns the UID of the app described by this entry. * Returns the UID of the app described by this entry.
*/ */
public int getUid() { public int getUid() {
if (mBatteryConsumer instanceof UidBatteryConsumer) { return mUid;
return ((UidBatteryConsumer) mBatteryConsumer).getUid();
} else {
return Process.INVALID_UID;
}
} }
/** /**
@@ -494,8 +500,7 @@ public class BatteryEntry {
*/ */
public long getTimeInForegroundMs() { public long getTimeInForegroundMs() {
if (mBatteryConsumer instanceof UidBatteryConsumer) { if (mBatteryConsumer instanceof UidBatteryConsumer) {
return ((UidBatteryConsumer) mBatteryConsumer).getTimeInStateMs( return mTimeInForegroundMs;
UidBatteryConsumer.STATE_FOREGROUND);
} else { } else {
return mUsageDurationMs; return mUsageDurationMs;
} }
@@ -506,8 +511,7 @@ public class BatteryEntry {
*/ */
public long getTimeInBackgroundMs() { public long getTimeInBackgroundMs() {
if (mBatteryConsumer instanceof UidBatteryConsumer) { if (mBatteryConsumer instanceof UidBatteryConsumer) {
return ((UidBatteryConsumer) mBatteryConsumer).getTimeInStateMs( return mTimeInBackgroundMs;
UidBatteryConsumer.STATE_BACKGROUND);
} else { } else {
return 0; return 0;
} }
@@ -526,9 +530,15 @@ public class BatteryEntry {
*/ */
public void add(BatteryConsumer batteryConsumer) { public void add(BatteryConsumer batteryConsumer) {
mConsumedPower += batteryConsumer.getConsumedPower(); mConsumedPower += batteryConsumer.getConsumedPower();
if (mDefaultPackageName == null && batteryConsumer instanceof UidBatteryConsumer) { if (batteryConsumer instanceof UidBatteryConsumer) {
mDefaultPackageName = UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer;
((UidBatteryConsumer) batteryConsumer).getPackageWithHighestDrain(); mTimeInForegroundMs += uidBatteryConsumer.getTimeInStateMs(
UidBatteryConsumer.STATE_FOREGROUND);
mTimeInBackgroundMs += uidBatteryConsumer.getTimeInStateMs(
UidBatteryConsumer.STATE_BACKGROUND);
if (mDefaultPackageName == null) {
mDefaultPackageName = uidBatteryConsumer.getPackageWithHighestDrain();
}
} }
} }

View File

@@ -93,7 +93,7 @@ public class BatteryEntryTest {
when(consumer.getUid()).thenReturn(APP_UID); when(consumer.getUid()).thenReturn(APP_UID);
when(consumer.getPackageWithHighestDrain()).thenReturn(highDrainPackage); when(consumer.getPackageWithHighestDrain()).thenReturn(highDrainPackage);
return new BatteryEntry(mMockContext, mockHandler, mockUserManager, return new BatteryEntry(mMockContext, mockHandler, mockUserManager,
consumer, false, packages, packageName); consumer, false, APP_UID, packages, packageName);
} }
private BatteryEntry createAggregateBatteryEntry(int powerComponentId) { private BatteryEntry createAggregateBatteryEntry(int powerComponentId) {
@@ -108,7 +108,7 @@ public class BatteryEntryTest {
UserBatteryConsumer consumer = mock(UserBatteryConsumer.class); UserBatteryConsumer consumer = mock(UserBatteryConsumer.class);
when(consumer.getUserId()).thenReturn(userId); when(consumer.getUserId()).thenReturn(userId);
return new BatteryEntry(mMockContext, mockHandler, mockUserManager, return new BatteryEntry(mMockContext, mockHandler, mockUserManager,
consumer, false, null, null); consumer, false, 0, null, null);
} }
@Test @Test
@@ -169,12 +169,12 @@ public class BatteryEntryTest {
@Test @Test
public void getTimeInForegroundMs_app() { public void getTimeInForegroundMs_app() {
final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
mockUserManager, mUidBatteryConsumer, false, null, null);
when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND)) when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND))
.thenReturn(100L); .thenReturn(100L);
final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
mockUserManager, mUidBatteryConsumer, false, 0, null, null);
assertThat(entry.getTimeInForegroundMs()).isEqualTo(100L); assertThat(entry.getTimeInForegroundMs()).isEqualTo(100L);
} }
@@ -188,12 +188,12 @@ public class BatteryEntryTest {
@Test @Test
public void getTimeInBackgroundMs_app() { public void getTimeInBackgroundMs_app() {
final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
mockUserManager, mUidBatteryConsumer, false, null, null);
when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND)) when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
.thenReturn(100L); .thenReturn(100L);
final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
mockUserManager, mUidBatteryConsumer, false, 0, null, null);
assertThat(entry.getTimeInBackgroundMs()).isEqualTo(100L); assertThat(entry.getTimeInBackgroundMs()).isEqualTo(100L);
} }