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 30public class AsecTests extends AndroidTestCase { 31 private static final String SECURE_CONTAINER_PREFIX = "com.android.unittests.AsecTests."; 32 private static final boolean localLOGV = true; 33 public static final String TAG="AsecTests"; 34 35 private static final String FS_FAT = "fat"; 36 private static final String FS_EXT4 = "ext4"; 37 38 @Override 39 protected void setUp() throws Exception { 40 super.setUp(); 41 if (localLOGV) Log.i(TAG, "Cleaning out old test containers"); 42 cleanupContainers(); 43 } 44 45 @Override 46 protected void tearDown() throws Exception { 47 super.tearDown(); 48 if (localLOGV) Log.i(TAG, "Cleaning out old test containers"); 49 cleanupContainers(); 50 } 51 52 private void cleanupContainers() throws RemoteException { 53 IMountService ms = getMs(); 54 String[] containers = ms.getSecureContainerList(); 55 56 for (int i = 0; i < containers.length; i++) { 57 if (containers[i].startsWith(SECURE_CONTAINER_PREFIX)) { 58 if (localLOGV) 59 Log.i(TAG, "Cleaning: " + containers[i]); 60 ms.destroySecureContainer(containers[i], true); 61 } 62 } 63 } 64 65 private boolean containerExists(String localId) throws RemoteException { 66 IMountService ms = getMs(); 67 String[] containers = ms.getSecureContainerList(); 68 String fullId = SECURE_CONTAINER_PREFIX + localId; 69 70 for (int i = 0; i < containers.length; i++) { 71 if (containers[i].equals(fullId)) { 72 return true; 73 } 74 } 75 return false; 76 } 77 78 private int createContainer(String localId, int size, String key, String filesystem, 79 boolean isExternal) throws Exception { 80 assertTrue("Media should be mounted", isMediaMounted()); 81 String fullId = SECURE_CONTAINER_PREFIX + localId; 82 83 IMountService ms = getMs(); 84 return ms.createSecureContainer(fullId, size, filesystem, key, android.os.Process.myUid(), 85 isExternal); 86 } 87 88 private int mountContainer(String localId, String key) throws Exception { 89 assertTrue("Media should be mounted", isMediaMounted()); 90 String fullId = SECURE_CONTAINER_PREFIX + localId; 91 92 IMountService ms = getMs(); 93 return ms.mountSecureContainer(fullId, key, android.os.Process.myUid(), true); 94 } 95 96 private int renameContainer(String localId1, String localId2) throws Exception { 97 assertTrue("Media should be mounted", isMediaMounted()); 98 String fullId1 = SECURE_CONTAINER_PREFIX + localId1; 99 String fullId2 = SECURE_CONTAINER_PREFIX + localId2; 100 101 IMountService ms = getMs(); 102 return ms.renameSecureContainer(fullId1, fullId2); 103 } 104 105 private int unmountContainer(String localId, boolean force) throws Exception { 106 assertTrue("Media should be mounted", isMediaMounted()); 107 String fullId = SECURE_CONTAINER_PREFIX + localId; 108 109 IMountService ms = getMs(); 110 return ms.unmountSecureContainer(fullId, force); 111 } 112 113 private int destroyContainer(String localId, boolean force) throws Exception { 114 assertTrue("Media should be mounted", isMediaMounted()); 115 String fullId = SECURE_CONTAINER_PREFIX + localId; 116 117 IMountService ms = getMs(); 118 return ms.destroySecureContainer(fullId, force); 119 } 120 121 private boolean isContainerMounted(String localId) throws Exception { 122 assertTrue("Media should be mounted", isMediaMounted()); 123 String fullId = SECURE_CONTAINER_PREFIX + localId; 124 125 IMountService ms = getMs(); 126 return ms.isSecureContainerMounted(fullId); 127 } 128 129 private IMountService getMs() { 130 IBinder service = ServiceManager.getService("mount"); 131 if (service != null) { 132 return IMountService.Stub.asInterface(service); 133 } else { 134 Log.e(TAG, "Can't get mount service"); 135 } 136 return null; 137 } 138 139 private boolean isMediaMounted() throws Exception { 140 String mPath = Environment.getExternalStorageDirectory().toString(); 141 String state = getMs().getVolumeState(mPath); 142 return Environment.MEDIA_MOUNTED.equals(state); 143 } 144 145 146 /* 147 * CREATE 148 */ 149 150 public void test_Fat_External_Create_Success() throws Exception { 151 if (Environment.isExternalStorageEmulated()) { 152 return; 153 } 154 155 assertEquals(StorageResultCode.OperationSucceeded, 156 createContainer("testCreateContainer", 4, "none", FS_FAT, true)); 157 assertTrue(containerExists("testCreateContainer")); 158 } 159 160 public void test_Ext4_External_Create_Success() throws Exception { 161 if (Environment.isExternalStorageEmulated()) { 162 return; 163 } 164 165 assertEquals(StorageResultCode.OperationSucceeded, 166 createContainer("testCreateContainer", 4, "none", FS_EXT4, true)); 167 assertTrue(containerExists("testCreateContainer")); 168 } 169 170 public void test_Fat_Internal_Create_Success() throws Exception { 171 assertEquals(StorageResultCode.OperationSucceeded, 172 createContainer("testCreateContainer", 4, "none", FS_FAT, false)); 173 assertTrue(containerExists("testCreateContainer")); 174 } 175 176 public void test_Ext4_Internal_Create_Success() throws Exception { 177 assertEquals(StorageResultCode.OperationSucceeded, 178 createContainer("testCreateContainer", 4, "none", FS_EXT4, false)); 179 assertTrue(containerExists("testCreateContainer")); 180 } 181 182 183 /* 184 * CREATE MIN SIZE 185 */ 186 187 public void test_Fat_External_CreateMinSize_Success() throws Exception { 188 if (Environment.isExternalStorageEmulated()) { 189 return; 190 } 191 192 assertEquals(StorageResultCode.OperationSucceeded, 193 createContainer("testCreateContainer", 1, "none", FS_FAT, true)); 194 assertTrue(containerExists("testCreateContainer")); 195 } 196 197 public void test_Ext4_External_CreateMinSize_Success() throws Exception { 198 if (Environment.isExternalStorageEmulated()) { 199 return; 200 } 201 202 assertEquals(StorageResultCode.OperationSucceeded, 203 createContainer("testCreateContainer", 1, "none", FS_EXT4, true)); 204 assertTrue(containerExists("testCreateContainer")); 205 } 206 207 public void test_Fat_Internal_CreateMinSize_Success() throws Exception { 208 assertEquals(StorageResultCode.OperationSucceeded, 209 createContainer("testCreateContainer", 1, "none", FS_FAT, false)); 210 assertTrue(containerExists("testCreateContainer")); 211 } 212 213 public void test_Ext4_Internal_CreateMinSize_Success() throws Exception { 214 assertEquals(StorageResultCode.OperationSucceeded, 215 createContainer("testCreateContainer", 1, "none", FS_EXT4, false)); 216 assertTrue(containerExists("testCreateContainer")); 217 } 218 219 220 /* 221 * CREATE ZERO SIZE - FAIL CASE 222 */ 223 224 public void test_Fat_External_CreateZeroSize_Failure() throws Exception { 225 if (Environment.isExternalStorageEmulated()) { 226 return; 227 } 228 229 assertEquals(StorageResultCode.OperationFailedInternalError, 230 createContainer("testCreateZeroContainer", 0, "none", FS_FAT, true)); 231 } 232 233 public void test_Ext4_External_CreateZeroSize_Failure() throws Exception { 234 if (Environment.isExternalStorageEmulated()) { 235 return; 236 } 237 238 assertEquals(StorageResultCode.OperationFailedInternalError, 239 createContainer("testCreateZeroContainer", 0, "none", FS_EXT4, true)); 240 } 241 242 public void test_Fat_Internal_CreateZeroSize_Failure() throws Exception { 243 assertEquals(StorageResultCode.OperationFailedInternalError, 244 createContainer("testCreateZeroContainer", 0, "none", FS_FAT, false)); 245 } 246 247 public void test_Ext4_Internal_CreateZeroSize_Failure() throws Exception { 248 assertEquals(StorageResultCode.OperationFailedInternalError, 249 createContainer("testCreateZeroContainer", 0, "none", FS_EXT4, false)); 250 } 251 252 253 /* 254 * CREATE DUPLICATE - FAIL CASE 255 */ 256 257 public void test_Fat_External_CreateDuplicate_Failure() throws Exception { 258 if (Environment.isExternalStorageEmulated()) { 259 return; 260 } 261 262 assertEquals(StorageResultCode.OperationSucceeded, 263 createContainer("testCreateDupContainer", 4, "none", FS_FAT, true)); 264 265 assertEquals(StorageResultCode.OperationFailedInternalError, 266 createContainer("testCreateDupContainer", 4, "none", FS_FAT, true)); 267 } 268 269 public void test_Ext4_External_CreateDuplicate_Failure() throws Exception { 270 if (Environment.isExternalStorageEmulated()) { 271 return; 272 } 273 274 assertEquals(StorageResultCode.OperationSucceeded, 275 createContainer("testCreateDupContainer", 4, "none", FS_EXT4, true)); 276 277 assertEquals(StorageResultCode.OperationFailedInternalError, 278 createContainer("testCreateDupContainer", 4, "none", FS_EXT4, true)); 279 } 280 281 public void test_Fat_Internal_CreateDuplicate_Failure() throws Exception { 282 assertEquals(StorageResultCode.OperationSucceeded, 283 createContainer("testCreateDupContainer", 4, "none", FS_FAT, false)); 284 285 assertEquals(StorageResultCode.OperationFailedInternalError, 286 createContainer("testCreateDupContainer", 4, "none", FS_FAT, false)); 287 } 288 289 public void test_Ext4_Internal_CreateDuplicate_Failure() throws Exception { 290 assertEquals(StorageResultCode.OperationSucceeded, 291 createContainer("testCreateDupContainer", 4, "none", FS_EXT4, false)); 292 293 assertEquals(StorageResultCode.OperationFailedInternalError, 294 createContainer("testCreateDupContainer", 4, "none", FS_EXT4, false)); 295 } 296 297 298 /* 299 * DESTROY 300 */ 301 302 public void test_Fat_External_Destroy_Success() throws Exception { 303 if (Environment.isExternalStorageEmulated()) { 304 return; 305 } 306 307 assertEquals(StorageResultCode.OperationSucceeded, 308 createContainer("testDestroyContainer", 4, "none", FS_FAT, true)); 309 assertEquals(StorageResultCode.OperationSucceeded, 310 destroyContainer("testDestroyContainer", false)); 311 } 312 313 public void test_Ext4_External_Destroy_Success() throws Exception { 314 if (Environment.isExternalStorageEmulated()) { 315 return; 316 } 317 318 assertEquals(StorageResultCode.OperationSucceeded, 319 createContainer("testDestroyContainer", 4, "none", FS_EXT4, true)); 320 assertEquals(StorageResultCode.OperationSucceeded, 321 destroyContainer("testDestroyContainer", false)); 322 } 323 324 public void test_Fat_Internal_Destroy_Success() throws Exception { 325 assertEquals(StorageResultCode.OperationSucceeded, 326 createContainer("testDestroyContainer", 4, "none", FS_FAT, false)); 327 assertEquals(StorageResultCode.OperationSucceeded, 328 destroyContainer("testDestroyContainer", false)); 329 } 330 331 public void test_Ext4_Internal_Destroy_Success() throws Exception { 332 assertEquals(StorageResultCode.OperationSucceeded, 333 createContainer("testDestroyContainer", 4, "none", FS_EXT4, false)); 334 assertEquals(StorageResultCode.OperationSucceeded, 335 destroyContainer("testDestroyContainer", false)); 336 } 337 338 339 /* 340 * MOUNT 341 */ 342 343 public void test_Fat_External_Mount() throws Exception { 344 if (Environment.isExternalStorageEmulated()) { 345 return; 346 } 347 348 assertEquals(StorageResultCode.OperationSucceeded, 349 createContainer("testMountContainer", 4, "none", FS_FAT, true)); 350 351 assertEquals(StorageResultCode.OperationSucceeded, 352 unmountContainer("testMountContainer", false)); 353 354 assertEquals(StorageResultCode.OperationSucceeded, 355 mountContainer("testMountContainer", "none")); 356 } 357 358 359 /* 360 * MOUNT BAD KEY - FAIL CASE 361 */ 362 363 public void test_Fat_External_MountBadKey_Failure() throws Exception { 364 if (Environment.isExternalStorageEmulated()) { 365 return; 366 } 367 368 assertEquals(StorageResultCode.OperationSucceeded, 369 createContainer("testMountBadKey", 4, "00000000000000000000000000000000", FS_FAT, 370 true)); 371 372 assertEquals(StorageResultCode.OperationSucceeded, 373 unmountContainer("testMountBadKey", false)); 374 375 assertEquals(StorageResultCode.OperationFailedInternalError, 376 mountContainer("testMountContainer", "000000000000000000000000000000001")); 377 378 assertEquals(StorageResultCode.OperationFailedInternalError, 379 mountContainer("testMountContainer", "none")); 380 } 381 382 383 public void test_Fat_External_UnmountBusy_Success() throws Exception { 384 if (Environment.isExternalStorageEmulated()) { 385 return; 386 } 387 388 IMountService ms = getMs(); 389 assertEquals(StorageResultCode.OperationSucceeded, 390 createContainer("testUnmountBusyContainer", 4, "none", FS_FAT, true)); 391 392 String path = ms.getSecureContainerPath(SECURE_CONTAINER_PREFIX 393 + "testUnmountBusyContainer"); 394 395 File f = new File(path, "reference"); 396 FileOutputStream fos = new FileOutputStream(f); 397 398 assertEquals(StorageResultCode.OperationFailedStorageBusy, 399 unmountContainer("testUnmountBusyContainer", false)); 400 401 fos.close(); 402 assertEquals(StorageResultCode.OperationSucceeded, 403 unmountContainer("testUnmountBusyContainer", false)); 404 } 405 406 public void test_Fat_External_DestroyBusy() throws Exception { 407 if (Environment.isExternalStorageEmulated()) { 408 return; 409 } 410 411 IMountService ms = getMs(); 412 413 assertEquals(StorageResultCode.OperationSucceeded, 414 createContainer("testDestroyBusyContainer", 4, "none", FS_FAT, true)); 415 416 String path = ms.getSecureContainerPath(SECURE_CONTAINER_PREFIX 417 + "testDestroyBusyContainer"); 418 419 File f = new File(path, "reference"); 420 FileOutputStream fos = new FileOutputStream(f); 421 422 assertEquals(StorageResultCode.OperationFailedStorageBusy, 423 destroyContainer("testDestroyBusyContainer", false)); 424 425 fos.close(); 426 assertEquals(StorageResultCode.OperationSucceeded, 427 destroyContainer("testDestroyBusyContainer", false)); 428 } 429 430 public void test_Fat_External_Rename_Success() throws Exception { 431 if (Environment.isExternalStorageEmulated()) { 432 return; 433 } 434 435 assertEquals(StorageResultCode.OperationSucceeded, 436 createContainer("testRenameContainer.1", 4, "none", FS_FAT, true)); 437 438 assertEquals(StorageResultCode.OperationSucceeded, 439 unmountContainer("testRenameContainer.1", false)); 440 441 assertEquals(StorageResultCode.OperationSucceeded, 442 renameContainer("testRenameContainer.1", "testRenameContainer.2")); 443 444 assertFalse(containerExists("testRenameContainer.1")); 445 assertTrue(containerExists("testRenameContainer.2")); 446 } 447 448 public void test_Fat_External_RenameSrcMounted_Failure() throws Exception { 449 if (Environment.isExternalStorageEmulated()) { 450 return; 451 } 452 453 assertEquals(StorageResultCode.OperationSucceeded, 454 createContainer("testRenameContainer.1", 4, "none", FS_FAT, true)); 455 456 assertEquals(StorageResultCode.OperationFailedStorageMounted, 457 renameContainer("testRenameContainer.1", "testRenameContainer.2")); 458 } 459 460 public void test_Fat_External_RenameDstMounted_Failure() throws Exception { 461 if (Environment.isExternalStorageEmulated()) { 462 return; 463 } 464 465 assertEquals(StorageResultCode.OperationSucceeded, 466 createContainer("testRenameContainer.1", 4, "none", FS_FAT, true)); 467 468 assertEquals(StorageResultCode.OperationSucceeded, 469 unmountContainer("testRenameContainer.1", false)); 470 471 assertEquals(StorageResultCode.OperationSucceeded, 472 createContainer("testRenameContainer.2", 4, "none", FS_FAT, true)); 473 474 assertEquals(StorageResultCode.OperationFailedStorageMounted, 475 renameContainer("testRenameContainer.1", "testRenameContainer.2")); 476 } 477 478 public void test_Fat_External_Size_Success() throws Exception { 479 if (Environment.isExternalStorageEmulated()) { 480 return; 481 } 482 483 IMountService ms = getMs(); 484 assertEquals(StorageResultCode.OperationSucceeded, 485 createContainer("testContainerSize", 1, "none", FS_FAT, true)); 486 String path = ms.getSecureContainerPath(SECURE_CONTAINER_PREFIX + "testContainerSize"); 487 488 byte[] buf = new byte[4096]; 489 File f = new File(path, "reference"); 490 FileOutputStream fos = new FileOutputStream(f); 491 for (int i = 0; i < (1024 * 1024); i += buf.length) { 492 fos.write(buf); 493 } 494 fos.close(); 495 } 496 497 public void testGetSecureContainerPath_NonExistPath_Failure() throws Exception { 498 IMountService ms = getMs(); 499 assertNull("Getting the path for an invalid container should return null", 500 ms.getSecureContainerPath("jparks.broke.it")); 501 } 502 503 /*------------ Tests for unmounting volume ---*/ 504 public final long MAX_WAIT_TIME=120*1000; 505 public final long WAIT_TIME_INCR=20*1000; 506 507 boolean getMediaState() throws Exception { 508 String mPath = Environment.getExternalStorageDirectory().toString(); 509 String state = getMs().getVolumeState(mPath); 510 return Environment.MEDIA_MOUNTED.equals(state); 511 } 512 513 boolean mountMedia() throws Exception { 514 if (Environment.isExternalStorageEmulated()) { 515 return true; 516 } 517 518 if (getMediaState()) { 519 return true; 520 } 521 522 String mPath = Environment.getExternalStorageDirectory().toString(); 523 int ret = getMs().mountVolume(mPath); 524 return ret == StorageResultCode.OperationSucceeded; 525 } 526 527 class StorageListener extends StorageEventListener { 528 String oldState; 529 String newState; 530 String path; 531 private boolean doneFlag = false; 532 533 public void action() { 534 synchronized (this) { 535 doneFlag = true; 536 notifyAll(); 537 } 538 } 539 540 public boolean isDone() { 541 return doneFlag; 542 } 543 544 @Override 545 public void onStorageStateChanged(String path, String oldState, String newState) { 546 if (localLOGV) Log.i(TAG, "Storage state changed from " + oldState + " to " + newState); 547 this.oldState = oldState; 548 this.newState = newState; 549 this.path = path; 550 action(); 551 } 552 } 553 554 private void unmountMedia() throws Exception { 555 if (Environment.isExternalStorageEmulated()) { 556 return; 557 } 558 559 if (!getMediaState()) { 560 return; 561 } 562 563 String path = Environment.getExternalStorageDirectory().toString(); 564 StorageListener observer = new StorageListener(); 565 StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE); 566 sm.registerListener(observer); 567 try { 568 // Wait on observer 569 synchronized(observer) { 570 getMs().unmountVolume(path, false, false); 571 long waitTime = 0; 572 while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) { 573 observer.wait(WAIT_TIME_INCR); 574 waitTime += WAIT_TIME_INCR; 575 } 576 if(!observer.isDone()) { 577 fail("Timed out waiting for packageInstalled callback"); 578 } 579 } 580 } finally { 581 sm.unregisterListener(observer); 582 } 583 } 584 585 public void testUnmount() throws Exception { 586 boolean oldStatus = getMediaState(); 587 Log.i(TAG, "oldStatus="+oldStatus); 588 try { 589 // Mount media firsts 590 if (!getMediaState()) { 591 mountMedia(); 592 } 593 unmountMedia(); 594 } finally { 595 // Restore old status 596 boolean currStatus = getMediaState(); 597 if (oldStatus != currStatus) { 598 if (oldStatus) { 599 // Mount media 600 mountMedia(); 601 } else { 602 unmountMedia(); 603 } 604 } 605 } 606 } 607 608 class MultipleStorageLis extends StorageListener { 609 int count = 0; 610 public void onStorageStateChanged(String path, String oldState, String newState) { 611 count++; 612 super.action(); 613 } 614 } 615 /* 616 * This test invokes unmount multiple time and expects the call back 617 * to be invoked just once. 618 */ 619 public void testUnmountMultiple() throws Exception { 620 if (Environment.isExternalStorageEmulated()) { 621 return; 622 } 623 624 boolean oldStatus = getMediaState(); 625 StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE); 626 MultipleStorageLis observer = new MultipleStorageLis(); 627 try { 628 // Mount media firsts 629 if (!getMediaState()) { 630 mountMedia(); 631 } 632 String path = Environment.getExternalStorageDirectory().toString(); 633 sm.registerListener(observer); 634 // Wait on observer 635 synchronized(observer) { 636 for (int i = 0; i < 5; i++) { 637 getMs().unmountVolume(path, false, false); 638 } 639 long waitTime = 0; 640 while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) { 641 observer.wait(WAIT_TIME_INCR); 642 waitTime += WAIT_TIME_INCR; 643 } 644 if(!observer.isDone()) { 645 fail("Timed out waiting for packageInstalled callback"); 646 } 647 } 648 assertEquals(observer.count, 1); 649 } finally { 650 sm.unregisterListener(observer); 651 // Restore old status 652 boolean currStatus = getMediaState(); 653 if (oldStatus != currStatus) { 654 if (oldStatus) { 655 // Mount media 656 mountMedia(); 657 } else { 658 unmountMedia(); 659 } 660 } 661 } 662 } 663 664 class ShutdownObserver extends IMountShutdownObserver.Stub{ 665 private boolean doneFlag = false; 666 int statusCode; 667 668 public void action() { 669 synchronized (this) { 670 doneFlag = true; 671 notifyAll(); 672 } 673 } 674 675 public boolean isDone() { 676 return doneFlag; 677 } 678 public void onShutDownComplete(int statusCode) throws RemoteException { 679 this.statusCode = statusCode; 680 action(); 681 } 682 683 } 684 685 void invokeShutdown() throws Exception { 686 IMountService ms = getMs(); 687 ShutdownObserver observer = new ShutdownObserver(); 688 synchronized (observer) { 689 ms.shutdown(observer); 690 } 691 } 692 693 public void testShutdown() throws Exception { 694 if (Environment.isExternalStorageEmulated()) { 695 return; 696 } 697 698 boolean oldStatus = getMediaState(); 699 try { 700 // Mount media firsts 701 if (!getMediaState()) { 702 mountMedia(); 703 } 704 invokeShutdown(); 705 } finally { 706 // Restore old status 707 boolean currStatus = getMediaState(); 708 if (oldStatus != currStatus) { 709 if (oldStatus) { 710 // Mount media 711 mountMedia(); 712 } else { 713 unmountMedia(); 714 } 715 } 716 } 717 } 718 719 /* 720 * This test invokes unmount multiple time and expects the call back 721 * to be invoked just once. 722 */ 723 public void testShutdownMultiple() throws Exception { 724 if (Environment.isExternalStorageEmulated()) { 725 return; 726 } 727 728 boolean oldStatus = getMediaState(); 729 try { 730 // Mount media firsts 731 if (!getMediaState()) { 732 mountMedia(); 733 } 734 IMountService ms = getMs(); 735 ShutdownObserver observer = new ShutdownObserver(); 736 synchronized (observer) { 737 ms.shutdown(observer); 738 for (int i = 0; i < 4; i++) { 739 ms.shutdown(null); 740 } 741 } 742 } finally { 743 // Restore old status 744 boolean currStatus = getMediaState(); 745 if (oldStatus != currStatus) { 746 if (oldStatus) { 747 // Mount media 748 mountMedia(); 749 } else { 750 unmountMedia(); 751 } 752 } 753 } 754 } 755 756} 757