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