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