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

Commit 2567573b authored by Pawit Pornkitprasan's avatar Pawit Pornkitprasan
Browse files

Allow mounting of multiple volumes via mass storage (framework part)



The volumes to mount is taken from storage_list.xml (allowMassStorage)
rather than ro.additionalmounts in CM7.

Hand ported from the following patches:

commit 02332098
Author: Tony Layher <layhertony@gmail.com>
Date:   Sun Jan 2 12:46:38 2011 -0500

    forward port of 93bb9592 to allow mounting and sharing of mulitple volumes to MountService.

    Change-Id: I9fa3994e6e7b85360b451f57c1cdd4df921bc035

(the second part of the above patch was not ported)

commit 678fadf5
Author: Josh Stone <cuviper@gmail.com>
Date:   Sun Nov 7 13:38:58 2010 -0800

    MountService: Remount all volumes after USB disconnect

    If USB was removed while UMS was enabled, the MountService was only
    remounting the primary share.  Any other shares, like the HTC Inc's
    emmc, were left in limbo.  This patch now iterates over *all* shared
    volumes to remount after disconnect.

    Change-Id: Ie6fd49ad80ba6fa0e4e194a386549cac786b4bbe
    Signed-off-by: default avatarJosh Stone <cuviper@gmail.com>

commit b1da9ed0
Author: Josh Stone <cuviper@gmail.com>
Date:   Sat Jan 22 12:03:53 2011 -0800

    MountService: Only notify PackageManager for true ASEC changes

    MountService can be dealing with multiple mounts (emmc, sdcard), but
    only the EXTERNAL_STORAGE has any ASEC mounts on it.  Since the PMS
    updateExternalMediaStatus doesn't specify the path, we need to make sure
    it's only called for the real ASEC mount.  Otherwise we get into nasty
    race conditions when multiple mounts are coming and going, like during
    UMS transitions, and sdcard-installed apps tend to break.

    Change-Id: I85c6a601e84afd30b44270b0892686c2d864ce8d

commit c8c58f3d
Author: Josh Stone <cuviper@gmail.com>
Date:   Sun Mar 6 12:34:50 2011 -0800

    MountService: Unmount secondary volumes more carefully

    Use the same message handler for unmounting both the ASEC external-
    storage path and any secondary paths like emmc.  This seems to help with
    additional race conditions encountered on Inc.

    Change-Id: Icca71756fa6721bd85da1f35b8b8c7fc7caa1eb1

commit 47495ab8
Author: atinm <atinm.dev@gmail.com>
Date:   Sun Apr 10 14:50:41 2011 -0400

    Allow multiple shareable SD Cards by using getShareableVolumes()
    to get all the volumes that are shareable and allowing
    sharing/unsharing for all of them rather than just the hardcoded
    getExternalStorage calls.

    Unmount immediately if PM is not updating and not an ASEC
    mount. Change from Josh Stone.
    Change-Id: Iaf1a7a4484deac373e1c1d7bf16d5f22ca49fd64

    Only allow package manager for sdcard (packages aren't on
    external card).

    Change-Id: I0d148ea52dc1285905a9dd061d1ceedcfb761b52

    Take out extra logging.

    Change-Id: I6beb007700ef4be04c3eb273bbf2069c87b30011

Change-Id: Ibc11b9affdf22a438a4d25cf14435fb16b3ad6d6
parent 9a10df59
Loading
Loading
Loading
Loading
+83 −39
Original line number Diff line number Diff line
@@ -369,6 +369,13 @@ class MountService extends IMountService.Stub
                case H_UNMOUNT_PM_UPDATE: {
                    if (DEBUG_UNMOUNT) Slog.i(TAG, "H_UNMOUNT_PM_UPDATE");
                    UnmountCallBack ucb = (UnmountCallBack) msg.obj;
                    if (!mUpdatingStatus && !isExternalStorage(ucb.path)) {
                        // If PM isn't already updating, and this isn't an ASEC
                        // mount, then go ahead and do the unmount immediately.
                        if (DEBUG_UNMOUNT) Slog.i(TAG, " skipping PackageManager for " + ucb.path);
                        ucb.handleFinished();
                        break;
                    }
                    mForceUnmounts.add(ucb);
                    if (DEBUG_UNMOUNT) Slog.i(TAG, " registered = " + mUpdatingStatus);
                    // Register only if needed.
@@ -588,7 +595,9 @@ class MountService extends IMountService.Stub
            // Update state on PackageManager, but only of real events
            if (!mEmulateExternalStorage) {
                if (Environment.MEDIA_UNMOUNTED.equals(state)) {
                    if (isExternalStorage(path)) {
                        mPms.updateExternalMediaStatus(false, false);
                    }

                    /*
                     * Some OBBs might have been unmounted when this volume was
@@ -598,10 +607,12 @@ class MountService extends IMountService.Stub
                    mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
                            OBB_FLUSH_MOUNT_STATE, path));
                } else if (Environment.MEDIA_MOUNTED.equals(state)) {
                    if (isExternalStorage(path)) {
                        mPms.updateExternalMediaStatus(true, false);
                    }
                }
            }
        }
        synchronized (mListeners) {
            for (int i = mListeners.size() -1; i >= 0; i--) {
                MountServiceBinderListener bl = mListeners.get(i);
@@ -907,7 +918,9 @@ class MountService extends IMountService.Stub
        Runtime.getRuntime().gc();

        // Redundant probably. But no harm in updating state again.
        if (isExternalStorage(path)) {
            mPms.updateExternalMediaStatus(false, false);
        }
        try {
            String arg = removeEncryption
                    ? " force_and_revert"
@@ -1007,8 +1020,13 @@ class MountService extends IMountService.Stub
            mSendUmsConnectedOnBoot = avail;
        }

        final String path = Environment.getExternalStorageDirectory().getPath();
        if (avail == false && getVolumeState(path).equals(Environment.MEDIA_SHARED)) {
        final ArrayList<String> volumes = getShareableVolumes();
        boolean mediaShared = false;
        for (String path : volumes) {
            if (getVolumeState(path).equals(Environment.MEDIA_SHARED))
                mediaShared = true;
        }
        if (avail == false && mediaShared) {
            /*
             * USB mass storage disconnected while enabled
             */
@@ -1018,12 +1036,16 @@ class MountService extends IMountService.Stub
                    try {
                        int rc;
                        Slog.w(TAG, "Disabling UMS after cable disconnect");
                        for (String path : volumes) {
                            if (getVolumeState(path).equals(Environment.MEDIA_SHARED)) {
                                doShareUnshareVolume(path, "ums", false);
                                if ((rc = doMountVolume(path)) != StorageResultCode.OperationSucceeded) {
                                    Slog.e(TAG, String.format(
                                            "Failed to remount {%s} on UMS enabled-disconnect (%d)",
                                                    path, rc));
                                }
                            }
                        }
                    } catch (Exception ex) {
                        Slog.w(TAG, "Failed to mount media on UMS enabled-disconnect", ex);
                    }
@@ -1305,16 +1327,32 @@ class MountService extends IMountService.Stub
        }
    }

    private boolean isExternalStorage(String path) {
        return Environment.getExternalStorageDirectory().getPath().equals(path);
    }

    private ArrayList<String> getShareableVolumes() {
        // Sharable volumes have android:allowMassStorage="true" in storage_list.xml
        ArrayList<String> volumesToMount = new ArrayList<String>();
        synchronized (mVolumes) {
            for (StorageVolume v : mVolumes) {
                if (v.allowMassStorage()) {
                    volumesToMount.add(v.getPath());
                }
            }
        }
        return volumesToMount;
    }

    public void setUsbMassStorageEnabled(boolean enable) {
        waitForReady();
        validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);

        // TODO: Add support for multiple share methods

        for (String path : getShareableVolumes()) {
            /*
             * If the volume is mounted and we're enabling then unmount it
             */
        String path = Environment.getExternalStorageDirectory().getPath();
            String vs = getVolumeState(path);
            String method = "ums";
            if (enable && vs.equals(Environment.MEDIA_MOUNTED)) {
@@ -1341,10 +1379,16 @@ class MountService extends IMountService.Stub
                }
            }
        }
    }

    public boolean isUsbMassStorageEnabled() {
        waitForReady();
        return doGetVolumeShared(Environment.getExternalStorageDirectory().getPath(), "ums");
        for (String path : getShareableVolumes()) {
            if (doGetVolumeShared(path, "ums"))
                return true;
        }
        // no volume is shared
        return false;
    }

    /**