Merge "Fix code accounting bugs, track external app data." into oc-dev

This commit is contained in:
Jeff Sharkey
2017-04-21 20:01:36 +00:00
committed by Android (Google) Code Review
10 changed files with 90 additions and 36 deletions

View File

@@ -6925,6 +6925,7 @@ package android.app.usage {
public final class ExternalStorageStats implements android.os.Parcelable {
method public int describeContents();
method public long getAppBytes();
method public long getAudioBytes();
method public long getImageBytes();
method public long getTotalBytes();

View File

@@ -7390,6 +7390,7 @@ package android.app.usage {
public final class ExternalStorageStats implements android.os.Parcelable {
method public int describeContents();
method public long getAppBytes();
method public long getAudioBytes();
method public long getImageBytes();
method public long getTotalBytes();

View File

@@ -6955,6 +6955,7 @@ package android.app.usage {
public final class ExternalStorageStats implements android.os.Parcelable {
method public int describeContents();
method public long getAppBytes();
method public long getAudioBytes();
method public long getImageBytes();
method public long getTotalBytes();

View File

@@ -31,6 +31,7 @@ public final class ExternalStorageStats implements Parcelable {
/** {@hide} */ public long audioBytes;
/** {@hide} */ public long videoBytes;
/** {@hide} */ public long imageBytes;
/** {@hide} */ public long appBytes;
/**
* Return the total bytes used by all files in the shared/external storage
@@ -64,6 +65,17 @@ public final class ExternalStorageStats implements Parcelable {
return imageBytes;
}
/**
* Return the total bytes used by app files in the shared/external storage
* hosted on this volume.
* <p>
* This data is already accounted against individual apps as returned
* through {@link StorageStats}.
*/
public long getAppBytes() {
return appBytes;
}
/** {@hide} */
public ExternalStorageStats() {
}
@@ -74,6 +86,7 @@ public final class ExternalStorageStats implements Parcelable {
this.audioBytes = in.readLong();
this.videoBytes = in.readLong();
this.imageBytes = in.readLong();
this.appBytes = in.readLong();
}
@Override
@@ -87,6 +100,7 @@ public final class ExternalStorageStats implements Parcelable {
dest.writeLong(audioBytes);
dest.writeLong(videoBytes);
dest.writeLong(imageBytes);
dest.writeLong(appBytes);
}
public static final Creator<ExternalStorageStats> CREATOR = new Creator<ExternalStorageStats>() {

View File

@@ -22,12 +22,8 @@ import android.os.Parcelable;
import android.os.UserHandle;
/**
* Storage statistics for a UID or {@link UserHandle} on a single storage
* volume.
* <p class="note">
* Note: multiple packages using the same {@code sharedUserId} in their manifest
* will be merged into a single UID.
* </p>
* Storage statistics for a UID, package, or {@link UserHandle} on a single
* storage volume.
*
* @see StorageStatsManager
*/
@@ -40,6 +36,9 @@ public final class StorageStats implements Parcelable {
* Return the size of all code. This includes {@code APK} files and
* optimized compiler output.
* <p>
* If the primary external/shared storage is hosted on this storage device,
* then this includes files stored under {@link Context#getObbDir()}.
* <p>
* Code is shared between all users on a multiuser device.
*/
public long getCodeBytes() {
@@ -51,6 +50,12 @@ public final class StorageStats implements Parcelable {
* {@link Context#getDataDir()}, {@link Context#getCacheDir()},
* {@link Context#getCodeCacheDir()}.
* <p>
* If the primary external/shared storage is hosted on this storage device,
* then this includes files stored under
* {@link Context#getExternalFilesDir(String)},
* {@link Context#getExternalCacheDir()}, and
* {@link Context#getExternalMediaDirs()}.
* <p>
* Data is isolated for each user on a multiuser device.
*/
public long getDataBytes() {
@@ -61,6 +66,10 @@ public final class StorageStats implements Parcelable {
* Return the size of all cached data. This includes files stored under
* {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}.
* <p>
* If the primary external/shared storage is hosted on this storage device,
* then this includes files stored under
* {@link Context#getExternalCacheDir()}.
* <p>
* Cached data is isolated for each user on a multiuser device.
*/
public long getCacheBytes() {

View File

@@ -73,7 +73,8 @@ public class StorageStatsManager {
}
/**
* Return the total size of the media hosting this storage volume.
* Return the total size of the underlying media that is hosting this
* storage volume.
* <p>
* To reduce end user confusion, this value matches the total storage size
* advertised in a retail environment, which is typically larger than the

View File

@@ -730,7 +730,7 @@ public class StorageManager {
*/
public @NonNull UUID getUuidForPath(@NonNull File path) throws IOException {
Preconditions.checkNotNull(path);
final String pathString = path.getAbsolutePath();
final String pathString = path.getCanonicalPath();
if (FileUtils.contains(Environment.getDataDirectory().getAbsolutePath(), pathString)) {
return UUID_DEFAULT;
}

View File

@@ -258,10 +258,11 @@ public class Installer extends SystemService {
}
}
public long[] getExternalSize(String uuid, int userId, int flags) throws InstallerException {
public long[] getExternalSize(String uuid, int userId, int flags, int[] appIds)
throws InstallerException {
if (!checkBeforeRemote()) return new long[4];
try {
return mInstalld.getExternalSize(uuid, userId, flags);
return mInstalld.getExternalSize(uuid, userId, flags, appIds);
} catch (Exception e) {
throw InstallerException.from(e);
}

View File

@@ -120,15 +120,7 @@ public class InstallerTest extends AndroidTestCase {
}
public void testGetUserSize() throws Exception {
int[] appIds = null;
final PackageManager pm = getContext().getPackageManager();
for (ApplicationInfo app : pm.getInstalledApplications(0)) {
final int appId = UserHandle.getAppId(app.uid);
if (!ArrayUtils.contains(appIds, appId)) {
appIds = ArrayUtils.appendInt(appIds, appId);
}
}
final int[] appIds = getAppIds(UserHandle.USER_SYSTEM);
final PackageStats stats = new PackageStats("android");
final PackageStats quotaStats = new PackageStats("android");
@@ -147,13 +139,15 @@ public class InstallerTest extends AndroidTestCase {
}
public void testGetExternalSize() throws Exception {
final int[] appIds = getAppIds(UserHandle.USER_SYSTEM);
mManual.start();
final long[] stats = mInstaller.getExternalSize(null, UserHandle.USER_SYSTEM, 0);
final long[] stats = mInstaller.getExternalSize(null, UserHandle.USER_SYSTEM, 0, appIds);
mManual.stop();
mQuota.start();
final long[] quotaStats = mInstaller.getExternalSize(null, UserHandle.USER_SYSTEM,
Installer.FLAG_USE_QUOTA);
Installer.FLAG_USE_QUOTA, appIds);
mQuota.stop();
for (int i = 0; i < stats.length; i++) {
@@ -161,6 +155,18 @@ public class InstallerTest extends AndroidTestCase {
}
}
private int[] getAppIds(int userId) {
int[] appIds = null;
for (ApplicationInfo app : getContext().getPackageManager().getInstalledApplicationsAsUser(
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId)) {
final int appId = UserHandle.getAppId(app.uid);
if (!ArrayUtils.contains(appIds, appId)) {
appIds = ArrayUtils.appendInt(appIds, appId);
}
}
return appIds;
}
private static void checkEquals(String msg, PackageStats a, PackageStats b) {
checkEquals(msg + " codeSize", a.codeSize, b.codeSize);
checkEquals(msg + " dataSize", a.dataSize, b.dataSize);

View File

@@ -235,7 +235,14 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
final int appId = UserHandle.getUserId(appInfo.uid);
final String[] packageNames = new String[] { packageName };
final long[] ceDataInodes = new long[1];
final String[] codePaths = new String[] { appInfo.getCodePath() };
String[] codePaths = new String[0];
if (appInfo.isSystemApp() && !appInfo.isUpdatedSystemApp()) {
// We don't count code baked into system image
} else {
codePaths = ArrayUtils.appendElement(String.class, codePaths,
appInfo.getCodePath());
}
final PackageStats stats = new PackageStats(TAG);
try {
@@ -261,12 +268,18 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
final String[] packageNames = mPackage.getPackagesForUid(uid);
final long[] ceDataInodes = new long[packageNames.length];
final String[] codePaths = new String[packageNames.length];
String[] codePaths = new String[0];
for (int i = 0; i < packageNames.length; i++) {
try {
codePaths[i] = mPackage.getApplicationInfoAsUser(packageNames[i],
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId).getCodePath();
final ApplicationInfo appInfo = mPackage.getApplicationInfoAsUser(packageNames[i],
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
if (appInfo.isSystemApp() && !appInfo.isUpdatedSystemApp()) {
// We don't count code baked into system image
} else {
codePaths = ArrayUtils.appendElement(String.class, codePaths,
appInfo.getCodePath());
}
} catch (NameNotFoundException e) {
throw new ParcelableException(e);
}
@@ -297,15 +310,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
android.Manifest.permission.INTERACT_ACROSS_USERS, TAG);
}
int[] appIds = null;
for (ApplicationInfo app : mPackage.getInstalledApplicationsAsUser(
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId)) {
final int appId = UserHandle.getAppId(app.uid);
if (!ArrayUtils.contains(appIds, appId)) {
appIds = ArrayUtils.appendInt(appIds, appId);
}
}
final int[] appIds = getAppIds(userId);
final PackageStats stats = new PackageStats(TAG);
try {
mInstaller.getUserSize(volumeUuid, userId, getDefaultFlags(), appIds, stats);
@@ -330,12 +335,14 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
android.Manifest.permission.INTERACT_ACROSS_USERS, TAG);
}
final int[] appIds = getAppIds(userId);
final long[] stats;
try {
stats = mInstaller.getExternalSize(volumeUuid, userId, getDefaultFlags());
stats = mInstaller.getExternalSize(volumeUuid, userId, getDefaultFlags(), appIds);
if (SystemProperties.getBoolean(PROP_VERIFY_STORAGE, false)) {
final long[] manualStats = mInstaller.getExternalSize(volumeUuid, userId, 0);
final long[] manualStats = mInstaller.getExternalSize(volumeUuid, userId, 0,
appIds);
checkEquals("External " + userId, manualStats, stats);
}
} catch (InstallerException e) {
@@ -347,9 +354,22 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
res.audioBytes = stats[1];
res.videoBytes = stats[2];
res.imageBytes = stats[3];
res.appBytes = stats[4];
return res;
}
private int[] getAppIds(int userId) {
int[] appIds = null;
for (ApplicationInfo app : mPackage.getInstalledApplicationsAsUser(
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId)) {
final int appId = UserHandle.getAppId(app.uid);
if (!ArrayUtils.contains(appIds, appId)) {
appIds = ArrayUtils.appendInt(appIds, appId);
}
}
return appIds;
}
private static int getDefaultFlags() {
if (SystemProperties.getBoolean(PROP_DISABLE_QUOTA, false)) {
return 0;