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