The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 | |
Brett Chabot | 0dc59e7 | 2010-04-01 18:21:38 -0700 | [diff] [blame] | 17 | package android.content.pm; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 18 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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; |
Brett Chabot | f76c56b | 2010-07-26 17:28:17 -0700 | [diff] [blame] | 24 | import android.os.RemoteException; |
| 25 | import android.os.ServiceManager; |
| 26 | import android.os.StatFs; |
Dianne Hackborn | f02b60a | 2012-08-16 10:48:27 -0700 | [diff] [blame] | 27 | import android.os.UserHandle; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 32 | import android.util.Log; |
Brett Chabot | f76c56b | 2010-07-26 17:28:17 -0700 | [diff] [blame] | 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; |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 39 | import java.util.ArrayList; |
| 40 | import java.util.Arrays; |
| 41 | import java.util.List; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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; |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 48 | private static final long THRESHOLD=5; |
| 49 | private static final long ACTUAL_THRESHOLD=10; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 | } |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 101 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 102 | void failStr(String errMsg) { |
| 103 | Log.w(TAG, "errMsg="+errMsg); |
| 104 | fail(errMsg); |
| 105 | } |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 106 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 107 | void failStr(Exception e) { |
| 108 | Log.w(TAG, "e.getMessage="+e.getMessage()); |
| 109 | Log.w(TAG, "e="+e); |
| 110 | } |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 111 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 112 | long getFreeStorageBlks(StatFs st) { |
| 113 | st.restat("/data"); |
| 114 | return st.getFreeBlocks(); |
| 115 | } |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 116 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 117 | long getFreeStorageSize(StatFs st) { |
| 118 | st.restat("/data"); |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 119 | return (long) st.getFreeBlocks() * (long) st.getBlockSize(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 120 | } |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 121 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 134 | if (!invokePMFreeApplicationCache(availableMem)) { |
| 135 | fail("Could not successfully invoke PackageManager free app cache API"); |
| 136 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 137 | long blks3 = getFreeStorageBlks(st); |
| 138 | if(localLOGV || TRACKING) Log.i(TAG, "blks3="+blks3); |
| 139 | verifyTestFiles1(cacheDir, "testtmpdir", 5); |
| 140 | } |
Suchi Amalapurapu | f654a48 | 2010-03-23 09:46:22 -0700 | [diff] [blame] | 141 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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); |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 151 | if (!invokePMFreeApplicationCache(diff * st.getBlockSize())) { |
| 152 | fail("Could not successfully invoke PackageManager free app cache API"); |
| 153 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 | } |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 270 | |
| 271 | long getFileNumBlocks(long fileSize, long blkSize) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 272 | long ret = fileSize/blkSize; |
| 273 | if(ret*blkSize < fileSize) { |
| 274 | ret++; |
| 275 | } |
| 276 | return ret; |
| 277 | } |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 278 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 279 | //@LargeTest |
| 280 | public void testAppCacheClear() { |
| 281 | String dataDir="/data/data"; |
| 282 | StatFs st = new StatFs(dataDir); |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 283 | long blkSize = st.getBlockSize(); |
| 284 | long totBlks = st.getBlockCount(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 285 | long availableBlks = st.getFreeBlocks(); |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 286 | long thresholdBlks = (totBlks * THRESHOLD) / 100L; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 | } |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 359 | assertTrue("Files should have been removed", removedFlag); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 | } |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 389 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 390 | void verifyTestFiles1(File cacheDir, String testFilePrefix, int numTestFiles) { |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 391 | List<String> files = new ArrayList<String>(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 392 | for(int i = 0; i < numTestFiles; i++) { |
| 393 | File file1 = new File(cacheDir, testFilePrefix+i+".txt"); |
| 394 | if(file1.exists()) { |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 395 | files.add(file1.getName()); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 396 | } |
| 397 | } |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 398 | if (files.size() > 0) { |
| 399 | fail("Files should have been deleted: " |
| 400 | + Arrays.toString(files.toArray(new String[files.size()]))); |
| 401 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 402 | } |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 403 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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) { |
Suchi Amalapurapu | bc806f6 | 2009-06-17 15:18:19 -0700 | [diff] [blame] | 518 | getPm().freeStorage(idealStorageSize, pi.getIntentSender()); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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) { |
Dianne Hackborn | 0c38049 | 2012-08-20 17:23:30 -0700 | [diff] [blame] | 573 | getPm().getPackageSizeInfo(packageName, UserHandle.myUserId(), observer); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 | |
Brett Chabot | f76c56b | 2010-07-26 17:28:17 -0700 | [diff] [blame] | 639 | // TODO: flaky test, omit from LargeTest for now |
| 640 | //@LargeTest |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |
Kenny Root | 6c46760 | 2011-01-12 13:09:15 -0800 | [diff] [blame] | 658 | if (!invokePMFreeStorage(availableMem, receiver, pi)) { |
| 659 | fail("Could not invoke PackageManager free storage API"); |
| 660 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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) { |
Amith Yamasani | 483f3b0 | 2012-03-13 16:08:00 -0700 | [diff] [blame] | 678 | getPm().clearApplicationUserData(packageName, observer, 0 /* TODO: Other users */); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 { |
Amith Yamasani | 483f3b0 | 2012-03-13 16:08:00 -0700 | [diff] [blame] | 721 | ApplicationInfo appInfo = getPm().getApplicationInfo(mContext.getPackageName(), 0, |
Dianne Hackborn | f02b60a | 2012-08-16 10:48:27 -0700 | [diff] [blame] | 722 | UserHandle.myUserId()); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 { |
Dianne Hackborn | f02b60a | 2012-08-16 10:48:27 -0700 | [diff] [blame] | 751 | getPm().clearApplicationUserData(mContext.getPackageName(), null, UserHandle.myUserId()); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 752 | //sleep for 1 minute |
| 753 | Thread.sleep(60*1000); |
| 754 | //confirm files dont exist |
| 755 | verifyUserDataCleared(getDataDir()); |
| 756 | } |
| 757 | |
| 758 | } |