BatteryStats: Fix coalescing of shared app GIDs and system UIDs
UIDs that consumed power and were actually shared app GIDs are now coelsced for system apps as well as regular applications. In addition, system UIDs like logd, NFC, DRM, etc are coalesced into Android System. Bug:23189342 Change-Id: I6c8eb4baec66fba3d1f71a155d8ea1fe920ffec9
This commit is contained in:
@@ -24,7 +24,6 @@ import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
@@ -191,7 +190,7 @@ public class BatteryEntry {
|
||||
icon = context.getDrawable(iconId);
|
||||
}
|
||||
if ((name == null || iconId == 0) && this.sipper.uidObj != null) {
|
||||
getQuickNameIconForUid(this.sipper.uidObj);
|
||||
getQuickNameIconForUid(this.sipper.uidObj.getUid());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,8 +205,7 @@ public class BatteryEntry {
|
||||
return name;
|
||||
}
|
||||
|
||||
void getQuickNameIconForUid(BatteryStats.Uid uidObj) {
|
||||
final int uid = uidObj.getUid();
|
||||
void getQuickNameIconForUid(final int uid) {
|
||||
final String uidString = Integer.toString(uid);
|
||||
if (sUidCache.containsKey(uidString)) {
|
||||
UidToDetail utd = sUidCache.get(uidString);
|
||||
@@ -217,10 +215,8 @@ public class BatteryEntry {
|
||||
return;
|
||||
}
|
||||
PackageManager pm = context.getPackageManager();
|
||||
String[] packages = pm.getPackagesForUid(uid);
|
||||
icon = pm.getDefaultActivityIcon();
|
||||
if (packages == null) {
|
||||
//name = Integer.toString(uid);
|
||||
if (pm.getPackagesForUid(uid) == null) {
|
||||
if (uid == 0) {
|
||||
name = context.getResources().getString(R.string.process_kernel_label);
|
||||
} else if ("mediaserver".equals(name)) {
|
||||
@@ -230,10 +226,8 @@ public class BatteryEntry {
|
||||
}
|
||||
iconId = R.drawable.ic_power_system;
|
||||
icon = context.getDrawable(iconId);
|
||||
return;
|
||||
} else {
|
||||
//name = packages[0];
|
||||
}
|
||||
|
||||
if (sHandler != null) {
|
||||
synchronized (mRequestQueue) {
|
||||
mRequestQueue.add(this);
|
||||
@@ -249,15 +243,11 @@ public class BatteryEntry {
|
||||
if (sipper.uidObj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PackageManager pm = context.getPackageManager();
|
||||
final int uid = sipper.uidObj.getUid();
|
||||
final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
|
||||
sipper.mPackages = pm.getPackagesForUid(uid);
|
||||
if (sipper.mPackages == null) {
|
||||
name = Integer.toString(uid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sipper.mPackages != null) {
|
||||
String[] packageLabels = new String[sipper.mPackages.length];
|
||||
System.arraycopy(sipper.mPackages, 0, packageLabels, 0, sipper.mPackages.length);
|
||||
|
||||
@@ -287,9 +277,6 @@ public class BatteryEntry {
|
||||
+ packageLabels[i] + ", user " + userId, e);
|
||||
}
|
||||
}
|
||||
if (icon == null) {
|
||||
icon = defaultActivityIcon;
|
||||
}
|
||||
|
||||
if (packageLabels.length == 1) {
|
||||
name = packageLabels[0];
|
||||
@@ -321,7 +308,17 @@ public class BatteryEntry {
|
||||
}
|
||||
}
|
||||
}
|
||||
final String uidString = Integer.toString(sipper.uidObj.getUid());
|
||||
}
|
||||
|
||||
final String uidString = Integer.toString(uid);
|
||||
if (name == null) {
|
||||
name = uidString;
|
||||
}
|
||||
|
||||
if (icon == null) {
|
||||
icon = pm.getDefaultActivityIcon();
|
||||
}
|
||||
|
||||
UidToDetail utd = new UidToDetail();
|
||||
utd.name = name;
|
||||
utd.icon = icon;
|
||||
|
@@ -76,7 +76,7 @@ public class PowerUsageSummary extends PowerUsageBase {
|
||||
private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
|
||||
|
||||
private static final int MIN_POWER_THRESHOLD_MILLI_AMP = 5;
|
||||
private static final int MAX_ITEMS_TO_LIST = 10;
|
||||
private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 10;
|
||||
private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
|
||||
private static final int SECONDS_IN_HOUR = 60 * 60;
|
||||
|
||||
@@ -181,11 +181,19 @@ public class PowerUsageSummary extends PowerUsageBase {
|
||||
mAppListGroup.addPreference(notAvailable);
|
||||
}
|
||||
|
||||
private static boolean isSharedGid(int uid) {
|
||||
return UserHandle.getAppIdFromSharedAppGid(uid) > 0;
|
||||
}
|
||||
|
||||
private static boolean isSystemUid(int uid) {
|
||||
return uid >= Process.SYSTEM_UID && uid < Process.FIRST_APPLICATION_UID;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 app's using power.
|
||||
* @return A sorted list of apps using power.
|
||||
*/
|
||||
private static List<BatterySipper> getCoalescedUsageList(final List<BatterySipper> sippers) {
|
||||
final SparseArray<BatterySipper> uidList = new SparseArray<>();
|
||||
@@ -193,30 +201,62 @@ public class PowerUsageSummary extends PowerUsageBase {
|
||||
final ArrayList<BatterySipper> results = new ArrayList<>();
|
||||
final int numSippers = sippers.size();
|
||||
for (int i = 0; i < numSippers; i++) {
|
||||
final BatterySipper sipper = sippers.get(i);
|
||||
BatterySipper sipper = sippers.get(i);
|
||||
if (sipper.getUid() > 0) {
|
||||
int realUid = sipper.getUid();
|
||||
if (sipper.getUid() >= Process.FIRST_SHARED_APPLICATION_GID &&
|
||||
sipper.getUid() <= Process.LAST_SHARED_APPLICATION_GID) {
|
||||
// This is a shared gid being used to do work on behalf of an app across all
|
||||
// users. But we'll blame the power on the device OWNER.
|
||||
|
||||
// Check if this UID is a shared GID. If so, we combine it with the OWNER's
|
||||
// actual app UID.
|
||||
if (isSharedGid(sipper.getUid())) {
|
||||
realUid = UserHandle.getUid(UserHandle.USER_OWNER,
|
||||
UserHandle.getAppIdFromSharedAppGid(sipper.getUid()));
|
||||
}
|
||||
|
||||
// Check if this UID is a system UID (mediaserver, logd, nfc, drm, etc).
|
||||
if (isSystemUid(realUid)
|
||||
&& !"mediaserver".equals(sipper.packageWithHighestDrain)) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (realUid != sipper.getUid()) {
|
||||
// Replace the BatterySipper with a new one with the real UID set.
|
||||
BatterySipper newSipper = new BatterySipper(sipper.drainType,
|
||||
new FakeUid(realUid), 0.0);
|
||||
newSipper.add(sipper);
|
||||
newSipper.packageWithHighestDrain = sipper.packageWithHighestDrain;
|
||||
newSipper.mPackages = sipper.mPackages;
|
||||
sipper = newSipper;
|
||||
}
|
||||
|
||||
int index = uidList.indexOfKey(realUid);
|
||||
if (index < 0) {
|
||||
// New entry.
|
||||
uidList.put(realUid, sipper);
|
||||
} else {
|
||||
BatterySipper existingSipper = uidList.valueAt(index);
|
||||
if (existingSipper.getUid() >= Process.FIRST_SHARED_APPLICATION_GID &&
|
||||
existingSipper.getUid() <= Process.FIRST_SHARED_APPLICATION_GID) {
|
||||
// If the app already under this uid is a dex2oat run, then combine and
|
||||
// substitute it with the actual app.
|
||||
sipper.add(existingSipper);
|
||||
uidList.setValueAt(index, sipper);
|
||||
} else {
|
||||
// Combine BatterySippers if we already have one with this UID.
|
||||
final BatterySipper existingSipper = uidList.valueAt(index);
|
||||
existingSipper.add(sipper);
|
||||
if (existingSipper.packageWithHighestDrain == null
|
||||
&& sipper.packageWithHighestDrain != null) {
|
||||
existingSipper.packageWithHighestDrain = sipper.packageWithHighestDrain;
|
||||
}
|
||||
|
||||
final int existingPackageLen = existingSipper.mPackages != null ?
|
||||
existingSipper.mPackages.length : 0;
|
||||
final int newPackageLen = sipper.mPackages != null ?
|
||||
sipper.mPackages.length : 0;
|
||||
if (newPackageLen > 0) {
|
||||
String[] newPackages = new String[existingPackageLen + newPackageLen];
|
||||
if (existingPackageLen > 0) {
|
||||
System.arraycopy(existingSipper.mPackages, 0, newPackages, 0,
|
||||
existingPackageLen);
|
||||
}
|
||||
System.arraycopy(sipper.mPackages, 0, newPackages, existingPackageLen,
|
||||
newPackageLen);
|
||||
existingSipper.mPackages = newPackages;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -355,6 +395,15 @@ public class PowerUsageSummary extends PowerUsageBase {
|
||||
sipper.packageWithHighestDrain = "dex2oat";
|
||||
stats.add(sipper);
|
||||
|
||||
sipper = new BatterySipper(DrainType.APP,
|
||||
new FakeUid(UserHandle.getSharedAppGid(Process.FIRST_APPLICATION_UID + 1)), 10.0f);
|
||||
sipper.packageWithHighestDrain = "dex2oat";
|
||||
stats.add(sipper);
|
||||
|
||||
sipper = new BatterySipper(DrainType.APP,
|
||||
new FakeUid(UserHandle.getSharedAppGid(Process.LOG_UID)), 9.0f);
|
||||
stats.add(sipper);
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user