diff options
author | 2010-01-06 11:06:32 -0800 | |
---|---|---|
committer | 2010-01-06 13:54:41 -0800 | |
commit | 3697229cc7adfd89493e87ba8b6401c8b68bdd71 (patch) | |
tree | 4af80cf6e36951b86cf244823218864f17432c60 | |
parent | 432bff01ec67533dbbb6ed27cb190c99e83ea226 (diff) |
framework: MountService: Add initial support for Android Secure External Caches
Signed-off-by: San Mehat <san@google.com>
-rw-r--r-- | core/java/android/os/IMountService.aidl | 35 | ||||
-rw-r--r-- | media/sdutils/sdutil.cpp | 66 | ||||
-rw-r--r-- | services/java/com/android/server/MountListener.java | 91 | ||||
-rw-r--r-- | services/java/com/android/server/MountService.java | 56 |
4 files changed, 220 insertions, 28 deletions
diff --git a/core/java/android/os/IMountService.aidl b/core/java/android/os/IMountService.aidl index 447e764db6d2..1ea720090123 100644 --- a/core/java/android/os/IMountService.aidl +++ b/core/java/android/os/IMountService.aidl @@ -80,4 +80,39 @@ interface IMountService * Gets the state of an volume via it's mountpoint. */ String getVolumeState(String mountPoint); + + /* + * Creates a secure cache with the specified parameters. + * On success, the filesystem cache-path is returned. + */ + String createSecureCache(String id, int sizeMb, String fstype, String key, int ownerUid); + + /* + * Finalize a cache which has just been created and populated. + * After finalization, the cache is immutable. + */ + void finalizeSecureCache(String id); + + /* + * Destroy a secure cache, and free up all resources associated with it. + * NOTE: Ensure all references are released prior to deleting. + */ + void destroySecureCache(String id); + + /* + * Mount a secure cache with the specified key and owner UID. + * On success, the filesystem cache-path is returned. + */ + String mountSecureCache(String id, String key, int ownerUid); + + /* + * Returns the filesystem path of a mounted secure cache. + */ + String getSecureCachePath(String id); + + /** + * Gets an Array of currently known secure cache IDs + */ + String[] getSecureCacheList(); + } diff --git a/media/sdutils/sdutil.cpp b/media/sdutils/sdutil.cpp index fe1187897126..7f0dda7a9b70 100644 --- a/media/sdutils/sdutil.cpp +++ b/media/sdutils/sdutil.cpp @@ -99,6 +99,42 @@ static int mount(const char* path) { return -1; } +static int asec_create(const char *id, int sizeMb, const char *fstype, + const char *key, int ownerUid) { + String16 sId(id); + String16 sFstype(fstype); + String16 sKey(key); + + String16 r = gMountService->createSecureCache(sId, sizeMb, sFstype, + sKey, ownerUid); + return 0; +} + +static int asec_finalize(const char *id) { + String16 sId(id); + gMountService->finalizeSecureCache(sId); + return 0; +} + +static int asec_destroy(const char *id) { + String16 sId(id); + gMountService->destroySecureCache(sId); + return 0; +} + +static int asec_mount(const char *id, const char *key, int ownerUid) { + String16 sId(id); + String16 sKey(key); + gMountService->mountSecureCache(sId, sKey, ownerUid); + return 0; +} + +static int asec_path(const char *id) { + String16 sId(id); + gMountService->getSecureCachePath(sId); + return 0; +} + static int unmount(const char* path) { String16 string(path); gMountService->unmountMedia(string); @@ -153,14 +189,42 @@ int main(int argc, char **argv) android::init(); return android::umsEnable(false); } + } else if (!strcmp(command, "asec")) { + const char* id = (argc > 3 ? argv[3] : NULL); + + if (!id) + goto usage; + + android::init(); + if (!strcmp(argument, "create")) { + + if (argc != 8) + goto usage; + return android::asec_create(id, atoi(argv[4]), argv[5], argv[6], + atoi(argv[7])); + } else if (!strcmp(argument, "finalize")) { + return android::asec_finalize(id); + } else if (!strcmp(argument, "destroy")) { + return android::asec_destroy(id); + } else if (!strcmp(argument, "mount")) { + return android::asec_mount(id, argv[4], atoi(argv[5])); + } else if (!strcmp(argument, "path")) { + return android::asec_path(id); + } } +usage: fprintf(stderr, "usage:\n" " sdutil mount <mount path> - mounts the SD card at the given mount point\n" " sdutil unmount <mount path> - unmounts the SD card at the given mount point\n" " sdutil format <mount path> - formats the SD card at the given mount point\n" " sdutil ums enable - enables USB mass storage\n" - " sdutil ums disable - disnables USB mass storage\n" + " sdutil ums disable - disables USB mass storage\n" + " sdutil asec create <id> <sizeMb> <fstype> <key> <ownerUid>\n" + " sdutil asec finalize <id>\n" + " sdutil asec destroy <id>\n" + " sdutil asec mount <id> <key> <ownerUid>\n" + " sdutil asec path <id>\n" ); return -1; } diff --git a/services/java/com/android/server/MountListener.java b/services/java/com/android/server/MountListener.java index d4943ffcc7df..5a1107b89559 100644 --- a/services/java/com/android/server/MountListener.java +++ b/services/java/com/android/server/MountListener.java @@ -21,7 +21,6 @@ import android.net.LocalSocket; import android.os.Environment; import android.os.SystemClock; import android.os.SystemProperties; -import android.os.RemoteException; import android.util.Config; import android.util.Log; @@ -29,6 +28,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; +import java.lang.IllegalStateException; import java.util.List; import java.util.ArrayList; @@ -49,7 +49,13 @@ final class MountListener implements Runnable { private OutputStream mOutputStream; class ResponseCode { + public static final int ActionInitiated = 100; + public static final int VolumeListResult = 110; + public static final int AsecListResult = 111; + + public static final int CommandOkay = 200; public static final int ShareAvailabilityResult = 210; + public static final int AsecPathResult = 211; public static final int UnsolicitedInformational = 600; public static final int VolumeStateChange = 605; @@ -163,7 +169,8 @@ final class MountListener implements Runnable { SystemClock.sleep(5000); } - private void handleUnsolicitedEvent(int code, String raw, String[] cooked) throws RemoteException { + private void handleUnsolicitedEvent(int code, String raw, + String[] cooked) throws IllegalStateException { // Log.d(TAG, "unsolicited {" + raw + "}"); if (code == ResponseCode.VolumeStateChange) { // FMT: NNN Volume <label> <mountpoint> state changed from <old_#> (<old_str>) to <new_#> (<new_str>) @@ -232,7 +239,7 @@ final class MountListener implements Runnable { } } - private synchronized ArrayList<String> doCommand(String cmd) throws RemoteException { + private synchronized ArrayList<String> doCommand(String cmd) throws IllegalStateException { sendCommand(cmd); ArrayList<String> response = new ArrayList<String>(); @@ -255,13 +262,14 @@ final class MountListener implements Runnable { } if (code >= 400 && code < 600) { - Log.w(TAG, "Vold cmd {" + cmd + "} err code " + code); - throw new RemoteException(); + throw new IllegalStateException(String.format( + "Command %s failed with code %d", + cmd, code)); } return response; } - boolean getShareAvailable(String method) throws RemoteException { + boolean getShareAvailable(String method) throws IllegalStateException { ArrayList<String> rsp = doCommand("share_available " + method); for (String line : rsp) { @@ -272,10 +280,10 @@ final class MountListener implements Runnable { return true; return false; } else { - throw new RemoteException(); + throw new IllegalStateException(String.format("Unexpected response code %d", code)); } } - throw new RemoteException(); + throw new IllegalStateException("Got an empty response"); } /** @@ -283,28 +291,87 @@ final class MountListener implements Runnable { * * @param enable true to enable USB mass storage support */ - void setShareMethodEnabled(String mountPoint, String method, boolean enable) throws RemoteException { + void setShareMethodEnabled(String mountPoint, String method, + boolean enable) throws IllegalStateException { doCommand((enable ? "" : "un") + "share " + mountPoint + " " + method); } /** * Mount media at given mount point. */ - public void mountVolume(String label) throws RemoteException { + public void mountVolume(String label) throws IllegalStateException { doCommand("mount " + label); } /** * Unmount media at given mount point. */ - public void unmountVolume(String label) throws RemoteException { + public void unmountVolume(String label) throws IllegalStateException { doCommand("unmount " + label); } /** * Format media at given mount point. */ - public void formatVolume(String label) throws RemoteException { + public void formatVolume(String label) throws IllegalStateException { doCommand("format " + label); } + + public String createAsec(String id, int sizeMb, String fstype, String key, + int ownerUid) throws IllegalStateException { + String cmd = String.format("create_asec %s %d %s %s %d", + id, sizeMb, fstype, key, ownerUid); + doCommand(cmd); + return getAsecPath(id); + } + + public void finalizeAsec(String id) throws IllegalStateException { + doCommand("finalize_asec " + id); + } + + public void destroyAsec(String id) throws IllegalStateException { + doCommand("destroy_asec " + id); + } + + public String mountAsec(String id, String key, int ownerUid) throws IllegalStateException { + String cmd = String.format("mount_asec %s %s %d", + id, key, ownerUid); + doCommand(cmd); + return getAsecPath(id); + } + + public String getAsecPath(String id) throws IllegalStateException { + ArrayList<String> rsp = doCommand("asec_path " + id); + + for (String line : rsp) { + String []tok = line.split(" "); + int code = Integer.parseInt(tok[0]); + if (code == ResponseCode.AsecPathResult) { + return tok[1]; + } else { + throw new IllegalStateException(String.format("Unexpected response code %d", code)); + } + } + throw new IllegalStateException("Got an empty response"); + } + + public String[] listAsec() throws IllegalStateException { + ArrayList<String> rsp = doCommand("list_asec"); + + String[] rdata = new String[rsp.size()]; + int idx = 0; + + for (String line : rsp) { + String []tok = line.split(" "); + int code = Integer.parseInt(tok[0]); + if (code == ResponseCode.AsecPathResult) { + rdata[idx++] = tok[1]; + } else if (code == ResponseCode.CommandOkay) { + return rdata; + } else { + throw new IllegalStateException(String.format("Unexpected response code %d", code)); + } + } + throw new IllegalStateException("Got an empty response"); + } } diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index 93617d1eee7d..1b0b0eb72ffc 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -28,7 +28,6 @@ import android.content.res.Resources; import android.net.Uri; import android.os.IMountService; import android.os.Environment; -import android.os.RemoteException; import android.os.SystemProperties; import android.os.UEventObserver; import android.text.TextUtils; @@ -36,6 +35,7 @@ import android.util.Log; import java.io.File; import java.io.FileReader; +import java.lang.IllegalStateException; /** * MountService implements an to the mount service daemon @@ -136,7 +136,7 @@ class MountService extends IMountService.Stub { /** * @return true if USB mass storage support is enabled. */ - public boolean getMassStorageEnabled() throws RemoteException { + public boolean getMassStorageEnabled() { return mUmsEnabled; } @@ -145,7 +145,7 @@ class MountService extends IMountService.Stub { * * @param enable true to enable USB mass storage support */ - public void setMassStorageEnabled(boolean enable) throws RemoteException { + public void setMassStorageEnabled(boolean enable) throws IllegalStateException { try { String vp = Environment.getExternalStorageDirectory().getPath(); String vs = getVolumeState(vp); @@ -164,7 +164,7 @@ class MountService extends IMountService.Stub { Log.d(TAG, "Mounting media after UMS disable"); mountMedia(vp); } - } catch (RemoteException rex) { + } catch (IllegalStateException rex) { Log.e(TAG, "Failed to set ums enable {" + enable + "}"); return; } @@ -173,14 +173,14 @@ class MountService extends IMountService.Stub { /** * @return true if USB mass storage is connected. */ - public boolean getMassStorageConnected() throws RemoteException { + public boolean getMassStorageConnected() { return mUmsConnected; } /** * @return state of the volume at the specified mount point */ - public String getVolumeState(String mountPoint) throws RemoteException { + public String getVolumeState(String mountPoint) throws IllegalStateException { /* * XXX: Until we have multiple volume discovery, just hardwire * this to /sdcard @@ -197,7 +197,7 @@ class MountService extends IMountService.Stub { /** * Attempt to mount external media */ - public void mountMedia(String mountPath) throws RemoteException { + public void mountMedia(String mountPath) throws IllegalStateException { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS) != PackageManager.PERMISSION_GRANTED) { @@ -209,7 +209,7 @@ class MountService extends IMountService.Stub { /** * Attempt to unmount external media to prepare for eject */ - public void unmountMedia(String mountPath) throws RemoteException { + public void unmountMedia(String mountPath) throws IllegalStateException { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS) != PackageManager.PERMISSION_GRANTED) { @@ -227,7 +227,7 @@ class MountService extends IMountService.Stub { /** * Attempt to format external media */ - public void formatMedia(String formatPath) throws RemoteException { + public void formatMedia(String formatPath) throws IllegalStateException { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS) != PackageManager.PERMISSION_GRANTED) { @@ -306,7 +306,7 @@ class MountService extends IMountService.Stub { } else { setUsbStorageNotification(0, 0, 0, false, false, null); } - } catch (RemoteException e) { + } catch (IllegalStateException e) { // Nothing to do } } @@ -335,7 +335,7 @@ class MountService extends IMountService.Stub { } else { Log.d(TAG, "Skipping connection-mount; already mounted"); } - } catch (RemoteException rex) { + } catch (IllegalStateException rex) { Log.e(TAG, "Exception while handling connection mount " + rex); } @@ -350,7 +350,7 @@ class MountService extends IMountService.Stub { } void notifyVolumeStateChange(String label, String mountPoint, int oldState, - int newState) throws RemoteException { + int newState) throws IllegalStateException { String vs = getVolumeState(mountPoint); if (newState == VolumeState.Init) { @@ -395,7 +395,7 @@ class MountService extends IMountService.Stub { if (mAutoStartUms) { try { setMassStorageEnabled(true); - } catch (RemoteException e) { + } catch (IllegalStateException e) { } } else { updateUsbMassStorageNotification(false, true); @@ -429,7 +429,7 @@ class MountService extends IMountService.Stub { mContext.sendBroadcast(intent); } - void notifyMediaInserted(final String path) throws RemoteException { + void notifyMediaInserted(final String path) throws IllegalStateException { new Thread() { public void run() { try { @@ -445,7 +445,7 @@ class MountService extends IMountService.Stub { /** * Broadcasts the media removed event to all clients. */ - void notifyMediaRemoved(String path) throws RemoteException { + void notifyMediaRemoved(String path) throws IllegalStateException { // Suppress this on bad removal if (getVolumeState(path).equals(Environment.MEDIA_BAD_REMOVAL)) { @@ -755,5 +755,31 @@ class MountService extends IMountService.Stub { notificationManager.cancel(notificationId); } } + + public String[] getSecureCacheList() throws IllegalStateException { + return mListener.listAsec(); + } + + public String createSecureCache(String id, int sizeMb, String fstype, + String key, int ownerUid) throws IllegalStateException { + return mListener.createAsec(id, sizeMb, fstype, key, ownerUid); + } + + public void finalizeSecureCache(String id) throws IllegalStateException { + mListener.finalizeAsec(id); + } + + public void destroySecureCache(String id) throws IllegalStateException { + mListener.destroyAsec(id); + } + + public String mountSecureCache(String id, String key, int ownerUid) throws IllegalStateException { + return mListener.mountAsec(id, key, ownerUid); + } + + public String getSecureCachePath(String id) throws IllegalStateException { + return mListener.getAsecPath(id); + } + } |