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