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

Commit 02332098 authored by Tony Layher's avatar Tony Layher Committed by Koushik Dutta
Browse files

forward port of 93bb9592 to allow mounting and...


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

Change-Id: I9fa3994e6e7b85360b451f57c1cdd4df921bc035

Wait for IDLE state before mounting on insert

As soon as we recive the insert event we try to
mount the mmc sending a "volume mount" command.
But, the volume manager sometimes is still on
"pending" state, and the insertion mount will
fail.

This patch calls the doMount command on insert
only after the state has changed to idle.
This way, the mount will not fail, because the
state is pending.

Change-Id: I1f8f13c8e232a6b9159eeb78a9484838f1c600af
Signed-off-by: default avatarAxel Haslam <axelhaslam@ti.com>
parent 7cc9593e
Loading
Loading
Loading
Loading
+128 −99
Original line number Diff line number Diff line
@@ -142,7 +142,7 @@ class MountService extends IMountService.Stub

    private Context                               mContext;
    private NativeDaemonConnector                 mConnector;
    private String                                mLegacyState = Environment.MEDIA_REMOVED;
    HashMap<String, String>                       mVolumeStates = new HashMap<String, String>();
    private PackageManagerService                 mPms;
    private boolean                               mUmsEnabling;
    // Used as a lock for methods that register/unregister listeners.
@@ -272,6 +272,8 @@ class MountService extends IMountService.Stub
    private static final int RETRY_UNMOUNT_DELAY = 30; // in ms
    private static final int MAX_UNMOUNT_RETRIES = 4;

    /*used to send the mount command after state is idle.*/
    boolean insertionMountPending = false;
    class UnmountCallBack {
        final String path;
        final boolean force;
@@ -441,8 +443,10 @@ class MountService extends IMountService.Stub
                }
                new Thread() {
                    public void run() {
                        ArrayList<String> volumesToMount = getShareableVolumes();

                        for (String path: volumesToMount) {
                            try {
                            String path = Environment.getExternalStorageDirectory().getPath();
                                String state = getVolumeState(path);

                                if (state.equals(Environment.MEDIA_UNMOUNTED)) {
@@ -470,6 +474,7 @@ class MountService extends IMountService.Stub
                                Slog.e(TAG, "Boot-time mount exception", ex);
                            }
                        }
                    }
                }.start();
            }
        }
@@ -507,13 +512,9 @@ class MountService extends IMountService.Stub
    }

    private void updatePublicVolumeState(String path, String state) {
        if (!path.equals(Environment.getExternalStorageDirectory().getPath())) {
            Slog.w(TAG, "Multiple volumes not currently supported");
            return;
        }

        if (mLegacyState.equals(state)) {
            Slog.w(TAG, String.format("Duplicate state transition (%s -> %s)", mLegacyState, state));
        String currentState = getVolumeState(path);
        if (currentState.equals(state)) {
            Slog.w(TAG, String.format("Duplicate state transition (%s -> %s)", currentState, state));
            return;
        }

@@ -533,8 +534,8 @@ class MountService extends IMountService.Stub
            mPms.updateExternalMediaStatus(true, false);
        }

        String oldState = mLegacyState;
        mLegacyState = state;
        String oldState = currentState;
        setVolumeState(path, state);

        synchronized (mListeners) {
            for (int i = mListeners.size() -1; i >= 0; i--) {
@@ -565,20 +566,15 @@ class MountService extends IMountService.Stub
                /**
                 * Determine media state and UMS detection status
                 */
                String path = Environment.getExternalStorageDirectory().getPath();
                String state = Environment.MEDIA_REMOVED;

                try {
                String[] vols = mConnector.doListCommand(
                    "volume list", VoldResponseCode.VolumeListResult);
                for (String volstr : vols) {
                    String path = null;
                    String state = Environment.MEDIA_REMOVED;
                    try {
                        String[] tok = volstr.split(" ");
                        path = tok[1];
                        // FMT: <label> <mountpoint> <state>
                        if (!tok[1].equals(path)) {
                            Slog.w(TAG, String.format(
                                    "Skipping unknown volume '%s'",tok[1]));
                            continue;
                        }
                        int st = Integer.parseInt(tok[2]);
                        if (st == VolumeState.NoMedia) {
                            state = Environment.MEDIA_REMOVED;
@@ -593,14 +589,14 @@ class MountService extends IMountService.Stub
                        } else {
                            throw new Exception(String.format("Unexpected state %d", st));
                        }
                    }
                        if (state != null) {
                            if (DEBUG_EVENTS) Slog.i(TAG, "Updating valid state " + state);
                            updatePublicVolumeState(path, state);
                        }
                    } catch (Exception e) {
                        Slog.e(TAG, "Error processing initial volume state", e);
                    updatePublicVolumeState(path, Environment.MEDIA_REMOVED);
                        if (path != null) updatePublicVolumeState(path, Environment.MEDIA_REMOVED);
                    }
                }

                try {
@@ -642,6 +638,26 @@ class MountService extends IMountService.Stub
             * Format: "NNN Volume <label> <path> state changed
             * from <old_#> (<old_str>) to <new_#> (<new_str>)"
             */
            if ((Integer.parseInt(cooked[10]) == VolumeState.Idle) &&
                 insertionMountPending == true) {
                /* If the state moves to idle after a insertion
                 * try to mount the device "Insertion mount"
                 */
                final String path = cooked[3];
                insertionMountPending = false;
                new Thread() {
                    public void run() {
                        try {
                            int rc;
                            if ((rc = doMountVolume(path)) != StorageResultCode.OperationSucceeded) {
                                Slog.w(TAG, String.format("Insertion mount failed (%d)", rc));
                            }
                        } catch (Exception ex) {
                            Slog.w(TAG, "Failed to mount media on insertion", ex);
                        }
                    }
                }.start();
           }
            notifyVolumeStateChange(
                    cooked[2], cooked[3], Integer.parseInt(cooked[7]),
                            Integer.parseInt(cooked[10]));
@@ -673,18 +689,11 @@ class MountService extends IMountService.Stub
            }

            if (code == VoldResponseCode.VolumeDiskInserted) {
                new Thread() {
                    public void run() {
                        try {
                            int rc;
                            if ((rc = doMountVolume(path)) != StorageResultCode.OperationSucceeded) {
                                Slog.w(TAG, String.format("Insertion mount failed (%d)", rc));
                            }
                        } catch (Exception ex) {
                            Slog.w(TAG, "Failed to mount media on insertion", ex);
                        }
                    }
                }.start();
               /* Instead of tring to mount here, wait for
                * the state to be Idle before atempting the
                * insertion mount, else "insertion mount" may fail.
                */
               insertionMountPending = true;
            } else if (code == VoldResponseCode.VolumeDiskRemoved) {
                /*
                 * This event gets trumped if we're already in BAD_REMOVAL state
@@ -1179,16 +1188,34 @@ class MountService extends IMountService.Stub
        return doGetShareMethodAvailable("ums");
    }

    private ArrayList<String> getShareableVolumes() {
        // build.prop will specify additional volumes to mount in the
        // ro.additionalmounts property.
        // This is a semicolon delimited list of paths. Such as "/emmc;/foo", etc.
        ArrayList<String> volumesToMount = new ArrayList<String>();
        volumesToMount.add(Environment.getExternalStorageDirectory().getPath());
        String additionalVolumesProperty = SystemProperties.get("ro.additionalmounts");
        if (null != additionalVolumesProperty) {
            String[] additionalVolumes = additionalVolumesProperty.split(";");
            for (String additionalVolume: additionalVolumes) {
                if (!"".equals(additionalVolume)) {
                    volumesToMount.add(additionalVolume);
                }
            }
        }
        return volumesToMount;
    }

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

        // TODO: Add support for multiple share methods
        ArrayList<String> volumesToShare = getShareableVolumes();

        for (String path: volumesToShare) {
            /*
             * 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)) {
@@ -1215,6 +1242,7 @@ class MountService extends IMountService.Stub
                }
            }
        }
    }

    public boolean isUsbMassStorageEnabled() {
        waitForReady();
@@ -1225,16 +1253,17 @@ class MountService extends IMountService.Stub
     * @return state of the volume at the specified mount point
     */
    public String getVolumeState(String mountPoint) {
        /*
         * XXX: Until we have multiple volume discovery, just hardwire
         * this to /sdcard
         */
        if (!mountPoint.equals(Environment.getExternalStorageDirectory().getPath())) {
            Slog.w(TAG, "getVolumeState(" + mountPoint + "): Unknown volume");
            throw new IllegalArgumentException();
        String volumeState = mVolumeStates.get(mountPoint);
        if (null == volumeState) {
            setVolumeState(mountPoint, Environment.MEDIA_REMOVED);
            return Environment.MEDIA_REMOVED;
        }

        return volumeState;
    }

        return mLegacyState;
    private void setVolumeState(String mountPoint, String volumeState) {
        mVolumeStates.put(mountPoint, volumeState);
    }

    public int mountVolume(String path) {