Merge "Optimize ResTable::getLocales() to improve bindApplication performance" into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
bfdc2020b9
@@ -29,6 +29,7 @@ import android.content.res.ResourcesImpl;
|
||||
import android.content.res.ResourcesKey;
|
||||
import android.hardware.display.DisplayManagerGlobal;
|
||||
import android.os.IBinder;
|
||||
import android.os.Trace;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.LocaleList;
|
||||
@@ -430,37 +431,44 @@ public class ResourcesManager {
|
||||
@Nullable Configuration overrideConfig,
|
||||
@NonNull CompatibilityInfo compatInfo,
|
||||
@Nullable ClassLoader classLoader) {
|
||||
final ResourcesKey key = new ResourcesKey(
|
||||
resDir,
|
||||
splitResDirs,
|
||||
overlayDirs,
|
||||
libDirs,
|
||||
displayId,
|
||||
overrideConfig != null ? new Configuration(overrideConfig) : null, // Copy
|
||||
compatInfo);
|
||||
classLoader = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
|
||||
try {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES,
|
||||
"ResourcesManager#createBaseActivityResources");
|
||||
final ResourcesKey key = new ResourcesKey(
|
||||
resDir,
|
||||
splitResDirs,
|
||||
overlayDirs,
|
||||
libDirs,
|
||||
displayId,
|
||||
overrideConfig != null ? new Configuration(overrideConfig) : null, // Copy
|
||||
compatInfo);
|
||||
classLoader = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "createBaseActivityResources activity=" + activityToken
|
||||
+ " with key=" + key);
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
final ActivityResources activityResources = getOrCreateActivityResourcesStructLocked(
|
||||
activityToken);
|
||||
|
||||
if (overrideConfig != null) {
|
||||
activityResources.overrideConfig.setTo(overrideConfig);
|
||||
} else {
|
||||
activityResources.overrideConfig.setToDefaults();
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "createBaseActivityResources activity=" + activityToken
|
||||
+ " with key=" + key);
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
final ActivityResources activityResources =
|
||||
getOrCreateActivityResourcesStructLocked(
|
||||
activityToken);
|
||||
|
||||
if (overrideConfig != null) {
|
||||
activityResources.overrideConfig.setTo(overrideConfig);
|
||||
} else {
|
||||
activityResources.overrideConfig.setToDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
// Update any existing Activity Resources references.
|
||||
updateResourcesForActivity(activityToken, overrideConfig);
|
||||
|
||||
// Now request an actual Resources object.
|
||||
return getOrCreateResources(activityToken, key, classLoader);
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
|
||||
}
|
||||
|
||||
// Update any existing Activity Resources references.
|
||||
updateResourcesForActivity(activityToken, overrideConfig);
|
||||
|
||||
// Now request an actual Resources object.
|
||||
return getOrCreateResources(activityToken, key, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -490,8 +498,8 @@ public class ResourcesManager {
|
||||
}
|
||||
|
||||
if (activityToken != null) {
|
||||
final ActivityResources activityResources = getOrCreateActivityResourcesStructLocked(
|
||||
activityToken);
|
||||
final ActivityResources activityResources =
|
||||
getOrCreateActivityResourcesStructLocked(activityToken);
|
||||
|
||||
// Clean up any dead references so they don't pile up.
|
||||
ArrayUtils.unstableRemoveIf(activityResources.activityResources,
|
||||
@@ -539,6 +547,7 @@ public class ResourcesManager {
|
||||
final String[] systemLocales = findSystemLocales
|
||||
? AssetManager.getSystem().getLocales() : null;
|
||||
final String[] nonSystemLocales = resourcesImpl.getAssets().getNonSystemLocales();
|
||||
|
||||
// Avoid checking for non-pseudo-locales if we already know there were some from a previous
|
||||
// Resources. The default value (for when hasNonSystemLocales is true) doesn't matter,
|
||||
// since mHasNonSystemLocales will also be true, and thus isPseudoLocalesOnly would not be
|
||||
@@ -613,16 +622,21 @@ public class ResourcesManager {
|
||||
@Nullable Configuration overrideConfig,
|
||||
@NonNull CompatibilityInfo compatInfo,
|
||||
@Nullable ClassLoader classLoader) {
|
||||
final ResourcesKey key = new ResourcesKey(
|
||||
resDir,
|
||||
splitResDirs,
|
||||
overlayDirs,
|
||||
libDirs,
|
||||
displayId,
|
||||
overrideConfig != null ? new Configuration(overrideConfig) : null, // Copy
|
||||
compatInfo);
|
||||
classLoader = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
|
||||
return getOrCreateResources(activityToken, key, classLoader);
|
||||
try {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesManager#getResources");
|
||||
final ResourcesKey key = new ResourcesKey(
|
||||
resDir,
|
||||
splitResDirs,
|
||||
overlayDirs,
|
||||
libDirs,
|
||||
displayId,
|
||||
overrideConfig != null ? new Configuration(overrideConfig) : null, // Copy
|
||||
compatInfo);
|
||||
classLoader = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
|
||||
return getOrCreateResources(activityToken, key, classLoader);
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -636,93 +650,104 @@ public class ResourcesManager {
|
||||
*/
|
||||
public void updateResourcesForActivity(@NonNull IBinder activityToken,
|
||||
@Nullable Configuration overrideConfig) {
|
||||
synchronized (this) {
|
||||
final ActivityResources activityResources = getOrCreateActivityResourcesStructLocked(
|
||||
activityToken);
|
||||
try {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES,
|
||||
"ResourcesManager#updateResourcesForActivity");
|
||||
synchronized (this) {
|
||||
final ActivityResources activityResources =
|
||||
getOrCreateActivityResourcesStructLocked(activityToken);
|
||||
|
||||
if (Objects.equals(activityResources.overrideConfig, overrideConfig)) {
|
||||
// They are the same, no work to do.
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab a copy of the old configuration so we can create the delta's of each
|
||||
// Resources object associated with this Activity.
|
||||
final Configuration oldConfig = new Configuration(activityResources.overrideConfig);
|
||||
|
||||
// Update the Activity's base override.
|
||||
if (overrideConfig != null) {
|
||||
activityResources.overrideConfig.setTo(overrideConfig);
|
||||
} else {
|
||||
activityResources.overrideConfig.setToDefaults();
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Throwable here = new Throwable();
|
||||
here.fillInStackTrace();
|
||||
Slog.d(TAG, "updating resources override for activity=" + activityToken
|
||||
+ " from oldConfig=" + Configuration.resourceQualifierString(oldConfig)
|
||||
+ " to newConfig="
|
||||
+ Configuration.resourceQualifierString(activityResources.overrideConfig),
|
||||
here);
|
||||
}
|
||||
|
||||
final boolean activityHasOverrideConfig =
|
||||
!activityResources.overrideConfig.equals(Configuration.EMPTY);
|
||||
|
||||
// Rebase each Resources associated with this Activity.
|
||||
final int refCount = activityResources.activityResources.size();
|
||||
for (int i = 0; i < refCount; i++) {
|
||||
WeakReference<Resources> weakResRef = activityResources.activityResources.get(i);
|
||||
Resources resources = weakResRef.get();
|
||||
if (resources == null) {
|
||||
continue;
|
||||
if (Objects.equals(activityResources.overrideConfig, overrideConfig)) {
|
||||
// They are the same, no work to do.
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract the ResourcesKey that was last used to create the Resources for this
|
||||
// activity.
|
||||
final ResourcesKey oldKey = findKeyForResourceImplLocked(resources.getImpl());
|
||||
if (oldKey == null) {
|
||||
Slog.e(TAG, "can't find ResourcesKey for resources impl="
|
||||
+ resources.getImpl());
|
||||
continue;
|
||||
}
|
||||
// Grab a copy of the old configuration so we can create the delta's of each
|
||||
// Resources object associated with this Activity.
|
||||
final Configuration oldConfig = new Configuration(activityResources.overrideConfig);
|
||||
|
||||
// Build the new override configuration for this ResourcesKey.
|
||||
final Configuration rebasedOverrideConfig = new Configuration();
|
||||
// Update the Activity's base override.
|
||||
if (overrideConfig != null) {
|
||||
rebasedOverrideConfig.setTo(overrideConfig);
|
||||
activityResources.overrideConfig.setTo(overrideConfig);
|
||||
} else {
|
||||
activityResources.overrideConfig.setToDefaults();
|
||||
}
|
||||
|
||||
if (activityHasOverrideConfig && oldKey.hasOverrideConfiguration()) {
|
||||
// Generate a delta between the old base Activity override configuration and
|
||||
// the actual final override configuration that was used to figure out the real
|
||||
// delta this Resources object wanted.
|
||||
Configuration overrideOverrideConfig = Configuration.generateDelta(
|
||||
oldConfig, oldKey.mOverrideConfiguration);
|
||||
rebasedOverrideConfig.updateFrom(overrideOverrideConfig);
|
||||
}
|
||||
|
||||
// Create the new ResourcesKey with the rebased override config.
|
||||
final ResourcesKey newKey = new ResourcesKey(oldKey.mResDir, oldKey.mSplitResDirs,
|
||||
oldKey.mOverlayDirs, oldKey.mLibDirs, oldKey.mDisplayId,
|
||||
rebasedOverrideConfig, oldKey.mCompatInfo);
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "rebasing ref=" + resources + " from oldKey=" + oldKey
|
||||
+ " to newKey=" + newKey);
|
||||
Throwable here = new Throwable();
|
||||
here.fillInStackTrace();
|
||||
Slog.d(TAG, "updating resources override for activity=" + activityToken
|
||||
+ " from oldConfig="
|
||||
+ Configuration.resourceQualifierString(oldConfig)
|
||||
+ " to newConfig="
|
||||
+ Configuration.resourceQualifierString(
|
||||
activityResources.overrideConfig),
|
||||
here);
|
||||
}
|
||||
|
||||
ResourcesImpl resourcesImpl = findResourcesImplForKeyLocked(newKey);
|
||||
if (resourcesImpl == null) {
|
||||
resourcesImpl = createResourcesImpl(newKey);
|
||||
mResourceImpls.put(newKey, new WeakReference<>(resourcesImpl));
|
||||
}
|
||||
final boolean activityHasOverrideConfig =
|
||||
!activityResources.overrideConfig.equals(Configuration.EMPTY);
|
||||
|
||||
if (resourcesImpl != resources.getImpl()) {
|
||||
// Set the ResourcesImpl, updating it for all users of this Resources object.
|
||||
resources.setImpl(resourcesImpl);
|
||||
// Rebase each Resources associated with this Activity.
|
||||
final int refCount = activityResources.activityResources.size();
|
||||
for (int i = 0; i < refCount; i++) {
|
||||
WeakReference<Resources> weakResRef = activityResources.activityResources.get(
|
||||
i);
|
||||
Resources resources = weakResRef.get();
|
||||
if (resources == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract the ResourcesKey that was last used to create the Resources for this
|
||||
// activity.
|
||||
final ResourcesKey oldKey = findKeyForResourceImplLocked(resources.getImpl());
|
||||
if (oldKey == null) {
|
||||
Slog.e(TAG, "can't find ResourcesKey for resources impl="
|
||||
+ resources.getImpl());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build the new override configuration for this ResourcesKey.
|
||||
final Configuration rebasedOverrideConfig = new Configuration();
|
||||
if (overrideConfig != null) {
|
||||
rebasedOverrideConfig.setTo(overrideConfig);
|
||||
}
|
||||
|
||||
if (activityHasOverrideConfig && oldKey.hasOverrideConfiguration()) {
|
||||
// Generate a delta between the old base Activity override configuration and
|
||||
// the actual final override configuration that was used to figure out the
|
||||
// real delta this Resources object wanted.
|
||||
Configuration overrideOverrideConfig = Configuration.generateDelta(
|
||||
oldConfig, oldKey.mOverrideConfiguration);
|
||||
rebasedOverrideConfig.updateFrom(overrideOverrideConfig);
|
||||
}
|
||||
|
||||
// Create the new ResourcesKey with the rebased override config.
|
||||
final ResourcesKey newKey = new ResourcesKey(oldKey.mResDir,
|
||||
oldKey.mSplitResDirs,
|
||||
oldKey.mOverlayDirs, oldKey.mLibDirs, oldKey.mDisplayId,
|
||||
rebasedOverrideConfig, oldKey.mCompatInfo);
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "rebasing ref=" + resources + " from oldKey=" + oldKey
|
||||
+ " to newKey=" + newKey);
|
||||
}
|
||||
|
||||
ResourcesImpl resourcesImpl = findResourcesImplForKeyLocked(newKey);
|
||||
if (resourcesImpl == null) {
|
||||
resourcesImpl = createResourcesImpl(newKey);
|
||||
mResourceImpls.put(newKey, new WeakReference<>(resourcesImpl));
|
||||
}
|
||||
|
||||
if (resourcesImpl != resources.getImpl()) {
|
||||
// Set the ResourcesImpl, updating it for all users of this Resources
|
||||
// object.
|
||||
resources.setImpl(resourcesImpl);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -745,86 +770,95 @@ public class ResourcesManager {
|
||||
|
||||
public final boolean applyConfigurationToResourcesLocked(@NonNull Configuration config,
|
||||
@Nullable CompatibilityInfo compat) {
|
||||
if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
|
||||
if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
|
||||
+ mResConfiguration.seq + ", newSeq=" + config.seq);
|
||||
return false;
|
||||
}
|
||||
int changes = mResConfiguration.updateFrom(config);
|
||||
// Things might have changed in display manager, so clear the cached displays.
|
||||
mDisplays.clear();
|
||||
DisplayMetrics defaultDisplayMetrics = getDisplayMetrics();
|
||||
try {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES,
|
||||
"ResourcesManager#applyConfigurationToResourcesLocked");
|
||||
|
||||
if (compat != null && (mResCompatibilityInfo == null ||
|
||||
!mResCompatibilityInfo.equals(compat))) {
|
||||
mResCompatibilityInfo = compat;
|
||||
changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT
|
||||
| ActivityInfo.CONFIG_SCREEN_SIZE
|
||||
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
|
||||
}
|
||||
if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
|
||||
if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
|
||||
+ mResConfiguration.seq + ", newSeq=" + config.seq);
|
||||
return false;
|
||||
}
|
||||
int changes = mResConfiguration.updateFrom(config);
|
||||
// Things might have changed in display manager, so clear the cached displays.
|
||||
mDisplays.clear();
|
||||
DisplayMetrics defaultDisplayMetrics = getDisplayMetrics();
|
||||
|
||||
Configuration localeAdjustedConfig = config;
|
||||
final LocaleList configLocales = config.getLocales();
|
||||
if (!configLocales.isEmpty()) {
|
||||
setDefaultLocalesLocked(configLocales);
|
||||
final LocaleList adjustedLocales = LocaleList.getAdjustedDefault();
|
||||
if (adjustedLocales != configLocales) { // has the same result as .equals() in this case
|
||||
// The first locale in the list was not chosen. So we create a modified
|
||||
// configuration with the adjusted locales (which moves the chosen locale to the
|
||||
// front).
|
||||
localeAdjustedConfig = new Configuration();
|
||||
localeAdjustedConfig.setTo(config);
|
||||
localeAdjustedConfig.setLocales(adjustedLocales);
|
||||
// Also adjust the locale list in mResConfiguration, so that the Resources created
|
||||
// later would have the same locale list.
|
||||
if (!mResConfiguration.getLocales().equals(adjustedLocales)) {
|
||||
mResConfiguration.setLocales(adjustedLocales);
|
||||
changes |= ActivityInfo.CONFIG_LOCALE;
|
||||
if (compat != null && (mResCompatibilityInfo == null ||
|
||||
!mResCompatibilityInfo.equals(compat))) {
|
||||
mResCompatibilityInfo = compat;
|
||||
changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT
|
||||
| ActivityInfo.CONFIG_SCREEN_SIZE
|
||||
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
|
||||
}
|
||||
|
||||
Configuration localeAdjustedConfig = config;
|
||||
final LocaleList configLocales = config.getLocales();
|
||||
if (!configLocales.isEmpty()) {
|
||||
setDefaultLocalesLocked(configLocales);
|
||||
final LocaleList adjustedLocales = LocaleList.getAdjustedDefault();
|
||||
if (adjustedLocales
|
||||
!= configLocales) { // has the same result as .equals() in this case
|
||||
// The first locale in the list was not chosen. So we create a modified
|
||||
// configuration with the adjusted locales (which moves the chosen locale to the
|
||||
// front).
|
||||
localeAdjustedConfig = new Configuration();
|
||||
localeAdjustedConfig.setTo(config);
|
||||
localeAdjustedConfig.setLocales(adjustedLocales);
|
||||
// Also adjust the locale list in mResConfiguration, so that the Resources
|
||||
// created later would have the same locale list.
|
||||
if (!mResConfiguration.getLocales().equals(adjustedLocales)) {
|
||||
mResConfiguration.setLocales(adjustedLocales);
|
||||
changes |= ActivityInfo.CONFIG_LOCALE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Resources.updateSystemConfiguration(localeAdjustedConfig, defaultDisplayMetrics, compat);
|
||||
Resources.updateSystemConfiguration(localeAdjustedConfig, defaultDisplayMetrics,
|
||||
compat);
|
||||
|
||||
ApplicationPackageManager.configurationChanged();
|
||||
//Slog.i(TAG, "Configuration changed in " + currentPackageName());
|
||||
ApplicationPackageManager.configurationChanged();
|
||||
//Slog.i(TAG, "Configuration changed in " + currentPackageName());
|
||||
|
||||
Configuration tmpConfig = null;
|
||||
Configuration tmpConfig = null;
|
||||
|
||||
for (int i = mResourceImpls.size() - 1; i >= 0; i--) {
|
||||
ResourcesKey key = mResourceImpls.keyAt(i);
|
||||
ResourcesImpl r = mResourceImpls.valueAt(i).get();
|
||||
if (r != null) {
|
||||
if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
|
||||
+ r + " config to: " + localeAdjustedConfig);
|
||||
int displayId = key.mDisplayId;
|
||||
boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
|
||||
DisplayMetrics dm = defaultDisplayMetrics;
|
||||
final boolean hasOverrideConfiguration = key.hasOverrideConfiguration();
|
||||
if (!isDefaultDisplay || hasOverrideConfiguration) {
|
||||
if (tmpConfig == null) {
|
||||
tmpConfig = new Configuration();
|
||||
for (int i = mResourceImpls.size() - 1; i >= 0; i--) {
|
||||
ResourcesKey key = mResourceImpls.keyAt(i);
|
||||
ResourcesImpl r = mResourceImpls.valueAt(i).get();
|
||||
if (r != null) {
|
||||
if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
|
||||
+ r + " config to: " + localeAdjustedConfig);
|
||||
int displayId = key.mDisplayId;
|
||||
boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
|
||||
DisplayMetrics dm = defaultDisplayMetrics;
|
||||
final boolean hasOverrideConfiguration = key.hasOverrideConfiguration();
|
||||
if (!isDefaultDisplay || hasOverrideConfiguration) {
|
||||
if (tmpConfig == null) {
|
||||
tmpConfig = new Configuration();
|
||||
}
|
||||
tmpConfig.setTo(localeAdjustedConfig);
|
||||
if (!isDefaultDisplay) {
|
||||
dm = getDisplayMetrics(displayId);
|
||||
applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
|
||||
}
|
||||
if (hasOverrideConfiguration) {
|
||||
tmpConfig.updateFrom(key.mOverrideConfiguration);
|
||||
}
|
||||
r.updateConfiguration(tmpConfig, dm, compat);
|
||||
} else {
|
||||
r.updateConfiguration(localeAdjustedConfig, dm, compat);
|
||||
}
|
||||
tmpConfig.setTo(localeAdjustedConfig);
|
||||
if (!isDefaultDisplay) {
|
||||
dm = getDisplayMetrics(displayId);
|
||||
applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
|
||||
}
|
||||
if (hasOverrideConfiguration) {
|
||||
tmpConfig.updateFrom(key.mOverrideConfiguration);
|
||||
}
|
||||
r.updateConfiguration(tmpConfig, dm, compat);
|
||||
//Slog.i(TAG, "Updated app resources " + v.getKey()
|
||||
// + " " + r + ": " + r.getConfiguration());
|
||||
} else {
|
||||
r.updateConfiguration(localeAdjustedConfig, dm, compat);
|
||||
//Slog.i(TAG, "Removing old resources " + v.getKey());
|
||||
mResourceImpls.removeAt(i);
|
||||
}
|
||||
//Slog.i(TAG, "Updated app resources " + v.getKey()
|
||||
// + " " + r + ": " + r.getConfiguration());
|
||||
} else {
|
||||
//Slog.i(TAG, "Removing old resources " + v.getKey());
|
||||
mResourceImpls.removeAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
return changes != 0;
|
||||
return changes != 0;
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,9 +34,7 @@
|
||||
#include <utils/String8.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/Timers.h>
|
||||
#ifdef __ANDROID__
|
||||
#include <cutils/trace.h>
|
||||
#endif
|
||||
#include <utils/Trace.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
@@ -54,14 +52,6 @@
|
||||
_rc; })
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#define MY_TRACE_BEGIN(x) ATRACE_BEGIN(x)
|
||||
#define MY_TRACE_END() ATRACE_END()
|
||||
#else
|
||||
#define MY_TRACE_BEGIN(x)
|
||||
#define MY_TRACE_END()
|
||||
#endif
|
||||
|
||||
using namespace android;
|
||||
|
||||
static const bool kIsDebug = false;
|
||||
@@ -623,7 +613,7 @@ bool AssetManager::appendPathToResTable(const asset_path& ap, bool appAsLib) con
|
||||
ResTable* sharedRes = NULL;
|
||||
bool shared = true;
|
||||
bool onlyEmptyResources = true;
|
||||
MY_TRACE_BEGIN(ap.path.string());
|
||||
ATRACE_NAME(ap.path.string());
|
||||
Asset* idmap = openIdmapLocked(ap);
|
||||
size_t nextEntryIdx = mResources->getTableCount();
|
||||
ALOGV("Looking for resource asset in '%s'\n", ap.path.string());
|
||||
@@ -703,8 +693,6 @@ bool AssetManager::appendPathToResTable(const asset_path& ap, bool appAsLib) con
|
||||
if (idmap != NULL) {
|
||||
delete idmap;
|
||||
}
|
||||
MY_TRACE_END();
|
||||
|
||||
return onlyEmptyResources;
|
||||
}
|
||||
|
||||
@@ -752,6 +740,7 @@ const ResTable* AssetManager::getResTable(bool required) const
|
||||
|
||||
void AssetManager::updateResourceParamsLocked() const
|
||||
{
|
||||
ATRACE_CALL();
|
||||
ResTable* res = mResources;
|
||||
if (!res) {
|
||||
return;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
@@ -5810,6 +5811,10 @@ const DynamicRefTable* ResTable::getDynamicRefTableForCookie(int32_t cookie) con
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool compareResTableConfig(const ResTable_config& a, const ResTable_config& b) {
|
||||
return a.compare(b) < 0;
|
||||
}
|
||||
|
||||
void ResTable::getConfigurations(Vector<ResTable_config>* configs, bool ignoreMipmap,
|
||||
bool ignoreAndroidPackage, bool includeSystemConfigs) const {
|
||||
const size_t packageCount = mPackageGroups.size();
|
||||
@@ -5840,17 +5845,11 @@ void ResTable::getConfigurations(Vector<ResTable_config>* configs, bool ignoreMi
|
||||
ResTable_config cfg;
|
||||
memset(&cfg, 0, sizeof(ResTable_config));
|
||||
cfg.copyFromDtoH(config->config);
|
||||
// only insert unique
|
||||
const size_t N = configs->size();
|
||||
size_t n;
|
||||
for (n = 0; n < N; n++) {
|
||||
if (0 == (*configs)[n].compare(cfg)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if we didn't find it
|
||||
if (n == N) {
|
||||
configs->add(cfg);
|
||||
|
||||
auto iter = std::lower_bound(configs->begin(), configs->end(), cfg,
|
||||
compareResTableConfig);
|
||||
if (iter == configs->end() || iter->compare(cfg) != 0) {
|
||||
configs->insertAt(cfg, std::distance(configs->begin(), iter));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5858,6 +5857,10 @@ void ResTable::getConfigurations(Vector<ResTable_config>* configs, bool ignoreMi
|
||||
}
|
||||
}
|
||||
|
||||
static bool compareString8AndCString(const String8& str, const char* cStr) {
|
||||
return strcmp(str.string(), cStr) < 0;
|
||||
}
|
||||
|
||||
void ResTable::getLocales(Vector<String8>* locales, bool includeSystemLocales) const
|
||||
{
|
||||
Vector<ResTable_config> configs;
|
||||
@@ -5872,15 +5875,11 @@ void ResTable::getLocales(Vector<String8>* locales, bool includeSystemLocales) c
|
||||
char locale[RESTABLE_MAX_LOCALE_LEN];
|
||||
for (size_t i=0; i<I; i++) {
|
||||
configs[i].getBcp47Locale(locale);
|
||||
const size_t J = locales->size();
|
||||
size_t j;
|
||||
for (j=0; j<J; j++) {
|
||||
if (0 == strcmp(locale, (*locales)[j].string())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == J) {
|
||||
locales->add(String8(locale));
|
||||
|
||||
auto iter = std::lower_bound(locales->begin(), locales->end(), locale,
|
||||
compareString8AndCString);
|
||||
if (iter == locales->end() || strcmp(iter->string(), locale) != 0) {
|
||||
locales->insertAt(String8(locale), std::distance(locales->begin(), iter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,20 @@ namespace {
|
||||
*/
|
||||
#include "data/basic/basic_arsc.h"
|
||||
|
||||
/**
|
||||
* Include a binary library resource table.
|
||||
*
|
||||
* Package: com.android.test.basic
|
||||
*/
|
||||
#include "data/lib/lib_arsc.h"
|
||||
|
||||
/**
|
||||
* Include a system resource table.
|
||||
*
|
||||
* Package: android
|
||||
*/
|
||||
#include "data/system/system_arsc.h"
|
||||
|
||||
TEST(ResTableTest, shouldLoadSuccessfully) {
|
||||
ResTable table;
|
||||
ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
|
||||
@@ -324,4 +336,25 @@ TEST(ResTableTest, ShareButDontModifyResTable) {
|
||||
ASSERT_EQ(uint32_t(600), val.data);
|
||||
}
|
||||
|
||||
TEST(ResTableTest, GetConfigurationsReturnsUniqueList) {
|
||||
ResTable table;
|
||||
ASSERT_EQ(NO_ERROR, table.add(system_arsc, system_arsc_len));
|
||||
ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
|
||||
|
||||
ResTable_config configSv;
|
||||
memset(&configSv, 0, sizeof(configSv));
|
||||
configSv.language[0] = 's';
|
||||
configSv.language[1] = 'v';
|
||||
|
||||
Vector<ResTable_config> configs;
|
||||
table.getConfigurations(&configs);
|
||||
|
||||
EXPECT_EQ(1, std::count(configs.begin(), configs.end(), configSv));
|
||||
|
||||
Vector<String8> locales;
|
||||
table.getLocales(&locales);
|
||||
|
||||
EXPECT_EQ(1, std::count(locales.begin(), locales.end(), String8("sv")));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace android {
|
||||
enum { MAY_NOT_BE_BAG = false };
|
||||
|
||||
static inline bool operator==(const android::ResTable_config& a, const android::ResTable_config& b) {
|
||||
return memcmp(&a, &b, sizeof(a)) == 0;
|
||||
return a.compare(b) == 0;
|
||||
}
|
||||
|
||||
static inline ::std::ostream& operator<<(::std::ostream& out, const android::ResTable_config& c) {
|
||||
|
||||
@@ -33,6 +33,12 @@ namespace style {
|
||||
};
|
||||
}
|
||||
|
||||
namespace integer {
|
||||
enum {
|
||||
number = 0x01030000, // sv
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace R
|
||||
} // namespace android
|
||||
|
||||
|
||||
20
libs/androidfw/tests/data/system/res/values-sv/values.xml
Normal file
20
libs/androidfw/tests/data/system/res/values-sv/values.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<public type="integer" name="number" id="0x01030000" />
|
||||
<integer name="number">1</integer>
|
||||
</resources>
|
||||
@@ -1,8 +1,8 @@
|
||||
unsigned char system_arsc[] = {
|
||||
0x02, 0x00, 0x0c, 0x00, 0x18, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x0c, 0x00, 0xf8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xf0, 0x02, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xd0, 0x03, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
|
||||
0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -25,26 +25,33 @@ unsigned char system_arsc[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
|
||||
0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00,
|
||||
0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
|
||||
0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x78, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0c, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00,
|
||||
0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00,
|
||||
0x00, 0x00, 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00,
|
||||
0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x5e, 0x00,
|
||||
0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x2d, 0x00, 0x70, 0x00,
|
||||
0x72, 0x00, 0x69, 0x00, 0x76, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x84, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
|
||||
0x0a, 0x00, 0x62, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x67, 0x00,
|
||||
0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x00, 0x00,
|
||||
0x0a, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x67, 0x00,
|
||||
0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x00, 0x00,
|
||||
0x09, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00,
|
||||
0x2e, 0x00, 0x4f, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40,
|
||||
0x01, 0x02, 0x44, 0x00, 0x84, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
|
||||
0x2e, 0x00, 0x4f, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x00, 0x00, 0x06, 0x00,
|
||||
0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
|
||||
0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x4c, 0x00, 0x8c, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
|
||||
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -55,15 +62,27 @@ unsigned char system_arsc[] = {
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00,
|
||||
0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x44, 0x00,
|
||||
0x70, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x4c, 0x00,
|
||||
0x78, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0xff, 0xff,
|
||||
0x01, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xff
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
|
||||
0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x01, 0x01,
|
||||
0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x10, 0x00,
|
||||
0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x4c, 0x00, 0x60, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
|
||||
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
|
||||
0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
unsigned int system_arsc_len = 792;
|
||||
unsigned int system_arsc_len = 1016;
|
||||
|
||||
Reference in New Issue
Block a user