AssetManager.cpp revision 48d22323ce39f9aab003dce74456889b6414af55
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Provide access to read-only assets.
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "asset"
22f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#define ATRACE_TAG ATRACE_TAG_RESOURCES
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//#define LOG_NDEBUG 0
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/Asset.h>
26b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/AssetDir.h>
27b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/AssetManager.h>
281f5762e646bed2290934280464832782766ee68eMathias Agopian#include <androidfw/misc.h>
29b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/ResourceTypes.h>
301f5762e646bed2290934280464832782766ee68eMathias Agopian#include <androidfw/ZipFileRO.h>
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Atomic.h>
32b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <utils/Log.h>
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String8.h>
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String8.h>
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/threads.h>
36b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <utils/Timers.h>
37c51d050f1bc2c393707f7c5e1f6906169ace7497Dianne Hackborn#ifdef HAVE_ANDROID_OS
38f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#include <cutils/trace.h>
39c51d050f1bc2c393707f7c5e1f6906169ace7497Dianne Hackborn#endif
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
41b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <assert.h>
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <dirent.h>
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h>
4448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#include <string.h> // strerror
45b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <strings.h>
4657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
4757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad#ifndef TEMP_FAILURE_RETRY
4857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad/* Used to retry syscalls that can return EINTR. */
4957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad#define TEMP_FAILURE_RETRY(exp) ({         \
5057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    typeof (exp) _rc;                      \
5157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    do {                                   \
5257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        _rc = (exp);                       \
5357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    } while (_rc == -1 && errno == EINTR); \
5457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    _rc; })
5557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad#endif
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
57f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#ifdef HAVE_ANDROID_OS
58f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#define MY_TRACE_BEGIN(x) ATRACE_BEGIN(x)
59f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#define MY_TRACE_END() ATRACE_END()
60f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#else
61f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#define MY_TRACE_BEGIN(x)
62f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#define MY_TRACE_END()
63f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#endif
64f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Names for default app, locale, and vendor.  We might want to change
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * these to be an actual locale, e.g. always use en-US as the default.
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* kDefaultLocale = "default";
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* kDefaultVendor = "default";
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* kAssetsRoot = "assets";
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* kAppZipName = NULL; //"classes.jar";
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* kSystemAssets = "framework/framework-res.apk";
7648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadstatic const char* kResourceCache = "resource-cache";
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* kExcludeExtension = ".EXCLUDE";
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic Asset* const kExcludedAsset = (Asset*) 0xd000000d;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic volatile int32_t gCount = 0;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8465a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstadconst char* AssetManager::RESOURCES_FILENAME = "resources.arsc";
8548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
8648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
8748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::TARGET_PACKAGE_NAME = "android";
8848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
8948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadconst char* AssetManager::IDMAP_DIR = "/data/resource-cache";
9065a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad
9157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstadnamespace {
9257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    String8 idmapPathForPackagePath(const String8& pkgPath)
9357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    {
9457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        const char* root = getenv("ANDROID_DATA");
9557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set");
9657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        String8 path(root);
9748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        path.appendPath(kResourceCache);
9857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
9957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        char buf[256]; // 256 chars should be enough for anyone...
10057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        strncpy(buf, pkgPath.string(), 255);
10157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        buf[255] = '\0';
10257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        char* filename = buf;
10357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        while (*filename && *filename == '/') {
10457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            ++filename;
10557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
10657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        char* p = filename;
10757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        while (*p) {
10857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            if (*p == '/') {
10957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                *p = '@';
11057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            }
11157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            ++p;
11257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
11357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        path.appendPath(filename);
11457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        path.append("@idmap");
11557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
11657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return path;
11757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
11869a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian
11969a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian    /*
12069a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian     * Like strdup(), but uses C++ "new" operator instead of malloc.
12169a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian     */
12269a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian    static char* strdupNew(const char* str)
12369a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian    {
12469a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        char* newStr;
12569a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        int len;
12669a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian
12769a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        if (str == NULL)
12869a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian            return NULL;
12969a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian
13069a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        len = strlen(str);
13169a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        newStr = new char[len+1];
13269a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        memcpy(newStr, str, len+1);
13369a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian
13469a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        return newStr;
13569a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian    }
13657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad}
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      AssetManager
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint32_t AssetManager::getGlobalCount()
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return gCount;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetManager::AssetManager(CacheMode cacheMode)
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mLocale(NULL), mVendor(NULL),
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mResources(NULL), mConfig(new ResTable_config),
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mCacheMode(cacheMode), mCacheValid(false)
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int count = android_atomic_inc(&gCount)+1;
1556215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block    //ALOGI("Creating AssetManager %p #%d\n", this, count);
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    memset(mConfig, 0, sizeof(ResTable_config));
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetManager::~AssetManager(void)
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int count = android_atomic_dec(&gCount);
1626215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block    //ALOGI("Destroying AssetManager in %p #%d\n", this, count);
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete mConfig;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete mResources;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // don't have a String class yet, so make sure we clean up
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete[] mLocale;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete[] mVendor;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
172745d4efc8369d255341d810790132660e33d3b61Narayan Kamathbool AssetManager::addAssetPath(const String8& path, int32_t* cookie)
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    asset_path ap;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 realPath(path);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (kAppZipName) {
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        realPath.appendPath(kAppZipName);
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ap.type = ::getFileType(realPath.string());
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ap.type == kFileTypeRegular) {
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ap.path = realPath;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ap.path = path;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ap.type = ::getFileType(path.string());
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ap.type != kFileTypeDirectory && ap.type != kFileTypeRegular) {
1898564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("Asset path %s is neither a directory nor file (type=%d).",
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 path.string(), (int)ap.type);
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Skip if we have it already.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<mAssetPaths.size(); i++) {
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mAssetPaths[i].path == ap.path) {
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cookie) {
199745d4efc8369d255341d810790132660e33d3b61Narayan Kamath                *cookie = static_cast<int32_t>(i+1);
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
20571f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("In %p Asset %s path: %s", this,
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         ap.type == kFileTypeDirectory ? "dir" : "zip", ap.path.string());
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mAssetPaths.add(ap);
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // new paths are always added at the end
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (cookie) {
212745d4efc8369d255341d810790132660e33d3b61Narayan Kamath        *cookie = static_cast<int32_t>(mAssetPaths.size());
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#ifdef HAVE_ANDROID_OS
21648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    // Load overlays, if any
21748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    asset_path oap;
21848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    for (size_t idx = 0; mZipSet.getOverlay(ap.path, idx, &oap); idx++) {
21948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        mAssetPaths.add(oap);
22057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
22148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#endif
22257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadbool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie)
22765a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad{
22848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    const String8 idmapPath = idmapPathForPackagePath(packagePath);
22965a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad
23048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    AutoMutex _l(mLock);
23165a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad
23248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    for (size_t i = 0; i < mAssetPaths.size(); ++i) {
23348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        if (mAssetPaths[i].idmap == idmapPath) {
23448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad           *cookie = static_cast<int32_t>(i + 1);
23548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            return true;
23648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad         }
23748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad     }
23865a05fd56dbc9fd9c2511a97f49c445a748fb3c5Mårten Kongstad
23948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    Asset* idmap = NULL;
24048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if ((idmap = openAssetFromFileLocked(idmapPath, Asset::ACCESS_BUFFER)) == NULL) {
24148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ALOGW("failed to open idmap file %s\n", idmapPath.string());
24257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
24357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
24457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
24548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    String8 targetPath;
24648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    String8 overlayPath;
24748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (!ResTable::getIdmapInfo(idmap->getBuffer(false), idmap->getLength(),
24848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                NULL, NULL, &targetPath, &overlayPath)) {
24948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ALOGW("failed to read idmap file %s\n", idmapPath.string());
25048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        delete idmap;
25157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
25257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
25348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    delete idmap;
25457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
25548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (overlayPath != packagePath) {
25648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ALOGW("idmap file %s inconcistent: expected path %s does not match actual path %s\n",
25748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                idmapPath.string(), packagePath.string(), overlayPath.string());
25857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
25957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
26048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (access(targetPath.string(), R_OK) != 0) {
26148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ALOGW("failed to access file %s: %s\n", targetPath.string(), strerror(errno));
26257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
26357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
26448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (access(idmapPath.string(), R_OK) != 0) {
26548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ALOGW("failed to access file %s: %s\n", idmapPath.string(), strerror(errno));
26657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
26757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
26848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (access(overlayPath.string(), R_OK) != 0) {
26948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ALOGW("failed to access file %s: %s\n", overlayPath.string(), strerror(errno));
27057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
27157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
272afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath
27348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    asset_path oap;
27448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    oap.path = overlayPath;
27548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    oap.type = ::getFileType(overlayPath.string());
27648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    oap.idmap = idmapPath;
27748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#if 0
27848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    ALOGD("Overlay added: targetPath=%s overlayPath=%s idmapPath=%s\n",
27948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            targetPath.string(), overlayPath.string(), idmapPath.string());
28048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#endif
28148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    mAssetPaths.add(oap);
28248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    *cookie = static_cast<int32_t>(mAssetPaths.size());
283afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath
28448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    return true;
28548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad }
28657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
28748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadbool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApkPath,
28848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, uint32_t* outSize)
28957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad{
29048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    AutoMutex _l(mLock);
29148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    const String8 paths[2] = { String8(targetApkPath), String8(overlayApkPath) };
29257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    ResTable tables[2];
29357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
29457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    for (int i = 0; i < 2; ++i) {
29557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        asset_path ap;
29657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        ap.type = kFileTypeRegular;
29748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        ap.path = paths[i];
29857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap);
29957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        if (ass == NULL) {
3008564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("failed to find resources.arsc in %s\n", ap.path.string());
30148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            return false;
30257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
3037c4887f66bfa3dad16f8b03dc825ade96d7de130Narayan Kamath        tables[i].add(ass, 1, false /* copyData */, NULL /* idMap */);
30457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
30557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
30648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    return tables[0].createIdmap(tables[1], targetCrc, overlayCrc,
30748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR;
30857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad}
30957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::addDefaultAssets()
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* root = getenv("ANDROID_ROOT");
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_ROOT not set");
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 path(root);
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    path.appendPath(kSystemAssets);
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return addAssetPath(path, NULL);
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
321745d4efc8369d255341d810790132660e33d3b61Narayan Kamathint32_t AssetManager::nextAssetPath(const int32_t cookie) const
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
324745d4efc8369d255341d810790132660e33d3b61Narayan Kamath    const size_t next = static_cast<size_t>(cookie) + 1;
325745d4efc8369d255341d810790132660e33d3b61Narayan Kamath    return next > mAssetPaths.size() ? -1 : next;
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
328745d4efc8369d255341d810790132660e33d3b61Narayan KamathString8 AssetManager::getAssetPath(const int32_t cookie) const
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
331745d4efc8369d255341d810790132660e33d3b61Narayan Kamath    const size_t which = static_cast<size_t>(cookie) - 1;
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (which < mAssetPaths.size()) {
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAssetPaths[which].path;
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return String8();
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the current locale.  Use NULL to indicate no locale.
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close and reopen Zip archives as appropriate, and reset cached
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * information in the locale-specific sections of the tree.
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::setLocale(const char* locale)
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    setLocaleLocked(locale);
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::setLocaleLocked(const char* locale)
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mLocale != NULL) {
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* previously set, purge cached data */
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        purgeFileNameCacheLocked();
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //mZipSet.purgeLocale();
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete[] mLocale;
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mLocale = strdupNew(locale);
359c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    updateResourceParamsLocked();
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the current vendor.  Use NULL to indicate no vendor.
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close and reopen Zip archives as appropriate, and reset cached
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * information in the vendor-specific sections of the tree.
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::setVendor(const char* vendor)
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mVendor != NULL) {
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* previously set, purge cached data */
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        purgeFileNameCacheLocked();
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //mZipSet.purgeVendor();
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete[] mVendor;
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mVendor = strdupNew(vendor);
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::setConfiguration(const ResTable_config& config, const char* locale)
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *mConfig = config;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (locale) {
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setLocaleLocked(locale);
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (config.language[0] != 0) {
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        char spec[9];
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        spec[0] = config.language[0];
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        spec[1] = config.language[1];
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (config.country[0] != 0) {
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            spec[2] = '_';
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            spec[3] = config.country[0];
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            spec[4] = config.country[1];
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            spec[5] = 0;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            spec[3] = 0;
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setLocaleLocked(spec);
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateResourceParamsLocked();
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
40608d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackbornvoid AssetManager::getConfiguration(ResTable_config* outConfig) const
40708d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackborn{
40808d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackborn    AutoMutex _l(mLock);
40908d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackborn    *outConfig = *mConfig;
41008d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackborn}
41108d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackborn
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open an asset.
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The data could be;
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  - In a file on disk (assetBase + fileName).
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  - In a compressed file on disk (assetBase + fileName.gz).
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  - In a Zip archive, uncompressed or compressed.
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * It can be in a number of different directories and Zip archives.
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The search order is:
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  - [appname]
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    - locale + vendor
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    - "default" + vendor
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    - locale + "default"
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    - "default + "default"
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  - "common"
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    - (same as above)
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * To find a particular file, we have to try up to eight paths with
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * all three forms of data.
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We should probably reject requests for "illegal" filenames, e.g. those
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with illegal characters or "../" backward relative paths.
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::open(const char* fileName, AccessMode mode)
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCacheMode != CACHE_OFF && !mCacheValid)
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        loadFileNameCacheLocked();
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 assetName(kAssetsRoot);
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assetName.appendPath(fileName);
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For each top-level asset path, search for the asset.
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t i = mAssetPaths.size();
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (i > 0) {
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i--;
45671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Looking for asset '%s' in '%s'\n",
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                assetName.string(), mAssetPaths.itemAt(i).path.string());
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Asset* pAsset = openNonAssetInPathLocked(assetName.string(), mode, mAssetPaths.itemAt(i));
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset != NULL) {
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return pAsset != kExcludedAsset ? pAsset : NULL;
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NULL;
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open a non-asset file as if it were an asset.
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The "fileName" is the partial path starting from the application
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * name.
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openNonAsset(const char* fileName, AccessMode mode)
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCacheMode != CACHE_OFF && !mCacheValid)
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        loadFileNameCacheLocked();
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For each top-level asset path, search for the asset.
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t i = mAssetPaths.size();
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (i > 0) {
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i--;
49071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Looking for non-asset '%s' in '%s'\n", fileName, mAssetPaths.itemAt(i).path.string());
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Asset* pAsset = openNonAssetInPathLocked(
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fileName, mode, mAssetPaths.itemAt(i));
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset != NULL) {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return pAsset != kExcludedAsset ? pAsset : NULL;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NULL;
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
501745d4efc8369d255341d810790132660e33d3b61Narayan KamathAsset* AssetManager::openNonAsset(const int32_t cookie, const char* fileName, AccessMode mode)
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
503745d4efc8369d255341d810790132660e33d3b61Narayan Kamath    const size_t which = static_cast<size_t>(cookie) - 1;
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCacheMode != CACHE_OFF && !mCacheValid)
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        loadFileNameCacheLocked();
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (which < mAssetPaths.size()) {
51371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Looking for non-asset '%s' in '%s'\n", fileName,
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mAssetPaths.itemAt(which).path.string());
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Asset* pAsset = openNonAssetInPathLocked(
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fileName, mode, mAssetPaths.itemAt(which));
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset != NULL) {
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return pAsset != kExcludedAsset ? pAsset : NULL;
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NULL;
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the type of a file in the asset namespace.
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This currently only works for regular files.  All others (including
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * directories) will return kFileTypeNonexistent.
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectFileType AssetManager::getFileType(const char* fileName)
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* pAsset = NULL;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Open the asset.  This is less efficient than simply finding the
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * file, but it's not too bad (we don't uncompress or mmap data until
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the first read() call).
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = open(fileName, Asset::ACCESS_STREAMING);
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete pAsset;
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pAsset == NULL)
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return kFileTypeNonexistent;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return kFileTypeRegular;
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst ResTable* AssetManager::getResTable(bool required) const
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResTable* rt = mResources;
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (rt) {
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return rt;
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Iterate through all asset packages, collecting resources from each.
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mResources != NULL) {
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mResources;
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (required) {
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCacheMode != CACHE_OFF && !mCacheValid)
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const_cast<AssetManager*>(this)->loadFileNameCacheLocked();
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t N = mAssetPaths.size();
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<N; i++) {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Asset* ass = NULL;
57478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        ResTable* sharedRes = NULL;
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool shared = true;
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const asset_path& ap = mAssetPaths.itemAt(i);
577f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn        MY_TRACE_BEGIN(ap.path.string());
57857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        Asset* idmap = openIdmapLocked(ap);
57971f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Looking for resource asset in '%s'\n", ap.path.string());
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ap.type != kFileTypeDirectory) {
58178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            if (i == 0) {
58278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                // The first item is typically the framework resources,
58378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                // which we want to avoid parsing every time.
58478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                sharedRes = const_cast<AssetManager*>(this)->
58578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    mZipSet.getZipResourceTable(ap.path);
58648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                if (sharedRes != NULL) {
58748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                    // skip ahead the number of system overlay packages preloaded
58848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                    i += sharedRes->getTableCount() - 1;
58948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                }
59078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            }
59178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            if (sharedRes == NULL) {
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ass = const_cast<AssetManager*>(this)->
59378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    mZipSet.getZipResourceTableAsset(ap.path);
59478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                if (ass == NULL) {
59571f2cf116aab893e224056c38ab146bd1538dd3eSteve Block                    ALOGV("loading resource table %s\n", ap.path.string());
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ass = const_cast<AssetManager*>(this)->
59778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                        openNonAssetInPathLocked("resources.arsc",
59878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                                                 Asset::ACCESS_BUFFER,
59978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                                                 ap);
60078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    if (ass != NULL && ass != kExcludedAsset) {
60178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                        ass = const_cast<AssetManager*>(this)->
60278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                            mZipSet.setZipResourceTableAsset(ap.path, ass);
60378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    }
60478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                }
605c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
60678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                if (i == 0 && ass != NULL) {
60778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    // If this is the first resource table in the asset
60878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    // manager, then we are going to cache it so that we
60978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    // can quickly copy it out for others.
61071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block                    ALOGV("Creating shared resources for %s", ap.path.string());
61178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    sharedRes = new ResTable();
6127c4887f66bfa3dad16f8b03dc825ade96d7de130Narayan Kamath                    sharedRes->add(ass, i + 1, false, idmap);
61348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#ifdef HAVE_ANDROID_OS
61448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                    const char* data = getenv("ANDROID_DATA");
61548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                    LOG_ALWAYS_FATAL_IF(data == NULL, "ANDROID_DATA not set");
61648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                    String8 overlaysListPath(data);
61748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                    overlaysListPath.appendPath(kResourceCache);
61848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                    overlaysListPath.appendPath("overlays.list");
61948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                    addSystemOverlays(overlaysListPath.string(), ap.path, sharedRes, i);
62048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad#endif
62178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    sharedRes = const_cast<AssetManager*>(this)->
62278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                        mZipSet.setZipResourceTable(ap.path, sharedRes);
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
62671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("loading resource table %s\n", ap.path.string());
627c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes            ass = const_cast<AssetManager*>(this)->
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                openNonAssetInPathLocked("resources.arsc",
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                         Asset::ACCESS_BUFFER,
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                         ap);
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            shared = false;
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
63378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        if ((ass != NULL || sharedRes != NULL) && ass != kExcludedAsset) {
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (rt == NULL) {
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mResources = rt = new ResTable();
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updateResourceParamsLocked();
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
63871f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("Installing resource asset %p in to table %p\n", ass, mResources);
63978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            if (sharedRes != NULL) {
64071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block                ALOGV("Copying existing resources for %s", ap.path.string());
64178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                rt->add(sharedRes);
64278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            } else {
64371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block                ALOGV("Parsing resources for %s", ap.path.string());
6447c4887f66bfa3dad16f8b03dc825ade96d7de130Narayan Kamath                rt->add(ass, i + 1, !shared, idmap);
64578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            }
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!shared) {
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delete ass;
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6512b91c67137dfcdfc3f418e13ad63cef68f5247acMårten Kongstad        if (idmap != NULL) {
6522b91c67137dfcdfc3f418e13ad63cef68f5247acMårten Kongstad            delete idmap;
6532b91c67137dfcdfc3f418e13ad63cef68f5247acMårten Kongstad        }
654f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn        MY_TRACE_END();
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6578564c8da817a845353d213acd8636b76f567b234Steve Block    if (required && !rt) ALOGW("Unable to find resources file resources.arsc");
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!rt) {
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mResources = rt = new ResTable();
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return rt;
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::updateResourceParamsLocked() const
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResTable* res = mResources;
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!res) {
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t llen = mLocale ? strlen(mLocale) : 0;
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mConfig->language[0] = 0;
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mConfig->language[1] = 0;
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mConfig->country[0] = 0;
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mConfig->country[1] = 0;
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (llen >= 2) {
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mConfig->language[0] = mLocale[0];
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mConfig->language[1] = mLocale[1];
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (llen >= 5) {
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mConfig->country[0] = mLocale[3];
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mConfig->country[1] = mLocale[4];
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mConfig->size = sizeof(*mConfig);
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    res->setParameters(mConfig);
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
68957f4b77c89bafedf9468f9a636561c0c193405c9Mårten KongstadAsset* AssetManager::openIdmapLocked(const struct asset_path& ap) const
69057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad{
69157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    Asset* ass = NULL;
69257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (ap.idmap.size() != 0) {
69357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        ass = const_cast<AssetManager*>(this)->
69457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            openAssetFromFileLocked(ap.idmap, Asset::ACCESS_BUFFER);
69557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        if (ass) {
69671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("loading idmap %s\n", ap.idmap.string());
69757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        } else {
6988564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("failed to load idmap %s\n", ap.idmap.string());
69957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
70057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
70157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    return ass;
70257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad}
70357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
70448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadvoid AssetManager::addSystemOverlays(const char* pathOverlaysList,
70548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        const String8& targetPackagePath, ResTable* sharedRes, size_t offset) const
70648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad{
70748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    FILE* fin = fopen(pathOverlaysList, "r");
70848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (fin == NULL) {
70948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        return;
71048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    }
71148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad
71248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    char buf[1024];
71348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    while (fgets(buf, sizeof(buf), fin)) {
71448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        // format of each line:
71548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        //   <path to apk><space><path to idmap><newline>
71648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        char* space = strchr(buf, ' ');
71748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        char* newline = strchr(buf, '\n');
71848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        asset_path oap;
71948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad
72048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        if (space == NULL || newline == NULL || newline < space) {
72148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            continue;
72248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        }
72348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad
72448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        oap.path = String8(buf, space - buf);
72548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        oap.type = kFileTypeRegular;
72648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        oap.idmap = String8(space + 1, newline - space - 1);
72748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad
72848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        Asset* oass = const_cast<AssetManager*>(this)->
72948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            openNonAssetInPathLocked("resources.arsc",
73048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                    Asset::ACCESS_BUFFER,
73148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad                    oap);
73248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad
73348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        if (oass != NULL) {
73448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            Asset* oidmap = openIdmapLocked(oap);
73548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            offset++;
73648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            sharedRes->add(oass, offset + 1, false, oidmap);
73748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            const_cast<AssetManager*>(this)->mAssetPaths.add(oap);
73848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad            const_cast<AssetManager*>(this)->mZipSet.addOverlay(targetPackagePath, oap);
73948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        }
74048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    }
74148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    fclose(fin);
74248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad}
74348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst ResTable& AssetManager::getResources(bool required) const
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const ResTable* rt = getResTable(required);
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return *rt;
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::isUpToDate()
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mZipSet.isUpToDate();
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::getLocales(Vector<String8>* locales) const
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResTable* res = mResources;
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (res != NULL) {
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        res->getLocales(locales);
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open a non-asset file as if it were an asset, searching for it in the
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified app.
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pass in a NULL values for "appName" if the common app directory should
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be used.
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode mode,
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const asset_path& ap)
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* pAsset = NULL;
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* look at the filesystem on disk */
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ap.type == kFileTypeDirectory) {
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String8 path(ap.path);
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path.appendPath(fileName);
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = openAssetFromFileLocked(path, mode);
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset == NULL) {
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* try again, this time with ".gz" */
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            path.append(".gz");
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pAsset = openAssetFromFileLocked(path, mode);
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset != NULL) {
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //printf("FOUND NA '%s' on disk\n", fileName);
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pAsset->setAssetSource(path);
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* look inside the zip file */
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String8 path(fileName);
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* check the appropriate Zip file */
799afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        ZipFileRO* pZip = getZipFileLocked(ap);
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pZip != NULL) {
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //printf("GOT zip, checking NA '%s'\n", (const char*) path);
802afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath            ZipEntryRO entry = pZip->findEntryByName(path.string());
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (entry != NULL) {
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("FOUND NA in Zip file for %s\n", appName ? appName : kAppCommon);
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pAsset = openAssetFromZipLocked(pZip, entry, mode, path);
806afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath                pZip->releaseEntry(entry);
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset != NULL) {
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* create a "source" name, for debug/display */
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pAsset->setAssetSource(
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    createZipSourceNameLocked(ZipSet::getPathName(ap.path.string()), String8(""),
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                String8(fileName)));
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open an asset, searching for it in the directory hierarchy for the
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified app.
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pass in a NULL values for "appName" if the common app directory should
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be used.
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openInPathLocked(const char* fileName, AccessMode mode,
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const asset_path& ap)
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* pAsset = NULL;
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Try various combinations of locale and vendor.
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mLocale != NULL && mVendor != NULL)
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = openInLocaleVendorLocked(fileName, mode, ap, mLocale, mVendor);
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pAsset == NULL && mVendor != NULL)
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = openInLocaleVendorLocked(fileName, mode, ap, NULL, mVendor);
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pAsset == NULL && mLocale != NULL)
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = openInLocaleVendorLocked(fileName, mode, ap, mLocale, NULL);
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pAsset == NULL)
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = openInLocaleVendorLocked(fileName, mode, ap, NULL, NULL);
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open an asset, searching for it in the directory hierarchy for the
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified locale and vendor.
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We also search in "app.jar".
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pass in NULL values for "appName", "locale", and "vendor" if the
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * defaults should be used.
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openInLocaleVendorLocked(const char* fileName, AccessMode mode,
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const asset_path& ap, const char* locale, const char* vendor)
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* pAsset = NULL;
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ap.type == kFileTypeDirectory) {
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCacheMode == CACHE_OFF) {
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* look at the filesystem on disk */
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 path(createPathNameLocked(ap, locale, vendor));
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            path.appendPath(fileName);
867c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 excludeName(path);
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            excludeName.append(kExcludeExtension);
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (::getFileType(excludeName.string()) != kFileTypeNonexistent) {
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* say no more */
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("+++ excluding '%s'\n", (const char*) excludeName);
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return kExcludedAsset;
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
875c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pAsset = openAssetFromFileLocked(path, mode);
877c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pAsset == NULL) {
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* try again, this time with ".gz" */
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                path.append(".gz");
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pAsset = openAssetFromFileLocked(path, mode);
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
883c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pAsset != NULL)
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pAsset->setAssetSource(path);
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* find in cache */
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 path(createPathNameLocked(ap, locale, vendor));
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            path.appendPath(fileName);
890c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            AssetDir::FileInfo tmpInfo;
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool found = false;
893c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 excludeName(path);
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            excludeName.append(kExcludeExtension);
896c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCache.indexOf(excludeName) != NAME_NOT_FOUND) {
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* go no farther */
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("+++ Excluding '%s'\n", (const char*) excludeName);
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return kExcludedAsset;
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * File compression extensions (".gz") don't get stored in the
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * name cache, so we have to try both here.
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCache.indexOf(path) != NAME_NOT_FOUND) {
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                found = true;
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pAsset = openAssetFromFileLocked(path, mode);
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (pAsset == NULL) {
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    /* try again, this time with ".gz" */
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    path.append(".gz");
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pAsset = openAssetFromFileLocked(path, mode);
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pAsset != NULL)
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pAsset->setAssetSource(path);
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Don't continue the search into the Zip files.  Our cached info
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * said it was a file on disk; to be consistent with openDir()
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * we want to return the loose asset.  If the cached file gets
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * removed, we fail.
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             *
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * The alternative is to update our cache when files get deleted,
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * or make some sort of "best effort" promise, but for now I'm
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * taking the hard line.
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (found) {
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (pAsset == NULL)
9325baa3a62a97544669fba6d65a11c07f252e654ddSteve Block                    ALOGD("Expected file not found: '%s'\n", path.string());
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return pAsset;
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Either it wasn't found on disk or on the cached view of the disk.
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Dig through the currently-opened set of Zip files.  If caching
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is disabled, the Zip file may get reopened.
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pAsset == NULL && ap.type == kFileTypeRegular) {
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String8 path;
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path.appendPath((locale != NULL) ? locale : kDefaultLocale);
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path.appendPath((vendor != NULL) ? vendor : kDefaultVendor);
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path.appendPath(fileName);
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* check the appropriate Zip file */
951afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        ZipFileRO* pZip = getZipFileLocked(ap);
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pZip != NULL) {
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //printf("GOT zip, checking '%s'\n", (const char*) path);
954afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath            ZipEntryRO entry = pZip->findEntryByName(path.string());
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (entry != NULL) {
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("FOUND in Zip file for %s/%s-%s\n",
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //    appName, locale, vendor);
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pAsset = openAssetFromZipLocked(pZip, entry, mode, path);
959afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath                pZip->releaseEntry(entry);
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset != NULL) {
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* create a "source" name, for debug/display */
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pAsset->setAssetSource(createZipSourceNameLocked(ZipSet::getPathName(ap.path.string()),
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                             String8(""), String8(fileName)));
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a "source name" for a file from a Zip archive.
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectString8 AssetManager::createZipSourceNameLocked(const String8& zipFileName,
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const String8& dirName, const String8& fileName)
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 sourceName("zip:");
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sourceName.append(zipFileName);
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sourceName.append(":");
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (dirName.length() > 0) {
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sourceName.appendPath(dirName);
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sourceName.appendPath(fileName);
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return sourceName;
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a path to a loose asset (asset-base/app/locale/vendor).
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectString8 AssetManager::createPathNameLocked(const asset_path& ap, const char* locale,
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* vendor)
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 path(ap.path);
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    path.appendPath((locale != NULL) ? locale : kDefaultLocale);
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    path.appendPath((vendor != NULL) ? vendor : kDefaultVendor);
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return path;
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a path to a loose asset (asset-base/app/rootDir).
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectString8 AssetManager::createPathNameLocked(const asset_path& ap, const char* rootDir)
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 path(ap.path);
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (rootDir != NULL) path.appendPath(rootDir);
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return path;
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return a pointer to one of our open Zip archives.  Returns NULL if no
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * matching Zip file exists.
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Right now we have 2 possible Zip files (1 each in app/"common").
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If caching is set to CACHE_OFF, to get the expected behavior we
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * need to reopen the Zip file on every request.  That would be silly
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and expensive, so instead we just check the file modification date.
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pass in NULL values for "appName", "locale", and "vendor" if the
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * generics should be used.
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectZipFileRO* AssetManager::getZipFileLocked(const asset_path& ap)
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
102671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("getZipFileLocked() in %p\n", this);
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mZipSet.getZip(ap.path);
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Try to open an asset from a file on disk.
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If the file is compressed with gzip, we seek to the start of the
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * deflated data and pass that in (just like we would for a Zip archive).
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For uncompressed data, we may already have an mmap()ed version sitting
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * around.  If so, we want to hand that to the Asset instead.
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This returns NULL if the file doesn't exist, couldn't be opened, or
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * claims to be a ".gz" but isn't.
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openAssetFromFileLocked(const String8& pathName,
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AccessMode mode)
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* pAsset = NULL;
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (strcasecmp(pathName.getPathExtension().string(), ".gz") == 0) {
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //printf("TRYING '%s'\n", (const char*) pathName);
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = Asset::createFromCompressedFile(pathName.string(), mode);
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //printf("TRYING '%s'\n", (const char*) pathName);
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = Asset::createFromFile(pathName.string(), mode);
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Given an entry in a Zip archive, create a new Asset object.
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If the entry is uncompressed, we may want to create or share a
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * slice of shared memory.
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openAssetFromZipLocked(const ZipFileRO* pZipFile,
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const ZipEntryRO entry, AccessMode mode, const String8& entryName)
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* pAsset = NULL;
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // TODO: look for previously-created shared memory slice?
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int method;
107268246dcec17c245a434dad70b778960dc5c84af1Kenny Root    size_t uncompressedLen;
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //printf("USING Zip '%s'\n", pEntry->getFileName());
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //pZipFile->getEntryInfo(entry, &method, &uncompressedLen, &compressedLen,
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    &offset);
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!pZipFile->getEntryInfo(entry, &method, &uncompressedLen, NULL, NULL,
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NULL, NULL))
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
10818564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("getEntryInfo failed\n");
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FileMap* dataMap = pZipFile->createEntryFileMap(entry);
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (dataMap == NULL) {
10878564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("create map from entry failed\n");
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (method == ZipFileRO::kCompressStored) {
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = Asset::createFromUncompressedMap(dataMap, mode);
109371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Opened uncompressed entry %s in zip %s mode %d: %p", entryName.string(),
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dataMap->getFileName(), mode, pAsset);
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = Asset::createFromCompressedMap(dataMap, method,
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            uncompressedLen, mode);
109871f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Opened compressed entry %s in zip %s mode %d: %p", entryName.string(),
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dataMap->getFileName(), mode, pAsset);
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pAsset == NULL) {
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* unexpected */
11038564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("create from segment failed\n");
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open a directory in the asset namespace.
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An "asset directory" is simply the combination of all files in all
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * locations, with ".gz" stripped for loose files.  With app, locale, and
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * vendor defined, we have 8 directories and 2 Zip archives to scan.
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pass in "" for the root dir.
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetDir* AssetManager::openDir(const char* dirName)
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AssetDir* pDir = NULL;
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo>* pMergedInfo = NULL;
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(dirName != NULL);
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //printf("+++ openDir(%s) in '%s'\n", dirName, (const char*) mAssetBase);
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCacheMode != CACHE_OFF && !mCacheValid)
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        loadFileNameCacheLocked();
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pDir = new AssetDir;
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Scan the various directories, merging what we find into a single
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * vector.  We want to scan them in reverse priority order so that
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the ".EXCLUDE" processing works correctly.  Also, if we decide we
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * want to remember where the file is coming from, we'll get the right
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * version.
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * We start with Zip archives, then do loose files.
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pMergedInfo = new SortedVector<AssetDir::FileInfo>;
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t i = mAssetPaths.size();
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (i > 0) {
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i--;
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const asset_path& ap = mAssetPaths.itemAt(i);
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ap.type == kFileTypeRegular) {
115371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("Adding directory %s from zip %s", dirName, ap.path.string());
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            scanAndMergeZipLocked(pMergedInfo, ap, kAssetsRoot, dirName);
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
115671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("Adding directory %s from dir %s", dirName, ap.path.string());
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            scanAndMergeDirLocked(pMergedInfo, ap, kAssetsRoot, dirName);
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    printf("FILE LIST:\n");
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = 0; i < (size_t) pMergedInfo->size(); i++) {
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf(" %d: (%d) '%s'\n", i,
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pMergedInfo->itemAt(i).getFileType(),
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (const char*) pMergedInfo->itemAt(i).getFileName());
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pDir->setFileList(pMergedInfo);
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pDir;
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1175bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn * Open a directory in the non-asset namespace.
1176bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn *
1177bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn * An "asset directory" is simply the combination of all files in all
1178bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn * locations, with ".gz" stripped for loose files.  With app, locale, and
1179bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn * vendor defined, we have 8 directories and 2 Zip archives to scan.
1180bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn *
1181bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn * Pass in "" for the root dir.
1182bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn */
1183745d4efc8369d255341d810790132660e33d3b61Narayan KamathAssetDir* AssetManager::openNonAssetDir(const int32_t cookie, const char* dirName)
1184bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn{
1185bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    AutoMutex _l(mLock);
1186bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1187bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    AssetDir* pDir = NULL;
1188bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    SortedVector<AssetDir::FileInfo>* pMergedInfo = NULL;
1189bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1190bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
1191bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    assert(dirName != NULL);
1192bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1193bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    //printf("+++ openDir(%s) in '%s'\n", dirName, (const char*) mAssetBase);
1194bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1195bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    if (mCacheMode != CACHE_OFF && !mCacheValid)
1196bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        loadFileNameCacheLocked();
1197bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1198bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    pDir = new AssetDir;
1199bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1200bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    pMergedInfo = new SortedVector<AssetDir::FileInfo>;
1201bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1202745d4efc8369d255341d810790132660e33d3b61Narayan Kamath    const size_t which = static_cast<size_t>(cookie) - 1;
1203bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1204bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    if (which < mAssetPaths.size()) {
1205bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        const asset_path& ap = mAssetPaths.itemAt(which);
1206bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        if (ap.type == kFileTypeRegular) {
120771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("Adding directory %s from zip %s", dirName, ap.path.string());
1208bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            scanAndMergeZipLocked(pMergedInfo, ap, NULL, dirName);
1209bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        } else {
121071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("Adding directory %s from dir %s", dirName, ap.path.string());
1211bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            scanAndMergeDirLocked(pMergedInfo, ap, NULL, dirName);
1212bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        }
1213bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    }
1214bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1215bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn#if 0
1216bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    printf("FILE LIST:\n");
1217bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    for (i = 0; i < (size_t) pMergedInfo->size(); i++) {
1218bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        printf(" %d: (%d) '%s'\n", i,
1219bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            pMergedInfo->itemAt(i).getFileType(),
1220bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            (const char*) pMergedInfo->itemAt(i).getFileName());
1221bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    }
1222bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn#endif
1223bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1224bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    pDir->setFileList(pMergedInfo);
1225bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    return pDir;
1226bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn}
1227bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1228bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn/*
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scan the contents of the specified directory and merge them into the
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "pMergedInfo" vector, removing previous entries if we find "exclude"
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * directives.
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns "false" if we found nothing to contribute.
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::scanAndMergeDirLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const asset_path& ap, const char* rootDir, const char* dirName)
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo>* pContents;
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 path;
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(pMergedInfo != NULL);
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //printf("scanAndMergeDir: %s %s %s %s\n", appName, locale, vendor,dirName);
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCacheValid) {
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int i, start, count;
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pContents = new SortedVector<AssetDir::FileInfo>;
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Get the basic partial path and find it in the cache.  That's
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the start point for the search.
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path = createPathNameLocked(ap, rootDir);
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dirName[0] != '\0')
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            path.appendPath(dirName);
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        start = mCache.indexOf(path);
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (start == NAME_NOT_FOUND) {
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //printf("+++ not found in cache: dir '%s'\n", (const char*) path);
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            delete pContents;
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * The match string looks like "common/default/default/foo/bar/".
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * The '/' on the end ensures that we don't match on the directory
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * itself or on ".../foo/barfy/".
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path.append("/");
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        count = mCache.size();
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Pick out the stuff in the current dir by examining the pathname.
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * It needs to match the partial pathname prefix, and not have a '/'
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * (fssep) anywhere after the prefix.
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (i = start+1; i < count; i++) {
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCache[i].getFileName().length() > path.length() &&
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                strncmp(mCache[i].getFileName().string(), path.string(), path.length()) == 0)
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            {
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const char* name = mCache[i].getFileName().string();
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // XXX THIS IS BROKEN!  Looks like we need to store the full
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // path prefix separately from the file path.
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (strchr(name + path.length(), '/') == NULL) {
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    /* grab it, reducing path to just the filename component */
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    AssetDir::FileInfo tmp = mCache[i];
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    tmp.setFileName(tmp.getFileName().getPathLeaf());
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pContents->add(tmp);
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* no longer in the dir or its subdirs */
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path = createPathNameLocked(ap, rootDir);
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dirName[0] != '\0')
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            path.appendPath(dirName);
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pContents = scanDirLocked(path);
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pContents == NULL)
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // if we wanted to do an incremental cache fill, we would do it here
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Process "exclude" directives.  If we find a filename that ends with
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * ".EXCLUDE", we look for a matching entry in the "merged" set, and
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * remove it if we find it.  We also delete the "exclude" entry.
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int i, count, exclExtLen;
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    count = pContents->size();
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    exclExtLen = strlen(kExcludeExtension);
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = 0; i < count; i++) {
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* name;
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int nameLen;
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        name = pContents->itemAt(i).getFileName().string();
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nameLen = strlen(name);
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (nameLen > exclExtLen &&
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            strcmp(name + (nameLen - exclExtLen), kExcludeExtension) == 0)
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 match(name, nameLen - exclExtLen);
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int matchIdx;
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            matchIdx = AssetDir::FileInfo::findEntry(pMergedInfo, match);
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (matchIdx > 0) {
133271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block                ALOGV("Excluding '%s' [%s]\n",
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pMergedInfo->itemAt(matchIdx).getFileName().string(),
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pMergedInfo->itemAt(matchIdx).getSourceName().string());
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pMergedInfo->removeAt(matchIdx);
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("+++ no match on '%s'\n", (const char*) match);
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13405baa3a62a97544669fba6d65a11c07f252e654ddSteve Block            ALOGD("HEY: size=%d removing %d\n", (int)pContents->size(), i);
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pContents->removeAt(i);
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            i--;        // adjust "for" loop
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            count--;    //  and loop limit
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mergeInfoLocked(pMergedInfo, pContents);
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete pContents;
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scan the contents of the specified directory, and stuff what we find
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * into a newly-allocated vector.
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Files ending in ".gz" will have their extensions removed.
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We should probably think about skipping files with "illegal" names,
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * e.g. illegal characters (/\:) or excessive length.
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns NULL if the specified directory doesn't exist.
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectSortedVector<AssetDir::FileInfo>* AssetManager::scanDirLocked(const String8& path)
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo>* pContents = NULL;
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    DIR* dir;
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct dirent* entry;
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FileType fileType;
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
137271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("Scanning dir '%s'\n", path.string());
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dir = opendir(path.string());
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (dir == NULL)
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pContents = new SortedVector<AssetDir::FileInfo>;
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (1) {
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        entry = readdir(dir);
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (entry == NULL)
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (strcmp(entry->d_name, ".") == 0 ||
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            strcmp(entry->d_name, "..") == 0)
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef _DIRENT_HAVE_D_TYPE
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (entry->d_type == DT_REG)
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fileType = kFileTypeRegular;
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else if (entry->d_type == DT_DIR)
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fileType = kFileTypeDirectory;
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fileType = kFileTypeUnknown;
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // stat the file
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fileType = ::getFileType(path.appendPathCopy(entry->d_name).string());
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fileType != kFileTypeRegular && fileType != kFileTypeDirectory)
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AssetDir::FileInfo info;
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        info.set(String8(entry->d_name), fileType);
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (strcasecmp(info.getFileName().getPathExtension().string(), ".gz") == 0)
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            info.setFileName(info.getFileName().getBasePath());
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        info.setSourceName(path.appendPathCopy(info.getFileName()));
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pContents->add(info);
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    closedir(dir);
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pContents;
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scan the contents out of the specified Zip archive, and merge what we
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * find into "pMergedInfo".  If the Zip archive in question doesn't exist,
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * we return immediately.
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns "false" if we found nothing to contribute.
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const asset_path& ap, const char* rootDir, const char* baseDirName)
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFileRO* pZip;
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Vector<String8> dirs;
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AssetDir::FileInfo info;
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo> contents;
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 sourceName, zipName, dirName;
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pZip = mZipSet.getZip(ap.path);
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pZip == NULL) {
14348564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("Failure opening zip %s\n", ap.path.string());
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zipName = ZipSet::getPathName(ap.path.string());
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* convert "sounds" to "rootDir/sounds" */
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (rootDir != NULL) dirName = rootDir;
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dirName.appendPath(baseDirName);
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Scan through the list of files, looking for a match.  The files in
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the Zip table of contents are not in sorted order, so we have to
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * process the entire list.  We're looking for a string that begins
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with the characters in "dirName", is followed by a '/', and has no
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * subsequent '/' in the stuff that follows.
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * What makes this especially fun is that directories are not stored
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * explicitly in Zip archives, so we have to infer them from context.
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * When we see "sounds/foo.wav" we have to leave a note to ourselves
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to insert a directory called "sounds" into the list.  We store
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * these in temporary vector so that we only return each one once.
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Name comparisons are case-sensitive to match UNIX filesystem
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * semantics.
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int dirNameLen = dirName.length();
1461afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    void *iterationCookie;
1462afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (!pZip->startIteration(&iterationCookie)) {
1463afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        ALOGW("ZipFileRO::startIteration returned false");
1464afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        return false;
1465afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    }
1466afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath
1467afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    ZipEntryRO entry;
1468afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    while ((entry = pZip->nextEntry(iterationCookie)) != NULL) {
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        char nameBuf[256];
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pZip->getEntryFileName(entry, nameBuf, sizeof(nameBuf)) != 0) {
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // TODO: fix this if we expect to have long names
14733762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("ARGH: name too long?\n");
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1476bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        //printf("Comparing %s in %s?\n", nameBuf, dirName.string());
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dirNameLen == 0 ||
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (strncmp(nameBuf, dirName.string(), dirNameLen) == 0 &&
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             nameBuf[dirNameLen] == '/'))
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const char* cp;
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const char* nextSlash;
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cp = nameBuf + dirNameLen;
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (dirNameLen != 0)
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cp++;       // advance past the '/'
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            nextSlash = strchr(cp, '/');
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//xxx this may break if there are bare directory entries
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (nextSlash == NULL) {
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* this is a file in the requested directory */
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.set(String8(nameBuf).getPathLeaf(), kFileTypeRegular);
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.setSourceName(
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    createZipSourceNameLocked(zipName, dirName, info.getFileName()));
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                contents.add(info);
1499bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                //printf("FOUND: file '%s'\n", info.getFileName().string());
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* this is a subdir; add it if we don't already have it*/
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8 subdirName(cp, nextSlash - cp);
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                size_t j;
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                size_t N = dirs.size();
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (j = 0; j < N; j++) {
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (subdirName == dirs[j]) {
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (j == N) {
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    dirs.add(subdirName);
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1515bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                //printf("FOUND: dir '%s'\n", subdirName.string());
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1520afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    pZip->endIteration(iterationCookie);
1521afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Add the set of unique directories.
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < (int) dirs.size(); i++) {
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        info.set(dirs[i], kFileTypeDirectory);
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        info.setSourceName(
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            createZipSourceNameLocked(zipName, dirName, info.getFileName()));
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        contents.add(info);
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mergeInfoLocked(pMergedInfo, &contents);
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Merge two vectors of FileInfo.
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The merged contents will be stuffed into *pMergedInfo.
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If an entry for a file exists in both "pMergedInfo" and "pContents",
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * we use the newer "pContents" entry.
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::mergeInfoLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const SortedVector<AssetDir::FileInfo>* pContents)
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Merge what we found in this directory with what we found in
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * other places.
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Two basic approaches:
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (1) Create a new array that holds the unique values of the two
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     arrays.
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (2) Take the elements from pContents and shove them into pMergedInfo.
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Because these are vectors of complex objects, moving elements around
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * inside the vector requires constructing new objects and allocating
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * storage for members.  With approach #1, we're always adding to the
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * end, whereas with #2 we could be inserting multiple elements at the
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * front of the vector.  Approach #1 requires a full copy of the
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * contents of pMergedInfo, but approach #2 requires the same copy for
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * every insertion at the front of pMergedInfo.
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (We should probably use a SortedVector interface that allows us to
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * just stuff items in, trusting us to maintain the sort order.)
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo>* pNewSorted;
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mergeMax, contMax;
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mergeIdx, contIdx;
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pNewSorted = new SortedVector<AssetDir::FileInfo>;
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mergeMax = pMergedInfo->size();
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    contMax = pContents->size();
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mergeIdx = contIdx = 0;
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (mergeIdx < mergeMax || contIdx < contMax) {
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mergeIdx == mergeMax) {
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* hit end of "merge" list, copy rest of "contents" */
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pNewSorted->add(pContents->itemAt(contIdx));
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            contIdx++;
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (contIdx == contMax) {
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* hit end of "cont" list, copy rest of "merge" */
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pNewSorted->add(pMergedInfo->itemAt(mergeIdx));
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mergeIdx++;
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (pMergedInfo->itemAt(mergeIdx) == pContents->itemAt(contIdx))
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* items are identical, add newer and advance both indices */
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pNewSorted->add(pContents->itemAt(contIdx));
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mergeIdx++;
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            contIdx++;
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (pMergedInfo->itemAt(mergeIdx) < pContents->itemAt(contIdx))
15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* "merge" is lower, add that one */
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pNewSorted->add(pMergedInfo->itemAt(mergeIdx));
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mergeIdx++;
15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* "cont" is lower, add that one */
16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            assert(pContents->itemAt(contIdx) < pMergedInfo->itemAt(mergeIdx));
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pNewSorted->add(pContents->itemAt(contIdx));
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            contIdx++;
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Overwrite the "merged" list with the new stuff.
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *pMergedInfo = *pNewSorted;
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete pNewSorted;
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0       // for Vector, rather than SortedVector
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int i, j;
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = pContents->size() -1; i >= 0; i--) {
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool add = true;
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (j = pMergedInfo->size() -1; j >= 0; j--) {
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* case-sensitive comparisons, to behave like UNIX fs */
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (strcmp(pContents->itemAt(i).mFileName,
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       pMergedInfo->itemAt(j).mFileName) == 0)
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            {
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* match, don't add this entry */
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                add = false;
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (add)
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pMergedInfo->add(pContents->itemAt(i));
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Load all files into the file name cache.  We want to do this across
16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * all combinations of { appname, locale, vendor }, performing a recursive
16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * directory traversal.
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is not the most efficient data structure.  Also, gathering the
16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * information as we needed it (file-by-file or directory-by-directory)
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * would be faster.  However, on the actual device, 99% of the files will
16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * live in Zip archives, so this list will be very small.  The trouble
16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is that we have to check the "loose" files first, so it's important
16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that we don't beat the filesystem silly looking for files that aren't
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * there.
16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note on thread safety: this is the only function that causes updates
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to mCache, and anybody who tries to use it will call here if !mCacheValid,
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * so we need to employ a mutex here.
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::loadFileNameCacheLocked(void)
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(!mCacheValid);
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mCache.size() == 0);
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef DO_TIMINGS   // need to link against -lrt for this now
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    DurationTimer timer;
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    timer.start();
16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fncScanLocked(&mCache, "");
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef DO_TIMINGS
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    timer.stop();
16665baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("Cache scan took %.3fms\n",
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        timer.durationUsecs() / 1000.0);
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int i;
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    printf("CACHED FILE LIST (%d entries):\n", mCache.size());
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = 0; i < (int) mCache.size(); i++) {
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf(" %d: (%d) '%s'\n", i,
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCache.itemAt(i).getFileType(),
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (const char*) mCache.itemAt(i).getFileName());
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCacheValid = true;
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scan up to 8 versions of the specified directory.
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::fncScanLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* dirName)
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t i = mAssetPaths.size();
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (i > 0) {
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i--;
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const asset_path& ap = mAssetPaths.itemAt(i);
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fncScanAndMergeDirLocked(pMergedInfo, ap, NULL, NULL, dirName);
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mLocale != NULL)
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fncScanAndMergeDirLocked(pMergedInfo, ap, mLocale, NULL, dirName);
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mVendor != NULL)
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fncScanAndMergeDirLocked(pMergedInfo, ap, NULL, mVendor, dirName);
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mLocale != NULL && mVendor != NULL)
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fncScanAndMergeDirLocked(pMergedInfo, ap, mLocale, mVendor, dirName);
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Recursively scan this directory and all subdirs.
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is similar to scanAndMergeDir, but we don't remove the .EXCLUDE
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * files, and we prepend the extended partial path to the filenames.
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::fncScanAndMergeDirLocked(
17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo>* pMergedInfo,
17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const asset_path& ap, const char* locale, const char* vendor,
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* dirName)
17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo>* pContents;
17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 partialPath;
17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 fullPath;
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // XXX This is broken -- the filename cache needs to hold the base
17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // asset path separately from its filename.
1720c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    partialPath = createPathNameLocked(ap, locale, vendor);
17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (dirName[0] != '\0') {
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        partialPath.appendPath(dirName);
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fullPath = partialPath;
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pContents = scanDirLocked(fullPath);
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pContents == NULL) {
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;       // directory did not exist
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Scan all subdirectories of the current dir, merging what we find
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * into "pMergedInfo".
17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < (int) pContents->size(); i++) {
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pContents->itemAt(i).getFileType() == kFileTypeDirectory) {
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 subdir(dirName);
17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            subdir.appendPath(pContents->itemAt(i).getFileName());
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fncScanAndMergeDirLocked(pMergedInfo, ap, locale, vendor, subdir.string());
17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * To be consistent, we want entries for the root directory.  If
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * we're the root, add one now.
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (dirName[0] == '\0') {
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AssetDir::FileInfo tmpInfo;
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmpInfo.set(String8(""), kFileTypeDirectory);
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmpInfo.setSourceName(createPathNameLocked(ap, locale, vendor));
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pContents->add(tmpInfo);
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * We want to prepend the extended partial path to every entry in
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "pContents".  It's the same value for each entry, so this will
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not change the sorting order of the vector contents.
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < (int) pContents->size(); i++) {
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const AssetDir::FileInfo& info = pContents->itemAt(i);
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pContents->editItemAt(i).setFileName(partialPath.appendPathCopy(info.getFileName()));
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mergeInfoLocked(pMergedInfo, pContents);
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Trash the cache.
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::purgeFileNameCacheLocked(void)
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCacheValid = false;
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCache.clear();
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      AssetManager::SharedZip
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectMutex AssetManager::SharedZip::gLock;
17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectDefaultKeyedVector<String8, wp<AssetManager::SharedZip> > AssetManager::SharedZip::gOpen;
17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetManager::SharedZip::SharedZip(const String8& path, time_t modWhen)
179178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    : mPath(path), mZipFile(NULL), mModWhen(modWhen),
179278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn      mResourceTableAsset(NULL), mResourceTable(NULL)
17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
17946215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block    //ALOGI("Creating SharedZip %p %s\n", this, (const char*)mPath);
179571f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("+++ opening zip '%s'\n", mPath.string());
1796afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    mZipFile = ZipFileRO::open(mPath.string());
1797afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (mZipFile == NULL) {
17985baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("failed to open Zip archive '%s'\n", mPath.string());
17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
180248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadsp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path,
180348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        bool createIfNotPresent)
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(gLock);
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    time_t modWhen = getFileModDate(path);
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<SharedZip> zip = gOpen.valueFor(path).promote();
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip != NULL && zip->mModWhen == modWhen) {
18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return zip;
18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
181148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (zip == NULL && !createIfNotPresent) {
181248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        return NULL;
181348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    }
18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = new SharedZip(path, modWhen);
18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    gOpen.add(path, zip);
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return zip;
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectZipFileRO* AssetManager::SharedZip::getZip()
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mZipFile;
18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::SharedZip::getResourceTableAsset()
18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
182771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("Getting from SharedZip %p resource asset %p\n", this, mResourceTableAsset);
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mResourceTableAsset;
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::SharedZip::setResourceTableAsset(Asset* asset)
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AutoMutex _l(gLock);
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mResourceTableAsset == NULL) {
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mResourceTableAsset = asset;
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This is not thread safe the first time it is called, so
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // do it here with the global lock held.
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset->getBuffer(true);
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return asset;
18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete asset;
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mResourceTableAsset;
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
184778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne HackbornResTable* AssetManager::SharedZip::getResourceTable()
184878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn{
184971f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("Getting from SharedZip %p resource table %p\n", this, mResourceTable);
185078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    return mResourceTable;
185178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn}
185278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn
185378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne HackbornResTable* AssetManager::SharedZip::setResourceTable(ResTable* res)
185478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn{
185578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    {
185678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        AutoMutex _l(gLock);
185778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        if (mResourceTable == NULL) {
185878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            mResourceTable = res;
185978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            return res;
186078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        }
186178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    }
186278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    delete res;
186378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    return mResourceTable;
186478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn}
186578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::SharedZip::isUpToDate()
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    time_t modWhen = getFileModDate(mPath.string());
18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mModWhen == modWhen;
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
187248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadvoid AssetManager::SharedZip::addOverlay(const asset_path& ap)
187348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad{
187448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    mOverlays.add(ap);
187548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad}
187648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad
187748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadbool AssetManager::SharedZip::getOverlay(size_t idx, asset_path* out) const
187848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad{
187948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (idx >= mOverlays.size()) {
188048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        return false;
188148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    }
188248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    *out = mOverlays[idx];
188348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    return true;
188448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad}
188548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetManager::SharedZip::~SharedZip()
18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18886215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block    //ALOGI("Destroying SharedZip %p %s\n", this, (const char*)mPath);
188978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    if (mResourceTable != NULL) {
189078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        delete mResourceTable;
189178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    }
18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mResourceTableAsset != NULL) {
18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete mResourceTableAsset;
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mZipFile != NULL) {
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete mZipFile;
189771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Closed '%s'\n", mPath.string());
18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      AssetManager::ZipSet
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor.
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetManager::ZipSet::ZipSet(void)
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Destructor.  Close any open archives.
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetManager::ZipSet::~ZipSet(void)
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t N = mZipFile.size();
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i = 0; i < N; i++)
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        closeZip(i);
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close a Zip file and reset the entry.
19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::ZipSet::closeZip(int idx)
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mZipFile.editItemAt(idx) = NULL;
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieve the appropriate Zip file from the set.
19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectZipFileRO* AssetManager::ZipSet::getZip(const String8& path)
19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int idx = getIndex(path);
19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<SharedZip> zip = mZipFile[idx];
19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL) {
19419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        zip = SharedZip::get(path);
19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mZipFile.editItemAt(idx) = zip;
19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return zip->getZip();
19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
194778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne HackbornAsset* AssetManager::ZipSet::getZipResourceTableAsset(const String8& path)
19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int idx = getIndex(path);
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<SharedZip> zip = mZipFile[idx];
19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL) {
19529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        zip = SharedZip::get(path);
19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mZipFile.editItemAt(idx) = zip;
19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return zip->getResourceTableAsset();
19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
195878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne HackbornAsset* AssetManager::ZipSet::setZipResourceTableAsset(const String8& path,
19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                 Asset* asset)
19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int idx = getIndex(path);
19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<SharedZip> zip = mZipFile[idx];
19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // doesn't make sense to call before previously accessing.
19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return zip->setResourceTableAsset(asset);
19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
196778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne HackbornResTable* AssetManager::ZipSet::getZipResourceTable(const String8& path)
196878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn{
196978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    int idx = getIndex(path);
197078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    sp<SharedZip> zip = mZipFile[idx];
197178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    if (zip == NULL) {
197278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        zip = SharedZip::get(path);
197378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        mZipFile.editItemAt(idx) = zip;
197478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    }
197578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    return zip->getResourceTable();
197678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn}
197778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn
197878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne HackbornResTable* AssetManager::ZipSet::setZipResourceTable(const String8& path,
197978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                                                    ResTable* res)
198078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn{
198178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    int idx = getIndex(path);
198278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    sp<SharedZip> zip = mZipFile[idx];
198378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    // doesn't make sense to call before previously accessing.
198478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    return zip->setResourceTable(res);
198578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn}
198678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn
19879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
19889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Generate the partial pathname for the specified archive.  The caller
19899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * gets to prepend the asset root directory.
19909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns something like "common/en-US-noogle.jar".
19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*static*/ String8 AssetManager::ZipSet::getPathName(const char* zipPath)
19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return String8(zipPath);
19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::ZipSet::isUpToDate()
19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t N = mZipFile.size();
20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<N; i++) {
20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mZipFile[i] != NULL && !mZipFile[i]->isUpToDate()) {
20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
20079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
20089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
200948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadvoid AssetManager::ZipSet::addOverlay(const String8& path, const asset_path& overlay)
201048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad{
201148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    int idx = getIndex(path);
201248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    sp<SharedZip> zip = mZipFile[idx];
201348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    zip->addOverlay(overlay);
201448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad}
201548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad
201648d22323ce39f9aab003dce74456889b6414af55Mårten Kongstadbool AssetManager::ZipSet::getOverlay(const String8& path, size_t idx, asset_path* out) const
201748d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad{
201848d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    sp<SharedZip> zip = SharedZip::get(path, false);
201948d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    if (zip == NULL) {
202048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad        return false;
202148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    }
202248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    return zip->getOverlay(idx, out);
202348d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad}
202448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad
20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
20269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Compute the zip file's index.
20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "appName", "locale", and "vendor" should be set to NULL to indicate the
20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * default directory.
20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint AssetManager::ZipSet::getIndex(const String8& zip) const
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t N = mZipPath.size();
20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<N; i++) {
20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mZipPath[i] == zip) {
20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return i;
20379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mZipPath.add(zip);
20419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mZipFile.add(NULL);
20429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mZipPath.size()-1;
20449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2045