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

Commit 93bb9592 authored by Koushik Dutta's avatar Koushik Dutta
Browse files

Add support for mounting and sharing of multiple volumes to MountService.

parent 5722ad7b
Loading
Loading
Loading
Loading
+104 −88
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Slog;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

/**
@@ -114,7 +115,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.
@@ -305,8 +306,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)) {
@@ -334,6 +337,7 @@ class MountService extends IMountService.Stub
                                Slog.e(TAG, "Boot-time mount exception", ex);
                            }
                        }
                    }
                }.start();
            }
        }
@@ -371,13 +375,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;
        }
        // Update state on PackageManager
@@ -386,8 +386,8 @@ class MountService extends IMountService.Stub
        } else if (Environment.MEDIA_MOUNTED.equals(state)) {
            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--) {
@@ -418,20 +418,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;
@@ -446,14 +441,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 {
@@ -580,6 +575,7 @@ class MountService extends IMountService.Stub
    private void notifyVolumeStateChange(String label, String path, int oldState, int newState) {
        String vs = getVolumeState(path);
        if (DEBUG_EVENTS) Slog.i(TAG, "notifyVolumeStateChanged::" + vs);
        Slog.i(TAG, String.format("notifyVolumeStateChange %s %s %s %s", label, path, oldState, newState));

        Intent in = null;

@@ -982,16 +978,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)) {
@@ -1018,6 +1032,7 @@ class MountService extends IMountService.Stub
                }
            }
        }
    }

    public boolean isUsbMassStorageEnabled() {
        waitForReady();
@@ -1028,16 +1043,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) {