From 834f4e6c928d5e74202fc4b2e11510bcf4f79d8f Mon Sep 17 00:00:00 2001 From: Yurii Zubrytskyi Date: Thu, 21 Oct 2021 09:13:18 -0700 Subject: [PATCH 1/2] [aapt2] Fix finalized resources removal The code used to expect all original staged resources to get parsed before their finalized version. Looks like that's not the actual case, and parsing code needs to expect those to come later, and preserve the information that they aren't needed anymore Bug: 203779955 Test: manual, aapt2 dump resources Change-Id: I6d9efe2eb7b406d05ca49a0a6ed745a1c509e2ef --- .../format/binary/BinaryResourceParser.cpp | 18 +++++++++++++++--- .../aapt2/format/binary/BinaryResourceParser.h | 4 ++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp index 72eaa3561a023..a8845ef96bc36 100644 --- a/tools/aapt2/format/binary/BinaryResourceParser.cpp +++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp @@ -120,6 +120,13 @@ bool BinaryResourceParser::Parse() { static_cast(parser.chunk()->type))); } } + + if (!staged_entries_to_remove_.empty()) { + diag_->Error(DiagMessage(source_) << "didn't find " << staged_entries_to_remove_.size() + << " original staged resources"); + return false; + } + return true; } @@ -393,6 +400,12 @@ bool BinaryResourceParser::ParseType(const ResourceTablePackage* package, return false; } + if (const auto to_remove_it = staged_entries_to_remove_.find({name, res_id}); + to_remove_it != staged_entries_to_remove_.end()) { + staged_entries_to_remove_.erase(to_remove_it); + continue; + } + NewResourceBuilder res_builder(name); res_builder.SetValue(std::move(resource_value), config) .SetId(res_id, OnIdConflict::CREATE_ENTRY) @@ -533,9 +546,8 @@ bool BinaryResourceParser::ParseStagedAliases(const ResChunk_header* chunk) { // Since a the finalized resource entry is cloned and added to the resource table under the // staged resource id, remove the cloned resource entry from the table. if (!table_->RemoveResource(resource_name, staged_id)) { - diag_->Error(DiagMessage(source_) << "failed to find resource entry for staged " - << " resource ID " << staged_id); - return false; + // If we haven't seen this resource yet let's add a record to skip it when parsing. + staged_entries_to_remove_.insert({resource_name, staged_id}); } } return true; diff --git a/tools/aapt2/format/binary/BinaryResourceParser.h b/tools/aapt2/format/binary/BinaryResourceParser.h index cd71d160703ad..1c83166c5cce9 100644 --- a/tools/aapt2/format/binary/BinaryResourceParser.h +++ b/tools/aapt2/format/binary/BinaryResourceParser.h @@ -119,6 +119,10 @@ class BinaryResourceParser { // A mapping of resource ID to type spec flags. std::unordered_map entry_type_spec_flags_; + + // A collection of staged resources that got finalized already and we're supposed to prune - + // but the original staged resource record hasn't been parsed yet. + std::set> staged_entries_to_remove_; }; } // namespace aapt From e9e1d94c4af4808bb779629e6add3ae35f4ad507 Mon Sep 17 00:00:00 2001 From: Yurii Zubrytskyi Date: Thu, 21 Oct 2021 01:37:23 -0700 Subject: [PATCH 2/2] [res] Finalize resources in SC-v2 RESTRICT AUTOMERGE + modify the finalization script to support new mode - staging-public-group + support removed items Bug: 203782582 Test: manual, aapt2 dump on the generated resources Change-Id: I507f85737d0ba5bf074dd8d98633087ff33c8382 --- core/api/current.txt | 8 +-- core/res/res/values/public.xml | 85 ++++-------------------------- tools/finalize_res/finalize_res.py | 35 +++++++++--- 3 files changed, 42 insertions(+), 86 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index e015169cf69ae..cf2faae909716 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -1298,7 +1298,7 @@ package android { field public static final int shortcutLongLabel = 16844074; // 0x101052a field public static final int shortcutShortLabel = 16844073; // 0x1010529 field public static final int shouldDisableView = 16843246; // 0x10101ee - field public static final int shouldUseDefaultUnfoldTransition; + field public static final int shouldUseDefaultUnfoldTransition = 16844364; // 0x101064c field public static final int showAsAction = 16843481; // 0x10102d9 field public static final int showDefault = 16843258; // 0x10101fa field public static final int showDividers = 16843561; // 0x1010329 @@ -2014,9 +2014,9 @@ package android { public static final class R.id { ctor public R.id(); field public static final int accessibilityActionContextClick = 16908348; // 0x102003c - field public static final int accessibilityActionDragCancel; - field public static final int accessibilityActionDragDrop; - field public static final int accessibilityActionDragStart; + field public static final int accessibilityActionDragCancel = 16908375; // 0x1020057 + field public static final int accessibilityActionDragDrop = 16908374; // 0x1020056 + field public static final int accessibilityActionDragStart = 16908373; // 0x1020055 field public static final int accessibilityActionHideTooltip = 16908357; // 0x1020045 field public static final int accessibilityActionImeEnter = 16908372; // 0x1020054 field public static final int accessibilityActionMoveWindow = 16908354; // 0x1020042 diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 7d489049d112f..1e30131ae6f98 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1235,7 +1235,6 @@ - @@ -3202,89 +3201,23 @@ - + - + - + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + diff --git a/tools/finalize_res/finalize_res.py b/tools/finalize_res/finalize_res.py index aaf01875024ec..724443c01852c 100755 --- a/tools/finalize_res/finalize_res.py +++ b/tools/finalize_res/finalize_res.py @@ -17,6 +17,7 @@ """ Finalize resource values in tags +and convert those to Usage: finalize_res.py core/res/res/values/public.xml public_finalized.xml """ @@ -24,18 +25,40 @@ Usage: finalize_res.py core/res/res/values/public.xml public_finalized.xml import re, sys, codecs def finalize_item(raw): - global _type, _id - _id += 1 - return '' % (_type, raw.group(1), '0x{0:0{1}x}'.format(_id-1,8)) + global _type_ids, _type + id = _type_ids[_type] + _type_ids[_type] += 1 + name = raw.group(1) + val = '' % (_type, name, '0x{0:0{1}x}'.format(id,8)) + if re.match(r'_*removed.+', name): + val = '' + return val def finalize_group(raw): - global _type, _id + global _type_ids, _type _type = raw.group(1) - _id = int(raw.group(2), 16) - return re.sub(r'', finalize_item, raw.group(3)) + id = int(raw.group(2), 16) + _type_ids[_type] = _type_ids.get(_type, id) + (res, count) = re.subn(r' {0,2}', finalize_item, raw.group(3)) + if count > 0: + res = raw.group(0).replace("staging-public-group", "staging-public-group-final") + '\n' + res + return res + +def collect_ids(raw): + global _type_ids + for m in re.finditer(r'', raw): + type = m.group(1) + id = int(m.group(2), 16) + _type_ids[type] = max(id + 1, _type_ids.get(type, 0)) with open(sys.argv[1]) as f: + global _type_ids, _type + _type_ids = {} raw = f.read() + collect_ids(raw) raw = re.sub(r'(.+?)', finalize_group, raw, flags=re.DOTALL) + raw = re.sub(r' *\n', '\n', raw) + raw = re.sub(r'\n{3,}', '\n\n', raw) with open(sys.argv[2], "w") as f: f.write(raw) +