@@ -4466,6 +4466,37 @@ static int getMinSdkVersion(const Bundle* bundle) {
44664466 return 0 ;
44674467}
44684468
4469+ static bool shouldGenerateVersionedResource (const sp<ResourceTable::ConfigList>& configList,
4470+ const ConfigDescription& sourceConfig,
4471+ const int sdkVersionToGenerate) {
4472+ assert (sdkVersionToGenerate > sourceConfig.sdkVersion );
4473+ const DefaultKeyedVector<ConfigDescription, sp<ResourceTable::Entry>>& entries
4474+ = configList->getEntries ();
4475+ ssize_t idx = entries.indexOfKey (sourceConfig);
4476+
4477+ // The source config came from this list, so it should be here.
4478+ assert (idx >= 0 );
4479+
4480+ idx += 1 ;
4481+ if (static_cast <size_t >(idx) >= entries.size ()) {
4482+ // This is the last configuration, so we should generate a versioned resource.
4483+ return true ;
4484+ }
4485+
4486+ const ConfigDescription& nextConfig = entries.keyAt (idx);
4487+
4488+ // Build a configuration that is the same as the source config,
4489+ // but with the SDK level of the next config. If they are the same,
4490+ // then they only differ in SDK level. If the next configs SDK level is
4491+ // higher than the one we want to generate, we must generate it.
4492+ ConfigDescription tempConfig (sourceConfig);
4493+ tempConfig.sdkVersion = nextConfig.sdkVersion ;
4494+ if (nextConfig == tempConfig) {
4495+ return sdkVersionToGenerate < nextConfig.sdkVersion ;
4496+ }
4497+ return false ;
4498+ }
4499+
44694500/* *
44704501 * Modifies the entries in the resource table to account for compatibility
44714502 * issues with older versions of Android.
@@ -4574,6 +4605,11 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle) {
45744605 for (size_t i = 0 ; i < sdkCount; i++) {
45754606 const int sdkLevel = attributesToRemove.keyAt (i);
45764607
4608+ if (!shouldGenerateVersionedResource (c, config, sdkLevel)) {
4609+ // There is a style that will override this generated one.
4610+ continue ;
4611+ }
4612+
45774613 // Duplicate the entry under the same configuration
45784614 // but with sdkVersion == sdkLevel.
45794615 ConfigDescription newConfig (config);
@@ -4610,13 +4646,7 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle) {
46104646
46114647 const size_t entriesToAddCount = entriesToAdd.size ();
46124648 for (size_t i = 0 ; i < entriesToAddCount; i++) {
4613- if (entries.indexOfKey (entriesToAdd[i].key ) >= 0 ) {
4614- // An entry already exists for this config.
4615- // That means that any attributes that were
4616- // defined in L in the original bag will be overriden
4617- // anyways on L devices, so we do nothing.
4618- continue ;
4619- }
4649+ assert (entries.indexOfKey (entriesToAdd[i].key ) < 0 );
46204650
46214651 if (bundle->getVerbose ()) {
46224652 entriesToAdd[i].value ->getPos ()
@@ -4662,8 +4692,7 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle,
46624692 }
46634693
46644694 sp<XMLNode> newRoot = NULL ;
4665- ConfigDescription newConfig (target->getGroupEntry ().toParams ());
4666- newConfig.sdkVersion = SDK_LOLLIPOP_MR1;
4695+ int sdkVersionToGenerate = SDK_LOLLIPOP_MR1;
46674696
46684697 Vector<sp<XMLNode> > nodesToVisit;
46694698 nodesToVisit.push (root);
@@ -4689,9 +4718,7 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle,
46894718 // Find the smallest sdk version that we need to synthesize for
46904719 // and do that one. Subsequent versions will be processed on
46914720 // the next pass.
4692- if (sdkLevel < newConfig.sdkVersion ) {
4693- newConfig.sdkVersion = sdkLevel;
4694- }
4721+ sdkVersionToGenerate = std::min (sdkLevel, sdkVersionToGenerate);
46954722
46964723 if (bundle->getVerbose ()) {
46974724 SourcePos (node->getFilename (), node->getStartLineNumber ()).printf (
@@ -4721,8 +4748,10 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle,
47214748 // Look to see if we already have an overriding v21 configuration.
47224749 sp<ConfigList> cl = getConfigList (String16 (mAssets ->getPackage ()),
47234750 String16 (target->getResourceType ()), resourceName);
4724- if (cl-> getEntries (). indexOfKey (newConfig) < 0 ) {
4751+ if (shouldGenerateVersionedResource (cl, config, sdkVersionToGenerate) ) {
47254752 // We don't have an overriding entry for v21, so we must duplicate this one.
4753+ ConfigDescription newConfig (config);
4754+ newConfig.sdkVersion = sdkVersionToGenerate;
47264755 sp<AaptFile> newFile = new AaptFile (target->getSourceFile (),
47274756 AaptGroupEntry (newConfig), target->getResourceType ());
47284757 String8 resPath = String8::format (" res/%s/%s" ,
@@ -4760,7 +4789,8 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle,
47604789 return NO_ERROR;
47614790}
47624791
4763- void ResourceTable::getDensityVaryingResources (KeyedVector<Symbol, Vector<SymbolDefinition> >& resources) {
4792+ void ResourceTable::getDensityVaryingResources (
4793+ KeyedVector<Symbol, Vector<SymbolDefinition> >& resources) {
47644794 const ConfigDescription nullConfig;
47654795
47664796 const size_t packageCount = mOrderedPackages .size ();
@@ -4771,19 +4801,23 @@ void ResourceTable::getDensityVaryingResources(KeyedVector<Symbol, Vector<Symbol
47714801 const Vector<sp<ConfigList> >& configs = types[t]->getOrderedConfigs ();
47724802 const size_t configCount = configs.size ();
47734803 for (size_t c = 0 ; c < configCount; c++) {
4774- const DefaultKeyedVector<ConfigDescription, sp<Entry> >& configEntries = configs[c]->getEntries ();
4804+ const DefaultKeyedVector<ConfigDescription, sp<Entry> >& configEntries
4805+ = configs[c]->getEntries ();
47754806 const size_t configEntryCount = configEntries.size ();
47764807 for (size_t ce = 0 ; ce < configEntryCount; ce++) {
47774808 const ConfigDescription& config = configEntries.keyAt (ce);
47784809 if (AaptConfig::isDensityOnly (config)) {
47794810 // This configuration only varies with regards to density.
4780- const Symbol symbol (mOrderedPackages [p]->getName (),
4811+ const Symbol symbol (
4812+ mOrderedPackages [p]->getName (),
47814813 types[t]->getName (),
47824814 configs[c]->getName (),
4783- getResId (mOrderedPackages [p], types[t], configs[c]->getEntryIndex ()));
4815+ getResId (mOrderedPackages [p], types[t],
4816+ configs[c]->getEntryIndex ()));
47844817
47854818 const sp<Entry>& entry = configEntries.valueAt (ce);
4786- AaptUtil::appendValue (resources, symbol, SymbolDefinition (symbol, config, entry->getPos ()));
4819+ AaptUtil::appendValue (resources, symbol,
4820+ SymbolDefinition (symbol, config, entry->getPos ()));
47874821 }
47884822 }
47894823 }
0 commit comments