xref: /aosp_15_r20/frameworks/base/tools/aapt2/format/proto/ProtoDeserialize.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "format/proto/ProtoDeserialize.h"
18 
19 #include "Resource.h"
20 #include "ResourceTable.h"
21 #include "ResourceUtils.h"
22 #include "ResourceValues.h"
23 #include "ValueVisitor.h"
24 #include "android-base/logging.h"
25 #include "android-base/macros.h"
26 #include "androidfw/Locale.h"
27 #include "androidfw/ResourceTypes.h"
28 #include "androidfw/Util.h"
29 
30 using ::android::ConfigDescription;
31 using ::android::LocaleValue;
32 using ::android::ResStringPool;
33 
34 using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
35 
36 namespace aapt {
37 
38 namespace {
39 
40 class ReferenceIdToNameVisitor : public DescendingValueVisitor {
41  public:
42   using DescendingValueVisitor::Visit;
43 
ReferenceIdToNameVisitor(const std::map<ResourceId,ResourceNameRef> * mapping)44   explicit ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceNameRef>* mapping)
45       : mapping_(mapping) {
46     CHECK(mapping_ != nullptr);
47   }
48 
Visit(Reference * reference)49   void Visit(Reference* reference) override {
50     if (!reference->id || !reference->id.value().is_valid()) {
51       return;
52     }
53 
54     ResourceId id = reference->id.value();
55     auto cache_iter = mapping_->find(id);
56     if (cache_iter != mapping_->end()) {
57       reference->name = cache_iter->second.ToResourceName();
58     }
59   }
60 
61  private:
62   DISALLOW_COPY_AND_ASSIGN(ReferenceIdToNameVisitor);
63 
64   const std::map<ResourceId, ResourceNameRef>* mapping_;
65 };
66 
67 }  // namespace
68 
DeserializeConfigFromPb(const pb::Configuration & pb_config,ConfigDescription * out_config,std::string * out_error)69 bool DeserializeConfigFromPb(const pb::Configuration& pb_config, ConfigDescription* out_config,
70                              std::string* out_error) {
71   out_config->mcc = static_cast<uint16_t>(pb_config.mcc());
72   out_config->mnc = static_cast<uint16_t>(pb_config.mnc());
73 
74   if (!pb_config.locale().empty()) {
75     LocaleValue lv;
76     if (!lv.InitFromBcp47Tag(pb_config.locale())) {
77       std::ostringstream error;
78       error << "configuration has invalid locale '" << pb_config.locale() << "'";
79       *out_error = error.str();
80       return false;
81     }
82     lv.WriteTo(out_config);
83   }
84 
85   switch (pb_config.layout_direction()) {
86     case pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_LTR:
87       out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_LAYOUTDIR) |
88                                  ConfigDescription::LAYOUTDIR_LTR;
89       break;
90 
91     case pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_RTL:
92       out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_LAYOUTDIR) |
93                                  ConfigDescription::LAYOUTDIR_RTL;
94       break;
95 
96     default:
97       break;
98   }
99 
100   out_config->smallestScreenWidthDp = static_cast<uint16_t>(pb_config.smallest_screen_width_dp());
101   out_config->screenWidthDp = static_cast<uint16_t>(pb_config.screen_width_dp());
102   out_config->screenHeightDp = static_cast<uint16_t>(pb_config.screen_height_dp());
103 
104   switch (pb_config.screen_layout_size()) {
105     case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_SMALL:
106       out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) |
107                                  ConfigDescription::SCREENSIZE_SMALL;
108       break;
109 
110     case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_NORMAL:
111       out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) |
112                                  ConfigDescription::SCREENSIZE_NORMAL;
113       break;
114 
115     case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_LARGE:
116       out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) |
117                                  ConfigDescription::SCREENSIZE_LARGE;
118       break;
119 
120     case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_XLARGE:
121       out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) |
122                                  ConfigDescription::SCREENSIZE_XLARGE;
123       break;
124 
125     default:
126       break;
127   }
128 
129   switch (pb_config.screen_layout_long()) {
130     case pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_LONG:
131       out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENLONG) |
132                                  ConfigDescription::SCREENLONG_YES;
133       break;
134 
135     case pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_NOTLONG:
136       out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENLONG) |
137                                  ConfigDescription::SCREENLONG_NO;
138       break;
139 
140     default:
141       break;
142   }
143 
144   switch (pb_config.screen_round()) {
145     case pb::Configuration_ScreenRound_SCREEN_ROUND_ROUND:
146       out_config->screenLayout2 =
147           (out_config->screenLayout2 & ~ConfigDescription::MASK_SCREENROUND) |
148           ConfigDescription::SCREENROUND_YES;
149       break;
150 
151     case pb::Configuration_ScreenRound_SCREEN_ROUND_NOTROUND:
152       out_config->screenLayout2 =
153           (out_config->screenLayout2 & ~ConfigDescription::MASK_SCREENROUND) |
154           ConfigDescription::SCREENROUND_NO;
155       break;
156 
157     default:
158       break;
159   }
160 
161   switch (pb_config.wide_color_gamut()) {
162     case pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_WIDECG:
163       out_config->colorMode = (out_config->colorMode & ~ConfigDescription::MASK_WIDE_COLOR_GAMUT) |
164                               ConfigDescription::WIDE_COLOR_GAMUT_YES;
165       break;
166 
167     case pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_NOWIDECG:
168       out_config->colorMode = (out_config->colorMode & ~ConfigDescription::MASK_WIDE_COLOR_GAMUT) |
169                               ConfigDescription::WIDE_COLOR_GAMUT_NO;
170       break;
171 
172     default:
173       break;
174   }
175 
176   switch (pb_config.hdr()) {
177     case pb::Configuration_Hdr_HDR_HIGHDR:
178       out_config->colorMode =
179           (out_config->colorMode & ~ConfigDescription::MASK_HDR) | ConfigDescription::HDR_YES;
180       break;
181 
182     case pb::Configuration_Hdr_HDR_LOWDR:
183       out_config->colorMode =
184           (out_config->colorMode & ~ConfigDescription::MASK_HDR) | ConfigDescription::HDR_NO;
185       break;
186 
187     default:
188       break;
189   }
190 
191   switch (pb_config.orientation()) {
192     case pb::Configuration_Orientation_ORIENTATION_PORT:
193       out_config->orientation = ConfigDescription::ORIENTATION_PORT;
194       break;
195 
196     case pb::Configuration_Orientation_ORIENTATION_LAND:
197       out_config->orientation = ConfigDescription::ORIENTATION_LAND;
198       break;
199 
200     case pb::Configuration_Orientation_ORIENTATION_SQUARE:
201       out_config->orientation = ConfigDescription::ORIENTATION_SQUARE;
202       break;
203 
204     default:
205       break;
206   }
207 
208   switch (pb_config.ui_mode_type()) {
209     case pb::Configuration_UiModeType_UI_MODE_TYPE_NORMAL:
210       out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
211                            ConfigDescription::UI_MODE_TYPE_NORMAL;
212       break;
213 
214     case pb::Configuration_UiModeType_UI_MODE_TYPE_DESK:
215       out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
216                            ConfigDescription::UI_MODE_TYPE_DESK;
217       break;
218 
219     case pb::Configuration_UiModeType_UI_MODE_TYPE_CAR:
220       out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
221                            ConfigDescription::UI_MODE_TYPE_CAR;
222       break;
223 
224     case pb::Configuration_UiModeType_UI_MODE_TYPE_TELEVISION:
225       out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
226                            ConfigDescription::UI_MODE_TYPE_TELEVISION;
227       break;
228 
229     case pb::Configuration_UiModeType_UI_MODE_TYPE_APPLIANCE:
230       out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
231                            ConfigDescription::UI_MODE_TYPE_APPLIANCE;
232       break;
233 
234     case pb::Configuration_UiModeType_UI_MODE_TYPE_WATCH:
235       out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
236                            ConfigDescription::UI_MODE_TYPE_WATCH;
237       break;
238 
239     case pb::Configuration_UiModeType_UI_MODE_TYPE_VRHEADSET:
240       out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
241                            ConfigDescription::UI_MODE_TYPE_VR_HEADSET;
242       break;
243 
244     default:
245       break;
246   }
247 
248   switch (pb_config.ui_mode_night()) {
249     case pb::Configuration_UiModeNight_UI_MODE_NIGHT_NIGHT:
250       out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_NIGHT) |
251                            ConfigDescription::UI_MODE_NIGHT_YES;
252       break;
253 
254     case pb::Configuration_UiModeNight_UI_MODE_NIGHT_NOTNIGHT:
255       out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_NIGHT) |
256                            ConfigDescription::UI_MODE_NIGHT_NO;
257       break;
258 
259     default:
260       break;
261   }
262 
263   out_config->density = static_cast<uint16_t>(pb_config.density());
264 
265   switch (pb_config.touchscreen()) {
266     case pb::Configuration_Touchscreen_TOUCHSCREEN_NOTOUCH:
267       out_config->touchscreen = ConfigDescription::TOUCHSCREEN_NOTOUCH;
268       break;
269 
270     case pb::Configuration_Touchscreen_TOUCHSCREEN_STYLUS:
271       out_config->touchscreen = ConfigDescription::TOUCHSCREEN_STYLUS;
272       break;
273 
274     case pb::Configuration_Touchscreen_TOUCHSCREEN_FINGER:
275       out_config->touchscreen = ConfigDescription::TOUCHSCREEN_FINGER;
276       break;
277 
278     default:
279       break;
280   }
281 
282   switch (pb_config.keys_hidden()) {
283     case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSEXPOSED:
284       out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) |
285                                ConfigDescription::KEYSHIDDEN_NO;
286       break;
287 
288     case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSHIDDEN:
289       out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) |
290                                ConfigDescription::KEYSHIDDEN_YES;
291       break;
292 
293     case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSSOFT:
294       out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) |
295                                ConfigDescription::KEYSHIDDEN_SOFT;
296       break;
297 
298     default:
299       break;
300   }
301 
302   switch (pb_config.keyboard()) {
303     case pb::Configuration_Keyboard_KEYBOARD_NOKEYS:
304       out_config->keyboard = ConfigDescription::KEYBOARD_NOKEYS;
305       break;
306 
307     case pb::Configuration_Keyboard_KEYBOARD_QWERTY:
308       out_config->keyboard = ConfigDescription::KEYBOARD_QWERTY;
309       break;
310 
311     case pb::Configuration_Keyboard_KEYBOARD_TWELVEKEY:
312       out_config->keyboard = ConfigDescription::KEYBOARD_12KEY;
313       break;
314 
315     default:
316       break;
317   }
318 
319   switch (pb_config.nav_hidden()) {
320     case pb::Configuration_NavHidden_NAV_HIDDEN_NAVEXPOSED:
321       out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_NAVHIDDEN) |
322                                ConfigDescription::NAVHIDDEN_NO;
323       break;
324 
325     case pb::Configuration_NavHidden_NAV_HIDDEN_NAVHIDDEN:
326       out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_NAVHIDDEN) |
327                                ConfigDescription::NAVHIDDEN_YES;
328       break;
329 
330     default:
331       break;
332   }
333 
334   switch (pb_config.navigation()) {
335     case pb::Configuration_Navigation_NAVIGATION_NONAV:
336       out_config->navigation = ConfigDescription::NAVIGATION_NONAV;
337       break;
338 
339     case pb::Configuration_Navigation_NAVIGATION_DPAD:
340       out_config->navigation = ConfigDescription::NAVIGATION_DPAD;
341       break;
342 
343     case pb::Configuration_Navigation_NAVIGATION_TRACKBALL:
344       out_config->navigation = ConfigDescription::NAVIGATION_TRACKBALL;
345       break;
346 
347     case pb::Configuration_Navigation_NAVIGATION_WHEEL:
348       out_config->navigation = ConfigDescription::NAVIGATION_WHEEL;
349       break;
350 
351     default:
352       break;
353   }
354 
355   out_config->screenWidth = static_cast<uint16_t>(pb_config.screen_width());
356   out_config->screenHeight = static_cast<uint16_t>(pb_config.screen_height());
357   out_config->sdkVersion = static_cast<uint16_t>(pb_config.sdk_version());
358   out_config->grammaticalInflection = pb_config.grammatical_gender();
359   return true;
360 }
361 
DeserializeSourceFromPb(const pb::Source & pb_source,const ResStringPool & src_pool,android::Source * out_source)362 static void DeserializeSourceFromPb(const pb::Source& pb_source, const ResStringPool& src_pool,
363                                     android::Source* out_source) {
364   out_source->path = android::util::GetString(src_pool, pb_source.path_idx());
365   out_source->line = static_cast<size_t>(pb_source.position().line_number());
366 }
367 
DeserializeVisibilityFromPb(const pb::Visibility::Level & pb_level)368 static Visibility::Level DeserializeVisibilityFromPb(const pb::Visibility::Level& pb_level) {
369   switch (pb_level) {
370     case pb::Visibility::PRIVATE:
371       return Visibility::Level::kPrivate;
372     case pb::Visibility::PUBLIC:
373       return Visibility::Level::kPublic;
374     default:
375       break;
376   }
377   return Visibility::Level::kUndefined;
378 }
379 
DeserializeOverlayableItemFromPb(const pb::OverlayableItem & pb_overlayable,const android::ResStringPool & src_pool,OverlayableItem * out_overlayable,std::string * out_error)380 bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable,
381                                       const android::ResStringPool& src_pool,
382                                       OverlayableItem* out_overlayable, std::string* out_error) {
383   for (const int policy : pb_overlayable.policy()) {
384     switch (policy) {
385       case pb::OverlayableItem::PUBLIC:
386         out_overlayable->policies |= PolicyFlags::PUBLIC;
387         break;
388       case pb::OverlayableItem::SYSTEM:
389         out_overlayable->policies |= PolicyFlags::SYSTEM_PARTITION;
390         break;
391       case pb::OverlayableItem::VENDOR:
392         out_overlayable->policies |= PolicyFlags::VENDOR_PARTITION;
393         break;
394       case pb::OverlayableItem::PRODUCT:
395         out_overlayable->policies |= PolicyFlags::PRODUCT_PARTITION;
396         break;
397       case pb::OverlayableItem::SIGNATURE:
398         out_overlayable->policies |= PolicyFlags::SIGNATURE;
399         break;
400       case pb::OverlayableItem::ODM:
401         out_overlayable->policies |= PolicyFlags::ODM_PARTITION;
402         break;
403       case pb::OverlayableItem::OEM:
404         out_overlayable->policies |= PolicyFlags::OEM_PARTITION;
405         break;
406       case pb::OverlayableItem::ACTOR:
407         out_overlayable->policies |= PolicyFlags::ACTOR_SIGNATURE;
408         break;
409       case pb::OverlayableItem::CONFIG_SIGNATURE:
410         out_overlayable->policies |= PolicyFlags::CONFIG_SIGNATURE;
411         break;
412       default:
413         *out_error = "unknown overlayable policy";
414         return false;
415     }
416   }
417 
418   if (pb_overlayable.has_source()) {
419     DeserializeSourceFromPb(pb_overlayable.source(), src_pool, &out_overlayable->source);
420   }
421 
422   out_overlayable->comment = pb_overlayable.comment();
423   return true;
424 }
425 
DeserializePackageFromPb(const pb::Package & pb_package,const ResStringPool & src_pool,io::IFileCollection * files,const std::vector<std::shared_ptr<Overlayable>> & overlayables,ResourceTable * out_table,std::string * out_error)426 static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStringPool& src_pool,
427                                      io::IFileCollection* files,
428                                      const std::vector<std::shared_ptr<Overlayable>>& overlayables,
429                                      ResourceTable* out_table, std::string* out_error) {
430   std::map<ResourceId, ResourceNameRef> id_index;
431 
432   ResourceTablePackage* pkg = out_table->FindOrCreatePackage(pb_package.package_name());
433   for (const pb::Type& pb_type : pb_package.type()) {
434     auto res_type = ParseResourceNamedType(pb_type.name());
435     if (!res_type) {
436       std::ostringstream error;
437       error << "unknown type '" << pb_type.name() << "'";
438       *out_error = error.str();
439       return false;
440     }
441 
442     ResourceTableType* type = pkg->FindOrCreateType(*res_type);
443 
444     for (const pb::Entry& pb_entry : pb_type.entry()) {
445       ResourceEntry* entry = type->CreateEntry(pb_entry.name());
446       const ResourceId resource_id(
447           pb_package.has_package_id() ? static_cast<uint8_t>(pb_package.package_id().id()) : 0u,
448           pb_type.has_type_id() ? static_cast<uint8_t>(pb_type.type_id().id()) : 0u,
449           pb_entry.has_entry_id() ? static_cast<uint16_t>(pb_entry.entry_id().id()) : 0u);
450       if (resource_id.id != 0u) {
451         entry->id = resource_id;
452       }
453 
454       // Deserialize the symbol status (public/private with source and comments).
455       if (pb_entry.has_visibility()) {
456         const pb::Visibility& pb_visibility = pb_entry.visibility();
457         if (pb_visibility.has_source()) {
458           DeserializeSourceFromPb(pb_visibility.source(), src_pool, &entry->visibility.source);
459         }
460         entry->visibility.comment = pb_visibility.comment();
461         entry->visibility.staged_api = pb_visibility.staged_api();
462 
463         const Visibility::Level level = DeserializeVisibilityFromPb(pb_visibility.level());
464         entry->visibility.level = level;
465         if (level == Visibility::Level::kPublic) {
466           // Propagate the public visibility up to the Type.
467           type->visibility_level = Visibility::Level::kPublic;
468         } else if (level == Visibility::Level::kPrivate) {
469           // Only propagate if no previous state was assigned.
470           if (type->visibility_level == Visibility::Level::kUndefined) {
471             type->visibility_level = Visibility::Level::kPrivate;
472           }
473         }
474       }
475 
476       if (pb_entry.has_allow_new()) {
477         const pb::AllowNew& pb_allow_new = pb_entry.allow_new();
478 
479         AllowNew allow_new;
480         if (pb_allow_new.has_source()) {
481           DeserializeSourceFromPb(pb_allow_new.source(), src_pool, &allow_new.source);
482         }
483         allow_new.comment = pb_allow_new.comment();
484         entry->allow_new = std::move(allow_new);
485       }
486 
487       if (pb_entry.has_overlayable_item()) {
488         // Find the overlayable to which this item belongs
489         pb::OverlayableItem pb_overlayable_item = pb_entry.overlayable_item();
490         if (pb_overlayable_item.overlayable_idx() >= overlayables.size()) {
491           *out_error =
492               android::base::StringPrintf("invalid overlayable_idx value %d for entry %s/%s",
493                                           pb_overlayable_item.overlayable_idx(),
494                                           pb_type.name().c_str(), pb_entry.name().c_str());
495           return false;
496         }
497 
498         OverlayableItem overlayable_item(overlayables[pb_overlayable_item.overlayable_idx()]);
499         if (!DeserializeOverlayableItemFromPb(pb_overlayable_item, src_pool, &overlayable_item,
500                                               out_error)) {
501           return false;
502         }
503         entry->overlayable_item = std::move(overlayable_item);
504       }
505 
506       if (pb_entry.has_staged_id()) {
507         const pb::StagedId& pb_staged_id = pb_entry.staged_id();
508 
509         StagedId staged_id;
510         if (pb_staged_id.has_source()) {
511           DeserializeSourceFromPb(pb_staged_id.source(), src_pool, &staged_id.source);
512         }
513         staged_id.id = pb_staged_id.staged_id();
514         entry->staged_id = std::move(staged_id);
515       }
516 
517       ResourceId resid(pb_package.package_id().id(), pb_type.type_id().id(),
518                        pb_entry.entry_id().id());
519       if (resid.is_valid()) {
520         id_index[resid] = ResourceNameRef(pkg->name, type->named_type, entry->name);
521       }
522 
523       for (const pb::ConfigValue& pb_config_value : pb_entry.config_value()) {
524         const pb::Configuration& pb_config = pb_config_value.config();
525 
526         ConfigDescription config;
527         if (!DeserializeConfigFromPb(pb_config, &config, out_error)) {
528           return false;
529         }
530 
531         ResourceConfigValue* config_value = entry->FindOrCreateValue(config, pb_config.product());
532         if (config_value->value != nullptr) {
533           *out_error = "duplicate configuration in resource table";
534           return false;
535         }
536 
537         config_value->value = DeserializeValueFromPb(pb_config_value.value(), src_pool, config,
538                                                      &out_table->string_pool, files, out_error);
539 
540         if (config_value->value == nullptr) {
541           return false;
542         }
543       }
544 
545       // flag disabled
546       for (const pb::ConfigValue& pb_config_value : pb_entry.flag_disabled_config_value()) {
547         const pb::Configuration& pb_config = pb_config_value.config();
548 
549         ConfigDescription config;
550         if (!DeserializeConfigFromPb(pb_config, &config, out_error)) {
551           return false;
552         }
553 
554         ResourceConfigValue* config_value = entry->FindOrCreateFlagDisabledValue(
555             FeatureFlagAttribute{.name = pb_config_value.value().item().flag_name(),
556                                  .negated = pb_config_value.value().item().flag_negated()},
557             config, pb_config.product());
558         if (config_value->value != nullptr) {
559           *out_error = "duplicate configuration in resource table";
560           return false;
561         }
562 
563         config_value->value = DeserializeValueFromPb(pb_config_value.value(), src_pool, config,
564                                                      &out_table->string_pool, files, out_error);
565         if (config_value->value == nullptr) {
566           return false;
567         }
568       }
569     }
570   }
571 
572   ReferenceIdToNameVisitor visitor(&id_index);
573   VisitAllValuesInPackage(pkg, &visitor);
574   return true;
575 }
576 
DeserializeTableFromPb(const pb::ResourceTable & pb_table,io::IFileCollection * files,ResourceTable * out_table,std::string * out_error)577 bool DeserializeTableFromPb(const pb::ResourceTable& pb_table, io::IFileCollection* files,
578                             ResourceTable* out_table, std::string* out_error) {
579   // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
580   // causes errors when qualifying it with android::
581   using namespace android;
582 
583   ResStringPool source_pool;
584   if (pb_table.has_source_pool()) {
585     status_t result = source_pool.setTo(pb_table.source_pool().data().data(),
586                                         pb_table.source_pool().data().size());
587     if (result != NO_ERROR) {
588       *out_error = "invalid source pool";
589       return false;
590     }
591   }
592 
593   for (const pb::DynamicRefTable& dynamic_ref : pb_table.dynamic_ref_table()) {
594     out_table->included_packages_.insert(
595         {dynamic_ref.package_id().id(), dynamic_ref.package_name()});
596   }
597 
598   // Deserialize the overlayable groups of the table
599   std::vector<std::shared_ptr<Overlayable>> overlayables;
600   for (const pb::Overlayable& pb_overlayable : pb_table.overlayable()) {
601     auto group = std::make_shared<Overlayable>(pb_overlayable.name(), pb_overlayable.actor());
602     if (pb_overlayable.has_source()) {
603       DeserializeSourceFromPb(pb_overlayable.source(), source_pool, &group->source);
604     }
605     overlayables.push_back(group);
606   }
607 
608   for (const pb::Package& pb_package : pb_table.package()) {
609     if (!DeserializePackageFromPb(pb_package, source_pool, files, overlayables, out_table,
610                                   out_error)) {
611       return false;
612     }
613   }
614   return true;
615 }
616 
DeserializeFileReferenceTypeFromPb(const pb::FileReference::Type & type)617 static ResourceFile::Type DeserializeFileReferenceTypeFromPb(const pb::FileReference::Type& type) {
618   switch (type) {
619     case pb::FileReference::BINARY_XML:
620       return ResourceFile::Type::kBinaryXml;
621     case pb::FileReference::PROTO_XML:
622       return ResourceFile::Type::kProtoXml;
623     case pb::FileReference::PNG:
624       return ResourceFile::Type::kPng;
625     default:
626       return ResourceFile::Type::kUnknown;
627   }
628 }
629 
DeserializeCompiledFileFromPb(const pb::internal::CompiledFile & pb_file,ResourceFile * out_file,std::string * out_error)630 bool DeserializeCompiledFileFromPb(const pb::internal::CompiledFile& pb_file,
631                                    ResourceFile* out_file, std::string* out_error) {
632   ResourceNameRef name_ref;
633   if (!ResourceUtils::ParseResourceName(pb_file.resource_name(), &name_ref)) {
634     std::ostringstream error;
635     error << "invalid resource name in compiled file header: " << pb_file.resource_name();
636     *out_error = error.str();
637     return false;
638   }
639 
640   out_file->name = name_ref.ToResourceName();
641   out_file->source.path = pb_file.source_path();
642   out_file->type = DeserializeFileReferenceTypeFromPb(pb_file.type());
643 
644   out_file->flag_status = (FlagStatus)pb_file.flag_status();
645   if (!pb_file.flag_name().empty()) {
646     out_file->flag =
647         FeatureFlagAttribute{.name = pb_file.flag_name(), .negated = pb_file.flag_negated()};
648   }
649 
650   std::string config_error;
651   if (!DeserializeConfigFromPb(pb_file.config(), &out_file->config, &config_error)) {
652     std::ostringstream error;
653     error << "invalid resource configuration in compiled file header: " << config_error;
654     *out_error = error.str();
655     return false;
656   }
657 
658   for (const pb::internal::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbol()) {
659     if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(), &name_ref)) {
660       std::ostringstream error;
661       error << "invalid resource name for exported symbol in compiled file header: "
662             << pb_file.resource_name();
663       *out_error = error.str();
664       return false;
665     }
666 
667     size_t line = 0u;
668     if (pb_symbol.has_source()) {
669       line = pb_symbol.source().line_number();
670     }
671     out_file->exported_symbols.push_back(SourcedResourceName{name_ref.ToResourceName(), line});
672   }
673   return true;
674 }
675 
DeserializeReferenceTypeFromPb(const pb::Reference_Type & pb_type)676 static Reference::Type DeserializeReferenceTypeFromPb(const pb::Reference_Type& pb_type) {
677   switch (pb_type) {
678     case pb::Reference_Type_REFERENCE:
679       return Reference::Type::kResource;
680     case pb::Reference_Type_ATTRIBUTE:
681       return Reference::Type::kAttribute;
682     default:
683       break;
684   }
685   return Reference::Type::kResource;
686 }
687 
DeserializeReferenceFromPb(const pb::Reference & pb_ref,Reference * out_ref,std::string * out_error)688 static bool DeserializeReferenceFromPb(const pb::Reference& pb_ref, Reference* out_ref,
689                                        std::string* out_error) {
690   out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type());
691   out_ref->private_reference = pb_ref.private_();
692   out_ref->is_dynamic = pb_ref.is_dynamic().value();
693 
694   if (pb_ref.id() != 0) {
695     out_ref->id = ResourceId(pb_ref.id());
696   }
697 
698   if (!pb_ref.name().empty()) {
699     ResourceNameRef name_ref;
700     if (!ResourceUtils::ParseResourceName(pb_ref.name(), &name_ref, nullptr)) {
701       std::ostringstream error;
702       error << "reference has invalid resource name '" << pb_ref.name() << "'";
703       *out_error = error.str();
704       return false;
705     }
706     out_ref->name = name_ref.ToResourceName();
707   }
708   if (pb_ref.type_flags() != 0) {
709     out_ref->type_flags = pb_ref.type_flags();
710   }
711   out_ref->allow_raw = pb_ref.allow_raw();
712   return true;
713 }
714 
DeserializeMacroFromPb(const pb::MacroBody & pb_ref,Macro * out_ref,std::string * out_error)715 static bool DeserializeMacroFromPb(const pb::MacroBody& pb_ref, Macro* out_ref,
716                                    std::string* out_error) {
717   out_ref->raw_value = pb_ref.raw_string();
718 
719   if (pb_ref.has_style_string()) {
720     out_ref->style_string.str = pb_ref.style_string().str();
721     for (const auto& span : pb_ref.style_string().spans()) {
722       out_ref->style_string.spans.emplace_back(android::Span{
723           .name = span.name(), .first_char = span.start_index(), .last_char = span.end_index()});
724     }
725   }
726 
727   for (const auto& untranslatable_section : pb_ref.untranslatable_sections()) {
728     out_ref->untranslatable_sections.emplace_back(
729         UntranslatableSection{.start = static_cast<size_t>(untranslatable_section.start_index()),
730                               .end = static_cast<size_t>(untranslatable_section.end_index())});
731   }
732 
733   for (const auto& namespace_decls : pb_ref.namespace_stack()) {
734     out_ref->alias_namespaces.emplace_back(
735         Macro::Namespace{.alias = namespace_decls.prefix(),
736                          .package_name = namespace_decls.package_name(),
737                          .is_private = namespace_decls.is_private()});
738   }
739 
740   return true;
741 }
742 
743 template <typename T>
DeserializeItemMetaDataFromPb(const T & pb_item,const android::ResStringPool & src_pool,Value * out_value)744 static void DeserializeItemMetaDataFromPb(const T& pb_item, const android::ResStringPool& src_pool,
745                                           Value* out_value) {
746   if (pb_item.has_source()) {
747     android::Source source;
748     DeserializeSourceFromPb(pb_item.source(), src_pool, &source);
749     out_value->SetSource(std::move(source));
750   }
751   out_value->SetComment(pb_item.comment());
752 }
753 
DeserializePluralEnumFromPb(const pb::Plural_Arity & arity)754 static size_t DeserializePluralEnumFromPb(const pb::Plural_Arity& arity) {
755   switch (arity) {
756     case pb::Plural_Arity_ZERO:
757       return Plural::Zero;
758     case pb::Plural_Arity_ONE:
759       return Plural::One;
760     case pb::Plural_Arity_TWO:
761       return Plural::Two;
762     case pb::Plural_Arity_FEW:
763       return Plural::Few;
764     case pb::Plural_Arity_MANY:
765       return Plural::Many;
766     default:
767       break;
768   }
769   return Plural::Other;
770 }
771 
DeserializeValueFromPb(const pb::Value & pb_value,const android::ResStringPool & src_pool,const ConfigDescription & config,android::StringPool * value_pool,io::IFileCollection * files,std::string * out_error)772 std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value,
773                                               const android::ResStringPool& src_pool,
774                                               const ConfigDescription& config,
775                                               android::StringPool* value_pool,
776                                               io::IFileCollection* files, std::string* out_error) {
777   std::unique_ptr<Value> value;
778   if (pb_value.has_item()) {
779     value = DeserializeItemFromPb(pb_value.item(), src_pool, config, value_pool, files, out_error);
780     if (value == nullptr) {
781       return {};
782     }
783   } else if (pb_value.has_compound_value()) {
784     const pb::CompoundValue& pb_compound_value = pb_value.compound_value();
785     switch (pb_compound_value.value_case()) {
786       case pb::CompoundValue::kAttr: {
787         const pb::Attribute& pb_attr = pb_compound_value.attr();
788         std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(pb_attr.format_flags());
789         attr->min_int = pb_attr.min_int();
790         attr->max_int = pb_attr.max_int();
791         for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbol()) {
792           Attribute::Symbol symbol;
793           DeserializeItemMetaDataFromPb(pb_symbol, src_pool, &symbol.symbol);
794           if (!DeserializeReferenceFromPb(pb_symbol.name(), &symbol.symbol, out_error)) {
795             return {};
796           }
797           symbol.value = pb_symbol.value();
798           symbol.type = pb_symbol.type() != 0U ? pb_symbol.type()
799                                                : android::Res_value::TYPE_INT_DEC;
800           attr->symbols.push_back(std::move(symbol));
801         }
802         value = std::move(attr);
803       } break;
804 
805       case pb::CompoundValue::kStyle: {
806         const pb::Style& pb_style = pb_compound_value.style();
807         std::unique_ptr<Style> style = util::make_unique<Style>();
808         if (pb_style.has_parent()) {
809           style->parent = Reference();
810           if (!DeserializeReferenceFromPb(pb_style.parent(), &style->parent.value(), out_error)) {
811             return {};
812           }
813 
814           if (pb_style.has_parent_source()) {
815             android::Source parent_source;
816             DeserializeSourceFromPb(pb_style.parent_source(), src_pool, &parent_source);
817             style->parent.value().SetSource(std::move(parent_source));
818           }
819         }
820 
821         for (const pb::Style_Entry& pb_entry : pb_style.entry()) {
822           Style::Entry entry;
823           if (!DeserializeReferenceFromPb(pb_entry.key(), &entry.key, out_error)) {
824             return {};
825           }
826           DeserializeItemMetaDataFromPb(pb_entry, src_pool, &entry.key);
827           entry.value = DeserializeItemFromPb(pb_entry.item(), src_pool, config, value_pool, files,
828                                               out_error);
829           if (entry.value == nullptr) {
830             return {};
831           }
832 
833           // Copy the meta-data into the value as well.
834           DeserializeItemMetaDataFromPb(pb_entry, src_pool, entry.value.get());
835           style->entries.push_back(std::move(entry));
836         }
837         value = std::move(style);
838       } break;
839 
840       case pb::CompoundValue::kStyleable: {
841         const pb::Styleable& pb_styleable = pb_compound_value.styleable();
842         std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
843         for (const pb::Styleable_Entry& pb_entry : pb_styleable.entry()) {
844           Reference attr_ref;
845           DeserializeItemMetaDataFromPb(pb_entry, src_pool, &attr_ref);
846           DeserializeReferenceFromPb(pb_entry.attr(), &attr_ref, out_error);
847           styleable->entries.push_back(std::move(attr_ref));
848         }
849         value = std::move(styleable);
850       } break;
851 
852       case pb::CompoundValue::kArray: {
853         const pb::Array& pb_array = pb_compound_value.array();
854         std::unique_ptr<Array> array = util::make_unique<Array>();
855         for (const pb::Array_Element& pb_entry : pb_array.element()) {
856           std::unique_ptr<Item> item = DeserializeItemFromPb(pb_entry.item(), src_pool, config,
857                                                              value_pool, files, out_error);
858           if (item == nullptr) {
859             return {};
860           }
861 
862           DeserializeItemMetaDataFromPb(pb_entry, src_pool, item.get());
863           array->elements.push_back(std::move(item));
864         }
865         value = std::move(array);
866       } break;
867 
868       case pb::CompoundValue::kPlural: {
869         const pb::Plural& pb_plural = pb_compound_value.plural();
870         std::unique_ptr<Plural> plural = util::make_unique<Plural>();
871         for (const pb::Plural_Entry& pb_entry : pb_plural.entry()) {
872           size_t plural_idx = DeserializePluralEnumFromPb(pb_entry.arity());
873           plural->values[plural_idx] = DeserializeItemFromPb(pb_entry.item(), src_pool, config,
874                                                              value_pool, files, out_error);
875           if (!plural->values[plural_idx]) {
876             return {};
877           }
878 
879           DeserializeItemMetaDataFromPb(pb_entry, src_pool, plural->values[plural_idx].get());
880         }
881         value = std::move(plural);
882       } break;
883 
884       case pb::CompoundValue::kMacro: {
885         const pb::MacroBody& pb_macro = pb_compound_value.macro();
886         auto macro = std::make_unique<Macro>();
887         if (!DeserializeMacroFromPb(pb_macro, macro.get(), out_error)) {
888           return {};
889         }
890         value = std::move(macro);
891       } break;
892 
893       default:
894         LOG(FATAL) << "unknown compound value: " << (int)pb_compound_value.value_case();
895         break;
896     }
897     value->SetFlagStatus((FlagStatus)pb_compound_value.flag_status());
898     value->SetFlag(FeatureFlagAttribute{.name = pb_compound_value.flag_name(),
899                                         .negated = pb_compound_value.flag_negated()});
900   } else {
901     LOG(FATAL) << "unknown value: " << (int)pb_value.value_case();
902     return {};
903   }
904 
905   CHECK(value) << "forgot to set value";
906 
907   value->SetWeak(pb_value.weak());
908   DeserializeItemMetaDataFromPb(pb_value, src_pool, value.get());
909   return value;
910 }
911 
DeserializeItemFromPbInternal(const pb::Item & pb_item,const android::ResStringPool & src_pool,const ConfigDescription & config,android::StringPool * value_pool,io::IFileCollection * files,std::string * out_error)912 std::unique_ptr<Item> DeserializeItemFromPbInternal(const pb::Item& pb_item,
913                                                     const android::ResStringPool& src_pool,
914                                                     const ConfigDescription& config,
915                                                     android::StringPool* value_pool,
916                                                     io::IFileCollection* files,
917                                                     std::string* out_error) {
918   switch (pb_item.value_case()) {
919     case pb::Item::kRef: {
920       const pb::Reference& pb_ref = pb_item.ref();
921       std::unique_ptr<Reference> ref = util::make_unique<Reference>();
922       if (!DeserializeReferenceFromPb(pb_ref, ref.get(), out_error)) {
923         return {};
924       }
925       return std::move(ref);
926     } break;
927 
928     case pb::Item::kPrim: {
929       const pb::Primitive& pb_prim = pb_item.prim();
930       android::Res_value val = {};
931       switch (pb_prim.oneof_value_case()) {
932         case pb::Primitive::kNullValue: {
933           val.dataType = android::Res_value::TYPE_NULL;
934           val.data = android::Res_value::DATA_NULL_UNDEFINED;
935         } break;
936         case pb::Primitive::kEmptyValue: {
937           val.dataType = android::Res_value::TYPE_NULL;
938           val.data = android::Res_value::DATA_NULL_EMPTY;
939         } break;
940         case pb::Primitive::kFloatValue: {
941           val.dataType = android::Res_value::TYPE_FLOAT;
942           float float_val = pb_prim.float_value();
943           val.data = *(uint32_t*)&float_val;
944         } break;
945         case pb::Primitive::kDimensionValue: {
946           val.dataType = android::Res_value::TYPE_DIMENSION;
947           val.data  = pb_prim.dimension_value();
948         } break;
949         case pb::Primitive::kFractionValue: {
950           val.dataType = android::Res_value::TYPE_FRACTION;
951           val.data  = pb_prim.fraction_value();
952         } break;
953         case pb::Primitive::kIntDecimalValue: {
954           val.dataType = android::Res_value::TYPE_INT_DEC;
955           val.data = static_cast<int32_t>(pb_prim.int_decimal_value());
956         } break;
957         case pb::Primitive::kIntHexadecimalValue: {
958           val.dataType = android::Res_value::TYPE_INT_HEX;
959           val.data = pb_prim.int_hexadecimal_value();
960         } break;
961         case pb::Primitive::kBooleanValue: {
962           val.dataType = android::Res_value::TYPE_INT_BOOLEAN;
963           val.data = pb_prim.boolean_value() ? 0xFFFFFFFF : 0x0;
964         } break;
965         case pb::Primitive::kColorArgb8Value: {
966           val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB8;
967           val.data = pb_prim.color_argb8_value();
968         } break;
969         case pb::Primitive::kColorRgb8Value: {
970           val.dataType = android::Res_value::TYPE_INT_COLOR_RGB8;
971           val.data = pb_prim.color_rgb8_value();
972         } break;
973         case pb::Primitive::kColorArgb4Value: {
974           val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB4;
975           val.data = pb_prim.color_argb4_value();
976         } break;
977         case pb::Primitive::kColorRgb4Value: {
978           val.dataType = android::Res_value::TYPE_INT_COLOR_RGB4;
979           val.data = pb_prim.color_rgb4_value();
980         } break;
981         case pb::Primitive::kDimensionValueDeprecated: {  // DEPRECATED
982           val.dataType = android::Res_value::TYPE_DIMENSION;
983           float dimen_val = pb_prim.dimension_value_deprecated();
984           val.data = *(uint32_t*)&dimen_val;
985         } break;
986         case pb::Primitive::kFractionValueDeprecated: {  // DEPRECATED
987           val.dataType = android::Res_value::TYPE_FRACTION;
988           float fraction_val = pb_prim.fraction_value_deprecated();
989           val.data = *(uint32_t*)&fraction_val;
990         } break;
991         default: {
992           LOG(FATAL) << "Unexpected Primitive type: "
993                      << static_cast<uint32_t>(pb_prim.oneof_value_case());
994           return {};
995         } break;
996       }
997       return util::make_unique<BinaryPrimitive>(val);
998     } break;
999 
1000     case pb::Item::kId: {
1001       return util::make_unique<Id>();
1002     } break;
1003 
1004     case pb::Item::kStr: {
1005       return util::make_unique<String>(
1006           value_pool->MakeRef(pb_item.str().value(), android::StringPool::Context(config)));
1007     } break;
1008 
1009     case pb::Item::kRawStr: {
1010       return util::make_unique<RawString>(
1011           value_pool->MakeRef(pb_item.raw_str().value(), android::StringPool::Context(config)));
1012     } break;
1013 
1014     case pb::Item::kStyledStr: {
1015       const pb::StyledString& pb_str = pb_item.styled_str();
1016       android::StyleString style_str{pb_str.value()};
1017       for (const pb::StyledString::Span& pb_span : pb_str.span()) {
1018         style_str.spans.push_back(
1019             android::Span{pb_span.tag(), pb_span.first_char(), pb_span.last_char()});
1020       }
1021       return util::make_unique<StyledString>(value_pool->MakeRef(
1022           style_str,
1023           android::StringPool::Context(android::StringPool::Context::kNormalPriority, config)));
1024     } break;
1025 
1026     case pb::Item::kFile: {
1027       const pb::FileReference& pb_file = pb_item.file();
1028       std::unique_ptr<FileReference> file_ref =
1029           util::make_unique<FileReference>(value_pool->MakeRef(
1030               pb_file.path(),
1031               android::StringPool::Context(android::StringPool::Context::kHighPriority, config)));
1032       file_ref->type = DeserializeFileReferenceTypeFromPb(pb_file.type());
1033       if (files != nullptr) {
1034         file_ref->file = files->FindFile(*file_ref->path);
1035       }
1036       return std::move(file_ref);
1037     } break;
1038 
1039     default:
1040       LOG(FATAL) << "unknown item: " << (int)pb_item.value_case();
1041       break;
1042   }
1043   return {};
1044 }
1045 
DeserializeItemFromPb(const pb::Item & pb_item,const android::ResStringPool & src_pool,const ConfigDescription & config,android::StringPool * value_pool,io::IFileCollection * files,std::string * out_error)1046 std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item,
1047                                             const android::ResStringPool& src_pool,
1048                                             const ConfigDescription& config,
1049                                             android::StringPool* value_pool,
1050                                             io::IFileCollection* files, std::string* out_error) {
1051   auto item =
1052       DeserializeItemFromPbInternal(pb_item, src_pool, config, value_pool, files, out_error);
1053   if (item) {
1054     item->SetFlagStatus((FlagStatus)pb_item.flag_status());
1055     if (!pb_item.flag_name().empty()) {
1056       item->SetFlag(
1057           FeatureFlagAttribute{.name = pb_item.flag_name(), .negated = pb_item.flag_negated()});
1058     }
1059   }
1060   return item;
1061 }
1062 
DeserializeXmlResourceFromPb(const pb::XmlNode & pb_node,std::string * out_error)1063 std::unique_ptr<xml::XmlResource> DeserializeXmlResourceFromPb(const pb::XmlNode& pb_node,
1064                                                                std::string* out_error) {
1065   if (!pb_node.has_element()) {
1066     return {};
1067   }
1068 
1069   std::unique_ptr<xml::XmlResource> resource = util::make_unique<xml::XmlResource>();
1070   resource->root = util::make_unique<xml::Element>();
1071   if (!DeserializeXmlFromPb(pb_node, resource->root.get(), &resource->string_pool, out_error)) {
1072     return {};
1073   }
1074   return resource;
1075 }
1076 
DeserializeXmlFromPb(const pb::XmlNode & pb_node,xml::Element * out_el,android::StringPool * value_pool,std::string * out_error)1077 bool DeserializeXmlFromPb(const pb::XmlNode& pb_node, xml::Element* out_el,
1078                           android::StringPool* value_pool, std::string* out_error) {
1079   const pb::XmlElement& pb_el = pb_node.element();
1080   out_el->name = pb_el.name();
1081   out_el->namespace_uri = pb_el.namespace_uri();
1082   out_el->line_number = pb_node.source().line_number();
1083   out_el->column_number = pb_node.source().column_number();
1084 
1085   for (const pb::XmlNamespace& pb_ns : pb_el.namespace_declaration()) {
1086     xml::NamespaceDecl decl;
1087     decl.uri = pb_ns.uri();
1088     decl.prefix = pb_ns.prefix();
1089     decl.line_number = pb_ns.source().line_number();
1090     decl.column_number = pb_ns.source().column_number();
1091     out_el->namespace_decls.push_back(std::move(decl));
1092   }
1093 
1094   for (const pb::XmlAttribute& pb_attr : pb_el.attribute()) {
1095     xml::Attribute attr;
1096     attr.name = pb_attr.name();
1097     attr.namespace_uri = pb_attr.namespace_uri();
1098     attr.value = pb_attr.value();
1099     if (pb_attr.resource_id() != 0u) {
1100       attr.compiled_attribute = xml::AaptAttribute{Attribute(), ResourceId(pb_attr.resource_id())};
1101     }
1102     if (pb_attr.has_compiled_item()) {
1103       attr.compiled_value =
1104           DeserializeItemFromPb(pb_attr.compiled_item(), {}, {}, value_pool, nullptr, out_error);
1105       if (attr.compiled_value == nullptr) {
1106         return {};
1107       }
1108       attr.compiled_value->SetSource(android::Source().WithLine(pb_attr.source().line_number()));
1109     }
1110     out_el->attributes.push_back(std::move(attr));
1111   }
1112 
1113   // Deserialize the children.
1114   for (const pb::XmlNode& pb_child : pb_el.child()) {
1115     switch (pb_child.node_case()) {
1116       case pb::XmlNode::NodeCase::kText: {
1117         std::unique_ptr<xml::Text> text = util::make_unique<xml::Text>();
1118         text->line_number = pb_child.source().line_number();
1119         text->column_number = pb_child.source().column_number();
1120         text->text = pb_child.text();
1121         out_el->AppendChild(std::move(text));
1122       } break;
1123 
1124       case pb::XmlNode::NodeCase::kElement: {
1125         std::unique_ptr<xml::Element> child_el = util::make_unique<xml::Element>();
1126         if (!DeserializeXmlFromPb(pb_child, child_el.get(), value_pool, out_error)) {
1127           return false;
1128         }
1129         out_el->AppendChild(std::move(child_el));
1130       } break;
1131 
1132       default:
1133         LOG(FATAL) << "unknown XmlNode " << (int)pb_child.node_case();
1134         break;
1135     }
1136   }
1137   return true;
1138 }
1139 
1140 }  // namespace aapt
1141