/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.content.pm;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StatFs;
import android.os.UserHandle;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class AppCacheTest extends AndroidTestCase {
    private static final boolean localLOGV = false;
    public static final String TAG="AppCacheTest";
    public final long MAX_WAIT_TIME=60*1000;
    public final long WAIT_TIME_INCR=10*1000;
    private static final long THRESHOLD=5;
    private static final long ACTUAL_THRESHOLD=10;
    
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        if(localLOGV) Log.i(TAG, "Cleaning up cache directory first");
        cleanUpCacheDirectory();
    }
    
    void cleanUpDirectory(File pDir, String dirName) {
       File testDir = new File(pDir,  dirName);
       if(!testDir.exists()) {
           return;
       }
        String fList[] = testDir.list();
        for(int i = 0; i < fList.length; i++) {
            File file = new File(testDir, fList[i]);
            if(file.isDirectory()) {
                cleanUpDirectory(testDir, fList[i]);
            } else {
                file.delete();
            }
        }
        testDir.delete();
    }
    
    void cleanUpCacheDirectory() {
        File testDir = mContext.getCacheDir();
        if(!testDir.exists()) {
            return;
        }
        
         String fList[] = testDir.list();
         if(fList == null) {
             testDir.delete();
             return;
         }
         for(int i = 0; i < fList.length; i++) {
             File file = new File(testDir, fList[i]);
             if(file.isDirectory()) {
                 cleanUpDirectory(testDir, fList[i]);
             } else {
                 file.delete();
             }
         }
     }
    
    @SmallTest
    public void testDeleteAllCacheFiles() {
        String testName="testDeleteAllCacheFiles";
        cleanUpCacheDirectory();
    }

    void failStr(String errMsg) {
        Log.w(TAG, "errMsg="+errMsg);
        fail(errMsg);
    }

    void failStr(Exception e) {
        Log.w(TAG, "e.getMessage="+e.getMessage());
        Log.w(TAG, "e="+e);
    }

    long getFreeStorageBlks(StatFs st) {
        st.restat("/data");
        return st.getFreeBlocks();
    }

    long getFreeStorageSize(StatFs st) {
        st.restat("/data");
        return (long) st.getFreeBlocks() * (long) st.getBlockSize();
    }

    @LargeTest
    public void testFreeApplicationCacheAllFiles() throws Exception {
        boolean TRACKING = true;
        StatFs st = new StatFs("/data");
        long blks1 = getFreeStorageBlks(st);
        long availableMem = getFreeStorageSize(st);
        File cacheDir = mContext.getCacheDir();
        assertNotNull(cacheDir);
        createTestFiles1(cacheDir, "testtmpdir", 5);
        long blks2 = getFreeStorageBlks(st);
        if(localLOGV || TRACKING) Log.i(TAG, "blk1="+blks1+", blks2="+blks2);
        //this should free up the test files that were created earlier
        if (!invokePMFreeApplicationCache(availableMem)) {
            fail("Could not successfully invoke PackageManager free app cache API");
        }
        long blks3 = getFreeStorageBlks(st);
        if(localLOGV || TRACKING) Log.i(TAG, "blks3="+blks3);
        verifyTestFiles1(cacheDir, "testtmpdir", 5);
    }

    public void testFreeApplicationCacheSomeFiles() throws Exception {
        StatFs st = new StatFs("/data");
        long blks1 = getFreeStorageBlks(st);
        File cacheDir = mContext.getCacheDir();
        assertNotNull(cacheDir);
        createTestFiles1(cacheDir, "testtmpdir", 5);
        long blks2 = getFreeStorageBlks(st);
        Log.i(TAG, "blk1="+blks1+", blks2="+blks2);
        long diff = (blks1-blks2-2);
        if (!invokePMFreeApplicationCache(diff * st.getBlockSize())) {
            fail("Could not successfully invoke PackageManager free app cache API");
        }
        long blks3 = getFreeStorageBlks(st);
        //blks3 should be greater than blks2 and less than blks1
        if(!((blks3 <= blks1) && (blks3 >= blks2))) {
            failStr("Expected "+(blks1-blks2)+" number of blocks to be freed but freed only "
                    +(blks1-blks3));
        }
    }
    
    /**
     * This method opens an output file writes to it, opens the same file as an input 
     * stream, reads the contents and verifies the data that was written earlier can be read
     */
    public void openOutFileInAppFilesDir(File pFile, String pFileOut) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(pFile);
        } catch (FileNotFoundException e1) {
            failStr("Error when opening file "+e1);
            return;
        }
        try {
            fos.write(pFileOut.getBytes());
            fos.close();
        } catch (FileNotFoundException e) {
            failStr(e.getMessage());
        } catch (IOException e) {
            failStr(e.getMessage());
        } 
        int count = pFileOut.getBytes().length;
        byte[] buffer = new byte[count];
        try {
            FileInputStream fis = new FileInputStream(pFile);
            fis.read(buffer, 0, count);
            fis.close();
        } catch (FileNotFoundException e) {
            failStr("Failed when verifing output opening file "+e.getMessage());
        } catch (IOException e) {
            failStr("Failed when verifying output, reading from written file "+e);
        }
        String str = new String(buffer);
        assertEquals(str, pFileOut);
    } 
    
    /*
     * This test case verifies that output written to a file
     * using Context.openFileOutput has executed successfully.
     * The operation is verified by invoking Context.openFileInput
     */
    @MediumTest
    public void testAppFilesCreateFile() {
        String fileName = "testFile1.txt";
        String fileOut = "abcdefghijklmnopqrstuvwxyz";
        Context con = super.getContext();
        try {
            FileOutputStream fos = con.openFileOutput(fileName, Context.MODE_PRIVATE);
            fos.close();
        } catch (FileNotFoundException e) {
            failStr(e);
        } catch (IOException e) {
            failStr(e);
        }
    }
    
    @SmallTest
    public void testAppCacheCreateFile() {
        String fileName = "testFile1.txt";
        String fileOut = "abcdefghijklmnopqrstuvwxyz";
        Context con = super.getContext();
        File file = new File(con.getCacheDir(), fileName);
        openOutFileInAppFilesDir(file, fileOut);
        cleanUpCacheDirectory();
    }
    
    @MediumTest
    public void testAppCreateCacheFiles() {
        File cacheDir = mContext.getCacheDir();
        String testDirName = "testtmp";
        File testTmpDir = new File(cacheDir, testDirName);
        testTmpDir.mkdir();
        int numDirs = 3;
        File fileArr[] = new File[numDirs];
        for(int i = 0; i < numDirs; i++) {
            fileArr[i] = new File(testTmpDir, "dir"+(i+1));
            fileArr[i].mkdir();
        }
        byte buffer[] = getBuffer();
        Log.i(TAG, "Size of bufer="+buffer.length);
        for(int i = 0; i < numDirs; i++) {
            for(int j = 1; j <= (i); j++) {
                File file1 = new File(fileArr[i], "testFile"+j+".txt");
                FileOutputStream fos = null;
                try {
                    fos = new FileOutputStream(file1);
                    for(int k = 1; k < 10; k++) {
                        fos.write(buffer);
                    }
                    Log.i(TAG, "wrote 10K bytes to "+file1);
                    fos.close();
                } catch (FileNotFoundException e) {
                    Log.i(TAG, "Excetion ="+e);
                    fail("Error when creating outputstream "+e);
                } catch(IOException e) {
                    Log.i(TAG, "Excetion ="+e);
                    fail("Error when writing output "+e);
                }
            }
        }
    }
    
    byte[] getBuffer() {
        String sbuffer = "a";
        for(int i = 0; i < 10; i++) {
            sbuffer += sbuffer;
        }
        return sbuffer.getBytes();
    }

    long getFileNumBlocks(long fileSize, long blkSize) {
        long ret = fileSize/blkSize;
        if(ret*blkSize < fileSize) {
            ret++;
        }
        return ret;
    }

    //@LargeTest
    public void testAppCacheClear() {
        String dataDir="/data/data";
        StatFs st = new StatFs(dataDir);
        long blkSize = st.getBlockSize();
        long totBlks = st.getBlockCount();
        long availableBlks = st.getFreeBlocks();
        long thresholdBlks = (totBlks * THRESHOLD) / 100L;
        String testDirName = "testdir";
        //create directory in cache
        File testDir = new File(mContext.getCacheDir(),  testDirName);
        testDir.mkdirs();
        byte[] buffer = getBuffer();
        int i = 1;
        if(localLOGV) Log.i(TAG, "availableBlks="+availableBlks+", thresholdBlks="+thresholdBlks);
        long createdFileBlks = 0;
        int imax = 300;
        while((availableBlks > thresholdBlks) &&(i < imax)) {
            File testFile = new File(testDir, "testFile"+i+".txt");
            if(localLOGV) Log.i(TAG, "Creating "+i+"th test file "+testFile);
            int jmax = i;
            i++;
            FileOutputStream fos;
            try {
                fos = new FileOutputStream(testFile);
            } catch (FileNotFoundException e) {
                Log.i(TAG, "Failed creating test file:"+testFile);
                continue;
            }
            boolean err = false;
            for(int j = 1; j <= jmax;j++) {
                try {
                    fos.write(buffer);
                } catch (IOException e) {
                    Log.i(TAG, "Failed to write to file:"+testFile);
                    err = true;
                }
            }
            try {
                fos.close();
            } catch (IOException e) {
                Log.i(TAG, "Failed closing file:"+testFile);
            }
            if(err) {
                continue;
            }
            createdFileBlks += getFileNumBlocks(testFile.length(), blkSize);
            st.restat(dataDir);
            availableBlks = st.getFreeBlocks();
        }
        st.restat(dataDir);
        long availableBytes = st.getFreeBlocks()*blkSize;
        long shouldFree = (ACTUAL_THRESHOLD-THRESHOLD)*totBlks;
        //would have run out of memory
        //wait for some time and confirm cache is deleted
        try {
            Log.i(TAG, "Sleeping for 2 minutes...");
            Thread.sleep(2*60*1000);
        } catch (InterruptedException e) {
            fail("Exception when sleeping "+e);
        }
        boolean removedFlag = false;
        long existingFileBlks = 0;
        for(int k = 1; k <i; k++) {
            File testFile = new File(testDir, "testFile"+k+".txt");
            if(!testFile.exists()) {
                removedFlag = true;
                if(localLOGV) Log.i(TAG, testFile+" removed");
            }  else {
                existingFileBlks += getFileNumBlocks(testFile.length(), blkSize);
            }
        }
        if(localLOGV) Log.i(TAG, "createdFileBlks="+createdFileBlks+
                ", existingFileBlks="+existingFileBlks);
        long fileSize = createdFileBlks-existingFileBlks;
        //verify fileSize number of bytes have been cleared from cache
        if(localLOGV) Log.i(TAG, "deletedFileBlks="+fileSize+" shouldFreeBlks="+shouldFree);
        if((fileSize > (shouldFree-blkSize) && (fileSize < (shouldFree+blkSize)))) {
            Log.i(TAG, "passed");
        }
        assertTrue("Files should have been removed", removedFlag);
    }
    
    //createTestFiles(new File(super.getContext().getCacheDir(), "testtmp", "dir", 3)
    void createTestFiles1(File cacheDir, String testFilePrefix, int numTestFiles) {
        byte buffer[] = getBuffer();
        for(int i = 0; i < numTestFiles; i++) {
            File file1 = new File(cacheDir, testFilePrefix+i+".txt");
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(file1);
                for(int k = 1; k < 10; k++) {
                    fos.write(buffer);
               }
                fos.close();
            } catch (FileNotFoundException e) {
                Log.i(TAG, "Exception ="+e);
                fail("Error when creating outputstream "+e);
            } catch(IOException e) {
                Log.i(TAG, "Exception ="+e);
                fail("Error when writing output "+e);
            }
            try {
                //introduce sleep for 1 s to avoid common time stamps for files being created
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                fail("Exception when sleeping "+e);
            }
        }
    }

    void verifyTestFiles1(File cacheDir, String testFilePrefix, int numTestFiles) {
        List<String> files = new ArrayList<String>();
        for(int i = 0; i < numTestFiles; i++) {
            File file1 = new File(cacheDir, testFilePrefix+i+".txt");
            if(file1.exists()) {
                files.add(file1.getName());
            }
        }
        if (files.size() > 0) {
            fail("Files should have been deleted: "
                    + Arrays.toString(files.toArray(new String[files.size()])));
        }
    }

    void createTestFiles2(File cacheDir, String rootTestDirName, String subDirPrefix, int numDirs, String testFilePrefix) {
        Context con = super.getContext();
        File testTmpDir = new File(cacheDir, rootTestDirName);
        testTmpDir.mkdir();
        File fileArr[] = new File[numDirs];
        for(int i = 0; i < numDirs; i++) {
            fileArr[i] = new File(testTmpDir, subDirPrefix+(i+1));
            fileArr[i].mkdir();
        }
        byte buffer[] = getBuffer();
        for(int i = 0; i < numDirs; i++) {
            for(int j = 1; j <= (i); j++) {
                File file1 = new File(fileArr[i], testFilePrefix+j+".txt");
                FileOutputStream fos = null;
                try {
                    fos = new FileOutputStream(file1);
                    for(int k = 1; k < 10; k++) {
                        fos.write(buffer);
                    }
                    fos.close();
                } catch (FileNotFoundException e) {
                    Log.i(TAG, "Exception ="+e);
                    fail("Error when creating outputstream "+e);
                } catch(IOException e) {
                    Log.i(TAG, "Exception ="+e);
                    fail("Error when writing output "+e);
                }
                try {
                    //introduce sleep for 10 ms to avoid common time stamps for files being created
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    fail("Exception when sleeping "+e);
                }
            }
        }
    }
    
    class PackageDataObserver extends IPackageDataObserver.Stub {
        public boolean retValue = false;
        private boolean doneFlag = false;
        public void onRemoveCompleted(String packageName, boolean succeeded)
                throws RemoteException {
            synchronized(this) {
                retValue = succeeded;
                doneFlag = true;
                notifyAll();
            }
        }
        public boolean isDone() {
            return doneFlag;
        }
    }
    
    IPackageManager getPm() {
        return  IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
    }
    
    boolean invokePMDeleteAppCacheFiles() throws Exception {
        try {
            String packageName = mContext.getPackageName();
            PackageDataObserver observer = new PackageDataObserver();
            //wait on observer
            synchronized(observer) {
                getPm().deleteApplicationCacheFiles(packageName, observer);
                long waitTime = 0;
                while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) {
                    observer.wait(WAIT_TIME_INCR);
                    waitTime += WAIT_TIME_INCR;
                }
                if(!observer.isDone()) {
                    throw new Exception("timed out waiting for PackageDataObserver.onRemoveCompleted");
                }
            }
            return observer.retValue;
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e);
            return false;
        } catch (InterruptedException e) {
            Log.w(TAG, "InterruptedException :"+e);
            return false;
        }
    }
    
    boolean invokePMFreeApplicationCache(long idealStorageSize) throws Exception {
        try {
            String packageName = mContext.getPackageName();
            PackageDataObserver observer = new PackageDataObserver();
            //wait on observer
            synchronized(observer) {
                getPm().freeStorageAndNotify(idealStorageSize, observer);
                long waitTime = 0;
                while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) {
                    observer.wait(WAIT_TIME_INCR);
                    waitTime += WAIT_TIME_INCR;
                }
                if(!observer.isDone()) {
                    throw new Exception("timed out waiting for PackageDataObserver.onRemoveCompleted");
                }
            }
            return observer.retValue;
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e);
            return false;
        } catch (InterruptedException e) {
            Log.w(TAG, "InterruptedException :"+e);
            return false;
        }
    }

    boolean invokePMFreeStorage(long idealStorageSize, FreeStorageReceiver r, 
            PendingIntent pi) throws Exception {
        try {
            // Spin lock waiting for call back
            synchronized(r) {
                getPm().freeStorage(idealStorageSize, pi.getIntentSender());
                long waitTime = 0;
                while(!r.isDone() && (waitTime < MAX_WAIT_TIME)) {
                    r.wait(WAIT_TIME_INCR);
                    waitTime += WAIT_TIME_INCR;
                }
                if(!r.isDone()) {
                    throw new Exception("timed out waiting for call back from PendingIntent");
                }
            }
            return r.getResultCode() == 1;
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e);
            return false;
        } catch (InterruptedException e) {
            Log.w(TAG, "InterruptedException :"+e);
            return false;
        }
    }
    
    @LargeTest
    public void testDeleteAppCacheFiles() throws Exception {
        String testName="testDeleteAppCacheFiles";
        File cacheDir = mContext.getCacheDir();
        createTestFiles1(cacheDir, "testtmpdir", 5);
        assertTrue(invokePMDeleteAppCacheFiles());
        //confirm files dont exist
        verifyTestFiles1(cacheDir, "testtmpdir", 5);
    }

    class PackageStatsObserver extends IPackageStatsObserver.Stub {
        public boolean retValue = false;
        public PackageStats stats;
        private boolean doneFlag = false;
        
        public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
                throws RemoteException {
            synchronized(this) {
                retValue = succeeded;
                stats = pStats;
                doneFlag = true;
                notifyAll();
            }
        }
        public boolean isDone() {
            return doneFlag;
        }
    }
    
    public PackageStats invokePMGetPackageSizeInfo() throws Exception {
        try {
            String packageName = mContext.getPackageName();
            PackageStatsObserver observer = new PackageStatsObserver();
            //wait on observer
            synchronized(observer) {
                getPm().getPackageSizeInfo(packageName, UserHandle.myUserId(), observer);
                long waitTime = 0;
                while((!observer.isDone()) || (waitTime > MAX_WAIT_TIME) ) {
                    observer.wait(WAIT_TIME_INCR);
                    waitTime += WAIT_TIME_INCR;
                }
                if(!observer.isDone()) {
                    throw new Exception("Timed out waiting for PackageStatsObserver.onGetStatsCompleted");
                }
            }
            if(localLOGV) Log.i(TAG, "OBSERVER RET VALUES code="+observer.stats.codeSize+
                    ", data="+observer.stats.dataSize+", cache="+observer.stats.cacheSize);
            return observer.stats;
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e);
            return null;
        } catch (InterruptedException e) {
            Log.w(TAG, "InterruptedException :"+e);
            return null;
        }
    }
    
    @SmallTest
    public void testGetPackageSizeInfo() throws Exception {
        String testName="testGetPackageSizeInfo";
        PackageStats stats = invokePMGetPackageSizeInfo();
        assertTrue(stats!=null);
        //confirm result
        if(localLOGV) Log.i(TAG, "code="+stats.codeSize+", data="+stats.dataSize+
                ", cache="+stats.cacheSize);
    }
    
    @SmallTest
    public void testGetSystemSharedLibraryNames() throws Exception {
        try {
            String[] sharedLibs = getPm().getSystemSharedLibraryNames();
            if (localLOGV) {
                for (String str : sharedLibs) {
                    Log.i(TAG, str);
                }
            }
        } catch (RemoteException e) {
            fail("Failed invoking getSystemSharedLibraryNames with exception:" + e);
        }   
    }
    
    class FreeStorageReceiver extends BroadcastReceiver {
        public static final String ACTION_FREE = "com.android.unit_tests.testcallback";
        private boolean doneFlag = false;
        
        public boolean isDone() {
            return doneFlag;
        }
        
        @Override
        public void onReceive(Context context, Intent intent) {
            if(intent.getAction().equalsIgnoreCase(ACTION_FREE)) {
                if (localLOGV) Log.i(TAG, "Got notification: clear cache succeeded "+getResultCode());
                synchronized (this) {
                    doneFlag = true;
                    notifyAll();
                }
            }
        }
    }
    
    // TODO: flaky test, omit from LargeTest for now
    //@LargeTest
    public void testFreeStorage() throws Exception {
        boolean TRACKING = true;
        StatFs st = new StatFs("/data");
        long blks1 = getFreeStorageBlks(st);
        if(localLOGV || TRACKING) Log.i(TAG, "Available free blocks="+blks1);
        long availableMem = getFreeStorageSize(st);
        File cacheDir = mContext.getCacheDir();
        assertNotNull(cacheDir);
        createTestFiles1(cacheDir, "testtmpdir", 5);
        long blks2 = getFreeStorageBlks(st);
        if(localLOGV || TRACKING) Log.i(TAG, "Available blocks after writing test files in application cache="+blks2);
        // Create receiver and register it
        FreeStorageReceiver receiver = new FreeStorageReceiver();
        mContext.registerReceiver(receiver, new IntentFilter(FreeStorageReceiver.ACTION_FREE));
        PendingIntent pi = PendingIntent.getBroadcast(mContext,
                0,  new Intent(FreeStorageReceiver.ACTION_FREE), 0);
        // Invoke PackageManager api
        if (!invokePMFreeStorage(availableMem, receiver, pi)) {
            fail("Could not invoke PackageManager free storage API");
        }
        long blks3 = getFreeStorageBlks(st);
        if(localLOGV || TRACKING) Log.i(TAG, "Available blocks after freeing cache"+blks3);
        assertEquals(receiver.getResultCode(), 1);
        mContext.unregisterReceiver(receiver);
        // Verify result  
        verifyTestFiles1(cacheDir, "testtmpdir", 5);
    }
    
    /* utility method used to create observer and check async call back from PackageManager.
     * ClearApplicationUserData
     */
    boolean invokePMClearApplicationUserData() throws Exception {
        try {
            String packageName = mContext.getPackageName();
            PackageDataObserver observer = new PackageDataObserver();
            //wait on observer
            synchronized(observer) {
                getPm().clearApplicationUserData(packageName, observer, 0 /* TODO: Other users */);
                long waitTime = 0;
                while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) {
                    observer.wait(WAIT_TIME_INCR);
                    waitTime += WAIT_TIME_INCR;
                }
                if(!observer.isDone()) {
                    throw new Exception("timed out waiting for PackageDataObserver.onRemoveCompleted");
                }
            }
            return observer.retValue;
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e);
            return false;
        } catch (InterruptedException e) {
            Log.w(TAG, "InterruptedException :"+e);
            return false;
        }
    }
    
    void verifyUserDataCleared(File pDir) {
        if(localLOGV) Log.i(TAG, "Verifying "+pDir);
        if(pDir == null) {
            return;
        }
        String fileList[] = pDir.list();
        if(fileList == null) {
            return;
        }
        int imax = fileList.length;
       //look recursively in user data dir
        for(int i = 0; i < imax; i++) {
            if(localLOGV) Log.i(TAG, "Found entry "+fileList[i]+ "in "+pDir);
            if("lib".equalsIgnoreCase(fileList[i])) {
                if(localLOGV) Log.i(TAG, "Ignoring lib directory");
                continue;
            }
            fail(pDir+" should be empty or contain only lib subdirectory. Found "+fileList[i]);
        }
    }
    
    File getDataDir() {
        try {
            ApplicationInfo appInfo = getPm().getApplicationInfo(mContext.getPackageName(), 0,
                    UserHandle.myUserId());
            return new File(appInfo.dataDir);
        } catch (RemoteException e) {
            throw new RuntimeException("Pacakge manager dead", e);
        }
    }
    
    @LargeTest
    public void testClearApplicationUserDataWithTestData() throws Exception {
        File cacheDir = mContext.getCacheDir();
        createTestFiles1(cacheDir, "testtmpdir", 5);
        if(localLOGV) {
            Log.i(TAG, "Created test data Waiting for 60seconds before continuing");
            Thread.sleep(60*1000);
        }
        assertTrue(invokePMClearApplicationUserData());
        //confirm files dont exist
        verifyUserDataCleared(getDataDir());
    }
    
    @SmallTest
    public void testClearApplicationUserDataWithNoTestData() throws Exception {
        assertTrue(invokePMClearApplicationUserData());
        //confirm files dont exist
        verifyUserDataCleared(getDataDir());
    }
    
    @LargeTest
    public void testClearApplicationUserDataNoObserver() throws Exception {
        getPm().clearApplicationUserData(mContext.getPackageName(), null, UserHandle.myUserId());
        //sleep for 1 minute
        Thread.sleep(60*1000);
        //confirm files dont exist
        verifyUserDataCleared(getDataDir());
    }
    
}
