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