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