Merge "BatteryStats: Fix coalescing of shared app GIDs and system UIDs" into mnc-dev

This commit is contained in:
Adam Lesinski
2015-08-14 19:38:34 +00:00
committed by Android (Google) Code Review
2 changed files with 133 additions and 87 deletions

View File

@@ -24,7 +24,6 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.BatteryStats;
import android.os.Handler; import android.os.Handler;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
@@ -191,7 +190,7 @@ public class BatteryEntry {
icon = context.getDrawable(iconId); icon = context.getDrawable(iconId);
} }
if ((name == null || iconId == 0) && this.sipper.uidObj != null) { 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; return name;
} }
void getQuickNameIconForUid(BatteryStats.Uid uidObj) { void getQuickNameIconForUid(final int uid) {
final int uid = uidObj.getUid();
final String uidString = Integer.toString(uid); final String uidString = Integer.toString(uid);
if (sUidCache.containsKey(uidString)) { if (sUidCache.containsKey(uidString)) {
UidToDetail utd = sUidCache.get(uidString); UidToDetail utd = sUidCache.get(uidString);
@@ -217,10 +215,8 @@ public class BatteryEntry {
return; return;
} }
PackageManager pm = context.getPackageManager(); PackageManager pm = context.getPackageManager();
String[] packages = pm.getPackagesForUid(uid);
icon = pm.getDefaultActivityIcon(); icon = pm.getDefaultActivityIcon();
if (packages == null) { if (pm.getPackagesForUid(uid) == null) {
//name = Integer.toString(uid);
if (uid == 0) { if (uid == 0) {
name = context.getResources().getString(R.string.process_kernel_label); name = context.getResources().getString(R.string.process_kernel_label);
} else if ("mediaserver".equals(name)) { } else if ("mediaserver".equals(name)) {
@@ -230,10 +226,8 @@ public class BatteryEntry {
} }
iconId = R.drawable.ic_power_system; iconId = R.drawable.ic_power_system;
icon = context.getDrawable(iconId); icon = context.getDrawable(iconId);
return;
} else {
//name = packages[0];
} }
if (sHandler != null) { if (sHandler != null) {
synchronized (mRequestQueue) { synchronized (mRequestQueue) {
mRequestQueue.add(this); mRequestQueue.add(this);
@@ -249,79 +243,82 @@ public class BatteryEntry {
if (sipper.uidObj == null) { if (sipper.uidObj == null) {
return; return;
} }
PackageManager pm = context.getPackageManager(); PackageManager pm = context.getPackageManager();
final int uid = sipper.uidObj.getUid(); final int uid = sipper.uidObj.getUid();
final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
sipper.mPackages = pm.getPackagesForUid(uid); sipper.mPackages = pm.getPackagesForUid(uid);
if (sipper.mPackages == null) { if (sipper.mPackages != null) {
name = Integer.toString(uid); String[] packageLabels = new String[sipper.mPackages.length];
return; System.arraycopy(sipper.mPackages, 0, packageLabels, 0, sipper.mPackages.length);
}
String[] packageLabels = new String[sipper.mPackages.length]; // Convert package names to user-facing labels where possible
System.arraycopy(sipper.mPackages, 0, packageLabels, 0, sipper.mPackages.length); IPackageManager ipm = AppGlobals.getPackageManager();
final int userId = UserHandle.getUserId(uid);
// Convert package names to user-facing labels where possible for (int i = 0; i < packageLabels.length; i++) {
IPackageManager ipm = AppGlobals.getPackageManager();
final int userId = UserHandle.getUserId(uid);
for (int i = 0; i < packageLabels.length; i++) {
try {
final ApplicationInfo ai = ipm.getApplicationInfo(packageLabels[i],
0 /* no flags */, userId);
if (ai == null) {
Log.d(PowerUsageSummary.TAG, "Retrieving null app info for package "
+ packageLabels[i] + ", user " + userId);
continue;
}
CharSequence label = ai.loadLabel(pm);
if (label != null) {
packageLabels[i] = label.toString();
}
if (ai.icon != 0) {
defaultPackageName = sipper.mPackages[i];
icon = ai.loadIcon(pm);
break;
}
} catch (RemoteException e) {
Log.d(PowerUsageSummary.TAG, "Error while retrieving app info for package "
+ packageLabels[i] + ", user " + userId, e);
}
}
if (icon == null) {
icon = defaultActivityIcon;
}
if (packageLabels.length == 1) {
name = packageLabels[0];
} else {
// Look for an official name for this UID.
for (String pkgName : sipper.mPackages) {
try { try {
final PackageInfo pi = ipm.getPackageInfo(pkgName, 0 /* no flags */, userId); final ApplicationInfo ai = ipm.getApplicationInfo(packageLabels[i],
if (pi == null) { 0 /* no flags */, userId);
Log.d(PowerUsageSummary.TAG, "Retrieving null package info for package " if (ai == null) {
+ pkgName + ", user " + userId); Log.d(PowerUsageSummary.TAG, "Retrieving null app info for package "
+ packageLabels[i] + ", user " + userId);
continue; continue;
} }
if (pi.sharedUserLabel != 0) { CharSequence label = ai.loadLabel(pm);
final CharSequence nm = pm.getText(pkgName, if (label != null) {
pi.sharedUserLabel, pi.applicationInfo); packageLabels[i] = label.toString();
if (nm != null) { }
name = nm.toString(); if (ai.icon != 0) {
if (pi.applicationInfo.icon != 0) { defaultPackageName = sipper.mPackages[i];
defaultPackageName = pkgName; icon = ai.loadIcon(pm);
icon = pi.applicationInfo.loadIcon(pm); break;
}
break;
}
} }
} catch (RemoteException e) { } catch (RemoteException e) {
Log.d(PowerUsageSummary.TAG, "Error while retrieving package info for package " Log.d(PowerUsageSummary.TAG, "Error while retrieving app info for package "
+ pkgName + ", user " + userId, e); + packageLabels[i] + ", user " + userId, e);
}
}
if (packageLabels.length == 1) {
name = packageLabels[0];
} else {
// Look for an official name for this UID.
for (String pkgName : sipper.mPackages) {
try {
final PackageInfo pi = ipm.getPackageInfo(pkgName, 0 /* no flags */, userId);
if (pi == null) {
Log.d(PowerUsageSummary.TAG, "Retrieving null package info for package "
+ pkgName + ", user " + userId);
continue;
}
if (pi.sharedUserLabel != 0) {
final CharSequence nm = pm.getText(pkgName,
pi.sharedUserLabel, pi.applicationInfo);
if (nm != null) {
name = nm.toString();
if (pi.applicationInfo.icon != 0) {
defaultPackageName = pkgName;
icon = pi.applicationInfo.loadIcon(pm);
}
break;
}
}
} catch (RemoteException e) {
Log.d(PowerUsageSummary.TAG, "Error while retrieving package info for package "
+ pkgName + ", user " + userId, e);
}
} }
} }
} }
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(); UidToDetail utd = new UidToDetail();
utd.name = name; utd.name = name;
utd.icon = icon; utd.icon = icon;

View File

@@ -76,7 +76,7 @@ public class PowerUsageSummary extends PowerUsageBase {
private int mStatsType = BatteryStats.STATS_SINCE_CHARGED; private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
private static final int MIN_POWER_THRESHOLD_MILLI_AMP = 5; 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 MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
private static final int SECONDS_IN_HOUR = 60 * 60; private static final int SECONDS_IN_HOUR = 60 * 60;
@@ -181,11 +181,19 @@ public class PowerUsageSummary extends PowerUsageBase {
mAppListGroup.addPreference(notAvailable); 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 * 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 * 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. * 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) { private static List<BatterySipper> getCoalescedUsageList(final List<BatterySipper> sippers) {
final SparseArray<BatterySipper> uidList = new SparseArray<>(); final SparseArray<BatterySipper> uidList = new SparseArray<>();
@@ -193,30 +201,62 @@ public class PowerUsageSummary extends PowerUsageBase {
final ArrayList<BatterySipper> results = new ArrayList<>(); final ArrayList<BatterySipper> results = new ArrayList<>();
final int numSippers = sippers.size(); final int numSippers = sippers.size();
for (int i = 0; i < numSippers; i++) { for (int i = 0; i < numSippers; i++) {
final BatterySipper sipper = sippers.get(i); BatterySipper sipper = sippers.get(i);
if (sipper.getUid() > 0) { if (sipper.getUid() > 0) {
int realUid = sipper.getUid(); int realUid = sipper.getUid();
if (sipper.getUid() >= Process.FIRST_SHARED_APPLICATION_GID &&
sipper.getUid() <= Process.LAST_SHARED_APPLICATION_GID) { // Check if this UID is a shared GID. If so, we combine it with the OWNER's
// This is a shared gid being used to do work on behalf of an app across all // actual app UID.
// users. But we'll blame the power on the device OWNER. if (isSharedGid(sipper.getUid())) {
realUid = UserHandle.getUid(UserHandle.USER_OWNER, realUid = UserHandle.getUid(UserHandle.USER_OWNER,
UserHandle.getAppIdFromSharedAppGid(sipper.getUid())); 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); int index = uidList.indexOfKey(realUid);
if (index < 0) { if (index < 0) {
// New entry.
uidList.put(realUid, sipper); uidList.put(realUid, sipper);
} else { } else {
BatterySipper existingSipper = uidList.valueAt(index); // Combine BatterySippers if we already have one with this UID.
if (existingSipper.getUid() >= Process.FIRST_SHARED_APPLICATION_GID && final BatterySipper existingSipper = uidList.valueAt(index);
existingSipper.getUid() <= Process.FIRST_SHARED_APPLICATION_GID) { existingSipper.add(sipper);
// If the app already under this uid is a dex2oat run, then combine and if (existingSipper.packageWithHighestDrain == null
// substitute it with the actual app. && sipper.packageWithHighestDrain != null) {
sipper.add(existingSipper); existingSipper.packageWithHighestDrain = sipper.packageWithHighestDrain;
uidList.setValueAt(index, sipper); }
} else {
existingSipper.add(sipper); 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 { } else {
@@ -355,6 +395,15 @@ public class PowerUsageSummary extends PowerUsageBase {
sipper.packageWithHighestDrain = "dex2oat"; sipper.packageWithHighestDrain = "dex2oat";
stats.add(sipper); 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; return stats;
} }