InstalldNativeService.cpp revision ea3a2b8f848a3a06667577e97ae9b0d5fb72c217
199e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten/* 265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** Copyright 2008, The Android Open Source Project 365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** 465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** Licensed under the Apache License, Version 2.0 (the "License"); 565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** you may not use this file except in compliance with the License. 665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** You may obtain a copy of the License at 765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** 865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** http://www.apache.org/licenses/LICENSE-2.0 965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** 1065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** Unless required by applicable law or agreed to in writing, software 1165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** distributed under the License is distributed on an "AS IS" BASIS, 1265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** See the License for the specific language governing permissions and 1465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** limitations under the License. 1565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian*/ 1665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "InstalldNativeService.h" 1865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER 2065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <errno.h> 2265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <inttypes.h> 2365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <fstream> 2465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <fts.h> 254ff14bae91075eb274eb1c2975982358946e7e63John Grossman#include <regex> 264ff14bae91075eb274eb1c2975982358946e7e63John Grossman#include <stdlib.h> 2765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <string.h> 2865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <sys/capability.h> 2965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <sys/file.h> 3065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <sys/resource.h> 31335787fe43596f38ea2fa50b24c54d0823a3fb1dGlenn Kasten#include <sys/quota.h> 324ff14bae91075eb274eb1c2975982358946e7e63John Grossman#include <sys/stat.h> 3365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <sys/statvfs.h> 3465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <sys/types.h> 3565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <sys/wait.h> 3665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <sys/xattr.h> 3765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <unistd.h> 38799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin 3965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <android-base/logging.h> 4065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <android-base/stringprintf.h> 415462fc9a38fa8c9dff434cd53fa5fb1782ae3042Mathias Agopian#include <android-base/strings.h> 425462fc9a38fa8c9dff434cd53fa5fb1782ae3042Mathias Agopian#include <android-base/unique_fd.h> 435462fc9a38fa8c9dff434cd53fa5fb1782ae3042Mathias Agopian#include <cutils/fs.h> 4464760240f931714858a59c1579f07264d7182ba2Dima Zavin#include <cutils/properties.h> 457394a4f358fa9908a9f0a7c954b65c399f4268e6Dima Zavin#include <cutils/sched_policy.h> 46a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent#include <log/log.h> // TODO: Move everything to base/logging. 4765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <logwrap/logwrap.h> 482dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <private/android_filesystem_config.h> 492dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <selinux/android.h> 5058912562617941964939a4182cda71eaeb153d4bGlenn Kasten#include <system/thread_defs.h> 512dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <utils/Trace.h> 52c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten 5365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "dexopt.h" 54feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent#include "globals.h" 55feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent#include "installd_deps.h" 5665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "otapreopt_utils.h" 5765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "utils.h" 5865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 5965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "CacheTracker.h" 6065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "MatchExtensionGen.h" 6165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 6265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#ifndef LOG_TAG 6358912562617941964939a4182cda71eaeb153d4bGlenn Kasten#define LOG_TAG "installd" 6465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 6565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 6665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianusing android::base::StringPrintf; 6753d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kastenusing std::endl; 6853d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kasten 6953d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kastennamespace android { 7053d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kastennamespace installd { 7153d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kasten 7253d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kastenstatic constexpr const char* kCpPath = "/system/bin/cp"; 7353d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kastenstatic constexpr const char* kXattrDefault = "user.default"; 7453d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kasten 7553d76dbe7c55821e89d9da02e7a563f7fb45de87Glenn Kastenstatic constexpr const int MIN_RESTRICTED_HOME_SDK_VERSION = 24; // > M 764ff14bae91075eb274eb1c2975982358946e7e63John Grossman 7765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic constexpr const char* PKG_LIB_POSTFIX = "/lib"; 785462fc9a38fa8c9dff434cd53fa5fb1782ae3042Mathias Agopianstatic constexpr const char* CACHE_DIR_POSTFIX = "/cache"; 795462fc9a38fa8c9dff434cd53fa5fb1782ae3042Mathias Agopianstatic constexpr const char* CODE_CACHE_DIR_POSTFIX = "/code_cache"; 805462fc9a38fa8c9dff434cd53fa5fb1782ae3042Mathias Agopian 8165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic constexpr const char* IDMAP_PREFIX = "/data/resource-cache/"; 821998661fdb6b0b5ae103e047e3d653c5da1b99e3Glenn Kastenstatic constexpr const char* IDMAP_SUFFIX = "@idmap"; 8365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 8454c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten// NOTE: keep in sync with StorageManager 8565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic constexpr int FLAG_STORAGE_DE = 1 << 0; 8665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic constexpr int FLAG_STORAGE_CE = 1 << 1; 8765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 882f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten// NOTE: keep in sync with Installer 8965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic constexpr int FLAG_CLEAR_CACHE_ONLY = 1 << 8; 9065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic constexpr int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9; 91fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kastenstatic constexpr int FLAG_USE_QUOTA = 1 << 12; 9265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic constexpr int FLAG_FREE_CACHE_V2 = 1 << 13; 9358f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kastenstatic constexpr int FLAG_FREE_CACHE_NOOP = 1 << 14; 94dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten 9565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiannamespace { 96a075db4ff9b086ac2885df77bb6da0869293df92Glenn Kasten 9765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianconstexpr const char* kDump = "android.permission.DUMP"; 9872ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten 993acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kastenstatic binder::Status ok() { 10065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return binder::Status::ok(); 10165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 10265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1032f732eb768004c6362fae8a02c60b69c9400b032Glenn Kastenstatic binder::Status exception(uint32_t code, const std::string& msg) { 1042f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten return binder::Status::fromExceptionCode(code, String8(msg.c_str())); 1052f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten} 1062f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten 1072f732eb768004c6362fae8a02c60b69c9400b032Glenn Kastenstatic binder::Status error() { 108dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten return binder::Status::fromServiceSpecificError(errno); 1092f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten} 110a075db4ff9b086ac2885df77bb6da0869293df92Glenn Kasten 1111879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kastenstatic binder::Status error(const std::string& msg) { 1122f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten PLOG(ERROR) << msg; 1132f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten return binder::Status::fromServiceSpecificError(errno, String8(msg.c_str())); 1142f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten} 11572ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten 11672ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kastenstatic binder::Status error(uint32_t code, const std::string& msg) { 11772ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten LOG(ERROR) << msg << " (" << code << ")"; 11872ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten return binder::Status::fromServiceSpecificError(code, String8(msg.c_str())); 11972ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten} 12065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 12165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbinder::Status checkPermission(const char* permission) { 12265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian pid_t pid; 12365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uid_t uid; 12465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 12565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (checkCallingPermission(String16(permission), reinterpret_cast<int32_t*>(&pid), 12665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian reinterpret_cast<int32_t*>(&uid))) { 12772ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten return ok(); 12872ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten } else { 129fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten return exception(binder::Status::EX_SECURITY, 13065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission)); 13172ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten } 13272ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten} 133fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten 13465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbinder::Status checkUid(uid_t expectedUid) { 135f78aee70d15daf4690de7e7b4983ee68b0d1381dGlenn Kasten uid_t uid = IPCThreadState::self()->getCallingUid(); 13665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (uid == expectedUid || uid == AID_ROOT) { 13765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return ok(); 13865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 13965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return exception(binder::Status::EX_SECURITY, 14072ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten StringPrintf("UID %d is not expected UID %d", uid, expectedUid)); 14172ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten } 14265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 14365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 14465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbinder::Status checkArgumentUuid(const std::unique_ptr<std::string>& uuid) { 145dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten if (!uuid || is_valid_filename(*uuid)) { 146dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten return ok(); 14765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 148a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent return exception(binder::Status::EX_ILLEGAL_ARGUMENT, 149a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent StringPrintf("UUID %s is malformed", uuid->c_str())); 150a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent } 151a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent} 152a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent 153a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurentbinder::Status checkArgumentPackageName(const std::string& packageName) { 1540ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent if (is_valid_package_name(packageName.c_str())) { 15565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return ok(); 15672ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten } else { 15772ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten return exception(binder::Status::EX_ILLEGAL_ARGUMENT, 15865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian StringPrintf("Package name %s is malformed", packageName.c_str())); 15972ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten } 16065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 16172ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten 16265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#define ENFORCE_UID(uid) { \ 16372ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten binder::Status status = checkUid((uid)); \ 16465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (!status.isOk()) { \ 165a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent return status; \ 166a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent } \ 167a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent} 168a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent 169a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent#define CHECK_ARGUMENT_UUID(uuid) { \ 17065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian binder::Status status = checkArgumentUuid((uuid)); \ 17172ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten if (!status.isOk()) { \ 17265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return status; \ 17372ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten } \ 17465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 17565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 17665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#define CHECK_ARGUMENT_PACKAGE_NAME(packageName) { \ 17772ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten binder::Status status = \ 17872ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten checkArgumentPackageName((packageName)); \ 17965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (!status.isOk()) { \ 1802f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten return status; \ 1812f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten } \ 18265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 18365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1843a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen} // namespace 1853a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen 1863a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissenstatus_t InstalldNativeService::start() { 1873a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen IPCThreadState::self()->disableBackgroundScheduling(true); 188f587ba5b991c7cd91e4df093d0d796bd419e5d67Glenn Kasten status_t ret = BinderService<InstalldNativeService>::publish(); 18965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (ret != android::OK) { 190f587ba5b991c7cd91e4df093d0d796bd419e5d67Glenn Kasten return ret; 19165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 1925e92a7861196ddae14638d4b7a63fc4892b7ef59Glenn Kasten sp<ProcessState> ps(ProcessState::self()); 193f587ba5b991c7cd91e4df093d0d796bd419e5d67Glenn Kasten ps->startThreadPool(); 19465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ps->giveThreadPoolName(); 19565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return android::OK; 19665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 19765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 19865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */) { 19972ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten auto out = std::fstream(StringPrintf("/proc/self/fd/%d", fd)); 20065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const binder::Status dump_permission = checkPermission(kDump); 20165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (!dump_permission.isOk()) { 20265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out << dump_permission.toString8() << endl; 20365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return PERMISSION_DENIED; 20465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 20572ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten std::lock_guard<std::recursive_mutex> lock(mLock); 20672ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten 20765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out << "installd is happy!" << endl; 208a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent 209a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent out << endl << "Devices with quota support:" << endl; 210cc0f1cfb69ce8b8985fc2c0984847a06a13ad22dGlenn Kasten for (const auto& n : mQuotaDevices) { 211cc0f1cfb69ce8b8985fc2c0984847a06a13ad22dGlenn Kasten out << " " << n.first << " = " << n.second << endl; 212cc0f1cfb69ce8b8985fc2c0984847a06a13ad22dGlenn Kasten } 21365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 21465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out << endl << "Per-UID cache quotas:" << endl; 21565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian for (const auto& n : mCacheQuotas) { 21665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out << " " << n.first << " = " << n.second << endl; 21765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 21865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2192f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten out << endl; 2202f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten out.flush(); 221a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 222a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent return NO_ERROR; 223a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent} 224a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 225a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent/** 226a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent * Perform restorecon of the given path, but only perform recursive restorecon 227a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent * if the label of that top-level file actually changed. This can save us 228a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent * significant time by avoiding no-op traversals of large filesystem trees. 229a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent */ 230a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurentstatic int restorecon_app_data_lazy(const std::string& path, const std::string& seInfo, uid_t uid, 231a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent bool existing) { 232a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent int res = 0; 233a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent char* before = nullptr; 234a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent char* after = nullptr; 235a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 236a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent // Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by 237a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent // libselinux. Not needed here. 238a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 239106e8a42038f9e90d5ff97f8ab6f1a42258bde9eGlenn Kasten if (lgetfilecon(path.c_str(), &before) < 0) { 240106e8a42038f9e90d5ff97f8ab6f1a42258bde9eGlenn Kasten PLOG(ERROR) << "Failed before getfilecon for " << path; 241a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent goto fail; 242a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent } 243a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid, 0) < 0) { 244a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent PLOG(ERROR) << "Failed top-level restorecon for " << path; 245a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent goto fail; 246a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent } 247a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent if (lgetfilecon(path.c_str(), &after) < 0) { 248a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent PLOG(ERROR) << "Failed after getfilecon for " << path; 249a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent goto fail; 250a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent } 251a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 252106e8a42038f9e90d5ff97f8ab6f1a42258bde9eGlenn Kasten // If the initial top-level restorecon above changed the label, then go 253a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent // back and restorecon everything recursively 254a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent if (strcmp(before, after)) { 255a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent if (existing) { 256a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at " 257a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent << path << "; running recursive restorecon"; 258a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent } 259a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid, 260717e128691f083a9469a1d0e363ac6ecd5c65d58Eric Laurent SELINUX_ANDROID_RESTORECON_RECURSE) < 0) { 2612f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten PLOG(ERROR) << "Failed recursive restorecon for " << path; 262ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman goto fail; 263ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman } 264f78aee70d15daf4690de7e7b4983ee68b0d1381dGlenn Kasten } 26565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 266c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten goto done; 26759bd0da8373af0e5159b799495fda51e03120ea4Eric Laurentfail: 26865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res = -1; 26965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiandone: 27065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian free(before); 2712b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten free(after); 2722b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten return res; 2732b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten} 274000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten 2755a61d2f277af3098fc10b2881babca16391362daDima Zavinstatic int restorecon_app_data_lazy(const std::string& parent, const char* name, 276000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten const std::string& seInfo, uid_t uid, bool existing) { 277ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman return restorecon_app_data_lazy(StringPrintf("%s/%s", parent.c_str(), name), seInfo, uid, 2783a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen existing); 27965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 28066fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten 28166fcab972e9218d47c58a915f391b2f48a09903aGlenn Kastenstatic int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid) { 2824ff14bae91075eb274eb1c2975982358946e7e63John Grossman if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) { 2834ff14bae91075eb274eb1c2975982358946e7e63John Grossman PLOG(ERROR) << "Failed to prepare " << path; 284be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kasten return -1; 285be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kasten } 286be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kasten return 0; 287be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kasten} 28865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 28965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/** 29065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Prepare an app cache directory, which offers to fix-up the GID and 29165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * directory mode flags during a platform upgrade. 29265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian */ 29365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t target_mode, 294435dbe6c3ecd04bcb4bd80584064e287ebccd720Glenn Kasten uid_t uid, gid_t gid) { 29565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto path = StringPrintf("%s/%s", parent.c_str(), name); 296c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten struct stat st; 29765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (stat(path.c_str(), &st) != 0) { 2984ff14bae91075eb274eb1c2975982358946e7e63John Grossman if (errno == ENOENT) { 2994ff14bae91075eb274eb1c2975982358946e7e63John Grossman // This is fine, just create it 3004ff14bae91075eb274eb1c2975982358946e7e63John Grossman if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, gid) != 0) { 30165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian PLOG(ERROR) << "Failed to prepare " << path; 30265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return -1; 30365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 30484afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten return 0; 30584afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten } 30684afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten } else { 3074ff14bae91075eb274eb1c2975982358946e7e63John Grossman PLOG(ERROR) << "Failed to stat " << path; 3084ff14bae91075eb274eb1c2975982358946e7e63John Grossman return -1; 3094ff14bae91075eb274eb1c2975982358946e7e63John Grossman } 31065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 31165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 31265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mode_t actual_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID); 31365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (st.st_uid != uid) { 31465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Mismatched UID is real trouble; we can't recover 31565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian LOG(ERROR) << "Mismatched UID at " << path << ": found " << st.st_uid 31665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian << " but expected " << uid; 31765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return -1; 31865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else if (st.st_gid == gid && actual_mode == target_mode) { 31965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Everything looks good! 32084afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten return 0; 32165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 32265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 32365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Directory is owned correctly, but GID or mode mismatch means it's 32465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // probably a platform upgrade so we need to fix them 32565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian FTS *fts; 32665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian FTSENT *p; 32765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian char *argv[] = { (char*) path.c_str(), nullptr }; 32865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) { 32984afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten PLOG(ERROR) << "Failed to fts_open " << path; 33084afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten return -1; 33184afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten } 33265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while ((p = fts_read(fts)) != NULL) { 33365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian switch (p->fts_info) { 33465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case FTS_DP: 33565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (chmod(p->fts_accpath, target_mode) != 0) { 33665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian PLOG(WARNING) << "Failed to chmod " << p->fts_path; 33765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 33865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Intentional fall through to also set GID 33965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case FTS_F: 34065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (chown(p->fts_accpath, -1, gid) != 0) { 34165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian PLOG(WARNING) << "Failed to chown " << p->fts_path; 34265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 34365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; 34465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case FTS_SL: 34565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case FTS_SLNONE: 346799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin if (lchown(p->fts_accpath, -1, gid) != 0) { 347799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin PLOG(WARNING) << "Failed to chown " << p->fts_path; 34865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 34965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; 35065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 3517c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent } 35223bb8becff20449a9b1647d5a1a99b14c83f0cceGlenn Kasten fts_close(fts); 3537c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent return 0; 3547c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent} 3557c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent 3567c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurentbinder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::string>& uuid, 3577c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent const std::string& packageName, int32_t userId, int32_t flags, int32_t appId, 3587c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent const std::string& seInfo, int32_t targetSdkVersion, int64_t* _aidl_return) { 359f1c04f952916cf70407051c9f824ab84fb2b6e09Eric Laurent ENFORCE_UID(AID_SYSTEM); 360f1c04f952916cf70407051c9f824ab84fb2b6e09Eric Laurent CHECK_ARGUMENT_UUID(uuid); 36123bb8becff20449a9b1647d5a1a99b14c83f0cceGlenn Kasten CHECK_ARGUMENT_PACKAGE_NAME(packageName); 36223bb8becff20449a9b1647d5a1a99b14c83f0cceGlenn Kasten std::lock_guard<std::recursive_mutex> lock(mLock); 363be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kasten 364be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kasten const char* uuid_ = uuid ? uuid->c_str() : nullptr; 36565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char* pkgname = packageName.c_str(); 366feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent 367feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent // Assume invalid inode unless filled in below 36865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (_aidl_return != nullptr) *_aidl_return = -1; 369288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten 37065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t uid = multiuser_get_uid(userId, appId); 37165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t cacheGid = multiuser_get_cache_gid(userId, appId); 37265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mode_t targetMode = targetSdkVersion >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751; 37365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 37465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // If UID doesn't have a specific cache GID, use UID value 3752986460984580833161bdaabc7f17da1005a8961Eric Laurent if (cacheGid == -1) { 37665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian cacheGid = uid; 377d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten } 378d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten 379d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten if (flags & FLAG_STORAGE_CE) { 38065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto path = create_data_user_ce_package_path(uuid_, userId, pkgname); 38165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian bool existing = (access(path.c_str(), F_OK) == 0); 38265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 38365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (prepare_app_dir(path, targetMode, uid) || 38465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) || 38565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) { 3869eaa55756c5b245970447019250ce852f5189525Glenn Kasten return error("Failed to prepare " + path); 38765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 38865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 38958f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten // Consider restorecon over contents if label changed 390254af180475346b6186b49c297f340c9c4817511Glenn Kasten if (restorecon_app_data_lazy(path, seInfo, uid, existing) || 39165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) || 39265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) { 39365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return error("Failed to restorecon " + path); 394c19e22450e6e3d07594c935c7a9522e85e909e82Glenn Kasten } 39565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 3960ec23ce0d1ff79566c402bc30df3074f6e25a22bGlenn Kasten // Remember inode numbers of cache directories so that we can clear 3970ec23ce0d1ff79566c402bc30df3074f6e25a22bGlenn Kasten // contents while CE storage is locked 39865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (write_path_inode(path, "cache", kXattrInodeCache) || 399c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten write_path_inode(path, "code_cache", kXattrInodeCodeCache)) { 40065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return error("Failed to write_path_inode for " + path); 401c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten } 402a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 40365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // And return the CE inode of the top-level data directory so we can 40465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // clear contents while CE storage is locked 40565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if ((_aidl_return != nullptr) 40665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian && get_path_inode(path, reinterpret_cast<ino_t*>(_aidl_return)) != 0) { 40765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return error("Failed to get_path_inode for " + path); 40801c4ebf6b794493898114a502ed36de13137f7e5Glenn Kasten } 40901c4ebf6b794493898114a502ed36de13137f7e5Glenn Kasten } 41065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (flags & FLAG_STORAGE_DE) { 41165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto path = create_data_user_de_package_path(uuid_, userId, pkgname); 412288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten bool existing = (access(path.c_str(), F_OK) == 0); 413288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten 414288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten if (prepare_app_dir(path, targetMode, uid) || 415288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) || 41658f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) { 41765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return error("Failed to prepare " + path); 41865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 41965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 420c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten // Consider restorecon over contents if label changed 42165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (restorecon_app_data_lazy(path, seInfo, uid, existing)) { 422254af180475346b6186b49c297f340c9c4817511Glenn Kasten return error("Failed to restorecon " + path); 4230d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi } 424c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten 42565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (property_get_bool("dalvik.vm.usejitprofiles", false)) { 4266648821933dc06c0b09ab2c8b32135edddcd4291Glenn Kasten const std::string profile_path = create_data_user_profile_package_path(userId, pkgname); 4276648821933dc06c0b09ab2c8b32135edddcd4291Glenn Kasten // read-write-execute only for the app user. 4286648821933dc06c0b09ab2c8b32135edddcd4291Glenn Kasten if (fs_prepare_dir_strict(profile_path.c_str(), 0700, uid, uid) != 0) { 4296648821933dc06c0b09ab2c8b32135edddcd4291Glenn Kasten return error("Failed to prepare " + profile_path); 4306648821933dc06c0b09ab2c8b32135edddcd4291Glenn Kasten } 4316648821933dc06c0b09ab2c8b32135edddcd4291Glenn Kasten std::string profile_file = create_primary_profile(profile_path); 4326648821933dc06c0b09ab2c8b32135edddcd4291Glenn Kasten // read-write only for the app user. 43365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (fs_prepare_file_strict(profile_file.c_str(), 0600, uid, uid) != 0) { 43465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return error("Failed to prepare " + profile_path); 43565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 4362986460984580833161bdaabc7f17da1005a8961Eric Laurent const std::string ref_profile_path = create_data_ref_profile_package_path(pkgname); 43765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // dex2oat/profman runs under the shared app gid and it needs to read/write reference 43865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // profiles. 439d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten int shared_app_gid = multiuser_get_shared_gid(0, appId); 440d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten if ((shared_app_gid != -1) && fs_prepare_dir_strict( 441d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten ref_profile_path.c_str(), 0700, shared_app_gid, shared_app_gid) != 0) { 442d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten return error("Failed to prepare " + ref_profile_path); 443d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten } 444d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten } 445d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten } 446d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten return ok(); 447d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten} 448d08f48c2ad2941d62b313007955c7145075d562cGlenn Kasten 449d08f48c2ad2941d62b313007955c7145075d562cGlenn Kastenbinder::Status InstalldNativeService::migrateAppData(const std::unique_ptr<std::string>& uuid, 45065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const std::string& packageName, int32_t userId, int32_t flags) { 45165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ENFORCE_UID(AID_SYSTEM); 45265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian CHECK_ARGUMENT_UUID(uuid); 45365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian CHECK_ARGUMENT_PACKAGE_NAME(packageName); 45465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::lock_guard<std::recursive_mutex> lock(mLock); 45565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 45665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char* uuid_ = uuid ? uuid->c_str() : nullptr; 45784afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten const char* pkgname = packageName.c_str(); 45884afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten 45965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // This method only exists to upgrade system apps that have requested 46065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // forceDeviceEncrypted, so their default storage always lives in a 461c3ae93f21280859086ae371428ffd32f39e76d50Glenn Kasten // consistent location. This only works on non-FBE devices, since we 462c3ae93f21280859086ae371428ffd32f39e76d50Glenn Kasten // never want to risk exposing data on a device with real CE/DE storage. 463c3ae93f21280859086ae371428ffd32f39e76d50Glenn Kasten 46465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto ce_path = create_data_user_ce_package_path(uuid_, userId, pkgname); 46565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto de_path = create_data_user_de_package_path(uuid_, userId, pkgname); 466b853e986caf43408ad95b9014f194aadff385e3cGlenn Kasten 46758912562617941964939a4182cda71eaeb153d4bGlenn Kasten // If neither directory is marked as default, assume CE is default 46858912562617941964939a4182cda71eaeb153d4bGlenn Kasten if (getxattr(ce_path.c_str(), kXattrDefault, nullptr, 0) == -1 46984afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten && getxattr(de_path.c_str(), kXattrDefault, nullptr, 0) == -1) { 4705cf034d92d901169ca6e36c90475f40715827fcdGlenn Kasten if (setxattr(ce_path.c_str(), kXattrDefault, nullptr, 0, 0) != 0) { 47184afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten return error("Failed to mark default storage " + ce_path); 4720d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi } 473254af180475346b6186b49c297f340c9c4817511Glenn Kasten } 474a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 47565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Migrate default data location if needed 47665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto target = (flags & FLAG_STORAGE_DE) ? de_path : ce_path; 477896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent auto source = (flags & FLAG_STORAGE_DE) ? ce_path : de_path; 478896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent 479896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent if (getxattr(target.c_str(), kXattrDefault, nullptr, 0) == -1) { 480896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent LOG(WARNING) << "Requested default storage " << target 481896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent << " is not active; migrating from " << source; 48265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (delete_dir_contents_and_dir(target) != 0) { 48365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return error("Failed to delete " + target); 484896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent } 485896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent if (rename(source.c_str(), target.c_str()) != 0) { 486896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent return error("Failed to rename " + source + " to " + target); 487896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent } 488896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent } 489896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent 490896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent return ok(); 491896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent} 492896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent 493896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent 494896adcd3ae6a1c7010e526327eff54e16179987bEric Laurentbinder::Status InstalldNativeService::clearAppProfiles(const std::string& packageName) { 495896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent ENFORCE_UID(AID_SYSTEM); 496896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent CHECK_ARGUMENT_PACKAGE_NAME(packageName); 497896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent std::lock_guard<std::recursive_mutex> lock(mLock); 498896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent 499896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent const char* pkgname = packageName.c_str(); 500896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent binder::Status res = ok(); 501896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent if (!clear_reference_profile(pkgname)) { 502896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent res = error("Failed to clear reference profile for " + packageName); 503896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent } 504896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent if (!clear_current_profiles(pkgname)) { 505896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent res = error("Failed to clear current profiles for " + packageName); 506896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent } 507896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent return res; 508896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent} 509896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent 510896adcd3ae6a1c7010e526327eff54e16179987bEric Laurentbinder::Status InstalldNativeService::clearAppData(const std::unique_ptr<std::string>& uuid, 511896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) { 512896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent ENFORCE_UID(AID_SYSTEM); 513896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent CHECK_ARGUMENT_UUID(uuid); 514896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent CHECK_ARGUMENT_PACKAGE_NAME(packageName); 515896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent std::lock_guard<std::recursive_mutex> lock(mLock); 516896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent 517896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent const char* uuid_ = uuid ? uuid->c_str() : nullptr; 51865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char* pkgname = packageName.c_str(); 519896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent 520896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent binder::Status res = ok(); 521896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent if (flags & FLAG_STORAGE_CE) { 522896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode); 523896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent if (flags & FLAG_CLEAR_CACHE_ONLY) { 524896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent path = read_path_inode(path, "cache", kXattrInodeCache); 525896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) { 526896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent path = read_path_inode(path, "code_cache", kXattrInodeCodeCache); 527896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent } 528896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent if (access(path.c_str(), F_OK) == 0) { 529896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent if (delete_dir_contents(path) != 0) { 530896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent res = error("Failed to delete contents of " + path); 53165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 53265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 533896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent } 534feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent if (flags & FLAG_STORAGE_DE) { 535feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent std::string suffix = ""; 536feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent bool only_cache = false; 537feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent if (flags & FLAG_CLEAR_CACHE_ONLY) { 538feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent suffix = CACHE_DIR_POSTFIX; 539feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent only_cache = true; 540feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) { 541feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent suffix = CODE_CACHE_DIR_POSTFIX; 542feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent only_cache = true; 543feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent } 544feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent 545feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent auto path = create_data_user_de_package_path(uuid_, userId, pkgname) + suffix; 546feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent if (access(path.c_str(), F_OK) == 0) { 547feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent if (delete_dir_contents(path) != 0) { 548feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent res = error("Failed to delete contents of " + path); 5497c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent } 55001542f2704f39956da09ae2840e192dab760091fGlenn Kasten } 55101542f2704f39956da09ae2840e192dab760091fGlenn Kasten if (!only_cache) { 55223bb8becff20449a9b1647d5a1a99b14c83f0cceGlenn Kasten if (!clear_current_profile(pkgname, userId)) { 55301542f2704f39956da09ae2840e192dab760091fGlenn Kasten res = error("Failed to clear current profile for " + packageName); 55401542f2704f39956da09ae2840e192dab760091fGlenn Kasten } 55501542f2704f39956da09ae2840e192dab760091fGlenn Kasten } 556c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten } 557c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten return res; 558254af180475346b6186b49c297f340c9c4817511Glenn Kasten} 559c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten 56058912562617941964939a4182cda71eaeb153d4bGlenn Kastenstatic int destroy_app_reference_profile(const char *pkgname) { 561cc0f1cfb69ce8b8985fc2c0984847a06a13ad22dGlenn Kasten return delete_dir_contents_and_dir( 56258912562617941964939a4182cda71eaeb153d4bGlenn Kasten create_data_ref_profile_package_path(pkgname), 563cc0f1cfb69ce8b8985fc2c0984847a06a13ad22dGlenn Kasten /*ignore_if_missing*/ true); 564cc0f1cfb69ce8b8985fc2c0984847a06a13ad22dGlenn Kasten} 56501542f2704f39956da09ae2840e192dab760091fGlenn Kasten 566b28686f95daee16edeb5f39af2cd5274ac3dc99fGlenn Kastenstatic int destroy_app_current_profiles(const char *pkgname, userid_t userid) { 567b28686f95daee16edeb5f39af2cd5274ac3dc99fGlenn Kasten return delete_dir_contents_and_dir( 56865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian create_data_user_profile_package_path(userid, pkgname), 56965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian /*ignore_if_missing*/ true); 57065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 57165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 57265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbinder::Status InstalldNativeService::destroyAppProfiles(const std::string& packageName) { 573896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent ENFORCE_UID(AID_SYSTEM); 574896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent CHECK_ARGUMENT_PACKAGE_NAME(packageName); 575896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent std::lock_guard<std::recursive_mutex> lock(mLock); 57665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 57701542f2704f39956da09ae2840e192dab760091fGlenn Kasten const char* pkgname = packageName.c_str(); 578f1c04f952916cf70407051c9f824ab84fb2b6e09Eric Laurent binder::Status res = ok(); 57902fe1bf923bbe5789202dbd5810e2c04794562e6Glenn Kasten std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr); 580f1c04f952916cf70407051c9f824ab84fb2b6e09Eric Laurent for (auto user : users) { 581f1c04f952916cf70407051c9f824ab84fb2b6e09Eric Laurent if (destroy_app_current_profiles(pkgname, user) != 0) { 58201542f2704f39956da09ae2840e192dab760091fGlenn Kasten res = error("Failed to destroy current profiles for " + packageName); 5830bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten } 5847c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent } 5857c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent if (destroy_app_reference_profile(pkgname) != 0) { 5867c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent res = error("Failed to destroy reference profile for " + packageName); 5877c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent } 5887c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent return res; 5897c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent} 5907c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent 5917c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurentbinder::Status InstalldNativeService::destroyAppData(const std::unique_ptr<std::string>& uuid, 5927c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) { 5937c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent ENFORCE_UID(AID_SYSTEM); 594a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent CHECK_ARGUMENT_UUID(uuid); 59558123c3a8b5f34f9d1f70264a3c568ed90288501Glenn Kasten CHECK_ARGUMENT_PACKAGE_NAME(packageName); 5967c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent std::lock_guard<std::recursive_mutex> lock(mLock); 5977c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent 5987c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent const char* uuid_ = uuid ? uuid->c_str() : nullptr; 5997c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent const char* pkgname = packageName.c_str(); 6007c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent 6017c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent binder::Status res = ok(); 6027c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent if (flags & FLAG_STORAGE_CE) { 6037c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode); 6047c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent if (delete_dir_contents_and_dir(path) != 0) { 6057c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent res = error("Failed to delete " + path); 6067c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent } 6077c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent } 608106e8a42038f9e90d5ff97f8ab6f1a42258bde9eGlenn Kasten if (flags & FLAG_STORAGE_DE) { 6097c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent auto path = create_data_user_de_package_path(uuid_, userId, pkgname); 6107c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent if (delete_dir_contents_and_dir(path) != 0) { 6117c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent res = error("Failed to delete " + path); 6127c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent } 613d805b718b1fd2d5407ef665c8d4bb42e63dc71a9Glenn Kasten destroy_app_current_profiles(pkgname, userId); 6147c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent // TODO(calin): If the package is still installed by other users it's probably 6157c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent // beneficial to keep the reference profile around. 616d805b718b1fd2d5407ef665c8d4bb42e63dc71a9Glenn Kasten // Verify if it's ok to do that. 617e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten destroy_app_reference_profile(pkgname); 6187c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent } 619e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten return res; 6207c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent} 621f78aee70d15daf4690de7e7b4983ee68b0d1381dGlenn Kasten 6227c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurentbinder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid, 623717e128691f083a9469a1d0e363ac6ecd5c65d58Eric Laurent const std::unique_ptr<std::string>& toUuid, const std::string& packageName, 6247c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent const std::string& dataAppName, int32_t appId, const std::string& seInfo, 6257c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent int32_t targetSdkVersion) { 6267c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent ENFORCE_UID(AID_SYSTEM); 6277c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent CHECK_ARGUMENT_UUID(fromUuid); 6287c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent CHECK_ARGUMENT_UUID(toUuid); 6297c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent CHECK_ARGUMENT_PACKAGE_NAME(packageName); 6307c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent std::lock_guard<std::recursive_mutex> lock(mLock); 6317c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent 6327c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent const char* from_uuid = fromUuid ? fromUuid->c_str() : nullptr; 6337c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent const char* to_uuid = toUuid ? toUuid->c_str() : nullptr; 6347c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent const char* package_name = packageName.c_str(); 635106e8a42038f9e90d5ff97f8ab6f1a42258bde9eGlenn Kasten const char* data_app_name = dataAppName.c_str(); 6367c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent 6377c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent binder::Status res = ok(); 6387c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent std::vector<userid_t> users = get_known_users(from_uuid); 63965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 64059255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent // Copy app 64159255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent { 64259255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent auto from = create_data_app_package_path(from_uuid, data_app_name); 64359255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent auto to = create_data_app_package_path(to_uuid, data_app_name); 64459255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent auto to_parent = create_data_app_path(to_uuid); 64559255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent 64659255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent char *argv[] = { 647a85a74a8219c03f2b1d1ef98f3f02e55f89f89a3Eric Laurent (char*) kCpPath, 64859255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent (char*) "-F", /* delete any existing destination file first (--remove-destination) */ 64959255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent (char*) "-p", /* preserve timestamps, ownership, and permissions */ 650a85a74a8219c03f2b1d1ef98f3f02e55f89f89a3Eric Laurent (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ 651a85a74a8219c03f2b1d1ef98f3f02e55f89f89a3Eric Laurent (char*) "-P", /* Do not follow symlinks [default] */ 652a85a74a8219c03f2b1d1ef98f3f02e55f89f89a3Eric Laurent (char*) "-d", /* don't dereference symlinks */ 653a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent (char*) from.c_str(), 654a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent (char*) to_parent.c_str() 655106e8a42038f9e90d5ff97f8ab6f1a42258bde9eGlenn Kasten }; 656a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 657a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent LOG(DEBUG) << "Copying " << from << " to " << to; 65865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); 65965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (rc != 0) { 66065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res = error(rc, "Failed copying " + from + " to " + to); 66165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian goto fail; 66259255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent } 66359255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent 66459255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent if (selinux_android_restorecon(to.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) { 66559255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent res = error("Failed to restorecon " + to); 66659255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent goto fail; 66759255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent } 66859255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent } 66959255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent 67059255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent // Copy private data for all known users 671feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent for (auto user : users) { 672feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent 673feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent // Data source may not exist for all users; that's okay 674feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent auto from_ce = create_data_user_ce_package_path(from_uuid, user, package_name); 67559255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent if (access(from_ce.c_str(), F_OK) != 0) { 67659255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent LOG(INFO) << "Missing source " << from_ce; 6770a7af18d0308295405491f86603e3d119450aba0Glenn Kasten continue; 67859255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent } 67959255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent 68059255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent if (!createAppData(toUuid, packageName, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE, appId, 68159255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent seInfo, targetSdkVersion, nullptr).isOk()) { 68259255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent res = error("Failed to create package target"); 68359255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent goto fail; 684feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent } 6851998661fdb6b0b5ae103e047e3d653c5da1b99e3Glenn Kasten 68665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian char *argv[] = { 68723bb8becff20449a9b1647d5a1a99b14c83f0cceGlenn Kasten (char*) kCpPath, 688cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten (char*) "-F", /* delete any existing destination file first (--remove-destination) */ 689cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten (char*) "-p", /* preserve timestamps, ownership, and permissions */ 69065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ 691cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten (char*) "-P", /* Do not follow symlinks [default] */ 69284afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten (char*) "-d", /* don't dereference symlinks */ 69365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian nullptr, 69458912562617941964939a4182cda71eaeb153d4bGlenn Kasten nullptr 69558912562617941964939a4182cda71eaeb153d4bGlenn Kasten }; 696254af180475346b6186b49c297f340c9c4817511Glenn Kasten 69765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian { 698b9980659501d0428d65d8292f3c32da69d37fbd2Glenn Kasten auto from = create_data_user_de_package_path(from_uuid, user, package_name); 69958f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten auto to = create_data_user_de_path(to_uuid, user); 700cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten argv[6] = (char*) from.c_str(); 701cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten argv[7] = (char*) to.c_str(); 702cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten 703cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten LOG(DEBUG) << "Copying " << from << " to " << to; 704cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); 705cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten if (rc != 0) { 706cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten res = error(rc, "Failed copying " + from + " to " + to); 707cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten goto fail; 708cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten } 709cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten } 710cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten { 711cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten auto from = create_data_user_ce_package_path(from_uuid, user, package_name); 712cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten auto to = create_data_user_ce_path(to_uuid, user); 713cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten argv[6] = (char*) from.c_str(); 714cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten argv[7] = (char*) to.c_str(); 715cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten 716cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten LOG(DEBUG) << "Copying " << from << " to " << to; 717cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); 718cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten if (rc != 0) { 719cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten res = error(rc, "Failed copying " + from + " to " + to); 72065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian goto fail; 72165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 72265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 723cbc52bfb3b51c81c945b1e35990324bde892829aGlenn Kasten 724896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent if (!restoreconAppData(toUuid, packageName, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE, 72501542f2704f39956da09ae2840e192dab760091fGlenn Kasten appId, seInfo).isOk()) { 72601542f2704f39956da09ae2840e192dab760091fGlenn Kasten res = error("Failed to restorecon"); 727f1c04f952916cf70407051c9f824ab84fb2b6e09Eric Laurent goto fail; 728f1c04f952916cf70407051c9f824ab84fb2b6e09Eric Laurent } 72901542f2704f39956da09ae2840e192dab760091fGlenn Kasten } 73001542f2704f39956da09ae2840e192dab760091fGlenn Kasten 73101542f2704f39956da09ae2840e192dab760091fGlenn Kasten // We let the framework scan the new location and persist that before 73201542f2704f39956da09ae2840e192dab760091fGlenn Kasten // deleting the data in the old location; this ordering ensures that 733f1c04f952916cf70407051c9f824ab84fb2b6e09Eric Laurent // we can recover from things like battery pulls. 734f1c04f952916cf70407051c9f824ab84fb2b6e09Eric Laurent return ok(); 73557b2dd1e78af53115985f18d31ec5421c9da947eEric Laurent 73601542f2704f39956da09ae2840e192dab760091fGlenn Kastenfail: 73772ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten // Nuke everything we might have already copied 7387c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent { 73901542f2704f39956da09ae2840e192dab760091fGlenn Kasten auto to = create_data_app_package_path(to_uuid, data_app_name); 740480b46802bef1371d5caa16ad5454fce04769c57Glenn Kasten if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { 741feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent LOG(WARNING) << "Failed to rollback " << to; 742feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent } 743feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent } 74484afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten for (auto user : users) { 74559255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent { 74659255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent auto to = create_data_user_de_package_path(to_uuid, user, package_name); 74759255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { 74865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian LOG(WARNING) << "Failed to rollback " << to; 74965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 750b7bf796b758e144f94f6ed4d16c21bf22a118fb3Glenn Kasten } 751b7bf796b758e144f94f6ed4d16c21bf22a118fb3Glenn Kasten { 752b7bf796b758e144f94f6ed4d16c21bf22a118fb3Glenn Kasten auto to = create_data_user_ce_package_path(to_uuid, user, package_name); 7531a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { 754b7bf796b758e144f94f6ed4d16c21bf22a118fb3Glenn Kasten LOG(WARNING) << "Failed to rollback " << to; 755b7bf796b758e144f94f6ed4d16c21bf22a118fb3Glenn Kasten } 756b7bf796b758e144f94f6ed4d16c21bf22a118fb3Glenn Kasten } 757b7bf796b758e144f94f6ed4d16c21bf22a118fb3Glenn Kasten } 758b7bf796b758e144f94f6ed4d16c21bf22a118fb3Glenn Kasten return res; 759b7bf796b758e144f94f6ed4d16c21bf22a118fb3Glenn Kasten} 76065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 76165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbinder::Status InstalldNativeService::createUserData(const std::unique_ptr<std::string>& uuid, 76265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t userId, int32_t userSerial ATTRIBUTE_UNUSED, int32_t flags) { 76365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ENFORCE_UID(AID_SYSTEM); 76465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian CHECK_ARGUMENT_UUID(uuid); 765d805b718b1fd2d5407ef665c8d4bb42e63dc71a9Glenn Kasten std::lock_guard<std::recursive_mutex> lock(mLock); 766d805b718b1fd2d5407ef665c8d4bb42e63dc71a9Glenn Kasten 767d805b718b1fd2d5407ef665c8d4bb42e63dc71a9Glenn Kasten const char* uuid_ = uuid ? uuid->c_str() : nullptr; 768d805b718b1fd2d5407ef665c8d4bb42e63dc71a9Glenn Kasten if (flags & FLAG_STORAGE_DE) { 769d805b718b1fd2d5407ef665c8d4bb42e63dc71a9Glenn Kasten if (uuid_ == nullptr) { 77065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (ensure_config_user_dirs(userId) != 0) { 77165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return error(StringPrintf("Failed to ensure dirs for %d", userId)); 77265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 77358912562617941964939a4182cda71eaeb153d4bGlenn Kasten } 77465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 7759eaa55756c5b245970447019250ce852f5189525Glenn Kasten return ok(); 77665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 777fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten 77865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbinder::Status InstalldNativeService::destroyUserData(const std::unique_ptr<std::string>& uuid, 77958f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten int32_t userId, int32_t flags) { 780254af180475346b6186b49c297f340c9c4817511Glenn Kasten ENFORCE_UID(AID_SYSTEM); 78165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian CHECK_ARGUMENT_UUID(uuid); 78265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::lock_guard<std::recursive_mutex> lock(mLock); 78373d227557ba5192735356bacab9f77b44980793bGlenn Kasten 78473d227557ba5192735356bacab9f77b44980793bGlenn Kasten const char* uuid_ = uuid ? uuid->c_str() : nullptr; 785c19e22450e6e3d07594c935c7a9522e85e909e82Glenn Kasten binder::Status res = ok(); 78665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (flags & FLAG_STORAGE_DE) { 787288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten auto path = create_data_user_de_path(uuid_, userId); 78865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (delete_dir_contents_and_dir(path, true) != 0) { 7893acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten res = error("Failed to delete " + path); 790a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent } 79165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (uuid_ == nullptr) { 79265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian path = create_data_misc_legacy_path(userId); 79365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (delete_dir_contents_and_dir(path, true) != 0) { 79465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res = error("Failed to delete " + path); 79565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 79665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian path = create_data_user_profile_path(userId); 7979f34a36d9cdb9595c288e50ffe00da038bc8abb9Glenn Kasten if (delete_dir_contents_and_dir(path, true) != 0) { 79865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res = error("Failed to delete " + path); 79902bbd20cece1785c223ac4ca2ddc635931a80673Glenn Kasten } 80065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 80165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 80265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (flags & FLAG_STORAGE_CE) { 80365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto path = create_data_user_ce_path(uuid_, userId); 804c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten if (delete_dir_contents_and_dir(path, true) != 0) { 80565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res = error("Failed to delete " + path); 806c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten } 807c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten path = create_data_media_path(uuid_, userId); 80865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (delete_dir_contents_and_dir(path, true) != 0) { 80958912562617941964939a4182cda71eaeb153d4bGlenn Kasten res = error("Failed to delete " + path); 81058912562617941964939a4182cda71eaeb153d4bGlenn Kasten } 8112986460984580833161bdaabc7f17da1005a8961Eric Laurent } 81273d227557ba5192735356bacab9f77b44980793bGlenn Kasten return res; 81365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 8141998661fdb6b0b5ae103e047e3d653c5da1b99e3Glenn Kasten 81565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/* Try to ensure free_size bytes of storage are available. 81665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Returns 0 on success. 81765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * This is rather simple-minded because doing a full LRU would 81865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * be potentially memory-intensive, and without atime it would 81965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * also require that apps constantly modify file metadata even 82065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * when just reading from the cache, which is pretty awful. 82165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian */ 82201c4ebf6b794493898114a502ed36de13137f7e5Glenn Kastenbinder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::string>& uuid, 82301c4ebf6b794493898114a502ed36de13137f7e5Glenn Kasten int64_t freeStorageSize, int32_t flags) { 82401c4ebf6b794493898114a502ed36de13137f7e5Glenn Kasten ENFORCE_UID(AID_SYSTEM); 82501c4ebf6b794493898114a502ed36de13137f7e5Glenn Kasten CHECK_ARGUMENT_UUID(uuid); 826288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten std::lock_guard<std::recursive_mutex> lock(mLock); 8274ff14bae91075eb274eb1c2975982358946e7e63John Grossman 828c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten // TODO: remove this once framework is more robust 82965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian invalidateMounts(); 83065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 83165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char* uuid_ = uuid ? uuid->c_str() : nullptr; 83265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto data_path = create_data_path(uuid_); 83365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto device = findQuotaDeviceForUuid(uuid); 83465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto noop = (flags & FLAG_FREE_CACHE_NOOP); 835288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten 836288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten int64_t free = data_disk_free(data_path); 837288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten int64_t needed = freeStorageSize - free; 83865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (free < 0) { 83965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return error("Failed to determine free space for " + data_path); 84065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else if (free >= freeStorageSize) { 84165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return ok(); 84265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 843fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin 84465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian LOG(DEBUG) << "Found " << data_path << " with " << free << " free; caller requested " 84565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian << freeStorageSize; 84683faee053cfd4251dbb591b62039f563ffdac399Eric Laurent 84783faee053cfd4251dbb591b62039f563ffdac399Eric Laurent if (flags & FLAG_FREE_CACHE_V2) { 848a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent // This new cache strategy fairly removes files from UIDs by deleting 849a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent // files from the UIDs which are most over their allocated quota 8501998661fdb6b0b5ae103e047e3d653c5da1b99e3Glenn Kasten 8512986460984580833161bdaabc7f17da1005a8961Eric Laurent // 1. Create trackers for every known UID 8524ff14bae91075eb274eb1c2975982358946e7e63John Grossman ATRACE_BEGIN("create"); 85358912562617941964939a4182cda71eaeb153d4bGlenn Kasten std::unordered_map<uid_t, std::shared_ptr<CacheTracker>> trackers; 854a34f8ec169986c5a28600c0decaa4e2db70df8e4Glenn Kasten for (auto user : get_known_users(uuid_)) { 8551998661fdb6b0b5ae103e047e3d653c5da1b99e3Glenn Kasten FTS *fts; 8564ff14bae91075eb274eb1c2975982358946e7e63John Grossman FTSENT *p; 857a34f8ec169986c5a28600c0decaa4e2db70df8e4Glenn Kasten char *argv[] = { 858a34f8ec169986c5a28600c0decaa4e2db70df8e4Glenn Kasten (char*) create_data_user_ce_path(uuid_, user).c_str(), 859a34f8ec169986c5a28600c0decaa4e2db70df8e4Glenn Kasten (char*) create_data_user_de_path(uuid_, user).c_str(), 860a34f8ec169986c5a28600c0decaa4e2db70df8e4Glenn Kasten nullptr 861a34f8ec169986c5a28600c0decaa4e2db70df8e4Glenn Kasten }; 86265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) { 86358912562617941964939a4182cda71eaeb153d4bGlenn Kasten return error("Failed to fts_open"); 86465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 86565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while ((p = fts_read(fts)) != NULL) { 866f99590187e2e3f1cf6f093063170edec269cac5dGlenn Kasten if (p->fts_info == FTS_D && p->fts_level == 1) { 86765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uid_t uid = p->fts_statp->st_uid; 868f99590187e2e3f1cf6f093063170edec269cac5dGlenn Kasten auto search = trackers.find(uid); 869288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten if (search != trackers.end()) { 870288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten search->second->addDataPath(p->fts_path); 871288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten } else { 872893a05479c96f911d02beb0443da3ed6508143a7Glenn Kasten auto tracker = std::shared_ptr<CacheTracker>(new CacheTracker( 87365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian multiuser_get_user_id(uid), multiuser_get_app_id(uid), device)); 87465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian tracker->addDataPath(p->fts_path); 87565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian tracker->cacheQuota = mCacheQuotas[uid]; 8768f45bd725549436eeacd12ee69349e2332ed8da5Eric Laurent if (tracker->cacheQuota == 0) { 877a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent LOG(WARNING) << "UID " << uid << " has no cache quota; assuming 64MB"; 878a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent tracker->cacheQuota = 67108864; 87973d227557ba5192735356bacab9f77b44980793bGlenn Kasten } 88073d227557ba5192735356bacab9f77b44980793bGlenn Kasten trackers[uid] = tracker; 881288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten } 882288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten fts_set(fts, p, FTS_SKIP); 883288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten } 884893a05479c96f911d02beb0443da3ed6508143a7Glenn Kasten } 885288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten fts_close(fts); 886288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten } 887288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten ATRACE_END(); 888288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten 88909474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten // 2. Populate tracker stats and insert into priority queue 890288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten ATRACE_BEGIN("populate"); 891288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) { 89258912562617941964939a4182cda71eaeb153d4bGlenn Kasten return (left->getCacheRatio() < right->getCacheRatio()); 89358912562617941964939a4182cda71eaeb153d4bGlenn Kasten }; 89458912562617941964939a4182cda71eaeb153d4bGlenn Kasten std::priority_queue<std::shared_ptr<CacheTracker>, 89565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::vector<std::shared_ptr<CacheTracker>>, decltype(cmp)> queue(cmp); 89665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian for (const auto& it : trackers) { 8974ff14bae91075eb274eb1c2975982358946e7e63John Grossman it.second->loadStats(); 8984ff14bae91075eb274eb1c2975982358946e7e63John Grossman queue.push(it.second); 8999eaa55756c5b245970447019250ce852f5189525Glenn Kasten } 9004ff14bae91075eb274eb1c2975982358946e7e63John Grossman ATRACE_END(); 9014ff14bae91075eb274eb1c2975982358946e7e63John Grossman 9024ff14bae91075eb274eb1c2975982358946e7e63John Grossman // 3. Bounce across the queue, freeing items from whichever tracker is 9034ff14bae91075eb274eb1c2975982358946e7e63John Grossman // the most over their assigned quota 904254af180475346b6186b49c297f340c9c4817511Glenn Kasten ATRACE_BEGIN("bounce"); 9054ff14bae91075eb274eb1c2975982358946e7e63John Grossman std::shared_ptr<CacheTracker> active; 9064ff14bae91075eb274eb1c2975982358946e7e63John Grossman while (active || !queue.empty()) { 9074ff14bae91075eb274eb1c2975982358946e7e63John Grossman // Find the best tracker to work with; this might involve swapping 908d96c5724818fb47917bb5e7abe37799735e1ec0eGlenn Kasten // if the active tracker is no longer the most over quota 9094ff14bae91075eb274eb1c2975982358946e7e63John Grossman bool nextBetter = active && !queue.empty() 9104ff14bae91075eb274eb1c2975982358946e7e63John Grossman && active->getCacheRatio() < queue.top()->getCacheRatio(); 9114ff14bae91075eb274eb1c2975982358946e7e63John Grossman if (!active || nextBetter) { 9124ff14bae91075eb274eb1c2975982358946e7e63John Grossman if (active) { 9134ff14bae91075eb274eb1c2975982358946e7e63John Grossman // Current tracker still has items, so we'll consider it 9144ff14bae91075eb274eb1c2975982358946e7e63John Grossman // again later once it bubbles up to surface 9154ff14bae91075eb274eb1c2975982358946e7e63John Grossman queue.push(active); 9161c345196edc61694f29307a1826a64a0d26028dcJohn Grossman } 9171c345196edc61694f29307a1826a64a0d26028dcJohn Grossman active = queue.top(); queue.pop(); 9184ff14bae91075eb274eb1c2975982358946e7e63John Grossman active->ensureItems(); 9194ff14bae91075eb274eb1c2975982358946e7e63John Grossman continue; 9201c345196edc61694f29307a1826a64a0d26028dcJohn Grossman } 9211c345196edc61694f29307a1826a64a0d26028dcJohn Grossman 9224ff14bae91075eb274eb1c2975982358946e7e63John Grossman // If no items remain, go find another tracker 9234ff14bae91075eb274eb1c2975982358946e7e63John Grossman if (active->items.empty()) { 9241c345196edc61694f29307a1826a64a0d26028dcJohn Grossman active = nullptr; 9254ff14bae91075eb274eb1c2975982358946e7e63John Grossman continue; 926288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten } else { 9274ff14bae91075eb274eb1c2975982358946e7e63John Grossman auto item = active->items.back(); 92801c4ebf6b794493898114a502ed36de13137f7e5Glenn Kasten active->items.pop_back(); 9291c345196edc61694f29307a1826a64a0d26028dcJohn Grossman 9301c345196edc61694f29307a1826a64a0d26028dcJohn Grossman LOG(DEBUG) << "Purging " << item->toString() << " from " << active->toString(); 9314ff14bae91075eb274eb1c2975982358946e7e63John Grossman if (!noop) { 9324ff14bae91075eb274eb1c2975982358946e7e63John Grossman item->purge(); 9331c345196edc61694f29307a1826a64a0d26028dcJohn Grossman } 9344ff14bae91075eb274eb1c2975982358946e7e63John Grossman active->cacheUsed -= item->size; 9354ff14bae91075eb274eb1c2975982358946e7e63John Grossman needed -= item->size; 9364ff14bae91075eb274eb1c2975982358946e7e63John Grossman } 9374ff14bae91075eb274eb1c2975982358946e7e63John Grossman 9384ff14bae91075eb274eb1c2975982358946e7e63John Grossman // Verify that we're actually done before bailing, since sneaky 9394ff14bae91075eb274eb1c2975982358946e7e63John Grossman // apps might be using hardlinks 9404ff14bae91075eb274eb1c2975982358946e7e63John Grossman if (needed <= 0) { 9414ff14bae91075eb274eb1c2975982358946e7e63John Grossman free = data_disk_free(data_path); 9429eaa55756c5b245970447019250ce852f5189525Glenn Kasten needed = freeStorageSize - free; 9434ff14bae91075eb274eb1c2975982358946e7e63John Grossman if (needed <= 0) { 9444ff14bae91075eb274eb1c2975982358946e7e63John Grossman break; 9454ff14bae91075eb274eb1c2975982358946e7e63John Grossman } else { 9464ff14bae91075eb274eb1c2975982358946e7e63John Grossman LOG(WARNING) << "Expected to be done but still need " << needed; 947254af180475346b6186b49c297f340c9c4817511Glenn Kasten } 9484ff14bae91075eb274eb1c2975982358946e7e63John Grossman } 9494ff14bae91075eb274eb1c2975982358946e7e63John Grossman } 9504ff14bae91075eb274eb1c2975982358946e7e63John Grossman ATRACE_END(); 9514ff14bae91075eb274eb1c2975982358946e7e63John Grossman 9521c345196edc61694f29307a1826a64a0d26028dcJohn Grossman } else { 9531c345196edc61694f29307a1826a64a0d26028dcJohn Grossman ATRACE_BEGIN("start"); 9541c345196edc61694f29307a1826a64a0d26028dcJohn Grossman cache_t* cache = start_cache_collection(); 9551c345196edc61694f29307a1826a64a0d26028dcJohn Grossman ATRACE_END(); 9561c345196edc61694f29307a1826a64a0d26028dcJohn Grossman 9571c345196edc61694f29307a1826a64a0d26028dcJohn Grossman ATRACE_BEGIN("add"); 9581c345196edc61694f29307a1826a64a0d26028dcJohn Grossman for (auto user : get_known_users(uuid_)) { 9591c345196edc61694f29307a1826a64a0d26028dcJohn Grossman add_cache_files(cache, create_data_user_ce_path(uuid_, user)); 9604ff14bae91075eb274eb1c2975982358946e7e63John Grossman add_cache_files(cache, create_data_user_de_path(uuid_, user)); 9614ff14bae91075eb274eb1c2975982358946e7e63John Grossman add_cache_files(cache, 9629fbdee13d09447550dd22ae72c2dbabdce7f0a80John Grossman StringPrintf("%s/Android/data", create_data_media_path(uuid_, user).c_str())); 9634ff14bae91075eb274eb1c2975982358946e7e63John Grossman } 9649fbdee13d09447550dd22ae72c2dbabdce7f0a80John Grossman ATRACE_END(); 9654ff14bae91075eb274eb1c2975982358946e7e63John Grossman 9669fbdee13d09447550dd22ae72c2dbabdce7f0a80John Grossman ATRACE_BEGIN("clear"); 9679fbdee13d09447550dd22ae72c2dbabdce7f0a80John Grossman clear_cache_files(data_path, cache, freeStorageSize); 9681c345196edc61694f29307a1826a64a0d26028dcJohn Grossman ATRACE_END(); 9699fbdee13d09447550dd22ae72c2dbabdce7f0a80John Grossman 9704ff14bae91075eb274eb1c2975982358946e7e63John Grossman ATRACE_BEGIN("finish"); 9714ff14bae91075eb274eb1c2975982358946e7e63John Grossman finish_cache_collection(cache); 9724ff14bae91075eb274eb1c2975982358946e7e63John Grossman ATRACE_END(); 9734ff14bae91075eb274eb1c2975982358946e7e63John Grossman } 9744ff14bae91075eb274eb1c2975982358946e7e63John Grossman 9754ff14bae91075eb274eb1c2975982358946e7e63John Grossman free = data_disk_free(data_path); 9764ff14bae91075eb274eb1c2975982358946e7e63John Grossman if (free >= freeStorageSize) { 9774ff14bae91075eb274eb1c2975982358946e7e63John Grossman return ok(); 9784ff14bae91075eb274eb1c2975982358946e7e63John Grossman } else { 9794ff14bae91075eb274eb1c2975982358946e7e63John Grossman return error(StringPrintf("Failed to free up %" PRId64 " on %s; final free space %" PRId64, 9804ff14bae91075eb274eb1c2975982358946e7e63John Grossman freeStorageSize, data_path.c_str(), free)); 9814ff14bae91075eb274eb1c2975982358946e7e63John Grossman } 98265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 98365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 98465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbinder::Status InstalldNativeService::rmdex(const std::string& codePath, 98565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const std::string& instructionSet) { 98665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ENFORCE_UID(AID_SYSTEM); 98765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::lock_guard<std::recursive_mutex> lock(mLock); 98865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 98965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian char dex_path[PKG_PATH_MAX]; 99065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 99165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char* path = codePath.c_str(); 9929eaa55756c5b245970447019250ce852f5189525Glenn Kasten const char* instruction_set = instructionSet.c_str(); 99365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 99465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (validate_apk_path(path) && validate_system_app_path(path)) { 99558f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten return error("Invalid path " + codePath); 996254af180475346b6186b49c297f340c9c4817511Glenn Kasten } 99765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 998c19e22450e6e3d07594c935c7a9522e85e909e82Glenn Kasten if (!create_cache_path(dex_path, path, instruction_set)) { 99965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return error("Failed to create cache path for " + codePath); 10003acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten } 1001a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 100265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ALOGV("unlink %s\n", dex_path); 100365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (unlink(dex_path) < 0) { 1004a111792f1314479c649d1d44c30c2caf70c00c2aGlenn Kasten return error(StringPrintf("Failed to unlink %s", dex_path)); 1005c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten } else { 1006c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten return ok(); 100765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 100865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 100965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1010335787fe43596f38ea2fa50b24c54d0823a3fb1dGlenn Kastenstruct stats { 1011335787fe43596f38ea2fa50b24c54d0823a3fb1dGlenn Kasten int64_t codeSize; 1012335787fe43596f38ea2fa50b24c54d0823a3fb1dGlenn Kasten int64_t dataSize; 1013335787fe43596f38ea2fa50b24c54d0823a3fb1dGlenn Kasten int64_t cacheSize; 101465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}; 101565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 101665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if MEASURE_DEBUG 101765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic std::string toString(std::vector<int64_t> values) { 101865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::stringstream res; 101965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res << "["; 102065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian for (size_t i = 0; i < values.size(); i++) { 102165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res << values[i]; 102265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (i < values.size() - 1) { 102384afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten res << ","; 102465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 102565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 102672ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten res << "]"; 1027bb4350d3b9e9485ae59e084de270f86aecef8066Glenn Kasten return res.str(); 102865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 102965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 1030be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kasten 103165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic void collectQuotaStats(const std::string& device, int32_t userId, 103265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t appId, struct stats* stats, struct stats* extStats) { 103365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (device.empty()) return; 1034000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten 1035000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten struct dqblk dq; 1036000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten 103765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uid_t uid = multiuser_get_uid(userId, appId); 103865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid, 1039000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten reinterpret_cast<char*>(&dq)) != 0) { 1040000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten if (errno != ESRCH) { 1041000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid; 1042000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten } 1043000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten } else { 1044000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten#if MEASURE_DEBUG 104544a957f06400a338e7af20b3d16c4c4ae22a673cEric Laurent LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace; 1046000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten#endif 1047288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten stats->dataSize += dq.dqb_curspace; 1048288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten } 1049288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten 10501465f0c3df04c3166155a852a6a5c10069c1fd0aGlenn Kasten int cacheGid = multiuser_get_cache_gid(userId, appId); 10511465f0c3df04c3166155a852a6a5c10069c1fd0aGlenn Kasten if (cacheGid != -1) { 1052000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), cacheGid, 1053000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten reinterpret_cast<char*>(&dq)) != 0) { 1054000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten if (errno != ESRCH) { 1055e0feee3da22beeffbd9357540e265f13b2119cbbGlenn Kasten PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << cacheGid; 10567c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent } 1057688aac7675f18bdd7bff13334759e20bc4e6c390Glenn Kasten } else { 1058688aac7675f18bdd7bff13334759e20bc4e6c390Glenn Kasten#if MEASURE_DEBUG 1059f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen LOG(DEBUG) << "quotactl() for GID " << cacheGid << " " << dq.dqb_curspace; 1060f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen#endif 106165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian stats->cacheSize += dq.dqb_curspace; 10626637baae4244aec731c4014da72418d330636ae1Glenn Kasten } 10636637baae4244aec731c4014da72418d330636ae1Glenn Kasten } 106465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 10656637baae4244aec731c4014da72418d330636ae1Glenn Kasten int extGid = multiuser_get_ext_gid(userId, appId); 10666637baae4244aec731c4014da72418d330636ae1Glenn Kasten if (extGid != -1) { 106765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extGid, 10686637baae4244aec731c4014da72418d330636ae1Glenn Kasten reinterpret_cast<char*>(&dq)) != 0) { 106965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (errno != ESRCH) { 107065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extGid; 107165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 1072fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten } else { 107365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if MEASURE_DEBUG 107458f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten LOG(DEBUG) << "quotactl() for GID " << extGid << " " << dq.dqb_curspace; 1075254af180475346b6186b49c297f340c9c4817511Glenn Kasten#endif 107665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian extStats->dataSize += dq.dqb_curspace; 107765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 107865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 107973d227557ba5192735356bacab9f77b44980793bGlenn Kasten 10803acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten int sharedGid = multiuser_get_shared_gid(userId, appId); 108165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (sharedGid != -1) { 108265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), sharedGid, 1083aed850d0d3b3c8cf3feaf1438076f33db2a60946Glenn Kasten reinterpret_cast<char*>(&dq)) != 0) { 1084b8ba0a979067a4efb0b3819bf17770793e41c15eEric Laurent if (errno != ESRCH) { 10850bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << sharedGid; 108665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 10871ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten } else { 10881ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten#if MEASURE_DEBUG 10891ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace; 10901ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten#endif 10911ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten stats->codeSize += dq.dqb_curspace; 10921ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten } 10931ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten } 10941ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten} 10951ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten 10961ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kastenstatic void collectManualStats(const std::string& path, struct stats* stats) { 10971ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten DIR *d; 10981ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten int dfd; 10991ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten struct dirent *de; 110065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian struct stat s; 110165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1102688aac7675f18bdd7bff13334759e20bc4e6c390Glenn Kasten d = opendir(path.c_str()); 1103c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten if (d == nullptr) { 110465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (errno != ENOENT) { 11057c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent PLOG(WARNING) << "Failed to open " << path; 1106de070137f11d346fba77605bd76a44c040a618fcEric Laurent } 1107de070137f11d346fba77605bd76a44c040a618fcEric Laurent return; 1108de070137f11d346fba77605bd76a44c040a618fcEric Laurent } 1109de070137f11d346fba77605bd76a44c040a618fcEric Laurent dfd = dirfd(d); 111065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while ((de = readdir(d))) { 11117c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent const char *name = de->d_name; 11127c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent 1113106e8a42038f9e90d5ff97f8ab6f1a42258bde9eGlenn Kasten int64_t size = 0; 11147c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 1115de070137f11d346fba77605bd76a44c040a618fcEric Laurent size = s.st_blocks * 512; 11169f6530f53ae9eda43f4e7c1cb30d2379db00aa00Eric Laurent } 1117a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 1118106e8a42038f9e90d5ff97f8ab6f1a42258bde9eGlenn Kasten if (de->d_type == DT_DIR) { 111922167855ff9af7b13fda669ca27c67a037a7d585Eric Laurent if (!strcmp(name, ".")) { 112022167855ff9af7b13fda669ca27c67a037a7d585Eric Laurent // Don't recurse, but still count node size 1121a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent } else if (!strcmp(name, "..")) { 112265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Don't recurse or count node size 112365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian continue; 11241ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten } else { 11251ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten // Measure all children nodes 11261ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten size = 0; 11271ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten calculate_tree_size(StringPrintf("%s/%s", path.c_str(), name), &size); 11281ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten } 11291ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten 11301ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) { 11311ea6d23396118a9cfe912b7b8a4e6f231e318ea2Glenn Kasten stats->cacheSize += size; 113265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 11339806710f5d6722cfc5783c7eca3512451a0f2035Glenn Kasten } 113499e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten 113599e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten // Legacy symlink isn't owned by app 113699e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten if (de->d_type == DT_LNK && !strcmp(name, "lib")) { 113765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian continue; 11386637baae4244aec731c4014da72418d330636ae1Glenn Kasten } 11399806710f5d6722cfc5783c7eca3512451a0f2035Glenn Kasten 1140288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // Everything found inside is considered data 114165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian stats->dataSize += size; 11427d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi } 11437d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi closedir(d); 1144fe3156ec6fd9fa57dde913fd8567530d095a6550Jean-Michel Trivi} 114565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 11460bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kastenstatic void collectManualStatsForUser(const std::string& path, struct stats* stats, 11470bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten bool exclude_apps = false) { 11480bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten DIR *d; 11490bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten int dfd; 11500bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten struct dirent *de; 11510bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten struct stat s; 11520bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten 115365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian d = opendir(path.c_str()); 115437d825e72a6c606553a745da1212590a425996d3Glenn Kasten if (d == nullptr) { 115537d825e72a6c606553a745da1212590a425996d3Glenn Kasten if (errno != ENOENT) { 115637d825e72a6c606553a745da1212590a425996d3Glenn Kasten PLOG(WARNING) << "Failed to open " << path; 1157fa26a859bacb597587a8f49acfc3127351fa688cGlenn Kasten } 1158fa26a859bacb597587a8f49acfc3127351fa688cGlenn Kasten return; 1159fa26a859bacb597587a8f49acfc3127351fa688cGlenn Kasten } 1160fa26a859bacb597587a8f49acfc3127351fa688cGlenn Kasten dfd = dirfd(d); 116166fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten while ((de = readdir(d))) { 116266fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten if (de->d_type == DT_DIR) { 116366fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten const char *name = de->d_name; 1164e737cda649acbfa43fc1b74612a83f2fac9aa449Eric Laurent if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) != 0) { 1165e737cda649acbfa43fc1b74612a83f2fac9aa449Eric Laurent continue; 116665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 116765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (!strcmp(name, ".") || !strcmp(name, "..")) { 11681998661fdb6b0b5ae103e047e3d653c5da1b99e3Glenn Kasten continue; 116965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else if (exclude_apps && (s.st_uid >= AID_APP_START && s.st_uid <= AID_APP_END)) { 117065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian continue; 117165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 117265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian collectManualStats(StringPrintf("%s/%s", path.c_str(), name), stats); 117365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 117465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 1175b469b9490b3cd9e0f0466d9b9ab228f6c793b82eEric Laurent } 117665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian closedir(d); 117765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 117865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1179be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kastenstatic void collectManualExternalStatsForUser(const std::string& path, struct stats* stats) { 1180be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kasten FTS *fts; 118165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian FTSENT *p; 118265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian char *argv[] = { (char*) path.c_str(), nullptr }; 1183263709e7be37c7040aaef385bc5c9389a9b5f514Glenn Kasten if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) { 1184fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin PLOG(ERROR) << "Failed to fts_open " << path; 1185aed850d0d3b3c8cf3feaf1438076f33db2a60946Glenn Kasten return; 11869f34a36d9cdb9595c288e50ffe00da038bc8abb9Glenn Kasten } 118765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while ((p = fts_read(fts)) != NULL) { 118865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian switch (p->fts_info) { 118965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case FTS_D: 119065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (p->fts_level == 4 119165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian && !strcmp(p->fts_name, "cache") 1192000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten && !strcmp(p->fts_parent->fts_parent->fts_name, "data") 1193000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten && !strcmp(p->fts_parent->fts_parent->fts_parent->fts_name, "Android")) { 1194000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten p->fts_number = 1; 1195000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten } 119666fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten p->fts_number = p->fts_parent->fts_number; 119766fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten // Fall through to count the directory 1198000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten case FTS_DEFAULT: 1199000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten case FTS_F: 120066fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten case FTS_SL: 1201000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten case FTS_SLNONE: 1202fec279f5a0bfaa2a42e91ab6dfa0282baeee308bGlenn Kasten int64_t size = (p->fts_statp->st_blocks * 512); 1203fec279f5a0bfaa2a42e91ab6dfa0282baeee308bGlenn Kasten if (p->fts_number == 1) { 1204da747447c1d4b5205469b4e94485b8769df57a97Eric Laurent stats->cacheSize += size; 1205da747447c1d4b5205469b4e94485b8769df57a97Eric Laurent } 1206810280460da5000785662f6c5b0c7ff3ee0a4cb3Glenn Kasten stats->dataSize += size; 1207810280460da5000785662f6c5b0c7ff3ee0a4cb3Glenn Kasten break; 1208000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten } 1209000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten } 1210000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten fts_close(fts); 1211000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten} 121266fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten 121366fcab972e9218d47c58a915f391b2f48a09903aGlenn Kastenbinder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::string>& uuid, 1214000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten const std::vector<std::string>& packageNames, int32_t userId, int32_t flags, 121566fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten int32_t appId, const std::vector<int64_t>& ceDataInodes, 121666fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten const std::vector<std::string>& codePaths, std::vector<int64_t>* _aidl_return) { 121766fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten ENFORCE_UID(AID_SYSTEM); 121866fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten CHECK_ARGUMENT_UUID(uuid); 1219000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten for (auto packageName : packageNames) { 1220000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten CHECK_ARGUMENT_PACKAGE_NAME(packageName); 122158912562617941964939a4182cda71eaeb153d4bGlenn Kasten } 122258912562617941964939a4182cda71eaeb153d4bGlenn Kasten std::lock_guard<std::recursive_mutex> lock(mLock); 122358912562617941964939a4182cda71eaeb153d4bGlenn Kasten 122458912562617941964939a4182cda71eaeb153d4bGlenn Kasten // When modifying this logic, always verify using tests: 122558912562617941964939a4182cda71eaeb153d4bGlenn Kasten // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetAppSize 122658912562617941964939a4182cda71eaeb153d4bGlenn Kasten 122758912562617941964939a4182cda71eaeb153d4bGlenn Kasten#if MEASURE_DEBUG 122858912562617941964939a4182cda71eaeb153d4bGlenn Kasten LOG(INFO) << "Measuring user " << userId << " app " << appId; 1229fbae5dae5187aca9d974cbe15ec818e9c6f56705Glenn Kasten#endif 1230fbae5dae5187aca9d974cbe15ec818e9c6f56705Glenn Kasten 1231fbae5dae5187aca9d974cbe15ec818e9c6f56705Glenn Kasten // Here's a summary of the common storage locations across the platform, 123228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // and how they're each tagged: 123358912562617941964939a4182cda71eaeb153d4bGlenn Kasten // 123458912562617941964939a4182cda71eaeb153d4bGlenn Kasten // /data/app/com.example UID system 123509474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten // /data/app/com.example/oat UID system 123609474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten // /data/user/0/com.example UID u0_a10 GID u0_a10 123758912562617941964939a4182cda71eaeb153d4bGlenn Kasten // /data/user/0/com.example/cache UID u0_a10 GID u0_a10_cache 123858912562617941964939a4182cda71eaeb153d4bGlenn Kasten // /data/media/0/foo.txt UID u0_media_rw 123958912562617941964939a4182cda71eaeb153d4bGlenn Kasten // /data/media/0/bar.jpg UID u0_media_rw GID u0_media_image 124058912562617941964939a4182cda71eaeb153d4bGlenn Kasten // /data/media/0/Android/data/com.example UID u0_media_rw GID u0_a10_ext 124158912562617941964939a4182cda71eaeb153d4bGlenn Kasten // /data/media/0/Android/data/com.example/cache UID u0_media_rw GID u0_a10_ext_cache 124265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // /data/media/obb/com.example UID system 124365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 124465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian struct stats stats; 124565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian struct stats extStats; 1246de070137f11d346fba77605bd76a44c040a618fcEric Laurent memset(&stats, 0, sizeof(stats)); 1247799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin memset(&extStats, 0, sizeof(extStats)); 124872ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten 1249bb4350d3b9e9485ae59e084de270f86aecef8066Glenn Kasten const char* uuid_ = uuid ? uuid->c_str() : nullptr; 125023bb8becff20449a9b1647d5a1a99b14c83f0cceGlenn Kasten 125165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto device = findQuotaDeviceForUuid(uuid); 125265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (device.empty()) { 125365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian flags &= ~FLAG_USE_QUOTA; 125465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 125565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1256be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kasten ATRACE_BEGIN("obb"); 125765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian for (auto packageName : packageNames) { 125865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto obbCodePath = create_data_media_obb_path(uuid_, packageName.c_str()); 1259000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten calculate_tree_size(obbCodePath, &extStats.codeSize); 1260fe3156ec6fd9fa57dde913fd8567530d095a6550Jean-Michel Trivi } 126165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ATRACE_END(); 12620bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten 12630bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten if (flags & FLAG_USE_QUOTA && appId >= AID_APP_START) { 126466fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten ATRACE_BEGIN("code"); 126565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian for (auto codePath : codePaths) { 1266000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten calculate_tree_size(codePath, &stats.codeSize, -1, 126758912562617941964939a4182cda71eaeb153d4bGlenn Kasten multiuser_get_shared_gid(userId, appId)); 126858912562617941964939a4182cda71eaeb153d4bGlenn Kasten } 1269000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten ATRACE_END(); 1270000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten 127158912562617941964939a4182cda71eaeb153d4bGlenn Kasten ATRACE_BEGIN("quota"); 1272e737cda649acbfa43fc1b74612a83f2fac9aa449Eric Laurent collectQuotaStats(device, userId, appId, &stats, &extStats); 127358912562617941964939a4182cda71eaeb153d4bGlenn Kasten ATRACE_END(); 127458912562617941964939a4182cda71eaeb153d4bGlenn Kasten 127558912562617941964939a4182cda71eaeb153d4bGlenn Kasten } else { 127658912562617941964939a4182cda71eaeb153d4bGlenn Kasten ATRACE_BEGIN("code"); 127758912562617941964939a4182cda71eaeb153d4bGlenn Kasten for (auto codePath : codePaths) { 1278c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten calculate_tree_size(codePath, &stats.codeSize); 127958912562617941964939a4182cda71eaeb153d4bGlenn Kasten } 128058912562617941964939a4182cda71eaeb153d4bGlenn Kasten ATRACE_END(); 128158912562617941964939a4182cda71eaeb153d4bGlenn Kasten 1282399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten for (size_t i = 0; i < packageNames.size(); i++) { 1283399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten const char* pkgname = packageNames[i].c_str(); 1284399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten 1285399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten ATRACE_BEGIN("data"); 1286c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten auto cePath = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInodes[i]); 1287000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten collectManualStats(cePath, &stats); 128858912562617941964939a4182cda71eaeb153d4bGlenn Kasten auto dePath = create_data_user_de_package_path(uuid_, userId, pkgname); 128958912562617941964939a4182cda71eaeb153d4bGlenn Kasten collectManualStats(dePath, &stats); 129058912562617941964939a4182cda71eaeb153d4bGlenn Kasten ATRACE_END(); 129158912562617941964939a4182cda71eaeb153d4bGlenn Kasten 129258912562617941964939a4182cda71eaeb153d4bGlenn Kasten ATRACE_BEGIN("profiles"); 129358912562617941964939a4182cda71eaeb153d4bGlenn Kasten auto userProfilePath = create_data_user_profile_package_path(userId, pkgname); 129409474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten calculate_tree_size(userProfilePath, &stats.dataSize); 129588cbea8a918bbaf5e06e48aadd5af5e81d58d232Glenn Kasten auto refProfilePath = create_data_ref_profile_package_path(pkgname); 129609474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten calculate_tree_size(refProfilePath, &stats.codeSize); 1297288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten ATRACE_END(); 129865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 129965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ATRACE_BEGIN("external"); 130065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto extPath = create_data_media_package_path(uuid_, userId, pkgname, "data"); 130165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian collectManualStats(extPath, &extStats); 130265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto mediaPath = create_data_media_package_path(uuid_, userId, pkgname, "media"); 130372ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten calculate_tree_size(mediaPath, &extStats.dataSize); 1304bb4350d3b9e9485ae59e084de270f86aecef8066Glenn Kasten ATRACE_END(); 1305c19e22450e6e3d07594c935c7a9522e85e909e82Glenn Kasten } 130665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 130765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ATRACE_BEGIN("dalvik"); 130865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t sharedGid = multiuser_get_shared_gid(userId, appId); 130965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (sharedGid != -1) { 131065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize, 131165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sharedGid, -1); 1312fe3156ec6fd9fa57dde913fd8567530d095a6550Jean-Michel Trivi } 131365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize, 13140bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten multiuser_get_uid(userId, appId), -1); 13150bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten ATRACE_END(); 13160bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten } 131766fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten 131865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::vector<int64_t> ret; 1319000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten ret.push_back(stats.codeSize); 13201465f0c3df04c3166155a852a6a5c10069c1fd0aGlenn Kasten ret.push_back(stats.dataSize); 1321000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten ret.push_back(stats.cacheSize); 1322000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten ret.push_back(extStats.codeSize); 132365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ret.push_back(extStats.dataSize); 132499e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten ret.push_back(extStats.cacheSize); 132565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if MEASURE_DEBUG 132665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian LOG(DEBUG) << "Final result " << toString(ret); 1327d4513b09123deebf8023b73a82d2d46d35806ceaGlenn Kasten#endif 1328d4513b09123deebf8023b73a82d2d46d35806ceaGlenn Kasten *_aidl_return = ret; 1329b071e9bc248865ef87a339044c0c5cbabfac175cGlenn Kasten return ok(); 1330b071e9bc248865ef87a339044c0c5cbabfac175cGlenn Kasten} 133158912562617941964939a4182cda71eaeb153d4bGlenn Kasten 133258912562617941964939a4182cda71eaeb153d4bGlenn Kastenbinder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::string>& uuid, 133365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t userId, int32_t flags, const std::vector<int32_t>& appIds, 133465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::vector<int64_t>* _aidl_return) { 133565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ENFORCE_UID(AID_SYSTEM); 133665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian CHECK_ARGUMENT_UUID(uuid); 133772ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten std::lock_guard<std::recursive_mutex> lock(mLock); 133872ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten 1339c19e22450e6e3d07594c935c7a9522e85e909e82Glenn Kasten // When modifying this logic, always verify using tests: 134065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetUserSize 134165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 134265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if MEASURE_DEBUG 134365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian LOG(INFO) << "Measuring user " << userId; 13440bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten#endif 134565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 13460bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten struct stats stats; 134765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian struct stats extStats; 134865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian memset(&stats, 0, sizeof(stats)); 1349e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten memset(&extStats, 0, sizeof(extStats)); 1350000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten 1351000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten const char* uuid_ = uuid ? uuid->c_str() : nullptr; 1352000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten 1353000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten auto device = findQuotaDeviceForUuid(uuid); 1354000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten if (device.empty()) { 1355000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten flags &= ~FLAG_USE_QUOTA; 135666fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten } 1357438b036deaf4413503567a75a2861c000d21da5bGlenn Kasten 135866fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten if (flags & FLAG_USE_QUOTA) { 1359438b036deaf4413503567a75a2861c000d21da5bGlenn Kasten struct dqblk dq; 1360438b036deaf4413503567a75a2861c000d21da5bGlenn Kasten 136166fcab972e9218d47c58a915f391b2f48a09903aGlenn Kasten ATRACE_BEGIN("obb"); 1362fa26a859bacb597587a8f49acfc3127351fa688cGlenn Kasten if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), AID_MEDIA_OBB, 1363fa26a859bacb597587a8f49acfc3127351fa688cGlenn Kasten reinterpret_cast<char*>(&dq)) != 0) { 1364000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten if (errno != ESRCH) { 136565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << AID_MEDIA_OBB; 136665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 1367fa26a859bacb597587a8f49acfc3127351fa688cGlenn Kasten } else { 1368fa26a859bacb597587a8f49acfc3127351fa688cGlenn Kasten#if MEASURE_DEBUG 136958912562617941964939a4182cda71eaeb153d4bGlenn Kasten LOG(DEBUG) << "quotactl() for GID " << AID_MEDIA_OBB << " " << dq.dqb_curspace; 137058912562617941964939a4182cda71eaeb153d4bGlenn Kasten#endif 137165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian extStats.codeSize += dq.dqb_curspace; 137265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 137372ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten ATRACE_END(); 137472ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten 137572ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten ATRACE_BEGIN("code"); 13766637baae4244aec731c4014da72418d330636ae1Glenn Kasten calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true); 13776637baae4244aec731c4014da72418d330636ae1Glenn Kasten ATRACE_END(); 13786637baae4244aec731c4014da72418d330636ae1Glenn Kasten 13796637baae4244aec731c4014da72418d330636ae1Glenn Kasten ATRACE_BEGIN("data"); 13806637baae4244aec731c4014da72418d330636ae1Glenn Kasten auto cePath = create_data_user_ce_path(uuid_, userId); 138172ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten collectManualStatsForUser(cePath, &stats, true); 1382b81cc8c6f3eec9edb255ea99b6a6f243585b1e38Glenn Kasten auto dePath = create_data_user_de_path(uuid_, userId); 138365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian collectManualStatsForUser(dePath, &stats, true); 138472ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten ATRACE_END(); 13857c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent 138672ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten ATRACE_BEGIN("profile"); 138759255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent auto userProfilePath = create_data_user_profile_path(userId); 1388a111792f1314479c649d1d44c30c2caf70c00c2aGlenn Kasten calculate_tree_size(userProfilePath, &stats.dataSize, -1, -1, true); 1389a111792f1314479c649d1d44c30c2caf70c00c2aGlenn Kasten auto refProfilePath = create_data_ref_profile_path(); 139039e94f8f723d445447fdee0822291e664b631f60Eric Laurent calculate_tree_size(refProfilePath, &stats.codeSize, -1, -1, true); 139102fe1bf923bbe5789202dbd5810e2c04794562e6Glenn Kasten ATRACE_END(); 139202fe1bf923bbe5789202dbd5810e2c04794562e6Glenn Kasten 1393bb4350d3b9e9485ae59e084de270f86aecef8066Glenn Kasten ATRACE_BEGIN("external"); 139465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW); 1395717e128691f083a9469a1d0e363ac6ecd5c65d58Eric Laurent if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid, 1396717e128691f083a9469a1d0e363ac6ecd5c65d58Eric Laurent reinterpret_cast<char*>(&dq)) != 0) { 139799e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten if (errno != ESRCH) { 139865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid; 139965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 140065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 140165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if MEASURE_DEBUG 140290716c5728b37637b2d0a730a721bfc9fad299e0Glenn Kasten LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace; 14033acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten#endif 140465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian extStats.dataSize += dq.dqb_curspace; 140565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 140665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ATRACE_END(); 140765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 140865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ATRACE_BEGIN("dalvik"); 14094ff14bae91075eb274eb1c2975982358946e7e63John Grossman calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize, 14104ff14bae91075eb274eb1c2975982358946e7e63John Grossman -1, -1, true); 14114ff14bae91075eb274eb1c2975982358946e7e63John Grossman calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize, 14124ff14bae91075eb274eb1c2975982358946e7e63John Grossman -1, -1, true); 14134ff14bae91075eb274eb1c2975982358946e7e63John Grossman ATRACE_END(); 14144ff14bae91075eb274eb1c2975982358946e7e63John Grossman 141565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ATRACE_BEGIN("quota"); 141665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian for (auto appId : appIds) { 141765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (appId >= AID_APP_START) { 141884afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten collectQuotaStats(device, userId, appId, &stats, &extStats); 141965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if MEASURE_DEBUG 142065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Sleep to make sure we don't lose logs 142165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian usleep(1); 142265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 142365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 142465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 142565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ATRACE_END(); 142665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 1427c3ae93f21280859086ae371428ffd32f39e76d50Glenn Kasten ATRACE_BEGIN("obb"); 142865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto obbPath = create_data_path(uuid_) + "/media/obb"; 142965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian calculate_tree_size(obbPath, &extStats.codeSize); 143065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ATRACE_END(); 143165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 143265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ATRACE_BEGIN("code"); 143365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize); 14349eaa55756c5b245970447019250ce852f5189525Glenn Kasten ATRACE_END(); 143565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 143665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ATRACE_BEGIN("data"); 143758f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten auto cePath = create_data_user_ce_path(uuid_, userId); 1438254af180475346b6186b49c297f340c9c4817511Glenn Kasten collectManualStatsForUser(cePath, &stats); 143965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto dePath = create_data_user_de_path(uuid_, userId); 144065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian collectManualStatsForUser(dePath, &stats); 1441c19e22450e6e3d07594c935c7a9522e85e909e82Glenn Kasten ATRACE_END(); 144265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 14430ec23ce0d1ff79566c402bc30df3074f6e25a22bGlenn Kasten ATRACE_BEGIN("profile"); 144465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto userProfilePath = create_data_user_profile_path(userId); 144565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian calculate_tree_size(userProfilePath, &stats.dataSize); 1446510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten auto refProfilePath = create_data_ref_profile_path(); 1447510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten calculate_tree_size(refProfilePath, &stats.codeSize); 144804270daf50f0c602d7c57a257a693e68246cbeb7Glenn Kasten ATRACE_END(); 144904270daf50f0c602d7c57a257a693e68246cbeb7Glenn Kasten 145004270daf50f0c602d7c57a257a693e68246cbeb7Glenn Kasten ATRACE_BEGIN("external"); 145165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto dataMediaPath = create_data_media_path(uuid_, userId); 145265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian collectManualExternalStatsForUser(dataMediaPath, &extStats); 1453510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten#if MEASURE_DEBUG 145465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian LOG(DEBUG) << "Measured external data " << extStats.dataSize << " cache " 145559255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent << extStats.cacheSize; 145665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 14571998661fdb6b0b5ae103e047e3d653c5da1b99e3Glenn Kasten ATRACE_END(); 145865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 145965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ATRACE_BEGIN("dalvik"); 146065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize); 146165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize); 146201c4ebf6b794493898114a502ed36de13137f7e5Glenn Kasten ATRACE_END(); 146301c4ebf6b794493898114a502ed36de13137f7e5Glenn Kasten } 146401c4ebf6b794493898114a502ed36de13137f7e5Glenn Kasten 146565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::vector<int64_t> ret; 146604270daf50f0c602d7c57a257a693e68246cbeb7Glenn Kasten ret.push_back(stats.codeSize); 146765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ret.push_back(stats.dataSize); 146865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ret.push_back(stats.cacheSize); 146965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ret.push_back(extStats.codeSize); 1470799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin ret.push_back(extStats.dataSize); 147165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ret.push_back(extStats.cacheSize); 1472254af180475346b6186b49c297f340c9c4817511Glenn Kasten#if MEASURE_DEBUG 147372ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten LOG(DEBUG) << "Final result " << toString(ret); 1474bb4350d3b9e9485ae59e084de270f86aecef8066Glenn Kasten#endif 1475c19e22450e6e3d07594c935c7a9522e85e909e82Glenn Kasten *_aidl_return = ret; 147665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return ok(); 1477510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten} 1478510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten 1479510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kastenbinder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std::string>& uuid, 1480510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten int32_t userId, int32_t flags, std::vector<int64_t>* _aidl_return) { 1481510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten ENFORCE_UID(AID_SYSTEM); 1482510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten CHECK_ARGUMENT_UUID(uuid); 1483510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten std::lock_guard<std::recursive_mutex> lock(mLock); 1484c3ae93f21280859086ae371428ffd32f39e76d50Glenn Kasten 148565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // When modifying this logic, always verify using tests: 1486b8ba0a979067a4efb0b3819bf17770793e41c15eEric Laurent // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetExternalSize 1487000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten 1488000f0e39b4d0c88441297a05ab5f8da6832c1640Glenn Kasten#if MEASURE_DEBUG 148965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian LOG(INFO) << "Measuring external " << userId; 149065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 1491e0feee3da22beeffbd9357540e265f13b2119cbbGlenn Kasten 14927c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent const char* uuid_ = uuid ? uuid->c_str() : nullptr; 14937c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent 14947c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent int64_t totalSize = 0; 149558f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten int64_t audioSize = 0; 1496254af180475346b6186b49c297f340c9c4817511Glenn Kasten int64_t videoSize = 0; 14977c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent int64_t imageSize = 0; 14987c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent 14991879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten auto device = findQuotaDeviceForUuid(uuid); 15001879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten if (device.empty()) { 15017c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent flags &= ~FLAG_USE_QUOTA; 15027c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent } 15033acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten 1504a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent if (flags & FLAG_USE_QUOTA) { 1505a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent struct dqblk dq; 15061d491ff06f4b9c90ff24fe953b90d0843eaf1c04Glenn Kasten 15071d491ff06f4b9c90ff24fe953b90d0843eaf1c04Glenn Kasten uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW); 15081d491ff06f4b9c90ff24fe953b90d0843eaf1c04Glenn Kasten if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid, 15091d491ff06f4b9c90ff24fe953b90d0843eaf1c04Glenn Kasten reinterpret_cast<char*>(&dq)) != 0) { 15101d491ff06f4b9c90ff24fe953b90d0843eaf1c04Glenn Kasten if (errno != ESRCH) { 1511be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kasten PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid; 1512b8ba0a979067a4efb0b3819bf17770793e41c15eEric Laurent } 15130bf65bdde04b8e66c998ff37e2b2afafddddfa33Glenn Kasten } else { 15147c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent#if MEASURE_DEBUG 151501c4ebf6b794493898114a502ed36de13137f7e5Glenn Kasten LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace; 151601c4ebf6b794493898114a502ed36de13137f7e5Glenn Kasten#endif 151765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian totalSize = dq.dqb_curspace; 151801c4ebf6b794493898114a502ed36de13137f7e5Glenn Kasten } 151965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 152065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO); 152165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), audioGid, 152265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian reinterpret_cast<char*>(&dq)) == 0) { 152365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if MEASURE_DEBUG 152465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian LOG(DEBUG) << "quotactl() for GID " << audioGid << " " << dq.dqb_curspace; 15257c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent#endif 15267c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent audioSize = dq.dqb_curspace; 1527106e8a42038f9e90d5ff97f8ab6f1a42258bde9eGlenn Kasten } 1528510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO); 1529510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), videoGid, 1530510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten reinterpret_cast<char*>(&dq)) == 0) { 1531510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten#if MEASURE_DEBUG 1532106e8a42038f9e90d5ff97f8ab6f1a42258bde9eGlenn Kasten LOG(DEBUG) << "quotactl() for GID " << videoGid << " " << dq.dqb_curspace; 15337c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent#endif 1534a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent videoSize = dq.dqb_curspace; 1535106e8a42038f9e90d5ff97f8ab6f1a42258bde9eGlenn Kasten } 1536a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE); 1537a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), imageGid, 1538a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent reinterpret_cast<char*>(&dq)) == 0) { 1539a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent#if MEASURE_DEBUG 154065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian LOG(DEBUG) << "quotactl() for GID " << imageGid << " " << dq.dqb_curspace; 1541a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent#endif 1542a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent imageSize = dq.dqb_curspace; 1543e4e2a37dbe2a4d923232305549101f779a2e3638Glenn Kasten } 1544e4e2a37dbe2a4d923232305549101f779a2e3638Glenn Kasten } else { 1545e4e2a37dbe2a4d923232305549101f779a2e3638Glenn Kasten FTS *fts; 1546e4e2a37dbe2a4d923232305549101f779a2e3638Glenn Kasten FTSENT *p; 1547e4e2a37dbe2a4d923232305549101f779a2e3638Glenn Kasten auto path = create_data_media_path(uuid_, userId); 1548e4e2a37dbe2a4d923232305549101f779a2e3638Glenn Kasten char *argv[] = { (char*) path.c_str(), nullptr }; 1549799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) { 1550510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten return error("Failed to fts_open " + path); 1551510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten } 1552510a3d6b8018a77683dac466127ffd0af34bef6eGlenn Kasten while ((p = fts_read(fts)) != NULL) { 155365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian char* ext; 155465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int64_t size = (p->fts_statp->st_blocks * 512); 155565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian switch (p->fts_info) { 155665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case FTS_F: 155765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Only categorize files not belonging to apps 155865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (p->fts_statp->st_gid < AID_APP_START) { 155965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ext = strrchr(p->fts_name, '.'); 156084afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten if (ext != nullptr) { 156184afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten switch (MatchExtension(++ext)) { 156265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case AID_MEDIA_AUDIO: audioSize += size; break; 1563a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent case AID_MEDIA_VIDEO: videoSize += size; break; 1564a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent case AID_MEDIA_IMAGE: imageSize += size; break; 1565a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent } 1566a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent } 15672986460984580833161bdaabc7f17da1005a8961Eric Laurent } 15682986460984580833161bdaabc7f17da1005a8961Eric Laurent // Fall through to always count against total 1569a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent case FTS_D: 157065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case FTS_DEFAULT: 157165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case FTS_SL: 157299e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten case FTS_SLNONE: 157365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian totalSize += size; 157465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; 157565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 157665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 157790716c5728b37637b2d0a730a721bfc9fad299e0Glenn Kasten fts_close(fts); 15780ec23ce0d1ff79566c402bc30df3074f6e25a22bGlenn Kasten } 157965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 158065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::vector<int64_t> ret; 158165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ret.push_back(totalSize); 158265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ret.push_back(audioSize); 158384afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kasten ret.push_back(videoSize); 1584d96c5724818fb47917bb5e7abe37799735e1ec0eGlenn Kasten ret.push_back(imageSize); 1585d96c5724818fb47917bb5e7abe37799735e1ec0eGlenn Kasten#if MEASURE_DEBUG 1586d96c5724818fb47917bb5e7abe37799735e1ec0eGlenn Kasten LOG(DEBUG) << "Final result " << toString(ret); 158765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 158865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian *_aidl_return = ret; 158965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return ok(); 159065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 159165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 159265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbinder::Status InstalldNativeService::setAppQuota(const std::unique_ptr<std::string>& uuid, 159365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t userId, int32_t appId, int64_t cacheQuota) { 159465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ENFORCE_UID(AID_SYSTEM); 159565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian CHECK_ARGUMENT_UUID(uuid); 159665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::lock_guard<std::recursive_mutex> lock(mLock); 159765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 159865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t uid = multiuser_get_uid(userId, appId); 159965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mCacheQuotas[uid] = cacheQuota; 160065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 160165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return ok(); 160265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 160365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 160465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// Dumps the contents of a profile file, using pkgname's dex files for pretty 160565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// printing the result. 160665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbinder::Status InstalldNativeService::dumpProfiles(int32_t uid, const std::string& packageName, 16079eaa55756c5b245970447019250ce852f5189525Glenn Kasten const std::string& codePaths, bool* _aidl_return) { 160865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ENFORCE_UID(AID_SYSTEM); 160965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian CHECK_ARGUMENT_PACKAGE_NAME(packageName); 161065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::lock_guard<std::recursive_mutex> lock(mLock); 161165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1612c19e22450e6e3d07594c935c7a9522e85e909e82Glenn Kasten const char* pkgname = packageName.c_str(); 161365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char* code_paths = codePaths.c_str(); 161465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 161565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian *_aidl_return = dump_profiles(uid, pkgname, code_paths); 161665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return ok(); 161765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 161865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 161965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// TODO: Consider returning error codes. 1620ec437d8d3db79459d7b19e1734e6fe309bd621e8Eric Laurentbinder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::string& packageName, 1621ec437d8d3db79459d7b19e1734e6fe309bd621e8Eric Laurent bool* _aidl_return) { 162265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ENFORCE_UID(AID_SYSTEM); 162365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian CHECK_ARGUMENT_PACKAGE_NAME(packageName); 1624c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten std::lock_guard<std::recursive_mutex> lock(mLock); 162565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 162665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char* pkgname = packageName.c_str(); 162725f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent *_aidl_return = analyse_profiles(uid, pkgname); 162825f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent return ok(); 162925f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent} 163025f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent 163125f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurentbinder::Status InstalldNativeService::dexopt(const std::string& apkPath, int32_t uid, 163265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const std::unique_ptr<std::string>& packageName, const std::string& instructionSet, 163365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags, 163465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid, 163565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const std::unique_ptr<std::string>& sharedLibraries) { 163628243dd563fee1c82f0fff6cc27b5cbf21fa2585Glenn Kasten ENFORCE_UID(AID_SYSTEM); 163765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian CHECK_ARGUMENT_UUID(uuid); 163865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (packageName && *packageName != "*") { 163965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian CHECK_ARGUMENT_PACKAGE_NAME(*packageName); 164065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 164165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::lock_guard<std::recursive_mutex> lock(mLock); 1642c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten 1643de070137f11d346fba77605bd76a44c040a618fcEric Laurent const char* apk_path = apkPath.c_str(); 1644de070137f11d346fba77605bd76a44c040a618fcEric Laurent const char* pkgname = packageName ? packageName->c_str() : "*"; 164565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char* instruction_set = instructionSet.c_str(); 1646a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent const char* oat_dir = outputPath ? outputPath->c_str() : nullptr; 1647c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten const char* compiler_filter = compilerFilter.c_str(); 1648c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten const char* volume_uuid = uuid ? uuid->c_str() : nullptr; 164965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char* shared_libraries = sharedLibraries ? sharedLibraries->c_str() : nullptr; 165065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 165165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded, 165265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian oat_dir, dexFlags, compiler_filter, volume_uuid, shared_libraries); 165365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return res ? error(res, "Failed to dexopt") : ok(); 1654de070137f11d346fba77605bd76a44c040a618fcEric Laurent} 1655de070137f11d346fba77605bd76a44c040a618fcEric Laurent 165684afa3b51ac48f84ed62489529ce78cba7fca00eGlenn Kastenbinder::Status InstalldNativeService::markBootComplete(const std::string& instructionSet) { 165765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ENFORCE_UID(AID_SYSTEM); 1658a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent std::lock_guard<std::recursive_mutex> lock(mLock); 1659a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent 1660a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent const char* instruction_set = instructionSet.c_str(); 166165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 166258e5aa34f01d663654d8bafad65db1dda42161ffGlenn Kasten char boot_marker_path[PKG_PATH_MAX]; 166365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sprintf(boot_marker_path, 166465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian "%s/%s/%s/.booting", 1665bb4350d3b9e9485ae59e084de270f86aecef8066Glenn Kasten android_data_dir.path, 166665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian DALVIK_CACHE, 1667f78aee70d15daf4690de7e7b4983ee68b0d1381dGlenn Kasten instruction_set); 166857b2dd1e78af53115985f18d31ec5421c9da947eEric Laurent 1669ec35a1416472865dbebc22b10199ad718ed2cc95Eric Laurent ALOGV("mark_boot_complete : %s", boot_marker_path); 1670ec437d8d3db79459d7b19e1734e6fe309bd621e8Eric Laurent if (unlink(boot_marker_path) != 0) { 167159255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent return error(StringPrintf("Failed to unlink %s", boot_marker_path)); 1672a3a854868a80fd9b9b8720e06a172754943f9417Glenn Kasten } 167359255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent return ok(); 1674a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent} 167565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1676c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kastenvoid mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid, 16773a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen struct stat* statbuf) 1678a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent{ 1679a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent while (path[basepos] != 0) { 1680a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent if (path[basepos] == '/') { 16813a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen path[basepos] = 0; 1682be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kasten if (lstat(path, statbuf) < 0) { 168365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ALOGV("Making directory: %s\n", path); 168465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (mkdir(path, mode) == 0) { 16851998661fdb6b0b5ae103e047e3d653c5da1b99e3Glenn Kasten chown(path, uid, gid); 16863a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen } else { 168765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ALOGW("Unable to make directory %s: %s\n", path, strerror(errno)); 168865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 168965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 169065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian path[basepos] = '/'; 169165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian basepos++; 169265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 169365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian basepos++; 169465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 169565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 169665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1697a3a854868a80fd9b9b8720e06a172754943f9417Glenn Kastenbinder::Status InstalldNativeService::linkNativeLibraryDirectory( 169865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const std::unique_ptr<std::string>& uuid, const std::string& packageName, 169965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const std::string& nativeLibPath32, int32_t userId) { 1700415fa7599f48494f99206b8d6e1974abb52c5923Glenn Kasten ENFORCE_UID(AID_SYSTEM); 1701415fa7599f48494f99206b8d6e1974abb52c5923Glenn Kasten CHECK_ARGUMENT_UUID(uuid); 170258e5aa34f01d663654d8bafad65db1dda42161ffGlenn Kasten CHECK_ARGUMENT_PACKAGE_NAME(packageName); 170365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::lock_guard<std::recursive_mutex> lock(mLock); 1704e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 170528243dd563fee1c82f0fff6cc27b5cbf21fa2585Glenn Kasten const char* uuid_ = uuid ? uuid->c_str() : nullptr; 170628243dd563fee1c82f0fff6cc27b5cbf21fa2585Glenn Kasten const char* pkgname = packageName.c_str(); 1707a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent const char* asecLibDir = nativeLibPath32.c_str(); 170899e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten struct stat s, libStat; 170965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian binder::Status res = ok(); 171065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 171165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian auto _pkgdir = create_data_user_ce_package_path(uuid_, userId, pkgname); 171259255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent auto _libsymlink = _pkgdir + PKG_LIB_POSTFIX; 171365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 171465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char* pkgdir = _pkgdir.c_str(); 171565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char* libsymlink = _libsymlink.c_str(); 171665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 171765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (stat(pkgdir, &s) < 0) { 171865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return error("Failed to stat " + _pkgdir); 171965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 172065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 172165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) { 172265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return error("Failed to chown " + _pkgdir); 172365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 172465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 172565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (chmod(pkgdir, 0700) < 0) { 172665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res = error("Failed to chmod " + _pkgdir); 172765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian goto out; 172865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 172965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 173065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (lstat(libsymlink, &libStat) < 0) { 173165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (errno != ENOENT) { 173265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res = error("Failed to stat " + _libsymlink); 173325f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent goto out; 173425f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent } 173525f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent } else { 173625f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent if (S_ISDIR(libStat.st_mode)) { 173725f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent if (delete_dir_contents(libsymlink, 1, NULL) < 0) { 173865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res = error("Failed to delete " + _libsymlink); 173958123c3a8b5f34f9d1f70264a3c568ed90288501Glenn Kasten goto out; 174058123c3a8b5f34f9d1f70264a3c568ed90288501Glenn Kasten } 174158123c3a8b5f34f9d1f70264a3c568ed90288501Glenn Kasten } else if (S_ISLNK(libStat.st_mode)) { 1742c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten if (unlink(libsymlink) < 0) { 174365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res = error("Failed to unlink " + _libsymlink); 174465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian goto out; 174565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 174665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 174765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 174859255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent 174959255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent if (symlink(asecLibDir, libsymlink) < 0) { 175059255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent res = error("Failed to symlink " + _libsymlink + " to " + nativeLibPath32); 175159255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent goto out; 175225f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent } 175325f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent 175425f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurentout: 175525f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent if (chmod(pkgdir, s.st_mode) < 0) { 175625f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent auto msg = "Failed to cleanup chmod " + _pkgdir; 175765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (res.isOk()) { 1758c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten res = error(msg); 175965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 176065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian PLOG(ERROR) << msg; 1761c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten } 1762c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten } 1763c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten 1764c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten if (chown(pkgdir, s.st_uid, s.st_gid) < 0) { 1765a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent auto msg = "Failed to cleanup chown " + _pkgdir; 1766a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent if (res.isOk()) { 176765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res = error(msg); 176865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 176965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian PLOG(ERROR) << msg; 177065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 17711998661fdb6b0b5ae103e047e3d653c5da1b99e3Glenn Kasten } 177265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 177365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return res; 177465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 177565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 177665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd) 177798ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten{ 177865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian static const char *IDMAP_BIN = "/system/bin/idmap"; 177965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian static const size_t MAX_INT_LEN = 32; 178065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian char idmap_str[MAX_INT_LEN]; 178165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 178265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd); 178359255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent 178459255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL); 1785a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno)); 1786a5f44ebaf58911805b4fb7fb479b19fd89d2e39bEric Laurent} 178765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 178865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix) 178965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// eg /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap 179065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic int flatten_path(const char *prefix, const char *suffix, 179165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char *overlay_path, char *idmap_path, size_t N) 179265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 179365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (overlay_path == NULL || idmap_path == NULL) { 179465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return -1; 179565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 179665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const size_t len_overlay_path = strlen(overlay_path); 179765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // will access overlay_path + 1 further below; requires absolute path 179865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (len_overlay_path < 2 || *overlay_path != '/') { 17999eaa55756c5b245970447019250ce852f5189525Glenn Kasten return -1; 1800c19e22450e6e3d07594c935c7a9522e85e909e82Glenn Kasten } 180165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const size_t len_idmap_root = strlen(prefix); 180259255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent const size_t len_suffix = strlen(suffix); 180359255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent if (SIZE_MAX - len_idmap_root < len_overlay_path || 180459255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) { 180559255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent // additions below would cause overflow 1806544fe9b6e9325701df4ab8c1d29774fc13c4cf6cEric Laurent return -1; 1807544fe9b6e9325701df4ab8c1d29774fc13c4cf6cEric Laurent } 1808544fe9b6e9325701df4ab8c1d29774fc13c4cf6cEric Laurent if (N < len_idmap_root + len_overlay_path + len_suffix) { 1809544fe9b6e9325701df4ab8c1d29774fc13c4cf6cEric Laurent return -1; 181065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 181165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian memset(idmap_path, 0, N); 181265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix); 181365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian char *ch = idmap_path + len_idmap_root; 181465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (*ch != '\0') { 181565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (*ch == '/') { 181665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian *ch = '@'; 181765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 181865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ++ch; 1819de070137f11d346fba77605bd76a44c040a618fcEric Laurent } 1820cab112421da6e8eac19ffddbbe3d76067cffee78Eric Laurent return 0; 182165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 1822c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten 18237c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurentbinder::Status InstalldNativeService::idmap(const std::string& targetApkPath, 1824de070137f11d346fba77605bd76a44c040a618fcEric Laurent const std::string& overlayApkPath, int32_t uid) { 1825cab112421da6e8eac19ffddbbe3d76067cffee78Eric Laurent ENFORCE_UID(AID_SYSTEM); 1826cab112421da6e8eac19ffddbbe3d76067cffee78Eric Laurent std::lock_guard<std::recursive_mutex> lock(mLock); 182759255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent 1828cab112421da6e8eac19ffddbbe3d76067cffee78Eric Laurent const char* target_apk = targetApkPath.c_str(); 1829bb4350d3b9e9485ae59e084de270f86aecef8066Glenn Kasten const char* overlay_apk = overlayApkPath.c_str(); 1830f78aee70d15daf4690de7e7b4983ee68b0d1381dGlenn Kasten ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid); 183157b2dd1e78af53115985f18d31ec5421c9da947eEric Laurent 183265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int idmap_fd = -1; 183365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian char idmap_path[PATH_MAX]; 183465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 183565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk, 183665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian idmap_path, sizeof(idmap_path)) == -1) { 1837c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk); 183865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian goto fail; 183965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 184065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 184165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian unlink(idmap_path); 184265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644); 1843c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten if (idmap_fd < 0) { 184465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno)); 184565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian goto fail; 184665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 1847b469b9490b3cd9e0f0466d9b9ab228f6c793b82eEric Laurent if (fchown(idmap_fd, AID_SYSTEM, uid) < 0) { 1848b469b9490b3cd9e0f0466d9b9ab228f6c793b82eEric Laurent ALOGE("idmap cannot chown '%s'\n", idmap_path); 18492df8f55055fe431a508148cf525df1ba40f03113Glenn Kasten goto fail; 1850b469b9490b3cd9e0f0466d9b9ab228f6c793b82eEric Laurent } 1851544fe9b6e9325701df4ab8c1d29774fc13c4cf6cEric Laurent if (fchmod(idmap_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { 1852544fe9b6e9325701df4ab8c1d29774fc13c4cf6cEric Laurent ALOGE("idmap cannot chmod '%s'\n", idmap_path); 1853b469b9490b3cd9e0f0466d9b9ab228f6c793b82eEric Laurent goto fail; 18542df8f55055fe431a508148cf525df1ba40f03113Glenn Kasten } 185565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1856c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten pid_t pid; 1857de070137f11d346fba77605bd76a44c040a618fcEric Laurent pid = fork(); 1858e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten if (pid == 0) { 1859de070137f11d346fba77605bd76a44c040a618fcEric Laurent /* child -- drop privileges before continuing */ 186059255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent if (setgid(uid) != 0) { 186159255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent ALOGE("setgid(%d) failed during idmap\n", uid); 186259255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent exit(1); 186359255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent } 186459255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent if (setuid(uid) != 0) { 186559255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent ALOGE("setuid(%d) failed during idmap\n", uid); 1866a85a74a8219c03f2b1d1ef98f3f02e55f89f89a3Eric Laurent exit(1); 186759255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent } 186859255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) { 186991b14c4c144d0cc957a427cffc02ba10d0615677Eric Laurent ALOGE("flock(%s) failed during idmap: %s\n", idmap_path, strerror(errno)); 187091b14c4c144d0cc957a427cffc02ba10d0615677Eric Laurent exit(1); 1871be5f05e0fdfc4e3799653702187861a2afa072eeGlenn Kasten } 187265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 187365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian run_idmap(target_apk, overlay_apk, idmap_fd); 18741998661fdb6b0b5ae103e047e3d653c5da1b99e3Glenn Kasten exit(1); /* only if exec call to idmap failed */ 187565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 187665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int status = wait_child(pid); 187765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (status != 0) { 187859255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent ALOGE("idmap failed, status=0x%04x\n", status); 187959255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent goto fail; 188059255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent } 188159255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent } 188259255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent 188359255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent close(idmap_fd); 188459255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent return ok(); 188559255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurentfail: 188659255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent if (idmap_fd >= 0) { 188759255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent close(idmap_fd); 188859255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent unlink(idmap_path); 1889d05397144be774f2f3623c754e865f51753e4e31Glenn Kasten } 1890d05397144be774f2f3623c754e865f51753e4e31Glenn Kasten return error(); 189159255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent} 189259255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent 1893db7c079f284f6e91266f6653ae0ec198b1c5006eEric Laurentbinder::Status InstalldNativeService::restoreconAppData(const std::unique_ptr<std::string>& uuid, 1894db7c079f284f6e91266f6653ae0ec198b1c5006eEric Laurent const std::string& packageName, int32_t userId, int32_t flags, int32_t appId, 1895db7c079f284f6e91266f6653ae0ec198b1c5006eEric Laurent const std::string& seInfo) { 1896db7c079f284f6e91266f6653ae0ec198b1c5006eEric Laurent ENFORCE_UID(AID_SYSTEM); 189759255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent CHECK_ARGUMENT_UUID(uuid); 189891b14c4c144d0cc957a427cffc02ba10d0615677Eric Laurent CHECK_ARGUMENT_PACKAGE_NAME(packageName); 189991b14c4c144d0cc957a427cffc02ba10d0615677Eric Laurent std::lock_guard<std::recursive_mutex> lock(mLock); 190065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 190165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian binder::Status res = ok(); 1902e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten 190365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here. 190465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian unsigned int seflags = SELINUX_ANDROID_RESTORECON_RECURSE; 190565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const char* uuid_ = uuid ? uuid->c_str() : nullptr; 19062df8f55055fe431a508148cf525df1ba40f03113Glenn Kasten const char* pkgName = packageName.c_str(); 19072df8f55055fe431a508148cf525df1ba40f03113Glenn Kasten const char* seinfo = seInfo.c_str(); 19082df8f55055fe431a508148cf525df1ba40f03113Glenn Kasten 19092df8f55055fe431a508148cf525df1ba40f03113Glenn Kasten uid_t uid = multiuser_get_uid(userId, appId); 19102df8f55055fe431a508148cf525df1ba40f03113Glenn Kasten if (flags & FLAG_STORAGE_CE) { 1911544fe9b6e9325701df4ab8c1d29774fc13c4cf6cEric Laurent auto path = create_data_user_ce_package_path(uuid_, userId, pkgName); 1912544fe9b6e9325701df4ab8c1d29774fc13c4cf6cEric Laurent if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) { 191365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian res = error("restorecon failed for " + path); 1914cab112421da6e8eac19ffddbbe3d76067cffee78Eric Laurent } 1915cab112421da6e8eac19ffddbbe3d76067cffee78Eric Laurent } 1916cab112421da6e8eac19ffddbbe3d76067cffee78Eric Laurent if (flags & FLAG_STORAGE_DE) { 1917f997cabca292d70d078ae828e21c28e6df62995fEric Laurent auto path = create_data_user_de_package_path(uuid_, userId, pkgName); 1918f997cabca292d70d078ae828e21c28e6df62995fEric Laurent if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) { 1919de070137f11d346fba77605bd76a44c040a618fcEric Laurent res = error("restorecon failed for " + path); 192017a736c3e1d062d7fc916329eb32aef8935614afGlenn Kasten } 192117a736c3e1d062d7fc916329eb32aef8935614afGlenn Kasten } 192259255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent return res; 192317a736c3e1d062d7fc916329eb32aef8935614afGlenn Kasten} 192459255e4fc7d8ff52874b85b1988dc0785140cf81Eric Laurent 192565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbinder::Status InstalldNativeService::createOatDir(const std::string& oatDir, 192665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const std::string& instructionSet) { 1927ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman ENFORCE_UID(AID_SYSTEM); 1928ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman std::lock_guard<std::recursive_mutex> lock(mLock); 1929ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman 1930ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman const char* oat_dir = oatDir.c_str(); 1931ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman const char* instruction_set = instructionSet.c_str(); 1932ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman char oat_instr_dir[PKG_PATH_MAX]; 1933ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman 1934ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman if (validate_apk_path(oat_dir)) { 1935ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman return error("Invalid path " + oatDir); 1936ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman } 1937ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) { 1938ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman return error("Failed to prepare " + oatDir); 1939ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman } 1940ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman if (selinux_android_restorecon(oat_dir, 0)) { 1941ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman return error("Failed to restorecon " + oatDir); 1942ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman } 1943ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set); 1944ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) { 1945ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman return error(StringPrintf("Failed to prepare %s", oat_instr_dir)); 1946ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman } 1947ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman return ok(); 1948ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman} 1949ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman 1950ee578c0330319f04a48bccbdb26b53fea0388d04John Grossmanbinder::Status InstalldNativeService::rmPackageDir(const std::string& packageDir) { 1951ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman ENFORCE_UID(AID_SYSTEM); 1952ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman std::lock_guard<std::recursive_mutex> lock(mLock); 1953ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman 1954ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman if (validate_apk_path(packageDir.c_str())) { 1955ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman return error("Invalid path " + packageDir); 1956ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman } 1957ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman if (delete_dir_contents_and_dir(packageDir) != 0) { 1958aed850d0d3b3c8cf3feaf1438076f33db2a60946Glenn Kasten return error("Failed to delete " + packageDir); 1959aed850d0d3b3c8cf3feaf1438076f33db2a60946Glenn Kasten } 1960aed850d0d3b3c8cf3feaf1438076f33db2a60946Glenn Kasten return ok(); 1961aed850d0d3b3c8cf3feaf1438076f33db2a60946Glenn Kasten} 1962799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin 1963ee578c0330319f04a48bccbdb26b53fea0388d04John Grossmanbinder::Status InstalldNativeService::linkFile(const std::string& relativePath, 1964aed850d0d3b3c8cf3feaf1438076f33db2a60946Glenn Kasten const std::string& fromBase, const std::string& toBase) { 1965799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin ENFORCE_UID(AID_SYSTEM); 1966ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman std::lock_guard<std::recursive_mutex> lock(mLock); 1967ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman 1968ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman const char* relative_path = relativePath.c_str(); 1969ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman const char* from_base = fromBase.c_str(); 1970799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin const char* to_base = toBase.c_str(); 1971799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin char from_path[PKG_PATH_MAX]; 1972799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin char to_path[PKG_PATH_MAX]; 1973ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman snprintf(from_path, PKG_PATH_MAX, "%s/%s", from_base, relative_path); 1974aed850d0d3b3c8cf3feaf1438076f33db2a60946Glenn Kasten snprintf(to_path, PKG_PATH_MAX, "%s/%s", to_base, relative_path); 1975799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin 1976ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman if (validate_apk_path_subdirs(from_path)) { 1977ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman return error(StringPrintf("Invalid from path %s", from_path)); 1978ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman } 1979ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman 1980799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin if (validate_apk_path_subdirs(to_path)) { 1981799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin return error(StringPrintf("Invalid to path %s", to_path)); 198299e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten } 19833a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen 1984012ca6b4f69fb24385025c0e84b8f816525a3032Glenn Kasten if (link(from_path, to_path) < 0) { 1985012ca6b4f69fb24385025c0e84b8f816525a3032Glenn Kasten return error(StringPrintf("Failed to link from %s to %s", from_path, to_path)); 1986012ca6b4f69fb24385025c0e84b8f816525a3032Glenn Kasten } 1987012ca6b4f69fb24385025c0e84b8f816525a3032Glenn Kasten 1988012ca6b4f69fb24385025c0e84b8f816525a3032Glenn Kasten return ok(); 19893a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen} 19903a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen 199165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbinder::Status InstalldNativeService::moveAb(const std::string& apkPath, 199265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const std::string& instructionSet, const std::string& outputPath) { 199398ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten ENFORCE_UID(AID_SYSTEM); 199465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::lock_guard<std::recursive_mutex> lock(mLock); 199565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1996a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent const char* apk_path = apkPath.c_str(); 1997a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent const char* instruction_set = instructionSet.c_str(); 19982b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten const char* oat_dir = outputPath.c_str(); 19992b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten 2000ee578c0330319f04a48bccbdb26b53fea0388d04John Grossman bool success = move_ab(apk_path, instruction_set, oat_dir); 2001a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent return success ? ok() : error(); 20022f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten} 20038abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten 20042f732eb768004c6362fae8a02c60b69c9400b032Glenn Kastenbinder::Status InstalldNativeService::deleteOdex(const std::string& apkPath, 20058abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten const std::string& instructionSet, const std::string& outputPath) { 20068abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten ENFORCE_UID(AID_SYSTEM); 20078abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten std::lock_guard<std::recursive_mutex> lock(mLock); 20088abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten 20098abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten const char* apk_path = apkPath.c_str(); 20108abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten const char* instruction_set = instructionSet.c_str(); 20118abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten const char* oat_dir = outputPath.c_str(); 20128abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten 20138abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten bool res = delete_odex(apk_path, instruction_set, oat_dir); 20148abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten return res ? ok() : error(); 20158abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten} 20168abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten 20178abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kastenbinder::Status InstalldNativeService::invalidateMounts() { 20188abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten ENFORCE_UID(AID_SYSTEM); 20198abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten std::lock_guard<std::recursive_mutex> lock(mLock); 20208abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten 20218abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten mQuotaDevices.clear(); 20228abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten 20238abf44d2f2bcd20a2835570efe89d89c19db426aGlenn Kasten std::ifstream in("/proc/mounts"); 2024d8f178d613821c3f61a5c5e391eb275339e526a9John Grossman if (!in.is_open()) { 2025d8f178d613821c3f61a5c5e391eb275339e526a9John Grossman return error("Failed to read mounts"); 20262f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten } 20272f732eb768004c6362fae8a02c60b69c9400b032Glenn Kasten 2028a4454b4765c5905f14186893b0688be375642283Glenn Kasten std::string source; 202965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::string target; 203065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::string ignored; 203172ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten struct dqblk dq; 2032b7bf796b758e144f94f6ed4d16c21bf22a118fb3Glenn Kasten while (!in.eof()) { 20339806710f5d6722cfc5783c7eca3512451a0f2035Glenn Kasten std::getline(in, source, ' '); 2034c3ae93f21280859086ae371428ffd32f39e76d50Glenn Kasten std::getline(in, target, ' '); 203565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian std::getline(in, ignored); 203665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2037c3ae93f21280859086ae371428ffd32f39e76d50Glenn Kasten if (source.compare(0, 11, "/dev/block/") == 0) { 203865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0, 203972ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten reinterpret_cast<char*>(&dq)) == 0) { 204065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian LOG(DEBUG) << "Found " << source << " with quota"; 204165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mQuotaDevices[target] = source; 204299e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten } 2043f78aee70d15daf4690de7e7b4983ee68b0d1381dGlenn Kasten } 2044bee5337da7659b3b7128622ba1f42618b11df5beEric Laurent } 204565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return ok(); 204699e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten} 20473a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen 20489806710f5d6722cfc5783c7eca3512451a0f2035Glenn Kastenstd::string InstalldNativeService::findQuotaDeviceForUuid( 20494ff14bae91075eb274eb1c2975982358946e7e63John Grossman const std::unique_ptr<std::string>& uuid) { 2050d8f178d613821c3f61a5c5e391eb275339e526a9John Grossman auto path = create_data_path(uuid ? uuid->c_str() : nullptr); 2051a4c5a550e2a3bc237179b8684e51718e05894492Eric Laurent return mQuotaDevices[path]; 205298ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten} 2053a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 2054a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent} // namespace installd 2055a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent} // namespace android 205698ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten