AssetManager.cpp revision c367d48c55e5a3fa0df14fd62889e4bb6b63cb01
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>
28b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/ResourceTypes.h>
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Atomic.h>
30b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <utils/Log.h>
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String8.h>
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String8.h>
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/threads.h>
34b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <utils/Timers.h>
35a982dc05d7ca919c07f50e446549ef9dceadf6bdColin Cross#include <utils/ZipFileRO.h>
36c51d050f1bc2c393707f7c5e1f6906169ace7497Dianne Hackborn#ifdef HAVE_ANDROID_OS
37f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#include <cutils/trace.h>
38c51d050f1bc2c393707f7c5e1f6906169ace7497Dianne Hackborn#endif
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
40b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <assert.h>
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <dirent.h>
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h>
4357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad#include <fcntl.h>
44b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <strings.h>
4557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad#include <sys/stat.h>
4657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad#include <unistd.h>
4757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
4857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad#ifndef TEMP_FAILURE_RETRY
4957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad/* Used to retry syscalls that can return EINTR. */
5057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad#define TEMP_FAILURE_RETRY(exp) ({         \
5157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    typeof (exp) _rc;                      \
5257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    do {                                   \
5357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        _rc = (exp);                       \
5457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    } while (_rc == -1 && errno == EINTR); \
5557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    _rc; })
5657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad#endif
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
58f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#ifdef HAVE_ANDROID_OS
59f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#define MY_TRACE_BEGIN(x) ATRACE_BEGIN(x)
60f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#define MY_TRACE_END() ATRACE_END()
61f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#else
62f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#define MY_TRACE_BEGIN(x)
63f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#define MY_TRACE_END()
64f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn#endif
65f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Names for default app, locale, and vendor.  We might want to change
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * these to be an actual locale, e.g. always use en-US as the default.
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* kDefaultLocale = "default";
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* kDefaultVendor = "default";
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* kAssetsRoot = "assets";
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* kAppZipName = NULL; //"classes.jar";
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* kSystemAssets = "framework/framework-res.apk";
7757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstadstatic const char* kIdmapCacheDir = "resource-cache";
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* kExcludeExtension = ".EXCLUDE";
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic Asset* const kExcludedAsset = (Asset*) 0xd000000d;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic volatile int32_t gCount = 0;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstadnamespace {
8657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    // Transform string /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap
8757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    String8 idmapPathForPackagePath(const String8& pkgPath)
8857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    {
8957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        const char* root = getenv("ANDROID_DATA");
9057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set");
9157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        String8 path(root);
9257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        path.appendPath(kIdmapCacheDir);
9357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
9457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        char buf[256]; // 256 chars should be enough for anyone...
9557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        strncpy(buf, pkgPath.string(), 255);
9657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        buf[255] = '\0';
9757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        char* filename = buf;
9857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        while (*filename && *filename == '/') {
9957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            ++filename;
10057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
10157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        char* p = filename;
10257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        while (*p) {
10357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            if (*p == '/') {
10457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                *p = '@';
10557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            }
10657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            ++p;
10757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
10857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        path.appendPath(filename);
10957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        path.append("@idmap");
11057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
11157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return path;
11257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
11369a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian
11469a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian    /*
11569a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian     * Like strdup(), but uses C++ "new" operator instead of malloc.
11669a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian     */
11769a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian    static char* strdupNew(const char* str)
11869a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian    {
11969a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        char* newStr;
12069a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        int len;
12169a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian
12269a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        if (str == NULL)
12369a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian            return NULL;
12469a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian
12569a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        len = strlen(str);
12669a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        newStr = new char[len+1];
12769a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        memcpy(newStr, str, len+1);
12869a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian
12969a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian        return newStr;
13069a3ce1eb1af3129056f7da95a491da0280019b5Mathias Agopian    }
13157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad}
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      AssetManager
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint32_t AssetManager::getGlobalCount()
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return gCount;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetManager::AssetManager(CacheMode cacheMode)
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mLocale(NULL), mVendor(NULL),
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mResources(NULL), mConfig(new ResTable_config),
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mCacheMode(cacheMode), mCacheValid(false)
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int count = android_atomic_inc(&gCount)+1;
1506215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block    //ALOGI("Creating AssetManager %p #%d\n", this, count);
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    memset(mConfig, 0, sizeof(ResTable_config));
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetManager::~AssetManager(void)
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int count = android_atomic_dec(&gCount);
1576215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block    //ALOGI("Destroying AssetManager in %p #%d\n", this, count);
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete mConfig;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete mResources;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // don't have a String class yet, so make sure we clean up
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete[] mLocale;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete[] mVendor;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::addAssetPath(const String8& path, void** cookie)
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    asset_path ap;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 realPath(path);
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (kAppZipName) {
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        realPath.appendPath(kAppZipName);
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ap.type = ::getFileType(realPath.string());
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ap.type == kFileTypeRegular) {
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ap.path = realPath;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ap.path = path;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ap.type = ::getFileType(path.string());
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ap.type != kFileTypeDirectory && ap.type != kFileTypeRegular) {
1848564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("Asset path %s is neither a directory nor file (type=%d).",
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 path.string(), (int)ap.type);
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Skip if we have it already.
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<mAssetPaths.size(); i++) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mAssetPaths[i].path == ap.path) {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cookie) {
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                *cookie = (void*)(i+1);
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
20071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("In %p Asset %s path: %s", this,
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         ap.type == kFileTypeDirectory ? "dir" : "zip", ap.path.string());
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mAssetPaths.add(ap);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // new paths are always added at the end
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (cookie) {
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *cookie = (void*)mAssetPaths.size();
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    // add overlay packages for /system/framework; apps are handled by the
21157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    // (Java) package manager
21257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (strncmp(path.string(), "/system/framework/", 18) == 0) {
21357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        // When there is an environment variable for /vendor, this
21457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        // should be changed to something similar to how ANDROID_ROOT
21557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        // and ANDROID_DATA are used in this file.
21657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        String8 overlayPath("/vendor/overlay/framework/");
21757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        overlayPath.append(path.getPathLeaf());
21857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        if (TEMP_FAILURE_RETRY(access(overlayPath.string(), R_OK)) == 0) {
21957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            asset_path oap;
22057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            oap.path = overlayPath;
22157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            oap.type = ::getFileType(overlayPath.string());
22257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            bool addOverlay = (oap.type == kFileTypeRegular); // only .apks supported as overlay
22357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            if (addOverlay) {
22457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                oap.idmap = idmapPathForPackagePath(overlayPath);
22557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
22657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                if (isIdmapStaleLocked(ap.path, oap.path, oap.idmap)) {
22757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                    addOverlay = createIdmapFileLocked(ap.path, oap.path, oap.idmap);
22857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                }
22957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            }
23057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            if (addOverlay) {
23157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                mAssetPaths.add(oap);
23257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            } else {
2338564c8da817a845353d213acd8636b76f567b234Steve Block                ALOGW("failed to add overlay package %s\n", overlayPath.string());
23457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            }
23557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
23657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
23757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstadbool AssetManager::isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath,
24257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                                      const String8& idmapPath)
24357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad{
24457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    struct stat st;
24557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (TEMP_FAILURE_RETRY(stat(idmapPath.string(), &st)) == -1) {
24657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        if (errno == ENOENT) {
24757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            return true; // non-existing idmap is always stale
24857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        } else {
2498564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("failed to stat file %s: %s\n", idmapPath.string(), strerror(errno));
25057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            return false;
25157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
25257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
25357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (st.st_size < ResTable::IDMAP_HEADER_SIZE_BYTES) {
2548564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("file %s has unexpectedly small size=%zd\n", idmapPath.string(), (size_t)st.st_size);
25557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
25657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
25757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    int fd = TEMP_FAILURE_RETRY(::open(idmapPath.string(), O_RDONLY));
25857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (fd == -1) {
2598564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("failed to open file %s: %s\n", idmapPath.string(), strerror(errno));
26057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
26157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
26257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    char buf[ResTable::IDMAP_HEADER_SIZE_BYTES];
26357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    ssize_t bytesLeft = ResTable::IDMAP_HEADER_SIZE_BYTES;
26457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    for (;;) {
26557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        ssize_t r = TEMP_FAILURE_RETRY(read(fd, buf + ResTable::IDMAP_HEADER_SIZE_BYTES - bytesLeft,
26657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                                            bytesLeft));
26757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        if (r < 0) {
26857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            TEMP_FAILURE_RETRY(close(fd));
26957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            return false;
27057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
27157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        bytesLeft -= r;
27257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        if (bytesLeft == 0) {
27357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            break;
27457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
27557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
27657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    TEMP_FAILURE_RETRY(close(fd));
27757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
27857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    uint32_t cachedOriginalCrc, cachedOverlayCrc;
27957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (!ResTable::getIdmapInfo(buf, ResTable::IDMAP_HEADER_SIZE_BYTES,
28057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                                &cachedOriginalCrc, &cachedOverlayCrc)) {
28157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
28257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
28357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
28457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    uint32_t actualOriginalCrc, actualOverlayCrc;
28557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (!getZipEntryCrcLocked(originalPath, "resources.arsc", &actualOriginalCrc)) {
28657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
28757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
28857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (!getZipEntryCrcLocked(overlayPath, "resources.arsc", &actualOverlayCrc)) {
28957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
29057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
29157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    return cachedOriginalCrc != actualOriginalCrc || cachedOverlayCrc != actualOverlayCrc;
29257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad}
29357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
29457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstadbool AssetManager::getZipEntryCrcLocked(const String8& zipPath, const char* entryFilename,
29557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                                        uint32_t* pCrc)
29657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad{
29757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    asset_path ap;
29857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    ap.path = zipPath;
29957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    const ZipFileRO* zip = getZipFileLocked(ap);
30057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (zip == NULL) {
30157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
30257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
30357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    const ZipEntryRO entry = zip->findEntryByName(entryFilename);
30457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (entry == NULL) {
30557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
30657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
30757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (!zip->getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, (long*)pCrc)) {
30857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        return false;
30957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
31057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    return true;
31157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad}
31257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
31357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstadbool AssetManager::createIdmapFileLocked(const String8& originalPath, const String8& overlayPath,
31457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                                         const String8& idmapPath)
31557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad{
3165baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("%s: originalPath=%s overlayPath=%s idmapPath=%s\n",
31757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad         __FUNCTION__, originalPath.string(), overlayPath.string(), idmapPath.string());
31857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    ResTable tables[2];
31957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    const String8* paths[2] = { &originalPath, &overlayPath };
32057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    uint32_t originalCrc, overlayCrc;
32157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    bool retval = false;
32257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    ssize_t offset = 0;
32357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    int fd = 0;
32457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    uint32_t* data = NULL;
32557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    size_t size;
32657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
32757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    for (int i = 0; i < 2; ++i) {
32857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        asset_path ap;
32957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        ap.type = kFileTypeRegular;
33057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        ap.path = *paths[i];
33157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap);
33257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        if (ass == NULL) {
3338564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("failed to find resources.arsc in %s\n", ap.path.string());
33457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            goto error;
33557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
33657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        tables[i].add(ass, (void*)1, false);
33757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
33857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
33957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (!getZipEntryCrcLocked(originalPath, "resources.arsc", &originalCrc)) {
3408564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("failed to retrieve crc for resources.arsc in %s\n", originalPath.string());
34157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        goto error;
34257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
34357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (!getZipEntryCrcLocked(overlayPath, "resources.arsc", &overlayCrc)) {
3448564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("failed to retrieve crc for resources.arsc in %s\n", overlayPath.string());
34557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        goto error;
34657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
34757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
34857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (tables[0].createIdmap(tables[1], originalCrc, overlayCrc,
34957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                              (void**)&data, &size) != NO_ERROR) {
3508564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("failed to generate idmap data for file %s\n", idmapPath.string());
35157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        goto error;
35257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
35357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
35457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    // This should be abstracted (eg replaced by a stand-alone
35557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    // application like dexopt, triggered by something equivalent to
35657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    // installd).
35757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    fd = TEMP_FAILURE_RETRY(::open(idmapPath.string(), O_WRONLY | O_CREAT | O_TRUNC, 0644));
35857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (fd == -1) {
3598564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("failed to write idmap file %s (open: %s)\n", idmapPath.string(), strerror(errno));
36057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        goto error_free;
36157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
36257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    for (;;) {
36357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        ssize_t written = TEMP_FAILURE_RETRY(write(fd, data + offset, size));
36457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        if (written < 0) {
3658564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("failed to write idmap file %s (write: %s)\n", idmapPath.string(),
36657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                 strerror(errno));
36757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            goto error_close;
36857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
36957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        size -= (size_t)written;
37057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        offset += written;
37157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        if (size == 0) {
37257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            break;
37357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
37457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
37557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
37657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    retval = true;
37757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstaderror_close:
37857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    TEMP_FAILURE_RETRY(close(fd));
37957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstaderror_free:
38057f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    free(data);
38157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstaderror:
38257f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    return retval;
38357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad}
38457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::addDefaultAssets()
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* root = getenv("ANDROID_ROOT");
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_ROOT not set");
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 path(root);
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    path.appendPath(kSystemAssets);
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return addAssetPath(path, NULL);
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid* AssetManager::nextAssetPath(void* cookie) const
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t next = ((size_t)cookie)+1;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return next > mAssetPaths.size() ? NULL : (void*)next;
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectString8 AssetManager::getAssetPath(void* cookie) const
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t which = ((size_t)cookie)-1;
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (which < mAssetPaths.size()) {
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAssetPaths[which].path;
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return String8();
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the current locale.  Use NULL to indicate no locale.
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close and reopen Zip archives as appropriate, and reset cached
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * information in the locale-specific sections of the tree.
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::setLocale(const char* locale)
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    setLocaleLocked(locale);
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::setLocaleLocked(const char* locale)
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mLocale != NULL) {
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* previously set, purge cached data */
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        purgeFileNameCacheLocked();
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //mZipSet.purgeLocale();
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete[] mLocale;
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mLocale = strdupNew(locale);
434c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    updateResourceParamsLocked();
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the current vendor.  Use NULL to indicate no vendor.
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close and reopen Zip archives as appropriate, and reset cached
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * information in the vendor-specific sections of the tree.
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::setVendor(const char* vendor)
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mVendor != NULL) {
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* previously set, purge cached data */
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        purgeFileNameCacheLocked();
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //mZipSet.purgeVendor();
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete[] mVendor;
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mVendor = strdupNew(vendor);
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::setConfiguration(const ResTable_config& config, const char* locale)
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *mConfig = config;
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (locale) {
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setLocaleLocked(locale);
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (config.language[0] != 0) {
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        char spec[9];
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        spec[0] = config.language[0];
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        spec[1] = config.language[1];
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (config.country[0] != 0) {
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            spec[2] = '_';
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            spec[3] = config.country[0];
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            spec[4] = config.country[1];
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            spec[5] = 0;
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            spec[3] = 0;
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setLocaleLocked(spec);
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateResourceParamsLocked();
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
48108d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackbornvoid AssetManager::getConfiguration(ResTable_config* outConfig) const
48208d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackborn{
48308d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackborn    AutoMutex _l(mLock);
48408d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackborn    *outConfig = *mConfig;
48508d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackborn}
48608d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackborn
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open an asset.
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The data could be;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  - In a file on disk (assetBase + fileName).
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  - In a compressed file on disk (assetBase + fileName.gz).
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  - In a Zip archive, uncompressed or compressed.
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * It can be in a number of different directories and Zip archives.
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The search order is:
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  - [appname]
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    - locale + vendor
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    - "default" + vendor
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    - locale + "default"
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    - "default + "default"
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  - "common"
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    - (same as above)
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * To find a particular file, we have to try up to eight paths with
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * all three forms of data.
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We should probably reject requests for "illegal" filenames, e.g. those
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with illegal characters or "../" backward relative paths.
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::open(const char* fileName, AccessMode mode)
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCacheMode != CACHE_OFF && !mCacheValid)
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        loadFileNameCacheLocked();
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 assetName(kAssetsRoot);
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assetName.appendPath(fileName);
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For each top-level asset path, search for the asset.
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t i = mAssetPaths.size();
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (i > 0) {
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i--;
53171f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Looking for asset '%s' in '%s'\n",
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                assetName.string(), mAssetPaths.itemAt(i).path.string());
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Asset* pAsset = openNonAssetInPathLocked(assetName.string(), mode, mAssetPaths.itemAt(i));
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset != NULL) {
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return pAsset != kExcludedAsset ? pAsset : NULL;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NULL;
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open a non-asset file as if it were an asset.
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The "fileName" is the partial path starting from the application
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * name.
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openNonAsset(const char* fileName, AccessMode mode)
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCacheMode != CACHE_OFF && !mCacheValid)
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        loadFileNameCacheLocked();
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For each top-level asset path, search for the asset.
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t i = mAssetPaths.size();
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (i > 0) {
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i--;
56571f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Looking for non-asset '%s' in '%s'\n", fileName, mAssetPaths.itemAt(i).path.string());
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Asset* pAsset = openNonAssetInPathLocked(
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fileName, mode, mAssetPaths.itemAt(i));
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset != NULL) {
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return pAsset != kExcludedAsset ? pAsset : NULL;
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NULL;
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openNonAsset(void* cookie, const char* fileName, AccessMode mode)
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t which = ((size_t)cookie)-1;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCacheMode != CACHE_OFF && !mCacheValid)
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        loadFileNameCacheLocked();
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (which < mAssetPaths.size()) {
58971f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Looking for non-asset '%s' in '%s'\n", fileName,
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mAssetPaths.itemAt(which).path.string());
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Asset* pAsset = openNonAssetInPathLocked(
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fileName, mode, mAssetPaths.itemAt(which));
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset != NULL) {
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return pAsset != kExcludedAsset ? pAsset : NULL;
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NULL;
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the type of a file in the asset namespace.
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This currently only works for regular files.  All others (including
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * directories) will return kFileTypeNonexistent.
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectFileType AssetManager::getFileType(const char* fileName)
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* pAsset = NULL;
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Open the asset.  This is less efficient than simply finding the
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * file, but it's not too bad (we don't uncompress or mmap data until
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the first read() call).
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = open(fileName, Asset::ACCESS_STREAMING);
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete pAsset;
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pAsset == NULL)
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return kFileTypeNonexistent;
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return kFileTypeRegular;
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst ResTable* AssetManager::getResTable(bool required) const
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResTable* rt = mResources;
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (rt) {
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return rt;
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Iterate through all asset packages, collecting resources from each.
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mResources != NULL) {
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mResources;
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (required) {
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCacheMode != CACHE_OFF && !mCacheValid)
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const_cast<AssetManager*>(this)->loadFileNameCacheLocked();
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t N = mAssetPaths.size();
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<N; i++) {
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Asset* ass = NULL;
65078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        ResTable* sharedRes = NULL;
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool shared = true;
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const asset_path& ap = mAssetPaths.itemAt(i);
653f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn        MY_TRACE_BEGIN(ap.path.string());
65457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        Asset* idmap = openIdmapLocked(ap);
65571f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Looking for resource asset in '%s'\n", ap.path.string());
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ap.type != kFileTypeDirectory) {
65778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            if (i == 0) {
65878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                // The first item is typically the framework resources,
65978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                // which we want to avoid parsing every time.
66078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                sharedRes = const_cast<AssetManager*>(this)->
66178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    mZipSet.getZipResourceTable(ap.path);
66278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            }
66378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            if (sharedRes == NULL) {
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ass = const_cast<AssetManager*>(this)->
66578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    mZipSet.getZipResourceTableAsset(ap.path);
66678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                if (ass == NULL) {
66771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block                    ALOGV("loading resource table %s\n", ap.path.string());
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ass = const_cast<AssetManager*>(this)->
66978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                        openNonAssetInPathLocked("resources.arsc",
67078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                                                 Asset::ACCESS_BUFFER,
67178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                                                 ap);
67278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    if (ass != NULL && ass != kExcludedAsset) {
67378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                        ass = const_cast<AssetManager*>(this)->
67478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                            mZipSet.setZipResourceTableAsset(ap.path, ass);
67578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    }
67678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                }
677c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
67878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                if (i == 0 && ass != NULL) {
67978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    // If this is the first resource table in the asset
68078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    // manager, then we are going to cache it so that we
68178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    // can quickly copy it out for others.
68271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block                    ALOGV("Creating shared resources for %s", ap.path.string());
68378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    sharedRes = new ResTable();
68457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                    sharedRes->add(ass, (void*)(i+1), false, idmap);
68578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                    sharedRes = const_cast<AssetManager*>(this)->
68678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                        mZipSet.setZipResourceTable(ap.path, sharedRes);
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
69071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("loading resource table %s\n", ap.path.string());
691c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes            ass = const_cast<AssetManager*>(this)->
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                openNonAssetInPathLocked("resources.arsc",
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                         Asset::ACCESS_BUFFER,
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                         ap);
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            shared = false;
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
69778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        if ((ass != NULL || sharedRes != NULL) && ass != kExcludedAsset) {
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (rt == NULL) {
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mResources = rt = new ResTable();
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updateResourceParamsLocked();
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
70271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("Installing resource asset %p in to table %p\n", ass, mResources);
70378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            if (sharedRes != NULL) {
70471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block                ALOGV("Copying existing resources for %s", ap.path.string());
70578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                rt->add(sharedRes);
70678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            } else {
70771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block                ALOGV("Parsing resources for %s", ap.path.string());
70857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad                rt->add(ass, (void*)(i+1), !shared, idmap);
70978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            }
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!shared) {
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delete ass;
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7152b91c67137dfcdfc3f418e13ad63cef68f5247acMårten Kongstad        if (idmap != NULL) {
7162b91c67137dfcdfc3f418e13ad63cef68f5247acMårten Kongstad            delete idmap;
7172b91c67137dfcdfc3f418e13ad63cef68f5247acMårten Kongstad        }
718f7be4800df28d7cb6a96003046bf90245e7054abDianne Hackborn        MY_TRACE_END();
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7218564c8da817a845353d213acd8636b76f567b234Steve Block    if (required && !rt) ALOGW("Unable to find resources file resources.arsc");
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!rt) {
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mResources = rt = new ResTable();
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return rt;
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::updateResourceParamsLocked() const
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResTable* res = mResources;
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!res) {
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t llen = mLocale ? strlen(mLocale) : 0;
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mConfig->language[0] = 0;
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mConfig->language[1] = 0;
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mConfig->country[0] = 0;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mConfig->country[1] = 0;
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (llen >= 2) {
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mConfig->language[0] = mLocale[0];
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mConfig->language[1] = mLocale[1];
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (llen >= 5) {
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mConfig->country[0] = mLocale[3];
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mConfig->country[1] = mLocale[4];
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mConfig->size = sizeof(*mConfig);
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    res->setParameters(mConfig);
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
75357f4b77c89bafedf9468f9a636561c0c193405c9Mårten KongstadAsset* AssetManager::openIdmapLocked(const struct asset_path& ap) const
75457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad{
75557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    Asset* ass = NULL;
75657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    if (ap.idmap.size() != 0) {
75757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        ass = const_cast<AssetManager*>(this)->
75857f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad            openAssetFromFileLocked(ap.idmap, Asset::ACCESS_BUFFER);
75957f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        if (ass) {
76071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("loading idmap %s\n", ap.idmap.string());
76157f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        } else {
7628564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("failed to load idmap %s\n", ap.idmap.string());
76357f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad        }
76457f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    }
76557f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad    return ass;
76657f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad}
76757f4b77c89bafedf9468f9a636561c0c193405c9Mårten Kongstad
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst ResTable& AssetManager::getResources(bool required) const
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const ResTable* rt = getResTable(required);
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return *rt;
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::isUpToDate()
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mZipSet.isUpToDate();
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::getLocales(Vector<String8>* locales) const
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResTable* res = mResources;
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (res != NULL) {
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        res->getLocales(locales);
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open a non-asset file as if it were an asset, searching for it in the
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified app.
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pass in a NULL values for "appName" if the common app directory should
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be used.
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode mode,
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const asset_path& ap)
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* pAsset = NULL;
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* look at the filesystem on disk */
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ap.type == kFileTypeDirectory) {
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String8 path(ap.path);
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path.appendPath(fileName);
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = openAssetFromFileLocked(path, mode);
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset == NULL) {
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* try again, this time with ".gz" */
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            path.append(".gz");
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pAsset = openAssetFromFileLocked(path, mode);
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset != NULL) {
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //printf("FOUND NA '%s' on disk\n", fileName);
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pAsset->setAssetSource(path);
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* look inside the zip file */
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String8 path(fileName);
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* check the appropriate Zip file */
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ZipFileRO* pZip;
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ZipEntryRO entry;
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pZip = getZipFileLocked(ap);
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pZip != NULL) {
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //printf("GOT zip, checking NA '%s'\n", (const char*) path);
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            entry = pZip->findEntryByName(path.string());
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (entry != NULL) {
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("FOUND NA in Zip file for %s\n", appName ? appName : kAppCommon);
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pAsset = openAssetFromZipLocked(pZip, entry, mode, path);
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset != NULL) {
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* create a "source" name, for debug/display */
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pAsset->setAssetSource(
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    createZipSourceNameLocked(ZipSet::getPathName(ap.path.string()), String8(""),
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                String8(fileName)));
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open an asset, searching for it in the directory hierarchy for the
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified app.
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pass in a NULL values for "appName" if the common app directory should
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be used.
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openInPathLocked(const char* fileName, AccessMode mode,
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const asset_path& ap)
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* pAsset = NULL;
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Try various combinations of locale and vendor.
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mLocale != NULL && mVendor != NULL)
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = openInLocaleVendorLocked(fileName, mode, ap, mLocale, mVendor);
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pAsset == NULL && mVendor != NULL)
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = openInLocaleVendorLocked(fileName, mode, ap, NULL, mVendor);
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pAsset == NULL && mLocale != NULL)
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = openInLocaleVendorLocked(fileName, mode, ap, mLocale, NULL);
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pAsset == NULL)
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = openInLocaleVendorLocked(fileName, mode, ap, NULL, NULL);
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open an asset, searching for it in the directory hierarchy for the
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified locale and vendor.
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We also search in "app.jar".
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pass in NULL values for "appName", "locale", and "vendor" if the
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * defaults should be used.
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openInLocaleVendorLocked(const char* fileName, AccessMode mode,
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const asset_path& ap, const char* locale, const char* vendor)
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* pAsset = NULL;
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ap.type == kFileTypeDirectory) {
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCacheMode == CACHE_OFF) {
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* look at the filesystem on disk */
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 path(createPathNameLocked(ap, locale, vendor));
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            path.appendPath(fileName);
893c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 excludeName(path);
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            excludeName.append(kExcludeExtension);
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (::getFileType(excludeName.string()) != kFileTypeNonexistent) {
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* say no more */
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("+++ excluding '%s'\n", (const char*) excludeName);
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return kExcludedAsset;
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
901c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pAsset = openAssetFromFileLocked(path, mode);
903c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pAsset == NULL) {
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* try again, this time with ".gz" */
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                path.append(".gz");
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pAsset = openAssetFromFileLocked(path, mode);
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
909c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pAsset != NULL)
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pAsset->setAssetSource(path);
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* find in cache */
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 path(createPathNameLocked(ap, locale, vendor));
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            path.appendPath(fileName);
916c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            AssetDir::FileInfo tmpInfo;
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool found = false;
919c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 excludeName(path);
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            excludeName.append(kExcludeExtension);
922c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCache.indexOf(excludeName) != NAME_NOT_FOUND) {
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* go no farther */
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("+++ Excluding '%s'\n", (const char*) excludeName);
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return kExcludedAsset;
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * File compression extensions (".gz") don't get stored in the
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * name cache, so we have to try both here.
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCache.indexOf(path) != NAME_NOT_FOUND) {
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                found = true;
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pAsset = openAssetFromFileLocked(path, mode);
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (pAsset == NULL) {
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    /* try again, this time with ".gz" */
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    path.append(".gz");
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pAsset = openAssetFromFileLocked(path, mode);
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pAsset != NULL)
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pAsset->setAssetSource(path);
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Don't continue the search into the Zip files.  Our cached info
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * said it was a file on disk; to be consistent with openDir()
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * we want to return the loose asset.  If the cached file gets
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * removed, we fail.
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             *
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * The alternative is to update our cache when files get deleted,
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * or make some sort of "best effort" promise, but for now I'm
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * taking the hard line.
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (found) {
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (pAsset == NULL)
9585baa3a62a97544669fba6d65a11c07f252e654ddSteve Block                    ALOGD("Expected file not found: '%s'\n", path.string());
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return pAsset;
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Either it wasn't found on disk or on the cached view of the disk.
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Dig through the currently-opened set of Zip files.  If caching
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is disabled, the Zip file may get reopened.
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pAsset == NULL && ap.type == kFileTypeRegular) {
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String8 path;
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path.appendPath((locale != NULL) ? locale : kDefaultLocale);
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path.appendPath((vendor != NULL) ? vendor : kDefaultVendor);
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path.appendPath(fileName);
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* check the appropriate Zip file */
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ZipFileRO* pZip;
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ZipEntryRO entry;
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pZip = getZipFileLocked(ap);
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pZip != NULL) {
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //printf("GOT zip, checking '%s'\n", (const char*) path);
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            entry = pZip->findEntryByName(path.string());
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (entry != NULL) {
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("FOUND in Zip file for %s/%s-%s\n",
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //    appName, locale, vendor);
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pAsset = openAssetFromZipLocked(pZip, entry, mode, path);
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pAsset != NULL) {
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* create a "source" name, for debug/display */
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pAsset->setAssetSource(createZipSourceNameLocked(ZipSet::getPathName(ap.path.string()),
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                             String8(""), String8(fileName)));
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a "source name" for a file from a Zip archive.
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectString8 AssetManager::createZipSourceNameLocked(const String8& zipFileName,
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const String8& dirName, const String8& fileName)
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 sourceName("zip:");
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sourceName.append(zipFileName);
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sourceName.append(":");
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (dirName.length() > 0) {
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sourceName.appendPath(dirName);
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sourceName.appendPath(fileName);
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return sourceName;
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a path to a loose asset (asset-base/app/locale/vendor).
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectString8 AssetManager::createPathNameLocked(const asset_path& ap, const char* locale,
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* vendor)
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 path(ap.path);
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    path.appendPath((locale != NULL) ? locale : kDefaultLocale);
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    path.appendPath((vendor != NULL) ? vendor : kDefaultVendor);
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return path;
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a path to a loose asset (asset-base/app/rootDir).
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectString8 AssetManager::createPathNameLocked(const asset_path& ap, const char* rootDir)
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 path(ap.path);
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (rootDir != NULL) path.appendPath(rootDir);
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return path;
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return a pointer to one of our open Zip archives.  Returns NULL if no
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * matching Zip file exists.
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Right now we have 2 possible Zip files (1 each in app/"common").
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If caching is set to CACHE_OFF, to get the expected behavior we
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * need to reopen the Zip file on every request.  That would be silly
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and expensive, so instead we just check the file modification date.
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pass in NULL values for "appName", "locale", and "vendor" if the
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * generics should be used.
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectZipFileRO* AssetManager::getZipFileLocked(const asset_path& ap)
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
105471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("getZipFileLocked() in %p\n", this);
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mZipSet.getZip(ap.path);
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Try to open an asset from a file on disk.
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If the file is compressed with gzip, we seek to the start of the
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * deflated data and pass that in (just like we would for a Zip archive).
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For uncompressed data, we may already have an mmap()ed version sitting
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * around.  If so, we want to hand that to the Asset instead.
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This returns NULL if the file doesn't exist, couldn't be opened, or
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * claims to be a ".gz" but isn't.
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openAssetFromFileLocked(const String8& pathName,
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AccessMode mode)
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* pAsset = NULL;
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (strcasecmp(pathName.getPathExtension().string(), ".gz") == 0) {
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //printf("TRYING '%s'\n", (const char*) pathName);
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = Asset::createFromCompressedFile(pathName.string(), mode);
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //printf("TRYING '%s'\n", (const char*) pathName);
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = Asset::createFromFile(pathName.string(), mode);
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Given an entry in a Zip archive, create a new Asset object.
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If the entry is uncompressed, we may want to create or share a
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * slice of shared memory.
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::openAssetFromZipLocked(const ZipFileRO* pZipFile,
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const ZipEntryRO entry, AccessMode mode, const String8& entryName)
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* pAsset = NULL;
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // TODO: look for previously-created shared memory slice?
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int method;
110068246dcec17c245a434dad70b778960dc5c84af1Kenny Root    size_t uncompressedLen;
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //printf("USING Zip '%s'\n", pEntry->getFileName());
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //pZipFile->getEntryInfo(entry, &method, &uncompressedLen, &compressedLen,
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    &offset);
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!pZipFile->getEntryInfo(entry, &method, &uncompressedLen, NULL, NULL,
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NULL, NULL))
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
11098564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("getEntryInfo failed\n");
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FileMap* dataMap = pZipFile->createEntryFileMap(entry);
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (dataMap == NULL) {
11158564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("create map from entry failed\n");
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (method == ZipFileRO::kCompressStored) {
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = Asset::createFromUncompressedMap(dataMap, mode);
112171f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Opened uncompressed entry %s in zip %s mode %d: %p", entryName.string(),
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dataMap->getFileName(), mode, pAsset);
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pAsset = Asset::createFromCompressedMap(dataMap, method,
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            uncompressedLen, mode);
112671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Opened compressed entry %s in zip %s mode %d: %p", entryName.string(),
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dataMap->getFileName(), mode, pAsset);
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pAsset == NULL) {
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* unexpected */
11318564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("create from segment failed\n");
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open a directory in the asset namespace.
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An "asset directory" is simply the combination of all files in all
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * locations, with ".gz" stripped for loose files.  With app, locale, and
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * vendor defined, we have 8 directories and 2 Zip archives to scan.
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pass in "" for the root dir.
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetDir* AssetManager::openDir(const char* dirName)
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(mLock);
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AssetDir* pDir = NULL;
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo>* pMergedInfo = NULL;
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(dirName != NULL);
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //printf("+++ openDir(%s) in '%s'\n", dirName, (const char*) mAssetBase);
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCacheMode != CACHE_OFF && !mCacheValid)
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        loadFileNameCacheLocked();
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pDir = new AssetDir;
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Scan the various directories, merging what we find into a single
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * vector.  We want to scan them in reverse priority order so that
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the ".EXCLUDE" processing works correctly.  Also, if we decide we
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * want to remember where the file is coming from, we'll get the right
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * version.
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * We start with Zip archives, then do loose files.
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pMergedInfo = new SortedVector<AssetDir::FileInfo>;
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t i = mAssetPaths.size();
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (i > 0) {
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i--;
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const asset_path& ap = mAssetPaths.itemAt(i);
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ap.type == kFileTypeRegular) {
118171f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("Adding directory %s from zip %s", dirName, ap.path.string());
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            scanAndMergeZipLocked(pMergedInfo, ap, kAssetsRoot, dirName);
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
118471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("Adding directory %s from dir %s", dirName, ap.path.string());
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            scanAndMergeDirLocked(pMergedInfo, ap, kAssetsRoot, dirName);
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    printf("FILE LIST:\n");
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = 0; i < (size_t) pMergedInfo->size(); i++) {
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf(" %d: (%d) '%s'\n", i,
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pMergedInfo->itemAt(i).getFileType(),
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (const char*) pMergedInfo->itemAt(i).getFileName());
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pDir->setFileList(pMergedInfo);
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pDir;
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1203bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn * Open a directory in the non-asset namespace.
1204bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn *
1205bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn * An "asset directory" is simply the combination of all files in all
1206bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn * locations, with ".gz" stripped for loose files.  With app, locale, and
1207bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn * vendor defined, we have 8 directories and 2 Zip archives to scan.
1208bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn *
1209bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn * Pass in "" for the root dir.
1210bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn */
1211bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne HackbornAssetDir* AssetManager::openNonAssetDir(void* cookie, const char* dirName)
1212bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn{
1213bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    AutoMutex _l(mLock);
1214bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1215bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    AssetDir* pDir = NULL;
1216bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    SortedVector<AssetDir::FileInfo>* pMergedInfo = NULL;
1217bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1218bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
1219bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    assert(dirName != NULL);
1220bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1221bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    //printf("+++ openDir(%s) in '%s'\n", dirName, (const char*) mAssetBase);
1222bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1223bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    if (mCacheMode != CACHE_OFF && !mCacheValid)
1224bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        loadFileNameCacheLocked();
1225bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1226bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    pDir = new AssetDir;
1227bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1228bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    pMergedInfo = new SortedVector<AssetDir::FileInfo>;
1229bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1230bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    const size_t which = ((size_t)cookie)-1;
1231bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1232bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    if (which < mAssetPaths.size()) {
1233bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        const asset_path& ap = mAssetPaths.itemAt(which);
1234bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        if (ap.type == kFileTypeRegular) {
123571f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("Adding directory %s from zip %s", dirName, ap.path.string());
1236bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            scanAndMergeZipLocked(pMergedInfo, ap, NULL, dirName);
1237bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        } else {
123871f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("Adding directory %s from dir %s", dirName, ap.path.string());
1239bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            scanAndMergeDirLocked(pMergedInfo, ap, NULL, dirName);
1240bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        }
1241bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    }
1242bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1243bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn#if 0
1244bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    printf("FILE LIST:\n");
1245bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    for (i = 0; i < (size_t) pMergedInfo->size(); i++) {
1246bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        printf(" %d: (%d) '%s'\n", i,
1247bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            pMergedInfo->itemAt(i).getFileType(),
1248bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            (const char*) pMergedInfo->itemAt(i).getFileName());
1249bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    }
1250bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn#endif
1251bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1252bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    pDir->setFileList(pMergedInfo);
1253bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    return pDir;
1254bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn}
1255bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn
1256bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn/*
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scan the contents of the specified directory and merge them into the
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "pMergedInfo" vector, removing previous entries if we find "exclude"
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * directives.
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns "false" if we found nothing to contribute.
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::scanAndMergeDirLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const asset_path& ap, const char* rootDir, const char* dirName)
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo>* pContents;
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 path;
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(pMergedInfo != NULL);
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //printf("scanAndMergeDir: %s %s %s %s\n", appName, locale, vendor,dirName);
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCacheValid) {
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int i, start, count;
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pContents = new SortedVector<AssetDir::FileInfo>;
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Get the basic partial path and find it in the cache.  That's
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the start point for the search.
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path = createPathNameLocked(ap, rootDir);
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dirName[0] != '\0')
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            path.appendPath(dirName);
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        start = mCache.indexOf(path);
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (start == NAME_NOT_FOUND) {
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //printf("+++ not found in cache: dir '%s'\n", (const char*) path);
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            delete pContents;
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * The match string looks like "common/default/default/foo/bar/".
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * The '/' on the end ensures that we don't match on the directory
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * itself or on ".../foo/barfy/".
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path.append("/");
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        count = mCache.size();
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Pick out the stuff in the current dir by examining the pathname.
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * It needs to match the partial pathname prefix, and not have a '/'
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * (fssep) anywhere after the prefix.
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (i = start+1; i < count; i++) {
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCache[i].getFileName().length() > path.length() &&
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                strncmp(mCache[i].getFileName().string(), path.string(), path.length()) == 0)
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            {
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const char* name = mCache[i].getFileName().string();
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // XXX THIS IS BROKEN!  Looks like we need to store the full
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // path prefix separately from the file path.
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (strchr(name + path.length(), '/') == NULL) {
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    /* grab it, reducing path to just the filename component */
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    AssetDir::FileInfo tmp = mCache[i];
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    tmp.setFileName(tmp.getFileName().getPathLeaf());
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pContents->add(tmp);
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* no longer in the dir or its subdirs */
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        path = createPathNameLocked(ap, rootDir);
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dirName[0] != '\0')
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            path.appendPath(dirName);
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pContents = scanDirLocked(path);
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pContents == NULL)
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // if we wanted to do an incremental cache fill, we would do it here
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Process "exclude" directives.  If we find a filename that ends with
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * ".EXCLUDE", we look for a matching entry in the "merged" set, and
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * remove it if we find it.  We also delete the "exclude" entry.
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int i, count, exclExtLen;
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    count = pContents->size();
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    exclExtLen = strlen(kExcludeExtension);
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = 0; i < count; i++) {
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* name;
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int nameLen;
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        name = pContents->itemAt(i).getFileName().string();
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nameLen = strlen(name);
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (nameLen > exclExtLen &&
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            strcmp(name + (nameLen - exclExtLen), kExcludeExtension) == 0)
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 match(name, nameLen - exclExtLen);
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int matchIdx;
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            matchIdx = AssetDir::FileInfo::findEntry(pMergedInfo, match);
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (matchIdx > 0) {
136071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block                ALOGV("Excluding '%s' [%s]\n",
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pMergedInfo->itemAt(matchIdx).getFileName().string(),
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pMergedInfo->itemAt(matchIdx).getSourceName().string());
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pMergedInfo->removeAt(matchIdx);
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("+++ no match on '%s'\n", (const char*) match);
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13685baa3a62a97544669fba6d65a11c07f252e654ddSteve Block            ALOGD("HEY: size=%d removing %d\n", (int)pContents->size(), i);
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pContents->removeAt(i);
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            i--;        // adjust "for" loop
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            count--;    //  and loop limit
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mergeInfoLocked(pMergedInfo, pContents);
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete pContents;
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scan the contents of the specified directory, and stuff what we find
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * into a newly-allocated vector.
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Files ending in ".gz" will have their extensions removed.
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We should probably think about skipping files with "illegal" names,
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * e.g. illegal characters (/\:) or excessive length.
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns NULL if the specified directory doesn't exist.
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectSortedVector<AssetDir::FileInfo>* AssetManager::scanDirLocked(const String8& path)
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo>* pContents = NULL;
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    DIR* dir;
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct dirent* entry;
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FileType fileType;
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
140071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("Scanning dir '%s'\n", path.string());
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dir = opendir(path.string());
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (dir == NULL)
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pContents = new SortedVector<AssetDir::FileInfo>;
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (1) {
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        entry = readdir(dir);
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (entry == NULL)
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (strcmp(entry->d_name, ".") == 0 ||
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            strcmp(entry->d_name, "..") == 0)
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef _DIRENT_HAVE_D_TYPE
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (entry->d_type == DT_REG)
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fileType = kFileTypeRegular;
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else if (entry->d_type == DT_DIR)
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fileType = kFileTypeDirectory;
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fileType = kFileTypeUnknown;
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // stat the file
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fileType = ::getFileType(path.appendPathCopy(entry->d_name).string());
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fileType != kFileTypeRegular && fileType != kFileTypeDirectory)
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AssetDir::FileInfo info;
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        info.set(String8(entry->d_name), fileType);
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (strcasecmp(info.getFileName().getPathExtension().string(), ".gz") == 0)
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            info.setFileName(info.getFileName().getBasePath());
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        info.setSourceName(path.appendPathCopy(info.getFileName()));
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pContents->add(info);
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    closedir(dir);
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pContents;
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scan the contents out of the specified Zip archive, and merge what we
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * find into "pMergedInfo".  If the Zip archive in question doesn't exist,
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * we return immediately.
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns "false" if we found nothing to contribute.
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const asset_path& ap, const char* rootDir, const char* baseDirName)
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFileRO* pZip;
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Vector<String8> dirs;
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AssetDir::FileInfo info;
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo> contents;
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 sourceName, zipName, dirName;
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pZip = mZipSet.getZip(ap.path);
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pZip == NULL) {
14628564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("Failure opening zip %s\n", ap.path.string());
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zipName = ZipSet::getPathName(ap.path.string());
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* convert "sounds" to "rootDir/sounds" */
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (rootDir != NULL) dirName = rootDir;
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dirName.appendPath(baseDirName);
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Scan through the list of files, looking for a match.  The files in
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the Zip table of contents are not in sorted order, so we have to
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * process the entire list.  We're looking for a string that begins
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with the characters in "dirName", is followed by a '/', and has no
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * subsequent '/' in the stuff that follows.
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * What makes this especially fun is that directories are not stored
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * explicitly in Zip archives, so we have to infer them from context.
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * When we see "sounds/foo.wav" we have to leave a note to ourselves
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to insert a directory called "sounds" into the list.  We store
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * these in temporary vector so that we only return each one once.
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Name comparisons are case-sensitive to match UNIX filesystem
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * semantics.
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int dirNameLen = dirName.length();
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < pZip->getNumEntries(); i++) {
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ZipEntryRO entry;
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        char nameBuf[256];
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        entry = pZip->findEntryByIndex(i);
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pZip->getEntryFileName(entry, nameBuf, sizeof(nameBuf)) != 0) {
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // TODO: fix this if we expect to have long names
14963762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("ARGH: name too long?\n");
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1499bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        //printf("Comparing %s in %s?\n", nameBuf, dirName.string());
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dirNameLen == 0 ||
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (strncmp(nameBuf, dirName.string(), dirNameLen) == 0 &&
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             nameBuf[dirNameLen] == '/'))
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const char* cp;
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const char* nextSlash;
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cp = nameBuf + dirNameLen;
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (dirNameLen != 0)
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cp++;       // advance past the '/'
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            nextSlash = strchr(cp, '/');
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//xxx this may break if there are bare directory entries
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (nextSlash == NULL) {
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* this is a file in the requested directory */
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.set(String8(nameBuf).getPathLeaf(), kFileTypeRegular);
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.setSourceName(
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    createZipSourceNameLocked(zipName, dirName, info.getFileName()));
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                contents.add(info);
1522bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                //printf("FOUND: file '%s'\n", info.getFileName().string());
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* this is a subdir; add it if we don't already have it*/
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8 subdirName(cp, nextSlash - cp);
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                size_t j;
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                size_t N = dirs.size();
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (j = 0; j < N; j++) {
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (subdirName == dirs[j]) {
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (j == N) {
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    dirs.add(subdirName);
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1538bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                //printf("FOUND: dir '%s'\n", subdirName.string());
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Add the set of unique directories.
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < (int) dirs.size(); i++) {
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        info.set(dirs[i], kFileTypeDirectory);
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        info.setSourceName(
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            createZipSourceNameLocked(zipName, dirName, info.getFileName()));
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        contents.add(info);
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mergeInfoLocked(pMergedInfo, &contents);
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Merge two vectors of FileInfo.
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The merged contents will be stuffed into *pMergedInfo.
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If an entry for a file exists in both "pMergedInfo" and "pContents",
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * we use the newer "pContents" entry.
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::mergeInfoLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const SortedVector<AssetDir::FileInfo>* pContents)
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Merge what we found in this directory with what we found in
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * other places.
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Two basic approaches:
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (1) Create a new array that holds the unique values of the two
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     arrays.
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (2) Take the elements from pContents and shove them into pMergedInfo.
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Because these are vectors of complex objects, moving elements around
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * inside the vector requires constructing new objects and allocating
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * storage for members.  With approach #1, we're always adding to the
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * end, whereas with #2 we could be inserting multiple elements at the
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * front of the vector.  Approach #1 requires a full copy of the
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * contents of pMergedInfo, but approach #2 requires the same copy for
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * every insertion at the front of pMergedInfo.
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (We should probably use a SortedVector interface that allows us to
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * just stuff items in, trusting us to maintain the sort order.)
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo>* pNewSorted;
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mergeMax, contMax;
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mergeIdx, contIdx;
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pNewSorted = new SortedVector<AssetDir::FileInfo>;
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mergeMax = pMergedInfo->size();
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    contMax = pContents->size();
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mergeIdx = contIdx = 0;
15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (mergeIdx < mergeMax || contIdx < contMax) {
16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mergeIdx == mergeMax) {
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* hit end of "merge" list, copy rest of "contents" */
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pNewSorted->add(pContents->itemAt(contIdx));
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            contIdx++;
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (contIdx == contMax) {
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* hit end of "cont" list, copy rest of "merge" */
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pNewSorted->add(pMergedInfo->itemAt(mergeIdx));
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mergeIdx++;
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (pMergedInfo->itemAt(mergeIdx) == pContents->itemAt(contIdx))
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* items are identical, add newer and advance both indices */
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pNewSorted->add(pContents->itemAt(contIdx));
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mergeIdx++;
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            contIdx++;
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (pMergedInfo->itemAt(mergeIdx) < pContents->itemAt(contIdx))
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* "merge" is lower, add that one */
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pNewSorted->add(pMergedInfo->itemAt(mergeIdx));
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mergeIdx++;
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* "cont" is lower, add that one */
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            assert(pContents->itemAt(contIdx) < pMergedInfo->itemAt(mergeIdx));
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pNewSorted->add(pContents->itemAt(contIdx));
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            contIdx++;
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Overwrite the "merged" list with the new stuff.
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *pMergedInfo = *pNewSorted;
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete pNewSorted;
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0       // for Vector, rather than SortedVector
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int i, j;
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = pContents->size() -1; i >= 0; i--) {
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool add = true;
16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (j = pMergedInfo->size() -1; j >= 0; j--) {
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* case-sensitive comparisons, to behave like UNIX fs */
16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (strcmp(pContents->itemAt(i).mFileName,
16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       pMergedInfo->itemAt(j).mFileName) == 0)
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            {
16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /* match, don't add this entry */
16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                add = false;
16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (add)
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pMergedInfo->add(pContents->itemAt(i));
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Load all files into the file name cache.  We want to do this across
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * all combinations of { appname, locale, vendor }, performing a recursive
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * directory traversal.
16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is not the most efficient data structure.  Also, gathering the
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * information as we needed it (file-by-file or directory-by-directory)
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * would be faster.  However, on the actual device, 99% of the files will
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * live in Zip archives, so this list will be very small.  The trouble
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is that we have to check the "loose" files first, so it's important
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that we don't beat the filesystem silly looking for files that aren't
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * there.
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note on thread safety: this is the only function that causes updates
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to mCache, and anybody who tries to use it will call here if !mCacheValid,
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * so we need to employ a mutex here.
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::loadFileNameCacheLocked(void)
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(!mCacheValid);
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mCache.size() == 0);
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef DO_TIMINGS   // need to link against -lrt for this now
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    DurationTimer timer;
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    timer.start();
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fncScanLocked(&mCache, "");
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef DO_TIMINGS
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    timer.stop();
16875baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("Cache scan took %.3fms\n",
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        timer.durationUsecs() / 1000.0);
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int i;
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    printf("CACHED FILE LIST (%d entries):\n", mCache.size());
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = 0; i < (int) mCache.size(); i++) {
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf(" %d: (%d) '%s'\n", i,
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCache.itemAt(i).getFileType(),
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (const char*) mCache.itemAt(i).getFileName());
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCacheValid = true;
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scan up to 8 versions of the specified directory.
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::fncScanLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* dirName)
17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t i = mAssetPaths.size();
17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (i > 0) {
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i--;
17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const asset_path& ap = mAssetPaths.itemAt(i);
17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fncScanAndMergeDirLocked(pMergedInfo, ap, NULL, NULL, dirName);
17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mLocale != NULL)
17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fncScanAndMergeDirLocked(pMergedInfo, ap, mLocale, NULL, dirName);
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mVendor != NULL)
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fncScanAndMergeDirLocked(pMergedInfo, ap, NULL, mVendor, dirName);
17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mLocale != NULL && mVendor != NULL)
17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fncScanAndMergeDirLocked(pMergedInfo, ap, mLocale, mVendor, dirName);
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Recursively scan this directory and all subdirs.
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is similar to scanAndMergeDir, but we don't remove the .EXCLUDE
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * files, and we prepend the extended partial path to the filenames.
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::fncScanAndMergeDirLocked(
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo>* pMergedInfo,
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const asset_path& ap, const char* locale, const char* vendor,
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* dirName)
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SortedVector<AssetDir::FileInfo>* pContents;
17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 partialPath;
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 fullPath;
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // XXX This is broken -- the filename cache needs to hold the base
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // asset path separately from its filename.
1741c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    partialPath = createPathNameLocked(ap, locale, vendor);
17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (dirName[0] != '\0') {
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        partialPath.appendPath(dirName);
17459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fullPath = partialPath;
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pContents = scanDirLocked(fullPath);
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pContents == NULL) {
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;       // directory did not exist
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Scan all subdirectories of the current dir, merging what we find
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * into "pMergedInfo".
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < (int) pContents->size(); i++) {
17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pContents->itemAt(i).getFileType() == kFileTypeDirectory) {
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 subdir(dirName);
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            subdir.appendPath(pContents->itemAt(i).getFileName());
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fncScanAndMergeDirLocked(pMergedInfo, ap, locale, vendor, subdir.string());
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * To be consistent, we want entries for the root directory.  If
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * we're the root, add one now.
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (dirName[0] == '\0') {
17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AssetDir::FileInfo tmpInfo;
17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmpInfo.set(String8(""), kFileTypeDirectory);
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmpInfo.setSourceName(createPathNameLocked(ap, locale, vendor));
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pContents->add(tmpInfo);
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * We want to prepend the extended partial path to every entry in
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "pContents".  It's the same value for each entry, so this will
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not change the sorting order of the vector contents.
17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < (int) pContents->size(); i++) {
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const AssetDir::FileInfo& info = pContents->itemAt(i);
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pContents->editItemAt(i).setFileName(partialPath.appendPathCopy(info.getFileName()));
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mergeInfoLocked(pMergedInfo, pContents);
17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Trash the cache.
17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::purgeFileNameCacheLocked(void)
17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCacheValid = false;
17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCache.clear();
17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      AssetManager::SharedZip
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectMutex AssetManager::SharedZip::gLock;
18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectDefaultKeyedVector<String8, wp<AssetManager::SharedZip> > AssetManager::SharedZip::gOpen;
18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetManager::SharedZip::SharedZip(const String8& path, time_t modWhen)
181278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    : mPath(path), mZipFile(NULL), mModWhen(modWhen),
181378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn      mResourceTableAsset(NULL), mResourceTable(NULL)
18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18156215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block    //ALOGI("Creating SharedZip %p %s\n", this, (const char*)mPath);
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mZipFile = new ZipFileRO;
181771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("+++ opening zip '%s'\n", mPath.string());
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mZipFile->open(mPath.string()) != NO_ERROR) {
18195baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("failed to open Zip archive '%s'\n", mPath.string());
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete mZipFile;
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mZipFile = NULL;
18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path)
18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex _l(gLock);
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    time_t modWhen = getFileModDate(path);
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<SharedZip> zip = gOpen.valueFor(path).promote();
18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip != NULL && zip->mModWhen == modWhen) {
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return zip;
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = new SharedZip(path, modWhen);
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    gOpen.add(path, zip);
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return zip;
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectZipFileRO* AssetManager::SharedZip::getZip()
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mZipFile;
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::SharedZip::getResourceTableAsset()
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
184671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("Getting from SharedZip %p resource asset %p\n", this, mResourceTableAsset);
18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mResourceTableAsset;
18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset* AssetManager::SharedZip::setResourceTableAsset(Asset* asset)
18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AutoMutex _l(gLock);
18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mResourceTableAsset == NULL) {
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mResourceTableAsset = asset;
18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This is not thread safe the first time it is called, so
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // do it here with the global lock held.
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset->getBuffer(true);
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return asset;
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete asset;
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mResourceTableAsset;
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
186678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne HackbornResTable* AssetManager::SharedZip::getResourceTable()
186778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn{
186871f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("Getting from SharedZip %p resource table %p\n", this, mResourceTable);
186978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    return mResourceTable;
187078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn}
187178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn
187278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne HackbornResTable* AssetManager::SharedZip::setResourceTable(ResTable* res)
187378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn{
187478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    {
187578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        AutoMutex _l(gLock);
187678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        if (mResourceTable == NULL) {
187778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            mResourceTable = res;
187878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            return res;
187978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        }
188078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    }
188178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    delete res;
188278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    return mResourceTable;
188378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn}
188478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::SharedZip::isUpToDate()
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    time_t modWhen = getFileModDate(mPath.string());
18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mModWhen == modWhen;
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetManager::SharedZip::~SharedZip()
18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18936215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block    //ALOGI("Destroying SharedZip %p %s\n", this, (const char*)mPath);
189478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    if (mResourceTable != NULL) {
189578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        delete mResourceTable;
189678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    }
18979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mResourceTableAsset != NULL) {
18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete mResourceTableAsset;
18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mZipFile != NULL) {
19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete mZipFile;
190271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Closed '%s'\n", mPath.string());
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
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 *      AssetManager::ZipSet
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor.
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetManager::ZipSet::ZipSet(void)
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Destructor.  Close any open archives.
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAssetManager::ZipSet::~ZipSet(void)
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t N = mZipFile.size();
19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i = 0; i < N; i++)
19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        closeZip(i);
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close a Zip file and reset the entry.
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AssetManager::ZipSet::closeZip(int idx)
19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mZipFile.editItemAt(idx) = NULL;
19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieve the appropriate Zip file from the set.
19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
19419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectZipFileRO* AssetManager::ZipSet::getZip(const String8& path)
19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int idx = getIndex(path);
19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<SharedZip> zip = mZipFile[idx];
19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL) {
19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        zip = SharedZip::get(path);
19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mZipFile.editItemAt(idx) = zip;
19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return zip->getZip();
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
195278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne HackbornAsset* AssetManager::ZipSet::getZipResourceTableAsset(const String8& path)
19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int idx = getIndex(path);
19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<SharedZip> zip = mZipFile[idx];
19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL) {
19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        zip = SharedZip::get(path);
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mZipFile.editItemAt(idx) = zip;
19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return zip->getResourceTableAsset();
19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
196378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne HackbornAsset* AssetManager::ZipSet::setZipResourceTableAsset(const String8& path,
19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                 Asset* asset)
19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int idx = getIndex(path);
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<SharedZip> zip = mZipFile[idx];
19689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // doesn't make sense to call before previously accessing.
19699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return zip->setResourceTableAsset(asset);
19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
197278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne HackbornResTable* AssetManager::ZipSet::getZipResourceTable(const String8& path)
197378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn{
197478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    int idx = getIndex(path);
197578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    sp<SharedZip> zip = mZipFile[idx];
197678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    if (zip == NULL) {
197778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        zip = SharedZip::get(path);
197878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn        mZipFile.editItemAt(idx) = zip;
197978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    }
198078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    return zip->getResourceTable();
198178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn}
198278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn
198378c405178c57bb45e40f1e2839d6a18d91f7f02cDianne HackbornResTable* AssetManager::ZipSet::setZipResourceTable(const String8& path,
198478c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                                                    ResTable* res)
198578c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn{
198678c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    int idx = getIndex(path);
198778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    sp<SharedZip> zip = mZipFile[idx];
198878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    // doesn't make sense to call before previously accessing.
198978c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn    return zip->setResourceTable(res);
199078c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn}
199178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn
19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Generate the partial pathname for the specified archive.  The caller
19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * gets to prepend the asset root directory.
19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns something like "common/en-US-noogle.jar".
19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*static*/ String8 AssetManager::ZipSet::getPathName(const char* zipPath)
19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return String8(zipPath);
20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AssetManager::ZipSet::isUpToDate()
20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t N = mZipFile.size();
20069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<N; i++) {
20079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mZipFile[i] != NULL && !mZipFile[i]->isUpToDate()) {
20089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
20099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
20129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
20139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Compute the zip file's index.
20169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "appName", "locale", and "vendor" should be set to NULL to indicate the
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * default directory.
20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
20209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint AssetManager::ZipSet::getIndex(const String8& zip) const
20219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
20229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t N = mZipPath.size();
20239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<N; i++) {
20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mZipPath[i] == zip) {
20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return i;
20269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mZipPath.add(zip);
20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mZipFile.add(NULL);
20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mZipPath.size()-1;
20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2034