From 3f0645ba835111d3df9fe2ceac8aa8e456f604c2 Mon Sep 17 00:00:00 2001 From: Sudheer Shanka Date: Tue, 18 Sep 2018 13:07:59 -0700 Subject: [PATCH] Bind mount pkg specific dirs in the zygote child namespaces. - Also update vold to create sandboxes for secondary storage devices. - Since bind mounts are created in the process specific namespaces, we don't need /mnt/storage anymore which we were using it to prevent some bind mounts from propagating onto /mnt/runtime/write. - Create bind mounts for {media,obb} dirs similar to data dir in per process namespace. - Also fix a bug where we are not passing correct packages to vold when a new user starts. Bug: 111890351 Test: manual Change-Id: I1abbafabc58993860305e5a928c980420f89f289 --- core/java/android/os/Process.java | 12 +- core/java/android/os/ZygoteProcess.java | 39 +++++- .../os/storage/StorageManagerInternal.java | 7 +- core/java/android/os/storage/VolumeInfo.java | 2 +- core/java/com/android/internal/os/Zygote.java | 15 ++- .../android/internal/os/ZygoteConnection.java | 13 +- core/jni/com_android_internal_os_Zygote.cpp | 123 +++++++++++++++--- .../android/server/StorageManagerService.java | 86 ++++++++++-- .../server/am/ActivityManagerService.java | 6 +- 9 files changed, 257 insertions(+), 46 deletions(-) diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 6fab3c412ae5f..0f64c4531bc3b 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -483,6 +483,8 @@ public class Process { * @param appDataDir null-ok the data directory of the app. * @param invokeWith null-ok the command to invoke with. * @param packageName null-ok the name of the package this process belongs to. + * @param packagesForUid null-ok all the packages with the same uid as this process. + * @param visibleVols null-ok storage volumes that can be accessed by this process. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @return An object that describes the result of the attempt to start the process. @@ -501,10 +503,13 @@ public class Process { @Nullable String appDataDir, @Nullable String invokeWith, @Nullable String packageName, + @Nullable String[] packagesForUid, + @Nullable String[] visibleVols, @Nullable String[] zygoteArgs) { return zygoteProcess.start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, - abi, instructionSet, appDataDir, invokeWith, packageName, zygoteArgs); + abi, instructionSet, appDataDir, invokeWith, packageName, + packagesForUid, visibleVols, zygoteArgs); } /** @hide */ @@ -519,10 +524,13 @@ public class Process { @Nullable String appDataDir, @Nullable String invokeWith, @Nullable String packageName, + @Nullable String[] packagesForUid, + @Nullable String[] visibleVols, @Nullable String[] zygoteArgs) { return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, - abi, instructionSet, appDataDir, invokeWith, packageName, zygoteArgs); + abi, instructionSet, appDataDir, invokeWith, packageName, + packagesForUid, visibleVols, zygoteArgs); } /** diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index 99181acb03c7e..7fd0a4b66d66b 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -215,6 +215,8 @@ public class ZygoteProcess { * @param appDataDir null-ok the data directory of the app. * @param invokeWith null-ok the command to invoke with. * @param packageName null-ok the name of the package this process belongs to. + * @param packagesForUid null-ok all the packages with the same uid as this process. + * @param visibleVols null-ok storage volumes that can be accessed by this process. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @return An object that describes the result of the attempt to start the process. @@ -231,12 +233,14 @@ public class ZygoteProcess { @Nullable String appDataDir, @Nullable String invokeWith, @Nullable String packageName, + @Nullable String[] packagesForUid, + @Nullable String[] visibleVols, @Nullable String[] zygoteArgs) { try { return startViaZygote(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */, - packageName, zygoteArgs); + packageName, packagesForUid, visibleVols, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); @@ -355,6 +359,8 @@ public class ZygoteProcess { * @param startChildZygote Start a sub-zygote. This creates a new zygote process * that has its state cloned from this zygote process. * @param packageName null-ok the name of the package this process belongs to. + * @param packagesForUid null-ok all the packages with the same uid as this process. + * @param visibleVols null-ok storage volumes that can be accessed by this process. * @param extraArgs Additional arguments to supply to the zygote process. * @return An object that describes the result of the attempt to start the process. * @throws ZygoteStartFailedEx if process start failed for any reason @@ -372,6 +378,8 @@ public class ZygoteProcess { @Nullable String invokeWith, boolean startChildZygote, @Nullable String packageName, + @Nullable String[] packagesForUid, + @Nullable String[] visibleVols, @Nullable String[] extraArgs) throws ZygoteStartFailedEx { ArrayList argsForZygote = new ArrayList(); @@ -439,6 +447,32 @@ public class ZygoteProcess { argsForZygote.add("--package-name=" + packageName); } + if (packagesForUid != null && packagesForUid.length > 0) { + final StringBuilder sb = new StringBuilder(); + sb.append("--packages-for-uid="); + + for (int i = 0; i < packagesForUid.length; ++i) { + if (i != 0) { + sb.append(','); + } + sb.append(packagesForUid[i]); + } + argsForZygote.add(sb.toString()); + } + + if (visibleVols != null && visibleVols.length > 0) { + final StringBuilder sb = new StringBuilder(); + sb.append("--visible-vols="); + + for (int i = 0; i < visibleVols.length; ++i) { + if (i != 0) { + sb.append(','); + } + sb.append(visibleVols[i]); + } + argsForZygote.add(sb.toString()); + } + argsForZygote.add(processClass); if (extraArgs != null) { @@ -746,7 +780,8 @@ public class ZygoteProcess { result = startViaZygote(processClass, niceName, uid, gid, gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo, abi, instructionSet, null /* appDataDir */, null /* invokeWith */, - true /* startChildZygote */, null /* packageName */, extraArgs); + true /* startChildZygote */, null /* packageName */, + null /* packagesForUid */, null /* visibleVolumes */, extraArgs); } catch (ZygoteStartFailedEx ex) { throw new RuntimeException("Starting child-zygote through Zygote failed", ex); } diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java index d850e27e913f0..1f54ea53facc3 100644 --- a/core/java/android/os/storage/StorageManagerInternal.java +++ b/core/java/android/os/storage/StorageManagerInternal.java @@ -89,8 +89,13 @@ public abstract class StorageManagerInternal { * @param appId The appId for the given package. * @param sharedUserId The sharedUserId for given package if it specified * {@code android:sharedUserId} in the manifest, otherwise {@code null} - * @param userId + * @param userId The userId in which the storage needs to be mounted. */ public abstract void mountExternalStorageForApp(String packageName, int appId, String sharedUserId, int userId); + + /** + * @return Labels of storage volumes that are visible to the given userId. + */ + public abstract String[] getVisibleVolumesForUser(int userId); } diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java index afd3836913009..e55afb69bab92 100644 --- a/core/java/android/os/storage/VolumeInfo.java +++ b/core/java/android/os/storage/VolumeInfo.java @@ -157,7 +157,7 @@ public class VolumeInfo implements Parcelable { public final DiskInfo disk; public final String partGuid; public int mountFlags = 0; - public int mountUserId = -1; + public int mountUserId = UserHandle.USER_NULL; @UnsupportedAppUsage public int state = STATE_UNMOUNTED; public String fsType; diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 927322e97e28d..98b7b5d28779b 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -133,15 +133,16 @@ public final class Zygote { * if this is the parent, or -1 on error. */ public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, - int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, - int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, - String packageName) { + int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, + int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, + String packageName, String[] packagesForUid, String[] visibleVolIds) { VM_HOOKS.preFork(); // Resets nice priority for zygote process. resetNicePriority(); int pid = nativeForkAndSpecialize( uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, - fdsToIgnore, startChildZygote, instructionSet, appDataDir, packageName); + fdsToIgnore, startChildZygote, instructionSet, appDataDir, packageName, + packagesForUid, visibleVolIds); // Enable tracing as soon as possible for the child process. if (pid == 0) { Trace.setTracingEnabled(true, runtimeFlags); @@ -154,9 +155,9 @@ public final class Zygote { } native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int runtimeFlags, - int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, - int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, - String packageName); + int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, + int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, + String packageName, String[] packagesForUid, String[] visibleVolIds); /** * Called to do any initialization before starting an application. diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 06c41d858f7c8..4a94ec4a40719 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -241,7 +241,8 @@ class ZygoteConnection { pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote, - parsedArgs.instructionSet, parsedArgs.appDataDir, parsedArgs.packageName); + parsedArgs.instructionSet, parsedArgs.appDataDir, parsedArgs.packageName, + parsedArgs.packagesForUid, parsedArgs.visibleVolIds); try { if (pid == 0) { @@ -432,6 +433,12 @@ class ZygoteConnection { /** from --package-name */ String packageName; + /** from --packages-for-uid */ + String[] packagesForUid; + + /** from --visible-vols */ + String[] visibleVolIds; + /** * Any args after and including the first non-option arg * (or after a '--') @@ -687,6 +694,10 @@ class ZygoteConnection { throw new IllegalArgumentException("Duplicate arg specified"); } packageName = arg.substring(arg.indexOf('=') + 1); + } else if (arg.startsWith("--packages-for-uid=")) { + packagesForUid = arg.substring(arg.indexOf('=') + 1).split(","); + } else if (arg.startsWith("--visible-vols=")) { + visibleVolIds = arg.substring(arg.indexOf('=') + 1).split(","); } else { break; } diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 364393e1c649d..1f958628374dd 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -382,11 +382,10 @@ static int UnmountTree(const char* path) { return 0; } -static bool createPkgSandbox(uid_t uid, const char* package_name, std::string& pkg_sandbox_dir, - std::string* error_msg) { +static bool createPkgSandbox(uid_t uid, const std::string& package_name, std::string* error_msg) { // Create /mnt/user/0/package/ userid_t user_id = multiuser_get_user_id(uid); - StringAppendF(&pkg_sandbox_dir, "/%d", user_id); + std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d", user_id); if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0751, AID_ROOT, AID_ROOT) != 0) { *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str()); return false; @@ -396,7 +395,7 @@ static bool createPkgSandbox(uid_t uid, const char* package_name, std::string& p *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str()); return false; } - StringAppendF(&pkg_sandbox_dir, "/%s", package_name); + StringAppendF(&pkg_sandbox_dir, "/%s", package_name.c_str()); if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0755, uid, uid) != 0) { *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str()); return false; @@ -404,10 +403,51 @@ static bool createPkgSandbox(uid_t uid, const char* package_name, std::string& p return true; } +static bool mountPkgSpecificDir(const std::string& mntSourceRoot, + const std::string& mntTargetRoot, const std::string& packageName, + const char* dirName, std::string* error_msg) { + std::string mntSourceDir = StringPrintf("%s/Android/%s/%s", + mntSourceRoot.c_str(), dirName, packageName.c_str()); + std::string mntTargetDir = StringPrintf("%s/Android/%s/%s", + mntTargetRoot.c_str(), dirName, packageName.c_str()); + if (TEMP_FAILURE_RETRY(mount(mntSourceDir.c_str(), mntTargetDir.c_str(), + nullptr, MS_BIND | MS_REC, nullptr)) == -1) { + *error_msg = CREATE_ERROR("Failed to mount %s to %s: %s", + mntSourceDir.c_str(), mntTargetDir.c_str(), strerror(errno)); + return false; + } + if (TEMP_FAILURE_RETRY(mount(nullptr, mntTargetDir.c_str(), + nullptr, MS_SLAVE | MS_REC, nullptr)) == -1) { + *error_msg = CREATE_ERROR("Failed to set MS_SLAVE for %s", mntTargetDir.c_str()); + return false; + } + return true; +} + +static bool preparePkgSpecificDirs(const std::vector& packageNames, + const std::vector& volumeLabels, userid_t userId, std::string* error_msg) { + for (auto& label : volumeLabels) { + std::string mntSource = StringPrintf("/mnt/runtime/write/%s", label.c_str()); + std::string mntTarget = StringPrintf("/storage/%s", label.c_str()); + if (label == "emulated") { + StringAppendF(&mntSource, "/%d", userId); + StringAppendF(&mntTarget, "/%d", userId); + } + for (auto& package : packageNames) { + mountPkgSpecificDir(mntSource, mntTarget, package, "data", error_msg); + mountPkgSpecificDir(mntSource, mntTarget, package, "media", error_msg); + mountPkgSpecificDir(mntSource, mntTarget, package, "obb", error_msg); + } + } + return true; +} + // Create a private mount namespace and bind mount appropriate emulated // storage for the given user. static bool MountEmulatedStorage(uid_t uid, jint mount_mode, - bool force_mount_namespace, std::string* error_msg, const char* package_name) { + bool force_mount_namespace, std::string* error_msg, const std::string& package_name, + const std::vector& packages_for_uid, + const std::vector& visible_vol_ids) { // See storage config details at http://source.android.com/tech/storage/ String8 storageSource; @@ -459,12 +499,25 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode, return false; } } else { - if (package_name == nullptr) { + if (package_name.empty()) { return true; } - std::string pkgSandboxDir("/mnt/user"); - if (!createPkgSandbox(uid, package_name, pkgSandboxDir, error_msg)) { - return false; + userid_t user_id = multiuser_get_user_id(uid); + std::string pkgSandboxDir = StringPrintf("/mnt/user/%d/package/%s", + user_id, package_name.c_str()); + struct stat sb; + bool sandboxAlreadyCreated = true; + if (TEMP_FAILURE_RETRY(lstat(pkgSandboxDir.c_str(), &sb)) == -1) { + if (errno == ENOENT) { + ALOGD("Sandbox not yet created for %s", pkgSandboxDir.c_str()); + sandboxAlreadyCreated = false; + if (!createPkgSandbox(uid, package_name, error_msg)) { + return false; + } + } else { + ALOGE("Failed to lstat %s", pkgSandboxDir.c_str()); + return false; + } } if (TEMP_FAILURE_RETRY(mount(pkgSandboxDir.c_str(), "/storage", nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) { @@ -472,6 +525,15 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode, pkgSandboxDir.c_str(), strerror(errno)); return false; } + // If the sandbox was already created by vold, only then set up the bind mounts for + // pkg specific directories. Otherwise, leave as is and bind mounts will be taken + // care of by vold later. + if (sandboxAlreadyCreated) { + if (!preparePkgSpecificDirs(packages_for_uid, visible_vol_ids, + user_id, error_msg)) { + return false; + } + } } } else { if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage", @@ -611,7 +673,8 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGi jlong permittedCapabilities, jlong effectiveCapabilities, jint mount_external, jstring java_se_info, jstring java_se_name, bool is_system_server, bool is_child_zygote, jstring instructionSet, - jstring dataDir, jstring packageName) { + jstring dataDir, jstring packageName, jobjectArray packagesForUid, + jobjectArray visibleVolIds) { std::string error_msg; auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg) @@ -661,17 +724,33 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGi ALOGW("Native bridge will not be used because dataDir == NULL."); } - ScopedUtfChars* package_name = nullptr; - const char* package_name_c_str = nullptr; + std::string package_name_str(""); if (packageName != nullptr) { - package_name = new ScopedUtfChars(env, packageName); - package_name_c_str = package_name->c_str(); + ScopedUtfChars package(env, packageName); + package_name_str = package.c_str(); } else if (is_system_server) { - package_name_c_str = "android"; + package_name_str = "android"; + } + std::vector packages_for_uid; + if (packagesForUid != nullptr) { + jsize count = env->GetArrayLength(packagesForUid); + for (jsize i = 0; i < count; ++i) { + jstring package_for_uid = (jstring) env->GetObjectArrayElement(packagesForUid, i); + ScopedUtfChars package(env, package_for_uid); + packages_for_uid.push_back(package.c_str()); + } + } + std::vector visible_vol_ids; + if (visibleVolIds != nullptr) { + jsize count = env->GetArrayLength(visibleVolIds); + for (jsize i = 0; i < count; ++i) { + jstring visible_vol_id = (jstring) env->GetObjectArrayElement(visibleVolIds, i); + ScopedUtfChars vol(env, visible_vol_id); + visible_vol_ids.push_back(vol.c_str()); + } } bool success = MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg, - package_name_c_str); - delete package_name; + package_name_str, packages_for_uid, visible_vol_ids); if (!success) { ALOGW("Failed to mount emulated storage: %s (%s)", error_msg.c_str(), strerror(errno)); if (errno == ENOTCONN || errno == EROFS) { @@ -936,7 +1015,8 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring se_name, jintArray fdsToClose, jintArray fdsToIgnore, jboolean is_child_zygote, - jstring instructionSet, jstring appDataDir, jstring packageName) { + jstring instructionSet, jstring appDataDir, jstring packageName, + jobjectArray packagesForUid, jobjectArray visibleVolIds) { jlong capabilities = 0; // Grant CAP_WAKE_ALARM to the Bluetooth process. @@ -989,7 +1069,8 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities, mount_external, se_info, se_name, false, - is_child_zygote == JNI_TRUE, instructionSet, appDataDir, packageName); + is_child_zygote == JNI_TRUE, instructionSet, appDataDir, packageName, + packagesForUid, visibleVolIds); } return pid; } @@ -1003,7 +1084,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permittedCapabilities, effectiveCapabilities, MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, - false, NULL, NULL, nullptr); + false, NULL, NULL, nullptr, nullptr, nullptr); } else if (pid > 0) { // The zygote process checks whether the child process has died or not. ALOGI("System server process %d has been created", pid); @@ -1084,7 +1165,7 @@ static const JNINativeMethod gMethods[] = { { "nativeSecurityInit", "()V", (void *) com_android_internal_os_Zygote_nativeSecurityInit }, { "nativeForkAndSpecialize", - "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", + "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)I", (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize }, { "nativeForkSystemServer", "(II[II[[IJJ)I", (void *) com_android_internal_os_Zygote_nativeForkSystemServer }, diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index d505a77c91921..21f54dd33d3e8 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -329,6 +329,12 @@ class StorageManagerService extends IStorageManager.Stub @GuardedBy("mPackagesLock") private final SparseArray mSandboxIds = new SparseArray<>(); + /** + * List of volumes visible to any user. + * TODO: may be have a map of userId -> volumes? + */ + private final CopyOnWriteArrayList mVisibleVols = new CopyOnWriteArrayList<>(); + private volatile int mCurrentUserId = UserHandle.USER_SYSTEM; /** Holding lock for AppFuse business */ @@ -623,16 +629,12 @@ class StorageManagerService extends IStorageManager.Stub Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy"); break; } - try { - mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); - } catch (Exception e) { - Slog.wtf(TAG, e); - } + mount(vol); break; } case H_VOLUME_UNMOUNT: { final VolumeInfo vol = (VolumeInfo) msg.obj; - unmount(vol.getId()); + unmount(vol); break; } case H_VOLUME_BROADCAST: { @@ -869,6 +871,8 @@ class StorageManagerService extends IStorageManager.Stub addInternalVolumeLocked(); } + mVisibleVols.clear(); + try { mVold.reset(); @@ -1466,7 +1470,7 @@ class StorageManagerService extends IStorageManager.Stub = mContext.getPackageManager().getInstalledApplicationsAsUser( PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); synchronized (mPackagesLock) { - final ArraySet userPackages = getPackagesForUserPL(userId); + final ArraySet userPackages = getAvailablePackagesForUserPL(userId); for (int i = appInfos.size() - 1; i >= 0; --i) { if (appInfos.get(i).isInstantApp()) { continue; @@ -1523,7 +1527,7 @@ class StorageManagerService extends IStorageManager.Stub } @GuardedBy("mPackagesLock") - private ArraySet getPackagesForUserPL(int userId) { + private ArraySet getAvailablePackagesForUserPL(int userId) { ArraySet userPackages = mPackages.get(userId); if (userPackages == null) { userPackages = new ArraySet<>(); @@ -1535,8 +1539,24 @@ class StorageManagerService extends IStorageManager.Stub private String[] getPackagesArrayForUser(int userId) { if (!ENABLE_ISOLATED_STORAGE) return EmptyArray.STRING; + final ArraySet userPackages; synchronized (mPackagesLock) { - return getPackagesForUserPL(userId).toArray(new String[0]); + userPackages = getAvailablePackagesForUserPL(userId); + if (!userPackages.isEmpty()) { + return userPackages.toArray(new String[0]); + } + } + final List appInfos = + mContext.getPackageManager().getInstalledApplicationsAsUser( + PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); + synchronized (mPackagesLock) { + for (int i = appInfos.size() - 1; i >= 0; --i) { + if (appInfos.get(i).isInstantApp()) { + continue; + } + userPackages.add(appInfos.get(i).packageName); + } + return userPackages.toArray(new String[0]); } } @@ -1747,8 +1767,15 @@ class StorageManagerService extends IStorageManager.Stub if (isMountDisallowed(vol)) { throw new SecurityException("Mounting " + volId + " restricted by policy"); } + mount(vol); + } + + private void mount(VolumeInfo vol) { try { mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); + if ((vol.mountFlags & VolumeInfo.MOUNT_FLAG_VISIBLE) != 0) { + mVisibleVols.add(vol); + } } catch (Exception e) { Slog.wtf(TAG, e); } @@ -1759,8 +1786,15 @@ class StorageManagerService extends IStorageManager.Stub enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); final VolumeInfo vol = findVolumeByIdOrThrow(volId); + unmount(vol); + } + + private void unmount(VolumeInfo vol) { try { mVold.unmount(vol.id); + if ((vol.mountFlags & VolumeInfo.MOUNT_FLAG_VISIBLE) != 0) { + mVisibleVols.remove(vol); + } } catch (Exception e) { Slog.wtf(TAG, e); } @@ -3595,6 +3629,14 @@ class StorageManagerService extends IStorageManager.Stub } pw.decreaseIndent(); + pw.println(); + pw.println("mVisibleVols:"); + pw.increaseIndent(); + for (int i = 0; i < mVisibleVols.size(); i++) { + mVisibleVols.get(i).dump(pw); + } + pw.decreaseIndent(); + pw.println(); pw.println("Primary storage UUID: " + mPrimaryStorageUuid); final Pair pair = StorageManager.getPrimaryStoragePathAndSize(); @@ -3716,7 +3758,7 @@ class StorageManagerService extends IStorageManager.Stub int userId) { final String sandboxId; synchronized (mPackagesLock) { - final ArraySet userPackages = getPackagesForUserPL(userId); + final ArraySet userPackages = getAvailablePackagesForUserPL(userId); // If userPackages is empty, it means the user is not started yet, so no need to // do anything now. if (userPackages.isEmpty() || userPackages.contains(packageName)) { @@ -3734,5 +3776,29 @@ class StorageManagerService extends IStorageManager.Stub Slog.wtf(TAG, e); } } + + @Override + public String[] getVisibleVolumesForUser(int userId) { + final ArrayList visibleVolsForUser = new ArrayList<>(); + for (int i = mVisibleVols.size() - 1; i >= 0; --i) { + final VolumeInfo vol = mVisibleVols.get(i); + if (vol.isVisibleForUser(userId)) { + visibleVolsForUser.add(getVolumeLabel(vol)); + } + } + return visibleVolsForUser.toArray(new String[visibleVolsForUser.size()]); + } + + private String getVolumeLabel(VolumeInfo vol) { + // STOPSHIP: Label needs to part of VolumeInfo and need to be passed on from vold + switch (vol.getType()) { + case VolumeInfo.TYPE_EMULATED: + return "emulated"; + case VolumeInfo.TYPE_PUBLIC: + return vol.fsUuid == null ? vol.id : vol.fsUuid; + default: + return null; + } + } } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 2fd699e5a8298..d670bf1b387cb 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -368,7 +368,6 @@ import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.StringWriter; import java.io.UnsupportedEncodingException; -import java.lang.ref.WeakReference; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -3538,6 +3537,9 @@ public class ActivityManagerService extends IActivityManager.Stub String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime) { try { + final String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); + final String[] visibleVolIds = LocalServices.getService(StorageManagerInternal.class) + .getVisibleVolumesForUser(UserHandle.getUserId(uid)); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " + app.processName); checkTime(startTime, "startProcess: asking zygote to start proc"); @@ -3547,12 +3549,14 @@ public class ActivityManagerService extends IActivityManager.Stub app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, app.info.packageName, + packageNames, visibleVolIds, new String[] {PROC_START_SEQ_IDENT + app.startSeq}); } else { startResult = Process.start(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, app.info.packageName, + packageNames, visibleVolIds, new String[] {PROC_START_SEQ_IDENT + app.startSeq}); } checkTime(startTime, "startProcess: returned from zygote!");