Merge "Added test cases to dumpsys."
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index ed5fc4a..72efd55 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -53,12 +53,12 @@
#include "otapreopt_utils.h"
#include "utils.h"
+#include "MatchExtensionGen.h"
+
#ifndef LOG_TAG
#define LOG_TAG "installd"
#endif
-#define MEASURE_EXTERNAL 0
-
using android::base::StringPrintf;
namespace android {
@@ -756,7 +756,7 @@
if (delete_dir_contents_and_dir(path, true) != 0) {
res = error("Failed to delete " + path);
}
- path = create_data_user_profiles_path(userId);
+ path = create_data_user_profile_path(userId);
if (delete_dir_contents_and_dir(path, true) != 0) {
res = error("Failed to delete " + path);
}
@@ -849,54 +849,54 @@
}
}
-static bool uuidEquals(const std::unique_ptr<std::string>& a,
- const std::unique_ptr<std::string>& b) {
- if (!a && !b) {
- return true;
- } else if (!a && b) {
- return false;
- } else if (a && !b) {
- return false;
- } else {
- return *a == *b;
- }
-}
-
struct stats {
int64_t codeSize;
int64_t dataSize;
int64_t cacheSize;
};
-static void collectQuotaStats(const std::unique_ptr<std::string>& uuid, int32_t userId,
- int32_t appId, struct stats* stats) {
- struct dqblk dq;
+#if MEASURE_DEBUG
+static std::string toString(std::vector<int64_t> values) {
+ std::stringstream res;
+ res << "[";
+ for (size_t i = 0; i < values.size(); i++) {
+ res << values[i];
+ if (i < values.size() - 1) {
+ res << ",";
+ }
+ }
+ res << "]";
+ return res.str();
+}
+#endif
+static std::string findDeviceForUuid(const std::unique_ptr<std::string>& uuid) {
auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
- std::string device;
- {
- std::ifstream in("/proc/mounts");
- if (!in.is_open()) {
- PLOG(ERROR) << "Failed to read mounts";
- return;
- }
- std::string source;
- std::string target;
- while (!in.eof()) {
- std::getline(in, source, ' ');
- std::getline(in, target, ' ');
- if (target == path) {
- device = source;
- break;
- }
- // Skip to next line
- std::getline(in, source);
- }
+ std::ifstream in("/proc/mounts");
+ if (!in.is_open()) {
+ PLOG(ERROR) << "Failed to read mounts";
+ return "";
}
- if (device.empty()) {
- PLOG(ERROR) << "Failed to resolve block device for " << path;
- return;
+ std::string source;
+ std::string target;
+ while (!in.eof()) {
+ std::getline(in, source, ' ');
+ std::getline(in, target, ' ');
+ if (target == path) {
+ return source;
+ }
+ // Skip to next line
+ std::getline(in, source);
}
+ PLOG(ERROR) << "Failed to resolve block device for " << path;
+ return "";
+}
+
+static void collectQuotaStats(const std::string& device, int32_t userId,
+ int32_t appId, struct stats* stats, struct stats* extStats ATTRIBUTE_UNUSED) {
+ if (device.empty()) return;
+
+ struct dqblk dq;
uid_t uid = multiuser_get_uid(userId, appId);
if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
@@ -905,6 +905,9 @@
PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
}
} else {
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
+#endif
stats->dataSize += dq.dqb_curspace;
}
@@ -916,6 +919,9 @@
PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << cacheGid;
}
} else {
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "quotactl() for GID " << cacheGid << " " << dq.dqb_curspace;
+#endif
stats->cacheSize += dq.dqb_curspace;
}
}
@@ -928,12 +934,24 @@
PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << sharedGid;
}
} else {
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace;
+#endif
stats->codeSize += dq.dqb_curspace;
}
}
+
+#if MEASURE_EXTERNAL
+ // TODO: measure using external GIDs
+#endif
}
-static void collectManualStats(std::string& path, struct stats* stats) {
+static void collectQuotaStats(const std::unique_ptr<std::string>& uuid, int32_t userId,
+ int32_t appId, struct stats* stats, struct stats* extStats) {
+ collectQuotaStats(findDeviceForUuid(uuid), userId, appId, stats, extStats);
+}
+
+static void collectManualStats(const std::string& path, struct stats* stats) {
DIR *d;
int dfd;
struct dirent *de;
@@ -983,80 +1001,343 @@
closedir(d);
}
+static void collectManualStatsForUser(const std::string& path, struct stats* stats,
+ bool exclude_apps = false) {
+ DIR *d;
+ int dfd;
+ struct dirent *de;
+ struct stat s;
+
+ d = opendir(path.c_str());
+ if (d == nullptr) {
+ if (errno != ENOENT) {
+ PLOG(WARNING) << "Failed to open " << path;
+ }
+ return;
+ }
+ dfd = dirfd(d);
+ while ((de = readdir(d))) {
+ if (de->d_type == DT_DIR) {
+ const char *name = de->d_name;
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) != 0) {
+ continue;
+ }
+ if (!strcmp(name, ".") || !strcmp(name, "..")) {
+ continue;
+ } else if (exclude_apps && (s.st_uid >= AID_APP_START && s.st_uid <= AID_APP_END)) {
+ continue;
+ } else {
+ collectManualStats(StringPrintf("%s/%s", path.c_str(), name), stats);
+ }
+ }
+ }
+ closedir(d);
+}
+
binder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::string>& uuid,
- const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
- int64_t ceDataInode, const std::string& codePath,
- const std::unique_ptr<std::string>& externalUuid, std::vector<int64_t>* _aidl_return) {
+ const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
+ int32_t appId, const std::vector<int64_t>& ceDataInodes,
+ const std::vector<std::string>& codePaths, std::vector<int64_t>* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
- CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ for (auto packageName : packageNames) {
+ CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ }
- const char* uuid_ = uuid ? uuid->c_str() : nullptr;
- const char* extuuid_ = externalUuid ? externalUuid->c_str() : nullptr;
- const char* pkgname = packageName.c_str();
+ // When modifying this logic, always verify using tests:
+ // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetAppSize
+
+#if MEASURE_DEBUG
+ LOG(INFO) << "Measuring user " << userId << " app " << appId;
+#endif
// Here's a summary of the common storage locations across the platform,
// and how they're each tagged:
//
// /data/app/com.example UID system
// /data/app/com.example/oat UID system
- // /data/user/0/com.example UID u0_a10 GID u0_a10
- // /data/user/0/com.example/cache UID u0_a10 GID u0_a10_cache
- // /data/media/0/Android/data/com.example UID u0_a10 GID u0_a10
- // /data/media/0/Android/data/com.example/cache UID u0_a10 GID u0_a10_cache
- // /data/media/0/Android/obb/com.example UID system
+ // /data/user/0/com.example UID u0_a10 GID u0_a10
+ // /data/user/0/com.example/cache UID u0_a10 GID u0_a10_cache
+ // /data/media/0/foo.txt UID u0_media_rw
+ // /data/media/0/bar.jpg UID u0_media_rw GID u0_media_image
+ // /data/media/0/Android/data/com.example UID u0_media_rw GID u0_a10_ext
+ // /data/media/0/Android/data/com.example/cache UID u0_media_rw GID u0_a10_ext_cache
+ // /data/media/obb/com.example UID system
struct stats stats;
+ struct stats extStats;
memset(&stats, 0, sizeof(stats));
+ memset(&extStats, 0, sizeof(extStats));
- auto obbCodePath = create_data_media_package_path(extuuid_, userId, pkgname, "obb");
- calculate_tree_size(obbCodePath, &stats.codeSize);
+ const char* uuid_ = uuid ? uuid->c_str() : nullptr;
- if (flags & FLAG_USE_QUOTA) {
- calculate_tree_size(codePath, &stats.codeSize,
- 0, multiuser_get_shared_gid(userId, appId));
+ for (auto packageName : packageNames) {
+ auto obbCodePath = create_data_media_obb_path(uuid_, packageName.c_str());
+ calculate_tree_size(obbCodePath, &extStats.codeSize);
+ }
- collectQuotaStats(uuid, userId, appId, &stats);
-
- // If external storage lives on a different storage device, also
- // collect quota stats from that block device
- if (!uuidEquals(uuid, externalUuid)) {
- collectQuotaStats(externalUuid, userId, appId, &stats);
+ if (flags & FLAG_USE_QUOTA && appId >= AID_APP_START) {
+ for (auto codePath : codePaths) {
+ calculate_tree_size(codePath, &stats.codeSize, -1,
+ multiuser_get_shared_gid(userId, appId));
}
+
+ collectQuotaStats(uuid, userId, appId, &stats, &extStats);
+
} else {
- calculate_tree_size(codePath, &stats.codeSize);
+ for (auto codePath : codePaths) {
+ calculate_tree_size(codePath, &stats.codeSize);
+ }
- auto cePath = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
- collectManualStats(cePath, &stats);
+ for (size_t i = 0; i < packageNames.size(); i++) {
+ const char* pkgname = packageNames[i].c_str();
- auto dePath = create_data_user_de_package_path(uuid_, userId, pkgname);
- collectManualStats(dePath, &stats);
+ auto cePath = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInodes[i]);
+ collectManualStats(cePath, &stats);
- auto userProfilePath = create_data_user_profile_package_path(userId, pkgname);
- calculate_tree_size(userProfilePath, &stats.dataSize);
+ auto dePath = create_data_user_de_package_path(uuid_, userId, pkgname);
+ collectManualStats(dePath, &stats);
- auto refProfilePath = create_data_ref_profile_package_path(pkgname);
- calculate_tree_size(refProfilePath, &stats.codeSize);
+ auto userProfilePath = create_data_user_profile_package_path(userId, pkgname);
+ calculate_tree_size(userProfilePath, &stats.dataSize);
- calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
- multiuser_get_shared_gid(userId, appId), 0);
-
- calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize,
- multiuser_get_uid(userId, appId), 0);
+ auto refProfilePath = create_data_ref_profile_package_path(pkgname);
+ calculate_tree_size(refProfilePath, &stats.codeSize);
#if MEASURE_EXTERNAL
- auto extPath = create_data_media_package_path(extuuid_, userId, pkgname, "data");
- collectManualStats(extPath, &stats);
+ auto extPath = create_data_media_package_path(uuid_, userId, pkgname, "data");
+ collectManualStats(extPath, &extStats);
- auto mediaPath = create_data_media_package_path(extuuid_, userId, pkgname, "media");
- calculate_tree_size(mediaPath, &stats.dataSize);
+ auto mediaPath = create_data_media_package_path(uuid_, userId, pkgname, "media");
+ calculate_tree_size(mediaPath, &extStats.dataSize);
#endif
+ }
+
+ int32_t sharedGid = multiuser_get_shared_gid(userId, appId);
+ if (sharedGid != -1) {
+ calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
+ sharedGid, -1);
+ }
+
+ calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize,
+ multiuser_get_uid(userId, appId), -1);
}
std::vector<int64_t> ret;
ret.push_back(stats.codeSize);
ret.push_back(stats.dataSize);
ret.push_back(stats.cacheSize);
+ ret.push_back(extStats.codeSize);
+ ret.push_back(extStats.dataSize);
+ ret.push_back(extStats.cacheSize);
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "Final result " << toString(ret);
+#endif
+ *_aidl_return = ret;
+ return ok();
+}
+
+binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::string>& uuid,
+ int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
+ std::vector<int64_t>* _aidl_return) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_UUID(uuid);
+
+ // When modifying this logic, always verify using tests:
+ // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetUserSize
+
+#if MEASURE_DEBUG
+ LOG(INFO) << "Measuring user " << userId;
+#endif
+
+ struct stats stats;
+ struct stats extStats;
+ memset(&stats, 0, sizeof(stats));
+ memset(&extStats, 0, sizeof(extStats));
+
+ const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+
+ auto obbPath = create_data_path(uuid_) + "/media/obb";
+ calculate_tree_size(obbPath, &extStats.codeSize);
+
+ if (flags & FLAG_USE_QUOTA) {
+ calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true);
+
+ auto cePath = create_data_user_ce_path(uuid_, userId);
+ collectManualStatsForUser(cePath, &stats, true);
+
+ auto dePath = create_data_user_de_path(uuid_, userId);
+ collectManualStatsForUser(dePath, &stats, true);
+
+ auto userProfilePath = create_data_user_profile_path(userId);
+ calculate_tree_size(userProfilePath, &stats.dataSize, -1, -1, true);
+
+ auto refProfilePath = create_data_ref_profile_path();
+ calculate_tree_size(refProfilePath, &stats.codeSize, -1, -1, true);
+
+#if MEASURE_EXTERNAL
+ // TODO: measure external storage paths
+#endif
+
+ calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
+ -1, -1, true);
+
+ calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize,
+ -1, -1, true);
+
+ auto device = findDeviceForUuid(uuid);
+ for (auto appId : appIds) {
+ if (appId >= AID_APP_START) {
+ collectQuotaStats(device, userId, appId, &stats, &extStats);
+#if MEASURE_DEBUG
+ // Sleep to make sure we don't lose logs
+ usleep(1);
+#endif
+ }
+ }
+ } else {
+ calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize);
+
+ auto cePath = create_data_user_ce_path(uuid_, userId);
+ collectManualStatsForUser(cePath, &stats);
+
+ auto dePath = create_data_user_de_path(uuid_, userId);
+ collectManualStatsForUser(dePath, &stats);
+
+ auto userProfilePath = create_data_user_profile_path(userId);
+ calculate_tree_size(userProfilePath, &stats.dataSize);
+
+ auto refProfilePath = create_data_ref_profile_path();
+ calculate_tree_size(refProfilePath, &stats.codeSize);
+
+#if MEASURE_EXTERNAL
+ // TODO: measure external storage paths
+#endif
+
+ calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize);
+
+ calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize);
+ }
+
+ std::vector<int64_t> ret;
+ ret.push_back(stats.codeSize);
+ ret.push_back(stats.dataSize);
+ ret.push_back(stats.cacheSize);
+ ret.push_back(extStats.codeSize);
+ ret.push_back(extStats.dataSize);
+ ret.push_back(extStats.cacheSize);
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "Final result " << toString(ret);
+#endif
+ *_aidl_return = ret;
+ return ok();
+}
+
+binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std::string>& uuid,
+ int32_t userId, int32_t flags, std::vector<int64_t>* _aidl_return) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_UUID(uuid);
+
+ // When modifying this logic, always verify using tests:
+ // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetExternalSize
+
+#if MEASURE_DEBUG
+ LOG(INFO) << "Measuring external " << userId;
+#endif
+
+ const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+
+ int64_t totalSize = 0;
+ int64_t audioSize = 0;
+ int64_t videoSize = 0;
+ int64_t imageSize = 0;
+
+ if (flags & FLAG_USE_QUOTA) {
+ struct dqblk dq;
+
+ auto device = findDeviceForUuid(uuid);
+
+ uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
+ if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
+ reinterpret_cast<char*>(&dq)) != 0) {
+ if (errno != ESRCH) {
+ PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
+ }
+ } else {
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
+#endif
+ totalSize = dq.dqb_curspace;
+ }
+
+ gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO);
+ if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), audioGid,
+ reinterpret_cast<char*>(&dq)) == 0) {
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "quotactl() for GID " << audioGid << " " << dq.dqb_curspace;
+#endif
+ audioSize = dq.dqb_curspace;
+ }
+ gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO);
+ if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), videoGid,
+ reinterpret_cast<char*>(&dq)) == 0) {
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "quotactl() for GID " << videoGid << " " << dq.dqb_curspace;
+#endif
+ videoSize = dq.dqb_curspace;
+ }
+ gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE);
+ if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), imageGid,
+ reinterpret_cast<char*>(&dq)) == 0) {
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "quotactl() for GID " << imageGid << " " << dq.dqb_curspace;
+#endif
+ imageSize = dq.dqb_curspace;
+ }
+ } else {
+ FTS *fts;
+ FTSENT *p;
+ auto path = create_data_media_path(uuid_, userId);
+ char *argv[] = { (char*) path.c_str(), nullptr };
+ if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+ return error("Failed to fts_open " + path);
+ }
+ while ((p = fts_read(fts)) != NULL) {
+ char* ext;
+ int64_t size = (p->fts_statp->st_blocks * 512);
+ switch (p->fts_info) {
+ case FTS_F:
+ // Only categorize files not belonging to apps
+ if (p->fts_statp->st_gid < AID_APP_START) {
+ ext = strrchr(p->fts_name, '.');
+ if (ext != nullptr) {
+ switch (MatchExtension(++ext)) {
+ case AID_MEDIA_AUDIO: audioSize += size; break;
+ case AID_MEDIA_VIDEO: videoSize += size; break;
+ case AID_MEDIA_IMAGE: imageSize += size; break;
+ }
+ }
+ }
+ // Fall through to always count against total
+ case FTS_D:
+ case FTS_DEFAULT:
+ case FTS_SL:
+ case FTS_SLNONE:
+ totalSize += size;
+ break;
+ }
+ }
+ fts_close(fts);
+ }
+
+ std::vector<int64_t> ret;
+ ret.push_back(totalSize);
+ ret.push_back(audioSize);
+ ret.push_back(videoSize);
+ ret.push_back(imageSize);
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "Final result " << toString(ret);
+#endif
*_aidl_return = ret;
return ok();
}
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index cad9e43..5397a74 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -55,10 +55,16 @@
const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
binder::Status destroyAppData(const std::unique_ptr<std::string>& uuid,
const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
+
binder::Status getAppSize(const std::unique_ptr<std::string>& uuid,
- const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
- int64_t ceDataInode, const std::string& codePath,
- const std::unique_ptr<std::string>& externalUuid, std::vector<int64_t>* _aidl_return);
+ const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
+ int32_t appId, const std::vector<int64_t>& ceDataInodes,
+ const std::vector<std::string>& codePaths, std::vector<int64_t>* _aidl_return);
+ binder::Status getUserSize(const std::unique_ptr<std::string>& uuid,
+ int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
+ std::vector<int64_t>* _aidl_return);
+ binder::Status getExternalSize(const std::unique_ptr<std::string>& uuid,
+ int32_t userId, int32_t flags, std::vector<int64_t>* _aidl_return);
binder::Status moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
diff --git a/cmds/installd/MatchExtensionGen.h b/cmds/installd/MatchExtensionGen.h
new file mode 100644
index 0000000..fded6b7
--- /dev/null
+++ b/cmds/installd/MatchExtensionGen.h
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/******************************************************************
+ * THIS CODE WAS GENERATED BY matchgen.py, DO NOT MODIFY DIRECTLY *
+ ******************************************************************/
+
+#include <private/android_filesystem_config.h>
+
+int MatchExtension(const char* ext) {
+
+ switch (ext[0]) {
+ case '3':
+ switch (ext[1]) {
+ case 'g': case 'G':
+ switch (ext[2]) {
+ case '2':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ case 'p': case 'P':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ case 'p': case 'P':
+ switch (ext[4]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ case '2':
+ switch (ext[5]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ }
+ }
+ }
+ case 'a': case 'A':
+ switch (ext[1]) {
+ case 'a': case 'A':
+ switch (ext[2]) {
+ case 'c': case 'C':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ case 'i': case 'I':
+ switch (ext[2]) {
+ case 'f': case 'F':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ case 'c': case 'C':
+ switch (ext[4]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ case 'f': case 'F':
+ switch (ext[4]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ }
+ case 'm': case 'M':
+ switch (ext[2]) {
+ case 'r': case 'R':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ case 'r': case 'R':
+ switch (ext[2]) {
+ case 't': case 'T':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ case 'w': case 'W':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 's': case 'S':
+ switch (ext[2]) {
+ case 'f': case 'F':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ case 'x': case 'X':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ case 'v': case 'V':
+ switch (ext[2]) {
+ case 'i': case 'I':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ case 'w': case 'W':
+ switch (ext[2]) {
+ case 'b': case 'B':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ }
+ case 'b': case 'B':
+ switch (ext[1]) {
+ case 'm': case 'M':
+ switch (ext[2]) {
+ case 'p': case 'P':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ }
+ case 'c': case 'C':
+ switch (ext[1]) {
+ case 'r': case 'R':
+ switch (ext[2]) {
+ case '2':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ }
+ case 'd': case 'D':
+ switch (ext[1]) {
+ case 'i': case 'I':
+ switch (ext[2]) {
+ case 'f': case 'F':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ case 'l': case 'L':
+ switch (ext[2]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ case 'n': case 'N':
+ switch (ext[2]) {
+ case 'g': case 'G':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'v': case 'V':
+ switch (ext[2]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ case 'f': case 'F':
+ switch (ext[1]) {
+ case 'l': case 'L':
+ switch (ext[2]) {
+ case 'a': case 'A':
+ switch (ext[3]) {
+ case 'c': case 'C':
+ switch (ext[4]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ case 'i': case 'I':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ }
+ case 'g': case 'G':
+ switch (ext[1]) {
+ case 'i': case 'I':
+ switch (ext[2]) {
+ case 'f': case 'F':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 's': case 'S':
+ switch (ext[2]) {
+ case 'm': case 'M':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ }
+ case 'j': case 'J':
+ switch (ext[1]) {
+ case 'n': case 'N':
+ switch (ext[2]) {
+ case 'g': case 'G':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'p': case 'P':
+ switch (ext[2]) {
+ case 'e': case 'E':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ case 'g': case 'G':
+ switch (ext[4]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'g': case 'G':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ }
+ case 'l': case 'L':
+ switch (ext[1]) {
+ case 's': case 'S':
+ switch (ext[2]) {
+ case 'f': case 'F':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ case 'x': case 'X':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ }
+ case 'm': case 'M':
+ switch (ext[1]) {
+ case '3':
+ switch (ext[2]) {
+ case 'u': case 'U':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ case '4':
+ switch (ext[2]) {
+ case 'a': case 'A':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ case 'v': case 'V':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ case 'k': case 'K':
+ switch (ext[2]) {
+ case 'a': case 'A':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ case 'v': case 'V':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ case 'n': case 'N':
+ switch (ext[2]) {
+ case 'g': case 'G':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ case 'o': case 'O':
+ switch (ext[2]) {
+ case 'v': case 'V':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ case 'i': case 'I':
+ switch (ext[4]) {
+ case 'e': case 'E':
+ switch (ext[5]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ }
+ }
+ case 'p': case 'P':
+ switch (ext[2]) {
+ case '2':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ case '3':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ case '4':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ case 'e': case 'E':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ case 'g': case 'G':
+ switch (ext[4]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ case 'a': case 'A':
+ switch (ext[5]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ }
+ case 'g': case 'G':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ case 'a': case 'A':
+ switch (ext[4]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ }
+ case 'x': case 'X':
+ switch (ext[2]) {
+ case 'u': case 'U':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ }
+ case 'n': case 'N':
+ switch (ext[1]) {
+ case 'e': case 'E':
+ switch (ext[2]) {
+ case 'f': case 'F':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'r': case 'R':
+ switch (ext[2]) {
+ case 'w': case 'W':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ }
+ case 'o': case 'O':
+ switch (ext[1]) {
+ case 'g': case 'G':
+ switch (ext[2]) {
+ case 'a': case 'A':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ case 'g': case 'G':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ case 'r': case 'R':
+ switch (ext[2]) {
+ case 'f': case 'F':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ }
+ case 'p': case 'P':
+ switch (ext[1]) {
+ case 'b': case 'B':
+ switch (ext[2]) {
+ case 'm': case 'M':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'c': case 'C':
+ switch (ext[2]) {
+ case 'x': case 'X':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'e': case 'E':
+ switch (ext[2]) {
+ case 'f': case 'F':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'g': case 'G':
+ switch (ext[2]) {
+ case 'm': case 'M':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'l': case 'L':
+ switch (ext[2]) {
+ case 's': case 'S':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ case 'n': case 'N':
+ switch (ext[2]) {
+ case 'g': case 'G':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ case 'm': case 'M':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'p': case 'P':
+ switch (ext[2]) {
+ case 'm': case 'M':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 's': case 'S':
+ switch (ext[2]) {
+ case 'd': case 'D':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ }
+ case 'q': case 'Q':
+ switch (ext[1]) {
+ case 't': case 'T':
+ switch (ext[2]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ case 'r': case 'R':
+ switch (ext[1]) {
+ case 'a': case 'A':
+ switch (ext[2]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ case 'm': case 'M':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ case 's': case 'S':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'g': case 'G':
+ switch (ext[2]) {
+ case 'b': case 'B':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'm': case 'M':
+ switch (ext[2]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ case 'w': case 'W':
+ switch (ext[2]) {
+ case '2':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ }
+ case 's': case 'S':
+ switch (ext[1]) {
+ case 'd': case 'D':
+ switch (ext[2]) {
+ case '2':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ case 'n': case 'N':
+ switch (ext[2]) {
+ case 'd': case 'D':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ case 'r': case 'R':
+ switch (ext[2]) {
+ case 'w': case 'W':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'v': case 'V':
+ switch (ext[2]) {
+ case 'g': case 'G':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ case 'z': case 'Z':
+ switch (ext[4]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ }
+ }
+ case 't': case 'T':
+ switch (ext[1]) {
+ case 'i': case 'I':
+ switch (ext[2]) {
+ case 'f': case 'F':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ case 'f': case 'F':
+ switch (ext[4]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ }
+ case 's': case 'S':
+ switch (ext[2]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ case 'v': case 'V':
+ switch (ext[1]) {
+ case 'o': case 'O':
+ switch (ext[2]) {
+ case 'b': case 'B':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ }
+ case 'w': case 'W':
+ switch (ext[1]) {
+ case 'a': case 'A':
+ switch (ext[2]) {
+ case 'v': case 'V':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ case 'x': case 'X':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ }
+ case 'b': case 'B':
+ switch (ext[2]) {
+ case 'm': case 'M':
+ switch (ext[3]) {
+ case 'p': case 'P':
+ switch (ext[4]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ }
+ case 'e': case 'E':
+ switch (ext[2]) {
+ case 'b': case 'B':
+ switch (ext[3]) {
+ case 'm': case 'M':
+ switch (ext[4]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ case 'p': case 'P':
+ switch (ext[4]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ }
+ case 'm': case 'M':
+ switch (ext[2]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ case 'a': case 'A':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_AUDIO;
+ }
+ case 'v': case 'V':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ case 'x': case 'X':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ case 'r': case 'R':
+ switch (ext[2]) {
+ case 'f': case 'F':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ case 'v': case 'V':
+ switch (ext[2]) {
+ case 'x': case 'X':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_VIDEO;
+ }
+ }
+ }
+ case 'x': case 'X':
+ switch (ext[1]) {
+ case 'b': case 'B':
+ switch (ext[2]) {
+ case 'm': case 'M':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'p': case 'P':
+ switch (ext[2]) {
+ case 'm': case 'M':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ case 'w': case 'W':
+ switch (ext[2]) {
+ case 'd': case 'D':
+ switch (ext[3]) {
+ case '\0': return AID_MEDIA_IMAGE;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 8c5d2f4..6e4d7fa 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -31,9 +31,12 @@
int userId, int flags, long ceDataInode);
void destroyAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
int userId, int flags, long ceDataInode);
- long[] getAppSize(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
- int userId, int flags, int appId, long ceDataInode, @utf8InCpp String codePath,
- @nullable @utf8InCpp String externalUuid);
+
+ long[] getAppSize(@nullable @utf8InCpp String uuid, in @utf8InCpp String[] packageNames,
+ int userId, int flags, int appId, in long[] ceDataInodes,
+ in @utf8InCpp String[] codePaths);
+ long[] getUserSize(@nullable @utf8InCpp String uuid, int userId, int flags, in int[] appIds);
+ long[] getExternalSize(@nullable @utf8InCpp String uuid, int userId, int flags);
void moveCompleteApp(@nullable @utf8InCpp String fromUuid, @nullable @utf8InCpp String toUuid,
@utf8InCpp String packageName, @utf8InCpp String dataAppName, int appId,
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 5025fde..868e494 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -153,57 +153,6 @@
return count;
}
-static void run_patchoat(int input_oat_fd, int input_vdex_fd, int out_oat_fd, int out_vdex_fd,
- const char* input_oat_file_name, const char* input_vdex_file_name,
- const char* output_oat_file_name, const char* output_vdex_file_name,
- const char *pkgname ATTRIBUTE_UNUSED, const char *instruction_set)
-{
- static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
- static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
-
- static const char* PATCHOAT_BIN = "/system/bin/patchoat";
- if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
- ALOGE("Instruction set %s longer than max length of %d",
- instruction_set, MAX_INSTRUCTION_SET_LEN);
- return;
- }
-
- /* input_file_name/input_fd should be the .odex/.oat file that is precompiled. I think*/
- char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
- char input_oat_fd_arg[strlen("--input-oat-fd=") + MAX_INT_LEN];
- char input_vdex_fd_arg[strlen("--input-vdex-fd=") + MAX_INT_LEN];
- char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN];
- char output_vdex_fd_arg[strlen("--output-vdex-fd=") + MAX_INT_LEN];
- const char* patched_image_location_arg = "--patched-image-location=/system/framework/boot.art";
- // The caller has already gotten all the locks we need.
- const char* no_lock_arg = "--no-lock-output";
- sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
- sprintf(output_oat_fd_arg, "--output-oat-fd=%d", out_oat_fd);
- sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_oat_fd);
- ALOGV("Running %s isa=%s in-oat-fd=%d (%s) in-vdex-fd=%d (%s) "
- "out-oat-fd=%d (%s) out-vdex-fd=%d (%s)\n",
- PATCHOAT_BIN, instruction_set,
- input_oat_fd, input_oat_file_name,
- input_vdex_fd, input_vdex_file_name,
- out_oat_fd, output_oat_file_name,
- out_vdex_fd, output_vdex_file_name);
-
- /* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */
- char* argv[9];
- argv[0] = (char*) PATCHOAT_BIN;
- argv[1] = (char*) patched_image_location_arg;
- argv[2] = (char*) no_lock_arg;
- argv[3] = instruction_set_arg;
- argv[4] = input_oat_fd_arg;
- argv[5] = input_vdex_fd_arg;
- argv[6] = output_oat_fd_arg;
- argv[7] = output_vdex_fd_arg;
- argv[8] = NULL;
-
- execv(PATCHOAT_BIN, (char* const *)argv);
- ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
-}
-
static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd,
const char* input_file_name, const char* output_file_name, int swap_fd,
const char *instruction_set, const char* compiler_filter, bool vm_safe_mode,
@@ -502,7 +451,7 @@
return kDefaultProvideSwapFile;
}
-static void SetDex2OatAndPatchOatScheduling(bool set_to_bg) {
+static void SetDex2OatScheduling(bool set_to_bg) {
if (set_to_bg) {
if (set_sched_policy(0, SP_BACKGROUND) < 0) {
ALOGE("set_sched_policy failed: %s\n", strerror(errno));
@@ -1062,40 +1011,12 @@
return false;
}
- const char *input_file;
- char in_odex_path[PKG_PATH_MAX];
- int dexopt_action = abs(dexopt_needed);
- bool is_odex_location = dexopt_needed < 0;
- switch (dexopt_action) {
- case DEX2OAT_FROM_SCRATCH:
- case DEX2OAT_FOR_BOOT_IMAGE:
- case DEX2OAT_FOR_FILTER:
- case DEX2OAT_FOR_RELOCATION:
- input_file = apk_path;
- break;
-
- case PATCHOAT_FOR_RELOCATION:
- if (is_odex_location) {
- if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
- return -1;
- }
- input_file = in_odex_path;
- } else {
- input_file = out_oat_path;
- }
- break;
-
- default:
- ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
- return 72;
- }
-
+ const char *input_file = apk_path;
struct stat input_stat;
memset(&input_stat, 0, sizeof(input_stat));
stat(input_file, &input_stat);
- // Open the input file. If running dex2oat, `input_file` is the APK. If running
- // patchoat, it is the OAT file to be relocated.
+ // Open the input file.
base::unique_fd input_fd(open(input_file, O_RDONLY, 0));
if (input_fd.get() < 0) {
ALOGE("installd cannot open '%s' for input during dexopt\n", input_file);
@@ -1117,22 +1038,12 @@
// Open the existing VDEX. We do this before creating the new output VDEX, which will
// unlink the old one.
+ char in_odex_path[PKG_PATH_MAX];
+ int dexopt_action = abs(dexopt_needed);
+ bool is_odex_location = dexopt_needed < 0;
base::unique_fd in_vdex_fd;
std::string in_vdex_path_str;
- if (dexopt_action == PATCHOAT_FOR_RELOCATION) {
- // `input_file` is the OAT file to be relocated. The VDEX has to be there as well.
- in_vdex_path_str = create_vdex_filename(input_file);
- if (in_vdex_path_str.empty()) {
- ALOGE("installd cannot compute input vdex location for '%s'\n", input_file);
- return -1;
- }
- in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
- if (in_vdex_fd.get() < 0) {
- ALOGE("installd cannot open '%s' for input during dexopt: %s\n",
- in_vdex_path_str.c_str(), strerror(errno));
- return -1;
- }
- } else if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
+ if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
// Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
const char* path = nullptr;
if (is_odex_location) {
@@ -1212,7 +1123,7 @@
// Avoid generating an app image for extract only since it will not contain any classes.
Dex2oatFileWrapper<std::function<void ()>> image_fd;
const std::string image_path = create_image_filename(out_oat_path);
- if (dexopt_action != PATCHOAT_FOR_RELOCATION && !image_path.empty()) {
+ if (!image_path.empty()) {
char app_image_format[kPropertyValueMax];
bool have_app_image_format =
get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
@@ -1256,42 +1167,29 @@
/* child -- drop privileges before continuing */
drop_capabilities(uid);
- SetDex2OatAndPatchOatScheduling(boot_complete);
+ SetDex2OatScheduling(boot_complete);
if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) {
ALOGE("flock(%s) failed: %s\n", out_oat_path, strerror(errno));
_exit(67);
}
- if (dexopt_action == PATCHOAT_FOR_RELOCATION) {
- run_patchoat(input_fd.get(),
- in_vdex_fd.get(),
- out_oat_fd.get(),
- out_vdex_fd,
- input_file,
- in_vdex_path_str.c_str(),
- out_oat_path,
- out_vdex_path_str.c_str(),
- pkgname,
- instruction_set);
- } else {
- // Pass dex2oat the relative path to the input file.
- const char *input_file_name = get_location_from_path(input_file);
- run_dex2oat(input_fd.get(),
- out_oat_fd.get(),
- in_vdex_fd.get(),
- out_vdex_fd,
- image_fd.get(),
- input_file_name,
- out_oat_path,
- swap_fd.get(),
- instruction_set,
- compiler_filter,
- vm_safe_mode,
- debuggable,
- boot_complete,
- reference_profile_fd.get(),
- shared_libraries);
- }
+ // Pass dex2oat the relative path to the input file.
+ const char *input_file_name = get_location_from_path(input_file);
+ run_dex2oat(input_fd.get(),
+ out_oat_fd.get(),
+ in_vdex_fd.get(),
+ out_vdex_fd,
+ image_fd.get(),
+ input_file_name,
+ out_oat_path,
+ swap_fd.get(),
+ instruction_set,
+ compiler_filter,
+ vm_safe_mode,
+ debuggable,
+ boot_complete,
+ reference_profile_fd.get(),
+ shared_libraries);
_exit(68); /* only get here on exec failure */
} else {
int res = wait_child(pid);
diff --git a/cmds/installd/matchgen.py b/cmds/installd/matchgen.py
new file mode 100644
index 0000000..b37352b
--- /dev/null
+++ b/cmds/installd/matchgen.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2017 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.
+
+import collections
+
+TYPES = {
+ "AID_MEDIA_AUDIO": ["aac","aac","amr","awb","snd","flac","flac","mp3","mpga","mpega","mp2","m4a","aif","aiff","aifc","gsm","mka","m3u","wma","wax","ra","rm","ram","ra","pls","sd2","wav","ogg","oga"],
+ "AID_MEDIA_VIDEO": ["3gpp","3gp","3gpp2","3g2","avi","dl","dif","dv","fli","m4v","ts","mpeg","mpg","mpe","mp4","vob","qt","mov","mxu","webm","lsf","lsx","mkv","mng","asf","asx","wm","wmv","wmx","wvx","movie","wrf"],
+ "AID_MEDIA_IMAGE": ["bmp","gif","jpg","jpeg","jpe","pcx","png","svg","svgz","tiff","tif","wbmp","webp","dng","cr2","ras","art","jng","nef","nrw","orf","rw2","pef","psd","pnm","pbm","pgm","ppm","srw","arw","rgb","xbm","xpm","xwd"]
+}
+
+print """/*
+ * Copyright (C) 2017 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.
+ */
+
+/******************************************************************
+ * THIS CODE WAS GENERATED BY matchgen.py, DO NOT MODIFY DIRECTLY *
+ ******************************************************************/
+
+#include <private/android_filesystem_config.h>
+
+int MatchExtension(const char* ext) {
+"""
+
+trie = collections.defaultdict(lambda: collections.defaultdict(lambda: collections.defaultdict(lambda: collections.defaultdict(lambda: collections.defaultdict(lambda: collections.defaultdict(lambda: ""))))))
+
+for t in TYPES:
+ for v in TYPES[t]:
+ v = v.lower()
+ target = trie
+ for c in v:
+ target = target[c]
+ target["\0"] = t
+
+def dump(target, index):
+ prefix = " " * (index + 1)
+ print "%sswitch (ext[%d]) {" % (prefix, index)
+ for k in sorted(target.keys()):
+ if k == "\0":
+ print "%scase '\\0': return %s;" % (prefix, target[k])
+ else:
+ upper = k.upper()
+ if k != upper:
+ print "%scase '%s': case '%s':" % (prefix, k, upper)
+ else:
+ print "%scase '%s':" % (prefix, k)
+ dump(target[k], index + 1)
+ print "%s}" % (prefix)
+
+dump(trie, 0)
+
+print """
+ return 0;
+}
+"""
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index e1a59d4..9849a0f 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -199,6 +199,10 @@
return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
}
+std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name) {
+ return StringPrintf("%s/media/obb/%s", create_data_path(volume_uuid).c_str(), package_name);
+}
+
std::string create_data_media_package_path(const char* volume_uuid, userid_t userid,
const char* data_type, const char* package_name) {
return StringPrintf("%s/Android/%s/%s", create_data_media_path(volume_uuid, userid).c_str(),
@@ -209,13 +213,17 @@
return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid);
}
-std::string create_data_user_profiles_path(userid_t userid) {
+std::string create_data_user_profile_path(userid_t userid) {
return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid);
}
std::string create_data_user_profile_package_path(userid_t user, const char* package_name) {
check_package_name(package_name);
- return StringPrintf("%s/%s",create_data_user_profiles_path(user).c_str(), package_name);
+ return StringPrintf("%s/%s",create_data_user_profile_path(user).c_str(), package_name);
+}
+
+std::string create_data_ref_profile_path() {
+ return StringPrintf("%s/ref", android_profiles_dir.path);
}
std::string create_data_ref_profile_package_path(const char* package_name) {
@@ -271,9 +279,10 @@
}
int calculate_tree_size(const std::string& path, int64_t* size,
- gid_t include_gid, gid_t exclude_gid) {
+ int32_t include_gid, int32_t exclude_gid, bool exclude_apps) {
FTS *fts;
FTSENT *p;
+ int64_t matchedSize = 0;
char *argv[] = { (char*) path.c_str(), nullptr };
if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
if (errno != ENOENT) {
@@ -288,17 +297,37 @@
case FTS_F:
case FTS_SL:
case FTS_SLNONE:
- if (include_gid != 0 && p->fts_statp->st_gid != include_gid) {
+ int32_t uid = p->fts_statp->st_uid;
+ int32_t gid = p->fts_statp->st_gid;
+ int32_t user_uid = multiuser_get_app_id(uid);
+ int32_t user_gid = multiuser_get_app_id(gid);
+ if (exclude_apps && ((user_uid >= AID_APP_START && user_uid <= AID_APP_END)
+ || (user_gid >= AID_CACHE_GID_START && user_gid <= AID_CACHE_GID_END)
+ || (user_gid >= AID_SHARED_GID_START && user_gid <= AID_SHARED_GID_END))) {
+ // Don't traverse inside or measure
+ fts_set(fts, p, FTS_SKIP);
break;
}
- if (exclude_gid != 0 && p->fts_statp->st_gid == exclude_gid) {
+ if (include_gid != -1 && gid != include_gid) {
break;
}
- *size += (p->fts_statp->st_blocks * 512);
+ if (exclude_gid != -1 && gid == exclude_gid) {
+ break;
+ }
+ matchedSize += (p->fts_statp->st_blocks * 512);
break;
}
}
fts_close(fts);
+#if MEASURE_DEBUG
+ if ((include_gid == -1) && (exclude_gid == -1)) {
+ LOG(DEBUG) << "Measured " << path << " size " << matchedSize;
+ } else {
+ LOG(DEBUG) << "Measured " << path << " size " << matchedSize << "; include " << include_gid
+ << " exclude " << exclude_gid;
+ }
+#endif
+ *size += matchedSize;
return 0;
}
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index ff04118..f2f0cbb 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -30,6 +30,9 @@
#include <installd_constants.h>
+#define MEASURE_DEBUG 0
+#define MEASURE_EXTERNAL 0
+
namespace android {
namespace installd {
@@ -86,13 +89,16 @@
userid_t user, const char* package_name);
std::string create_data_media_path(const char* volume_uuid, userid_t userid);
+std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name);
std::string create_data_media_package_path(const char* volume_uuid, userid_t userid,
const char* data_type, const char* package_name);
std::string create_data_misc_legacy_path(userid_t userid);
-std::string create_data_user_profiles_path(userid_t userid);
+std::string create_data_user_profile_path(userid_t userid);
std::string create_data_user_profile_package_path(userid_t user, const char* package_name);
+
+std::string create_data_ref_profile_path();
std::string create_data_ref_profile_package_path(const char* package_name);
std::string create_data_dalvik_cache_path();
@@ -103,7 +109,7 @@
std::vector<userid_t> get_known_users(const char* volume_uuid);
int calculate_tree_size(const std::string& path, int64_t* size,
- gid_t include_gid = 0, gid_t exclude_gid = 0);
+ int32_t include_gid = -1, int32_t exclude_gid = -1, bool exclude_apps = false);
int create_user_config_path(char path[PKG_PATH_MAX], userid_t userid);