AsecTests.java revision 13c7197da8a16f77f6398708a6314c80cb01e0d1
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.os.storage; 18 19import android.content.Context; 20import android.os.Environment; 21import android.os.IBinder; 22import android.os.RemoteException; 23import android.os.ServiceManager; 24import android.test.AndroidTestCase; 25import android.util.Log; 26 27import java.io.File; 28import java.io.FileOutputStream; 29 30import junit.framework.Assert; 31 32public class AsecTests extends AndroidTestCase { 33 private static final boolean localLOGV = true; 34 public static final String TAG="AsecTests"; 35 36 void failStr(String errMsg) { 37 Log.w(TAG, "errMsg="+errMsg); 38 } 39 40 void failStr(Exception e) { 41 Log.w(TAG, "e.getMessage="+e.getMessage()); 42 Log.w(TAG, "e="+e); 43 } 44 45 @Override 46 protected void setUp() throws Exception { 47 super.setUp(); 48 if (localLOGV) Log.i(TAG, "Cleaning out old test containers"); 49 cleanupContainers(); 50 } 51 52 @Override 53 protected void tearDown() throws Exception { 54 super.tearDown(); 55 if (localLOGV) Log.i(TAG, "Cleaning out old test containers"); 56 cleanupContainers(); 57 } 58 59 private void cleanupContainers() throws RemoteException { 60 IMountService ms = getMs(); 61 String[] containers = ms.getSecureContainerList(); 62 63 for (int i = 0; i < containers.length; i++) { 64 if (containers[i].startsWith("com.android.unittests.AsecTests.")) { 65 ms.destroySecureContainer(containers[i], true); 66 } 67 } 68 } 69 70 private boolean containerExists(String localId) throws RemoteException { 71 IMountService ms = getMs(); 72 String[] containers = ms.getSecureContainerList(); 73 String fullId = "com.android.unittests.AsecTests." + localId; 74 75 for (int i = 0; i < containers.length; i++) { 76 if (containers[i].equals(fullId)) { 77 return true; 78 } 79 } 80 return false; 81 } 82 83 private int createContainer(String localId, int size, String key) throws RemoteException { 84 Assert.assertTrue(isMediaMounted()); 85 String fullId = "com.android.unittests.AsecTests." + localId; 86 87 IMountService ms = getMs(); 88 return ms.createSecureContainer(fullId, size, "fat", key, android.os.Process.myUid()); 89 } 90 91 private int mountContainer(String localId, String key) throws RemoteException { 92 Assert.assertTrue(isMediaMounted()); 93 String fullId = "com.android.unittests.AsecTests." + localId; 94 95 IMountService ms = getMs(); 96 return ms.mountSecureContainer(fullId, key, android.os.Process.myUid()); 97 } 98 99 private int renameContainer(String localId1, String localId2) throws RemoteException { 100 Assert.assertTrue(isMediaMounted()); 101 String fullId1 = "com.android.unittests.AsecTests." + localId1; 102 String fullId2 = "com.android.unittests.AsecTests." + localId2; 103 104 IMountService ms = getMs(); 105 return ms.renameSecureContainer(fullId1, fullId2); 106 } 107 108 private int unmountContainer(String localId, boolean force) throws RemoteException { 109 Assert.assertTrue(isMediaMounted()); 110 String fullId = "com.android.unittests.AsecTests." + localId; 111 112 IMountService ms = getMs(); 113 return ms.unmountSecureContainer(fullId, force); 114 } 115 116 private int destroyContainer(String localId, boolean force) throws RemoteException { 117 Assert.assertTrue(isMediaMounted()); 118 String fullId = "com.android.unittests.AsecTests." + localId; 119 120 IMountService ms = getMs(); 121 return ms.destroySecureContainer(fullId, force); 122 } 123 124 private boolean isContainerMounted(String localId) throws RemoteException { 125 Assert.assertTrue(isMediaMounted()); 126 String fullId = "com.android.unittests.AsecTests." + localId; 127 128 IMountService ms = getMs(); 129 return ms.isSecureContainerMounted(fullId); 130 } 131 132 private IMountService getMs() { 133 IBinder service = ServiceManager.getService("mount"); 134 if (service != null) { 135 return IMountService.Stub.asInterface(service); 136 } else { 137 Log.e(TAG, "Can't get mount service"); 138 } 139 return null; 140 } 141 142 private boolean isMediaMounted() { 143 try { 144 String mPath = Environment.getExternalStorageDirectory().toString(); 145 String state = getMs().getVolumeState(mPath); 146 return Environment.MEDIA_MOUNTED.equals(state); 147 } catch (RemoteException e) { 148 failStr(e); 149 return false; 150 } 151 } 152 153 public void testCreateContainer() { 154 try { 155 Assert.assertEquals(StorageResultCode.OperationSucceeded, 156 createContainer("testCreateContainer", 4, "none")); 157 Assert.assertEquals(true, containerExists("testCreateContainer")); 158 } catch (Exception e) { 159 failStr(e); 160 } 161 } 162 163 public void testCreateMinSizeContainer() { 164 try { 165 Assert.assertEquals(StorageResultCode.OperationSucceeded, 166 createContainer("testCreateContainer", 1, "none")); 167 Assert.assertEquals(true, containerExists("testCreateContainer")); 168 } catch (Exception e) { 169 failStr(e); 170 } 171 } 172 173 public void testCreateZeroSizeContainer() { 174 try { 175 Assert.assertEquals(StorageResultCode.OperationFailedInternalError, 176 createContainer("testCreateZeroContainer", 0, "none")); 177 } catch (Exception e) { 178 failStr(e); 179 } 180 } 181 182 public void testCreateDuplicateContainer() { 183 try { 184 Assert.assertEquals(StorageResultCode.OperationSucceeded, 185 createContainer("testCreateDupContainer", 4, "none")); 186 187 Assert.assertEquals(StorageResultCode.OperationFailedInternalError, 188 createContainer("testCreateDupContainer", 4, "none")); 189 } catch (Exception e) { 190 failStr(e); 191 } 192 } 193 194 public void testDestroyContainer() { 195 try { 196 Assert.assertEquals(StorageResultCode.OperationSucceeded, 197 createContainer("testDestroyContainer", 4, "none")); 198 Assert.assertEquals(StorageResultCode.OperationSucceeded, 199 destroyContainer("testDestroyContainer", false)); 200 } catch (Exception e) { 201 failStr(e); 202 } 203 } 204 205 public void testMountContainer() { 206 try { 207 Assert.assertEquals(StorageResultCode.OperationSucceeded, 208 createContainer("testMountContainer", 4, "none")); 209 210 Assert.assertEquals(StorageResultCode.OperationSucceeded, 211 unmountContainer("testMountContainer", false)); 212 213 Assert.assertEquals(StorageResultCode.OperationSucceeded, 214 mountContainer("testMountContainer", "none")); 215 } catch (Exception e) { 216 failStr(e); 217 } 218 } 219 220 public void testMountBadKey() { 221 try { 222 Assert.assertEquals(StorageResultCode.OperationSucceeded, 223 createContainer("testMountBadKey", 4, "00000000000000000000000000000000")); 224 225 Assert.assertEquals(StorageResultCode.OperationSucceeded, 226 unmountContainer("testMountBadKey", false)); 227 228 Assert.assertEquals(StorageResultCode.OperationFailedInternalError, 229 mountContainer("testMountContainer", "000000000000000000000000000000001")); 230 231 Assert.assertEquals(StorageResultCode.OperationFailedInternalError, 232 mountContainer("testMountContainer", "none")); 233 } catch (Exception e) { 234 failStr(e); 235 } 236 } 237 238 public void testNonExistPath() { 239 IMountService ms = getMs(); 240 try { 241 String path = ms.getSecureContainerPath("jparks.broke.it"); 242 failStr(path); 243 } catch (IllegalArgumentException e) { 244 } catch (Exception e) { 245 failStr(e); 246 } 247 } 248 249 public void testUnmountBusyContainer() { 250 IMountService ms = getMs(); 251 try { 252 Assert.assertEquals(StorageResultCode.OperationSucceeded, 253 createContainer("testUnmountBusyContainer", 4, "none")); 254 255 String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer"); 256 257 File f = new File(path, "reference"); 258 FileOutputStream fos = new FileOutputStream(f); 259 260 Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy, 261 unmountContainer("testUnmountBusyContainer", false)); 262 263 fos.close(); 264 Assert.assertEquals(StorageResultCode.OperationSucceeded, 265 unmountContainer("testUnmountBusyContainer", false)); 266 } catch (Exception e) { 267 failStr(e); 268 } 269 } 270 271 public void testDestroyBusyContainer() { 272 IMountService ms = getMs(); 273 try { 274 Assert.assertEquals(StorageResultCode.OperationSucceeded, 275 createContainer("testDestroyBusyContainer", 4, "none")); 276 277 String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testDestroyBusyContainer"); 278 279 File f = new File(path, "reference"); 280 FileOutputStream fos = new FileOutputStream(f); 281 282 Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy, 283 destroyContainer("testDestroyBusyContainer", false)); 284 285 fos.close(); 286 Assert.assertEquals(StorageResultCode.OperationSucceeded, 287 destroyContainer("testDestroyBusyContainer", false)); 288 } catch (Exception e) { 289 failStr(e); 290 } 291 } 292 293 public void testRenameContainer() { 294 try { 295 Assert.assertEquals(StorageResultCode.OperationSucceeded, 296 createContainer("testRenameContainer.1", 4, "none")); 297 298 Assert.assertEquals(StorageResultCode.OperationSucceeded, 299 unmountContainer("testRenameContainer.1", false)); 300 301 Assert.assertEquals(StorageResultCode.OperationSucceeded, 302 renameContainer("testRenameContainer.1", "testRenameContainer.2")); 303 304 Assert.assertEquals(false, containerExists("testRenameContainer.1")); 305 Assert.assertEquals(true, containerExists("testRenameContainer.2")); 306 } catch (Exception e) { 307 failStr(e); 308 } 309 } 310 311 public void testRenameSrcMountedContainer() { 312 try { 313 Assert.assertEquals(StorageResultCode.OperationSucceeded, 314 createContainer("testRenameContainer.1", 4, "none")); 315 316 Assert.assertEquals(StorageResultCode.OperationFailedStorageMounted, 317 renameContainer("testRenameContainer.1", "testRenameContainer.2")); 318 } catch (Exception e) { 319 failStr(e); 320 } 321 } 322 323 public void testRenameDstMountedContainer() { 324 try { 325 Assert.assertEquals(StorageResultCode.OperationSucceeded, 326 createContainer("testRenameContainer.1", 4, "none")); 327 328 Assert.assertEquals(StorageResultCode.OperationSucceeded, 329 unmountContainer("testRenameContainer.1", false)); 330 331 Assert.assertEquals(StorageResultCode.OperationSucceeded, 332 createContainer("testRenameContainer.2", 4, "none")); 333 334 Assert.assertEquals(StorageResultCode.OperationFailedStorageMounted, 335 renameContainer("testRenameContainer.1", "testRenameContainer.2")); 336 } catch (Exception e) { 337 failStr(e); 338 } 339 } 340 341 public void testContainerSize() { 342 IMountService ms = getMs(); 343 try { 344 Assert.assertEquals(StorageResultCode.OperationSucceeded, 345 createContainer("testContainerSize", 1, "none")); 346 String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer"); 347 348 byte[] buf = new byte[4096]; 349 File f = new File(path, "reference"); 350 FileOutputStream fos = new FileOutputStream(f); 351 for (int i = 0; i < (1024 * 1024); i+= buf.length) { 352 fos.write(buf); 353 } 354 fos.close(); 355 } catch (Exception e) { 356 failStr(e); 357 } 358 } 359 360 /*------------ Tests for unmounting volume ---*/ 361 public final long MAX_WAIT_TIME=120*1000; 362 public final long WAIT_TIME_INCR=20*1000; 363 boolean getMediaState() { 364 try { 365 String mPath = Environment.getExternalStorageDirectory().toString(); 366 String state = getMs().getVolumeState(mPath); 367 return Environment.MEDIA_MOUNTED.equals(state); 368 } catch (RemoteException e) { 369 return false; 370 } 371 } 372 373 boolean mountMedia() { 374 if (getMediaState()) { 375 return true; 376 } 377 try { 378 String mPath = Environment.getExternalStorageDirectory().toString(); 379 int ret = getMs().mountVolume(mPath); 380 return ret == StorageResultCode.OperationSucceeded; 381 } catch (RemoteException e) { 382 return false; 383 } 384 } 385 386 class StorageListener extends StorageEventListener { 387 String oldState; 388 String newState; 389 String path; 390 private boolean doneFlag = false; 391 392 public void action() { 393 synchronized (this) { 394 doneFlag = true; 395 notifyAll(); 396 } 397 } 398 399 public boolean isDone() { 400 return doneFlag; 401 } 402 403 @Override 404 public void onStorageStateChanged(String path, String oldState, String newState) { 405 if (localLOGV) Log.i(TAG, "Storage state changed from " + oldState + " to " + newState); 406 this.oldState = oldState; 407 this.newState = newState; 408 this.path = path; 409 action(); 410 } 411 } 412 413 private boolean unmountMedia() { 414 if (!getMediaState()) { 415 return true; 416 } 417 String path = Environment.getExternalStorageDirectory().toString(); 418 StorageListener observer = new StorageListener(); 419 StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE); 420 sm.registerListener(observer); 421 try { 422 // Wait on observer 423 synchronized(observer) { 424 getMs().unmountVolume(path, false, false); 425 long waitTime = 0; 426 while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) { 427 observer.wait(WAIT_TIME_INCR); 428 waitTime += WAIT_TIME_INCR; 429 } 430 if(!observer.isDone()) { 431 throw new Exception("Timed out waiting for packageInstalled callback"); 432 } 433 return true; 434 } 435 } catch (Exception e) { 436 return false; 437 } finally { 438 sm.unregisterListener(observer); 439 } 440 } 441 public void testUnmount() { 442 boolean oldStatus = getMediaState(); 443 Log.i(TAG, "oldStatus="+oldStatus); 444 try { 445 // Mount media firsts 446 if (!getMediaState()) { 447 mountMedia(); 448 } 449 assertTrue(unmountMedia()); 450 } finally { 451 // Restore old status 452 boolean currStatus = getMediaState(); 453 if (oldStatus != currStatus) { 454 if (oldStatus) { 455 // Mount media 456 mountMedia(); 457 } else { 458 unmountMedia(); 459 } 460 } 461 } 462 } 463 464 class MultipleStorageLis extends StorageListener { 465 int count = 0; 466 public void onStorageStateChanged(String path, String oldState, String newState) { 467 count++; 468 super.action(); 469 } 470 } 471 /* 472 * This test invokes unmount multiple time and expects the call back 473 * to be invoked just once. 474 */ 475 public void testUnmountMultiple() { 476 boolean oldStatus = getMediaState(); 477 StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE); 478 MultipleStorageLis observer = new MultipleStorageLis(); 479 try { 480 // Mount media firsts 481 if (!getMediaState()) { 482 mountMedia(); 483 } 484 String path = Environment.getExternalStorageDirectory().toString(); 485 sm.registerListener(observer); 486 // Wait on observer 487 synchronized(observer) { 488 for (int i = 0; i < 5; i++) { 489 getMs().unmountVolume(path, false, false); 490 } 491 long waitTime = 0; 492 while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) { 493 observer.wait(WAIT_TIME_INCR); 494 waitTime += WAIT_TIME_INCR; 495 } 496 if(!observer.isDone()) { 497 failStr("Timed out waiting for packageInstalled callback"); 498 } 499 } 500 assertEquals(observer.count, 1); 501 } catch (Exception e) { 502 failStr(e); 503 } finally { 504 sm.unregisterListener(observer); 505 // Restore old status 506 boolean currStatus = getMediaState(); 507 if (oldStatus != currStatus) { 508 if (oldStatus) { 509 // Mount media 510 mountMedia(); 511 } else { 512 unmountMedia(); 513 } 514 } 515 } 516 } 517 518 class ShutdownObserver extends IMountShutdownObserver.Stub{ 519 private boolean doneFlag = false; 520 int statusCode; 521 522 public void action() { 523 synchronized (this) { 524 doneFlag = true; 525 notifyAll(); 526 } 527 } 528 529 public boolean isDone() { 530 return doneFlag; 531 } 532 public void onShutDownComplete(int statusCode) throws RemoteException { 533 this.statusCode = statusCode; 534 action(); 535 } 536 537 } 538 539 boolean invokeShutdown() { 540 IMountService ms = getMs(); 541 ShutdownObserver observer = new ShutdownObserver(); 542 synchronized (observer) { 543 try { 544 ms.shutdown(observer); 545 return true; 546 } catch (RemoteException e) { 547 failStr(e); 548 } 549 } 550 return false; 551 } 552 553 public void testShutdown() { 554 boolean oldStatus = getMediaState(); 555 try { 556 // Mount media firsts 557 if (!getMediaState()) { 558 mountMedia(); 559 } 560 assertTrue(invokeShutdown()); 561 } finally { 562 // Restore old status 563 boolean currStatus = getMediaState(); 564 if (oldStatus != currStatus) { 565 if (oldStatus) { 566 // Mount media 567 mountMedia(); 568 } else { 569 unmountMedia(); 570 } 571 } 572 } 573 } 574 575 /* 576 * This test invokes unmount multiple time and expects the call back 577 * to be invoked just once. 578 */ 579 public void testShutdownMultiple() { 580 boolean oldStatus = getMediaState(); 581 try { 582 // Mount media firsts 583 if (!getMediaState()) { 584 mountMedia(); 585 } 586 IMountService ms = getMs(); 587 ShutdownObserver observer = new ShutdownObserver(); 588 synchronized (observer) { 589 try { 590 ms.shutdown(observer); 591 for (int i = 0; i < 4; i++) { 592 ms.shutdown(null); 593 } 594 } catch (RemoteException e) { 595 failStr(e); 596 } 597 } 598 } finally { 599 // Restore old status 600 boolean currStatus = getMediaState(); 601 if (oldStatus != currStatus) { 602 if (oldStatus) { 603 // Mount media 604 mountMedia(); 605 } else { 606 unmountMedia(); 607 } 608 } 609 } 610 } 611 612} 613