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

Commit 16f31e45 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "Storage: Add secondary storage support for app installation"

parents 22be7a7f d9d25bc7
Loading
Loading
Loading
Loading
+42 −0
Original line number Original line Diff line number Diff line
@@ -70,6 +70,7 @@ public class Environment {


    @GuardedBy("sLock")
    @GuardedBy("sLock")
    private static volatile StorageVolume sPrimaryVolume;
    private static volatile StorageVolume sPrimaryVolume;
    private static volatile StorageVolume sNoEmulatedVolume;


    private static StorageVolume getPrimaryVolume() {
    private static StorageVolume getPrimaryVolume() {
        if (SystemProperties.getBoolean("config.disable_storage", false)) {
        if (SystemProperties.getBoolean("config.disable_storage", false)) {
@@ -93,6 +94,24 @@ public class Environment {
        return sPrimaryVolume;
        return sPrimaryVolume;
    }
    }


    private static StorageVolume getNoEmulatedVolume() {
        if (sNoEmulatedVolume == null) {
            synchronized (sLock) {
                if (sNoEmulatedVolume == null) {
                    try {
                        IMountService mountService = IMountService.Stub.asInterface(ServiceManager
                                .getService("mount"));
                        final StorageVolume[] volumes = mountService.getVolumeList();
                        sNoEmulatedVolume = StorageManager.getNoEmulatedVolume(volumes);
                    } catch (Exception e) {
                        Log.e(TAG, "couldn't talk to MountService", e);
                    }
                }
            }
        }
        return sNoEmulatedVolume;
    }

    static {
    static {
        initForCurrentUser();
        initForCurrentUser();
    }
    }
@@ -178,6 +197,11 @@ public class Environment {
            return mExternalDirsForApp[0];
            return mExternalDirsForApp[0];
        }
        }


        /** {@hide} */
        public File getSecondaryStorageDirectory() {
            return mExternalDirsForApp[1];
        }

        @Deprecated
        @Deprecated
        public File getExternalStoragePublicDirectory(String type) {
        public File getExternalStoragePublicDirectory(String type) {
            return buildExternalStoragePublicDirs(type)[0];
            return buildExternalStoragePublicDirs(type)[0];
@@ -389,6 +413,12 @@ public class Environment {
        return sCurrentUser.getExternalDirsForApp()[0];
        return sCurrentUser.getExternalDirsForApp()[0];
    }
    }


    /** {@hide} */
    public static File getSecondaryStorageDirectory() {
        throwIfUserRequired();
        return sCurrentUser.getExternalDirsForApp()[1];
    }

    /** {@hide} */
    /** {@hide} */
    public static File getLegacyExternalStorageDirectory() {
    public static File getLegacyExternalStorageDirectory() {
        return new File(System.getenv(ENV_EXTERNAL_STORAGE));
        return new File(System.getenv(ENV_EXTERNAL_STORAGE));
@@ -709,6 +739,12 @@ public class Environment {
        return getStorageState(externalDir);
        return getStorageState(externalDir);
    }
    }


    /** {@hide} */
    public static String getSecondaryStorageState() {
        final File externalDir = sCurrentUser.getExternalDirsForApp()[1];
        return getStorageState(externalDir);
    }

    /**
    /**
     * Returns the current state of the storage device that provides the given
     * Returns the current state of the storage device that provides the given
     * path.
     * path.
@@ -756,6 +792,12 @@ public class Environment {
        return (primary != null && primary.isRemovable());
        return (primary != null && primary.isRemovable());
    }
    }


    /** {@hide} */
    public static boolean isNoEmulatedStorageExist() {
        final StorageVolume volume = getNoEmulatedVolume();
        return (volume != null);
    }

    /**
    /**
     * Returns whether the device has an external storage device which is
     * Returns whether the device has an external storage device which is
     * emulated. If true, the device does not have real external storage, and the directory
     * emulated. If true, the device does not have real external storage, and the directory
+10 −0
Original line number Original line Diff line number Diff line
@@ -632,6 +632,16 @@ public class StorageManager {
        return null;
        return null;
    }
    }


    /**{@hide} */
    public static StorageVolume getNoEmulatedVolume(StorageVolume[] volumes) {
        for (StorageVolume volume : volumes) {
            if (!volume.isEmulated()) {
                return volume;
            }
        }
        return null;
    }

    private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
    private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
    private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500 * MB_IN_BYTES;
    private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500 * MB_IN_BYTES;
    private static final long DEFAULT_FULL_THRESHOLD_BYTES = MB_IN_BYTES;
    private static final long DEFAULT_FULL_THRESHOLD_BYTES = MB_IN_BYTES;
+10 −10
Original line number Original line Diff line number Diff line
@@ -717,7 +717,7 @@ public class DefaultContainerService extends IntentService {
            prefer = PREFER_INTERNAL;
            prefer = PREFER_INTERNAL;
        }
        }


        final boolean emulated = Environment.isExternalStorageEmulated();
        final boolean noemulated = Environment.isNoEmulatedStorageExist();


        final File apkFile = new File(archiveFilePath);
        final File apkFile = new File(archiveFilePath);


@@ -731,7 +731,7 @@ public class DefaultContainerService extends IntentService {
        }
        }


        boolean fitsOnSd = false;
        boolean fitsOnSd = false;
        if (!emulated && (checkBoth || prefer == PREFER_EXTERNAL)) {
        if (noemulated && (checkBoth || prefer == PREFER_EXTERNAL)) {
            try {
            try {
                fitsOnSd = isUnderExternalThreshold(apkFile, isForwardLocked);
                fitsOnSd = isUnderExternalThreshold(apkFile, isForwardLocked);
            } catch (IOException e) {
            } catch (IOException e) {
@@ -743,7 +743,7 @@ public class DefaultContainerService extends IntentService {
            if (fitsOnInternal) {
            if (fitsOnInternal) {
                return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
                return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
            }
            }
        } else if (!emulated && prefer == PREFER_EXTERNAL) {
        } else if (noemulated && prefer == PREFER_EXTERNAL) {
            if (fitsOnSd) {
            if (fitsOnSd) {
                return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
                return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
            }
            }
@@ -752,7 +752,7 @@ public class DefaultContainerService extends IntentService {
        if (checkBoth) {
        if (checkBoth) {
            if (fitsOnInternal) {
            if (fitsOnInternal) {
                return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
                return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
            } else if (!emulated && fitsOnSd) {
            } else if (noemulated && fitsOnSd) {
                return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
                return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
            }
            }
        }
        }
@@ -762,8 +762,8 @@ public class DefaultContainerService extends IntentService {
         * the media was unavailable. Otherwise, indicate there was insufficient
         * the media was unavailable. Otherwise, indicate there was insufficient
         * storage space available.
         * storage space available.
         */
         */
        if (!emulated && (checkBoth || prefer == PREFER_EXTERNAL)
        if (noemulated && (checkBoth || prefer == PREFER_EXTERNAL)
                && !Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
                && !Environment.MEDIA_MOUNTED.equals(Environment.getSecondaryStorageState())) {
            return PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE;
            return PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE;
        } else {
        } else {
            return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
            return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
@@ -806,17 +806,17 @@ public class DefaultContainerService extends IntentService {
     */
     */
    private boolean isUnderExternalThreshold(File apkFile, boolean isForwardLocked)
    private boolean isUnderExternalThreshold(File apkFile, boolean isForwardLocked)
            throws IOException {
            throws IOException {
        if (Environment.isExternalStorageEmulated()) {
        if (!Environment.isNoEmulatedStorageExist()) {
            return false;
            return false;
        }
        }


        final int sizeMb = calculateContainerSize(apkFile, isForwardLocked);
        final int sizeMb = calculateContainerSize(apkFile, isForwardLocked);


        final int availSdMb;
        final int availSdMb;
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
        if (Environment.MEDIA_MOUNTED.equals(Environment.getSecondaryStorageState())) {
            final StatFs sdStats = new StatFs(Environment.getExternalStorageDirectory().getPath());
            final StatFs sdStats = new StatFs(Environment.getSecondaryStorageDirectory().getPath());
            final int blocksToMb = (1 << 20) / sdStats.getBlockSize();
            final int blocksToMb = (1 << 20) / sdStats.getBlockSize();
            availSdMb = sdStats.getAvailableBlocks() * blocksToMb;
            availSdMb = sdStats.getAvailableBlocks() / blocksToMb;
        } else {
        } else {
            availSdMb = -1;
            availSdMb = -1;
        }
        }
+3 −3
Original line number Original line Diff line number Diff line
@@ -678,9 +678,9 @@ class MountService extends IMountService.Stub


        Slog.d(TAG, "volume state changed for " + path + " (" + oldState + " -> " + state + ")");
        Slog.d(TAG, "volume state changed for " + path + " (" + oldState + " -> " + state + ")");


        // Tell PackageManager about changes to primary volume state, but only
        // Tell PackageManager about changes, not only to primary volume,
        // when not emulated.
        // to all the non-emulated storage volumes
        if (volume.isPrimary() && !volume.isEmulated()) {
        if (!volume.isEmulated()) {
            if (Environment.MEDIA_UNMOUNTED.equals(state)) {
            if (Environment.MEDIA_UNMOUNTED.equals(state)) {
                mPms.updateExternalMediaStatus(false, false);
                mPms.updateExternalMediaStatus(false, false);


+14 −2
Original line number Original line Diff line number Diff line
@@ -6605,8 +6605,20 @@ public class PackageManagerService extends IPackageManager.Stub {


        verificationParams.setInstallerUid(uid);
        verificationParams.setInstallerUid(uid);


        final int userFilteredFlags;

        if (getInstallLocation() == PackageHelper.APP_INSTALL_INTERNAL) {
            Slog.w(TAG, "PackageManager.INSTALL_INTERNAL"  );
            userFilteredFlags = flags | PackageManager.INSTALL_INTERNAL;
        } else if (getInstallLocation() == PackageHelper.APP_INSTALL_EXTERNAL) {
            Slog.w(TAG, "PackageManager.INSTALL_EXTERNAL"  );
            userFilteredFlags = flags | PackageManager.INSTALL_EXTERNAL;
        } else{
            userFilteredFlags = filteredFlags;
        }

        final Message msg = mHandler.obtainMessage(INIT_COPY);
        final Message msg = mHandler.obtainMessage(INIT_COPY);
        msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
        msg.obj = new InstallParams(packageURI, observer, userFilteredFlags, installerPackageName,
                verificationParams, encryptionParams, user);
                verificationParams, encryptionParams, user);
        mHandler.sendMessage(msg);
        mHandler.sendMessage(msg);
    }
    }
@@ -7233,7 +7245,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            if (Environment.isExternalStorageEmulated()) {
            if (Environment.isExternalStorageEmulated()) {
                mounted = true;
                mounted = true;
            } else {
            } else {
                final String status = Environment.getExternalStorageState();
                final String status = Environment.getSecondaryStorageState();
                mounted = (Environment.MEDIA_MOUNTED.equals(status)
                mounted = (Environment.MEDIA_MOUNTED.equals(status)
                        || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
                        || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
            }
            }