1 // 2 // Copyright 2011 The Android Open Source Project 3 // 4 // Implementation file for CrunchCache 5 // This file defines functions laid out and documented in 6 // CrunchCache.h 7 8 #include <utils/Compat.h> 9 #include <utils/Vector.h> 10 #include <utils/String8.h> 11 12 #include "DirectoryWalker.h" 13 #include "FileFinder.h" 14 #include "CacheUpdater.h" 15 #include "CrunchCache.h" 16 17 using namespace android; 18 19 CrunchCache::CrunchCache(String8 sourcePath, String8 destPath, FileFinder* ff) 20 : mSourcePath(sourcePath), mDestPath(destPath), mSourceFiles(0), mDestFiles(0), mFileFinder(ff) 21 { 22 // We initialize the default value to return to 0 so if a file doesn't exist 23 // then all files are automatically "newer" than it. 24 25 // Set file extensions to look for. Right now just pngs. 26 mExtensions.push(String8(".png")); 27 28 // Load files into our data members 29 loadFiles(); 30 } 31 32 size_t CrunchCache::crunch(CacheUpdater* cu, bool forceOverwrite) 33 { 34 size_t numFilesUpdated = 0; 35 36 // Iterate through the source files and compare to cache. 37 // After processing a file, remove it from the source files and 38 // from the dest files. 39 // We're done when we're out of files in source. 40 String8 relativePath; 41 while (mSourceFiles.size() > 0) { 42 // Get the full path to the source file, then convert to a c-string 43 // and offset our beginning pointer to the length of the sourcePath 44 // This efficiently strips the source directory prefix from our path. 45 // Also, String8 doesn't have a substring method so this is what we've 46 // got to work with. 47 const char* rPathPtr = mSourceFiles.keyAt(0).string()+mSourcePath.length(); 48 // Strip leading slash if present 49 int offset = 0; 50 if (rPathPtr[0] == OS_PATH_SEPARATOR) 51 offset = 1; 52 relativePath = String8(rPathPtr + offset); 53 54 if (forceOverwrite || needsUpdating(relativePath)) { 55 cu->processImage(mSourcePath.appendPathCopy(relativePath), 56 mDestPath.appendPathCopy(relativePath)); 57 numFilesUpdated++; 58 // crunchFile(relativePath); 59 } 60 // Delete this file from the source files and (if it exists) from the 61 // dest files. 62 mSourceFiles.removeItemsAt(0); 63 mDestFiles.removeItem(mDestPath.appendPathCopy(relativePath)); 64 } 65 66 // Iterate through what's left of destFiles and delete leftovers 67 while (mDestFiles.size() > 0) { 68 cu->deleteFile(mDestFiles.keyAt(0)); 69 mDestFiles.removeItemsAt(0); 70 } 71 72 // Update our knowledge of the files cache 73 // both source and dest should be empty by now. 74 loadFiles(); 75 76 return numFilesUpdated; 77 } 78 79 void CrunchCache::loadFiles() 80 { 81 // Clear out our data structures to avoid putting in duplicates 82 mSourceFiles.clear(); 83 mDestFiles.clear(); 84 85 // Make a directory walker that points to the system. 86 DirectoryWalker* dw = new SystemDirectoryWalker(); 87 88 // Load files in the source directory 89 mFileFinder->findFiles(mSourcePath, mExtensions, mSourceFiles,dw); 90 91 // Load files in the destination directory 92 mFileFinder->findFiles(mDestPath,mExtensions,mDestFiles,dw); 93 94 delete dw; 95 } 96 97 bool CrunchCache::needsUpdating(const String8& relativePath) const 98 { 99 // Retrieve modification dates for this file entry under the source and 100 // cache directory trees. The vectors will return a modification date of 0 101 // if the file doesn't exist. 102 time_t sourceDate = mSourceFiles.valueFor(mSourcePath.appendPathCopy(relativePath)); 103 time_t destDate = mDestFiles.valueFor(mDestPath.appendPathCopy(relativePath)); 104 return sourceDate > destDate; 105 } 106