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>
37b7e1ce07756aaca829828c2053eca0d66dd4d440Adam Lesinski#include <utils/Trace.h>
380fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren#ifndef _WIN32
390fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren#include <sys/file.h>
400fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren#endif
4116c4d154dca43c662571129af31b27433b919a32Adam Lesinski
4216c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <assert.h>
4316c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <dirent.h>
4416c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <errno.h>
4548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#include <string.h> // strerror
4616c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <strings.h>
4716c4d154dca43c662571129af31b27433b919a32Adam Lesinski
4816c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifndef TEMP_FAILURE_RETRY
4916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* Used to retry syscalls that can return EINTR. */
5016c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define TEMP_FAILURE_RETRY(exp) ({         \
5116c4d154dca43c662571129af31b27433b919a32Adam Lesinski    typeof (exp) _rc;                      \
5216c4d154dca43c662571129af31b27433b919a32Adam Lesinski    do {                                   \
5316c4d154dca43c662571129af31b27433b919a32Adam Lesinski        _rc = (exp);                       \
5416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    } while (_rc == -1 && errno == EINTR); \
5516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    _rc; })
5616c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif
5716c4d154dca43c662571129af31b27433b919a32Adam Lesinski
5816c4d154dca43c662571129af31b27433b919a32Adam Lesinskiusing namespace android;
5916c4d154dca43c662571129af31b27433b919a32Adam Lesinski
602204f0bf56af53b588a01701b8cf9cd05b1b3ff9Andreas Gampestatic const bool kIsDebug = false;
612204f0bf56af53b588a01701b8cf9cd05b1b3ff9Andreas Gampe
6216c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kAssetsRoot = "assets";
6316c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kAppZipName = NULL; //"classes.jar";
6416c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kSystemAssets = "framework/framework-res.apk";
6548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadstatic const char* kResourceCache = "resource-cache";
6616c4d154dca43c662571129af31b27433b919a32Adam Lesinski
6716c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic const char* kExcludeExtension = ".EXCLUDE";
6816c4d154dca43c662571129af31b27433b919a32Adam Lesinski
6916c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic Asset* const kExcludedAsset = (Asset*) 0xd000000d;
7016c4d154dca43c662571129af31b27433b919a32Adam Lesinski
7116c4d154dca43c662571129af31b27433b919a32Adam Lesinskistatic volatile int32_t gCount = 0;
7216c4d154dca43c662571129af31b27433b919a32Adam Lesinski
7365a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstadconst char* AssetManager::RESOURCES_FILENAME = "resources.arsc";
7448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
7548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
7654dcaaba4fa0392c36864f99b9dc1da9c975a100Jakub Adamekconst char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
7748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::TARGET_PACKAGE_NAME = "android";
7848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
7948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::IDMAP_DIR = "/data/resource-cache";
8065a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad
8116c4d154dca43c662571129af31b27433b919a32Adam Lesinskinamespace {
8216c4d154dca43c662571129af31b27433b919a32Adam Lesinski
83a77685fa59a327b33e7acbcefe35e63243014cbdAdam LesinskiString8 idmapPathForPackagePath(const String8& pkgPath) {
84a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    const char* root = getenv("ANDROID_DATA");
85a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set");
86a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    String8 path(root);
87a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    path.appendPath(kResourceCache);
88a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski
89a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    char buf[256]; // 256 chars should be enough for anyone...
90a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    strncpy(buf, pkgPath.string(), 255);
91a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    buf[255] = '\0';
92a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    char* filename = buf;
93a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    while (*filename && *filename == '/') {
94a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski        ++filename;
95a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    }
96a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    char* p = filename;
97a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    while (*p) {
98a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski        if (*p == '/') {
99a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski            *p = '@';
100a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski        }
101a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski        ++p;
10216c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
103a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    path.appendPath(filename);
104a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    path.append("@idmap");
10516c4d154dca43c662571129af31b27433b919a32Adam Lesinski
106a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    return path;
107a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski}
108a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski
109a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski/*
110a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski * Like strdup(), but uses C++ "new" operator instead of malloc.
111a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski */
112a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinskistatic char* strdupNew(const char* str) {
113a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    char* newStr;
114a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    int len;
11516c4d154dca43c662571129af31b27433b919a32Adam Lesinski
116a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    if (str == NULL)
117a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski        return NULL;
11816c4d154dca43c662571129af31b27433b919a32Adam Lesinski
119a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    len = strlen(str);
120a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    newStr = new char[len+1];
121a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    memcpy(newStr, str, len+1);
12216c4d154dca43c662571129af31b27433b919a32Adam Lesinski
123a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski    return newStr;
12416c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
12516c4d154dca43c662571129af31b27433b919a32Adam Lesinski
126a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski} // namespace
127a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski
12816c4d154dca43c662571129af31b27433b919a32Adam Lesinski/*
12916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * ===========================================================================
13016c4d154dca43c662571129af31b27433b919a32Adam Lesinski *      AssetManager
13116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * ===========================================================================
13216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */
13316c4d154dca43c662571129af31b27433b919a32Adam Lesinski
134a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinskiint32_t AssetManager::getGlobalCount() {
13516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    return gCount;
13616c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
13716c4d154dca43c662571129af31b27433b919a32Adam Lesinski
138a77685fa59a327b33e7acbcefe35e63243014cbdAdam LesinskiAssetManager::AssetManager() :
139a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski        mLocale(NULL), mResources(NULL), mConfig(new ResTable_config) {
1402204f0bf56af53b588a01701b8cf9cd05b1b3ff9Andreas Gampe    int count = android_atomic_inc(&gCount) + 1;
1412204f0bf56af53b588a01701b8cf9cd05b1b3ff9Andreas Gampe    if (kIsDebug) {
1422204f0bf56af53b588a01701b8cf9cd05b1b3ff9Andreas Gampe        ALOGI("Creating AssetManager %p #%d\n", this, count);
1432204f0bf56af53b588a01701b8cf9cd05b1b3ff9Andreas Gampe    }
14416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    memset(mConfig, 0, sizeof(ResTable_config));
14516c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
14616c4d154dca43c662571129af31b27433b919a32Adam Lesinski
147a77685fa59a327b33e7acbcefe35e63243014cbdAdam LesinskiAssetManager::~AssetManager() {
14816c4d154dca43c662571129af31b27433b919a32Adam Lesinski    int count = android_atomic_dec(&gCount);
1492204f0bf56af53b588a01701b8cf9cd05b1b3ff9Andreas Gampe    if (kIsDebug) {
1502204f0bf56af53b588a01701b8cf9cd05b1b3ff9Andreas Gampe        ALOGI("Destroying AssetManager in %p #%d\n", this, count);
1512204f0bf56af53b588a01701b8cf9cd05b1b3ff9Andreas Gampe    }
15216c4d154dca43c662571129af31b27433b919a32Adam Lesinski
15316c4d154dca43c662571129af31b27433b919a32Adam Lesinski    delete mConfig;
15416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    delete mResources;
15516c4d154dca43c662571129af31b27433b919a32Adam Lesinski
15616c4d154dca43c662571129af31b27433b919a32Adam Lesinski    // don't have a String class yet, so make sure we clean up
15716c4d154dca43c662571129af31b27433b919a32Adam Lesinski    delete[] mLocale;
15816c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
15916c4d154dca43c662571129af31b27433b919a32Adam Lesinski
1601c686f2ce6cbfa3fdb598f452aa31d38f3eb2320Roozbeh Pournaderbool AssetManager::addAssetPath(
161a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski        const String8& path, int32_t* cookie, bool appAsLib, bool isSystemAsset) {
16216c4d154dca43c662571129af31b27433b919a32Adam Lesinski    AutoMutex _l(mLock);
16316c4d154dca43c662571129af31b27433b919a32Adam Lesinski
16416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    asset_path ap;
16516c4d154dca43c662571129af31b27433b919a32Adam Lesinski
16616c4d154dca43c662571129af31b27433b919a32Adam Lesinski    String8 realPath(path);
16716c4d154dca43c662571129af31b27433b919a32Adam Lesinski    if (kAppZipName) {
16816c4d154dca43c662571129af31b27433b919a32Adam Lesinski        realPath.appendPath(kAppZipName);
16916c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
17016c4d154dca43c662571129af31b27433b919a32Adam Lesinski    ap.type = ::getFileType(realPath.string());
17116c4d154dca43c662571129af31b27433b919a32Adam Lesinski    if (ap.type == kFileTypeRegular) {
17216c4d154dca43c662571129af31b27433b919a32Adam Lesinski        ap.path = realPath;
17316c4d154dca43c662571129af31b27433b919a32Adam Lesinski    } else {
17416c4d154dca43c662571129af31b27433b919a32Adam Lesinski        ap.path = path;
17516c4d154dca43c662571129af31b27433b919a32Adam Lesinski        ap.type = ::getFileType(path.string());
17616c4d154dca43c662571129af31b27433b919a32Adam Lesinski        if (ap.type != kFileTypeDirectory && ap.type != kFileTypeRegular) {
17716c4d154dca43c662571129af31b27433b919a32Adam Lesinski            ALOGW("Asset path %s is neither a directory nor file (type=%d).",
17816c4d154dca43c662571129af31b27433b919a32Adam Lesinski                 path.string(), (int)ap.type);
17916c4d154dca43c662571129af31b27433b919a32Adam Lesinski            return false;
18016c4d154dca43c662571129af31b27433b919a32Adam Lesinski        }
18116c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
18216c4d154dca43c662571129af31b27433b919a32Adam Lesinski
18316c4d154dca43c662571129af31b27433b919a32Adam Lesinski    // Skip if we have it already.
18416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    for (size_t i=0; i<mAssetPaths.size(); i++) {
18516c4d154dca43c662571129af31b27433b919a32Adam Lesinski        if (mAssetPaths[i].path == ap.path) {
18616c4d154dca43c662571129af31b27433b919a32Adam Lesinski            if (cookie) {
187a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath                *cookie = static_cast<int32_t>(i+1);
18816c4d154dca43c662571129af31b27433b919a32Adam Lesinski            }
18916c4d154dca43c662571129af31b27433b919a32Adam Lesinski            return true;
19016c4d154dca43c662571129af31b27433b919a32Adam Lesinski        }
19116c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
19216c4d154dca43c662571129af31b27433b919a32Adam Lesinski
19316c4d154dca43c662571129af31b27433b919a32Adam Lesinski    ALOGV("In %p Asset %s path: %s", this,
19416c4d154dca43c662571129af31b27433b919a32Adam Lesinski         ap.type == kFileTypeDirectory ? "dir" : "zip", ap.path.string());
19516c4d154dca43c662571129af31b27433b919a32Adam Lesinski
1961c686f2ce6cbfa3fdb598f452aa31d38f3eb2320Roozbeh Pournader    ap.isSystemAsset = isSystemAsset;
19716c4d154dca43c662571129af31b27433b919a32Adam Lesinski    mAssetPaths.add(ap);
19816c4d154dca43c662571129af31b27433b919a32Adam Lesinski
19916c4d154dca43c662571129af31b27433b919a32Adam Lesinski    // new paths are always added at the end
20016c4d154dca43c662571129af31b27433b919a32Adam Lesinski    if (cookie) {
201a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath        *cookie = static_cast<int32_t>(mAssetPaths.size());
20216c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
20316c4d154dca43c662571129af31b27433b919a32Adam Lesinski
2047de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#ifdef __ANDROID__
2057de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    // Load overlays, if any
2067de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    asset_path oap;
2077de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    for (size_t idx = 0; mZipSet.getOverlay(ap.path, idx, &oap); idx++) {
2087de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        oap.isSystemAsset = isSystemAsset;
2097de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        mAssetPaths.add(oap);
2107de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    }
2117de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#endif
2127de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
2137df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba    if (mResources != NULL) {
214a6d7e3fb9c9233b9ae46b702d17433854c43d6a0Tao Bai        appendPathToResTable(ap, appAsLib);
2157df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba    }
2167df3625d5bb28d11cce9ac23429f5e3c6ebac030Martin Kosiba
21716c4d154dca43c662571129af31b27433b919a32Adam Lesinski    return true;
21816c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
21916c4d154dca43c662571129af31b27433b919a32Adam Lesinski
22048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadbool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie)
22165a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad{
22248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    const String8 idmapPath = idmapPathForPackagePath(packagePath);
22365a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad
22448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    AutoMutex _l(mLock);
22565a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad
22648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    for (size_t i = 0; i < mAssetPaths.size(); ++i) {
22748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        if (mAssetPaths[i].idmap == idmapPath) {
22848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad           *cookie = static_cast<int32_t>(i + 1);
22948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            return true;
23048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad         }
23148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad     }
23265a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad
23348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    Asset* idmap = NULL;
23448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if ((idmap = openAssetFromFileLocked(idmapPath, Asset::ACCESS_BUFFER)) == NULL) {
23548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ALOGW("failed to open idmap file %s\n", idmapPath.string());
23616c4d154dca43c662571129af31b27433b919a32Adam Lesinski        return false;
23716c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
23816c4d154dca43c662571129af31b27433b919a32Adam Lesinski
23948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    String8 targetPath;
24048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    String8 overlayPath;
24148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (!ResTable::getIdmapInfo(idmap->getBuffer(false), idmap->getLength(),
242f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                NULL, NULL, NULL, &targetPath, &overlayPath)) {
24348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ALOGW("failed to read idmap file %s\n", idmapPath.string());
24448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        delete idmap;
24516c4d154dca43c662571129af31b27433b919a32Adam Lesinski        return false;
24616c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
24748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    delete idmap;
24816c4d154dca43c662571129af31b27433b919a32Adam Lesinski
24948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (overlayPath != packagePath) {
25048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ALOGW("idmap file %s inconcistent: expected path %s does not match actual path %s\n",
25148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                idmapPath.string(), packagePath.string(), overlayPath.string());
25216c4d154dca43c662571129af31b27433b919a32Adam Lesinski        return false;
25316c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
25448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (access(targetPath.string(), R_OK) != 0) {
25548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ALOGW("failed to access file %s: %s\n", targetPath.string(), strerror(errno));
25616c4d154dca43c662571129af31b27433b919a32Adam Lesinski        return false;
25716c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
25848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (access(idmapPath.string(), R_OK) != 0) {
25948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ALOGW("failed to access file %s: %s\n", idmapPath.string(), strerror(errno));
26016c4d154dca43c662571129af31b27433b919a32Adam Lesinski        return false;
26116c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
26248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (access(overlayPath.string(), R_OK) != 0) {
26348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ALOGW("failed to access file %s: %s\n", overlayPath.string(), strerror(errno));
26416c4d154dca43c662571129af31b27433b919a32Adam Lesinski        return false;
26516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
266560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath
26748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    asset_path oap;
26848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    oap.path = overlayPath;
26948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    oap.type = ::getFileType(overlayPath.string());
27048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    oap.idmap = idmapPath;
27148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#if 0
27248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    ALOGD("Overlay added: targetPath=%s overlayPath=%s idmapPath=%s\n",
27348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            targetPath.string(), overlayPath.string(), idmapPath.string());
27448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#endif
27548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    mAssetPaths.add(oap);
27648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    *cookie = static_cast<int32_t>(mAssetPaths.size());
277560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath
27830113131fb958850ef92c6a8f7f2aa2ed92a8ffeMårten Kongstad    if (mResources != NULL) {
27930113131fb958850ef92c6a8f7f2aa2ed92a8ffeMårten Kongstad        appendPathToResTable(oap);
28030113131fb958850ef92c6a8f7f2aa2ed92a8ffeMårten Kongstad    }
28130113131fb958850ef92c6a8f7f2aa2ed92a8ffeMårten Kongstad
28248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    return true;
28348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad }
28416c4d154dca43c662571129af31b27433b919a32Adam Lesinski
28548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadbool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApkPath,
2861cbea39fe1740d7d1c3e4aa0e4771a99a56c79efNick Kralevich        uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize)
28716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{
28848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    AutoMutex _l(mLock);
28948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    const String8 paths[2] = { String8(targetApkPath), String8(overlayApkPath) };
2906bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad    Asset* assets[2] = {NULL, NULL};
2916bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad    bool ret = false;
2926bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad    {
2936bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad        ResTable tables[2];
2946bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad
2956bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad        for (int i = 0; i < 2; ++i) {
2966bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad            asset_path ap;
2976bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad            ap.type = kFileTypeRegular;
2986bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad            ap.path = paths[i];
2996bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad            assets[i] = openNonAssetInPathLocked("resources.arsc",
3006bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad                    Asset::ACCESS_BUFFER, ap);
3016bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad            if (assets[i] == NULL) {
3026bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad                ALOGW("failed to find resources.arsc in %s\n", ap.path.string());
3036bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad                goto exit;
3046bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad            }
3056bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad            if (tables[i].add(assets[i]) != NO_ERROR) {
3066bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad                ALOGW("failed to add %s to resource table", paths[i].string());
3076bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad                goto exit;
3086bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad            }
30916c4d154dca43c662571129af31b27433b919a32Adam Lesinski        }
3106bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad        ret = tables[0].createIdmap(tables[1], targetCrc, overlayCrc,
3116bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad                targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR;
31216c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
31316c4d154dca43c662571129af31b27433b919a32Adam Lesinski
3146bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstadexit:
3156bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad    delete assets[0];
3166bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad    delete assets[1];
3176bb13da2789b2485a628e4fc077524b430661c82Mårten Kongstad    return ret;
31816c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
31916c4d154dca43c662571129af31b27433b919a32Adam Lesinski
32016c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool AssetManager::addDefaultAssets()
32116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{
32216c4d154dca43c662571129af31b27433b919a32Adam Lesinski    const char* root = getenv("ANDROID_ROOT");
32316c4d154dca43c662571129af31b27433b919a32Adam Lesinski    LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_ROOT not set");
32416c4d154dca43c662571129af31b27433b919a32Adam Lesinski
32516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    String8 path(root);
32616c4d154dca43c662571129af31b27433b919a32Adam Lesinski    path.appendPath(kSystemAssets);
32716c4d154dca43c662571129af31b27433b919a32Adam Lesinski
3281c686f2ce6cbfa3fdb598f452aa31d38f3eb2320Roozbeh Pournader    return addAssetPath(path, NULL, false /* appAsLib */, true /* isSystemAsset */);
32916c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
33016c4d154dca43c662571129af31b27433b919a32Adam Lesinski
331a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamathint32_t AssetManager::nextAssetPath(const int32_t cookie) const
33216c4d154dca43c662571129af31b27433b919a32Adam Lesinski{
33316c4d154dca43c662571129af31b27433b919a32Adam Lesinski    AutoMutex _l(mLock);
334a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath    const size_t next = static_cast<size_t>(cookie) + 1;
335a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath    return next > mAssetPaths.size() ? -1 : next;
33616c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
33716c4d154dca43c662571129af31b27433b919a32Adam Lesinski
338a0c6260705c841f501282e0e337970ca9a00e064Narayan KamathString8 AssetManager::getAssetPath(const int32_t cookie) const
33916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{
34016c4d154dca43c662571129af31b27433b919a32Adam Lesinski    AutoMutex _l(mLock);
341a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath    const size_t which = static_cast<size_t>(cookie) - 1;
34216c4d154dca43c662571129af31b27433b919a32Adam Lesinski    if (which < mAssetPaths.size()) {
34316c4d154dca43c662571129af31b27433b919a32Adam Lesinski        return mAssetPaths[which].path;
34416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
34516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    return String8();
34616c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
34716c4d154dca43c662571129af31b27433b919a32Adam Lesinski
34816c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::setLocaleLocked(const char* locale)
34916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{
35016c4d154dca43c662571129af31b27433b919a32Adam Lesinski    if (mLocale != NULL) {
35116c4d154dca43c662571129af31b27433b919a32Adam Lesinski        delete[] mLocale;
35216c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
353c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
35416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    mLocale = strdupNew(locale);
35516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    updateResourceParamsLocked();
35616c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
35716c4d154dca43c662571129af31b27433b919a32Adam Lesinski
35816c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::setConfiguration(const ResTable_config& config, const char* locale)
35916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{
36016c4d154dca43c662571129af31b27433b919a32Adam Lesinski    AutoMutex _l(mLock);
36116c4d154dca43c662571129af31b27433b919a32Adam Lesinski    *mConfig = config;
36216c4d154dca43c662571129af31b27433b919a32Adam Lesinski    if (locale) {
36316c4d154dca43c662571129af31b27433b919a32Adam Lesinski        setLocaleLocked(locale);
36416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    } else if (config.language[0] != 0) {
36591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath        char spec[RESTABLE_MAX_LOCALE_LEN];
36691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath        config.getBcp47Locale(spec);
36716c4d154dca43c662571129af31b27433b919a32Adam Lesinski        setLocaleLocked(spec);
36816c4d154dca43c662571129af31b27433b919a32Adam Lesinski    } else {
36916c4d154dca43c662571129af31b27433b919a32Adam Lesinski        updateResourceParamsLocked();
37016c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
37116c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
37216c4d154dca43c662571129af31b27433b919a32Adam Lesinski
37316c4d154dca43c662571129af31b27433b919a32Adam Lesinskivoid AssetManager::getConfiguration(ResTable_config* outConfig) const
37416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{
37516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    AutoMutex _l(mLock);
37616c4d154dca43c662571129af31b27433b919a32Adam Lesinski    *outConfig = *mConfig;
37716c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
37816c4d154dca43c662571129af31b27433b919a32Adam Lesinski
37916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/*
38016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open an asset.
38116c4d154dca43c662571129af31b27433b919a32Adam Lesinski *
382fe90eaf528622d66549432538d24722534ad48fcAdam Lesinski * The data could be in any asset path. Each asset path could be:
383fe90eaf528622d66549432538d24722534ad48fcAdam Lesinski *  - A directory on disk.
384fe90eaf528622d66549432538d24722534ad48fcAdam Lesinski *  - A Zip archive, uncompressed or compressed.
38516c4d154dca43c662571129af31b27433b919a32Adam Lesinski *
386fe90eaf528622d66549432538d24722534ad48fcAdam Lesinski * If the file is in a directory, it could have a .gz suffix, meaning it is compressed.
38716c4d154dca43c662571129af31b27433b919a32Adam Lesinski *
38816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * We should probably reject requests for "illegal" filenames, e.g. those
38916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * with illegal characters or "../" backward relative paths.
39016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */
39116c4d154dca43c662571129af31b27433b919a32Adam LesinskiAsset* AssetManager::open(const char* fileName, AccessMode mode)
39216c4d154dca43c662571129af31b27433b919a32Adam Lesinski{
39316c4d154dca43c662571129af31b27433b919a32Adam Lesinski    AutoMutex _l(mLock);
39416c4d154dca43c662571129af31b27433b919a32Adam Lesinski
39516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
39616c4d154dca43c662571129af31b27433b919a32Adam Lesinski
39716c4d154dca43c662571129af31b27433b919a32Adam Lesinski    String8 assetName(kAssetsRoot);
39816c4d154dca43c662571129af31b27433b919a32Adam Lesinski    assetName.appendPath(fileName);
39916c4d154dca43c662571129af31b27433b919a32Adam Lesinski
40016c4d154dca43c662571129af31b27433b919a32Adam Lesinski    /*
40116c4d154dca43c662571129af31b27433b919a32Adam Lesinski     * For each top-level asset path, search for the asset.
40216c4d154dca43c662571129af31b27433b919a32Adam Lesinski     */
40316c4d154dca43c662571129af31b27433b919a32Adam Lesinski
40416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    size_t i = mAssetPaths.size();
40516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    while (i > 0) {
40616c4d154dca43c662571129af31b27433b919a32Adam Lesinski        i--;
40716c4d154dca43c662571129af31b27433b919a32Adam Lesinski        ALOGV("Looking for asset '%s' in '%s'\n",
40816c4d154dca43c662571129af31b27433b919a32Adam Lesinski                assetName.string(), mAssetPaths.itemAt(i).path.string());
40916c4d154dca43c662571129af31b27433b919a32Adam Lesinski        Asset* pAsset = openNonAssetInPathLocked(assetName.string(), mode, mAssetPaths.itemAt(i));
41016c4d154dca43c662571129af31b27433b919a32Adam Lesinski        if (pAsset != NULL) {
41116c4d154dca43c662571129af31b27433b919a32Adam Lesinski            return pAsset != kExcludedAsset ? pAsset : NULL;
41216c4d154dca43c662571129af31b27433b919a32Adam Lesinski        }
41316c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
41416c4d154dca43c662571129af31b27433b919a32Adam Lesinski
41516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    return NULL;
41616c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
41716c4d154dca43c662571129af31b27433b919a32Adam Lesinski
41816c4d154dca43c662571129af31b27433b919a32Adam Lesinski/*
41916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open a non-asset file as if it were an asset.
42016c4d154dca43c662571129af31b27433b919a32Adam Lesinski *
421fe90eaf528622d66549432538d24722534ad48fcAdam Lesinski * The "fileName" is the partial path starting from the application name.
42216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */
423de898ff42912bd7ca1bfb099cd439562496765a4Adam LesinskiAsset* AssetManager::openNonAsset(const char* fileName, AccessMode mode, int32_t* outCookie)
42416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{
42516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    AutoMutex _l(mLock);
42616c4d154dca43c662571129af31b27433b919a32Adam Lesinski
42716c4d154dca43c662571129af31b27433b919a32Adam Lesinski    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
42816c4d154dca43c662571129af31b27433b919a32Adam Lesinski
42916c4d154dca43c662571129af31b27433b919a32Adam Lesinski    /*
43016c4d154dca43c662571129af31b27433b919a32Adam Lesinski     * For each top-level asset path, search for the asset.
43116c4d154dca43c662571129af31b27433b919a32Adam Lesinski     */
43216c4d154dca43c662571129af31b27433b919a32Adam Lesinski
43316c4d154dca43c662571129af31b27433b919a32Adam Lesinski    size_t i = mAssetPaths.size();
43416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    while (i > 0) {
43516c4d154dca43c662571129af31b27433b919a32Adam Lesinski        i--;
43616c4d154dca43c662571129af31b27433b919a32Adam Lesinski        ALOGV("Looking for non-asset '%s' in '%s'\n", fileName, mAssetPaths.itemAt(i).path.string());
43716c4d154dca43c662571129af31b27433b919a32Adam Lesinski        Asset* pAsset = openNonAssetInPathLocked(
43816c4d154dca43c662571129af31b27433b919a32Adam Lesinski            fileName, mode, mAssetPaths.itemAt(i));
43916c4d154dca43c662571129af31b27433b919a32Adam Lesinski        if (pAsset != NULL) {
440de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            if (outCookie != NULL) *outCookie = static_cast<int32_t>(i + 1);
44116c4d154dca43c662571129af31b27433b919a32Adam Lesinski            return pAsset != kExcludedAsset ? pAsset : NULL;
44216c4d154dca43c662571129af31b27433b919a32Adam Lesinski        }
44316c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
44416c4d154dca43c662571129af31b27433b919a32Adam Lesinski
44516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    return NULL;
44616c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
44716c4d154dca43c662571129af31b27433b919a32Adam Lesinski
448a0c6260705c841f501282e0e337970ca9a00e064Narayan KamathAsset* AssetManager::openNonAsset(const int32_t cookie, const char* fileName, AccessMode mode)
44916c4d154dca43c662571129af31b27433b919a32Adam Lesinski{
450a0c6260705c841f501282e0e337970ca9a00e064Narayan Kamath    const size_t which = static_cast<size_t>(cookie) - 1;
45116c4d154dca43c662571129af31b27433b919a32Adam Lesinski
45216c4d154dca43c662571129af31b27433b919a32Adam Lesinski    AutoMutex _l(mLock);
45316c4d154dca43c662571129af31b27433b919a32Adam Lesinski
45416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
45516c4d154dca43c662571129af31b27433b919a32Adam Lesinski
45616c4d154dca43c662571129af31b27433b919a32Adam Lesinski    if (which < mAssetPaths.size()) {
45716c4d154dca43c662571129af31b27433b919a32Adam Lesinski        ALOGV("Looking for non-asset '%s' in '%s'\n", fileName,
45816c4d154dca43c662571129af31b27433b919a32Adam Lesinski                mAssetPaths.itemAt(which).path.string());
45916c4d154dca43c662571129af31b27433b919a32Adam Lesinski        Asset* pAsset = openNonAssetInPathLocked(
46016c4d154dca43c662571129af31b27433b919a32Adam Lesinski            fileName, mode, mAssetPaths.itemAt(which));
46116c4d154dca43c662571129af31b27433b919a32Adam Lesinski        if (pAsset != NULL) {
46216c4d154dca43c662571129af31b27433b919a32Adam Lesinski            return pAsset != kExcludedAsset ? pAsset : NULL;
46316c4d154dca43c662571129af31b27433b919a32Adam Lesinski        }
46416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    }
46516c4d154dca43c662571129af31b27433b919a32Adam Lesinski
46616c4d154dca43c662571129af31b27433b919a32Adam Lesinski    return NULL;
46716c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
46816c4d154dca43c662571129af31b27433b919a32Adam Lesinski
46916c4d154dca43c662571129af31b27433b919a32Adam Lesinski/*
47016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Get the type of a file in the asset namespace.
47116c4d154dca43c662571129af31b27433b919a32Adam Lesinski *
47216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * This currently only works for regular files.  All others (including
47316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * directories) will return kFileTypeNonexistent.
47416c4d154dca43c662571129af31b27433b919a32Adam Lesinski */
47516c4d154dca43c662571129af31b27433b919a32Adam LesinskiFileType AssetManager::getFileType(const char* fileName)
47616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{
47716c4d154dca43c662571129af31b27433b919a32Adam Lesinski    Asset* pAsset = NULL;
47816c4d154dca43c662571129af31b27433b919a32Adam Lesinski
47916c4d154dca43c662571129af31b27433b919a32Adam Lesinski    /*
48016c4d154dca43c662571129af31b27433b919a32Adam Lesinski     * Open the asset.  This is less efficient than simply finding the
48116c4d154dca43c662571129af31b27433b919a32Adam Lesinski     * file, but it's not too bad (we don't uncompress or mmap data until
48216c4d154dca43c662571129af31b27433b919a32Adam Lesinski     * the first read() call).
48316c4d154dca43c662571129af31b27433b919a32Adam Lesinski     */
48416c4d154dca43c662571129af31b27433b919a32Adam Lesinski    pAsset = open(fileName, Asset::ACCESS_STREAMING);
48516c4d154dca43c662571129af31b27433b919a32Adam Lesinski    delete pAsset;
48616c4d154dca43c662571129af31b27433b919a32Adam Lesinski
487fe90eaf528622d66549432538d24722534ad48fcAdam Lesinski    if (pAsset == NULL) {
48816c4d154dca43c662571129af31b27433b919a32Adam Lesinski        return kFileTypeNonexistent;
489fe90eaf528622d66549432538d24722534ad48fcAdam Lesinski    } else {
49016c4d154dca43c662571129af31b27433b919a32Adam Lesinski        return kFileTypeRegular;
491fe90eaf528622d66549432538d24722534ad48fcAdam Lesinski    }
49216c4d154dca43c662571129af31b27433b919a32Adam Lesinski}
49316c4d154dca43c662571129af31b27433b919a32Adam Lesinski
494a6d7e3fb9c9233b9ae46b702d17433854c43d6a0Tao Baibool AssetManager::appendPathToResTable(const asset_path& ap, bool appAsLib) const {
4957de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    // skip those ap's that correspond to system overlays
4967de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    if (ap.isSystemOverlay) {
4977de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        return true;
4987de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    }
4997de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok