diff options
author | 2017-01-03 19:31:36 +0000 | |
---|---|---|
committer | 2017-01-03 19:31:36 +0000 | |
commit | 1e1cdbead134b55301786c85e8fe5ec8776df061 (patch) | |
tree | 2ab52c731005c73f59aa8c322194f8bae07c1b45 | |
parent | e6b6653da899890f2e44071915d1fa0f851290e9 (diff) | |
parent | 4b80a4a3727f7f9fc45997fb6c1ac8e708a2bc65 (diff) |
Merge "Offer to measure disk stats using quotas." am: f8720b95be
am: 4b80a4a372
Change-Id: I2ab9a2bd2ff60cafea332998789ad947dda0140b
-rw-r--r-- | core/java/android/app/ContextImpl.java | 21 | ||||
-rw-r--r-- | core/java/android/os/Build.java | 6 | ||||
-rw-r--r-- | core/java/android/os/Process.java | 5 | ||||
-rw-r--r-- | core/java/android/os/UserHandle.java | 9 | ||||
-rw-r--r-- | services/core/java/com/android/server/EventLogTags.logtags | 3 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 9 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/Installer.java | 10 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 55 |
8 files changed, 96 insertions, 22 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 8f424676dbe5..857a361788d6 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -509,10 +509,23 @@ class ContextImpl extends Context { * Common-path handling of app data dir creation */ private static File ensurePrivateDirExists(File file) { + return ensurePrivateDirExists(file, 0771, -1); + } + + private static File ensurePrivateCacheDirExists(File file) { + final int gid = UserHandle.getCacheAppGid(Process.myUid()); + return ensurePrivateDirExists(file, 02771, gid); + } + + private static File ensurePrivateDirExists(File file, int mode, int gid) { if (!file.exists()) { + final String path = file.getAbsolutePath(); try { - Os.mkdir(file.getAbsolutePath(), 0771); - Os.chmod(file.getAbsolutePath(), 0771); + Os.mkdir(path, mode); + Os.chmod(path, mode); + if (gid != -1) { + Os.chown(path, -1, gid); + } } catch (ErrnoException e) { if (e.errno == OsConstants.EEXIST) { // We must have raced with someone; that's okay @@ -581,7 +594,7 @@ class ContextImpl extends Context { if (mCacheDir == null) { mCacheDir = new File(getDataDir(), "cache"); } - return ensurePrivateDirExists(mCacheDir); + return ensurePrivateCacheDirExists(mCacheDir); } } @@ -591,7 +604,7 @@ class ContextImpl extends Context { if (mCodeCacheDir == null) { mCodeCacheDir = new File(getDataDir(), "code_cache"); } - return ensurePrivateDirExists(mCodeCacheDir); + return ensurePrivateCacheDirExists(mCodeCacheDir); } } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 151239bed02b..f6edee0f78e7 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -783,7 +783,7 @@ public class Build { */ public static boolean isBuildConsistent() { // Don't care on eng builds. Incremental build may trigger false negative. - if ("eng".equals(TYPE)) return true; + if (IS_ENG) return true; final String system = SystemProperties.get("ro.build.fingerprint"); final String vendor = SystemProperties.get("ro.vendor.build.fingerprint"); @@ -847,6 +847,10 @@ public class Build { public static final boolean IS_DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1; + /** {@hide} */ + public static final boolean IS_ENG = + "eng".equals(getString("ro.build.type")); + /** * Specifies whether the permissions needed by a legacy app should be * reviewed before any of its components can run. A legacy app is one diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 9cd1a4246a58..d6688e3c00f7 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -184,6 +184,11 @@ public class Process { */ public static final int LAST_SHARED_APPLICATION_GID = 59999; + /** {@hide} */ + public static final int FIRST_APPLICATION_CACHE_GID = 20000; + /** {@hide} */ + public static final int LAST_APPLICATION_CACHE_GID = 29999; + /** * Standard priority of application threads. * Use with {@link #setThreadPriority(int)} and diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index b3f44536214b..535a05a9fcb1 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -213,6 +213,15 @@ public final class UserHandle implements Parcelable { } /** + * Returns the cache GID for a given UID or appId. + * @hide + */ + public static int getCacheAppGid(int id) { + return Process.FIRST_APPLICATION_CACHE_GID + (id % PER_USER_RANGE) + - Process.FIRST_APPLICATION_UID; + } + + /** * Generate a text representation of the uid, breaking out its individual * components -- user, app, isolated, etc. * @hide diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index 74ff41c13802..6296375525a4 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -154,7 +154,8 @@ option java_package com.android.server 3110 unknown_sources_enabled (value|1) # Package Manager critical info 3120 pm_critical_info (msg|3) - +# Disk usage stats for verifying quota correctness +3121 pm_package_stats (manual_time|2|3),(quota_time|2|3),(manual_data|2|2),(quota_data|2|2),(manual_cache|2|2),(quota_cache|2|2) # --------------------------- # WindowManagerService.java diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 9e7990d27328..0251a639bc4c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3730,13 +3730,14 @@ public final class ActivityManagerService extends ActivityManagerNative * resources like shared libraries and access user-wide resources */ if (ArrayUtils.isEmpty(permGids)) { - gids = new int[2]; + gids = new int[3]; } else { - gids = new int[permGids.length + 2]; - System.arraycopy(permGids, 0, gids, 2, permGids.length); + gids = new int[permGids.length + 3]; + System.arraycopy(permGids, 0, gids, 3, permGids.length); } gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid)); - gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid)); + gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid)); + gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid)); } checkTime(startTime, "startProcess: building args"); if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) { diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 1f83d9e9230d..605fa5d8d0c3 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -54,6 +54,7 @@ public class Installer extends SystemService { // NOTE: keep in sync with installd public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8; public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9; + public static final int FLAG_USE_QUOTA = 1 << 12; private final boolean mIsolated; @@ -198,12 +199,13 @@ public class Installer extends SystemService { } } - public void getAppSize(String uuid, String packageName, int userId, int flags, long ceDataInode, - String codePath, PackageStats stats) throws InstallerException { + public void getAppSize(String uuid, String packageName, int userId, int flags, int appId, + long ceDataInode, String codePath, String externalUuid, PackageStats stats) + throws InstallerException { if (!checkBeforeRemote()) return; try { - final long[] res = mInstalld.getAppSize(uuid, packageName, userId, flags, ceDataInode, - codePath); + final long[] res = mInstalld.getAppSize(uuid, packageName, userId, flags, appId, + ceDataInode, codePath, externalUuid); stats.codeSize += res[0]; stats.dataSize += res[1]; stats.cacheSize += res[2]; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index ef3484cf3e79..79845905010c 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -370,6 +370,9 @@ public class PackageManagerService extends IPackageManager.Stub { private static final boolean DISABLE_EPHEMERAL_APPS = false; private static final boolean HIDE_EPHEMERAL_APIS = true; + private static final boolean ENABLE_QUOTA = + SystemProperties.getBoolean("persist.fw.quota", false); + private static final int RADIO_UID = Process.PHONE_UID; private static final int LOG_UID = Process.LOG_UID; private static final int NFC_UID = Process.NFC_UID; @@ -16893,6 +16896,11 @@ public class PackageManagerService extends IPackageManager.Stub { mHandler.sendMessage(msg); } + private boolean equals(PackageStats a, PackageStats b) { + return (a.codeSize == b.codeSize) && (a.dataSize == b.dataSize) + && (a.cacheSize == b.cacheSize); + } + private boolean getPackageSizeInfoLI(String packageName, int userId, PackageStats stats) { final PackageSetting ps; synchronized (mPackages) { @@ -16902,20 +16910,51 @@ public class PackageManagerService extends IPackageManager.Stub { return false; } } + + final long ceDataInode = ps.getCeDataInode(userId); + final PackageStats quotaStats = new PackageStats(stats.packageName, stats.userHandle); + + final StorageManager storage = mContext.getSystemService(StorageManager.class); + final String externalUuid = storage.getPrimaryStorageUuid(); try { - mInstaller.getAppSize(ps.volumeUuid, packageName, userId, - StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE, - ps.getCeDataInode(userId), ps.codePathString, stats); + final long start = SystemClock.elapsedRealtimeNanos(); + mInstaller.getAppSize(ps.volumeUuid, packageName, userId, 0, + ps.appId, ceDataInode, ps.codePathString, externalUuid, stats); + final long stopManual = SystemClock.elapsedRealtimeNanos(); + if (ENABLE_QUOTA) { + mInstaller.getAppSize(ps.volumeUuid, packageName, userId, Installer.FLAG_USE_QUOTA, + ps.appId, ceDataInode, ps.codePathString, externalUuid, quotaStats); + } + final long stopQuota = SystemClock.elapsedRealtimeNanos(); + + // For now, ignore code size of packages on system partition + if (isSystemApp(ps) && !isUpdatedSystemApp(ps)) { + stats.codeSize = 0; + quotaStats.codeSize = 0; + } + + if (ENABLE_QUOTA && Build.IS_ENG && !ps.isSharedUser()) { + if (!equals(stats, quotaStats)) { + Log.w(TAG, "Found discrepancy between statistics:"); + Log.w(TAG, "Manual: " + stats); + Log.w(TAG, "Quota: " + quotaStats); + } + final long manualTime = stopManual - start; + final long quotaTime = stopQuota - stopManual; + EventLogTags.writePmPackageStats(manualTime, quotaTime, + stats.dataSize, quotaStats.dataSize, + stats.cacheSize, quotaStats.cacheSize); + } + + // External clients expect these to be tracked separately + stats.dataSize -= stats.cacheSize; + quotaStats.dataSize -= quotaStats.cacheSize; + } catch (InstallerException e) { Slog.w(TAG, String.valueOf(e)); return false; } - // For now, ignore code size of packages on system partition - if (isSystemApp(ps) && !isUpdatedSystemApp(ps)) { - stats.codeSize = 0; - } - return true; } |