From 771cc344c65894405b05da1a22ffd57ae915d819 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 19 Feb 2020 23:26:56 +0100 Subject: Implement quota calculation for project ID based quota. Devices launching with R will no longer have the sdcardfs filesystem; instead, quota tracking on external storage is implemented by project IDs. Switch over the existing quota calculation to use project IDs when sdcardfs is not available. Bug: 146419093 Test: atest StorageHostTest (on devices with and without sdcardfs) Change-Id: I17925c811b08c7c85fff02ee6e279e4d7586e3ff --- cmds/installd/InstalldNativeService.cpp | 190 ++++++++++++++++++++++++-------- 1 file changed, 144 insertions(+), 46 deletions(-) (limited to 'cmds/installd/InstalldNativeService.cpp') diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 737c6c9582..d8d324aa58 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -53,6 +53,7 @@ #include // TODO: Move everything to base/logging. #include #include +#include #include #include #include @@ -1474,8 +1475,8 @@ static std::string toString(std::vector values) { static void collectQuotaStats(const std::string& uuid, int32_t userId, int32_t appId, struct stats* stats, struct stats* extStats) { int64_t space; + uid_t uid = multiuser_get_uid(userId, appId); if (stats != nullptr) { - uid_t uid = multiuser_get_uid(userId, appId); if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) { stats->dataSize += space; } @@ -1496,20 +1497,44 @@ static void collectQuotaStats(const std::string& uuid, int32_t userId, } if (extStats != nullptr) { - int extGid = multiuser_get_ext_gid(userId, appId); - if (extGid != -1) { - if ((space = GetOccupiedSpaceForGid(uuid, extGid)) != -1) { - extStats->dataSize += space; + static const bool supportsSdCardFs = supports_sdcardfs(); + space = get_occupied_app_space_external(uuid, userId, appId); + + if (space != -1) { + extStats->dataSize += space; + if (!supportsSdCardFs && stats != nullptr) { + // On devices without sdcardfs, if internal and external are on + // the same volume, a uid such as u0_a123 is used for + // application dirs on both internal and external storage; + // therefore, substract that amount from internal to make sure + // we don't count it double. + stats->dataSize -= space; } } - int extCacheGid = multiuser_get_ext_cache_gid(userId, appId); - if (extCacheGid != -1) { - if ((space = GetOccupiedSpaceForGid(uuid, extCacheGid)) != -1) { - extStats->dataSize += space; - extStats->cacheSize += space; + space = get_occupied_app_cache_space_external(uuid, userId, appId); + if (space != -1) { + extStats->dataSize += space; // cache counts for "data" + extStats->cacheSize += space; + if (!supportsSdCardFs && stats != nullptr) { + // On devices without sdcardfs, if internal and external are on + // the same volume, a uid such as u0_a123 is used for both + // internal and external storage; therefore, substract that + // amount from internal to make sure we don't count it double. + stats->dataSize -= space; } } + + if (!supportsSdCardFs && stats != nullptr) { + // On devices without sdcardfs, the UID of OBBs on external storage + // matches the regular app UID (eg u0_a123); therefore, to avoid + // OBBs being include in stats->dataSize, compute the OBB size for + // this app, and substract it from the size reported on internal + // storage + long obbProjectId = uid - AID_APP_START + PROJECT_ID_EXT_OBB_START; + int64_t appObbSize = GetOccupiedSpaceForProjectId(uuid, obbProjectId); + stats->dataSize -= appObbSize; + } } } @@ -1758,6 +1783,106 @@ binder::Status InstalldNativeService::getAppSize(const std::unique_ptr& appIds) { + struct external_sizes sizes = {}; + int64_t space; + + if (supports_sdcardfs()) { + uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW); + if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) { + sizes.totalSize = space; + } + + gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO); + if ((space = GetOccupiedSpaceForGid(uuid, audioGid)) != -1) { + sizes.audioSize = space; + } + + gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO); + if ((space = GetOccupiedSpaceForGid(uuid, videoGid)) != -1) { + sizes.videoSize = space; + } + + gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE); + if ((space = GetOccupiedSpaceForGid(uuid, imageGid)) != -1) { + sizes.imageSize = space; + } + + if ((space = GetOccupiedSpaceForGid(uuid, AID_MEDIA_OBB)) != -1) { + sizes.obbSize = space; + } + } else { + int64_t totalSize = 0; + long defaultProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_DEFAULT); + if ((space = GetOccupiedSpaceForProjectId(uuid, defaultProjectId)) != -1) { + // This is all files that are not audio/video/images, excluding + // OBBs and app-private data + totalSize += space; + } + + long audioProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_AUDIO); + if ((space = GetOccupiedSpaceForProjectId(uuid, audioProjectId)) != -1) { + sizes.audioSize = space; + totalSize += space; + } + + long videoProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_VIDEO); + if ((space = GetOccupiedSpaceForProjectId(uuid, videoProjectId)) != -1) { + sizes.videoSize = space; + totalSize += space; + } + + long imageProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_IMAGE); + if ((space = GetOccupiedSpaceForProjectId(uuid, imageProjectId)) != -1) { + sizes.imageSize = space; + totalSize += space; + } + + int64_t totalAppDataSize = 0; + int64_t totalAppCacheSize = 0; + int64_t totalAppObbSize = 0; + for (auto appId : appIds) { + if (appId >= AID_APP_START) { + // App data + uid_t uid = multiuser_get_uid(userId, appId); + long projectId = uid - AID_APP_START + PROJECT_ID_EXT_DATA_START; + totalAppDataSize += GetOccupiedSpaceForProjectId(uuid, projectId); + + // App cache + long cacheProjectId = uid - AID_APP_START + PROJECT_ID_EXT_CACHE_START; + totalAppCacheSize += GetOccupiedSpaceForProjectId(uuid, cacheProjectId); + + // App OBBs + long obbProjectId = uid - AID_APP_START + PROJECT_ID_EXT_OBB_START; + totalAppObbSize += GetOccupiedSpaceForProjectId(uuid, obbProjectId); + } + } + // Total size should include app data + cache + totalSize += totalAppDataSize; + totalSize += totalAppCacheSize; + sizes.totalSize = totalSize; + + // Only OBB is separate + sizes.obbSize = totalAppObbSize; + } + + return sizes; +} + binder::Status InstalldNativeService::getUserSize(const std::unique_ptr& uuid, int32_t userId, int32_t flags, const std::vector& appIds, std::vector* _aidl_return) { @@ -1786,14 +1911,6 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr= AID_APP_START) { collectQuotaStats(uuidString, userId, appId, &stats, &extStats); - #if MEASURE_DEBUG // Sleep to make sure we don't lose logs usleep(1); @@ -1931,29 +2045,13 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr