AssetManager.cpp revision 30113131fb958850ef92c6a8f7f2aa2ed92a8ffe
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> 4448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#include <string.h> // strerror 4516c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <strings.h> 4616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 4716c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifndef TEMP_FAILURE_RETRY 4816c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* Used to retry syscalls that can return EINTR. */ 4916c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define TEMP_FAILURE_RETRY(exp) ({ \ 5016c4d154dca43c662571129af31b27433b919a32Adam Lesinski typeof (exp) _rc; \ 5116c4d154dca43c662571129af31b27433b919a32Adam Lesinski do { \ 5216c4d154dca43c662571129af31b27433b919a32Adam Lesinski _rc = (exp); \ 5316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } while (_rc == -1 && errno == EINTR); \ 5416c4d154dca43c662571129af31b27433b919a32Adam Lesinski _rc; }) 5516c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 5616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 5716c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifdef HAVE_ANDROID_OS 5816c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define MY_TRACE_BEGIN(x) ATRACE_BEGIN(x) 5916c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define MY_TRACE_END() ATRACE_END() 6016c4d154dca43c662571129af31b27433b919a32Adam Lesinski#else 6116c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define MY_TRACE_BEGIN(x) 6216c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define MY_TRACE_END() 6316c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 6416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 6516c4d154dca43c662571129af31b27433b919a32Adam Lesinskiusing namespace android; 6616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 6716c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 6816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Names for default app, locale, and vendor. We might want to change 6916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * these to be an actual locale, e.g. always use en-US as the default. 7016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 7116c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kDefaultLocale = "default"; 7216c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kDefaultVendor = "default"; 7316c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kAssetsRoot = "assets"; 7416c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kAppZipName = NULL; //"classes.jar"; 7516c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kSystemAssets = "framework/framework-res.apk"; 7648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadstatic const char* kResourceCache = "resource-cache"; 77de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinskistatic const char* kAndroidManifest = "AndroidManifest.xml"; 7816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 7916c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kExcludeExtension = ".EXCLUDE"; 8016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 8116c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic Asset* const kExcludedAsset = (Asset*) 0xd000000d; 8216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 8316c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic volatile int32_t gCount = 0; 8416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 8565a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstadconst char* AssetManager::RESOURCES_FILENAME = "resources.arsc"; 8648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::IDMAP_BIN = "/system/bin/idmap"; 8748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::OVERLAY_DIR = "/vendor/overlay"; 8848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::TARGET_PACKAGE_NAME = "android"; 8948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk"; 9048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::IDMAP_DIR = "/data/resource-cache"; 9165a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad 9216c4d154dca43c662571129af31b27433b919a32Adam Lesinskinamespace { 9316c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 idmapPathForPackagePath(const String8& pkgPath) 9416c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 9516c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* root = getenv("ANDROID_DATA"); 9616c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set"); 9716c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(root); 9848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad path.appendPath(kResourceCache); 9916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 10016c4d154dca43c662571129af31b27433b919a32Adam Lesinski char buf[256]; // 256 chars should be enough for anyone... 10116c4d154dca43c662571129af31b27433b919a32Adam Lesinski strncpy(buf, pkgPath.string(), 255); 10216c4d154dca43c662571129af31b27433b919a32Adam Lesinski buf[255] = '\0'; 10316c4d154dca43c662571129af31b27433b919a32Adam Lesinski char* filename = buf; 10416c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (*filename && *filename == '/') { 10516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ++filename; 10616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 10716c4d154dca43c662571129af31b27433b919a32Adam Lesinski char* p = filename; 10816c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (*p) { 10916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (*p == '/') { 11016c4d154dca43c662571129af31b27433b919a32Adam Lesinski *p = '@'; 11116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 11216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ++p; 11316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 11416c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(filename); 11516c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.append("@idmap"); 11616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 11716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return path; 11816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 11916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 12016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 12116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Like strdup(), but uses C++ "new" operator instead of malloc. 12216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 12316c4d154dca43c662571129af31b27433b919a32Adam Lesinski static char* strdupNew(const char* str) 12416c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 12516c4d154dca43c662571129af31b27433b919a32Adam Lesinski char* newStr; 12616c4d154dca43c662571129af31b27433b919a32Adam Lesinski int len; 12716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 12816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (str == NULL) 12916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 13016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 13116c4d154dca43c662571129af31b27433b919a32Adam Lesinski len = strlen(str); 13216c4d154dca43c662571129af31b27433b919a32Adam Lesinski newStr = new char[len+1]; 13316c4d154dca43c662571129af31b27433b919a32Adam Lesinski memcpy(newStr, str, len+1); 13416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 13516c4d154dca43c662571129af31b27433b919a32Adam Lesinski return newStr; 13616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 13716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 13816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 13916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 14016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * =========================================================================== 14116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * AssetManager 14216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * =========================================================================== 14316c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 14416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 14516c4d154dca43c662571129af31b27433b919a32Adam Lesinskiint32_t AssetManager::getGlobalCount() 14616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 14716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return gCount; 14816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 14916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 15016c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetManager::AssetManager(CacheMode cacheMode) 15116c4d154dca43c662571129af31b27433b919a32Adam Lesinski : mLocale(NULL), mVendor(NULL), 15216c4d154dca43c662571129af31b27433b919a32Adam Lesinski mResources(NULL), mConfig(new ResTable_config), 15316c4d154dca43c662571129af31b27433b919a32Adam Lesinski mCacheMode(cacheMode), mCacheValid(false) 15416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 15516c4d154dca43c662571129af31b27433b919a32Adam Lesinski int count = android_atomic_inc(&gCount)+1; 15616c4d154dca43c662571129af31b27433b919a32Adam Lesinski //ALOGI("Creating AssetManager %p #%d\n", this, count); 15716c4d154dca43c662571129af31b27433b919a32Adam Lesinski memset(mConfig, 0, sizeof(ResTable_config)); 15816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 15916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 16016c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetManager::~AssetManager(void) 16116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 16216c4d154dca43c662571129af31b27433b919a32Adam Lesinski int count = android_atomic_dec(&gCount); 16316c4d154dca43c662571129af31b27433b919a32Adam Lesinski //ALOGI("Destroying AssetManager in %p #%d\n", this, count); 16416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 16516c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete mConfig; 16616c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete mResources; 16716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 16816c4d154dca43c662571129af31b27433b919a32Adam Lesinski // don't have a String class yet, so make sure we clean up 16916c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete[] mLocale; 17016c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete[] mVendor; 17116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 17216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 173a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamathbool AssetManager::addAssetPath(const String8& path, int32_t* cookie) 17416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 17516c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 17616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 17716c4d154dca43c662571129af31b27433b919a32Adam Lesinski asset_path ap; 17816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 17916c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 realPath(path); 18016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (kAppZipName) { 18116c4d154dca43c662571129af31b27433b919a32Adam Lesinski realPath.appendPath(kAppZipName); 18216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 18316c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.type = ::getFileType(realPath.string()); 18416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type == kFileTypeRegular) { 18516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.path = realPath; 18616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 18716c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.path = path; 18816c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.type = ::getFileType(path.string()); 18916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type != kFileTypeDirectory && ap.type != kFileTypeRegular) { 19016c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("Asset path %s is neither a directory nor file (type=%d).", 19116c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.string(), (int)ap.type); 19216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 19316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 19416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 19516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 19616c4d154dca43c662571129af31b27433b919a32Adam Lesinski // Skip if we have it already. 19716c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (size_t i=0; i<mAssetPaths.size(); i++) { 19816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mAssetPaths[i].path == ap.path) { 19916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (cookie) { 200a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath *cookie = static_cast<int32_t>(i+1); 20116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 20216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 20316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 20416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 20516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 20616c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("In %p Asset %s path: %s", this, 20716c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.type == kFileTypeDirectory ? "dir" : "zip", ap.path.string()); 20816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 209de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski // Check that the path has an AndroidManifest.xml 210de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski Asset* manifestAsset = const_cast<AssetManager*>(this)->openNonAssetInPathLocked( 211de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski kAndroidManifest, Asset::ACCESS_BUFFER, ap); 212de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski if (manifestAsset == NULL) { 213de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski // This asset path does not contain any resources. 214de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski delete manifestAsset; 215de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski return false; 216de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski } 217de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski delete manifestAsset; 218de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski 21916c4d154dca43c662571129af31b27433b919a32Adam Lesinski mAssetPaths.add(ap); 22016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 22116c4d154dca43c662571129af31b27433b919a32Adam Lesinski // new paths are always added at the end 22216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (cookie) { 223a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath *cookie = static_cast<int32_t>(mAssetPaths.size()); 22416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 22516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 22648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#ifdef HAVE_ANDROID_OS 22748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad // Load overlays, if any 22848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad asset_path oap; 22948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad for (size_t idx = 0; mZipSet.getOverlay(ap.path, idx, &oap); idx++) { 23048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad mAssetPaths.add(oap); 23116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 23248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#endif 23316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 2347df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba if (mResources != NULL) { 2357df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba appendPathToResTable(ap); 2367df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } 2377df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba 23816c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 23916c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 24016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 24148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadbool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie) 24265a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad{ 24348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad const String8 idmapPath = idmapPathForPackagePath(packagePath); 24465a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad 24548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad AutoMutex _l(mLock); 24665a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad 24748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad for (size_t i = 0; i < mAssetPaths.size(); ++i) { 24848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if (mAssetPaths[i].idmap == idmapPath) { 24948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad *cookie = static_cast<int32_t>(i + 1); 25048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad return true; 25148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad } 25248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad } 25365a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad 25448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad Asset* idmap = NULL; 25548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if ((idmap = openAssetFromFileLocked(idmapPath, Asset::ACCESS_BUFFER)) == NULL) { 25648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad ALOGW("failed to open idmap file %s\n", idmapPath.string()); 25716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 25816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 25916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 26048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad String8 targetPath; 26148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad String8 overlayPath; 26248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if (!ResTable::getIdmapInfo(idmap->getBuffer(false), idmap->getLength(), 263f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski NULL, NULL, NULL, &targetPath, &overlayPath)) { 26448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad ALOGW("failed to read idmap file %s\n", idmapPath.string()); 26548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad delete idmap; 26616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 26716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 26848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad delete idmap; 26916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 27048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if (overlayPath != packagePath) { 27148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad ALOGW("idmap file %s inconcistent: expected path %s does not match actual path %s\n", 27248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad idmapPath.string(), packagePath.string(), overlayPath.string()); 27316c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 27416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 27548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if (access(targetPath.string(), R_OK) != 0) { 27648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad ALOGW("failed to access file %s: %s\n", targetPath.string(), strerror(errno)); 27716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 27816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 27948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if (access(idmapPath.string(), R_OK) != 0) { 28048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad ALOGW("failed to access file %s: %s\n", idmapPath.string(), strerror(errno)); 28116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 28216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 28348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if (access(overlayPath.string(), R_OK) != 0) { 28448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad ALOGW("failed to access file %s: %s\n", overlayPath.string(), strerror(errno)); 28516c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 28616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 287560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath 28848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad asset_path oap; 28948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad oap.path = overlayPath; 29048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad oap.type = ::getFileType(overlayPath.string()); 29148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad oap.idmap = idmapPath; 29248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#if 0 29348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad ALOGD("Overlay added: targetPath=%s overlayPath=%s idmapPath=%s\n", 29448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad targetPath.string(), overlayPath.string(), idmapPath.string()); 29548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#endif 29648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad mAssetPaths.add(oap); 29748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad *cookie = static_cast<int32_t>(mAssetPaths.size()); 298560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath 29930113131fb958850ef92c6a8f7f2aa2ed92a8ffeMårten Kongstad if (mResources != NULL) { 30030113131fb958850ef92c6a8f7f2aa2ed92a8ffeMårten Kongstad appendPathToResTable(oap); 30130113131fb958850ef92c6a8f7f2aa2ed92a8ffeMårten Kongstad } 30230113131fb958850ef92c6a8f7f2aa2ed92a8ffeMårten Kongstad 30348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad return true; 30448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad } 30516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 30648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadbool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApkPath, 3071cbea39fe1740d7d1c3e4aa0e4771a99a56c79efNick Kralevich uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize) 30816c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 30948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad AutoMutex _l(mLock); 31048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad const String8 paths[2] = { String8(targetApkPath), String8(overlayApkPath) }; 31116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ResTable tables[2]; 31216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 31316c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (int i = 0; i < 2; ++i) { 31416c4d154dca43c662571129af31b27433b919a32Adam Lesinski asset_path ap; 31516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ap.type = kFileTypeRegular; 31648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad ap.path = paths[i]; 31716c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap); 31816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ass == NULL) { 31916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("failed to find resources.arsc in %s\n", ap.path.string()); 32048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad return false; 32116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 322f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski tables[i].add(ass); 32316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 32416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 32548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad return tables[0].createIdmap(tables[1], targetCrc, overlayCrc, 32648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR; 32716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 32816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 32916c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::addDefaultAssets() 33016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 33116c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* root = getenv("ANDROID_ROOT"); 33216c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_ROOT not set"); 33316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 33416c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(root); 33516c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(kSystemAssets); 33616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 33716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return addAssetPath(path, NULL); 33816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 33916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 340a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamathint32_t AssetManager::nextAssetPath(const int32_t cookie) const 34116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 34216c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 343a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath const size_t next = static_cast<size_t>(cookie) + 1; 344a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath return next > mAssetPaths.size() ? -1 : next; 34516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 34616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 347a0c6260705c841f501282e0e337970ca9a00e064Narayan KamathString8 AssetManager::getAssetPath(const int32_t cookie) const 34816c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 34916c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 350a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath const size_t which = static_cast<size_t>(cookie) - 1; 35116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (which < mAssetPaths.size()) { 35216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mAssetPaths[which].path; 35316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 35416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return String8(); 35516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 35616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 35716c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 35816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Set the current locale. Use NULL to indicate no locale. 35916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 36016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Close and reopen Zip archives as appropriate, and reset cached 36116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * information in the locale-specific sections of the tree. 36216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 36316c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::setLocale(const char* locale) 36416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 36516c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 36616c4d154dca43c662571129af31b27433b919a32Adam Lesinski setLocaleLocked(locale); 36716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 36816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 369e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath 370e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamathstatic const char kFilPrefix[] = "fil"; 371e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamathstatic const char kTlPrefix[] = "tl"; 372e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath 373e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath// The sizes of the prefixes, excluding the 0 suffix. 374e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath// char. 375e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamathstatic const int kFilPrefixLen = sizeof(kFilPrefix) - 1; 376e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamathstatic const int kTlPrefixLen = sizeof(kTlPrefix) - 1; 377e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath 37816c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::setLocaleLocked(const char* locale) 37916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 38016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mLocale != NULL) { 38116c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* previously set, purge cached data */ 38216c4d154dca43c662571129af31b27433b919a32Adam Lesinski purgeFileNameCacheLocked(); 38316c4d154dca43c662571129af31b27433b919a32Adam Lesinski //mZipSet.purgeLocale(); 38416c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete[] mLocale; 38516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 386c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes 387e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath // If we're attempting to set a locale that starts with "fil", 388e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath // we should convert it to "tl" for backwards compatibility since 389e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath // we've been using "tl" instead of "fil" prior to L. 390e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath // 391e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath // If the resource table already has entries for "fil", we use that 392e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath // instead of attempting a fallback. 393e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath if (strncmp(locale, kFilPrefix, kFilPrefixLen) == 0) { 394e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath Vector<String8> locales; 395fec5106c8ea5791614385c17bd1bf0ecff9afe9aNarayan Kamath ResTable* res = mResources; 396fec5106c8ea5791614385c17bd1bf0ecff9afe9aNarayan Kamath if (res != NULL) { 397fec5106c8ea5791614385c17bd1bf0ecff9afe9aNarayan Kamath res->getLocales(&locales); 398fec5106c8ea5791614385c17bd1bf0ecff9afe9aNarayan Kamath } 399e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath const size_t localesSize = locales.size(); 400e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath bool hasFil = false; 401e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath for (size_t i = 0; i < localesSize; ++i) { 402e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath if (locales[i].find(kFilPrefix) == 0) { 403e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath hasFil = true; 404e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath break; 405e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath } 406e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath } 407e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath 408e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath 409e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath if (!hasFil) { 410e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath const size_t newLocaleLen = strlen(locale); 411e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath // This isn't a bug. We really do want mLocale to be 1 byte 412e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath // shorter than locale, because we're replacing "fil-" with 413e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath // "tl-". 414e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath mLocale = new char[newLocaleLen]; 415e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath // Copy over "tl". 416e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath memcpy(mLocale, kTlPrefix, kTlPrefixLen); 417e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath // Copy the rest of |locale|, including the terminating '\0'. 418e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath memcpy(mLocale + kTlPrefixLen, locale + kFilPrefixLen, 419e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath newLocaleLen - kFilPrefixLen + 1); 420e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath updateResourceParamsLocked(); 421e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath return; 422e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath } 423e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath } 424e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath 42516c4d154dca43c662571129af31b27433b919a32Adam Lesinski mLocale = strdupNew(locale); 42616c4d154dca43c662571129af31b27433b919a32Adam Lesinski updateResourceParamsLocked(); 42716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 42816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 42916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 43016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Set the current vendor. Use NULL to indicate no vendor. 43116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 43216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Close and reopen Zip archives as appropriate, and reset cached 43316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * information in the vendor-specific sections of the tree. 43416c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 43516c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::setVendor(const char* vendor) 43616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 43716c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 43816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 43916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mVendor != NULL) { 44016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* previously set, purge cached data */ 44116c4d154dca43c662571129af31b27433b919a32Adam Lesinski purgeFileNameCacheLocked(); 44216c4d154dca43c662571129af31b27433b919a32Adam Lesinski //mZipSet.purgeVendor(); 44316c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete[] mVendor; 44416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 44516c4d154dca43c662571129af31b27433b919a32Adam Lesinski mVendor = strdupNew(vendor); 44616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 44716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 44816c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::setConfiguration(const ResTable_config& config, const char* locale) 44916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 45016c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 45116c4d154dca43c662571129af31b27433b919a32Adam Lesinski *mConfig = config; 45216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (locale) { 45316c4d154dca43c662571129af31b27433b919a32Adam Lesinski setLocaleLocked(locale); 45416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else if (config.language[0] != 0) { 45591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath char spec[RESTABLE_MAX_LOCALE_LEN]; 45691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath config.getBcp47Locale(spec); 45716c4d154dca43c662571129af31b27433b919a32Adam Lesinski setLocaleLocked(spec); 45816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 45916c4d154dca43c662571129af31b27433b919a32Adam Lesinski updateResourceParamsLocked(); 46016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 46116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 46216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 46316c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::getConfiguration(ResTable_config* outConfig) const 46416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 46516c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 46616c4d154dca43c662571129af31b27433b919a32Adam Lesinski *outConfig = *mConfig; 46716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 46816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 46916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 47016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open an asset. 47116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 47216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The data could be; 47316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - In a file on disk (assetBase + fileName). 47416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - In a compressed file on disk (assetBase + fileName.gz). 47516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - In a Zip archive, uncompressed or compressed. 47616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 47716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * It can be in a number of different directories and Zip archives. 47816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The search order is: 47916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - [appname] 48016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - locale + vendor 48116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - "default" + vendor 48216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - locale + "default" 48316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - "default + "default" 48416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - "common" 48516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * - (same as above) 48616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 48716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * To find a particular file, we have to try up to eight paths with 48816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * all three forms of data. 48916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 49016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * We should probably reject requests for "illegal" filenames, e.g. those 49116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * with illegal characters or "../" backward relative paths. 49216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 49316c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::open(const char* fileName, AccessMode mode) 49416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 49516c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 49616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 49716c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); 49816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 49916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 50016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode != CACHE_OFF && !mCacheValid) 50116c4d154dca43c662571129af31b27433b919a32Adam Lesinski loadFileNameCacheLocked(); 50216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 50316c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 assetName(kAssetsRoot); 50416c4d154dca43c662571129af31b27433b919a32Adam Lesinski assetName.appendPath(fileName); 50516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 50616c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 50716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * For each top-level asset path, search for the asset. 50816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 50916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 51016c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t i = mAssetPaths.size(); 51116c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (i > 0) { 51216c4d154dca43c662571129af31b27433b919a32Adam Lesinski i--; 51316c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Looking for asset '%s' in '%s'\n", 51416c4d154dca43c662571129af31b27433b919a32Adam Lesinski assetName.string(), mAssetPaths.itemAt(i).path.string()); 51516c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = openNonAssetInPathLocked(assetName.string(), mode, mAssetPaths.itemAt(i)); 51616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) { 51716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset != kExcludedAsset ? pAsset : NULL; 51816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 51916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 52016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 52116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 52216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 52316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 52416c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 52516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open a non-asset file as if it were an asset. 52616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 52716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The "fileName" is the partial path starting from the application 52816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * name. 52916c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 530de898ff42912bd7ca1bfb099cd439562496765a4Adam LesinskiAsset* AssetManager::openNonAsset(const char* fileName, AccessMode mode, int32_t* outCookie) 53116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 53216c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 53316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 53416c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); 53516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 53616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 53716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode != CACHE_OFF && !mCacheValid) 53816c4d154dca43c662571129af31b27433b919a32Adam Lesinski loadFileNameCacheLocked(); 53916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 54016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 54116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * For each top-level asset path, search for the asset. 54216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 54316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 54416c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t i = mAssetPaths.size(); 54516c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (i > 0) { 54616c4d154dca43c662571129af31b27433b919a32Adam Lesinski i--; 54716c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Looking for non-asset '%s' in '%s'\n", fileName, mAssetPaths.itemAt(i).path.string()); 54816c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = openNonAssetInPathLocked( 54916c4d154dca43c662571129af31b27433b919a32Adam Lesinski fileName, mode, mAssetPaths.itemAt(i)); 55016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) { 551de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski if (outCookie != NULL) *outCookie = static_cast<int32_t>(i + 1); 55216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset != kExcludedAsset ? pAsset : NULL; 55316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 55416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 55516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 55616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 55716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 55816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 559a0c6260705c841f501282e0e337970ca9a00e064Narayan KamathAsset* AssetManager::openNonAsset(const int32_t cookie, const char* fileName, AccessMode mode) 56016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 561a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath const size_t which = static_cast<size_t>(cookie) - 1; 56216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 56316c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 56416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 56516c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); 56616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 56716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode != CACHE_OFF && !mCacheValid) 56816c4d154dca43c662571129af31b27433b919a32Adam Lesinski loadFileNameCacheLocked(); 56916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 57016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (which < mAssetPaths.size()) { 57116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Looking for non-asset '%s' in '%s'\n", fileName, 57216c4d154dca43c662571129af31b27433b919a32Adam Lesinski mAssetPaths.itemAt(which).path.string()); 57316c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = openNonAssetInPathLocked( 57416c4d154dca43c662571129af31b27433b919a32Adam Lesinski fileName, mode, mAssetPaths.itemAt(which)); 57516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) { 57616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset != kExcludedAsset ? pAsset : NULL; 57716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 57816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 57916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 58016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 58116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 58216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 58316c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 58416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Get the type of a file in the asset namespace. 58516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 58616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * This currently only works for regular files. All others (including 58716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * directories) will return kFileTypeNonexistent. 58816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 58916c4d154dca43c662571129af31b27433b919a32Adam LesinskiFileType AssetManager::getFileType(const char* fileName) 59016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 59116c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = NULL; 59216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 59316c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 59416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open the asset. This is less efficient than simply finding the 59516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * file, but it's not too bad (we don't uncompress or mmap data until 59616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * the first read() call). 59716c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 59816c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = open(fileName, Asset::ACCESS_STREAMING); 59916c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete pAsset; 60016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 60116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) 60216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return kFileTypeNonexistent; 60316c4d154dca43c662571129af31b27433b919a32Adam Lesinski else 60416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return kFileTypeRegular; 60516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 60616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 6077df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosibabool AssetManager::appendPathToResTable(const asset_path& ap) const { 6087df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba Asset* ass = NULL; 6097df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ResTable* sharedRes = NULL; 6107df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba bool shared = true; 6117df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba bool onlyEmptyResources = true; 6127df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba MY_TRACE_BEGIN(ap.path.string()); 6137df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba Asset* idmap = openIdmapLocked(ap); 6147df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba size_t nextEntryIdx = mResources->getTableCount(); 6157df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ALOGV("Looking for resource asset in '%s'\n", ap.path.string()); 6167df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba if (ap.type != kFileTypeDirectory) { 6177df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba if (nextEntryIdx == 0) { 6187df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba // The first item is typically the framework resources, 6197df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba // which we want to avoid parsing every time. 6207df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba sharedRes = const_cast<AssetManager*>(this)-> 6217df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba mZipSet.getZipResourceTable(ap.path); 6227df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba if (sharedRes != NULL) { 6237df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba // skip ahead the number of system overlay packages preloaded 6247df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba nextEntryIdx = sharedRes->getTableCount(); 6257df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } 6267df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } 6277df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba if (sharedRes == NULL) { 6287df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ass = const_cast<AssetManager*>(this)-> 6297df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba mZipSet.getZipResourceTableAsset(ap.path); 6307df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba if (ass == NULL) { 6317df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ALOGV("loading resource table %s\n", ap.path.string()); 6327df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ass = const_cast<AssetManager*>(this)-> 6337df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba openNonAssetInPathLocked("resources.arsc", 6347df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba Asset::ACCESS_BUFFER, 6357df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ap); 6367df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba if (ass != NULL && ass != kExcludedAsset) { 6377df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ass = const_cast<AssetManager*>(this)-> 6387df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba mZipSet.setZipResourceTableAsset(ap.path, ass); 6397df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } 6407df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } 6417df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba 6427df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba if (nextEntryIdx == 0 && ass != NULL) { 6437df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba // If this is the first resource table in the asset 6447df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba // manager, then we are going to cache it so that we 6457df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba // can quickly copy it out for others. 6467df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ALOGV("Creating shared resources for %s", ap.path.string()); 6477df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba sharedRes = new ResTable(); 6487df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba sharedRes->add(ass, idmap, nextEntryIdx + 1, false); 6497df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba#ifdef HAVE_ANDROID_OS 6507df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba const char* data = getenv("ANDROID_DATA"); 6517df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba LOG_ALWAYS_FATAL_IF(data == NULL, "ANDROID_DATA not set"); 6527df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba String8 overlaysListPath(data); 6537df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba overlaysListPath.appendPath(kResourceCache); 6547df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba overlaysListPath.appendPath("overlays.list"); 6557df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba addSystemOverlays(overlaysListPath.string(), ap.path, sharedRes, nextEntryIdx); 6567df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba#endif 6577df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba sharedRes = const_cast<AssetManager*>(this)-> 6587df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba mZipSet.setZipResourceTable(ap.path, sharedRes); 6597df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } 6607df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } 6617df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } else { 6627df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ALOGV("loading resource table %s\n", ap.path.string()); 6637df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ass = const_cast<AssetManager*>(this)-> 6647df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba openNonAssetInPathLocked("resources.arsc", 6657df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba Asset::ACCESS_BUFFER, 6667df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ap); 6677df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba shared = false; 6687df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } 6697df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba 6707df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba if ((ass != NULL || sharedRes != NULL) && ass != kExcludedAsset) { 6717df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ALOGV("Installing resource asset %p in to table %p\n", ass, mResources); 6727df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba if (sharedRes != NULL) { 6737df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ALOGV("Copying existing resources for %s", ap.path.string()); 6747df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba mResources->add(sharedRes); 6757df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } else { 6767df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ALOGV("Parsing resources for %s", ap.path.string()); 6777df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba mResources->add(ass, idmap, nextEntryIdx + 1, !shared); 6787df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } 6797df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba onlyEmptyResources = false; 6807df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba 6817df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba if (!shared) { 6827df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba delete ass; 6837df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } 6847df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } else { 6857df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba ALOGV("Installing empty resources in to table %p\n", mResources); 6867df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba mResources->addEmpty(nextEntryIdx + 1); 6877df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } 6887df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba 6897df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba if (idmap != NULL) { 6907df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba delete idmap; 6917df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba } 6927df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba MY_TRACE_END(); 6937df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba 6947df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba return onlyEmptyResources; 6957df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba} 6967df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba 69716c4d154dca43c662571129af31b27433b919a32Adam Lesinskiconst ResTable* AssetManager::getResTable(bool required) const 69816c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 69916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ResTable* rt = mResources; 70016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (rt) { 70116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return rt; 70216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 70316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 70416c4d154dca43c662571129af31b27433b919a32Adam Lesinski // Iterate through all asset packages, collecting resources from each. 70516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 70616c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 70716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 70816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mResources != NULL) { 70916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mResources; 71016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 71116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 71216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (required) { 71316c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); 71416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 71516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 716de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski if (mCacheMode != CACHE_OFF && !mCacheValid) { 71716c4d154dca43c662571129af31b27433b919a32Adam Lesinski const_cast<AssetManager*>(this)->loadFileNameCacheLocked(); 718de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski } 719de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski 720de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski mResources = new ResTable(); 721de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski updateResourceParamsLocked(); 72216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 723de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski bool onlyEmptyResources = true; 72416c4d154dca43c662571129af31b27433b919a32Adam Lesinski const size_t N = mAssetPaths.size(); 72516c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (size_t i=0; i<N; i++) { 7267df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba bool empty = appendPathToResTable(mAssetPaths.itemAt(i)); 7277df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba onlyEmptyResources = onlyEmptyResources && empty; 72816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 72916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 730de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski if (required && onlyEmptyResources) { 731de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski ALOGW("Unable to find resources file resources.arsc"); 732de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski delete mResources; 733de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski mResources = NULL; 73416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 735de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski 736de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski return mResources; 73716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 73816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 73916c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::updateResourceParamsLocked() const 74016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 74116c4d154dca43c662571129af31b27433b919a32Adam Lesinski ResTable* res = mResources; 74216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (!res) { 74316c4d154dca43c662571129af31b27433b919a32Adam Lesinski return; 74416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 74516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 74691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath if (mLocale) { 74791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath mConfig->setBcp47Locale(mLocale); 74891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath } else { 74991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath mConfig->clearLocale(); 75016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 75116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 75216c4d154dca43c662571129af31b27433b919a32Adam Lesinski res->setParameters(mConfig); 75316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 75416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 75516c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openIdmapLocked(const struct asset_path& ap) const 75616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 75716c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* ass = NULL; 75816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.idmap.size() != 0) { 75916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ass = const_cast<AssetManager*>(this)-> 76016c4d154dca43c662571129af31b27433b919a32Adam Lesinski openAssetFromFileLocked(ap.idmap, Asset::ACCESS_BUFFER); 76116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ass) { 76216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("loading idmap %s\n", ap.idmap.string()); 76316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 76416c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("failed to load idmap %s\n", ap.idmap.string()); 76516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 76616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 76716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return ass; 76816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 76916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 77048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadvoid AssetManager::addSystemOverlays(const char* pathOverlaysList, 77148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad const String8& targetPackagePath, ResTable* sharedRes, size_t offset) const 77248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad{ 77348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad FILE* fin = fopen(pathOverlaysList, "r"); 77448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if (fin == NULL) { 77548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad return; 77648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad } 77748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad 77848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad char buf[1024]; 77948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad while (fgets(buf, sizeof(buf), fin)) { 78048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad // format of each line: 78148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad // <path to apk><space><path to idmap><newline> 78248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad char* space = strchr(buf, ' '); 78348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad char* newline = strchr(buf, '\n'); 78448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad asset_path oap; 78548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad 78648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if (space == NULL || newline == NULL || newline < space) { 78748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad continue; 78848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad } 78948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad 79048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad oap.path = String8(buf, space - buf); 79148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad oap.type = kFileTypeRegular; 79248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad oap.idmap = String8(space + 1, newline - space - 1); 79348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad 79448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad Asset* oass = const_cast<AssetManager*>(this)-> 79548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad openNonAssetInPathLocked("resources.arsc", 79648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad Asset::ACCESS_BUFFER, 79748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad oap); 79848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad 79948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if (oass != NULL) { 80048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad Asset* oidmap = openIdmapLocked(oap); 80148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad offset++; 802f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski sharedRes->add(oass, oidmap, offset + 1, false); 80348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad const_cast<AssetManager*>(this)->mAssetPaths.add(oap); 80448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad const_cast<AssetManager*>(this)->mZipSet.addOverlay(targetPackagePath, oap); 80548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad } 80648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad } 80748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad fclose(fin); 80848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad} 80948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad 81016c4d154dca43c662571129af31b27433b919a32Adam Lesinskiconst ResTable& AssetManager::getResources(bool required) const 81116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 81216c4d154dca43c662571129af31b27433b919a32Adam Lesinski const ResTable* rt = getResTable(required); 81316c4d154dca43c662571129af31b27433b919a32Adam Lesinski return *rt; 81416c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 81516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 81616c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::isUpToDate() 81716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 81816c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 81916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mZipSet.isUpToDate(); 82016c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 82116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 82216c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::getLocales(Vector<String8>* locales) const 82316c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 82416c4d154dca43c662571129af31b27433b919a32Adam Lesinski ResTable* res = mResources; 82516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (res != NULL) { 82616c4d154dca43c662571129af31b27433b919a32Adam Lesinski res->getLocales(locales); 82716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 828e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath 829e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath const size_t numLocales = locales->size(); 830e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath for (size_t i = 0; i < numLocales; ++i) { 831e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath const String8& localeStr = locales->itemAt(i); 832e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath if (localeStr.find(kTlPrefix) == 0) { 833e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath String8 replaced("fil"); 834e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath replaced += (localeStr.string() + kTlPrefixLen); 835e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath locales->editItemAt(i) = replaced; 836e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath } 837e4345dbd2a892f38e62269d94e5ee7002d121bedNarayan Kamath } 83816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 83916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 84016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 84116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open a non-asset file as if it were an asset, searching for it in the 84216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * specified app. 84316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 84416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pass in a NULL values for "appName" if the common app directory should 84516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * be used. 84616c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 84716c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode mode, 84816c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap) 84916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 85016c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = NULL; 85116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 85216c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* look at the filesystem on disk */ 85316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type == kFileTypeDirectory) { 85416c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(ap.path); 85516c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(fileName); 85616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 85716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromFileLocked(path, mode); 85816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 85916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) { 86016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* try again, this time with ".gz" */ 86116c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.append(".gz"); 86216c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromFileLocked(path, mode); 86316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 86416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 86516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) { 86616c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("FOUND NA '%s' on disk\n", fileName); 86716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset->setAssetSource(path); 86816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 86916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 87016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* look inside the zip file */ 87116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 87216c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(fileName); 87316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 87416c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* check the appropriate Zip file */ 875560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ZipFileRO* pZip = getZipFileLocked(ap); 87616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pZip != NULL) { 87716c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("GOT zip, checking NA '%s'\n", (const char*) path); 878560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ZipEntryRO entry = pZip->findEntryByName(path.string()); 87916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (entry != NULL) { 88016c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("FOUND NA in Zip file for %s\n", appName ? appName : kAppCommon); 88116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromZipLocked(pZip, entry, mode, path); 882560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath pZip->releaseEntry(entry); 88316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 88416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 88516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 88616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) { 88716c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* create a "source" name, for debug/display */ 88816c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset->setAssetSource( 88916c4d154dca43c662571129af31b27433b919a32Adam Lesinski createZipSourceNameLocked(ZipSet::getPathName(ap.path.string()), String8(""), 89016c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8(fileName))); 89116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 89216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 89316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 89416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset; 89516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 89616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 89716c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 89816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open an asset, searching for it in the directory hierarchy for the 89916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * specified app. 90016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 90116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pass in a NULL values for "appName" if the common app directory should 90216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * be used. 90316c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 90416c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openInPathLocked(const char* fileName, AccessMode mode, 90516c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap) 90616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 90716c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = NULL; 90816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 90916c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 91016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Try various combinations of locale and vendor. 91116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 91216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mLocale != NULL && mVendor != NULL) 91316c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openInLocaleVendorLocked(fileName, mode, ap, mLocale, mVendor); 91416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL && mVendor != NULL) 91516c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openInLocaleVendorLocked(fileName, mode, ap, NULL, mVendor); 91616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL && mLocale != NULL) 91716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openInLocaleVendorLocked(fileName, mode, ap, mLocale, NULL); 91816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) 91916c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openInLocaleVendorLocked(fileName, mode, ap, NULL, NULL); 92016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 92116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset; 92216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 92316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 92416c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 92516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open an asset, searching for it in the directory hierarchy for the 92616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * specified locale and vendor. 92716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 92816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * We also search in "app.jar". 92916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 93016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pass in NULL values for "appName", "locale", and "vendor" if the 93116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * defaults should be used. 93216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 93316c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openInLocaleVendorLocked(const char* fileName, AccessMode mode, 93416c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap, const char* locale, const char* vendor) 93516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 93616c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = NULL; 93716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 93816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type == kFileTypeDirectory) { 93916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode == CACHE_OFF) { 94016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* look at the filesystem on disk */ 94116c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(createPathNameLocked(ap, locale, vendor)); 94216c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(fileName); 94316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 94416c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 excludeName(path); 94516c4d154dca43c662571129af31b27433b919a32Adam Lesinski excludeName.append(kExcludeExtension); 94616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (::getFileType(excludeName.string()) != kFileTypeNonexistent) { 94716c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* say no more */ 94816c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("+++ excluding '%s'\n", (const char*) excludeName); 94916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return kExcludedAsset; 95016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 95116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 95216c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromFileLocked(path, mode); 95316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 95416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) { 95516c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* try again, this time with ".gz" */ 95616c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.append(".gz"); 95716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromFileLocked(path, mode); 95816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 95916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 96016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) 96116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset->setAssetSource(path); 96216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 96316c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* find in cache */ 96416c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(createPathNameLocked(ap, locale, vendor)); 96516c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(fileName); 96616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 96716c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir::FileInfo tmpInfo; 96816c4d154dca43c662571129af31b27433b919a32Adam Lesinski bool found = false; 96916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 97016c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 excludeName(path); 97116c4d154dca43c662571129af31b27433b919a32Adam Lesinski excludeName.append(kExcludeExtension); 97216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 97316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCache.indexOf(excludeName) != NAME_NOT_FOUND) { 97416c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* go no farther */ 97516c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("+++ Excluding '%s'\n", (const char*) excludeName); 97616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return kExcludedAsset; 97716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 97816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 97916c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 98016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * File compression extensions (".gz") don't get stored in the 98116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * name cache, so we have to try both here. 98216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 98316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCache.indexOf(path) != NAME_NOT_FOUND) { 98416c4d154dca43c662571129af31b27433b919a32Adam Lesinski found = true; 98516c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromFileLocked(path, mode); 98616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) { 98716c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* try again, this time with ".gz" */ 98816c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.append(".gz"); 98916c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromFileLocked(path, mode); 99016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 99116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 99216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 99316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) 99416c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset->setAssetSource(path); 99516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 99616c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 99716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Don't continue the search into the Zip files. Our cached info 99816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * said it was a file on disk; to be consistent with openDir() 99916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * we want to return the loose asset. If the cached file gets 100016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * removed, we fail. 100116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 100216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The alternative is to update our cache when files get deleted, 100316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * or make some sort of "best effort" promise, but for now I'm 100416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * taking the hard line. 100516c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 100616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (found) { 100716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) 100816c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGD("Expected file not found: '%s'\n", path.string()); 100916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset; 101016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 101116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 101216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 101316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 101416c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 101516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Either it wasn't found on disk or on the cached view of the disk. 101616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Dig through the currently-opened set of Zip files. If caching 101716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * is disabled, the Zip file may get reopened. 101816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 101916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL && ap.type == kFileTypeRegular) { 102016c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path; 102116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 102216c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath((locale != NULL) ? locale : kDefaultLocale); 102316c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath((vendor != NULL) ? vendor : kDefaultVendor); 102416c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(fileName); 102516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 102616c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* check the appropriate Zip file */ 1027560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ZipFileRO* pZip = getZipFileLocked(ap); 102816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pZip != NULL) { 102916c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("GOT zip, checking '%s'\n", (const char*) path); 1030560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ZipEntryRO entry = pZip->findEntryByName(path.string()); 103116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (entry != NULL) { 103216c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("FOUND in Zip file for %s/%s-%s\n", 103316c4d154dca43c662571129af31b27433b919a32Adam Lesinski // appName, locale, vendor); 103416c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = openAssetFromZipLocked(pZip, entry, mode, path); 1035560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath pZip->releaseEntry(entry); 103616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 103716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 103816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 103916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset != NULL) { 104016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* create a "source" name, for debug/display */ 104116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset->setAssetSource(createZipSourceNameLocked(ZipSet::getPathName(ap.path.string()), 104216c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8(""), String8(fileName))); 104316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 104416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 104516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 104616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset; 104716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 104816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 104916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 105016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Create a "source name" for a file from a Zip archive. 105116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 105216c4d154dca43c662571129af31b27433b919a32Adam LesinskiString8 AssetManager::createZipSourceNameLocked(const String8& zipFileName, 105316c4d154dca43c662571129af31b27433b919a32Adam Lesinski const String8& dirName, const String8& fileName) 105416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 105516c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 sourceName("zip:"); 105616c4d154dca43c662571129af31b27433b919a32Adam Lesinski sourceName.append(zipFileName); 105716c4d154dca43c662571129af31b27433b919a32Adam Lesinski sourceName.append(":"); 105816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirName.length() > 0) { 105916c4d154dca43c662571129af31b27433b919a32Adam Lesinski sourceName.appendPath(dirName); 106016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 106116c4d154dca43c662571129af31b27433b919a32Adam Lesinski sourceName.appendPath(fileName); 106216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return sourceName; 106316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 106416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 106516c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 106616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Create a path to a loose asset (asset-base/app/locale/vendor). 106716c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 106816c4d154dca43c662571129af31b27433b919a32Adam LesinskiString8 AssetManager::createPathNameLocked(const asset_path& ap, const char* locale, 106916c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* vendor) 107016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 107116c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(ap.path); 107216c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath((locale != NULL) ? locale : kDefaultLocale); 107316c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath((vendor != NULL) ? vendor : kDefaultVendor); 107416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return path; 107516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 107616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 107716c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 107816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Create a path to a loose asset (asset-base/app/rootDir). 107916c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 108016c4d154dca43c662571129af31b27433b919a32Adam LesinskiString8 AssetManager::createPathNameLocked(const asset_path& ap, const char* rootDir) 108116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 108216c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path(ap.path); 108316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (rootDir != NULL) path.appendPath(rootDir); 108416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return path; 108516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 108616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 108716c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 108816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Return a pointer to one of our open Zip archives. Returns NULL if no 108916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * matching Zip file exists. 109016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 109116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Right now we have 2 possible Zip files (1 each in app/"common"). 109216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 109316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * If caching is set to CACHE_OFF, to get the expected behavior we 109416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * need to reopen the Zip file on every request. That would be silly 109516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * and expensive, so instead we just check the file modification date. 109616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 109716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pass in NULL values for "appName", "locale", and "vendor" if the 109816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * generics should be used. 109916c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 110016c4d154dca43c662571129af31b27433b919a32Adam LesinskiZipFileRO* AssetManager::getZipFileLocked(const asset_path& ap) 110116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 110216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("getZipFileLocked() in %p\n", this); 110316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 110416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mZipSet.getZip(ap.path); 110516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 110616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 110716c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 110816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Try to open an asset from a file on disk. 110916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 111016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * If the file is compressed with gzip, we seek to the start of the 111116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * deflated data and pass that in (just like we would for a Zip archive). 111216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 111316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * For uncompressed data, we may already have an mmap()ed version sitting 111416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * around. If so, we want to hand that to the Asset instead. 111516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 111616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * This returns NULL if the file doesn't exist, couldn't be opened, or 111716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * claims to be a ".gz" but isn't. 111816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 111916c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openAssetFromFileLocked(const String8& pathName, 112016c4d154dca43c662571129af31b27433b919a32Adam Lesinski AccessMode mode) 112116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 112216c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = NULL; 112316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 112416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (strcasecmp(pathName.getPathExtension().string(), ".gz") == 0) { 112516c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("TRYING '%s'\n", (const char*) pathName); 112616c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = Asset::createFromCompressedFile(pathName.string(), mode); 112716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 112816c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("TRYING '%s'\n", (const char*) pathName); 112916c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = Asset::createFromFile(pathName.string(), mode); 113016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 113116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 113216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset; 113316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 113416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 113516c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 113616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Given an entry in a Zip archive, create a new Asset object. 113716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 113816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * If the entry is uncompressed, we may want to create or share a 113916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * slice of shared memory. 114016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 114116c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::openAssetFromZipLocked(const ZipFileRO* pZipFile, 114216c4d154dca43c662571129af31b27433b919a32Adam Lesinski const ZipEntryRO entry, AccessMode mode, const String8& entryName) 114316c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 114416c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* pAsset = NULL; 114516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 114616c4d154dca43c662571129af31b27433b919a32Adam Lesinski // TODO: look for previously-created shared memory slice? 114716c4d154dca43c662571129af31b27433b919a32Adam Lesinski int method; 114816c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t uncompressedLen; 114916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 115016c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("USING Zip '%s'\n", pEntry->getFileName()); 115116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 115216c4d154dca43c662571129af31b27433b919a32Adam Lesinski //pZipFile->getEntryInfo(entry, &method, &uncompressedLen, &compressedLen, 115316c4d154dca43c662571129af31b27433b919a32Adam Lesinski // &offset); 115416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (!pZipFile->getEntryInfo(entry, &method, &uncompressedLen, NULL, NULL, 115516c4d154dca43c662571129af31b27433b919a32Adam Lesinski NULL, NULL)) 115616c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 115716c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("getEntryInfo failed\n"); 115816c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 115916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 116016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 116116c4d154dca43c662571129af31b27433b919a32Adam Lesinski FileMap* dataMap = pZipFile->createEntryFileMap(entry); 116216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dataMap == NULL) { 116316c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("create map from entry failed\n"); 116416c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 116516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 116616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 116716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (method == ZipFileRO::kCompressStored) { 116816c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = Asset::createFromUncompressedMap(dataMap, mode); 116916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Opened uncompressed entry %s in zip %s mode %d: %p", entryName.string(), 117016c4d154dca43c662571129af31b27433b919a32Adam Lesinski dataMap->getFileName(), mode, pAsset); 117116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 117216c4d154dca43c662571129af31b27433b919a32Adam Lesinski pAsset = Asset::createFromCompressedMap(dataMap, method, 117316c4d154dca43c662571129af31b27433b919a32Adam Lesinski uncompressedLen, mode); 117416c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Opened compressed entry %s in zip %s mode %d: %p", entryName.string(), 117516c4d154dca43c662571129af31b27433b919a32Adam Lesinski dataMap->getFileName(), mode, pAsset); 117616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 117716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pAsset == NULL) { 117816c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* unexpected */ 117916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("create from segment failed\n"); 118016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 118116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 118216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pAsset; 118316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 118416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 118516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 118616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 118716c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 118816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open a directory in the asset namespace. 118916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 119016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * An "asset directory" is simply the combination of all files in all 119116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * locations, with ".gz" stripped for loose files. With app, locale, and 119216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * vendor defined, we have 8 directories and 2 Zip archives to scan. 119316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 119416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pass in "" for the root dir. 119516c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 119616c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetDir* AssetManager::openDir(const char* dirName) 119716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 119816c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 119916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 120016c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir* pDir = NULL; 120116c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pMergedInfo = NULL; 120216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 120316c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); 120416c4d154dca43c662571129af31b27433b919a32Adam Lesinski assert(dirName != NULL); 120516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 120616c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("+++ openDir(%s) in '%s'\n", dirName, (const char*) mAssetBase); 120716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 120816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode != CACHE_OFF && !mCacheValid) 120916c4d154dca43c662571129af31b27433b919a32Adam Lesinski loadFileNameCacheLocked(); 121016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 121116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pDir = new AssetDir; 121216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 121316c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 121416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan the various directories, merging what we find into a single 121516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * vector. We want to scan them in reverse priority order so that 121616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * the ".EXCLUDE" processing works correctly. Also, if we decide we 121716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * want to remember where the file is coming from, we'll get the right 121816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * version. 121916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 122016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * We start with Zip archives, then do loose files. 122116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 122216c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo = new SortedVector<AssetDir::FileInfo>; 122316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 122416c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t i = mAssetPaths.size(); 122516c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (i > 0) { 122616c4d154dca43c662571129af31b27433b919a32Adam Lesinski i--; 122716c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap = mAssetPaths.itemAt(i); 122816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type == kFileTypeRegular) { 122916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Adding directory %s from zip %s", dirName, ap.path.string()); 123016c4d154dca43c662571129af31b27433b919a32Adam Lesinski scanAndMergeZipLocked(pMergedInfo, ap, kAssetsRoot, dirName); 123116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 123216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Adding directory %s from dir %s", dirName, ap.path.string()); 123316c4d154dca43c662571129af31b27433b919a32Adam Lesinski scanAndMergeDirLocked(pMergedInfo, ap, kAssetsRoot, dirName); 123416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 123516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 123616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 123716c4d154dca43c662571129af31b27433b919a32Adam Lesinski#if 0 123816c4d154dca43c662571129af31b27433b919a32Adam Lesinski printf("FILE LIST:\n"); 123916c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (i = 0; i < (size_t) pMergedInfo->size(); i++) { 124016c4d154dca43c662571129af31b27433b919a32Adam Lesinski printf(" %d: (%d) '%s'\n", i, 124116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->itemAt(i).getFileType(), 124216c4d154dca43c662571129af31b27433b919a32Adam Lesinski (const char*) pMergedInfo->itemAt(i).getFileName()); 124316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 124416c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 124516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 124616c4d154dca43c662571129af31b27433b919a32Adam Lesinski pDir->setFileList(pMergedInfo); 124716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pDir; 124816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 124916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 125016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 125116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open a directory in the non-asset namespace. 125216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 125316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * An "asset directory" is simply the combination of all files in all 125416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * locations, with ".gz" stripped for loose files. With app, locale, and 125516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * vendor defined, we have 8 directories and 2 Zip archives to scan. 125616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 125716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pass in "" for the root dir. 125816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 1259a0c6260705c841f501282e0e337970ca9a00e064Narayan KamathAssetDir* AssetManager::openNonAssetDir(const int32_t cookie, const char* dirName) 126016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 126116c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(mLock); 126216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 126316c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir* pDir = NULL; 126416c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pMergedInfo = NULL; 126516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 126616c4d154dca43c662571129af31b27433b919a32Adam Lesinski LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); 126716c4d154dca43c662571129af31b27433b919a32Adam Lesinski assert(dirName != NULL); 126816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 126916c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("+++ openDir(%s) in '%s'\n", dirName, (const char*) mAssetBase); 127016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 127116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheMode != CACHE_OFF && !mCacheValid) 127216c4d154dca43c662571129af31b27433b919a32Adam Lesinski loadFileNameCacheLocked(); 127316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 127416c4d154dca43c662571129af31b27433b919a32Adam Lesinski pDir = new AssetDir; 127516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 127616c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo = new SortedVector<AssetDir::FileInfo>; 127716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 1278a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath const size_t which = static_cast<size_t>(cookie) - 1; 127916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 128016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (which < mAssetPaths.size()) { 128116c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap = mAssetPaths.itemAt(which); 128216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (ap.type == kFileTypeRegular) { 128316c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Adding directory %s from zip %s", dirName, ap.path.string()); 128416c4d154dca43c662571129af31b27433b919a32Adam Lesinski scanAndMergeZipLocked(pMergedInfo, ap, NULL, dirName); 128516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 128616c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Adding directory %s from dir %s", dirName, ap.path.string()); 128716c4d154dca43c662571129af31b27433b919a32Adam Lesinski scanAndMergeDirLocked(pMergedInfo, ap, NULL, dirName); 128816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 128916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 129016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 129116c4d154dca43c662571129af31b27433b919a32Adam Lesinski#if 0 129216c4d154dca43c662571129af31b27433b919a32Adam Lesinski printf("FILE LIST:\n"); 129316c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (i = 0; i < (size_t) pMergedInfo->size(); i++) { 129416c4d154dca43c662571129af31b27433b919a32Adam Lesinski printf(" %d: (%d) '%s'\n", i, 129516c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->itemAt(i).getFileType(), 129616c4d154dca43c662571129af31b27433b919a32Adam Lesinski (const char*) pMergedInfo->itemAt(i).getFileName()); 129716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 129816c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 129916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 130016c4d154dca43c662571129af31b27433b919a32Adam Lesinski pDir->setFileList(pMergedInfo); 130116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pDir; 130216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 130316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 130416c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 130516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan the contents of the specified directory and merge them into the 130616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * "pMergedInfo" vector, removing previous entries if we find "exclude" 130716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * directives. 130816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 130916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Returns "false" if we found nothing to contribute. 131016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 131116c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::scanAndMergeDirLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, 131216c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap, const char* rootDir, const char* dirName) 131316c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 131416c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pContents; 131516c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 path; 131616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 131716c4d154dca43c662571129af31b27433b919a32Adam Lesinski assert(pMergedInfo != NULL); 131816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 131916c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("scanAndMergeDir: %s %s %s %s\n", appName, locale, vendor,dirName); 132016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 132116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCacheValid) { 132216c4d154dca43c662571129af31b27433b919a32Adam Lesinski int i, start, count; 132316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 132416c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents = new SortedVector<AssetDir::FileInfo>; 132516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 132616c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 132716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Get the basic partial path and find it in the cache. That's 132816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * the start point for the search. 132916c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 133016c4d154dca43c662571129af31b27433b919a32Adam Lesinski path = createPathNameLocked(ap, rootDir); 133116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirName[0] != '\0') 133216c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(dirName); 133316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 133416c4d154dca43c662571129af31b27433b919a32Adam Lesinski start = mCache.indexOf(path); 133516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (start == NAME_NOT_FOUND) { 133616c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("+++ not found in cache: dir '%s'\n", (const char*) path); 133716c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete pContents; 133816c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 133916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 134016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 134116c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 134216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The match string looks like "common/default/default/foo/bar/". 134316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The '/' on the end ensures that we don't match on the directory 134416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * itself or on ".../foo/barfy/". 134516c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 134616c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.append("/"); 134716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 134816c4d154dca43c662571129af31b27433b919a32Adam Lesinski count = mCache.size(); 134916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 135016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 135116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Pick out the stuff in the current dir by examining the pathname. 135216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * It needs to match the partial pathname prefix, and not have a '/' 135316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * (fssep) anywhere after the prefix. 135416c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 135516c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (i = start+1; i < count; i++) { 135616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mCache[i].getFileName().length() > path.length() && 135716c4d154dca43c662571129af31b27433b919a32Adam Lesinski strncmp(mCache[i].getFileName().string(), path.string(), path.length()) == 0) 135816c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 135916c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* name = mCache[i].getFileName().string(); 136016c4d154dca43c662571129af31b27433b919a32Adam Lesinski // XXX THIS IS BROKEN! Looks like we need to store the full 136116c4d154dca43c662571129af31b27433b919a32Adam Lesinski // path prefix separately from the file path. 136216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (strchr(name + path.length(), '/') == NULL) { 136316c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* grab it, reducing path to just the filename component */ 136416c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir::FileInfo tmp = mCache[i]; 136516c4d154dca43c662571129af31b27433b919a32Adam Lesinski tmp.setFileName(tmp.getFileName().getPathLeaf()); 136616c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents->add(tmp); 136716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 136816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 136916c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* no longer in the dir or its subdirs */ 137016c4d154dca43c662571129af31b27433b919a32Adam Lesinski break; 137116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 137216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 137316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 137416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 137516c4d154dca43c662571129af31b27433b919a32Adam Lesinski path = createPathNameLocked(ap, rootDir); 137616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirName[0] != '\0') 137716c4d154dca43c662571129af31b27433b919a32Adam Lesinski path.appendPath(dirName); 137816c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents = scanDirLocked(path); 137916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pContents == NULL) 138016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 138116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 138216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 138316c4d154dca43c662571129af31b27433b919a32Adam Lesinski // if we wanted to do an incremental cache fill, we would do it here 138416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 138516c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 138616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Process "exclude" directives. If we find a filename that ends with 138716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * ".EXCLUDE", we look for a matching entry in the "merged" set, and 138816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * remove it if we find it. We also delete the "exclude" entry. 138916c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 139016c4d154dca43c662571129af31b27433b919a32Adam Lesinski int i, count, exclExtLen; 139116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 139216c4d154dca43c662571129af31b27433b919a32Adam Lesinski count = pContents->size(); 139316c4d154dca43c662571129af31b27433b919a32Adam Lesinski exclExtLen = strlen(kExcludeExtension); 139416c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (i = 0; i < count; i++) { 139516c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* name; 139616c4d154dca43c662571129af31b27433b919a32Adam Lesinski int nameLen; 139716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 139816c4d154dca43c662571129af31b27433b919a32Adam Lesinski name = pContents->itemAt(i).getFileName().string(); 139916c4d154dca43c662571129af31b27433b919a32Adam Lesinski nameLen = strlen(name); 140016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (nameLen > exclExtLen && 140116c4d154dca43c662571129af31b27433b919a32Adam Lesinski strcmp(name + (nameLen - exclExtLen), kExcludeExtension) == 0) 140216c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 140316c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 match(name, nameLen - exclExtLen); 140416c4d154dca43c662571129af31b27433b919a32Adam Lesinski int matchIdx; 140516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 140616c4d154dca43c662571129af31b27433b919a32Adam Lesinski matchIdx = AssetDir::FileInfo::findEntry(pMergedInfo, match); 140716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (matchIdx > 0) { 140816c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Excluding '%s' [%s]\n", 140916c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->itemAt(matchIdx).getFileName().string(), 141016c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->itemAt(matchIdx).getSourceName().string()); 141116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->removeAt(matchIdx); 141216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 141316c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("+++ no match on '%s'\n", (const char*) match); 141416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 141516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 141616c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGD("HEY: size=%d removing %d\n", (int)pContents->size(), i); 141716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents->removeAt(i); 141816c4d154dca43c662571129af31b27433b919a32Adam Lesinski i--; // adjust "for" loop 141916c4d154dca43c662571129af31b27433b919a32Adam Lesinski count--; // and loop limit 142016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 142116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 142216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 142316c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeInfoLocked(pMergedInfo, pContents); 142416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 142516c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete pContents; 142616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 142716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 142816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 142916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 143016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 143116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan the contents of the specified directory, and stuff what we find 143216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * into a newly-allocated vector. 143316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 143416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Files ending in ".gz" will have their extensions removed. 143516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 143616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * We should probably think about skipping files with "illegal" names, 143716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * e.g. illegal characters (/\:) or excessive length. 143816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 143916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Returns NULL if the specified directory doesn't exist. 144016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 144116c4d154dca43c662571129af31b27433b919a32Adam LesinskiSortedVector<AssetDir::FileInfo>* AssetManager::scanDirLocked(const String8& path) 144216c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 144316c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pContents = NULL; 144416c4d154dca43c662571129af31b27433b919a32Adam Lesinski DIR* dir; 144516c4d154dca43c662571129af31b27433b919a32Adam Lesinski struct dirent* entry; 144616c4d154dca43c662571129af31b27433b919a32Adam Lesinski FileType fileType; 144716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 144816c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Scanning dir '%s'\n", path.string()); 144916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 145016c4d154dca43c662571129af31b27433b919a32Adam Lesinski dir = opendir(path.string()); 145116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dir == NULL) 145216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 145316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 145416c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents = new SortedVector<AssetDir::FileInfo>; 145516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 145616c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (1) { 145716c4d154dca43c662571129af31b27433b919a32Adam Lesinski entry = readdir(dir); 145816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (entry == NULL) 145916c4d154dca43c662571129af31b27433b919a32Adam Lesinski break; 146016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 146116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (strcmp(entry->d_name, ".") == 0 || 146216c4d154dca43c662571129af31b27433b919a32Adam Lesinski strcmp(entry->d_name, "..") == 0) 146316c4d154dca43c662571129af31b27433b919a32Adam Lesinski continue; 146416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 146516c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifdef _DIRENT_HAVE_D_TYPE 146616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (entry->d_type == DT_REG) 146716c4d154dca43c662571129af31b27433b919a32Adam Lesinski fileType = kFileTypeRegular; 146816c4d154dca43c662571129af31b27433b919a32Adam Lesinski else if (entry->d_type == DT_DIR) 146916c4d154dca43c662571129af31b27433b919a32Adam Lesinski fileType = kFileTypeDirectory; 147016c4d154dca43c662571129af31b27433b919a32Adam Lesinski else 147116c4d154dca43c662571129af31b27433b919a32Adam Lesinski fileType = kFileTypeUnknown; 147216c4d154dca43c662571129af31b27433b919a32Adam Lesinski#else 147316c4d154dca43c662571129af31b27433b919a32Adam Lesinski // stat the file 147416c4d154dca43c662571129af31b27433b919a32Adam Lesinski fileType = ::getFileType(path.appendPathCopy(entry->d_name).string()); 147516c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 147616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 147716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (fileType != kFileTypeRegular && fileType != kFileTypeDirectory) 147816c4d154dca43c662571129af31b27433b919a32Adam Lesinski continue; 147916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 148016c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir::FileInfo info; 148116c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.set(String8(entry->d_name), fileType); 148216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (strcasecmp(info.getFileName().getPathExtension().string(), ".gz") == 0) 148316c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.setFileName(info.getFileName().getBasePath()); 148416c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.setSourceName(path.appendPathCopy(info.getFileName())); 148516c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents->add(info); 148616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 148716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 148816c4d154dca43c662571129af31b27433b919a32Adam Lesinski closedir(dir); 148916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return pContents; 149016c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 149116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 149216c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 149316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan the contents out of the specified Zip archive, and merge what we 149416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * find into "pMergedInfo". If the Zip archive in question doesn't exist, 149516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * we return immediately. 149616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 149716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Returns "false" if we found nothing to contribute. 149816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 149916c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, 150016c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap, const char* rootDir, const char* baseDirName) 150116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 150216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ZipFileRO* pZip; 150316c4d154dca43c662571129af31b27433b919a32Adam Lesinski Vector<String8> dirs; 150416c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir::FileInfo info; 150516c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo> contents; 150616c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 sourceName, zipName, dirName; 150716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 150816c4d154dca43c662571129af31b27433b919a32Adam Lesinski pZip = mZipSet.getZip(ap.path); 150916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pZip == NULL) { 151016c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGW("Failure opening zip %s\n", ap.path.string()); 151116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 151216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 151316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 151416c4d154dca43c662571129af31b27433b919a32Adam Lesinski zipName = ZipSet::getPathName(ap.path.string()); 151516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 151616c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* convert "sounds" to "rootDir/sounds" */ 151716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (rootDir != NULL) dirName = rootDir; 151816c4d154dca43c662571129af31b27433b919a32Adam Lesinski dirName.appendPath(baseDirName); 151916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 152016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 152116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan through the list of files, looking for a match. The files in 152216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * the Zip table of contents are not in sorted order, so we have to 152316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * process the entire list. We're looking for a string that begins 152416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * with the characters in "dirName", is followed by a '/', and has no 152516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * subsequent '/' in the stuff that follows. 152616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 152716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * What makes this especially fun is that directories are not stored 152816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * explicitly in Zip archives, so we have to infer them from context. 152916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * When we see "sounds/foo.wav" we have to leave a note to ourselves 153016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * to insert a directory called "sounds" into the list. We store 153116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * these in temporary vector so that we only return each one once. 153216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 153316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Name comparisons are case-sensitive to match UNIX filesystem 153416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * semantics. 153516c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 153616c4d154dca43c662571129af31b27433b919a32Adam Lesinski int dirNameLen = dirName.length(); 1537560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath void *iterationCookie; 1538560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (!pZip->startIteration(&iterationCookie)) { 1539560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ALOGW("ZipFileRO::startIteration returned false"); 1540560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath return false; 1541560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath } 1542560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath 1543560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ZipEntryRO entry; 1544560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath while ((entry = pZip->nextEntry(iterationCookie)) != NULL) { 154516c4d154dca43c662571129af31b27433b919a32Adam Lesinski char nameBuf[256]; 154616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 154716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pZip->getEntryFileName(entry, nameBuf, sizeof(nameBuf)) != 0) { 154816c4d154dca43c662571129af31b27433b919a32Adam Lesinski // TODO: fix this if we expect to have long names 154916c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGE("ARGH: name too long?\n"); 155016c4d154dca43c662571129af31b27433b919a32Adam Lesinski continue; 155116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 155216c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("Comparing %s in %s?\n", nameBuf, dirName.string()); 155316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirNameLen == 0 || 155416c4d154dca43c662571129af31b27433b919a32Adam Lesinski (strncmp(nameBuf, dirName.string(), dirNameLen) == 0 && 155516c4d154dca43c662571129af31b27433b919a32Adam Lesinski nameBuf[dirNameLen] == '/')) 155616c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 155716c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* cp; 155816c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* nextSlash; 155916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 156016c4d154dca43c662571129af31b27433b919a32Adam Lesinski cp = nameBuf + dirNameLen; 156116c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirNameLen != 0) 156216c4d154dca43c662571129af31b27433b919a32Adam Lesinski cp++; // advance past the '/' 156316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 156416c4d154dca43c662571129af31b27433b919a32Adam Lesinski nextSlash = strchr(cp, '/'); 156516c4d154dca43c662571129af31b27433b919a32Adam Lesinski//xxx this may break if there are bare directory entries 156616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (nextSlash == NULL) { 156716c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* this is a file in the requested directory */ 156816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 156916c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.set(String8(nameBuf).getPathLeaf(), kFileTypeRegular); 157016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 157116c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.setSourceName( 157216c4d154dca43c662571129af31b27433b919a32Adam Lesinski createZipSourceNameLocked(zipName, dirName, info.getFileName())); 157316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 157416c4d154dca43c662571129af31b27433b919a32Adam Lesinski contents.add(info); 157516c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("FOUND: file '%s'\n", info.getFileName().string()); 157616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 157716c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* this is a subdir; add it if we don't already have it*/ 157816c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 subdirName(cp, nextSlash - cp); 157916c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t j; 158016c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t N = dirs.size(); 158116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 158216c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (j = 0; j < N; j++) { 158316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (subdirName == dirs[j]) { 158416c4d154dca43c662571129af31b27433b919a32Adam Lesinski break; 158516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 158616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 158716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (j == N) { 158816c4d154dca43c662571129af31b27433b919a32Adam Lesinski dirs.add(subdirName); 158916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 159016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 159116c4d154dca43c662571129af31b27433b919a32Adam Lesinski //printf("FOUND: dir '%s'\n", subdirName.string()); 159216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 159316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 159416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 159516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 1596560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath pZip->endIteration(iterationCookie); 1597560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath 159816c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 159916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Add the set of unique directories. 160016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 160116c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (int i = 0; i < (int) dirs.size(); i++) { 160216c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.set(dirs[i], kFileTypeDirectory); 160316c4d154dca43c662571129af31b27433b919a32Adam Lesinski info.setSourceName( 160416c4d154dca43c662571129af31b27433b919a32Adam Lesinski createZipSourceNameLocked(zipName, dirName, info.getFileName())); 160516c4d154dca43c662571129af31b27433b919a32Adam Lesinski contents.add(info); 160616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 160716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 160816c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeInfoLocked(pMergedInfo, &contents); 160916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 161016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 161116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 161216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 161316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 161416c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 161516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Merge two vectors of FileInfo. 161616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 161716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * The merged contents will be stuffed into *pMergedInfo. 161816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 161916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * If an entry for a file exists in both "pMergedInfo" and "pContents", 162016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * we use the newer "pContents" entry. 162116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 162216c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::mergeInfoLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, 162316c4d154dca43c662571129af31b27433b919a32Adam Lesinski const SortedVector<AssetDir::FileInfo>* pContents) 162416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 162516c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 162616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Merge what we found in this directory with what we found in 162716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * other places. 162816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 162916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Two basic approaches: 163016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * (1) Create a new array that holds the unique values of the two 163116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * arrays. 163216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * (2) Take the elements from pContents and shove them into pMergedInfo. 163316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 163416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Because these are vectors of complex objects, moving elements around 163516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * inside the vector requires constructing new objects and allocating 163616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * storage for members. With approach #1, we're always adding to the 163716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * end, whereas with #2 we could be inserting multiple elements at the 163816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * front of the vector. Approach #1 requires a full copy of the 163916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * contents of pMergedInfo, but approach #2 requires the same copy for 164016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * every insertion at the front of pMergedInfo. 164116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 164216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * (We should probably use a SortedVector interface that allows us to 164316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * just stuff items in, trusting us to maintain the sort order.) 164416c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 164516c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pNewSorted; 164616c4d154dca43c662571129af31b27433b919a32Adam Lesinski int mergeMax, contMax; 164716c4d154dca43c662571129af31b27433b919a32Adam Lesinski int mergeIdx, contIdx; 164816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 164916c4d154dca43c662571129af31b27433b919a32Adam Lesinski pNewSorted = new SortedVector<AssetDir::FileInfo>; 165016c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeMax = pMergedInfo->size(); 165116c4d154dca43c662571129af31b27433b919a32Adam Lesinski contMax = pContents->size(); 165216c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeIdx = contIdx = 0; 165316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 165416c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (mergeIdx < mergeMax || contIdx < contMax) { 165516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mergeIdx == mergeMax) { 165616c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* hit end of "merge" list, copy rest of "contents" */ 165716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pNewSorted->add(pContents->itemAt(contIdx)); 165816c4d154dca43c662571129af31b27433b919a32Adam Lesinski contIdx++; 165916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else if (contIdx == contMax) { 166016c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* hit end of "cont" list, copy rest of "merge" */ 166116c4d154dca43c662571129af31b27433b919a32Adam Lesinski pNewSorted->add(pMergedInfo->itemAt(mergeIdx)); 166216c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeIdx++; 166316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else if (pMergedInfo->itemAt(mergeIdx) == pContents->itemAt(contIdx)) 166416c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 166516c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* items are identical, add newer and advance both indices */ 166616c4d154dca43c662571129af31b27433b919a32Adam Lesinski pNewSorted->add(pContents->itemAt(contIdx)); 166716c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeIdx++; 166816c4d154dca43c662571129af31b27433b919a32Adam Lesinski contIdx++; 166916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else if (pMergedInfo->itemAt(mergeIdx) < pContents->itemAt(contIdx)) 167016c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 167116c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* "merge" is lower, add that one */ 167216c4d154dca43c662571129af31b27433b919a32Adam Lesinski pNewSorted->add(pMergedInfo->itemAt(mergeIdx)); 167316c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeIdx++; 167416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 167516c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* "cont" is lower, add that one */ 167616c4d154dca43c662571129af31b27433b919a32Adam Lesinski assert(pContents->itemAt(contIdx) < pMergedInfo->itemAt(mergeIdx)); 167716c4d154dca43c662571129af31b27433b919a32Adam Lesinski pNewSorted->add(pContents->itemAt(contIdx)); 167816c4d154dca43c662571129af31b27433b919a32Adam Lesinski contIdx++; 167916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 168016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 168116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 168216c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 168316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Overwrite the "merged" list with the new stuff. 168416c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 168516c4d154dca43c662571129af31b27433b919a32Adam Lesinski *pMergedInfo = *pNewSorted; 168616c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete pNewSorted; 168716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 168816c4d154dca43c662571129af31b27433b919a32Adam Lesinski#if 0 // for Vector, rather than SortedVector 168916c4d154dca43c662571129af31b27433b919a32Adam Lesinski int i, j; 169016c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (i = pContents->size() -1; i >= 0; i--) { 169116c4d154dca43c662571129af31b27433b919a32Adam Lesinski bool add = true; 169216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 169316c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (j = pMergedInfo->size() -1; j >= 0; j--) { 169416c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* case-sensitive comparisons, to behave like UNIX fs */ 169516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (strcmp(pContents->itemAt(i).mFileName, 169616c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->itemAt(j).mFileName) == 0) 169716c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 169816c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* match, don't add this entry */ 169916c4d154dca43c662571129af31b27433b919a32Adam Lesinski add = false; 170016c4d154dca43c662571129af31b27433b919a32Adam Lesinski break; 170116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 170216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 170316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 170416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (add) 170516c4d154dca43c662571129af31b27433b919a32Adam Lesinski pMergedInfo->add(pContents->itemAt(i)); 170616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 170716c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 170816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 170916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 171016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 171116c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 171216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Load all files into the file name cache. We want to do this across 171316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * all combinations of { appname, locale, vendor }, performing a recursive 171416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * directory traversal. 171516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 171616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * This is not the most efficient data structure. Also, gathering the 171716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * information as we needed it (file-by-file or directory-by-directory) 171816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * would be faster. However, on the actual device, 99% of the files will 171916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * live in Zip archives, so this list will be very small. The trouble 172016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * is that we have to check the "loose" files first, so it's important 172116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * that we don't beat the filesystem silly looking for files that aren't 172216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * there. 172316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 172416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Note on thread safety: this is the only function that causes updates 172516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * to mCache, and anybody who tries to use it will call here if !mCacheValid, 172616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * so we need to employ a mutex here. 172716c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 172816c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::loadFileNameCacheLocked(void) 172916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 173016c4d154dca43c662571129af31b27433b919a32Adam Lesinski assert(!mCacheValid); 173116c4d154dca43c662571129af31b27433b919a32Adam Lesinski assert(mCache.size() == 0); 173216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 173316c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifdef DO_TIMINGS // need to link against -lrt for this now 173416c4d154dca43c662571129af31b27433b919a32Adam Lesinski DurationTimer timer; 173516c4d154dca43c662571129af31b27433b919a32Adam Lesinski timer.start(); 173616c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 173716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 173816c4d154dca43c662571129af31b27433b919a32Adam Lesinski fncScanLocked(&mCache, ""); 173916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 174016c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifdef DO_TIMINGS 174116c4d154dca43c662571129af31b27433b919a32Adam Lesinski timer.stop(); 174216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGD("Cache scan took %.3fms\n", 174316c4d154dca43c662571129af31b27433b919a32Adam Lesinski timer.durationUsecs() / 1000.0); 174416c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 174516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 174616c4d154dca43c662571129af31b27433b919a32Adam Lesinski#if 0 174716c4d154dca43c662571129af31b27433b919a32Adam Lesinski int i; 174816c4d154dca43c662571129af31b27433b919a32Adam Lesinski printf("CACHED FILE LIST (%d entries):\n", mCache.size()); 174916c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (i = 0; i < (int) mCache.size(); i++) { 175016c4d154dca43c662571129af31b27433b919a32Adam Lesinski printf(" %d: (%d) '%s'\n", i, 175116c4d154dca43c662571129af31b27433b919a32Adam Lesinski mCache.itemAt(i).getFileType(), 175216c4d154dca43c662571129af31b27433b919a32Adam Lesinski (const char*) mCache.itemAt(i).getFileName()); 175316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 175416c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 175516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 175616c4d154dca43c662571129af31b27433b919a32Adam Lesinski mCacheValid = true; 175716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 175816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 175916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 176016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan up to 8 versions of the specified directory. 176116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 176216c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::fncScanLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, 176316c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* dirName) 176416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 176516c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t i = mAssetPaths.size(); 176616c4d154dca43c662571129af31b27433b919a32Adam Lesinski while (i > 0) { 176716c4d154dca43c662571129af31b27433b919a32Adam Lesinski i--; 176816c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap = mAssetPaths.itemAt(i); 176916c4d154dca43c662571129af31b27433b919a32Adam Lesinski fncScanAndMergeDirLocked(pMergedInfo, ap, NULL, NULL, dirName); 177016c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mLocale != NULL) 177116c4d154dca43c662571129af31b27433b919a32Adam Lesinski fncScanAndMergeDirLocked(pMergedInfo, ap, mLocale, NULL, dirName); 177216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mVendor != NULL) 177316c4d154dca43c662571129af31b27433b919a32Adam Lesinski fncScanAndMergeDirLocked(pMergedInfo, ap, NULL, mVendor, dirName); 177416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mLocale != NULL && mVendor != NULL) 177516c4d154dca43c662571129af31b27433b919a32Adam Lesinski fncScanAndMergeDirLocked(pMergedInfo, ap, mLocale, mVendor, dirName); 177616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 177716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 177816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 177916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 178016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Recursively scan this directory and all subdirs. 178116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 178216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * This is similar to scanAndMergeDir, but we don't remove the .EXCLUDE 178316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * files, and we prepend the extended partial path to the filenames. 178416c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 178516c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::fncScanAndMergeDirLocked( 178616c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pMergedInfo, 178716c4d154dca43c662571129af31b27433b919a32Adam Lesinski const asset_path& ap, const char* locale, const char* vendor, 178816c4d154dca43c662571129af31b27433b919a32Adam Lesinski const char* dirName) 178916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 179016c4d154dca43c662571129af31b27433b919a32Adam Lesinski SortedVector<AssetDir::FileInfo>* pContents; 179116c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 partialPath; 179216c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 fullPath; 179316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 179416c4d154dca43c662571129af31b27433b919a32Adam Lesinski // XXX This is broken -- the filename cache needs to hold the base 179516c4d154dca43c662571129af31b27433b919a32Adam Lesinski // asset path separately from its filename. 179616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 179716c4d154dca43c662571129af31b27433b919a32Adam Lesinski partialPath = createPathNameLocked(ap, locale, vendor); 179816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirName[0] != '\0') { 179916c4d154dca43c662571129af31b27433b919a32Adam Lesinski partialPath.appendPath(dirName); 180016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 180116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 180216c4d154dca43c662571129af31b27433b919a32Adam Lesinski fullPath = partialPath; 180316c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents = scanDirLocked(fullPath); 180416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pContents == NULL) { 180516c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; // directory did not exist 180616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 180716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 180816c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 180916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Scan all subdirectories of the current dir, merging what we find 181016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * into "pMergedInfo". 181116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 181216c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (int i = 0; i < (int) pContents->size(); i++) { 181316c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (pContents->itemAt(i).getFileType() == kFileTypeDirectory) { 181416c4d154dca43c662571129af31b27433b919a32Adam Lesinski String8 subdir(dirName); 181516c4d154dca43c662571129af31b27433b919a32Adam Lesinski subdir.appendPath(pContents->itemAt(i).getFileName()); 181616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 181716c4d154dca43c662571129af31b27433b919a32Adam Lesinski fncScanAndMergeDirLocked(pMergedInfo, ap, locale, vendor, subdir.string()); 181816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 181916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 182016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 182116c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 182216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * To be consistent, we want entries for the root directory. If 182316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * we're the root, add one now. 182416c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 182516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (dirName[0] == '\0') { 182616c4d154dca43c662571129af31b27433b919a32Adam Lesinski AssetDir::FileInfo tmpInfo; 182716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 182816c4d154dca43c662571129af31b27433b919a32Adam Lesinski tmpInfo.set(String8(""), kFileTypeDirectory); 182916c4d154dca43c662571129af31b27433b919a32Adam Lesinski tmpInfo.setSourceName(createPathNameLocked(ap, locale, vendor)); 183016c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents->add(tmpInfo); 183116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 183216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 183316c4d154dca43c662571129af31b27433b919a32Adam Lesinski /* 183416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * We want to prepend the extended partial path to every entry in 183516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * "pContents". It's the same value for each entry, so this will 183616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * not change the sorting order of the vector contents. 183716c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 183816c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (int i = 0; i < (int) pContents->size(); i++) { 183916c4d154dca43c662571129af31b27433b919a32Adam Lesinski const AssetDir::FileInfo& info = pContents->itemAt(i); 184016c4d154dca43c662571129af31b27433b919a32Adam Lesinski pContents->editItemAt(i).setFileName(partialPath.appendPathCopy(info.getFileName())); 184116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 184216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 184316c4d154dca43c662571129af31b27433b919a32Adam Lesinski mergeInfoLocked(pMergedInfo, pContents); 18447c57d2337150ab52c148d30d9126f3b99ca951b4sean_lu delete pContents; 184516c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 184616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 184716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 184816c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 184916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Trash the cache. 185016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 185116c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::purgeFileNameCacheLocked(void) 185216c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 185316c4d154dca43c662571129af31b27433b919a32Adam Lesinski mCacheValid = false; 185416c4d154dca43c662571129af31b27433b919a32Adam Lesinski mCache.clear(); 185516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 185616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 185716c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 185816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * =========================================================================== 185916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * AssetManager::SharedZip 186016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * =========================================================================== 186116c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 186216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 186316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 186416c4d154dca43c662571129af31b27433b919a32Adam LesinskiMutex AssetManager::SharedZip::gLock; 186516c4d154dca43c662571129af31b27433b919a32Adam LesinskiDefaultKeyedVector<String8, wp<AssetManager::SharedZip> > AssetManager::SharedZip::gOpen; 186616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 186716c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetManager::SharedZip::SharedZip(const String8& path, time_t modWhen) 186816c4d154dca43c662571129af31b27433b919a32Adam Lesinski : mPath(path), mZipFile(NULL), mModWhen(modWhen), 186916c4d154dca43c662571129af31b27433b919a32Adam Lesinski mResourceTableAsset(NULL), mResourceTable(NULL) 187016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 187116c4d154dca43c662571129af31b27433b919a32Adam Lesinski //ALOGI("Creating SharedZip %p %s\n", this, (const char*)mPath); 187216c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("+++ opening zip '%s'\n", mPath.string()); 1873560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath mZipFile = ZipFileRO::open(mPath.string()); 1874560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (mZipFile == NULL) { 187516c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGD("failed to open Zip archive '%s'\n", mPath.string()); 187616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 187716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 187816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 187948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadsp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path, 188048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad bool createIfNotPresent) 188116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 188216c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(gLock); 188316c4d154dca43c662571129af31b27433b919a32Adam Lesinski time_t modWhen = getFileModDate(path); 188416c4d154dca43c662571129af31b27433b919a32Adam Lesinski sp<SharedZip> zip = gOpen.valueFor(path).promote(); 188516c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (zip != NULL && zip->mModWhen == modWhen) { 188616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip; 188716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 188848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if (zip == NULL && !createIfNotPresent) { 188948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad return NULL; 189048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad } 189116c4d154dca43c662571129af31b27433b919a32Adam Lesinski zip = new SharedZip(path, modWhen); 189216c4d154dca43c662571129af31b27433b919a32Adam Lesinski gOpen.add(path, zip); 189316c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip; 189416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 189516c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 189616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 189716c4d154dca43c662571129af31b27433b919a32Adam LesinskiZipFileRO* AssetManager::SharedZip::getZip() 189816c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 189916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mZipFile; 190016c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 190116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 190216c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::SharedZip::getResourceTableAsset() 190316c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 190416c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Getting from SharedZip %p resource asset %p\n", this, mResourceTableAsset); 190516c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mResourceTableAsset; 190616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 190716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 190816c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::SharedZip::setResourceTableAsset(Asset* asset) 190916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 191016c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 191116c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(gLock); 191216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mResourceTableAsset == NULL) { 191316c4d154dca43c662571129af31b27433b919a32Adam Lesinski mResourceTableAsset = asset; 191416c4d154dca43c662571129af31b27433b919a32Adam Lesinski // This is not thread safe the first time it is called, so 191516c4d154dca43c662571129af31b27433b919a32Adam Lesinski // do it here with the global lock held. 191616c4d154dca43c662571129af31b27433b919a32Adam Lesinski asset->getBuffer(true); 191716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return asset; 191816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 191916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 192016c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete asset; 192116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mResourceTableAsset; 192216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 192316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 192416c4d154dca43c662571129af31b27433b919a32Adam LesinskiResTable* AssetManager::SharedZip::getResourceTable() 192516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 192616c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Getting from SharedZip %p resource table %p\n", this, mResourceTable); 192716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mResourceTable; 192816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 192916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 193016c4d154dca43c662571129af31b27433b919a32Adam LesinskiResTable* AssetManager::SharedZip::setResourceTable(ResTable* res) 193116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 193216c4d154dca43c662571129af31b27433b919a32Adam Lesinski { 193316c4d154dca43c662571129af31b27433b919a32Adam Lesinski AutoMutex _l(gLock); 193416c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mResourceTable == NULL) { 193516c4d154dca43c662571129af31b27433b919a32Adam Lesinski mResourceTable = res; 193616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return res; 193716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 193816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 193916c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete res; 194016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mResourceTable; 194116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 194216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 194316c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::SharedZip::isUpToDate() 194416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 194516c4d154dca43c662571129af31b27433b919a32Adam Lesinski time_t modWhen = getFileModDate(mPath.string()); 194616c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mModWhen == modWhen; 194716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 194816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 194948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadvoid AssetManager::SharedZip::addOverlay(const asset_path& ap) 195048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad{ 195148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad mOverlays.add(ap); 195248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad} 195348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad 195448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadbool AssetManager::SharedZip::getOverlay(size_t idx, asset_path* out) const 195548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad{ 195648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if (idx >= mOverlays.size()) { 195748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad return false; 195848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad } 195948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad *out = mOverlays[idx]; 196048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad return true; 196148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad} 196248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad 196316c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetManager::SharedZip::~SharedZip() 196416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 196516c4d154dca43c662571129af31b27433b919a32Adam Lesinski //ALOGI("Destroying SharedZip %p %s\n", this, (const char*)mPath); 196616c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mResourceTable != NULL) { 196716c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete mResourceTable; 196816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 196916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mResourceTableAsset != NULL) { 197016c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete mResourceTableAsset; 197116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 197216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mZipFile != NULL) { 197316c4d154dca43c662571129af31b27433b919a32Adam Lesinski delete mZipFile; 197416c4d154dca43c662571129af31b27433b919a32Adam Lesinski ALOGV("Closed '%s'\n", mPath.string()); 197516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 197616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 197716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 197816c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 197916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * =========================================================================== 198016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * AssetManager::ZipSet 198116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * =========================================================================== 198216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 198316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 198416c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 198516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Constructor. 198616c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 198716c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetManager::ZipSet::ZipSet(void) 198816c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 198916c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 199016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 199116c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 199216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Destructor. Close any open archives. 199316c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 199416c4d154dca43c662571129af31b27433b919a32Adam LesinskiAssetManager::ZipSet::~ZipSet(void) 199516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 199616c4d154dca43c662571129af31b27433b919a32Adam Lesinski size_t N = mZipFile.size(); 199716c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (size_t i = 0; i < N; i++) 199816c4d154dca43c662571129af31b27433b919a32Adam Lesinski closeZip(i); 199916c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 200016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 200116c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 200216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Close a Zip file and reset the entry. 200316c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 200416c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::ZipSet::closeZip(int idx) 200516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 200616c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipFile.editItemAt(idx) = NULL; 200716c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 200816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 200916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 201016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 201116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Retrieve the appropriate Zip file from the set. 201216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 201316c4d154dca43c662571129af31b27433b919a32Adam LesinskiZipFileRO* AssetManager::ZipSet::getZip(const String8& path) 201416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 201516c4d154dca43c662571129af31b27433b919a32Adam Lesinski int idx = getIndex(path); 201616c4d154dca43c662571129af31b27433b919a32Adam Lesinski sp<SharedZip> zip = mZipFile[idx]; 201716c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (zip == NULL) { 201816c4d154dca43c662571129af31b27433b919a32Adam Lesinski zip = SharedZip::get(path); 201916c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipFile.editItemAt(idx) = zip; 202016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 202116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip->getZip(); 202216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 202316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 202416c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::ZipSet::getZipResourceTableAsset(const String8& path) 202516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 202616c4d154dca43c662571129af31b27433b919a32Adam Lesinski int idx = getIndex(path); 202716c4d154dca43c662571129af31b27433b919a32Adam Lesinski sp<SharedZip> zip = mZipFile[idx]; 202816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (zip == NULL) { 202916c4d154dca43c662571129af31b27433b919a32Adam Lesinski zip = SharedZip::get(path); 203016c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipFile.editItemAt(idx) = zip; 203116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 203216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip->getResourceTableAsset(); 203316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 203416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 203516c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::ZipSet::setZipResourceTableAsset(const String8& path, 203616c4d154dca43c662571129af31b27433b919a32Adam Lesinski Asset* asset) 203716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 203816c4d154dca43c662571129af31b27433b919a32Adam Lesinski int idx = getIndex(path); 203916c4d154dca43c662571129af31b27433b919a32Adam Lesinski sp<SharedZip> zip = mZipFile[idx]; 204016c4d154dca43c662571129af31b27433b919a32Adam Lesinski // doesn't make sense to call before previously accessing. 204116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip->setResourceTableAsset(asset); 204216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 204316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 204416c4d154dca43c662571129af31b27433b919a32Adam LesinskiResTable* AssetManager::ZipSet::getZipResourceTable(const String8& path) 204516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 204616c4d154dca43c662571129af31b27433b919a32Adam Lesinski int idx = getIndex(path); 204716c4d154dca43c662571129af31b27433b919a32Adam Lesinski sp<SharedZip> zip = mZipFile[idx]; 204816c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (zip == NULL) { 204916c4d154dca43c662571129af31b27433b919a32Adam Lesinski zip = SharedZip::get(path); 205016c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipFile.editItemAt(idx) = zip; 205116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 205216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip->getResourceTable(); 205316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 205416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 205516c4d154dca43c662571129af31b27433b919a32Adam LesinskiResTable* AssetManager::ZipSet::setZipResourceTable(const String8& path, 205616c4d154dca43c662571129af31b27433b919a32Adam Lesinski ResTable* res) 205716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 205816c4d154dca43c662571129af31b27433b919a32Adam Lesinski int idx = getIndex(path); 205916c4d154dca43c662571129af31b27433b919a32Adam Lesinski sp<SharedZip> zip = mZipFile[idx]; 206016c4d154dca43c662571129af31b27433b919a32Adam Lesinski // doesn't make sense to call before previously accessing. 206116c4d154dca43c662571129af31b27433b919a32Adam Lesinski return zip->setResourceTable(res); 206216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 206316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 206416c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 206516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Generate the partial pathname for the specified archive. The caller 206616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * gets to prepend the asset root directory. 206716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 206816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Returns something like "common/en-US-noogle.jar". 206916c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 207016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/*static*/ String8 AssetManager::ZipSet::getPathName(const char* zipPath) 207116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 207216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return String8(zipPath); 207316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 207416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 207516c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::ZipSet::isUpToDate() 207616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 207716c4d154dca43c662571129af31b27433b919a32Adam Lesinski const size_t N = mZipFile.size(); 207816c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (size_t i=0; i<N; i++) { 207916c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mZipFile[i] != NULL && !mZipFile[i]->isUpToDate()) { 208016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 208116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 208216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 208316c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 208416c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 208516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 208648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadvoid AssetManager::ZipSet::addOverlay(const String8& path, const asset_path& overlay) 208748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad{ 208848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad int idx = getIndex(path); 208948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad sp<SharedZip> zip = mZipFile[idx]; 209048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad zip->addOverlay(overlay); 209148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad} 209248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad 209348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadbool AssetManager::ZipSet::getOverlay(const String8& path, size_t idx, asset_path* out) const 209448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad{ 209548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad sp<SharedZip> zip = SharedZip::get(path, false); 209648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad if (zip == NULL) { 209748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad return false; 209848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad } 209948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad return zip->getOverlay(idx, out); 210048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad} 210148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad 210216c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 210316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Compute the zip file's index. 210416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 210516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * "appName", "locale", and "vendor" should be set to NULL to indicate the 210616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * default directory. 210716c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 210816c4d154dca43c662571129af31b27433b919a32Adam Lesinskiint AssetManager::ZipSet::getIndex(const String8& zip) const 210916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 211016c4d154dca43c662571129af31b27433b919a32Adam Lesinski const size_t N = mZipPath.size(); 211116c4d154dca43c662571129af31b27433b919a32Adam Lesinski for (size_t i=0; i<N; i++) { 211216c4d154dca43c662571129af31b27433b919a32Adam Lesinski if (mZipPath[i] == zip) { 211316c4d154dca43c662571129af31b27433b919a32Adam Lesinski return i; 211416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 211516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 211616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 211716c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipPath.add(zip); 211816c4d154dca43c662571129af31b27433b919a32Adam Lesinski mZipFile.add(NULL); 211916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 212016c4d154dca43c662571129af31b27433b919a32Adam Lesinski return mZipPath.size()-1; 212116c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 2122