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