Merge "Update StorageManagerService handling of packages info."
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 4f58321..6f49cc4 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -703,6 +703,18 @@
public abstract SparseArray<String> getAppsWithSharedUserIds();
/**
+ * Get the value of attribute android:sharedUserId for the given packageName if specified,
+ * otherwise {@code null}.
+ */
+ public abstract String getSharedUserIdForPackage(@NonNull String packageName);
+
+ /**
+ * Get all packages which specified the given sharedUserId as android:sharedUserId attribute
+ * or an empty array if no package specified it.
+ */
+ public abstract String[] getPackagesForSharedUserId(@NonNull String sharedUserId, int userId);
+
+ /**
* Return if device is currently in a "core" boot environment, typically
* used to support full-disk encryption. Only apps marked with
* {@code coreApp} attribute are available.
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index 63ff7b2..816a730 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -101,9 +101,11 @@
* Delete storage sandbox for the given package.
*
* @param packageName The package for which the sandbox needs to be destroyed.
+ * @param sharedUserId The sharedUserId if specified by the package.
* @param userId The userId in which the sandbox needs to be destroyed.
*/
- public abstract void destroySandboxForApp(@NonNull String packageName, int userId);
+ public abstract void destroySandboxForApp(@NonNull String packageName,
+ @Nullable String sharedUserId, int userId);
/**
* @return Labels of storage volumes that are visible to the given userId.
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 858dced..5643a6a 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -112,7 +112,6 @@
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.AppFuseMount;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.FuseUnavailableMountException;
@@ -323,12 +322,6 @@
@GuardedBy("mPackagesLock")
private final SparseArray<ArraySet<String>> mPackages = new SparseArray<>();
- @GuardedBy("mPackagesLock")
- private final ArrayMap<String, Integer> mAppIds = new ArrayMap<>();
-
- @GuardedBy("mPackagesLock")
- private final SparseArray<String> mSandboxIds = new SparseArray<>();
-
/**
* List of volumes visible to any user.
* TODO: may be have a map of userId -> volumes?
@@ -876,13 +869,12 @@
try {
mVold.reset();
- pushPackagesInfo();
// Tell vold about all existing and started users
for (UserInfo user : users) {
mVold.onUserAdded(user.id, user.serialNumber);
}
for (int userId : systemUnlockedUsers) {
- mVold.onUserStarted(userId, getPackagesArrayForUser(userId));
+ sendUserStartedCallback(userId);
mStoraged.onUserStarted(userId);
}
mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
@@ -899,7 +891,7 @@
// staging area is ready so it's ready for zygote-forked apps to
// bind mount against.
try {
- mVold.onUserStarted(userId, getPackagesArrayForUser(userId));
+ sendUserStartedCallback(userId);
mStoraged.onUserStarted(userId);
} catch (Exception e) {
Slog.wtf(TAG, e);
@@ -932,11 +924,52 @@
Slog.wtf(TAG, e);
}
+ synchronized (mPackagesLock) {
+ mPackages.delete(userId);
+ }
+
synchronized (mLock) {
mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
}
}
+ private void sendUserStartedCallback(int userId) throws Exception {
+ if (!ENABLE_ISOLATED_STORAGE) {
+ mVold.onUserStarted(userId, EmptyArray.STRING, EmptyArray.INT, EmptyArray.STRING);
+ }
+
+ final String[] packages;
+ final int[] appIds;
+ final String[] sandboxIds;
+ final SparseArray<String> sharedUserIds = mPmInternal.getAppsWithSharedUserIds();
+ final List<ApplicationInfo> appInfos =
+ mContext.getPackageManager().getInstalledApplicationsAsUser(
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+ synchronized (mPackagesLock) {
+ final ArraySet<String> userPackages = new ArraySet<>();
+ final ArrayMap<String, Integer> packageToAppId = new ArrayMap<>();
+ for (int i = appInfos.size() - 1; i >= 0; --i) {
+ final ApplicationInfo appInfo = appInfos.get(i);
+ if (appInfo.isInstantApp()) {
+ continue;
+ }
+ userPackages.add(appInfo.packageName);
+ packageToAppId.put(appInfo.packageName, UserHandle.getAppId(appInfo.uid));
+ }
+ mPackages.put(userId, userPackages);
+
+ packages = new String[userPackages.size()];
+ appIds = new int[userPackages.size()];
+ sandboxIds = new String[userPackages.size()];
+ for (int i = userPackages.size() - 1; i >= 0; --i) {
+ packages[i] = userPackages.valueAt(i);
+ appIds[i] = packageToAppId.get(packages[i]);
+ sandboxIds[i] = getSandboxId(packages[i], sharedUserIds.get(appIds[i]));
+ }
+ }
+ mVold.onUserStarted(userId, packages, appIds, sandboxIds);
+ }
+
@Override
public void onAwakeStateChanged(boolean isAwake) {
// Ignored
@@ -1454,111 +1487,12 @@
}
private void start() {
- collectPackagesInfo();
connect();
}
- @VisibleForTesting
- void collectPackagesInfo() {
- if (!ENABLE_ISOLATED_STORAGE) return;
-
- resetPackageData();
- final SparseArray<String> sharedUserIds = mPmInternal.getAppsWithSharedUserIds();
- final int[] userIds = mUmInternal.getUserIds();
- for (int userId : userIds) {
- final List<ApplicationInfo> appInfos
- = mContext.getPackageManager().getInstalledApplicationsAsUser(
- PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
- synchronized (mPackagesLock) {
- final ArraySet<String> userPackages = getAvailablePackagesForUserPL(userId);
- for (int i = appInfos.size() - 1; i >= 0; --i) {
- if (appInfos.get(i).isInstantApp()) {
- continue;
- }
- final String packageName = appInfos.get(i).packageName;
- userPackages.add(packageName);
-
- final int appId = UserHandle.getAppId(appInfos.get(i).uid);
- mAppIds.put(packageName, appId);
- mSandboxIds.put(appId, getSandboxId(packageName, sharedUserIds.get(appId)));
- }
- }
- }
- }
-
- private void resetPackageData() {
- synchronized (mPackagesLock) {
- mPackages.clear();
- mAppIds.clear();
- mSandboxIds.clear();
- }
- }
-
private static String getSandboxId(String packageName, String sharedUserId) {
return sharedUserId == null ? packageName : SHARED_SANDBOX_ID_PREFIX + sharedUserId;
}
- private void pushPackagesInfo() throws RemoteException {
- if (!ENABLE_ISOLATED_STORAGE) return;
-
- // Arrays to fill up from {@link #mAppIds}
- final String[] allPackageNames;
- final int[] appIdsForPackages;
-
- // Arrays to fill up from {@link #mSandboxIds}
- final int[] allAppIds;
- final String[] sandboxIdsForApps;
- synchronized (mPackagesLock) {
- allPackageNames = new String[mAppIds.size()];
- appIdsForPackages = new int[mAppIds.size()];
- for (int i = mAppIds.size() - 1; i >= 0; --i) {
- allPackageNames[i] = mAppIds.keyAt(i);
- appIdsForPackages[i] = mAppIds.valueAt(i);
- }
-
- allAppIds = new int[mSandboxIds.size()];
- sandboxIdsForApps = new String[mSandboxIds.size()];
- for (int i = mSandboxIds.size() - 1; i >= 0; --i) {
- allAppIds[i] = mSandboxIds.keyAt(i);
- sandboxIdsForApps[i] = mSandboxIds.valueAt(i);
- }
- }
- mVold.addAppIds(allPackageNames, appIdsForPackages);
- mVold.addSandboxIds(allAppIds, sandboxIdsForApps);
- }
-
- @GuardedBy("mPackagesLock")
- private ArraySet<String> getAvailablePackagesForUserPL(int userId) {
- ArraySet<String> userPackages = mPackages.get(userId);
- if (userPackages == null) {
- userPackages = new ArraySet<>();
- mPackages.put(userId, userPackages);
- }
- return userPackages;
- }
-
- private String[] getPackagesArrayForUser(int userId) {
- if (!ENABLE_ISOLATED_STORAGE) return EmptyArray.STRING;
-
- final ArraySet<String> userPackages;
- synchronized (mPackagesLock) {
- userPackages = getAvailablePackagesForUserPL(userId);
- if (!userPackages.isEmpty()) {
- return userPackages.toArray(new String[0]);
- }
- }
- final List<ApplicationInfo> 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]);
- }
- }
private void connect() {
IBinder binder = ServiceManager.getService("storaged");
@@ -3122,15 +3056,8 @@
throw new SecurityException("Shady looking path " + path);
}
- final int uid = mPmInternal.getPackageUid(packageName,
- PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
- final String sandboxId;
- synchronized (mPackagesLock) {
- sandboxId = mSandboxIds.get(UserHandle.getAppId(uid));
- }
- if (uid < 0 || sandboxId == null) {
- throw new IllegalArgumentException("Unknown package " + packageName);
- }
+ final String sharedUserId = mPmInternal.getSharedUserIdForPackage(packageName);
+ final String sandboxId = getSandboxId(packageName, sharedUserId);
final Matcher m = PATTERN_TRANSLATE.matcher(path);
if (m.matches()) {
@@ -3139,7 +3066,9 @@
// Does path belong to any packages belonging to this UID? If so,
// they get to go straight through to legacy paths.
- final String[] pkgs = mContext.getPackageManager().getPackagesForUid(uid);
+ final String[] pkgs = (sharedUserId == null)
+ ? new String[] {packageName}
+ : mPmInternal.getPackagesForSharedUserId(sharedUserId, userId);
for (String pkg : pkgs) {
if (devicePath.startsWith("Android/data/" + pkg + "/") ||
devicePath.startsWith("Android/media/" + pkg + "/") ||
@@ -3758,16 +3687,14 @@
int userId) {
final String sandboxId;
synchronized (mPackagesLock) {
- final ArraySet<String> userPackages = getAvailablePackagesForUserPL(userId);
+ final ArraySet<String> userPackages = mPackages.get(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)) {
+ if (userPackages == null || userPackages.contains(packageName)) {
return;
}
userPackages.add(packageName);
- mAppIds.put(packageName, appId);
sandboxId = getSandboxId(packageName, sharedUserId);
- mSandboxIds.put(appId, sandboxId);
}
try {
@@ -3778,34 +3705,21 @@
}
@Override
- public void destroySandboxForApp(String packageName, int userId) {
+ public void destroySandboxForApp(String packageName, String sharedUserId, int userId) {
if (!ENABLE_ISOLATED_STORAGE) {
return;
}
- final int appId;
- final String sandboxId;
+ final String sandboxId = getSandboxId(packageName, sharedUserId);
synchronized (mPackagesLock) {
- final ArraySet<String> userPackages = getAvailablePackagesForUserPL(userId);
- userPackages.remove(packageName);
- appId = mAppIds.get(packageName);
- sandboxId = mSandboxIds.get(appId);
-
- // If the package is not uninstalled in any other users, remove appId and sandboxId
- // corresponding to it from the internal state.
- boolean installedInAnyUser = false;
- for (int i = mPackages.size() - 1; i >= 0; --i) {
- if (mPackages.valueAt(i).contains(packageName)) {
- installedInAnyUser = true;
- break;
- }
- }
- if (!installedInAnyUser) {
- mAppIds.remove(packageName);
- mSandboxIds.remove(appId);
+ final ArraySet<String> userPackages = mPackages.get(userId);
+ // If the userPackages is null, it means the user is not started but we still
+ // need to delete the sandbox data though.
+ if (userPackages != null) {
+ userPackages.remove(packageName);
}
}
try {
- mVold.destroySandboxForApp(packageName, appId, sandboxId, userId);
+ mVold.destroySandboxForApp(packageName, sandboxId, userId);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f5a18b0..b988c6a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -322,6 +322,7 @@
import dalvik.system.VMRuntime;
import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -9530,7 +9531,8 @@
}
}
if (deleteSandboxData && getStorageManagerInternal() != null) {
- getStorageManagerInternal().destroySandboxForApp(pkg.packageName, realUserId);
+ getStorageManagerInternal().destroySandboxForApp(pkg.packageName,
+ pkg.mSharedUserId, realUserId);
}
} catch (PackageManagerException e) {
// Should not happen
@@ -22942,6 +22944,20 @@
}
@Override
+ public String getSharedUserIdForPackage(String packageName) {
+ synchronized (mPackages) {
+ return getSharedUserIdForPackageLocked(packageName);
+ }
+ }
+
+ @Override
+ public String[] getPackagesForSharedUserId(String sharedUserId, int userId) {
+ synchronized (mPackages) {
+ return getPackagesForSharedUserIdLocked(sharedUserId, userId);
+ }
+ }
+
+ @Override
public boolean isOnlyCoreApps() {
return PackageManagerService.this.isOnlyCoreApps();
}
@@ -22953,6 +22969,7 @@
}
}
+ @GuardedBy("mPackages")
private SparseArray<String> getAppsWithSharedUserIdsLocked() {
final SparseArray<String> sharedUserIds = new SparseArray<>();
synchronized (mPackages) {
@@ -22963,6 +22980,38 @@
return sharedUserIds;
}
+ @GuardedBy("mPackages")
+ private String getSharedUserIdForPackageLocked(String packageName) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ return (ps != null && ps.isSharedUser()) ? ps.sharedUser.name : null;
+ }
+
+ @GuardedBy("mPackages")
+ private String[] getPackagesForSharedUserIdLocked(String sharedUserId, int userId) {
+ try {
+ final SharedUserSetting sus = mSettings.getSharedUserLPw(
+ sharedUserId, 0, 0, false);
+ if (sus == null) {
+ return EmptyArray.STRING;
+ }
+ String[] res = new String[sus.packages.size()];
+ final Iterator<PackageSetting> it = sus.packages.iterator();
+ int i = 0;
+ while (it.hasNext()) {
+ PackageSetting ps = it.next();
+ if (ps.getInstalled(userId)) {
+ res[i++] = ps.name;
+ } else {
+ res = ArrayUtils.removeElement(String.class, res, res[i]);
+ }
+ }
+ return res;
+ } catch (PackageManagerException e) {
+ // Should not happen
+ }
+ return EmptyArray.STRING;
+ }
+
@Override
public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) {
enforceSystemOrPhoneCaller("grantPermissionsToEnabledCarrierApps");
diff --git a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
index 8022532..e53518c 100644
--- a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
@@ -30,7 +30,6 @@
import android.os.storage.StorageManagerInternal;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.util.SparseArray;
import org.junit.Before;
import org.junit.Test;
@@ -38,9 +37,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.ArrayList;
-import java.util.List;
-
@SmallTest
@RunWith(AndroidJUnit4.class)
public class StorageManagerServiceTest {
@@ -83,29 +79,14 @@
when(mUmi.getUserIds()).thenReturn(new int[] { 0 });
- {
- final SparseArray<String> res = new SparseArray<>();
- res.put(UID_COLORS, NAME_COLORS);
- when(mPmi.getAppsWithSharedUserIds()).thenReturn(res);
- }
+ when(mPmi.getSharedUserIdForPackage(eq(PKG_GREY))).thenReturn(null);
+ when(mPmi.getSharedUserIdForPackage(eq(PKG_RED))).thenReturn(NAME_COLORS);
+ when(mPmi.getSharedUserIdForPackage(eq(PKG_BLUE))).thenReturn(NAME_COLORS);
- {
- final List<ApplicationInfo> res = new ArrayList<>();
- res.add(buildApplicationInfo(PKG_GREY, UID_GREY));
- res.add(buildApplicationInfo(PKG_RED, UID_COLORS));
- res.add(buildApplicationInfo(PKG_BLUE, UID_COLORS));
- when(mPm.getInstalledApplicationsAsUser(anyInt(), anyInt())).thenReturn(res);
- }
-
- when(mPmi.getPackageUid(eq(PKG_GREY), anyInt(), anyInt())).thenReturn(UID_GREY);
- when(mPmi.getPackageUid(eq(PKG_RED), anyInt(), anyInt())).thenReturn(UID_COLORS);
- when(mPmi.getPackageUid(eq(PKG_BLUE), anyInt(), anyInt())).thenReturn(UID_COLORS);
-
- when(mPm.getPackagesForUid(eq(UID_GREY))).thenReturn(new String[] { PKG_GREY });
- when(mPm.getPackagesForUid(eq(UID_COLORS))).thenReturn(new String[] { PKG_RED, PKG_BLUE });
+ when(mPmi.getPackagesForSharedUserId(eq(NAME_COLORS), anyInt()))
+ .thenReturn(new String[] { PKG_RED, PKG_BLUE });
mService = new StorageManagerService(mContext);
- mService.collectPackagesInfo();
}
@Test