Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6036cd51 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Support moving apps to expanded storage."

parents 7c622e99 b9f3674c
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -220,6 +220,7 @@ public final class ActivityThread {
    // which means this lock gets held while the activity and window managers
    // holds their own lock.  Thus you MUST NEVER call back into the activity manager
    // or window manager or anything that depends on them while holding this lock.
    // These LoadedApk are only valid for the userId that we're running as.
    final ArrayMap<String, WeakReference<LoadedApk>> mPackages
            = new ArrayMap<String, WeakReference<LoadedApk>>();
    final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages
@@ -1705,13 +1706,18 @@ public final class ActivityThread {

    public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
            int flags, int userId) {
        final boolean differentUser = (UserHandle.myUserId() != userId);
        synchronized (mResourcesManager) {
            WeakReference<LoadedApk> ref;
            if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
            if (differentUser) {
                // Caching not supported across users
                ref = null;
            } else if ((flags & Context.CONTEXT_INCLUDE_CODE) != 0) {
                ref = mPackages.get(packageName);
            } else {
                ref = mResourcePackages.get(packageName);
            }

            LoadedApk packageInfo = ref != null ? ref.get() : null;
            //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
            //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
@@ -1791,13 +1797,18 @@ public final class ActivityThread {
    private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
            ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
            boolean registerPackage) {
        final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
        synchronized (mResourcesManager) {
            WeakReference<LoadedApk> ref;
            if (includeCode) {
            if (differentUser) {
                // Caching not supported across users
                ref = null;
            } else if (includeCode) {
                ref = mPackages.get(aInfo.packageName);
            } else {
                ref = mResourcePackages.get(aInfo.packageName);
            }

            LoadedApk packageInfo = ref != null ? ref.get() : null;
            if (packageInfo == null || (packageInfo.mResources != null
                    && !packageInfo.mResources.getAssets().isUpToDate())) {
@@ -1816,7 +1827,9 @@ public final class ActivityThread {
                            getSystemContext().mPackageInfo.getClassLoader());
                }

                if (includeCode) {
                if (differentUser) {
                    // Caching not supported across users
                } else if (includeCode) {
                    mPackages.put(aInfo.packageName,
                            new WeakReference<LoadedApk>(packageInfo));
                } else {
+1 −5
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package android.app;

import android.text.TextUtils;
import android.util.ArrayMap;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -46,6 +45,7 @@ import android.util.SparseArray;
import android.view.DisplayAdjustments;
import android.view.Display;
import android.os.SystemProperties;

import dalvik.system.VMRuntime;

import java.io.File;
@@ -136,10 +136,6 @@ public final class LoadedApk {
        mSplitAppDirs = aInfo.splitSourceDirs;
        mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
        mOverlayDirs = aInfo.resourceDirs;
        if (!UserHandle.isSameUser(aInfo.uid, myUid) && !Process.isIsolated()) {
            aInfo.dataDir = PackageManager.getDataDirForUser(UserHandle.getUserId(myUid),
                    mPackageName);
        }
        mSharedLibraries = aInfo.sharedLibraryFiles;
        mDataDir = aInfo.dataDir;
        mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
+11 −7
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.os.Environment;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.storage.VolumeInfo;
import android.text.TextUtils;
import android.util.AndroidException;

import com.android.internal.util.ArrayUtils;
@@ -4184,16 +4185,19 @@ public abstract class PackageManager {
    public abstract @NonNull PackageInstaller getPackageInstaller();

    /**
     * Returns the data directory for a particular user and package, given the uid of the package.
     * @param uid uid of the package, including the userId and appId
     * @param packageName name of the package
     * @return the user-specific data directory for the package
     * Returns the data directory for a particular package and user.
     *
     * @hide
     */
    public static String getDataDirForUser(int userId, String packageName) {
    public static File getDataDirForUser(String volumeUuid, String packageName, int userId) {
        // TODO: This should be shared with Installer's knowledge of user directory
        return Environment.getDataDirectory().toString() + "/user/" + userId
                + "/" + packageName;
        final File base;
        if (TextUtils.isEmpty(volumeUuid)) {
            base = Environment.getDataDirectory();
        } else {
            base = new File("/mnt/expand/" + volumeUuid);
        }
        return new File(base, "user/" + userId + "/" + packageName);
    }

    /**
+16 −2
Original line number Diff line number Diff line
@@ -111,6 +111,9 @@ public class PackageParser {
    /** File name in an APK for the Android manifest. */
    private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";

    /** Path prefix for apps on expanded storage */
    private static final String MNT_EXPAND = "/mnt/expand/";

    /** @hide */
    public static class NewPermissionInfo {
        public final String name;
@@ -860,6 +863,12 @@ public class PackageParser {
            throws PackageParserException {
        final String apkPath = apkFile.getAbsolutePath();

        String volumeUuid = null;
        if (apkPath.startsWith(MNT_EXPAND)) {
            final int end = apkPath.indexOf('/', MNT_EXPAND.length());
            volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
        }

        mParseError = PackageManager.INSTALL_SUCCEEDED;
        mArchiveSourcePath = apkFile.getAbsolutePath();

@@ -882,6 +891,7 @@ public class PackageParser {
                        apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
            }

            pkg.volumeUuid = volumeUuid;
            pkg.baseCodePath = apkPath;
            pkg.mSignatures = null;

@@ -4206,6 +4216,8 @@ public class PackageParser {

        // TODO: work towards making these paths invariant

        public String volumeUuid;

        /**
         * Path where this package was found on disk. For monolithic packages
         * this is path to single base APK file; for cluster packages this is
@@ -4727,7 +4739,8 @@ public class PackageParser {
        ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
        if (userId != 0) {
            ai.uid = UserHandle.getUid(userId, ai.uid);
            ai.dataDir = PackageManager.getDataDirForUser(userId, ai.packageName);
            ai.dataDir = PackageManager.getDataDirForUser(ai.volumeUuid, ai.packageName, userId)
                    .getAbsolutePath();
        }
        if ((flags & PackageManager.GET_META_DATA) != 0) {
            ai.metaData = p.mAppMetaData;
@@ -4755,7 +4768,8 @@ public class PackageParser {
        ai = new ApplicationInfo(ai);
        if (userId != 0) {
            ai.uid = UserHandle.getUid(userId, ai.uid);
            ai.dataDir = PackageManager.getDataDirForUser(userId, ai.packageName);
            ai.dataDir = PackageManager.getDataDirForUser(ai.volumeUuid, ai.packageName, userId)
                    .getAbsolutePath();
        }
        if (state.stopped) {
            ai.flags |= ApplicationInfo.FLAG_STOPPED;
+0 −8
Original line number Diff line number Diff line
@@ -576,14 +576,6 @@ public class PackageManagerTests extends AndroidTestCase {
            fail(pkgName + " shouldnt be installed");
        } catch (NameNotFoundException e) {
        }

        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        List<UserInfo> users = um.getUsers();
        for (UserInfo user : users) {
            String dataDir = PackageManager.getDataDirForUser(user.id, pkgName);
            assertFalse("Application data directory should not exist: " + dataDir,
                    new File(dataDir).exists());
        }
    }

    class InstallParams {
Loading