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