Merge branch 'jb-mr1-dev-plus-aosp' of https://googleplex-android.googlesource.com/_direct/platform/frameworks/base into jb-mr1-dev-plus-aosp
This commit is contained in:
@@ -20,6 +20,7 @@ LOCAL_SRC_FILES := \
|
|||||||
StringPool.cpp \
|
StringPool.cpp \
|
||||||
XMLNode.cpp \
|
XMLNode.cpp \
|
||||||
ResourceFilter.cpp \
|
ResourceFilter.cpp \
|
||||||
|
ResourceIdCache.cpp \
|
||||||
ResourceTable.cpp \
|
ResourceTable.cpp \
|
||||||
Images.cpp \
|
Images.cpp \
|
||||||
Resource.cpp \
|
Resource.cpp \
|
||||||
|
|||||||
107
tools/aapt/ResourceIdCache.cpp
Normal file
107
tools/aapt/ResourceIdCache.cpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2012 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Manage a resource ID cache.
|
||||||
|
|
||||||
|
#define LOG_TAG "ResourceIdCache"
|
||||||
|
|
||||||
|
#include <utils/String16.h>
|
||||||
|
#include <utils/Log.h>
|
||||||
|
#include "ResourceIdCache.h"
|
||||||
|
#include <map>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
static size_t mHits = 0;
|
||||||
|
static size_t mMisses = 0;
|
||||||
|
static size_t mCollisions = 0;
|
||||||
|
|
||||||
|
static const size_t MAX_CACHE_ENTRIES = 2048;
|
||||||
|
static const android::String16 TRUE16("1");
|
||||||
|
static const android::String16 FALSE16("0");
|
||||||
|
|
||||||
|
struct CacheEntry {
|
||||||
|
// concatenation of the relevant strings into a single instance
|
||||||
|
android::String16 hashedName;
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
|
CacheEntry() {}
|
||||||
|
CacheEntry(const android::String16& name, uint32_t resId) : hashedName(name), id(resId) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
static map< uint32_t, CacheEntry > mIdMap;
|
||||||
|
|
||||||
|
|
||||||
|
// djb2; reasonable choice for strings when collisions aren't particularly important
|
||||||
|
static inline uint32_t hashround(uint32_t hash, int c) {
|
||||||
|
return ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t hash(const android::String16& hashableString) {
|
||||||
|
uint32_t hash = 5381;
|
||||||
|
const char16_t* str = hashableString.string();
|
||||||
|
while (int c = *str++) hash = hashround(hash, c);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
static inline String16 makeHashableName(const android::String16& package,
|
||||||
|
const android::String16& type,
|
||||||
|
const android::String16& name,
|
||||||
|
bool onlyPublic) {
|
||||||
|
String16 hashable = String16(name);
|
||||||
|
hashable += type;
|
||||||
|
hashable += package;
|
||||||
|
hashable += (onlyPublic ? TRUE16 : FALSE16);
|
||||||
|
return hashable;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ResourceIdCache::lookup(const android::String16& package,
|
||||||
|
const android::String16& type,
|
||||||
|
const android::String16& name,
|
||||||
|
bool onlyPublic) {
|
||||||
|
const String16 hashedName = makeHashableName(package, type, name, onlyPublic);
|
||||||
|
const uint32_t hashcode = hash(hashedName);
|
||||||
|
map<uint32_t, CacheEntry>::iterator item = mIdMap.find(hashcode);
|
||||||
|
if (item == mIdMap.end()) {
|
||||||
|
// cache miss
|
||||||
|
mMisses++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// legit match?
|
||||||
|
if (hashedName == (*item).second.hashedName) {
|
||||||
|
mHits++;
|
||||||
|
return (*item).second.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// collision
|
||||||
|
mCollisions++;
|
||||||
|
mIdMap.erase(hashcode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the resource ID being stored, for callsite convenience
|
||||||
|
uint32_t ResourceIdCache::store(const android::String16& package,
|
||||||
|
const android::String16& type,
|
||||||
|
const android::String16& name,
|
||||||
|
bool onlyPublic,
|
||||||
|
uint32_t resId) {
|
||||||
|
if (mIdMap.size() < MAX_CACHE_ENTRIES) {
|
||||||
|
const String16 hashedName = makeHashableName(package, type, name, onlyPublic);
|
||||||
|
const uint32_t hashcode = hash(hashedName);
|
||||||
|
mIdMap[hashcode] = CacheEntry(hashedName, resId);
|
||||||
|
}
|
||||||
|
return resId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceIdCache::dump() {
|
||||||
|
printf("ResourceIdCache dump:\n");
|
||||||
|
printf("Size: %ld\n", mIdMap.size());
|
||||||
|
printf("Hits: %ld\n", mHits);
|
||||||
|
printf("Misses: %ld\n", mMisses);
|
||||||
|
printf("(Collisions: %ld)\n", mCollisions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
30
tools/aapt/ResourceIdCache.h
Normal file
30
tools/aapt/ResourceIdCache.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2012 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Manage a resource ID cache.
|
||||||
|
|
||||||
|
#ifndef RESOURCE_ID_CACHE_H
|
||||||
|
#define RESOURCE_ID_CACHE_H
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
class android::String16;
|
||||||
|
|
||||||
|
class ResourceIdCache {
|
||||||
|
public:
|
||||||
|
static uint32_t lookup(const android::String16& package,
|
||||||
|
const android::String16& type,
|
||||||
|
const android::String16& name,
|
||||||
|
bool onlyPublic);
|
||||||
|
|
||||||
|
static uint32_t store(const android::String16& package,
|
||||||
|
const android::String16& type,
|
||||||
|
const android::String16& name,
|
||||||
|
bool onlyPublic,
|
||||||
|
uint32_t resId);
|
||||||
|
|
||||||
|
static void dump(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "XMLNode.h"
|
#include "XMLNode.h"
|
||||||
#include "ResourceFilter.h"
|
#include "ResourceFilter.h"
|
||||||
|
#include "ResourceIdCache.h"
|
||||||
|
|
||||||
#include <androidfw/ResourceTypes.h>
|
#include <androidfw/ResourceTypes.h>
|
||||||
#include <utils/ByteOrder.h>
|
#include <utils/ByteOrder.h>
|
||||||
@@ -1998,6 +1999,9 @@ uint32_t ResourceTable::getResId(const String16& package,
|
|||||||
const String16& name,
|
const String16& name,
|
||||||
bool onlyPublic) const
|
bool onlyPublic) const
|
||||||
{
|
{
|
||||||
|
uint32_t id = ResourceIdCache::lookup(package, type, name, onlyPublic);
|
||||||
|
if (id != 0) return id; // cache hit
|
||||||
|
|
||||||
sp<Package> p = mPackages.valueFor(package);
|
sp<Package> p = mPackages.valueFor(package);
|
||||||
if (p == NULL) return 0;
|
if (p == NULL) return 0;
|
||||||
|
|
||||||
@@ -2016,11 +2020,10 @@ uint32_t ResourceTable::getResId(const String16& package,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Res_INTERNALID(rid)) {
|
if (Res_INTERNALID(rid)) {
|
||||||
return rid;
|
return ResourceIdCache::store(package, type, name, onlyPublic, rid);
|
||||||
}
|
}
|
||||||
return Res_MAKEID(p->getAssignedId()-1,
|
return ResourceIdCache::store(package, type, name, onlyPublic,
|
||||||
Res_GETTYPE(rid),
|
Res_MAKEID(p->getAssignedId()-1, Res_GETTYPE(rid), Res_GETENTRY(rid)));
|
||||||
Res_GETENTRY(rid));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sp<Type> t = p->getTypes().valueFor(type);
|
sp<Type> t = p->getTypes().valueFor(type);
|
||||||
@@ -2029,7 +2032,9 @@ uint32_t ResourceTable::getResId(const String16& package,
|
|||||||
if (c == NULL) return 0;
|
if (c == NULL) return 0;
|
||||||
int32_t ei = c->getEntryIndex();
|
int32_t ei = c->getEntryIndex();
|
||||||
if (ei < 0) return 0;
|
if (ei < 0) return 0;
|
||||||
return getResId(p, t, ei);
|
|
||||||
|
return ResourceIdCache::store(package, type, name, onlyPublic,
|
||||||
|
getResId(p, t, ei));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ResourceTable::getResId(const String16& ref,
|
uint32_t ResourceTable::getResId(const String16& ref,
|
||||||
|
|||||||
Reference in New Issue
Block a user