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