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