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