AssetManager.cpp revision 16c4d154dca43c662571129af31b27433b919a32
116c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Copyright (C) 2006 The Android Open Source Project 316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * you may not use this file except in compliance with the License. 616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * You may obtain a copy of the License at 716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 1016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Unless required by applicable law or agreed to in writing, software 1116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 1216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * See the License for the specific language governing permissions and 1416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * limitations under the License. 1516c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 1616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 1716c4d154dca43c662571129af31b27433b919a32Adam Lesinski// 1816c4d154dca43c662571129af31b27433b919a32Adam Lesinski// Provide access to read-only assets. 1916c4d154dca43c662571129af31b27433b919a32Adam Lesinski// 2016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 2116c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define LOG_TAG "asset" 2216c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define ATRACE_TAG ATRACE_TAG_RESOURCES 2316c4d154dca43c662571129af31b27433b919a32Adam Lesinski//#define LOG_NDEBUG 0 2416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 2516c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <androidfw/Asset.h> 2616c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <androidfw/AssetDir.h> 2716c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <androidfw/AssetManager.h> 2816c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <androidfw/misc.h> 2916c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <androidfw/ResourceTypes.h> 3016c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <androidfw/ZipFileRO.h> 3116c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <utils/Atomic.h> 3216c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <utils/Log.h> 3316c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <utils/String8.h> 3416c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <utils/String8.h> 3516c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <utils/threads.h> 3616c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <utils/Timers.h> 3716c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifdef HAVE_ANDROID_OS 3816c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <cutils/trace.h> 3916c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 4016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 4116c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <assert.h> 4216c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <dirent.h> 4316c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <errno.h> 4416c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <fcntl.h> 4516c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <strings.h> 4616c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <sys/stat.h> 4716c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <unistd.h> 4816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 4916c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifndef TEMP_FAILURE_RETRY 5016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* Used to retry syscalls that can return EINTR. */ 5116c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define TEMP_FAILURE_RETRY(exp) ({ \ 5216c4d154dca43c662571129af31b27433b919a32Adam Lesinski typeof (exp) _rc; \ 5316c4d154dca43c662571129af31b27433b919a32Adam Lesinski do { \ 5416c4d154dca43c662571129af31b27433b919a32Adam Lesinski _rc = (exp); \ 5516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } while (_rc == -1 && errno == EINTR); \ 5616c4d154dca43c662571129af31b27433b919a32Adam Lesinski _rc; }) 5716c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 5816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 5916c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifdef HAVE_ANDROID_OS 6016c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define MY_TRACE_BEGIN(x) ATRACE_BEGIN(x) 6116c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define MY_TRACE_END() ATRACE_END() 6216c4d154dca43c662571129af31b27433b919a32Adam Lesinski#else 6316c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define MY_TRACE_BEGIN(x) 6416c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define MY_TRACE_END() 6516c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 6616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 6716c4d154dca43c662571129af31b27433b919a32Adam Lesinskiusing namespace android; 6816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 6916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 7016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Names for default app, locale, and vendor. We might want to change 7116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * these to be an actual locale, e.g. always use en-US as the default. 7216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 7316c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kDefaultLocale = "default"; 7416c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kDefaultVendor = "default"; 7516c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kAssetsRoot = "assets"; 7616c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kAppZipName = NULL; //"classes.jar"; 7716c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kSystemAssets = "framework/framework-res.apk"; 7816c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kIdmapCacheDir = "resource-cache"; 7916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 8016c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kExcludeExtension = ".EXCLUDE"; 8116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 8216c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic Asset* const kExcludedAsset = (Asset*) 0xd000000d; 8316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 8416c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic volatile int32_t gCount = 0; 8516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 8616c4d154dca43c662571129af31b27433b919a32Adam Lesinskinamespace { 8716c4d154dca43c662571129af31b27433b919a32Adam Lesinski // Transform string /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap 8816c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 idmapPathForPackagePath(const String8& pkgPath) 8916c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 9016c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* root = getenv("ANDROID_DATA"); 9116c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set"); 9216c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(root); 9316c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(kIdmapCacheDir); 9416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 9516c4d154dca43c662571129af31b27433b919a32Adam Lesinski char buf[256]; // 256 chars should be enough for anyone... 9616c4d154dca43c662571129af31b27433b919a32Adam Lesinski strncpy(buf, pkgPath.string(), 255); 9716c4d154dca43c662571129af31b27433b919a32Adam Lesinski buf[255] = '\0'; 9816c4d154dca43c662571129af31b27433b919a32Adam Lesinski char* filename = buf; 9916c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (*filename && *filename == '/') { 10016c4d154dca43c662571129af31b27433b919a32Adam Lesinski ++filename; 10116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 10216c4d154dca43c662571129af31b27433b919a32Adam Lesinski char* p = filename; 10316c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (*p) { 10416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (*p == '/') { 10516c4d154dca43c662571129af31b27433b919a32Adam Lesinski *p = '@'; 10616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 10716c4d154dca43c662571129af31b27433b919a32Adam Lesinski ++p; 10816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 10916c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(filename); 11016c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.append("@idmap"); 11116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 11216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return path; 11316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 11416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 11516c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 11616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Like strdup(), but uses C++ "new" operator instead of malloc. 11716c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 11816c4d154dca43c662571129af31b27433b919a32Adam Lesinski static char* strdupNew(const char* str) 11916c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 12016c4d154dca43c662571129af31b27433b919a32Adam Lesinski char* newStr; 12116c4d154dca43c662571129af31b27433b919a32Adam Lesinski int len; 12216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 12316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (str == NULL) 12416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 12516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 12616c4d154dca43c662571129af31b27433b919a32Adam Lesinski len = strlen(str); 12716c4d154dca43c662571129af31b27433b919a32Adam Lesinski newStr = new char[len+1]; 12816c4d154dca43c662571129af31b27433b919a32Adam Lesinski memcpy(newStr, str, len+1); 12916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 13016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return newStr; 13116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 13216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 13316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 13416c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 13516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * =========================================================================== 13616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * AssetManager 13716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * =========================================================================== 13816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 13916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 14016c4d154dca43c662571129af31b27433b919a32Adam Lesinskiint32_t AssetManager::getGlobalCount() 14116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 14216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return gCount; 14316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 14416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 14516c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetManager::AssetManager(CacheMode cacheMode) 14616c4d154dca43c662571129af31b27433b919a32Adam Lesinski : mLocale(NULL), mVendor(NULL), 14716c4d154dca43c662571129af31b27433b919a32Adam Lesinski mResources(NULL), mConfig(new ResTable_config), 14816c4d154dca43c662571129af31b27433b919a32Adam Lesinski mCacheMode(cacheMode), mCacheValid(false) 14916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 15016c4d154dca43c662571129af31b27433b919a32Adam Lesinski int count = android_atomic_inc(&gCount)+1; 15116c4d154dca43c662571129af31b27433b919a32Adam Lesinski //ALOGI("Creating AssetManager %p #%d\n", this, count); 15216c4d154dca43c662571129af31b27433b919a32Adam Lesinski memset(mConfig, 0, sizeof(ResTable_config)); 15316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 15416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 15516c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetManager::~AssetManager(void) 15616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 15716c4d154dca43c662571129af31b27433b919a32Adam Lesinski int count = android_atomic_dec(&gCount); 15816c4d154dca43c662571129af31b27433b919a32Adam Lesinski //ALOGI("Destroying AssetManager in %p #%d\n", this, count); 15916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 16016c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete mConfig; 16116c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete mResources; 16216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 16316c4d154dca43c662571129af31b27433b919a32Adam Lesinski // don't have a String class yet, so make sure we clean up 16416c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete[] mLocale; 16516c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete[] mVendor; 16616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 16716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 16816c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::addAssetPath(const String8& path, void** cookie) 16916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 17016c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 17116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 17216c4d154dca43c662571129af31b27433b919a32Adam Lesinski asset_path ap; 17316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 17416c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 realPath(path); 17516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (kAppZipName) { 17616c4d154dca43c662571129af31b27433b919a32Adam Lesinski realPath.appendPath(kAppZipName); 17716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 17816c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.type = ::getFileType(realPath.string()); 17916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type == kFileTypeRegular) { 18016c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.path = realPath; 18116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 18216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.path = path; 18316c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.type = ::getFileType(path.string()); 18416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type != kFileTypeDirectory && ap.type != kFileTypeRegular) { 18516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("Asset path %s is neither a directory nor file (type=%d).", 18616c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.string(), (int)ap.type); 18716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 18816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 18916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 19016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 19116c4d154dca43c662571129af31b27433b919a32Adam Lesinski // Skip if we have it already. 19216c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (size_t i=0; i<mAssetPaths.size(); i++) { 19316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mAssetPaths[i].path == ap.path) { 19416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (cookie) { 19516c4d154dca43c662571129af31b27433b919a32Adam Lesinski *cookie = (void*)(i+1); 19616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 19716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 19816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 19916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 20016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 20116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("In %p Asset %s path: %s", this, 20216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.type == kFileTypeDirectory ? "dir" : "zip", ap.path.string()); 20316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 20416c4d154dca43c662571129af31b27433b919a32Adam Lesinski mAssetPaths.add(ap); 20516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 20616c4d154dca43c662571129af31b27433b919a32Adam Lesinski // new paths are always added at the end 20716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (cookie) { 20816c4d154dca43c662571129af31b27433b919a32Adam Lesinski *cookie = (void*)mAssetPaths.size(); 20916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 21016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 21116c4d154dca43c662571129af31b27433b919a32Adam Lesinski // add overlay packages for /system/framework; apps are handled by the 21216c4d154dca43c662571129af31b27433b919a32Adam Lesinski // (Java) package manager 21316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (strncmp(path.string(), "/system/framework/", 18) == 0) { 21416c4d154dca43c662571129af31b27433b919a32Adam Lesinski // When there is an environment variable for /vendor, this 21516c4d154dca43c662571129af31b27433b919a32Adam Lesinski // should be changed to something similar to how ANDROID_ROOT 21616c4d154dca43c662571129af31b27433b919a32Adam Lesinski // and ANDROID_DATA are used in this file. 21716c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 overlayPath("/vendor/overlay/framework/"); 21816c4d154dca43c662571129af31b27433b919a32Adam Lesinski overlayPath.append(path.getPathLeaf()); 21916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (TEMP_FAILURE_RETRY(access(overlayPath.string(), R_OK)) == 0) { 22016c4d154dca43c662571129af31b27433b919a32Adam Lesinski asset_path oap; 22116c4d154dca43c662571129af31b27433b919a32Adam Lesinski oap.path = overlayPath; 22216c4d154dca43c662571129af31b27433b919a32Adam Lesinski oap.type = ::getFileType(overlayPath.string()); 22316c4d154dca43c662571129af31b27433b919a32Adam Lesinski bool addOverlay = (oap.type == kFileTypeRegular); // only .apks supported as overlay 22416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (addOverlay) { 22516c4d154dca43c662571129af31b27433b919a32Adam Lesinski oap.idmap = idmapPathForPackagePath(overlayPath); 22616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 22716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (isIdmapStaleLocked(ap.path, oap.path, oap.idmap)) { 22816c4d154dca43c662571129af31b27433b919a32Adam Lesinski addOverlay = createIdmapFileLocked(ap.path, oap.path, oap.idmap); 22916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 23016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 23116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (addOverlay) { 23216c4d154dca43c662571129af31b27433b919a32Adam Lesinski mAssetPaths.add(oap); 23316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 23416c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("failed to add overlay package %s\n", overlayPath.string()); 23516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 23616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 23716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 23816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 23916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 24016c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 24116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 24216c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath, 24316c4d154dca43c662571129af31b27433b919a32Adam Lesinski const String8& idmapPath) 24416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 24516c4d154dca43c662571129af31b27433b919a32Adam Lesinski struct stat st; 24616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (TEMP_FAILURE_RETRY(stat(idmapPath.string(), &st)) == -1) { 24716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (errno == ENOENT) { 24816c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; // non-existing idmap is always stale 24916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 25016c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("failed to stat file %s: %s\n", idmapPath.string(), strerror(errno)); 25116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 25216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 25316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 25416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (st.st_size < ResTable::IDMAP_HEADER_SIZE_BYTES) { 25516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("file %s has unexpectedly small size=%zd\n", idmapPath.string(), (size_t)st.st_size); 25616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 25716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 25816c4d154dca43c662571129af31b27433b919a32Adam Lesinski int fd = TEMP_FAILURE_RETRY(::open(idmapPath.string(), O_RDONLY)); 25916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (fd == -1) { 26016c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("failed to open file %s: %s\n", idmapPath.string(), strerror(errno)); 26116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 26216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 26316c4d154dca43c662571129af31b27433b919a32Adam Lesinski char buf[ResTable::IDMAP_HEADER_SIZE_BYTES]; 26416c4d154dca43c662571129af31b27433b919a32Adam Lesinski ssize_t bytesLeft = ResTable::IDMAP_HEADER_SIZE_BYTES; 26516c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (;;) { 26616c4d154dca43c662571129af31b27433b919a32Adam Lesinski ssize_t r = TEMP_FAILURE_RETRY(read(fd, buf + ResTable::IDMAP_HEADER_SIZE_BYTES - bytesLeft, 26716c4d154dca43c662571129af31b27433b919a32Adam Lesinski bytesLeft)); 26816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (r < 0) { 26916c4d154dca43c662571129af31b27433b919a32Adam Lesinski TEMP_FAILURE_RETRY(close(fd)); 27016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 27116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 27216c4d154dca43c662571129af31b27433b919a32Adam Lesinski bytesLeft -= r; 27316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (bytesLeft == 0) { 27416c4d154dca43c662571129af31b27433b919a32Adam Lesinski break; 27516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 27616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 27716c4d154dca43c662571129af31b27433b919a32Adam Lesinski TEMP_FAILURE_RETRY(close(fd)); 27816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 27916c4d154dca43c662571129af31b27433b919a32Adam Lesinski uint32_t cachedOriginalCrc, cachedOverlayCrc; 28016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (!ResTable::getIdmapInfo(buf, ResTable::IDMAP_HEADER_SIZE_BYTES, 28116c4d154dca43c662571129af31b27433b919a32Adam Lesinski &cachedOriginalCrc, &cachedOverlayCrc)) { 28216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 28316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 28416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 28516c4d154dca43c662571129af31b27433b919a32Adam Lesinski uint32_t actualOriginalCrc, actualOverlayCrc; 28616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (!getZipEntryCrcLocked(originalPath, "resources.arsc", &actualOriginalCrc)) { 28716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 28816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 28916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (!getZipEntryCrcLocked(overlayPath, "resources.arsc", &actualOverlayCrc)) { 29016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 29116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 29216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return cachedOriginalCrc != actualOriginalCrc || cachedOverlayCrc != actualOverlayCrc; 29316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 29416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 29516c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::getZipEntryCrcLocked(const String8& zipPath, const char* entryFilename, 29616c4d154dca43c662571129af31b27433b919a32Adam Lesinski uint32_t* pCrc) 29716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 29816c4d154dca43c662571129af31b27433b919a32Adam Lesinski asset_path ap; 29916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.path = zipPath; 30016c4d154dca43c662571129af31b27433b919a32Adam Lesinski const ZipFileRO* zip = getZipFileLocked(ap); 30116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (zip == NULL) { 30216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 30316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 30416c4d154dca43c662571129af31b27433b919a32Adam Lesinski const ZipEntryRO entry = zip->findEntryByName(entryFilename); 30516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (entry == NULL) { 30616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 30716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 30816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (!zip->getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, (long*)pCrc)) { 30916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 31016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 31116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 31216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 31316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 31416c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::createIdmapFileLocked(const String8& originalPath, const String8& overlayPath, 31516c4d154dca43c662571129af31b27433b919a32Adam Lesinski const String8& idmapPath) 31616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 31716c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGD("%s: originalPath=%s overlayPath=%s idmapPath=%s\n", 31816c4d154dca43c662571129af31b27433b919a32Adam Lesinski __FUNCTION__, originalPath.string(), overlayPath.string(), idmapPath.string()); 31916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ResTable tables[2]; 32016c4d154dca43c662571129af31b27433b919a32Adam Lesinski const String8* paths[2] = { &originalPath, &overlayPath }; 32116c4d154dca43c662571129af31b27433b919a32Adam Lesinski uint32_t originalCrc, overlayCrc; 32216c4d154dca43c662571129af31b27433b919a32Adam Lesinski bool retval = false; 32316c4d154dca43c662571129af31b27433b919a32Adam Lesinski ssize_t offset = 0; 32416c4d154dca43c662571129af31b27433b919a32Adam Lesinski int fd = 0; 32516c4d154dca43c662571129af31b27433b919a32Adam Lesinski uint32_t* data = NULL; 32616c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t size; 32716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 32816c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (int i = 0; i < 2; ++i) { 32916c4d154dca43c662571129af31b27433b919a32Adam Lesinski asset_path ap; 33016c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.type = kFileTypeRegular; 33116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.path = *paths[i]; 33216c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap); 33316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ass == NULL) { 33416c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("failed to find resources.arsc in %s\n", ap.path.string()); 33516c4d154dca43c662571129af31b27433b919a32Adam Lesinski goto error; 33616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 33716c4d154dca43c662571129af31b27433b919a32Adam Lesinski tables[i].add(ass, (void*)1, false); 33816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 33916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 34016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (!getZipEntryCrcLocked(originalPath, "resources.arsc", &originalCrc)) { 34116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("failed to retrieve crc for resources.arsc in %s\n", originalPath.string()); 34216c4d154dca43c662571129af31b27433b919a32Adam Lesinski goto error; 34316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 34416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (!getZipEntryCrcLocked(overlayPath, "resources.arsc", &overlayCrc)) { 34516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("failed to retrieve crc for resources.arsc in %s\n", overlayPath.string()); 34616c4d154dca43c662571129af31b27433b919a32Adam Lesinski goto error; 34716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 34816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 34916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (tables[0].createIdmap(tables[1], originalCrc, overlayCrc, 35016c4d154dca43c662571129af31b27433b919a32Adam Lesinski (void**)&data, &size) != NO_ERROR) { 35116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("failed to generate idmap data for file %s\n", idmapPath.string()); 35216c4d154dca43c662571129af31b27433b919a32Adam Lesinski goto error; 35316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 35416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 35516c4d154dca43c662571129af31b27433b919a32Adam Lesinski // This should be abstracted (eg replaced by a stand-alone 35616c4d154dca43c662571129af31b27433b919a32Adam Lesinski // application like dexopt, triggered by something equivalent to 35716c4d154dca43c662571129af31b27433b919a32Adam Lesinski // installd). 35816c4d154dca43c662571129af31b27433b919a32Adam Lesinski fd = TEMP_FAILURE_RETRY(::open(idmapPath.string(), O_WRONLY | O_CREAT | O_TRUNC, 0644)); 35916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (fd == -1) { 36016c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("failed to write idmap file %s (open: %s)\n", idmapPath.string(), strerror(errno)); 36116c4d154dca43c662571129af31b27433b919a32Adam Lesinski goto error_free; 36216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 36316c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (;;) { 36416c4d154dca43c662571129af31b27433b919a32Adam Lesinski ssize_t written = TEMP_FAILURE_RETRY(write(fd, data + offset, size)); 36516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (written < 0) { 36616c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("failed to write idmap file %s (write: %s)\n", idmapPath.string(), 36716c4d154dca43c662571129af31b27433b919a32Adam Lesinski strerror(errno)); 36816c4d154dca43c662571129af31b27433b919a32Adam Lesinski goto error_close; 36916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 37016c4d154dca43c662571129af31b27433b919a32Adam Lesinski size -= (size_t)written; 37116c4d154dca43c662571129af31b27433b919a32Adam Lesinski offset += written; 37216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (size == 0) { 37316c4d154dca43c662571129af31b27433b919a32Adam Lesinski break; 37416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 37516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 37616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 37716c4d154dca43c662571129af31b27433b919a32Adam Lesinski retval = true; 37816c4d154dca43c662571129af31b27433b919a32Adam Lesinskierror_close: 37916c4d154dca43c662571129af31b27433b919a32Adam Lesinski TEMP_FAILURE_RETRY(close(fd)); 38016c4d154dca43c662571129af31b27433b919a32Adam Lesinskierror_free: 38116c4d154dca43c662571129af31b27433b919a32Adam Lesinski free(data); 38216c4d154dca43c662571129af31b27433b919a32Adam Lesinskierror: 38316c4d154dca43c662571129af31b27433b919a32Adam Lesinski return retval; 38416c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 38516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 38616c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::addDefaultAssets() 38716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 38816c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* root = getenv("ANDROID_ROOT"); 38916c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_ROOT not set"); 39016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 39116c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(root); 39216c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(kSystemAssets); 39316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 39416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return addAssetPath(path, NULL); 39516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 39616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 39716c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid* AssetManager::nextAssetPath(void* cookie) const 39816c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 39916c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 40016c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t next = ((size_t)cookie)+1; 40116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return next > mAssetPaths.size() ? NULL : (void*)next; 40216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 40316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 40416c4d154dca43c662571129af31b27433b919a32Adam LesinskiString8 AssetManager::getAssetPath(void* cookie) const 40516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 40616c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 40716c4d154dca43c662571129af31b27433b919a32Adam Lesinski const size_t which = ((size_t)cookie)-1; 40816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (which < mAssetPaths.size()) { 40916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mAssetPaths[which].path; 41016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 41116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return String8(); 41216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 41316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 41416c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 41516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Set the current locale. Use NULL to indicate no locale. 41616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 41716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Close and reopen Zip archives as appropriate, and reset cached 41816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * information in the locale-specific sections of the tree. 41916c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 42016c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::setLocale(const char* locale) 42116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 42216c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 42316c4d154dca43c662571129af31b27433b919a32Adam Lesinski setLocaleLocked(locale); 42416c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 42516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 42616c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::setLocaleLocked(const char* locale) 42716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 42816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mLocale != NULL) { 42916c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* previously set, purge cached data */ 43016c4d154dca43c662571129af31b27433b919a32Adam Lesinski purgeFileNameCacheLocked(); 43116c4d154dca43c662571129af31b27433b919a32Adam Lesinski //mZipSet.purgeLocale(); 43216c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete[] mLocale; 43316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 43416c4d154dca43c662571129af31b27433b919a32Adam Lesinski mLocale = strdupNew(locale); 43516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 43616c4d154dca43c662571129af31b27433b919a32Adam Lesinski updateResourceParamsLocked(); 43716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 43816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 43916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 44016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Set the current vendor. Use NULL to indicate no vendor. 44116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 44216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Close and reopen Zip archives as appropriate, and reset cached 44316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * information in the vendor-specific sections of the tree. 44416c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 44516c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::setVendor(const char* vendor) 44616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 44716c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 44816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 44916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mVendor != NULL) { 45016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* previously set, purge cached data */ 45116c4d154dca43c662571129af31b27433b919a32Adam Lesinski purgeFileNameCacheLocked(); 45216c4d154dca43c662571129af31b27433b919a32Adam Lesinski //mZipSet.purgeVendor(); 45316c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete[] mVendor; 45416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 45516c4d154dca43c662571129af31b27433b919a32Adam Lesinski mVendor = strdupNew(vendor); 45616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 45716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 45816c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::setConfiguration(const ResTable_config& config, const char* locale) 45916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 46016c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 46116c4d154dca43c662571129af31b27433b919a32Adam Lesinski *mConfig = config; 46216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (locale) { 46316c4d154dca43c662571129af31b27433b919a32Adam Lesinski setLocaleLocked(locale); 46416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else if (config.language[0] != 0) { 46516c4d154dca43c662571129af31b27433b919a32Adam Lesinski char spec[9]; 46616c4d154dca43c662571129af31b27433b919a32Adam Lesinski spec[0] = config.language[0]; 46716c4d154dca43c662571129af31b27433b919a32Adam Lesinski spec[1] = config.language[1]; 46816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (config.country[0] != 0) { 46916c4d154dca43c662571129af31b27433b919a32Adam Lesinski spec[2] = '_'; 47016c4d154dca43c662571129af31b27433b919a32Adam Lesinski spec[3] = config.country[0]; 47116c4d154dca43c662571129af31b27433b919a32Adam Lesinski spec[4] = config.country[1]; 47216c4d154dca43c662571129af31b27433b919a32Adam Lesinski spec[5] = 0; 47316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 47416c4d154dca43c662571129af31b27433b919a32Adam Lesinski spec[3] = 0; 47516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 47616c4d154dca43c662571129af31b27433b919a32Adam Lesinski setLocaleLocked(spec); 47716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 47816c4d154dca43c662571129af31b27433b919a32Adam Lesinski updateResourceParamsLocked(); 47916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 48016c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 48116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 48216c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::getConfiguration(ResTable_config* outConfig) const 48316c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 48416c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 48516c4d154dca43c662571129af31b27433b919a32Adam Lesinski *outConfig = *mConfig; 48616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 48716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 48816c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 48916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open an asset. 49016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 49116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The data could be; 49216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - In a file on disk (assetBase + fileName). 49316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - In a compressed file on disk (assetBase + fileName.gz). 49416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - In a Zip archive, uncompressed or compressed. 49516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 49616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * It can be in a number of different directories and Zip archives. 49716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The search order is: 49816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - [appname] 49916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - locale + vendor 50016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - "default" + vendor 50116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - locale + "default" 50216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - "default + "default" 50316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - "common" 50416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - (same as above) 50516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 50616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * To find a particular file, we have to try up to eight paths with 50716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * all three forms of data. 50816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 50916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * We should probably reject requests for "illegal" filenames, e.g. those 51016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * with illegal characters or "../" backward relative paths. 51116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 51216c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::open(const char* fileName, AccessMode mode) 51316c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 51416c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 51516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 51616c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); 51716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 51816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 51916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode != CACHE_OFF && !mCacheValid) 52016c4d154dca43c662571129af31b27433b919a32Adam Lesinski loadFileNameCacheLocked(); 52116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 52216c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 assetName(kAssetsRoot); 52316c4d154dca43c662571129af31b27433b919a32Adam Lesinski assetName.appendPath(fileName); 52416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 52516c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 52616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * For each top-level asset path, search for the asset. 52716c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 52816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 52916c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t i = mAssetPaths.size(); 53016c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (i > 0) { 53116c4d154dca43c662571129af31b27433b919a32Adam Lesinski i--; 53216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Looking for asset '%s' in '%s'\n", 53316c4d154dca43c662571129af31b27433b919a32Adam Lesinski assetName.string(), mAssetPaths.itemAt(i).path.string()); 53416c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = openNonAssetInPathLocked(assetName.string(), mode, mAssetPaths.itemAt(i)); 53516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) { 53616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset != kExcludedAsset ? pAsset : NULL; 53716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 53816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 53916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 54016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 54116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 54216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 54316c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 54416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open a non-asset file as if it were an asset. 54516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 54616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The "fileName" is the partial path starting from the application 54716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * name. 54816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 54916c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openNonAsset(const char* fileName, AccessMode mode) 55016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 55116c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 55216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 55316c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); 55416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 55516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 55616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode != CACHE_OFF && !mCacheValid) 55716c4d154dca43c662571129af31b27433b919a32Adam Lesinski loadFileNameCacheLocked(); 55816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 55916c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 56016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * For each top-level asset path, search for the asset. 56116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 56216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 56316c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t i = mAssetPaths.size(); 56416c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (i > 0) { 56516c4d154dca43c662571129af31b27433b919a32Adam Lesinski i--; 56616c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Looking for non-asset '%s' in '%s'\n", fileName, mAssetPaths.itemAt(i).path.string()); 56716c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = openNonAssetInPathLocked( 56816c4d154dca43c662571129af31b27433b919a32Adam Lesinski fileName, mode, mAssetPaths.itemAt(i)); 56916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) { 57016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset != kExcludedAsset ? pAsset : NULL; 57116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 57216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 57316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 57416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 57516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 57616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 57716c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openNonAsset(void* cookie, const char* fileName, AccessMode mode) 57816c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 57916c4d154dca43c662571129af31b27433b919a32Adam Lesinski const size_t which = ((size_t)cookie)-1; 58016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 58116c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 58216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 58316c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); 58416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 58516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 58616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode != CACHE_OFF && !mCacheValid) 58716c4d154dca43c662571129af31b27433b919a32Adam Lesinski loadFileNameCacheLocked(); 58816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 58916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (which < mAssetPaths.size()) { 59016c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Looking for non-asset '%s' in '%s'\n", fileName, 59116c4d154dca43c662571129af31b27433b919a32Adam Lesinski mAssetPaths.itemAt(which).path.string()); 59216c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = openNonAssetInPathLocked( 59316c4d154dca43c662571129af31b27433b919a32Adam Lesinski fileName, mode, mAssetPaths.itemAt(which)); 59416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) { 59516c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset != kExcludedAsset ? pAsset : NULL; 59616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 59716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 59816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 59916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 60016c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 60116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 60216c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 60316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Get the type of a file in the asset namespace. 60416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 60516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * This currently only works for regular files. All others (including 60616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * directories) will return kFileTypeNonexistent. 60716c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 60816c4d154dca43c662571129af31b27433b919a32Adam LesinskiFileType AssetManager::getFileType(const char* fileName) 60916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 61016c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = NULL; 61116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 61216c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 61316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open the asset. This is less efficient than simply finding the 61416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * file, but it's not too bad (we don't uncompress or mmap data until 61516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * the first read() call). 61616c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 61716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = open(fileName, Asset::ACCESS_STREAMING); 61816c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete pAsset; 61916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 62016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) 62116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return kFileTypeNonexistent; 62216c4d154dca43c662571129af31b27433b919a32Adam Lesinski else 62316c4d154dca43c662571129af31b27433b919a32Adam Lesinski return kFileTypeRegular; 62416c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 62516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 62616c4d154dca43c662571129af31b27433b919a32Adam Lesinskiconst ResTable* AssetManager::getResTable(bool required) const 62716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 62816c4d154dca43c662571129af31b27433b919a32Adam Lesinski ResTable* rt = mResources; 62916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (rt) { 63016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return rt; 63116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 63216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 63316c4d154dca43c662571129af31b27433b919a32Adam Lesinski // Iterate through all asset packages, collecting resources from each. 63416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 63516c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 63616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 63716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mResources != NULL) { 63816c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mResources; 63916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 64016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 64116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (required) { 64216c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); 64316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 64416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 64516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode != CACHE_OFF && !mCacheValid) 64616c4d154dca43c662571129af31b27433b919a32Adam Lesinski const_cast<AssetManager*>(this)->loadFileNameCacheLocked(); 64716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 64816c4d154dca43c662571129af31b27433b919a32Adam Lesinski const size_t N = mAssetPaths.size(); 64916c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (size_t i=0; i<N; i++) { 65016c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* ass = NULL; 65116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ResTable* sharedRes = NULL; 65216c4d154dca43c662571129af31b27433b919a32Adam Lesinski bool shared = true; 65316c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap = mAssetPaths.itemAt(i); 65416c4d154dca43c662571129af31b27433b919a32Adam Lesinski MY_TRACE_BEGIN(ap.path.string()); 65516c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* idmap = openIdmapLocked(ap); 65616c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Looking for resource asset in '%s'\n", ap.path.string()); 65716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type != kFileTypeDirectory) { 65816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (i == 0) { 65916c4d154dca43c662571129af31b27433b919a32Adam Lesinski // The first item is typically the framework resources, 66016c4d154dca43c662571129af31b27433b919a32Adam Lesinski // which we want to avoid parsing every time. 66116c4d154dca43c662571129af31b27433b919a32Adam Lesinski sharedRes = const_cast<AssetManager*>(this)-> 66216c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipSet.getZipResourceTable(ap.path); 66316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 66416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (sharedRes == NULL) { 66516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ass = const_cast<AssetManager*>(this)-> 66616c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipSet.getZipResourceTableAsset(ap.path); 66716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ass == NULL) { 66816c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("loading resource table %s\n", ap.path.string()); 66916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ass = const_cast<AssetManager*>(this)-> 67016c4d154dca43c662571129af31b27433b919a32Adam Lesinski openNonAssetInPathLocked("resources.arsc", 67116c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset::ACCESS_BUFFER, 67216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap); 67316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ass != NULL && ass != kExcludedAsset) { 67416c4d154dca43c662571129af31b27433b919a32Adam Lesinski ass = const_cast<AssetManager*>(this)-> 67516c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipSet.setZipResourceTableAsset(ap.path, ass); 67616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 67716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 67816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 67916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (i == 0 && ass != NULL) { 68016c4d154dca43c662571129af31b27433b919a32Adam Lesinski // If this is the first resource table in the asset 68116c4d154dca43c662571129af31b27433b919a32Adam Lesinski // manager, then we are going to cache it so that we 68216c4d154dca43c662571129af31b27433b919a32Adam Lesinski // can quickly copy it out for others. 68316c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Creating shared resources for %s", ap.path.string()); 68416c4d154dca43c662571129af31b27433b919a32Adam Lesinski sharedRes = new ResTable(); 68516c4d154dca43c662571129af31b27433b919a32Adam Lesinski sharedRes->add(ass, (void*)(i+1), false, idmap); 68616c4d154dca43c662571129af31b27433b919a32Adam Lesinski sharedRes = const_cast<AssetManager*>(this)-> 68716c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipSet.setZipResourceTable(ap.path, sharedRes); 68816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 68916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 69016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 69116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("loading resource table %s\n", ap.path.string()); 69216c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* ass = const_cast<AssetManager*>(this)-> 69316c4d154dca43c662571129af31b27433b919a32Adam Lesinski openNonAssetInPathLocked("resources.arsc", 69416c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset::ACCESS_BUFFER, 69516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap); 69616c4d154dca43c662571129af31b27433b919a32Adam Lesinski shared = false; 69716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 69816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if ((ass != NULL || sharedRes != NULL) && ass != kExcludedAsset) { 69916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (rt == NULL) { 70016c4d154dca43c662571129af31b27433b919a32Adam Lesinski mResources = rt = new ResTable(); 70116c4d154dca43c662571129af31b27433b919a32Adam Lesinski updateResourceParamsLocked(); 70216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 70316c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Installing resource asset %p in to table %p\n", ass, mResources); 70416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (sharedRes != NULL) { 70516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Copying existing resources for %s", ap.path.string()); 70616c4d154dca43c662571129af31b27433b919a32Adam Lesinski rt->add(sharedRes); 70716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 70816c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Parsing resources for %s", ap.path.string()); 70916c4d154dca43c662571129af31b27433b919a32Adam Lesinski rt->add(ass, (void*)(i+1), !shared, idmap); 71016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 71116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 71216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (!shared) { 71316c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete ass; 71416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 71516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 71616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (idmap != NULL) { 71716c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete idmap; 71816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 71916c4d154dca43c662571129af31b27433b919a32Adam Lesinski MY_TRACE_END(); 72016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 72116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 72216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (required && !rt) ALOGW("Unable to find resources file resources.arsc"); 72316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (!rt) { 72416c4d154dca43c662571129af31b27433b919a32Adam Lesinski mResources = rt = new ResTable(); 72516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 72616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return rt; 72716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 72816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 72916c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::updateResourceParamsLocked() const 73016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 73116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ResTable* res = mResources; 73216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (!res) { 73316c4d154dca43c662571129af31b27433b919a32Adam Lesinski return; 73416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 73516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 73616c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t llen = mLocale ? strlen(mLocale) : 0; 73716c4d154dca43c662571129af31b27433b919a32Adam Lesinski mConfig->language[0] = 0; 73816c4d154dca43c662571129af31b27433b919a32Adam Lesinski mConfig->language[1] = 0; 73916c4d154dca43c662571129af31b27433b919a32Adam Lesinski mConfig->country[0] = 0; 74016c4d154dca43c662571129af31b27433b919a32Adam Lesinski mConfig->country[1] = 0; 74116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (llen >= 2) { 74216c4d154dca43c662571129af31b27433b919a32Adam Lesinski mConfig->language[0] = mLocale[0]; 74316c4d154dca43c662571129af31b27433b919a32Adam Lesinski mConfig->language[1] = mLocale[1]; 74416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 74516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (llen >= 5) { 74616c4d154dca43c662571129af31b27433b919a32Adam Lesinski mConfig->country[0] = mLocale[3]; 74716c4d154dca43c662571129af31b27433b919a32Adam Lesinski mConfig->country[1] = mLocale[4]; 74816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 74916c4d154dca43c662571129af31b27433b919a32Adam Lesinski mConfig->size = sizeof(*mConfig); 75016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 75116c4d154dca43c662571129af31b27433b919a32Adam Lesinski res->setParameters(mConfig); 75216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 75316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 75416c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openIdmapLocked(const struct asset_path& ap) const 75516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 75616c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* ass = NULL; 75716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.idmap.size() != 0) { 75816c4d154dca43c662571129af31b27433b919a32Adam Lesinski ass = const_cast<AssetManager*>(this)-> 75916c4d154dca43c662571129af31b27433b919a32Adam Lesinski openAssetFromFileLocked(ap.idmap, Asset::ACCESS_BUFFER); 76016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ass) { 76116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("loading idmap %s\n", ap.idmap.string()); 76216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 76316c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("failed to load idmap %s\n", ap.idmap.string()); 76416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 76516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 76616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return ass; 76716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 76816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 76916c4d154dca43c662571129af31b27433b919a32Adam Lesinskiconst ResTable& AssetManager::getResources(bool required) const 77016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 77116c4d154dca43c662571129af31b27433b919a32Adam Lesinski const ResTable* rt = getResTable(required); 77216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return *rt; 77316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 77416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 77516c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::isUpToDate() 77616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 77716c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 77816c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mZipSet.isUpToDate(); 77916c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 78016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 78116c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::getLocales(Vector<String8>* locales) const 78216c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 78316c4d154dca43c662571129af31b27433b919a32Adam Lesinski ResTable* res = mResources; 78416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (res != NULL) { 78516c4d154dca43c662571129af31b27433b919a32Adam Lesinski res->getLocales(locales); 78616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 78716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 78816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 78916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 79016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open a non-asset file as if it were an asset, searching for it in the 79116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * specified app. 79216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 79316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pass in a NULL values for "appName" if the common app directory should 79416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * be used. 79516c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 79616c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode mode, 79716c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap) 79816c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 79916c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = NULL; 80016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 80116c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* look at the filesystem on disk */ 80216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type == kFileTypeDirectory) { 80316c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(ap.path); 80416c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(fileName); 80516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 80616c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromFileLocked(path, mode); 80716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 80816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) { 80916c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* try again, this time with ".gz" */ 81016c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.append(".gz"); 81116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromFileLocked(path, mode); 81216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 81316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 81416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) { 81516c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("FOUND NA '%s' on disk\n", fileName); 81616c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset->setAssetSource(path); 81716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 81816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 81916c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* look inside the zip file */ 82016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 82116c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(fileName); 82216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 82316c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* check the appropriate Zip file */ 82416c4d154dca43c662571129af31b27433b919a32Adam Lesinski ZipFileRO* pZip; 82516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ZipEntryRO entry; 82616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 82716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pZip = getZipFileLocked(ap); 82816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pZip != NULL) { 82916c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("GOT zip, checking NA '%s'\n", (const char*) path); 83016c4d154dca43c662571129af31b27433b919a32Adam Lesinski entry = pZip->findEntryByName(path.string()); 83116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (entry != NULL) { 83216c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("FOUND NA in Zip file for %s\n", appName ? appName : kAppCommon); 83316c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromZipLocked(pZip, entry, mode, path); 83416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 83516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 83616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 83716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) { 83816c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* create a "source" name, for debug/display */ 83916c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset->setAssetSource( 84016c4d154dca43c662571129af31b27433b919a32Adam Lesinski createZipSourceNameLocked(ZipSet::getPathName(ap.path.string()), String8(""), 84116c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8(fileName))); 84216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 84316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 84416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 84516c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset; 84616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 84716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 84816c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 84916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open an asset, searching for it in the directory hierarchy for the 85016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * specified app. 85116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 85216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pass in a NULL values for "appName" if the common app directory should 85316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * be used. 85416c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 85516c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openInPathLocked(const char* fileName, AccessMode mode, 85616c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap) 85716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 85816c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = NULL; 85916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 86016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 86116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Try various combinations of locale and vendor. 86216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 86316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mLocale != NULL && mVendor != NULL) 86416c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openInLocaleVendorLocked(fileName, mode, ap, mLocale, mVendor); 86516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL && mVendor != NULL) 86616c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openInLocaleVendorLocked(fileName, mode, ap, NULL, mVendor); 86716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL && mLocale != NULL) 86816c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openInLocaleVendorLocked(fileName, mode, ap, mLocale, NULL); 86916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) 87016c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openInLocaleVendorLocked(fileName, mode, ap, NULL, NULL); 87116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 87216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset; 87316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 87416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 87516c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 87616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open an asset, searching for it in the directory hierarchy for the 87716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * specified locale and vendor. 87816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 87916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * We also search in "app.jar". 88016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 88116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pass in NULL values for "appName", "locale", and "vendor" if the 88216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * defaults should be used. 88316c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 88416c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openInLocaleVendorLocked(const char* fileName, AccessMode mode, 88516c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap, const char* locale, const char* vendor) 88616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 88716c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = NULL; 88816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 88916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type == kFileTypeDirectory) { 89016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode == CACHE_OFF) { 89116c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* look at the filesystem on disk */ 89216c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(createPathNameLocked(ap, locale, vendor)); 89316c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(fileName); 89416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 89516c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 excludeName(path); 89616c4d154dca43c662571129af31b27433b919a32Adam Lesinski excludeName.append(kExcludeExtension); 89716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (::getFileType(excludeName.string()) != kFileTypeNonexistent) { 89816c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* say no more */ 89916c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("+++ excluding '%s'\n", (const char*) excludeName); 90016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return kExcludedAsset; 90116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 90216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 90316c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromFileLocked(path, mode); 90416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 90516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) { 90616c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* try again, this time with ".gz" */ 90716c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.append(".gz"); 90816c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromFileLocked(path, mode); 90916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 91016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 91116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) 91216c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset->setAssetSource(path); 91316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 91416c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* find in cache */ 91516c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(createPathNameLocked(ap, locale, vendor)); 91616c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(fileName); 91716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 91816c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir::FileInfo tmpInfo; 91916c4d154dca43c662571129af31b27433b919a32Adam Lesinski bool found = false; 92016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 92116c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 excludeName(path); 92216c4d154dca43c662571129af31b27433b919a32Adam Lesinski excludeName.append(kExcludeExtension); 92316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 92416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCache.indexOf(excludeName) != NAME_NOT_FOUND) { 92516c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* go no farther */ 92616c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("+++ Excluding '%s'\n", (const char*) excludeName); 92716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return kExcludedAsset; 92816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 92916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 93016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 93116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * File compression extensions (".gz") don't get stored in the 93216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * name cache, so we have to try both here. 93316c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 93416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCache.indexOf(path) != NAME_NOT_FOUND) { 93516c4d154dca43c662571129af31b27433b919a32Adam Lesinski found = true; 93616c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromFileLocked(path, mode); 93716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) { 93816c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* try again, this time with ".gz" */ 93916c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.append(".gz"); 94016c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromFileLocked(path, mode); 94116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 94216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 94316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 94416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) 94516c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset->setAssetSource(path); 94616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 94716c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 94816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Don't continue the search into the Zip files. Our cached info 94916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * said it was a file on disk; to be consistent with openDir() 95016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * we want to return the loose asset. If the cached file gets 95116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * removed, we fail. 95216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 95316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The alternative is to update our cache when files get deleted, 95416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * or make some sort of "best effort" promise, but for now I'm 95516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * taking the hard line. 95616c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 95716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (found) { 95816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) 95916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGD("Expected file not found: '%s'\n", path.string()); 96016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset; 96116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 96216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 96316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 96416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 96516c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 96616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Either it wasn't found on disk or on the cached view of the disk. 96716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Dig through the currently-opened set of Zip files. If caching 96816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * is disabled, the Zip file may get reopened. 96916c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 97016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL && ap.type == kFileTypeRegular) { 97116c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path; 97216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 97316c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath((locale != NULL) ? locale : kDefaultLocale); 97416c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath((vendor != NULL) ? vendor : kDefaultVendor); 97516c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(fileName); 97616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 97716c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* check the appropriate Zip file */ 97816c4d154dca43c662571129af31b27433b919a32Adam Lesinski ZipFileRO* pZip; 97916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ZipEntryRO entry; 98016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 98116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pZip = getZipFileLocked(ap); 98216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pZip != NULL) { 98316c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("GOT zip, checking '%s'\n", (const char*) path); 98416c4d154dca43c662571129af31b27433b919a32Adam Lesinski entry = pZip->findEntryByName(path.string()); 98516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (entry != NULL) { 98616c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("FOUND in Zip file for %s/%s-%s\n", 98716c4d154dca43c662571129af31b27433b919a32Adam Lesinski // appName, locale, vendor); 98816c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromZipLocked(pZip, entry, mode, path); 98916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 99016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 99116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 99216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) { 99316c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* create a "source" name, for debug/display */ 99416c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset->setAssetSource(createZipSourceNameLocked(ZipSet::getPathName(ap.path.string()), 99516c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8(""), String8(fileName))); 99616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 99716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 99816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 99916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset; 100016c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 100116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 100216c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 100316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Create a "source name" for a file from a Zip archive. 100416c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 100516c4d154dca43c662571129af31b27433b919a32Adam LesinskiString8 AssetManager::createZipSourceNameLocked(const String8& zipFileName, 100616c4d154dca43c662571129af31b27433b919a32Adam Lesinski const String8& dirName, const String8& fileName) 100716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 100816c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 sourceName("zip:"); 100916c4d154dca43c662571129af31b27433b919a32Adam Lesinski sourceName.append(zipFileName); 101016c4d154dca43c662571129af31b27433b919a32Adam Lesinski sourceName.append(":"); 101116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirName.length() > 0) { 101216c4d154dca43c662571129af31b27433b919a32Adam Lesinski sourceName.appendPath(dirName); 101316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 101416c4d154dca43c662571129af31b27433b919a32Adam Lesinski sourceName.appendPath(fileName); 101516c4d154dca43c662571129af31b27433b919a32Adam Lesinski return sourceName; 101616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 101716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 101816c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 101916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Create a path to a loose asset (asset-base/app/locale/vendor). 102016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 102116c4d154dca43c662571129af31b27433b919a32Adam LesinskiString8 AssetManager::createPathNameLocked(const asset_path& ap, const char* locale, 102216c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* vendor) 102316c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 102416c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(ap.path); 102516c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath((locale != NULL) ? locale : kDefaultLocale); 102616c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath((vendor != NULL) ? vendor : kDefaultVendor); 102716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return path; 102816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 102916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 103016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 103116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Create a path to a loose asset (asset-base/app/rootDir). 103216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 103316c4d154dca43c662571129af31b27433b919a32Adam LesinskiString8 AssetManager::createPathNameLocked(const asset_path& ap, const char* rootDir) 103416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 103516c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(ap.path); 103616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (rootDir != NULL) path.appendPath(rootDir); 103716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return path; 103816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 103916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 104016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 104116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Return a pointer to one of our open Zip archives. Returns NULL if no 104216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * matching Zip file exists. 104316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 104416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Right now we have 2 possible Zip files (1 each in app/"common"). 104516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 104616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * If caching is set to CACHE_OFF, to get the expected behavior we 104716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * need to reopen the Zip file on every request. That would be silly 104816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * and expensive, so instead we just check the file modification date. 104916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 105016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pass in NULL values for "appName", "locale", and "vendor" if the 105116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * generics should be used. 105216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 105316c4d154dca43c662571129af31b27433b919a32Adam LesinskiZipFileRO* AssetManager::getZipFileLocked(const asset_path& ap) 105416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 105516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("getZipFileLocked() in %p\n", this); 105616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 105716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mZipSet.getZip(ap.path); 105816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 105916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 106016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 106116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Try to open an asset from a file on disk. 106216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 106316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * If the file is compressed with gzip, we seek to the start of the 106416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * deflated data and pass that in (just like we would for a Zip archive). 106516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 106616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * For uncompressed data, we may already have an mmap()ed version sitting 106716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * around. If so, we want to hand that to the Asset instead. 106816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 106916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * This returns NULL if the file doesn't exist, couldn't be opened, or 107016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * claims to be a ".gz" but isn't. 107116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 107216c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openAssetFromFileLocked(const String8& pathName, 107316c4d154dca43c662571129af31b27433b919a32Adam Lesinski AccessMode mode) 107416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 107516c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = NULL; 107616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 107716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (strcasecmp(pathName.getPathExtension().string(), ".gz") == 0) { 107816c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("TRYING '%s'\n", (const char*) pathName); 107916c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = Asset::createFromCompressedFile(pathName.string(), mode); 108016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 108116c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("TRYING '%s'\n", (const char*) pathName); 108216c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = Asset::createFromFile(pathName.string(), mode); 108316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 108416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 108516c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset; 108616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 108716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 108816c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 108916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Given an entry in a Zip archive, create a new Asset object. 109016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 109116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * If the entry is uncompressed, we may want to create or share a 109216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * slice of shared memory. 109316c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 109416c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openAssetFromZipLocked(const ZipFileRO* pZipFile, 109516c4d154dca43c662571129af31b27433b919a32Adam Lesinski const ZipEntryRO entry, AccessMode mode, const String8& entryName) 109616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 109716c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = NULL; 109816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 109916c4d154dca43c662571129af31b27433b919a32Adam Lesinski // TODO: look for previously-created shared memory slice? 110016c4d154dca43c662571129af31b27433b919a32Adam Lesinski int method; 110116c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t uncompressedLen; 110216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 110316c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("USING Zip '%s'\n", pEntry->getFileName()); 110416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 110516c4d154dca43c662571129af31b27433b919a32Adam Lesinski //pZipFile->getEntryInfo(entry, &method, &uncompressedLen, &compressedLen, 110616c4d154dca43c662571129af31b27433b919a32Adam Lesinski // &offset); 110716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (!pZipFile->getEntryInfo(entry, &method, &uncompressedLen, NULL, NULL, 110816c4d154dca43c662571129af31b27433b919a32Adam Lesinski NULL, NULL)) 110916c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 111016c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("getEntryInfo failed\n"); 111116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 111216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 111316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 111416c4d154dca43c662571129af31b27433b919a32Adam Lesinski FileMap* dataMap = pZipFile->createEntryFileMap(entry); 111516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dataMap == NULL) { 111616c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("create map from entry failed\n"); 111716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 111816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 111916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 112016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (method == ZipFileRO::kCompressStored) { 112116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = Asset::createFromUncompressedMap(dataMap, mode); 112216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Opened uncompressed entry %s in zip %s mode %d: %p", entryName.string(), 112316c4d154dca43c662571129af31b27433b919a32Adam Lesinski dataMap->getFileName(), mode, pAsset); 112416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 112516c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = Asset::createFromCompressedMap(dataMap, method, 112616c4d154dca43c662571129af31b27433b919a32Adam Lesinski uncompressedLen, mode); 112716c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Opened compressed entry %s in zip %s mode %d: %p", entryName.string(), 112816c4d154dca43c662571129af31b27433b919a32Adam Lesinski dataMap->getFileName(), mode, pAsset); 112916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 113016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) { 113116c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* unexpected */ 113216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("create from segment failed\n"); 113316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 113416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 113516c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset; 113616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 113716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 113816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 113916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 114016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 114116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open a directory in the asset namespace. 114216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 114316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * An "asset directory" is simply the combination of all files in all 114416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * locations, with ".gz" stripped for loose files. With app, locale, and 114516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * vendor defined, we have 8 directories and 2 Zip archives to scan. 114616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 114716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pass in "" for the root dir. 114816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 114916c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetDir* AssetManager::openDir(const char* dirName) 115016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 115116c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 115216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 115316c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir* pDir = NULL; 115416c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pMergedInfo = NULL; 115516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 115616c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); 115716c4d154dca43c662571129af31b27433b919a32Adam Lesinski assert(dirName != NULL); 115816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 115916c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("+++ openDir(%s) in '%s'\n", dirName, (const char*) mAssetBase); 116016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 116116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode != CACHE_OFF && !mCacheValid) 116216c4d154dca43c662571129af31b27433b919a32Adam Lesinski loadFileNameCacheLocked(); 116316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 116416c4d154dca43c662571129af31b27433b919a32Adam Lesinski pDir = new AssetDir; 116516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 116616c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 116716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan the various directories, merging what we find into a single 116816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * vector. We want to scan them in reverse priority order so that 116916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * the ".EXCLUDE" processing works correctly. Also, if we decide we 117016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * want to remember where the file is coming from, we'll get the right 117116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * version. 117216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 117316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * We start with Zip archives, then do loose files. 117416c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 117516c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo = new SortedVector<AssetDir::FileInfo>; 117616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 117716c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t i = mAssetPaths.size(); 117816c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (i > 0) { 117916c4d154dca43c662571129af31b27433b919a32Adam Lesinski i--; 118016c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap = mAssetPaths.itemAt(i); 118116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type == kFileTypeRegular) { 118216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Adding directory %s from zip %s", dirName, ap.path.string()); 118316c4d154dca43c662571129af31b27433b919a32Adam Lesinski scanAndMergeZipLocked(pMergedInfo, ap, kAssetsRoot, dirName); 118416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 118516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Adding directory %s from dir %s", dirName, ap.path.string()); 118616c4d154dca43c662571129af31b27433b919a32Adam Lesinski scanAndMergeDirLocked(pMergedInfo, ap, kAssetsRoot, dirName); 118716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 118816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 118916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 119016c4d154dca43c662571129af31b27433b919a32Adam Lesinski#if 0 119116c4d154dca43c662571129af31b27433b919a32Adam Lesinski printf("FILE LIST:\n"); 119216c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (i = 0; i < (size_t) pMergedInfo->size(); i++) { 119316c4d154dca43c662571129af31b27433b919a32Adam Lesinski printf(" %d: (%d) '%s'\n", i, 119416c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->itemAt(i).getFileType(), 119516c4d154dca43c662571129af31b27433b919a32Adam Lesinski (const char*) pMergedInfo->itemAt(i).getFileName()); 119616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 119716c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 119816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 119916c4d154dca43c662571129af31b27433b919a32Adam Lesinski pDir->setFileList(pMergedInfo); 120016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pDir; 120116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 120216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 120316c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 120416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open a directory in the non-asset namespace. 120516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 120616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * An "asset directory" is simply the combination of all files in all 120716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * locations, with ".gz" stripped for loose files. With app, locale, and 120816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * vendor defined, we have 8 directories and 2 Zip archives to scan. 120916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 121016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pass in "" for the root dir. 121116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 121216c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetDir* AssetManager::openNonAssetDir(void* cookie, const char* dirName) 121316c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 121416c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 121516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 121616c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir* pDir = NULL; 121716c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pMergedInfo = NULL; 121816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 121916c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); 122016c4d154dca43c662571129af31b27433b919a32Adam Lesinski assert(dirName != NULL); 122116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 122216c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("+++ openDir(%s) in '%s'\n", dirName, (const char*) mAssetBase); 122316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 122416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode != CACHE_OFF && !mCacheValid) 122516c4d154dca43c662571129af31b27433b919a32Adam Lesinski loadFileNameCacheLocked(); 122616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 122716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pDir = new AssetDir; 122816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 122916c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo = new SortedVector<AssetDir::FileInfo>; 123016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 123116c4d154dca43c662571129af31b27433b919a32Adam Lesinski const size_t which = ((size_t)cookie)-1; 123216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 123316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (which < mAssetPaths.size()) { 123416c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap = mAssetPaths.itemAt(which); 123516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type == kFileTypeRegular) { 123616c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Adding directory %s from zip %s", dirName, ap.path.string()); 123716c4d154dca43c662571129af31b27433b919a32Adam Lesinski scanAndMergeZipLocked(pMergedInfo, ap, NULL, dirName); 123816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 123916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Adding directory %s from dir %s", dirName, ap.path.string()); 124016c4d154dca43c662571129af31b27433b919a32Adam Lesinski scanAndMergeDirLocked(pMergedInfo, ap, NULL, dirName); 124116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 124216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 124316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 124416c4d154dca43c662571129af31b27433b919a32Adam Lesinski#if 0 124516c4d154dca43c662571129af31b27433b919a32Adam Lesinski printf("FILE LIST:\n"); 124616c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (i = 0; i < (size_t) pMergedInfo->size(); i++) { 124716c4d154dca43c662571129af31b27433b919a32Adam Lesinski printf(" %d: (%d) '%s'\n", i, 124816c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->itemAt(i).getFileType(), 124916c4d154dca43c662571129af31b27433b919a32Adam Lesinski (const char*) pMergedInfo->itemAt(i).getFileName()); 125016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 125116c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 125216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 125316c4d154dca43c662571129af31b27433b919a32Adam Lesinski pDir->setFileList(pMergedInfo); 125416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pDir; 125516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 125616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 125716c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 125816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan the contents of the specified directory and merge them into the 125916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * "pMergedInfo" vector, removing previous entries if we find "exclude" 126016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * directives. 126116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 126216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Returns "false" if we found nothing to contribute. 126316c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 126416c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::scanAndMergeDirLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, 126516c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap, const char* rootDir, const char* dirName) 126616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 126716c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pContents; 126816c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path; 126916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 127016c4d154dca43c662571129af31b27433b919a32Adam Lesinski assert(pMergedInfo != NULL); 127116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 127216c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("scanAndMergeDir: %s %s %s %s\n", appName, locale, vendor,dirName); 127316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 127416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheValid) { 127516c4d154dca43c662571129af31b27433b919a32Adam Lesinski int i, start, count; 127616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 127716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents = new SortedVector<AssetDir::FileInfo>; 127816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 127916c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 128016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Get the basic partial path and find it in the cache. That's 128116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * the start point for the search. 128216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 128316c4d154dca43c662571129af31b27433b919a32Adam Lesinski path = createPathNameLocked(ap, rootDir); 128416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirName[0] != '\0') 128516c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(dirName); 128616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 128716c4d154dca43c662571129af31b27433b919a32Adam Lesinski start = mCache.indexOf(path); 128816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (start == NAME_NOT_FOUND) { 128916c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("+++ not found in cache: dir '%s'\n", (const char*) path); 129016c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete pContents; 129116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 129216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 129316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 129416c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 129516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The match string looks like "common/default/default/foo/bar/". 129616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The '/' on the end ensures that we don't match on the directory 129716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * itself or on ".../foo/barfy/". 129816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 129916c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.append("/"); 130016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 130116c4d154dca43c662571129af31b27433b919a32Adam Lesinski count = mCache.size(); 130216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 130316c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 130416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pick out the stuff in the current dir by examining the pathname. 130516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * It needs to match the partial pathname prefix, and not have a '/' 130616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * (fssep) anywhere after the prefix. 130716c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 130816c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (i = start+1; i < count; i++) { 130916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCache[i].getFileName().length() > path.length() && 131016c4d154dca43c662571129af31b27433b919a32Adam Lesinski strncmp(mCache[i].getFileName().string(), path.string(), path.length()) == 0) 131116c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 131216c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* name = mCache[i].getFileName().string(); 131316c4d154dca43c662571129af31b27433b919a32Adam Lesinski // XXX THIS IS BROKEN! Looks like we need to store the full 131416c4d154dca43c662571129af31b27433b919a32Adam Lesinski // path prefix separately from the file path. 131516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (strchr(name + path.length(), '/') == NULL) { 131616c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* grab it, reducing path to just the filename component */ 131716c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir::FileInfo tmp = mCache[i]; 131816c4d154dca43c662571129af31b27433b919a32Adam Lesinski tmp.setFileName(tmp.getFileName().getPathLeaf()); 131916c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents->add(tmp); 132016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 132116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 132216c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* no longer in the dir or its subdirs */ 132316c4d154dca43c662571129af31b27433b919a32Adam Lesinski break; 132416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 132516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 132616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 132716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 132816c4d154dca43c662571129af31b27433b919a32Adam Lesinski path = createPathNameLocked(ap, rootDir); 132916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirName[0] != '\0') 133016c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(dirName); 133116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents = scanDirLocked(path); 133216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pContents == NULL) 133316c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 133416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 133516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 133616c4d154dca43c662571129af31b27433b919a32Adam Lesinski // if we wanted to do an incremental cache fill, we would do it here 133716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 133816c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 133916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Process "exclude" directives. If we find a filename that ends with 134016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * ".EXCLUDE", we look for a matching entry in the "merged" set, and 134116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * remove it if we find it. We also delete the "exclude" entry. 134216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 134316c4d154dca43c662571129af31b27433b919a32Adam Lesinski int i, count, exclExtLen; 134416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 134516c4d154dca43c662571129af31b27433b919a32Adam Lesinski count = pContents->size(); 134616c4d154dca43c662571129af31b27433b919a32Adam Lesinski exclExtLen = strlen(kExcludeExtension); 134716c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (i = 0; i < count; i++) { 134816c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* name; 134916c4d154dca43c662571129af31b27433b919a32Adam Lesinski int nameLen; 135016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 135116c4d154dca43c662571129af31b27433b919a32Adam Lesinski name = pContents->itemAt(i).getFileName().string(); 135216c4d154dca43c662571129af31b27433b919a32Adam Lesinski nameLen = strlen(name); 135316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (nameLen > exclExtLen && 135416c4d154dca43c662571129af31b27433b919a32Adam Lesinski strcmp(name + (nameLen - exclExtLen), kExcludeExtension) == 0) 135516c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 135616c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 match(name, nameLen - exclExtLen); 135716c4d154dca43c662571129af31b27433b919a32Adam Lesinski int matchIdx; 135816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 135916c4d154dca43c662571129af31b27433b919a32Adam Lesinski matchIdx = AssetDir::FileInfo::findEntry(pMergedInfo, match); 136016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (matchIdx > 0) { 136116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Excluding '%s' [%s]\n", 136216c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->itemAt(matchIdx).getFileName().string(), 136316c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->itemAt(matchIdx).getSourceName().string()); 136416c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->removeAt(matchIdx); 136516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 136616c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("+++ no match on '%s'\n", (const char*) match); 136716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 136816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 136916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGD("HEY: size=%d removing %d\n", (int)pContents->size(), i); 137016c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents->removeAt(i); 137116c4d154dca43c662571129af31b27433b919a32Adam Lesinski i--; // adjust "for" loop 137216c4d154dca43c662571129af31b27433b919a32Adam Lesinski count--; // and loop limit 137316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 137416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 137516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 137616c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeInfoLocked(pMergedInfo, pContents); 137716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 137816c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete pContents; 137916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 138016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 138116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 138216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 138316c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 138416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan the contents of the specified directory, and stuff what we find 138516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * into a newly-allocated vector. 138616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 138716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Files ending in ".gz" will have their extensions removed. 138816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 138916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * We should probably think about skipping files with "illegal" names, 139016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * e.g. illegal characters (/\:) or excessive length. 139116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 139216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Returns NULL if the specified directory doesn't exist. 139316c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 139416c4d154dca43c662571129af31b27433b919a32Adam LesinskiSortedVector<AssetDir::FileInfo>* AssetManager::scanDirLocked(const String8& path) 139516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 139616c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pContents = NULL; 139716c4d154dca43c662571129af31b27433b919a32Adam Lesinski DIR* dir; 139816c4d154dca43c662571129af31b27433b919a32Adam Lesinski struct dirent* entry; 139916c4d154dca43c662571129af31b27433b919a32Adam Lesinski FileType fileType; 140016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 140116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Scanning dir '%s'\n", path.string()); 140216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 140316c4d154dca43c662571129af31b27433b919a32Adam Lesinski dir = opendir(path.string()); 140416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dir == NULL) 140516c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 140616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 140716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents = new SortedVector<AssetDir::FileInfo>; 140816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 140916c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (1) { 141016c4d154dca43c662571129af31b27433b919a32Adam Lesinski entry = readdir(dir); 141116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (entry == NULL) 141216c4d154dca43c662571129af31b27433b919a32Adam Lesinski break; 141316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 141416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (strcmp(entry->d_name, ".") == 0 || 141516c4d154dca43c662571129af31b27433b919a32Adam Lesinski strcmp(entry->d_name, "..") == 0) 141616c4d154dca43c662571129af31b27433b919a32Adam Lesinski continue; 141716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 141816c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifdef _DIRENT_HAVE_D_TYPE 141916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (entry->d_type == DT_REG) 142016c4d154dca43c662571129af31b27433b919a32Adam Lesinski fileType = kFileTypeRegular; 142116c4d154dca43c662571129af31b27433b919a32Adam Lesinski else if (entry->d_type == DT_DIR) 142216c4d154dca43c662571129af31b27433b919a32Adam Lesinski fileType = kFileTypeDirectory; 142316c4d154dca43c662571129af31b27433b919a32Adam Lesinski else 142416c4d154dca43c662571129af31b27433b919a32Adam Lesinski fileType = kFileTypeUnknown; 142516c4d154dca43c662571129af31b27433b919a32Adam Lesinski#else 142616c4d154dca43c662571129af31b27433b919a32Adam Lesinski // stat the file 142716c4d154dca43c662571129af31b27433b919a32Adam Lesinski fileType = ::getFileType(path.appendPathCopy(entry->d_name).string()); 142816c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 142916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 143016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (fileType != kFileTypeRegular && fileType != kFileTypeDirectory) 143116c4d154dca43c662571129af31b27433b919a32Adam Lesinski continue; 143216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 143316c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir::FileInfo info; 143416c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.set(String8(entry->d_name), fileType); 143516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (strcasecmp(info.getFileName().getPathExtension().string(), ".gz") == 0) 143616c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.setFileName(info.getFileName().getBasePath()); 143716c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.setSourceName(path.appendPathCopy(info.getFileName())); 143816c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents->add(info); 143916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 144016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 144116c4d154dca43c662571129af31b27433b919a32Adam Lesinski closedir(dir); 144216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pContents; 144316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 144416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 144516c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 144616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan the contents out of the specified Zip archive, and merge what we 144716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * find into "pMergedInfo". If the Zip archive in question doesn't exist, 144816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * we return immediately. 144916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 145016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Returns "false" if we found nothing to contribute. 145116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 145216c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, 145316c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap, const char* rootDir, const char* baseDirName) 145416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 145516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ZipFileRO* pZip; 145616c4d154dca43c662571129af31b27433b919a32Adam Lesinski Vector<String8> dirs; 145716c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir::FileInfo info; 145816c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo> contents; 145916c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 sourceName, zipName, dirName; 146016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 146116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pZip = mZipSet.getZip(ap.path); 146216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pZip == NULL) { 146316c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("Failure opening zip %s\n", ap.path.string()); 146416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 146516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 146616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 146716c4d154dca43c662571129af31b27433b919a32Adam Lesinski zipName = ZipSet::getPathName(ap.path.string()); 146816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 146916c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* convert "sounds" to "rootDir/sounds" */ 147016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (rootDir != NULL) dirName = rootDir; 147116c4d154dca43c662571129af31b27433b919a32Adam Lesinski dirName.appendPath(baseDirName); 147216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 147316c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 147416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan through the list of files, looking for a match. The files in 147516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * the Zip table of contents are not in sorted order, so we have to 147616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * process the entire list. We're looking for a string that begins 147716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * with the characters in "dirName", is followed by a '/', and has no 147816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * subsequent '/' in the stuff that follows. 147916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 148016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * What makes this especially fun is that directories are not stored 148116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * explicitly in Zip archives, so we have to infer them from context. 148216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * When we see "sounds/foo.wav" we have to leave a note to ourselves 148316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * to insert a directory called "sounds" into the list. We store 148416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * these in temporary vector so that we only return each one once. 148516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 148616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Name comparisons are case-sensitive to match UNIX filesystem 148716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * semantics. 148816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 148916c4d154dca43c662571129af31b27433b919a32Adam Lesinski int dirNameLen = dirName.length(); 149016c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (int i = 0; i < pZip->getNumEntries(); i++) { 149116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ZipEntryRO entry; 149216c4d154dca43c662571129af31b27433b919a32Adam Lesinski char nameBuf[256]; 149316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 149416c4d154dca43c662571129af31b27433b919a32Adam Lesinski entry = pZip->findEntryByIndex(i); 149516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pZip->getEntryFileName(entry, nameBuf, sizeof(nameBuf)) != 0) { 149616c4d154dca43c662571129af31b27433b919a32Adam Lesinski // TODO: fix this if we expect to have long names 149716c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGE("ARGH: name too long?\n"); 149816c4d154dca43c662571129af31b27433b919a32Adam Lesinski continue; 149916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 150016c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("Comparing %s in %s?\n", nameBuf, dirName.string()); 150116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirNameLen == 0 || 150216c4d154dca43c662571129af31b27433b919a32Adam Lesinski (strncmp(nameBuf, dirName.string(), dirNameLen) == 0 && 150316c4d154dca43c662571129af31b27433b919a32Adam Lesinski nameBuf[dirNameLen] == '/')) 150416c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 150516c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* cp; 150616c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* nextSlash; 150716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 150816c4d154dca43c662571129af31b27433b919a32Adam Lesinski cp = nameBuf + dirNameLen; 150916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirNameLen != 0) 151016c4d154dca43c662571129af31b27433b919a32Adam Lesinski cp++; // advance past the '/' 151116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 151216c4d154dca43c662571129af31b27433b919a32Adam Lesinski nextSlash = strchr(cp, '/'); 151316c4d154dca43c662571129af31b27433b919a32Adam Lesinski//xxx this may break if there are bare directory entries 151416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (nextSlash == NULL) { 151516c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* this is a file in the requested directory */ 151616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 151716c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.set(String8(nameBuf).getPathLeaf(), kFileTypeRegular); 151816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 151916c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.setSourceName( 152016c4d154dca43c662571129af31b27433b919a32Adam Lesinski createZipSourceNameLocked(zipName, dirName, info.getFileName())); 152116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 152216c4d154dca43c662571129af31b27433b919a32Adam Lesinski contents.add(info); 152316c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("FOUND: file '%s'\n", info.getFileName().string()); 152416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 152516c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* this is a subdir; add it if we don't already have it*/ 152616c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 subdirName(cp, nextSlash - cp); 152716c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t j; 152816c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t N = dirs.size(); 152916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 153016c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (j = 0; j < N; j++) { 153116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (subdirName == dirs[j]) { 153216c4d154dca43c662571129af31b27433b919a32Adam Lesinski break; 153316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 153416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 153516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (j == N) { 153616c4d154dca43c662571129af31b27433b919a32Adam Lesinski dirs.add(subdirName); 153716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 153816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 153916c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("FOUND: dir '%s'\n", subdirName.string()); 154016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 154116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 154216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 154316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 154416c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 154516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Add the set of unique directories. 154616c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 154716c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (int i = 0; i < (int) dirs.size(); i++) { 154816c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.set(dirs[i], kFileTypeDirectory); 154916c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.setSourceName( 155016c4d154dca43c662571129af31b27433b919a32Adam Lesinski createZipSourceNameLocked(zipName, dirName, info.getFileName())); 155116c4d154dca43c662571129af31b27433b919a32Adam Lesinski contents.add(info); 155216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 155316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 155416c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeInfoLocked(pMergedInfo, &contents); 155516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 155616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 155716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 155816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 155916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 156016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 156116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Merge two vectors of FileInfo. 156216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 156316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The merged contents will be stuffed into *pMergedInfo. 156416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 156516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * If an entry for a file exists in both "pMergedInfo" and "pContents", 156616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * we use the newer "pContents" entry. 156716c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 156816c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::mergeInfoLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, 156916c4d154dca43c662571129af31b27433b919a32Adam Lesinski const SortedVector<AssetDir::FileInfo>* pContents) 157016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 157116c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 157216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Merge what we found in this directory with what we found in 157316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * other places. 157416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 157516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Two basic approaches: 157616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * (1) Create a new array that holds the unique values of the two 157716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * arrays. 157816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * (2) Take the elements from pContents and shove them into pMergedInfo. 157916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 158016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Because these are vectors of complex objects, moving elements around 158116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * inside the vector requires constructing new objects and allocating 158216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * storage for members. With approach #1, we're always adding to the 158316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * end, whereas with #2 we could be inserting multiple elements at the 158416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * front of the vector. Approach #1 requires a full copy of the 158516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * contents of pMergedInfo, but approach #2 requires the same copy for 158616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * every insertion at the front of pMergedInfo. 158716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 158816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * (We should probably use a SortedVector interface that allows us to 158916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * just stuff items in, trusting us to maintain the sort order.) 159016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 159116c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pNewSorted; 159216c4d154dca43c662571129af31b27433b919a32Adam Lesinski int mergeMax, contMax; 159316c4d154dca43c662571129af31b27433b919a32Adam Lesinski int mergeIdx, contIdx; 159416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 159516c4d154dca43c662571129af31b27433b919a32Adam Lesinski pNewSorted = new SortedVector<AssetDir::FileInfo>; 159616c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeMax = pMergedInfo->size(); 159716c4d154dca43c662571129af31b27433b919a32Adam Lesinski contMax = pContents->size(); 159816c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeIdx = contIdx = 0; 159916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 160016c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (mergeIdx < mergeMax || contIdx < contMax) { 160116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mergeIdx == mergeMax) { 160216c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* hit end of "merge" list, copy rest of "contents" */ 160316c4d154dca43c662571129af31b27433b919a32Adam Lesinski pNewSorted->add(pContents->itemAt(contIdx)); 160416c4d154dca43c662571129af31b27433b919a32Adam Lesinski contIdx++; 160516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else if (contIdx == contMax) { 160616c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* hit end of "cont" list, copy rest of "merge" */ 160716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pNewSorted->add(pMergedInfo->itemAt(mergeIdx)); 160816c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeIdx++; 160916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else if (pMergedInfo->itemAt(mergeIdx) == pContents->itemAt(contIdx)) 161016c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 161116c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* items are identical, add newer and advance both indices */ 161216c4d154dca43c662571129af31b27433b919a32Adam Lesinski pNewSorted->add(pContents->itemAt(contIdx)); 161316c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeIdx++; 161416c4d154dca43c662571129af31b27433b919a32Adam Lesinski contIdx++; 161516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else if (pMergedInfo->itemAt(mergeIdx) < pContents->itemAt(contIdx)) 161616c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 161716c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* "merge" is lower, add that one */ 161816c4d154dca43c662571129af31b27433b919a32Adam Lesinski pNewSorted->add(pMergedInfo->itemAt(mergeIdx)); 161916c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeIdx++; 162016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 162116c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* "cont" is lower, add that one */ 162216c4d154dca43c662571129af31b27433b919a32Adam Lesinski assert(pContents->itemAt(contIdx) < pMergedInfo->itemAt(mergeIdx)); 162316c4d154dca43c662571129af31b27433b919a32Adam Lesinski pNewSorted->add(pContents->itemAt(contIdx)); 162416c4d154dca43c662571129af31b27433b919a32Adam Lesinski contIdx++; 162516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 162616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 162716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 162816c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 162916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Overwrite the "merged" list with the new stuff. 163016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 163116c4d154dca43c662571129af31b27433b919a32Adam Lesinski *pMergedInfo = *pNewSorted; 163216c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete pNewSorted; 163316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 163416c4d154dca43c662571129af31b27433b919a32Adam Lesinski#if 0 // for Vector, rather than SortedVector 163516c4d154dca43c662571129af31b27433b919a32Adam Lesinski int i, j; 163616c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (i = pContents->size() -1; i >= 0; i--) { 163716c4d154dca43c662571129af31b27433b919a32Adam Lesinski bool add = true; 163816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 163916c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (j = pMergedInfo->size() -1; j >= 0; j--) { 164016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* case-sensitive comparisons, to behave like UNIX fs */ 164116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (strcmp(pContents->itemAt(i).mFileName, 164216c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->itemAt(j).mFileName) == 0) 164316c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 164416c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* match, don't add this entry */ 164516c4d154dca43c662571129af31b27433b919a32Adam Lesinski add = false; 164616c4d154dca43c662571129af31b27433b919a32Adam Lesinski break; 164716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 164816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 164916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 165016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (add) 165116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->add(pContents->itemAt(i)); 165216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 165316c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 165416c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 165516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 165616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 165716c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 165816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Load all files into the file name cache. We want to do this across 165916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * all combinations of { appname, locale, vendor }, performing a recursive 166016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * directory traversal. 166116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 166216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * This is not the most efficient data structure. Also, gathering the 166316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * information as we needed it (file-by-file or directory-by-directory) 166416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * would be faster. However, on the actual device, 99% of the files will 166516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * live in Zip archives, so this list will be very small. The trouble 166616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * is that we have to check the "loose" files first, so it's important 166716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * that we don't beat the filesystem silly looking for files that aren't 166816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * there. 166916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 167016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Note on thread safety: this is the only function that causes updates 167116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * to mCache, and anybody who tries to use it will call here if !mCacheValid, 167216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * so we need to employ a mutex here. 167316c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 167416c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::loadFileNameCacheLocked(void) 167516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 167616c4d154dca43c662571129af31b27433b919a32Adam Lesinski assert(!mCacheValid); 167716c4d154dca43c662571129af31b27433b919a32Adam Lesinski assert(mCache.size() == 0); 167816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 167916c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifdef DO_TIMINGS // need to link against -lrt for this now 168016c4d154dca43c662571129af31b27433b919a32Adam Lesinski DurationTimer timer; 168116c4d154dca43c662571129af31b27433b919a32Adam Lesinski timer.start(); 168216c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 168316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 168416c4d154dca43c662571129af31b27433b919a32Adam Lesinski fncScanLocked(&mCache, ""); 168516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 168616c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifdef DO_TIMINGS 168716c4d154dca43c662571129af31b27433b919a32Adam Lesinski timer.stop(); 168816c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGD("Cache scan took %.3fms\n", 168916c4d154dca43c662571129af31b27433b919a32Adam Lesinski timer.durationUsecs() / 1000.0); 169016c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 169116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 169216c4d154dca43c662571129af31b27433b919a32Adam Lesinski#if 0 169316c4d154dca43c662571129af31b27433b919a32Adam Lesinski int i; 169416c4d154dca43c662571129af31b27433b919a32Adam Lesinski printf("CACHED FILE LIST (%d entries):\n", mCache.size()); 169516c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (i = 0; i < (int) mCache.size(); i++) { 169616c4d154dca43c662571129af31b27433b919a32Adam Lesinski printf(" %d: (%d) '%s'\n", i, 169716c4d154dca43c662571129af31b27433b919a32Adam Lesinski mCache.itemAt(i).getFileType(), 169816c4d154dca43c662571129af31b27433b919a32Adam Lesinski (const char*) mCache.itemAt(i).getFileName()); 169916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 170016c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 170116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 170216c4d154dca43c662571129af31b27433b919a32Adam Lesinski mCacheValid = true; 170316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 170416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 170516c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 170616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan up to 8 versions of the specified directory. 170716c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 170816c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::fncScanLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, 170916c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* dirName) 171016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 171116c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t i = mAssetPaths.size(); 171216c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (i > 0) { 171316c4d154dca43c662571129af31b27433b919a32Adam Lesinski i--; 171416c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap = mAssetPaths.itemAt(i); 171516c4d154dca43c662571129af31b27433b919a32Adam Lesinski fncScanAndMergeDirLocked(pMergedInfo, ap, NULL, NULL, dirName); 171616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mLocale != NULL) 171716c4d154dca43c662571129af31b27433b919a32Adam Lesinski fncScanAndMergeDirLocked(pMergedInfo, ap, mLocale, NULL, dirName); 171816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mVendor != NULL) 171916c4d154dca43c662571129af31b27433b919a32Adam Lesinski fncScanAndMergeDirLocked(pMergedInfo, ap, NULL, mVendor, dirName); 172016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mLocale != NULL && mVendor != NULL) 172116c4d154dca43c662571129af31b27433b919a32Adam Lesinski fncScanAndMergeDirLocked(pMergedInfo, ap, mLocale, mVendor, dirName); 172216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 172316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 172416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 172516c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 172616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Recursively scan this directory and all subdirs. 172716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 172816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * This is similar to scanAndMergeDir, but we don't remove the .EXCLUDE 172916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * files, and we prepend the extended partial path to the filenames. 173016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 173116c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::fncScanAndMergeDirLocked( 173216c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pMergedInfo, 173316c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap, const char* locale, const char* vendor, 173416c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* dirName) 173516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 173616c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pContents; 173716c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 partialPath; 173816c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 fullPath; 173916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 174016c4d154dca43c662571129af31b27433b919a32Adam Lesinski // XXX This is broken -- the filename cache needs to hold the base 174116c4d154dca43c662571129af31b27433b919a32Adam Lesinski // asset path separately from its filename. 174216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 174316c4d154dca43c662571129af31b27433b919a32Adam Lesinski partialPath = createPathNameLocked(ap, locale, vendor); 174416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirName[0] != '\0') { 174516c4d154dca43c662571129af31b27433b919a32Adam Lesinski partialPath.appendPath(dirName); 174616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 174716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 174816c4d154dca43c662571129af31b27433b919a32Adam Lesinski fullPath = partialPath; 174916c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents = scanDirLocked(fullPath); 175016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pContents == NULL) { 175116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; // directory did not exist 175216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 175316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 175416c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 175516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan all subdirectories of the current dir, merging what we find 175616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * into "pMergedInfo". 175716c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 175816c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (int i = 0; i < (int) pContents->size(); i++) { 175916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pContents->itemAt(i).getFileType() == kFileTypeDirectory) { 176016c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 subdir(dirName); 176116c4d154dca43c662571129af31b27433b919a32Adam Lesinski subdir.appendPath(pContents->itemAt(i).getFileName()); 176216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 176316c4d154dca43c662571129af31b27433b919a32Adam Lesinski fncScanAndMergeDirLocked(pMergedInfo, ap, locale, vendor, subdir.string()); 176416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 176516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 176616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 176716c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 176816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * To be consistent, we want entries for the root directory. If 176916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * we're the root, add one now. 177016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 177116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirName[0] == '\0') { 177216c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir::FileInfo tmpInfo; 177316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 177416c4d154dca43c662571129af31b27433b919a32Adam Lesinski tmpInfo.set(String8(""), kFileTypeDirectory); 177516c4d154dca43c662571129af31b27433b919a32Adam Lesinski tmpInfo.setSourceName(createPathNameLocked(ap, locale, vendor)); 177616c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents->add(tmpInfo); 177716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 177816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 177916c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 178016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * We want to prepend the extended partial path to every entry in 178116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * "pContents". It's the same value for each entry, so this will 178216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * not change the sorting order of the vector contents. 178316c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 178416c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (int i = 0; i < (int) pContents->size(); i++) { 178516c4d154dca43c662571129af31b27433b919a32Adam Lesinski const AssetDir::FileInfo& info = pContents->itemAt(i); 178616c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents->editItemAt(i).setFileName(partialPath.appendPathCopy(info.getFileName())); 178716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 178816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 178916c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeInfoLocked(pMergedInfo, pContents); 179016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 179116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 179216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 179316c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 179416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Trash the cache. 179516c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 179616c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::purgeFileNameCacheLocked(void) 179716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 179816c4d154dca43c662571129af31b27433b919a32Adam Lesinski mCacheValid = false; 179916c4d154dca43c662571129af31b27433b919a32Adam Lesinski mCache.clear(); 180016c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 180116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 180216c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 180316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * =========================================================================== 180416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * AssetManager::SharedZip 180516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * =========================================================================== 180616c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 180716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 180816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 180916c4d154dca43c662571129af31b27433b919a32Adam LesinskiMutex AssetManager::SharedZip::gLock; 181016c4d154dca43c662571129af31b27433b919a32Adam LesinskiDefaultKeyedVector<String8, wp<AssetManager::SharedZip> > AssetManager::SharedZip::gOpen; 181116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 181216c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetManager::SharedZip::SharedZip(const String8& path, time_t modWhen) 181316c4d154dca43c662571129af31b27433b919a32Adam Lesinski : mPath(path), mZipFile(NULL), mModWhen(modWhen), 181416c4d154dca43c662571129af31b27433b919a32Adam Lesinski mResourceTableAsset(NULL), mResourceTable(NULL) 181516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 181616c4d154dca43c662571129af31b27433b919a32Adam Lesinski //ALOGI("Creating SharedZip %p %s\n", this, (const char*)mPath); 181716c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipFile = new ZipFileRO; 181816c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("+++ opening zip '%s'\n", mPath.string()); 181916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mZipFile->open(mPath.string()) != NO_ERROR) { 182016c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGD("failed to open Zip archive '%s'\n", mPath.string()); 182116c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete mZipFile; 182216c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipFile = NULL; 182316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 182416c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 182516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 182616c4d154dca43c662571129af31b27433b919a32Adam Lesinskisp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path) 182716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 182816c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(gLock); 182916c4d154dca43c662571129af31b27433b919a32Adam Lesinski time_t modWhen = getFileModDate(path); 183016c4d154dca43c662571129af31b27433b919a32Adam Lesinski sp<SharedZip> zip = gOpen.valueFor(path).promote(); 183116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (zip != NULL && zip->mModWhen == modWhen) { 183216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip; 183316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 183416c4d154dca43c662571129af31b27433b919a32Adam Lesinski zip = new SharedZip(path, modWhen); 183516c4d154dca43c662571129af31b27433b919a32Adam Lesinski gOpen.add(path, zip); 183616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip; 183716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 183816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 183916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 184016c4d154dca43c662571129af31b27433b919a32Adam LesinskiZipFileRO* AssetManager::SharedZip::getZip() 184116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 184216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mZipFile; 184316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 184416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 184516c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::SharedZip::getResourceTableAsset() 184616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 184716c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Getting from SharedZip %p resource asset %p\n", this, mResourceTableAsset); 184816c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mResourceTableAsset; 184916c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 185016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 185116c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::SharedZip::setResourceTableAsset(Asset* asset) 185216c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 185316c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 185416c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(gLock); 185516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mResourceTableAsset == NULL) { 185616c4d154dca43c662571129af31b27433b919a32Adam Lesinski mResourceTableAsset = asset; 185716c4d154dca43c662571129af31b27433b919a32Adam Lesinski // This is not thread safe the first time it is called, so 185816c4d154dca43c662571129af31b27433b919a32Adam Lesinski // do it here with the global lock held. 185916c4d154dca43c662571129af31b27433b919a32Adam Lesinski asset->getBuffer(true); 186016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return asset; 186116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 186216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 186316c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete asset; 186416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mResourceTableAsset; 186516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 186616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 186716c4d154dca43c662571129af31b27433b919a32Adam LesinskiResTable* AssetManager::SharedZip::getResourceTable() 186816c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 186916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Getting from SharedZip %p resource table %p\n", this, mResourceTable); 187016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mResourceTable; 187116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 187216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 187316c4d154dca43c662571129af31b27433b919a32Adam LesinskiResTable* AssetManager::SharedZip::setResourceTable(ResTable* res) 187416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 187516c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 187616c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(gLock); 187716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mResourceTable == NULL) { 187816c4d154dca43c662571129af31b27433b919a32Adam Lesinski mResourceTable = res; 187916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return res; 188016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 188116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 188216c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete res; 188316c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mResourceTable; 188416c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 188516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 188616c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::SharedZip::isUpToDate() 188716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 188816c4d154dca43c662571129af31b27433b919a32Adam Lesinski time_t modWhen = getFileModDate(mPath.string()); 188916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mModWhen == modWhen; 189016c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 189116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 189216c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetManager::SharedZip::~SharedZip() 189316c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 189416c4d154dca43c662571129af31b27433b919a32Adam Lesinski //ALOGI("Destroying SharedZip %p %s\n", this, (const char*)mPath); 189516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mResourceTable != NULL) { 189616c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete mResourceTable; 189716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 189816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mResourceTableAsset != NULL) { 189916c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete mResourceTableAsset; 190016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 190116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mZipFile != NULL) { 190216c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete mZipFile; 190316c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Closed '%s'\n", mPath.string()); 190416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 190516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 190616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 190716c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 190816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * =========================================================================== 190916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * AssetManager::ZipSet 191016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * =========================================================================== 191116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 191216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 191316c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 191416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Constructor. 191516c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 191616c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetManager::ZipSet::ZipSet(void) 191716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 191816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 191916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 192016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 192116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Destructor. Close any open archives. 192216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 192316c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetManager::ZipSet::~ZipSet(void) 192416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 192516c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t N = mZipFile.size(); 192616c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (size_t i = 0; i < N; i++) 192716c4d154dca43c662571129af31b27433b919a32Adam Lesinski closeZip(i); 192816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 192916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 193016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 193116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Close a Zip file and reset the entry. 193216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 193316c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::ZipSet::closeZip(int idx) 193416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 193516c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipFile.editItemAt(idx) = NULL; 193616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 193716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 193816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 193916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 194016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Retrieve the appropriate Zip file from the set. 194116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 194216c4d154dca43c662571129af31b27433b919a32Adam LesinskiZipFileRO* AssetManager::ZipSet::getZip(const String8& path) 194316c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 194416c4d154dca43c662571129af31b27433b919a32Adam Lesinski int idx = getIndex(path); 194516c4d154dca43c662571129af31b27433b919a32Adam Lesinski sp<SharedZip> zip = mZipFile[idx]; 194616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (zip == NULL) { 194716c4d154dca43c662571129af31b27433b919a32Adam Lesinski zip = SharedZip::get(path); 194816c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipFile.editItemAt(idx) = zip; 194916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 195016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip->getZip(); 195116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 195216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 195316c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::ZipSet::getZipResourceTableAsset(const String8& path) 195416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 195516c4d154dca43c662571129af31b27433b919a32Adam Lesinski int idx = getIndex(path); 195616c4d154dca43c662571129af31b27433b919a32Adam Lesinski sp<SharedZip> zip = mZipFile[idx]; 195716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (zip == NULL) { 195816c4d154dca43c662571129af31b27433b919a32Adam Lesinski zip = SharedZip::get(path); 195916c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipFile.editItemAt(idx) = zip; 196016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 196116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip->getResourceTableAsset(); 196216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 196316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 196416c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::ZipSet::setZipResourceTableAsset(const String8& path, 196516c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* asset) 196616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 196716c4d154dca43c662571129af31b27433b919a32Adam Lesinski int idx = getIndex(path); 196816c4d154dca43c662571129af31b27433b919a32Adam Lesinski sp<SharedZip> zip = mZipFile[idx]; 196916c4d154dca43c662571129af31b27433b919a32Adam Lesinski // doesn't make sense to call before previously accessing. 197016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip->setResourceTableAsset(asset); 197116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 197216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 197316c4d154dca43c662571129af31b27433b919a32Adam LesinskiResTable* AssetManager::ZipSet::getZipResourceTable(const String8& path) 197416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 197516c4d154dca43c662571129af31b27433b919a32Adam Lesinski int idx = getIndex(path); 197616c4d154dca43c662571129af31b27433b919a32Adam Lesinski sp<SharedZip> zip = mZipFile[idx]; 197716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (zip == NULL) { 197816c4d154dca43c662571129af31b27433b919a32Adam Lesinski zip = SharedZip::get(path); 197916c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipFile.editItemAt(idx) = zip; 198016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 198116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip->getResourceTable(); 198216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 198316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 198416c4d154dca43c662571129af31b27433b919a32Adam LesinskiResTable* AssetManager::ZipSet::setZipResourceTable(const String8& path, 198516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ResTable* res) 198616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 198716c4d154dca43c662571129af31b27433b919a32Adam Lesinski int idx = getIndex(path); 198816c4d154dca43c662571129af31b27433b919a32Adam Lesinski sp<SharedZip> zip = mZipFile[idx]; 198916c4d154dca43c662571129af31b27433b919a32Adam Lesinski // doesn't make sense to call before previously accessing. 199016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip->setResourceTable(res); 199116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 199216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 199316c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 199416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Generate the partial pathname for the specified archive. The caller 199516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * gets to prepend the asset root directory. 199616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 199716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Returns something like "common/en-US-noogle.jar". 199816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 199916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/*static*/ String8 AssetManager::ZipSet::getPathName(const char* zipPath) 200016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 200116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return String8(zipPath); 200216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 200316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 200416c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::ZipSet::isUpToDate() 200516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 200616c4d154dca43c662571129af31b27433b919a32Adam Lesinski const size_t N = mZipFile.size(); 200716c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (size_t i=0; i<N; i++) { 200816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mZipFile[i] != NULL && !mZipFile[i]->isUpToDate()) { 200916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 201016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 201116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 201216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 201316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 201416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 201516c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 201616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Compute the zip file's index. 201716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 201816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * "appName", "locale", and "vendor" should be set to NULL to indicate the 201916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * default directory. 202016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 202116c4d154dca43c662571129af31b27433b919a32Adam Lesinskiint AssetManager::ZipSet::getIndex(const String8& zip) const 202216c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 202316c4d154dca43c662571129af31b27433b919a32Adam Lesinski const size_t N = mZipPath.size(); 202416c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (size_t i=0; i<N; i++) { 202516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mZipPath[i] == zip) { 202616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return i; 202716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 202816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 202916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 203016c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipPath.add(zip); 203116c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipFile.add(NULL); 203216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 203316c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mZipPath.size()-1; 203416c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 2035