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 17 package android.content.pm; 18 19 import android.app.PendingIntent; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.os.RemoteException; 25 import android.os.ServiceManager; 26 import android.os.StatFs; 27 import android.test.AndroidTestCase; 28 import android.test.suitebuilder.annotation.LargeTest; 29 import android.test.suitebuilder.annotation.MediumTest; 30 import android.test.suitebuilder.annotation.SmallTest; 31 import android.util.Log; 32 33 import java.io.File; 34 import java.io.FileInputStream; 35 import java.io.FileNotFoundException; 36 import java.io.FileOutputStream; 37 import java.io.IOException; 38 39 public class AppCacheTest extends AndroidTestCase { 40 private static final boolean localLOGV = false; 41 public static final String TAG="AppCacheTest"; 42 public final long MAX_WAIT_TIME=60*1000; 43 public final long WAIT_TIME_INCR=10*1000; 44 private static final int THRESHOLD=5; 45 private static final int ACTUAL_THRESHOLD=10; 46 47 @Override 48 protected void setUp() throws Exception { 49 super.setUp(); 50 if(localLOGV) Log.i(TAG, "Cleaning up cache directory first"); 51 cleanUpCacheDirectory(); 52 } 53 54 void cleanUpDirectory(File pDir, String dirName) { 55 File testDir = new File(pDir, dirName); 56 if(!testDir.exists()) { 57 return; 58 } 59 String fList[] = testDir.list(); 60 for(int i = 0; i < fList.length; i++) { 61 File file = new File(testDir, fList[i]); 62 if(file.isDirectory()) { 63 cleanUpDirectory(testDir, fList[i]); 64 } else { 65 file.delete(); 66 } 67 } 68 testDir.delete(); 69 } 70 71 void cleanUpCacheDirectory() { 72 File testDir = mContext.getCacheDir(); 73 if(!testDir.exists()) { 74 return; 75 } 76 77 String fList[] = testDir.list(); 78 if(fList == null) { 79 testDir.delete(); 80 return; 81 } 82 for(int i = 0; i < fList.length; i++) { 83 File file = new File(testDir, fList[i]); 84 if(file.isDirectory()) { 85 cleanUpDirectory(testDir, fList[i]); 86 } else { 87 file.delete(); 88 } 89 } 90 } 91 92 @SmallTest 93 public void testDeleteAllCacheFiles() { 94 String testName="testDeleteAllCacheFiles"; 95 cleanUpCacheDirectory(); 96 } 97 98 void failStr(String errMsg) { 99 Log.w(TAG, "errMsg="+errMsg); 100 fail(errMsg); 101 } 102 void failStr(Exception e) { 103 Log.w(TAG, "e.getMessage="+e.getMessage()); 104 Log.w(TAG, "e="+e); 105 } 106 long getFreeStorageBlks(StatFs st) { 107 st.restat("/data"); 108 return st.getFreeBlocks(); 109 } 110 111 long getFreeStorageSize(StatFs st) { 112 st.restat("/data"); 113 return (st.getFreeBlocks()*st.getBlockSize()); 114 } 115 @LargeTest 116 public void testFreeApplicationCacheAllFiles() throws Exception { 117 boolean TRACKING = true; 118 StatFs st = new StatFs("/data"); 119 long blks1 = getFreeStorageBlks(st); 120 long availableMem = getFreeStorageSize(st); 121 File cacheDir = mContext.getCacheDir(); 122 assertNotNull(cacheDir); 123 createTestFiles1(cacheDir, "testtmpdir", 5); 124 long blks2 = getFreeStorageBlks(st); 125 if(localLOGV || TRACKING) Log.i(TAG, "blk1="+blks1+", blks2="+blks2); 126 //this should free up the test files that were created earlier 127 invokePMFreeApplicationCache(availableMem); 128 long blks3 = getFreeStorageBlks(st); 129 if(localLOGV || TRACKING) Log.i(TAG, "blks3="+blks3); 130 verifyTestFiles1(cacheDir, "testtmpdir", 5); 131 } 132 133 public void testFreeApplicationCacheSomeFiles() throws Exception { 134 StatFs st = new StatFs("/data"); 135 long blks1 = getFreeStorageBlks(st); 136 File cacheDir = mContext.getCacheDir(); 137 assertNotNull(cacheDir); 138 createTestFiles1(cacheDir, "testtmpdir", 5); 139 long blks2 = getFreeStorageBlks(st); 140 Log.i(TAG, "blk1="+blks1+", blks2="+blks2); 141 long diff = (blks1-blks2-2); 142 assertTrue(invokePMFreeApplicationCache(diff*st.getBlockSize())); 143 long blks3 = getFreeStorageBlks(st); 144 //blks3 should be greater than blks2 and less than blks1 145 if(!((blks3 <= blks1) && (blks3 >= blks2))) { 146 failStr("Expected "+(blks1-blks2)+" number of blocks to be freed but freed only " 147 +(blks1-blks3)); 148 } 149 } 150 151 /** 152 * This method opens an output file writes to it, opens the same file as an input 153 * stream, reads the contents and verifies the data that was written earlier can be read 154 */ 155 public void openOutFileInAppFilesDir(File pFile, String pFileOut) { 156 FileOutputStream fos = null; 157 try { 158 fos = new FileOutputStream(pFile); 159 } catch (FileNotFoundException e1) { 160 failStr("Error when opening file "+e1); 161 return; 162 } 163 try { 164 fos.write(pFileOut.getBytes()); 165 fos.close(); 166 } catch (FileNotFoundException e) { 167 failStr(e.getMessage()); 168 } catch (IOException e) { 169 failStr(e.getMessage()); 170 } 171 int count = pFileOut.getBytes().length; 172 byte[] buffer = new byte[count]; 173 try { 174 FileInputStream fis = new FileInputStream(pFile); 175 fis.read(buffer, 0, count); 176 fis.close(); 177 } catch (FileNotFoundException e) { 178 failStr("Failed when verifing output opening file "+e.getMessage()); 179 } catch (IOException e) { 180 failStr("Failed when verifying output, reading from written file "+e); 181 } 182 String str = new String(buffer); 183 assertEquals(str, pFileOut); 184 } 185 186 /* 187 * This test case verifies that output written to a file 188 * using Context.openFileOutput has executed successfully. 189 * The operation is verified by invoking Context.openFileInput 190 */ 191 @MediumTest 192 public void testAppFilesCreateFile() { 193 String fileName = "testFile1.txt"; 194 String fileOut = "abcdefghijklmnopqrstuvwxyz"; 195 Context con = super.getContext(); 196 try { 197 FileOutputStream fos = con.openFileOutput(fileName, Context.MODE_PRIVATE); 198 fos.close(); 199 } catch (FileNotFoundException e) { 200 failStr(e); 201 } catch (IOException e) { 202 failStr(e); 203 } 204 } 205 206 @SmallTest 207 public void testAppCacheCreateFile() { 208 String fileName = "testFile1.txt"; 209 String fileOut = "abcdefghijklmnopqrstuvwxyz"; 210 Context con = super.getContext(); 211 File file = new File(con.getCacheDir(), fileName); 212 openOutFileInAppFilesDir(file, fileOut); 213 cleanUpCacheDirectory(); 214 } 215 216 @MediumTest 217 public void testAppCreateCacheFiles() { 218 File cacheDir = mContext.getCacheDir(); 219 String testDirName = "testtmp"; 220 File testTmpDir = new File(cacheDir, testDirName); 221 testTmpDir.mkdir(); 222 int numDirs = 3; 223 File fileArr[] = new File[numDirs]; 224 for(int i = 0; i < numDirs; i++) { 225 fileArr[i] = new File(testTmpDir, "dir"+(i+1)); 226 fileArr[i].mkdir(); 227 } 228 byte buffer[] = getBuffer(); 229 Log.i(TAG, "Size of bufer="+buffer.length); 230 for(int i = 0; i < numDirs; i++) { 231 for(int j = 1; j <= (i); j++) { 232 File file1 = new File(fileArr[i], "testFile"+j+".txt"); 233 FileOutputStream fos = null; 234 try { 235 fos = new FileOutputStream(file1); 236 for(int k = 1; k < 10; k++) { 237 fos.write(buffer); 238 } 239 Log.i(TAG, "wrote 10K bytes to "+file1); 240 fos.close(); 241 } catch (FileNotFoundException e) { 242 Log.i(TAG, "Excetion ="+e); 243 fail("Error when creating outputstream "+e); 244 } catch(IOException e) { 245 Log.i(TAG, "Excetion ="+e); 246 fail("Error when writing output "+e); 247 } 248 } 249 } 250 } 251 252 byte[] getBuffer() { 253 String sbuffer = "a"; 254 for(int i = 0; i < 10; i++) { 255 sbuffer += sbuffer; 256 } 257 return sbuffer.getBytes(); 258 } 259 260 long getFileNumBlocks(long fileSize, int blkSize) { 261 long ret = fileSize/blkSize; 262 if(ret*blkSize < fileSize) { 263 ret++; 264 } 265 return ret; 266 } 267 268 //@LargeTest 269 public void testAppCacheClear() { 270 String dataDir="/data/data"; 271 StatFs st = new StatFs(dataDir); 272 int blkSize = st.getBlockSize(); 273 int totBlks = st.getBlockCount(); 274 long availableBlks = st.getFreeBlocks(); 275 long thresholdBlks = (totBlks*THRESHOLD)/100; 276 String testDirName = "testdir"; 277 //create directory in cache 278 File testDir = new File(mContext.getCacheDir(), testDirName); 279 testDir.mkdirs(); 280 byte[] buffer = getBuffer(); 281 int i = 1; 282 if(localLOGV) Log.i(TAG, "availableBlks="+availableBlks+", thresholdBlks="+thresholdBlks); 283 long createdFileBlks = 0; 284 int imax = 300; 285 while((availableBlks > thresholdBlks) &&(i < imax)) { 286 File testFile = new File(testDir, "testFile"+i+".txt"); 287 if(localLOGV) Log.i(TAG, "Creating "+i+"th test file "+testFile); 288 int jmax = i; 289 i++; 290 FileOutputStream fos; 291 try { 292 fos = new FileOutputStream(testFile); 293 } catch (FileNotFoundException e) { 294 Log.i(TAG, "Failed creating test file:"+testFile); 295 continue; 296 } 297 boolean err = false; 298 for(int j = 1; j <= jmax;j++) { 299 try { 300 fos.write(buffer); 301 } catch (IOException e) { 302 Log.i(TAG, "Failed to write to file:"+testFile); 303 err = true; 304 } 305 } 306 try { 307 fos.close(); 308 } catch (IOException e) { 309 Log.i(TAG, "Failed closing file:"+testFile); 310 } 311 if(err) { 312 continue; 313 } 314 createdFileBlks += getFileNumBlocks(testFile.length(), blkSize); 315 st.restat(dataDir); 316 availableBlks = st.getFreeBlocks(); 317 } 318 st.restat(dataDir); 319 long availableBytes = st.getFreeBlocks()*blkSize; 320 long shouldFree = (ACTUAL_THRESHOLD-THRESHOLD)*totBlks; 321 //would have run out of memory 322 //wait for some time and confirm cache is deleted 323 try { 324 Log.i(TAG, "Sleeping for 2 minutes..."); 325 Thread.sleep(2*60*1000); 326 } catch (InterruptedException e) { 327 fail("Exception when sleeping "+e); 328 } 329 boolean removedFlag = false; 330 long existingFileBlks = 0; 331 for(int k = 1; k <i; k++) { 332 File testFile = new File(testDir, "testFile"+k+".txt"); 333 if(!testFile.exists()) { 334 removedFlag = true; 335 if(localLOGV) Log.i(TAG, testFile+" removed"); 336 } else { 337 existingFileBlks += getFileNumBlocks(testFile.length(), blkSize); 338 } 339 } 340 if(localLOGV) Log.i(TAG, "createdFileBlks="+createdFileBlks+ 341 ", existingFileBlks="+existingFileBlks); 342 long fileSize = createdFileBlks-existingFileBlks; 343 //verify fileSize number of bytes have been cleared from cache 344 if(localLOGV) Log.i(TAG, "deletedFileBlks="+fileSize+" shouldFreeBlks="+shouldFree); 345 if((fileSize > (shouldFree-blkSize) && (fileSize < (shouldFree+blkSize)))) { 346 Log.i(TAG, "passed"); 347 } 348 assertTrue(removedFlag); 349 } 350 351 //createTestFiles(new File(super.getContext().getCacheDir(), "testtmp", "dir", 3) 352 void createTestFiles1(File cacheDir, String testFilePrefix, int numTestFiles) { 353 byte buffer[] = getBuffer(); 354 for(int i = 0; i < numTestFiles; i++) { 355 File file1 = new File(cacheDir, testFilePrefix+i+".txt"); 356 FileOutputStream fos = null; 357 try { 358 fos = new FileOutputStream(file1); 359 for(int k = 1; k < 10; k++) { 360 fos.write(buffer); 361 } 362 fos.close(); 363 } catch (FileNotFoundException e) { 364 Log.i(TAG, "Exception ="+e); 365 fail("Error when creating outputstream "+e); 366 } catch(IOException e) { 367 Log.i(TAG, "Exception ="+e); 368 fail("Error when writing output "+e); 369 } 370 try { 371 //introduce sleep for 1 s to avoid common time stamps for files being created 372 Thread.sleep(1000); 373 } catch (InterruptedException e) { 374 fail("Exception when sleeping "+e); 375 } 376 } 377 } 378 379 void verifyTestFiles1(File cacheDir, String testFilePrefix, int numTestFiles) { 380 for(int i = 0; i < numTestFiles; i++) { 381 File file1 = new File(cacheDir, testFilePrefix+i+".txt"); 382 if(file1.exists()) { 383 fail("file:"+file1+" should not exist"); 384 } 385 } 386 } 387 388 void createTestFiles2(File cacheDir, String rootTestDirName, String subDirPrefix, int numDirs, String testFilePrefix) { 389 Context con = super.getContext(); 390 File testTmpDir = new File(cacheDir, rootTestDirName); 391 testTmpDir.mkdir(); 392 File fileArr[] = new File[numDirs]; 393 for(int i = 0; i < numDirs; i++) { 394 fileArr[i] = new File(testTmpDir, subDirPrefix+(i+1)); 395 fileArr[i].mkdir(); 396 } 397 byte buffer[] = getBuffer(); 398 for(int i = 0; i < numDirs; i++) { 399 for(int j = 1; j <= (i); j++) { 400 File file1 = new File(fileArr[i], testFilePrefix+j+".txt"); 401 FileOutputStream fos = null; 402 try { 403 fos = new FileOutputStream(file1); 404 for(int k = 1; k < 10; k++) { 405 fos.write(buffer); 406 } 407 fos.close(); 408 } catch (FileNotFoundException e) { 409 Log.i(TAG, "Exception ="+e); 410 fail("Error when creating outputstream "+e); 411 } catch(IOException e) { 412 Log.i(TAG, "Exception ="+e); 413 fail("Error when writing output "+e); 414 } 415 try { 416 //introduce sleep for 10 ms to avoid common time stamps for files being created 417 Thread.sleep(10); 418 } catch (InterruptedException e) { 419 fail("Exception when sleeping "+e); 420 } 421 } 422 } 423 } 424 425 class PackageDataObserver extends IPackageDataObserver.Stub { 426 public boolean retValue = false; 427 private boolean doneFlag = false; 428 public void onRemoveCompleted(String packageName, boolean succeeded) 429 throws RemoteException { 430 synchronized(this) { 431 retValue = succeeded; 432 doneFlag = true; 433 notifyAll(); 434 } 435 } 436 public boolean isDone() { 437 return doneFlag; 438 } 439 } 440 441 IPackageManager getPm() { 442 return IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 443 } 444 445 boolean invokePMDeleteAppCacheFiles() throws Exception { 446 try { 447 String packageName = mContext.getPackageName(); 448 PackageDataObserver observer = new PackageDataObserver(); 449 //wait on observer 450 synchronized(observer) { 451 getPm().deleteApplicationCacheFiles(packageName, observer); 452 long waitTime = 0; 453 while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) { 454 observer.wait(WAIT_TIME_INCR); 455 waitTime += WAIT_TIME_INCR; 456 } 457 if(!observer.isDone()) { 458 throw new Exception("timed out waiting for PackageDataObserver.onRemoveCompleted"); 459 } 460 } 461 return observer.retValue; 462 } catch (RemoteException e) { 463 Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); 464 return false; 465 } catch (InterruptedException e) { 466 Log.w(TAG, "InterruptedException :"+e); 467 return false; 468 } 469 } 470 471 boolean invokePMFreeApplicationCache(long idealStorageSize) throws Exception { 472 try { 473 String packageName = mContext.getPackageName(); 474 PackageDataObserver observer = new PackageDataObserver(); 475 //wait on observer 476 synchronized(observer) { 477 getPm().freeStorageAndNotify(idealStorageSize, observer); 478 long waitTime = 0; 479 while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) { 480 observer.wait(WAIT_TIME_INCR); 481 waitTime += WAIT_TIME_INCR; 482 } 483 if(!observer.isDone()) { 484 throw new Exception("timed out waiting for PackageDataObserver.onRemoveCompleted"); 485 } 486 } 487 return observer.retValue; 488 } catch (RemoteException e) { 489 Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); 490 return false; 491 } catch (InterruptedException e) { 492 Log.w(TAG, "InterruptedException :"+e); 493 return false; 494 } 495 } 496 497 boolean invokePMFreeStorage(long idealStorageSize, FreeStorageReceiver r, 498 PendingIntent pi) throws Exception { 499 try { 500 // Spin lock waiting for call back 501 synchronized(r) { 502 getPm().freeStorage(idealStorageSize, pi.getIntentSender()); 503 long waitTime = 0; 504 while(!r.isDone() && (waitTime < MAX_WAIT_TIME)) { 505 r.wait(WAIT_TIME_INCR); 506 waitTime += WAIT_TIME_INCR; 507 } 508 if(!r.isDone()) { 509 throw new Exception("timed out waiting for call back from PendingIntent"); 510 } 511 } 512 return r.getResultCode() == 1; 513 } catch (RemoteException e) { 514 Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); 515 return false; 516 } catch (InterruptedException e) { 517 Log.w(TAG, "InterruptedException :"+e); 518 return false; 519 } 520 } 521 522 @LargeTest 523 public void testDeleteAppCacheFiles() throws Exception { 524 String testName="testDeleteAppCacheFiles"; 525 File cacheDir = mContext.getCacheDir(); 526 createTestFiles1(cacheDir, "testtmpdir", 5); 527 assertTrue(invokePMDeleteAppCacheFiles()); 528 //confirm files dont exist 529 verifyTestFiles1(cacheDir, "testtmpdir", 5); 530 } 531 532 class PackageStatsObserver extends IPackageStatsObserver.Stub { 533 public boolean retValue = false; 534 public PackageStats stats; 535 private boolean doneFlag = false; 536 537 public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) 538 throws RemoteException { 539 synchronized(this) { 540 retValue = succeeded; 541 stats = pStats; 542 doneFlag = true; 543 notifyAll(); 544 } 545 } 546 public boolean isDone() { 547 return doneFlag; 548 } 549 } 550 551 public PackageStats invokePMGetPackageSizeInfo() throws Exception { 552 try { 553 String packageName = mContext.getPackageName(); 554 PackageStatsObserver observer = new PackageStatsObserver(); 555 //wait on observer 556 synchronized(observer) { 557 getPm().getPackageSizeInfo(packageName, observer); 558 long waitTime = 0; 559 while((!observer.isDone()) || (waitTime > MAX_WAIT_TIME) ) { 560 observer.wait(WAIT_TIME_INCR); 561 waitTime += WAIT_TIME_INCR; 562 } 563 if(!observer.isDone()) { 564 throw new Exception("Timed out waiting for PackageStatsObserver.onGetStatsCompleted"); 565 } 566 } 567 if(localLOGV) Log.i(TAG, "OBSERVER RET VALUES code="+observer.stats.codeSize+ 568 ", data="+observer.stats.dataSize+", cache="+observer.stats.cacheSize); 569 return observer.stats; 570 } catch (RemoteException e) { 571 Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); 572 return null; 573 } catch (InterruptedException e) { 574 Log.w(TAG, "InterruptedException :"+e); 575 return null; 576 } 577 } 578 579 @SmallTest 580 public void testGetPackageSizeInfo() throws Exception { 581 String testName="testGetPackageSizeInfo"; 582 PackageStats stats = invokePMGetPackageSizeInfo(); 583 assertTrue(stats!=null); 584 //confirm result 585 if(localLOGV) Log.i(TAG, "code="+stats.codeSize+", data="+stats.dataSize+ 586 ", cache="+stats.cacheSize); 587 } 588 589 @SmallTest 590 public void testGetSystemSharedLibraryNames() throws Exception { 591 try { 592 String[] sharedLibs = getPm().getSystemSharedLibraryNames(); 593 if (localLOGV) { 594 for (String str : sharedLibs) { 595 Log.i(TAG, str); 596 } 597 } 598 } catch (RemoteException e) { 599 fail("Failed invoking getSystemSharedLibraryNames with exception:" + e); 600 } 601 } 602 603 class FreeStorageReceiver extends BroadcastReceiver { 604 public static final String ACTION_FREE = "com.android.unit_tests.testcallback"; 605 private boolean doneFlag = false; 606 607 public boolean isDone() { 608 return doneFlag; 609 } 610 611 @Override 612 public void onReceive(Context context, Intent intent) { 613 if(intent.getAction().equalsIgnoreCase(ACTION_FREE)) { 614 if (localLOGV) Log.i(TAG, "Got notification: clear cache succeeded "+getResultCode()); 615 synchronized (this) { 616 doneFlag = true; 617 notifyAll(); 618 } 619 } 620 } 621 } 622 623 // TODO: flaky test, omit from LargeTest for now 624 //@LargeTest 625 public void testFreeStorage() throws Exception { 626 boolean TRACKING = true; 627 StatFs st = new StatFs("/data"); 628 long blks1 = getFreeStorageBlks(st); 629 if(localLOGV || TRACKING) Log.i(TAG, "Available free blocks="+blks1); 630 long availableMem = getFreeStorageSize(st); 631 File cacheDir = mContext.getCacheDir(); 632 assertNotNull(cacheDir); 633 createTestFiles1(cacheDir, "testtmpdir", 5); 634 long blks2 = getFreeStorageBlks(st); 635 if(localLOGV || TRACKING) Log.i(TAG, "Available blocks after writing test files in application cache="+blks2); 636 // Create receiver and register it 637 FreeStorageReceiver receiver = new FreeStorageReceiver(); 638 mContext.registerReceiver(receiver, new IntentFilter(FreeStorageReceiver.ACTION_FREE)); 639 PendingIntent pi = PendingIntent.getBroadcast(mContext, 640 0, new Intent(FreeStorageReceiver.ACTION_FREE), 0); 641 // Invoke PackageManager api 642 invokePMFreeStorage(availableMem, receiver, pi); 643 long blks3 = getFreeStorageBlks(st); 644 if(localLOGV || TRACKING) Log.i(TAG, "Available blocks after freeing cache"+blks3); 645 assertEquals(receiver.getResultCode(), 1); 646 mContext.unregisterReceiver(receiver); 647 // Verify result 648 verifyTestFiles1(cacheDir, "testtmpdir", 5); 649 } 650 651 /* utility method used to create observer and check async call back from PackageManager. 652 * ClearApplicationUserData 653 */ 654 boolean invokePMClearApplicationUserData() throws Exception { 655 try { 656 String packageName = mContext.getPackageName(); 657 PackageDataObserver observer = new PackageDataObserver(); 658 //wait on observer 659 synchronized(observer) { 660 getPm().clearApplicationUserData(packageName, observer); 661 long waitTime = 0; 662 while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) { 663 observer.wait(WAIT_TIME_INCR); 664 waitTime += WAIT_TIME_INCR; 665 } 666 if(!observer.isDone()) { 667 throw new Exception("timed out waiting for PackageDataObserver.onRemoveCompleted"); 668 } 669 } 670 return observer.retValue; 671 } catch (RemoteException e) { 672 Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); 673 return false; 674 } catch (InterruptedException e) { 675 Log.w(TAG, "InterruptedException :"+e); 676 return false; 677 } 678 } 679 680 void verifyUserDataCleared(File pDir) { 681 if(localLOGV) Log.i(TAG, "Verifying "+pDir); 682 if(pDir == null) { 683 return; 684 } 685 String fileList[] = pDir.list(); 686 if(fileList == null) { 687 return; 688 } 689 int imax = fileList.length; 690 //look recursively in user data dir 691 for(int i = 0; i < imax; i++) { 692 if(localLOGV) Log.i(TAG, "Found entry "+fileList[i]+ "in "+pDir); 693 if("lib".equalsIgnoreCase(fileList[i])) { 694 if(localLOGV) Log.i(TAG, "Ignoring lib directory"); 695 continue; 696 } 697 fail(pDir+" should be empty or contain only lib subdirectory. Found "+fileList[i]); 698 } 699 } 700 701 File getDataDir() { 702 try { 703 ApplicationInfo appInfo = getPm().getApplicationInfo(mContext.getPackageName(), 0); 704 return new File(appInfo.dataDir); 705 } catch (RemoteException e) { 706 throw new RuntimeException("Pacakge manager dead", e); 707 } 708 } 709 710 @LargeTest 711 public void testClearApplicationUserDataWithTestData() throws Exception { 712 File cacheDir = mContext.getCacheDir(); 713 createTestFiles1(cacheDir, "testtmpdir", 5); 714 if(localLOGV) { 715 Log.i(TAG, "Created test data Waiting for 60seconds before continuing"); 716 Thread.sleep(60*1000); 717 } 718 assertTrue(invokePMClearApplicationUserData()); 719 //confirm files dont exist 720 verifyUserDataCleared(getDataDir()); 721 } 722 723 @SmallTest 724 public void testClearApplicationUserDataWithNoTestData() throws Exception { 725 assertTrue(invokePMClearApplicationUserData()); 726 //confirm files dont exist 727 verifyUserDataCleared(getDataDir()); 728 } 729 730 @LargeTest 731 public void testClearApplicationUserDataNoObserver() throws Exception { 732 getPm().clearApplicationUserData(mContext.getPackageName(), null); 733 //sleep for 1 minute 734 Thread.sleep(60*1000); 735 //confirm files dont exist 736 verifyUserDataCleared(getDataDir()); 737 } 738 739 } 740