• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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