diff options
author | 2019-11-20 14:20:40 +0800 | |
---|---|---|
committer | 2019-12-18 14:13:26 +0800 | |
commit | 2a0a246603f9fe167d6f868667538d86092d8856 (patch) | |
tree | 29fc63375403f1102d82c00c23712ed95353d476 | |
parent | 1730b0be85f5005ffef0e9f2a68727045b039218 (diff) |
add function to traversal the crates
The system_server needs to traversal Context.getCratesDir() to get all
of crates. But, system_server doesn't have the permission. system_server
needs installd to traverse Context.getCratesDir().
The depth of traversal in Context.getCratesDir is 1. installd returns the
list CrateMetadata. CrateMetadata contains the following information.
* crateName: it is the folder name
To add .gitigTo add .gitignore to collect the ignore file list.
Test: atest \
CtsOsTestCases:android.os.storage.cts.CrateInfoTest \
CtsOsTestCases:android.os.storage.cts.StorageManagerCratesTest \
CtsOsTestCases:android.os.storage.cts.StorageStatsManagerTest
Bug: 141660526
Change-Id: Iea5eee4606e4ff437edef617a1f8db93e37f51c4
-rw-r--r-- | cmds/installd/.gitignore | 2 | ||||
-rw-r--r-- | cmds/installd/Android.bp | 2 | ||||
-rw-r--r-- | cmds/installd/CrateManager.cpp | 129 | ||||
-rw-r--r-- | cmds/installd/CrateManager.h | 82 | ||||
-rw-r--r-- | cmds/installd/InstalldNativeService.cpp | 77 | ||||
-rw-r--r-- | cmds/installd/InstalldNativeService.h | 10 | ||||
-rw-r--r-- | cmds/installd/binder/android/os/IInstalld.aidl | 8 | ||||
-rw-r--r-- | cmds/installd/binder/android/os/storage/CrateMetadata.aidl | 41 | ||||
-rw-r--r-- | cmds/installd/utils.cpp | 9 | ||||
-rw-r--r-- | cmds/installd/utils.h | 4 |
10 files changed, 364 insertions, 0 deletions
diff --git a/cmds/installd/.gitignore b/cmds/installd/.gitignore new file mode 100644 index 0000000000..abc921ce64 --- /dev/null +++ b/cmds/installd/.gitignore @@ -0,0 +1,2 @@ +# ignore the files generated by intellij +.idea diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp index 75dec371bc..8ff4dd862d 100644 --- a/cmds/installd/Android.bp +++ b/cmds/installd/Android.bp @@ -13,6 +13,7 @@ cc_defaults { srcs: [ "CacheItem.cpp", "CacheTracker.cpp", + "CrateManager.cpp", "InstalldNativeService.cpp", "QuotaUtils.cpp", "dexopt.cpp", @@ -163,6 +164,7 @@ filegroup { name: "installd_aidl", srcs: [ "binder/android/os/IInstalld.aidl", + "binder/android/os/storage/CrateMetadata.aidl", ], path: "binder", } diff --git a/cmds/installd/CrateManager.cpp b/cmds/installd/CrateManager.cpp new file mode 100644 index 0000000000..344aefbcbe --- /dev/null +++ b/cmds/installd/CrateManager.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CrateManager.h" + +#include <android-base/logging.h> +#include <android-base/stringprintf.h> +#include <android/log.h> +#include <errno.h> +#include <inttypes.h> +#include <libgen.h> +#include <stdint.h> +#include <string.h> +#include <sys/xattr.h> +#include <unistd.h> + +#include <fstream> +#include <string> +#include <utils.h> + +#include "utils.h" + +using android::base::StringPrintf; + +namespace android { +namespace installd { + +CrateManager::CrateManager(const char* uuid, userid_t userId, const std::string& packageName) { + mPackageName = packageName; + mRoot = create_data_user_ce_package_path(uuid, userId, (const char*)packageName.c_str()); + mCratedFoldersRoot = StringPrintf("%s/crates", mRoot.c_str()); +} + +CrateManager::~CrateManager() {} + +static std::string getValidatedCratedPath(std::string path) { + size_t pos = path.rfind("/"); + if (pos == std::string::npos) { + return path; + } + + return path.substr(pos + 1, path.length()); +} + +void CrateManager::traverseChildDir(const std::string& targetDir, + std::function<void(FTSENT*)>& onVisitChildDir) { + char* argv[] = {(char*)targetDir.c_str(), nullptr}; + FTS* fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr); + if (fts == nullptr) { + PLOG(WARNING) << "Failed to fts_open " << targetDir; + return; + } + + FTSENT* p; + while ((p = fts_read(fts)) != nullptr) { + switch (p->fts_info) { + case FTS_D: + if (p->fts_level == 1) { + onVisitChildDir(p); + } + break; + default: + break; + } + + if (p->fts_level == 1) { + fts_set(fts, p, FTS_SKIP); + } + } + fts_close(fts); +} + +void CrateManager::traverseAllPackagesForUser( + const std::unique_ptr<std::string>& uuid, userid_t userId, + std::function<void(FTSENT*)>& onHandlingPackage) { + const char* uuid_ = uuid ? uuid->c_str() : nullptr; + + auto ce_path = create_data_user_ce_path(uuid_, userId); + traverseChildDir(ce_path, onHandlingPackage); +} + +void CrateManager::createCrate( + CratedFolder cratedFolder, + std::function<void(CratedFolder, std::unique_ptr<CrateMetadata>&)>& onCreateCrate) { + const char* path = cratedFolder->fts_path; + if (path == nullptr || *path == '\0') { + return; + } + + std::unique_ptr<CrateMetadata> crateMetadata = std::make_unique<CrateMetadata>(); + crateMetadata->uid = cratedFolder->fts_statp->st_uid; + crateMetadata->packageName = mPackageName; + crateMetadata->id = getValidatedCratedPath(path); + + onCreateCrate(cratedFolder, crateMetadata); +} + +void CrateManager::traverseAllCrates(std::function<void(CratedFolder, std::unique_ptr<CrateMetadata>&)>& onCreateCrate) { + std::function<void(FTSENT*)> onVisitCrateDir = [&](FTSENT* cratedFolder) -> void { + createCrate(cratedFolder, onCreateCrate); + }; + traverseChildDir(mCratedFoldersRoot, onVisitCrateDir); +} + +#if CRATE_DEBUG +void CrateManager::dump(std::unique_ptr<CrateMetadata>& CrateMetadata) { + LOG(DEBUG) << "CrateMetadata = {" + << "uid : \"" << CrateMetadata->uid + << "\", packageName : \"" << CrateMetadata->packageName + << "\", id : \"" << CrateMetadata->id + << "\"}"; +} +#endif + +} // namespace installd +} // namespace android diff --git a/cmds/installd/CrateManager.h b/cmds/installd/CrateManager.h new file mode 100644 index 0000000000..1776622d6a --- /dev/null +++ b/cmds/installd/CrateManager.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INSTALLD_CRATE_INFO_MANAGER_H +#define ANDROID_INSTALLD_CRATE_INFO_MANAGER_H + +#include <android/os/storage/CrateMetadata.h> +#include <cutils/multiuser.h> +#include <fts.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <memory> +#include <string> +#include <vector> + +#ifndef CRATE_DEBUG +#define CRATE_DEBUG 1 +#endif + +namespace android { +namespace installd { + +using android::os::storage::CrateMetadata; + +/** + * The crated folder actually is a folder that is the first level child director. In order to + * distingish between the crated folder and the other FTSENT*, to define the type "CratedFolder" + * make the code easy to identify the difference. + */ +typedef FTSENT* CratedFolder; + +/** + * In order to give the users more fine-grained files controlling, the crate information can help + * applications' developers to show the more detail information to the users. The crate information + * include the Label, Expiration etc.. + */ +class CrateManager { +public: + CrateManager(const char* uuid, userid_t userId, const std::string& packageName); + ~CrateManager(); + + void traverseAllCrates(std::function<void(CratedFolder, std::unique_ptr<CrateMetadata>&)>& onCreateCrate); + + static void traverseChildDir(const std::string& targetDir, + std::function<void(FTSENT*)>& onVisitChildDir); + + static void traverseAllPackagesForUser( + const std::unique_ptr<std::string>& uuid, + userid_t userId, + std::function<void(FTSENT*)>& onHandlingPackage); + +#if CRATE_DEBUG + static void dump(std::unique_ptr<CrateMetadata>& CrateMetadata); +#endif +private: + std::string mRoot; + std::string mCratedFoldersRoot; + std::string mPackageName; + + void createCrate( + CratedFolder cratedFolder, + std::function<void(CratedFolder, std::unique_ptr<CrateMetadata>&)>& onCreateCrate); +}; + +} // namespace installd +} // namespace android + +#endif // ANDROID_INSTALLD_CRATE_INFO_MANAGER_H diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 8c8d94dafe..9e3520dd60 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -65,6 +65,7 @@ #include "view_compiler.h" #include "CacheTracker.h" +#include "CrateManager.h" #include "MatchExtensionGen.h" #include "QuotaUtils.h" @@ -2029,6 +2030,82 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std: return ok(); } +binder::Status InstalldNativeService::getAppCrates( + const std::unique_ptr<std::string>& uuid, + const std::vector<std::string>& packageNames, int32_t userId, + std::unique_ptr<std::vector<std::unique_ptr<CrateMetadata>>>* _aidl_return) { + ENFORCE_UID(AID_SYSTEM); + CHECK_ARGUMENT_UUID(uuid); + for (const auto& packageName : packageNames) { + CHECK_ARGUMENT_PACKAGE_NAME(packageName); + } + std::lock_guard<std::recursive_mutex> lock(mLock); + + auto retVector = std::make_unique<std::vector<std::unique_ptr<CrateMetadata>>>(); + const char* uuid_ = uuid ? uuid->c_str() : nullptr; + + std::function<void(CratedFolder, std::unique_ptr<CrateMetadata> &)> onCreateCrate = + [&](CratedFolder cratedFolder, std::unique_ptr<CrateMetadata> &crateMetadata) -> void { + if (cratedFolder == nullptr) { + return; + } + retVector->push_back(std::move(crateMetadata)); + }; + + for (const auto& packageName : packageNames) { +#if CRATE_DEBUG + LOG(DEBUG) << "packageName = " << packageName; +#endif + auto crateManager = std::make_unique<CrateManager>(uuid_, userId, packageName); + crateManager->traverseAllCrates(onCreateCrate); + } + +#if CRATE_DEBUG + LOG(WARNING) << "retVector->size() =" << retVector->size(); + for (auto iter = retVector->begin(); iter != retVector->end(); ++iter) { + CrateManager::dump(*iter); + } +#endif + + *_aidl_return = std::move(retVector); + return ok(); +} + +binder::Status InstalldNativeService::getUserCrates( + const std::unique_ptr<std::string>& uuid, int32_t userId, + std::unique_ptr<std::vector<std::unique_ptr<CrateMetadata>>>* _aidl_return) { + ENFORCE_UID(AID_SYSTEM); + CHECK_ARGUMENT_UUID(uuid); + std::lock_guard<std::recursive_mutex> lock(mLock); + + const char* uuid_ = uuid ? uuid->c_str() : nullptr; + auto retVector = std::make_unique<std::vector<std::unique_ptr<CrateMetadata>>>(); + + std::function<void(CratedFolder, std::unique_ptr<CrateMetadata> &)> onCreateCrate = + [&](CratedFolder cratedFolder, std::unique_ptr<CrateMetadata> &crateMetadata) -> void { + if (cratedFolder == nullptr) { + return; + } + retVector->push_back(std::move(crateMetadata)); + }; + + std::function<void(FTSENT*)> onHandingPackage = [&](FTSENT* packageDir) -> void { + auto crateManager = std::make_unique<CrateManager>(uuid_, userId, packageDir->fts_name); + crateManager->traverseAllCrates(onCreateCrate); + }; + CrateManager::traverseAllPackagesForUser(uuid, userId, onHandingPackage); + +#if CRATE_DEBUG + LOG(DEBUG) << "retVector->size() =" << retVector->size(); + for (auto iter = retVector->begin(); iter != retVector->end(); ++iter) { + CrateManager::dump(*iter); + } +#endif + + *_aidl_return = std::move(retVector); + return ok(); +} + binder::Status InstalldNativeService::setAppQuota(const std::unique_ptr<std::string>& uuid, int32_t userId, int32_t appId, int64_t cacheQuota) { ENFORCE_UID(AID_SYSTEM); diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h index fb0273098a..aff3733692 100644 --- a/cmds/installd/InstalldNativeService.h +++ b/cmds/installd/InstalldNativeService.h @@ -81,6 +81,16 @@ public: int32_t userId, int32_t flags, const std::vector<int32_t>& appIds, std::vector<int64_t>* _aidl_return); + binder::Status getAppCrates(const std::unique_ptr<std::string>& uuid, + const std::vector<std::string>& packageNames, + int32_t userId, + std::unique_ptr<std::vector<std::unique_ptr<android::os::storage::CrateMetadata>>>* + _aidl_return); + binder::Status getUserCrates( + const std::unique_ptr<std::string>& uuid, int32_t userId, + std::unique_ptr<std::vector<std::unique_ptr<android::os::storage::CrateMetadata>>>* + _aidl_return); + binder::Status setAppQuota(const std::unique_ptr<std::string>& uuid, int32_t userId, int32_t appId, int64_t cacheQuota); diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl index 6cc4bde2f1..f6a4530a9b 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -40,6 +40,14 @@ interface IInstalld { long[] getUserSize(@nullable @utf8InCpp String uuid, int userId, int flags, in int[] appIds); long[] getExternalSize(@nullable @utf8InCpp String uuid, int userId, int flags, in int[] appIds); + @nullable + android.os.storage.CrateMetadata[] getAppCrates( + @nullable @utf8InCpp String uuid, in @utf8InCpp String[] packageNames, + int userId); + @nullable + android.os.storage.CrateMetadata[] getUserCrates( + @nullable @utf8InCpp String uuid, int userId); + void setAppQuota(@nullable @utf8InCpp String uuid, int userId, int appId, long cacheQuota); void moveCompleteApp(@nullable @utf8InCpp String fromUuid, @nullable @utf8InCpp String toUuid, diff --git a/cmds/installd/binder/android/os/storage/CrateMetadata.aidl b/cmds/installd/binder/android/os/storage/CrateMetadata.aidl new file mode 100644 index 0000000000..bd6d12d9ce --- /dev/null +++ b/cmds/installd/binder/android/os/storage/CrateMetadata.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.os.storage; + +/** {@hide} */ +parcelable CrateMetadata { + /** + * To tell which uid the crate belong to. + * <p>Because installd query all of crates in specified userId, the install may return the list + * whose elements have the same crate id but different uid and package name. + * It needs to tell the caller the difference between these elements. + */ + int uid; + + /** + * To tell which the package the crate belong to. + * <p>Because installd query all of crates in specified uid, the install may return the list + * whose elements have the same uid and crate id but different package name. + * It needs to tell the caller the difference between these elements. + */ + @utf8InCpp String packageName; + + /** + * To tell the crate id that is the child directory/folder name in crates + * root. + */ + @utf8InCpp String id; +} diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index 4eb1df0b2e..6012822f69 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -278,6 +278,15 @@ std::string create_data_dalvik_cache_path() { return "/data/dalvik-cache"; } +std::string create_system_user_ce_path(userid_t userId) { + return StringPrintf("%s/system_ce/%u", create_data_path(nullptr).c_str(), userId); +} + +std::string create_system_user_ce_package_path(userid_t userId, const char* package_name) { + check_package_name(package_name); + return StringPrintf("%s/%s", create_system_user_ce_path(userId).c_str(), package_name); +} + // Keep profile paths in sync with ActivityThread and LoadedApk. const std::string PROFILE_EXT = ".prof"; const std::string CURRENT_PROFILE_EXT = ".cur"; diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h index 6a420261a1..6a39adc41f 100644 --- a/cmds/installd/utils.h +++ b/cmds/installd/utils.h @@ -82,6 +82,10 @@ std::string create_data_misc_legacy_path(userid_t userid); std::string create_data_dalvik_cache_path(); +std::string create_system_user_ce_path(userid_t userId); + +std::string create_system_user_ce_package_path(userid_t userId, const char* package_name); + std::string create_primary_cur_profile_dir_path(userid_t userid); std::string create_primary_current_profile_package_dir_path( userid_t user, const std::string& package_name); |