blob: 5efbd88530609ff87430960163f655e4184728ec [file] [log] [blame]
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.os.storage;
import android.content.Context;
import android.os.Environment;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.test.AndroidTestCase;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import junit.framework.Assert;
public class AsecTests extends AndroidTestCase {
private static final boolean localLOGV = true;
public static final String TAG="AsecTests";
void failStr(String errMsg) {
Log.w(TAG, "errMsg="+errMsg);
}
void failStr(Exception e) {
Log.w(TAG, "e.getMessage="+e.getMessage());
Log.w(TAG, "e="+e);
}
@Override
protected void setUp() throws Exception {
super.setUp();
if (localLOGV) Log.i(TAG, "Cleaning out old test containers");
cleanupContainers();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
if (localLOGV) Log.i(TAG, "Cleaning out old test containers");
cleanupContainers();
}
private void cleanupContainers() throws RemoteException {
IMountService ms = getMs();
String[] containers = ms.getSecureContainerList();
for (int i = 0; i < containers.length; i++) {
if (containers[i].startsWith("com.android.unittests.AsecTests.")) {
ms.destroySecureContainer(containers[i], true);
}
}
}
private boolean containerExists(String localId) throws RemoteException {
IMountService ms = getMs();
String[] containers = ms.getSecureContainerList();
String fullId = "com.android.unittests.AsecTests." + localId;
for (int i = 0; i < containers.length; i++) {
if (containers[i].equals(fullId)) {
return true;
}
}
return false;
}
private int createContainer(String localId, int size, String key) throws RemoteException {
Assert.assertTrue(isMediaMounted());
String fullId = "com.android.unittests.AsecTests." + localId;
IMountService ms = getMs();
return ms.createSecureContainer(fullId, size, "fat", key, android.os.Process.myUid());
}
private int mountContainer(String localId, String key) throws RemoteException {
Assert.assertTrue(isMediaMounted());
String fullId = "com.android.unittests.AsecTests." + localId;
IMountService ms = getMs();
return ms.mountSecureContainer(fullId, key, android.os.Process.myUid());
}
private int renameContainer(String localId1, String localId2) throws RemoteException {
Assert.assertTrue(isMediaMounted());
String fullId1 = "com.android.unittests.AsecTests." + localId1;
String fullId2 = "com.android.unittests.AsecTests." + localId2;
IMountService ms = getMs();
return ms.renameSecureContainer(fullId1, fullId2);
}
private int unmountContainer(String localId, boolean force) throws RemoteException {
Assert.assertTrue(isMediaMounted());
String fullId = "com.android.unittests.AsecTests." + localId;
IMountService ms = getMs();
return ms.unmountSecureContainer(fullId, force);
}
private int destroyContainer(String localId, boolean force) throws RemoteException {
Assert.assertTrue(isMediaMounted());
String fullId = "com.android.unittests.AsecTests." + localId;
IMountService ms = getMs();
return ms.destroySecureContainer(fullId, force);
}
private boolean isContainerMounted(String localId) throws RemoteException {
Assert.assertTrue(isMediaMounted());
String fullId = "com.android.unittests.AsecTests." + localId;
IMountService ms = getMs();
return ms.isSecureContainerMounted(fullId);
}
private IMountService getMs() {
IBinder service = ServiceManager.getService("mount");
if (service != null) {
return IMountService.Stub.asInterface(service);
} else {
Log.e(TAG, "Can't get mount service");
}
return null;
}
private boolean isMediaMounted() {
try {
String mPath = Environment.getExternalStorageDirectory().toString();
String state = getMs().getVolumeState(mPath);
return Environment.MEDIA_MOUNTED.equals(state);
} catch (RemoteException e) {
failStr(e);
return false;
}
}
public void testCreateContainer() {
try {
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testCreateContainer", 4, "none"));
Assert.assertEquals(true, containerExists("testCreateContainer"));
} catch (Exception e) {
failStr(e);
}
}
public void testCreateMinSizeContainer() {
try {
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testCreateContainer", 1, "none"));
Assert.assertEquals(true, containerExists("testCreateContainer"));
} catch (Exception e) {
failStr(e);
}
}
public void testCreateZeroSizeContainer() {
try {
Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
createContainer("testCreateZeroContainer", 0, "none"));
} catch (Exception e) {
failStr(e);
}
}
public void testCreateDuplicateContainer() {
try {
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testCreateDupContainer", 4, "none"));
Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
createContainer("testCreateDupContainer", 4, "none"));
} catch (Exception e) {
failStr(e);
}
}
public void testDestroyContainer() {
try {
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testDestroyContainer", 4, "none"));
Assert.assertEquals(StorageResultCode.OperationSucceeded,
destroyContainer("testDestroyContainer", false));
} catch (Exception e) {
failStr(e);
}
}
public void testMountContainer() {
try {
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testMountContainer", 4, "none"));
Assert.assertEquals(StorageResultCode.OperationSucceeded,
unmountContainer("testMountContainer", false));
Assert.assertEquals(StorageResultCode.OperationSucceeded,
mountContainer("testMountContainer", "none"));
} catch (Exception e) {
failStr(e);
}
}
public void testMountBadKey() {
try {
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testMountBadKey", 4, "00000000000000000000000000000000"));
Assert.assertEquals(StorageResultCode.OperationSucceeded,
unmountContainer("testMountBadKey", false));
Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
mountContainer("testMountContainer", "000000000000000000000000000000001"));
Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
mountContainer("testMountContainer", "none"));
} catch (Exception e) {
failStr(e);
}
}
public void testNonExistPath() {
IMountService ms = getMs();
try {
String path = ms.getSecureContainerPath("jparks.broke.it");
failStr(path);
} catch (IllegalArgumentException e) {
} catch (Exception e) {
failStr(e);
}
}
public void testUnmountBusyContainer() {
IMountService ms = getMs();
try {
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testUnmountBusyContainer", 4, "none"));
String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer");
File f = new File(path, "reference");
FileOutputStream fos = new FileOutputStream(f);
Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy,
unmountContainer("testUnmountBusyContainer", false));
fos.close();
Assert.assertEquals(StorageResultCode.OperationSucceeded,
unmountContainer("testUnmountBusyContainer", false));
} catch (Exception e) {
failStr(e);
}
}
public void testDestroyBusyContainer() {
IMountService ms = getMs();
try {
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testDestroyBusyContainer", 4, "none"));
String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testDestroyBusyContainer");
File f = new File(path, "reference");
FileOutputStream fos = new FileOutputStream(f);
Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy,
destroyContainer("testDestroyBusyContainer", false));
fos.close();
Assert.assertEquals(StorageResultCode.OperationSucceeded,
destroyContainer("testDestroyBusyContainer", false));
} catch (Exception e) {
failStr(e);
}
}
public void testRenameContainer() {
try {
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testRenameContainer.1", 4, "none"));
Assert.assertEquals(StorageResultCode.OperationSucceeded,
unmountContainer("testRenameContainer.1", false));
Assert.assertEquals(StorageResultCode.OperationSucceeded,
renameContainer("testRenameContainer.1", "testRenameContainer.2"));
Assert.assertEquals(false, containerExists("testRenameContainer.1"));
Assert.assertEquals(true, containerExists("testRenameContainer.2"));
} catch (Exception e) {
failStr(e);
}
}
public void testRenameSrcMountedContainer() {
try {
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testRenameContainer.1", 4, "none"));
Assert.assertEquals(StorageResultCode.OperationFailedStorageMounted,
renameContainer("testRenameContainer.1", "testRenameContainer.2"));
} catch (Exception e) {
failStr(e);
}
}
public void testRenameDstMountedContainer() {
try {
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testRenameContainer.1", 4, "none"));
Assert.assertEquals(StorageResultCode.OperationSucceeded,
unmountContainer("testRenameContainer.1", false));
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testRenameContainer.2", 4, "none"));
Assert.assertEquals(StorageResultCode.OperationFailedStorageMounted,
renameContainer("testRenameContainer.1", "testRenameContainer.2"));
} catch (Exception e) {
failStr(e);
}
}
public void testContainerSize() {
IMountService ms = getMs();
try {
Assert.assertEquals(StorageResultCode.OperationSucceeded,
createContainer("testContainerSize", 1, "none"));
String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer");
byte[] buf = new byte[4096];
File f = new File(path, "reference");
FileOutputStream fos = new FileOutputStream(f);
for (int i = 0; i < (1024 * 1024); i+= buf.length) {
fos.write(buf);
}
fos.close();
} catch (Exception e) {
failStr(e);
}
}
/*------------ Tests for unmounting volume ---*/
public final long MAX_WAIT_TIME=120*1000;
public final long WAIT_TIME_INCR=20*1000;
boolean getMediaState() {
try {
String mPath = Environment.getExternalStorageDirectory().toString();
String state = getMs().getVolumeState(mPath);
return Environment.MEDIA_MOUNTED.equals(state);
} catch (RemoteException e) {
return false;
}
}
boolean mountMedia() {
if (getMediaState()) {
return true;
}
try {
String mPath = Environment.getExternalStorageDirectory().toString();
int ret = getMs().mountVolume(mPath);
return ret == StorageResultCode.OperationSucceeded;
} catch (RemoteException e) {
return false;
}
}
class StorageListener extends StorageEventListener {
String oldState;
String newState;
String path;
private boolean doneFlag = false;
public void action() {
synchronized (this) {
doneFlag = true;
notifyAll();
}
}
public boolean isDone() {
return doneFlag;
}
@Override
public void onStorageStateChanged(String path, String oldState, String newState) {
if (localLOGV) Log.i(TAG, "Storage state changed from " + oldState + " to " + newState);
this.oldState = oldState;
this.newState = newState;
this.path = path;
action();
}
}
private boolean unmountMedia() {
if (!getMediaState()) {
return true;
}
String path = Environment.getExternalStorageDirectory().toString();
StorageListener observer = new StorageListener();
StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
sm.registerListener(observer);
try {
// Wait on observer
synchronized(observer) {
getMs().unmountVolume(path, false, false);
long waitTime = 0;
while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
observer.wait(WAIT_TIME_INCR);
waitTime += WAIT_TIME_INCR;
}
if(!observer.isDone()) {
throw new Exception("Timed out waiting for packageInstalled callback");
}
return true;
}
} catch (Exception e) {
return false;
} finally {
sm.unregisterListener(observer);
}
}
public void testUnmount() {
boolean oldStatus = getMediaState();
Log.i(TAG, "oldStatus="+oldStatus);
try {
// Mount media firsts
if (!getMediaState()) {
mountMedia();
}
assertTrue(unmountMedia());
} finally {
// Restore old status
boolean currStatus = getMediaState();
if (oldStatus != currStatus) {
if (oldStatus) {
// Mount media
mountMedia();
} else {
unmountMedia();
}
}
}
}
class MultipleStorageLis extends StorageListener {
int count = 0;
public void onStorageStateChanged(String path, String oldState, String newState) {
count++;
super.action();
}
}
/*
* This test invokes unmount multiple time and expects the call back
* to be invoked just once.
*/
public void testUnmountMultiple() {
boolean oldStatus = getMediaState();
StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
MultipleStorageLis observer = new MultipleStorageLis();
try {
// Mount media firsts
if (!getMediaState()) {
mountMedia();
}
String path = Environment.getExternalStorageDirectory().toString();
sm.registerListener(observer);
// Wait on observer
synchronized(observer) {
for (int i = 0; i < 5; i++) {
getMs().unmountVolume(path, false, false);
}
long waitTime = 0;
while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
observer.wait(WAIT_TIME_INCR);
waitTime += WAIT_TIME_INCR;
}
if(!observer.isDone()) {
failStr("Timed out waiting for packageInstalled callback");
}
}
assertEquals(observer.count, 1);
} catch (Exception e) {
failStr(e);
} finally {
sm.unregisterListener(observer);
// Restore old status
boolean currStatus = getMediaState();
if (oldStatus != currStatus) {
if (oldStatus) {
// Mount media
mountMedia();
} else {
unmountMedia();
}
}
}
}
class ShutdownObserver extends IMountShutdownObserver.Stub{
private boolean doneFlag = false;
int statusCode;
public void action() {
synchronized (this) {
doneFlag = true;
notifyAll();
}
}
public boolean isDone() {
return doneFlag;
}
public void onShutDownComplete(int statusCode) throws RemoteException {
this.statusCode = statusCode;
action();
}
}
boolean invokeShutdown() {
IMountService ms = getMs();
ShutdownObserver observer = new ShutdownObserver();
synchronized (observer) {
try {
ms.shutdown(observer);
return true;
} catch (RemoteException e) {
failStr(e);
}
}
return false;
}
public void testShutdown() {
boolean oldStatus = getMediaState();
try {
// Mount media firsts
if (!getMediaState()) {
mountMedia();
}
assertTrue(invokeShutdown());
} finally {
// Restore old status
boolean currStatus = getMediaState();
if (oldStatus != currStatus) {
if (oldStatus) {
// Mount media
mountMedia();
} else {
unmountMedia();
}
}
}
}
/*
* This test invokes unmount multiple time and expects the call back
* to be invoked just once.
*/
public void testShutdownMultiple() {
boolean oldStatus = getMediaState();
try {
// Mount media firsts
if (!getMediaState()) {
mountMedia();
}
IMountService ms = getMs();
ShutdownObserver observer = new ShutdownObserver();
synchronized (observer) {
try {
ms.shutdown(observer);
for (int i = 0; i < 4; i++) {
ms.shutdown(null);
}
} catch (RemoteException e) {
failStr(e);
}
}
} finally {
// Restore old status
boolean currStatus = getMediaState();
if (oldStatus != currStatus) {
if (oldStatus) {
// Mount media
mountMedia();
} else {
unmountMedia();
}
}
}
}
}