Merge "BatteryStats: Fix coalescing of shared app GIDs and system UIDs" into mnc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
3cc05c9d7e
@@ -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,79 +243,82 @@ 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);
|
||||
|
||||
String[] packageLabels = new String[sipper.mPackages.length];
|
||||
System.arraycopy(sipper.mPackages, 0, packageLabels, 0, sipper.mPackages.length);
|
||||
|
||||
// Convert package names to user-facing labels where possible
|
||||
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) {
|
||||
// Convert package names to user-facing labels where possible
|
||||
IPackageManager ipm = AppGlobals.getPackageManager();
|
||||
final int userId = UserHandle.getUserId(uid);
|
||||
for (int i = 0; i < packageLabels.length; i++) {
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 package info for package "
|
||||
+ pkgName + ", user " + userId, e);
|
||||
Log.d(PowerUsageSummary.TAG, "Error while retrieving app info for package "
|
||||
+ 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();
|
||||
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 {
|
||||
existingSipper.add(sipper);
|
||||
// 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