• 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/ProtoSerialize.h"
18 
19 #include "ResourceUtils.h"
20 #include "format/proto/ProtoDeserialize.h"
21 #include "test/Test.h"
22 
23 using ::android::StringPiece;
24 using ::testing::Eq;
25 using ::testing::IsEmpty;
26 using ::testing::NotNull;
27 using ::testing::SizeIs;
28 using ::testing::StrEq;
29 
30 namespace aapt {
31 
32 class MockFileCollection : public io::IFileCollection {
33  public:
34   MOCK_METHOD1(FindFile, io::IFile*(const StringPiece& path));
35   MOCK_METHOD0(Iterator, std::unique_ptr<io::IFileCollectionIterator>());
36 };
37 
TEST(ProtoSerializeTest,SerializeSinglePackage)38 TEST(ProtoSerializeTest, SerializeSinglePackage) {
39   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
40   std::unique_ptr<ResourceTable> table =
41       test::ResourceTableBuilder()
42           .SetPackageId("com.app.a", 0x7f)
43           .AddFileReference("com.app.a:layout/main", ResourceId(0x7f020000), "res/layout/main.xml")
44           .AddReference("com.app.a:layout/other", ResourceId(0x7f020001), "com.app.a:layout/main")
45           .AddString("com.app.a:string/text", {}, "hi")
46           .AddValue("com.app.a:id/foo", {}, util::make_unique<Id>())
47           .SetSymbolState("com.app.a:bool/foo", {}, Visibility::Level::kUndefined,
48                           true /*allow_new*/)
49           .Build();
50 
51   Visibility public_symbol;
52   public_symbol.level = Visibility::Level::kPublic;
53   ASSERT_TRUE(table->SetVisibilityWithId(test::ParseNameOrDie("com.app.a:layout/main"),
54                                          public_symbol, ResourceId(0x7f020000),
55                                          context->GetDiagnostics()));
56 
57   Id* id = test::GetValue<Id>(table.get(), "com.app.a:id/foo");
58   ASSERT_THAT(id, NotNull());
59 
60   // Make a plural.
61   std::unique_ptr<Plural> plural = util::make_unique<Plural>();
62   plural->values[Plural::One] = util::make_unique<String>(table->string_pool.MakeRef("one"));
63   ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("com.app.a:plurals/hey"), ConfigDescription{},
64                                  {}, std::move(plural), context->GetDiagnostics()));
65 
66   // Make a styled string.
67   StyleString style_string;
68   style_string.str = "hello";
69   style_string.spans.push_back(Span{"b", 0u, 4u});
70   ASSERT_TRUE(
71       table->AddResource(test::ParseNameOrDie("com.app.a:string/styled"), ConfigDescription{}, {},
72                          util::make_unique<StyledString>(table->string_pool.MakeRef(style_string)),
73                          context->GetDiagnostics()));
74 
75   // Make a resource with different products.
76   ASSERT_TRUE(table->AddResource(
77       test::ParseNameOrDie("com.app.a:integer/one"), test::ParseConfigOrDie("land"), {},
78       test::BuildPrimitive(android::Res_value::TYPE_INT_DEC, 123u), context->GetDiagnostics()));
79   ASSERT_TRUE(table->AddResource(
80       test::ParseNameOrDie("com.app.a:integer/one"), test::ParseConfigOrDie("land"), "tablet",
81       test::BuildPrimitive(android::Res_value::TYPE_INT_DEC, 321u), context->GetDiagnostics()));
82 
83   // Make a reference with both resource name and resource ID.
84   // The reference should point to a resource outside of this table to test that both name and id
85   // get serialized.
86   Reference expected_ref;
87   expected_ref.name = test::ParseNameOrDie("android:layout/main");
88   expected_ref.id = ResourceId(0x01020000);
89   ASSERT_TRUE(table->AddResource(
90       test::ParseNameOrDie("com.app.a:layout/abc"), ConfigDescription::DefaultConfig(), {},
91       util::make_unique<Reference>(expected_ref), context->GetDiagnostics()));
92 
93   // Make an overlayable resource.
94   ASSERT_TRUE(table->SetOverlayable(test::ParseNameOrDie("com.app.a:integer/overlayable"),
95                                     Overlayable{}, test::GetDiagnostics()));
96 
97   pb::ResourceTable pb_table;
98   SerializeTableToPb(*table, &pb_table, context->GetDiagnostics());
99 
100   test::TestFile file_a("res/layout/main.xml");
101   MockFileCollection files;
102   EXPECT_CALL(files, FindFile(Eq("res/layout/main.xml")))
103       .WillRepeatedly(::testing::Return(&file_a));
104 
105   ResourceTable new_table;
106   std::string error;
107   ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error));
108   EXPECT_THAT(error, IsEmpty());
109 
110   Id* new_id = test::GetValue<Id>(&new_table, "com.app.a:id/foo");
111   ASSERT_THAT(new_id, NotNull());
112   EXPECT_THAT(new_id->IsWeak(), Eq(id->IsWeak()));
113 
114   Maybe<ResourceTable::SearchResult> result =
115       new_table.FindResource(test::ParseNameOrDie("com.app.a:layout/main"));
116   ASSERT_TRUE(result);
117 
118   EXPECT_THAT(result.value().type->visibility_level, Eq(Visibility::Level::kPublic));
119   EXPECT_THAT(result.value().entry->visibility.level, Eq(Visibility::Level::kPublic));
120 
121   result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/foo"));
122   ASSERT_TRUE(result);
123   EXPECT_THAT(result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
124   EXPECT_TRUE(result.value().entry->allow_new);
125 
126   // Find the product-dependent values
127   BinaryPrimitive* prim = test::GetValueForConfigAndProduct<BinaryPrimitive>(
128       &new_table, "com.app.a:integer/one", test::ParseConfigOrDie("land"), "");
129   ASSERT_THAT(prim, NotNull());
130   EXPECT_THAT(prim->value.data, Eq(123u));
131 
132   prim = test::GetValueForConfigAndProduct<BinaryPrimitive>(
133       &new_table, "com.app.a:integer/one", test::ParseConfigOrDie("land"), "tablet");
134   ASSERT_THAT(prim, NotNull());
135   EXPECT_THAT(prim->value.data, Eq(321u));
136 
137   Reference* actual_ref = test::GetValue<Reference>(&new_table, "com.app.a:layout/abc");
138   ASSERT_THAT(actual_ref, NotNull());
139   ASSERT_TRUE(actual_ref->name);
140   ASSERT_TRUE(actual_ref->id);
141   EXPECT_THAT(*actual_ref, Eq(expected_ref));
142 
143   FileReference* actual_file_ref =
144       test::GetValue<FileReference>(&new_table, "com.app.a:layout/main");
145   ASSERT_THAT(actual_file_ref, NotNull());
146   EXPECT_THAT(actual_file_ref->file, Eq(&file_a));
147 
148   StyledString* actual_styled_str =
149       test::GetValue<StyledString>(&new_table, "com.app.a:string/styled");
150   ASSERT_THAT(actual_styled_str, NotNull());
151   EXPECT_THAT(actual_styled_str->value->value, Eq("hello"));
152   ASSERT_THAT(actual_styled_str->value->spans, SizeIs(1u));
153   EXPECT_THAT(*actual_styled_str->value->spans[0].name, Eq("b"));
154   EXPECT_THAT(actual_styled_str->value->spans[0].first_char, Eq(0u));
155   EXPECT_THAT(actual_styled_str->value->spans[0].last_char, Eq(4u));
156 
157   Maybe<ResourceTable::SearchResult> search_result =
158       new_table.FindResource(test::ParseNameOrDie("com.app.a:integer/overlayable"));
159   ASSERT_TRUE(search_result);
160   ASSERT_THAT(search_result.value().entry, NotNull());
161   EXPECT_TRUE(search_result.value().entry->overlayable);
162 }
163 
TEST(ProtoSerializeTest,SerializeAndDeserializeXml)164 TEST(ProtoSerializeTest, SerializeAndDeserializeXml) {
165   xml::Element element;
166   element.line_number = 22;
167   element.column_number = 23;
168   element.name = "element";
169   element.namespace_uri = "uri://";
170 
171   xml::NamespaceDecl decl;
172   decl.prefix = "android";
173   decl.uri = xml::kSchemaAndroid;
174   decl.line_number = 21;
175   decl.column_number = 24;
176 
177   element.namespace_decls.push_back(decl);
178 
179   xml::Attribute attr;
180   attr.name = "name";
181   attr.namespace_uri = xml::kSchemaAndroid;
182   attr.value = "23dp";
183   attr.compiled_attribute = xml::AaptAttribute(Attribute{}, ResourceId(0x01010000));
184   attr.compiled_value =
185       ResourceUtils::TryParseItemForAttribute(attr.value, android::ResTable_map::TYPE_DIMENSION);
186   attr.compiled_value->SetSource(Source().WithLine(25));
187   element.attributes.push_back(std::move(attr));
188 
189   std::unique_ptr<xml::Text> text = util::make_unique<xml::Text>();
190   text->line_number = 25;
191   text->column_number = 3;
192   text->text = "hey there";
193   element.AppendChild(std::move(text));
194 
195   std::unique_ptr<xml::Element> child = util::make_unique<xml::Element>();
196   child->name = "child";
197 
198   text = util::make_unique<xml::Text>();
199   text->text = "woah there";
200   child->AppendChild(std::move(text));
201 
202   element.AppendChild(std::move(child));
203 
204   pb::XmlNode pb_xml;
205   SerializeXmlToPb(element, &pb_xml);
206 
207   StringPool pool;
208   xml::Element actual_el;
209   std::string error;
210   ASSERT_TRUE(DeserializeXmlFromPb(pb_xml, &actual_el, &pool, &error));
211   ASSERT_THAT(error, IsEmpty());
212 
213   EXPECT_THAT(actual_el.name, StrEq("element"));
214   EXPECT_THAT(actual_el.namespace_uri, StrEq("uri://"));
215   EXPECT_THAT(actual_el.line_number, Eq(22u));
216   EXPECT_THAT(actual_el.column_number, Eq(23u));
217 
218   ASSERT_THAT(actual_el.namespace_decls, SizeIs(1u));
219   const xml::NamespaceDecl& actual_decl = actual_el.namespace_decls[0];
220   EXPECT_THAT(actual_decl.prefix, StrEq("android"));
221   EXPECT_THAT(actual_decl.uri, StrEq(xml::kSchemaAndroid));
222   EXPECT_THAT(actual_decl.line_number, Eq(21u));
223   EXPECT_THAT(actual_decl.column_number, Eq(24u));
224 
225   ASSERT_THAT(actual_el.attributes, SizeIs(1u));
226   const xml::Attribute& actual_attr = actual_el.attributes[0];
227   EXPECT_THAT(actual_attr.name, StrEq("name"));
228   EXPECT_THAT(actual_attr.namespace_uri, StrEq(xml::kSchemaAndroid));
229   EXPECT_THAT(actual_attr.value, StrEq("23dp"));
230 
231   ASSERT_THAT(actual_attr.compiled_value, NotNull());
232   const BinaryPrimitive* prim = ValueCast<BinaryPrimitive>(actual_attr.compiled_value.get());
233   ASSERT_THAT(prim, NotNull());
234   EXPECT_THAT(prim->value.dataType, Eq(android::Res_value::TYPE_DIMENSION));
235 
236   ASSERT_TRUE(actual_attr.compiled_attribute);
237   ASSERT_TRUE(actual_attr.compiled_attribute.value().id);
238 
239   ASSERT_THAT(actual_el.children, SizeIs(2u));
240   const xml::Text* child_text = xml::NodeCast<xml::Text>(actual_el.children[0].get());
241   ASSERT_THAT(child_text, NotNull());
242   const xml::Element* child_el = xml::NodeCast<xml::Element>(actual_el.children[1].get());
243   ASSERT_THAT(child_el, NotNull());
244 
245   EXPECT_THAT(child_text->line_number, Eq(25u));
246   EXPECT_THAT(child_text->column_number, Eq(3u));
247   EXPECT_THAT(child_text->text, StrEq("hey there"));
248 
249   EXPECT_THAT(child_el->name, StrEq("child"));
250   ASSERT_THAT(child_el->children, SizeIs(1u));
251 
252   child_text = xml::NodeCast<xml::Text>(child_el->children[0].get());
253   ASSERT_THAT(child_text, NotNull());
254   EXPECT_THAT(child_text->text, StrEq("woah there"));
255 }
256 
TEST(ProtoSerializeTest,SerializeAndDeserializePrimitives)257 TEST(ProtoSerializeTest, SerializeAndDeserializePrimitives) {
258   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
259   std::unique_ptr<ResourceTable> table =
260       test::ResourceTableBuilder()
261           .AddValue("android:bool/boolean_true",
262                     test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, true))
263           .AddValue("android:bool/boolean_false",
264                     test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, false))
265           .AddValue("android:color/color_rgb8", ResourceUtils::TryParseColor("#AABBCC"))
266           .AddValue("android:color/color_argb8", ResourceUtils::TryParseColor("#11223344"))
267           .AddValue("android:color/color_rgb4", ResourceUtils::TryParseColor("#DEF"))
268           .AddValue("android:color/color_argb4", ResourceUtils::TryParseColor("#5678"))
269           .AddValue("android:integer/integer_444", ResourceUtils::TryParseInt("444"))
270           .AddValue("android:integer/integer_neg_333", ResourceUtils::TryParseInt("-333"))
271           .AddValue("android:integer/hex_int_abcd", ResourceUtils::TryParseInt("0xABCD"))
272           .AddValue("android:dimen/dimen_1.39mm", ResourceUtils::TryParseFloat("1.39mm"))
273           .AddValue("android:fraction/fraction_27", ResourceUtils::TryParseFloat("27%"))
274           .AddValue("android:dimen/neg_2.3in", ResourceUtils::TryParseFloat("-2.3in"))
275           .AddValue("android:integer/null", ResourceUtils::MakeEmpty())
276           .Build();
277 
278   pb::ResourceTable pb_table;
279   SerializeTableToPb(*table, &pb_table, context->GetDiagnostics());
280 
281   test::TestFile file_a("res/layout/main.xml");
282   MockFileCollection files;
283   EXPECT_CALL(files, FindFile(Eq("res/layout/main.xml")))
284       .WillRepeatedly(::testing::Return(&file_a));
285 
286   ResourceTable new_table;
287   std::string error;
288   ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error));
289   EXPECT_THAT(error, IsEmpty());
290 
291   BinaryPrimitive* bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
292       &new_table, "android:bool/boolean_true", ConfigDescription::DefaultConfig(), "");
293   ASSERT_THAT(bp, NotNull());
294   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_BOOLEAN));
295   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseBool("true")->value.data));
296 
297   bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:bool/boolean_false",
298                                                           ConfigDescription::DefaultConfig(), "");
299   ASSERT_THAT(bp, NotNull());
300   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_BOOLEAN));
301   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseBool("false")->value.data));
302 
303   bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_rgb8",
304                                                           ConfigDescription::DefaultConfig(), "");
305   ASSERT_THAT(bp, NotNull());
306   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_RGB8));
307   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#AABBCC")->value.data));
308 
309   bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_argb8",
310                                                           ConfigDescription::DefaultConfig(), "");
311   ASSERT_THAT(bp, NotNull());
312   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_ARGB8));
313   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#11223344")->value.data));
314 
315   bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_rgb4",
316                                                           ConfigDescription::DefaultConfig(), "");
317   ASSERT_THAT(bp, NotNull());
318   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_RGB4));
319   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#DEF")->value.data));
320 
321   bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_argb4",
322                                                           ConfigDescription::DefaultConfig(), "");
323   ASSERT_THAT(bp, NotNull());
324   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_ARGB4));
325   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#5678")->value.data));
326 
327   bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:integer/integer_444",
328                                                           ConfigDescription::DefaultConfig(), "");
329   ASSERT_THAT(bp, NotNull());
330   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC));
331   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("444")->value.data));
332 
333   bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
334       &new_table, "android:integer/integer_neg_333", ConfigDescription::DefaultConfig(), "");
335   ASSERT_THAT(bp, NotNull());
336   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC));
337   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("-333")->value.data));
338 
339   bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
340       &new_table, "android:integer/hex_int_abcd", ConfigDescription::DefaultConfig(), "");
341   ASSERT_THAT(bp, NotNull());
342   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_HEX));
343   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("0xABCD")->value.data));
344 
345   bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:dimen/dimen_1.39mm",
346                                                           ConfigDescription::DefaultConfig(), "");
347   ASSERT_THAT(bp, NotNull());
348   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_DIMENSION));
349   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("1.39mm")->value.data));
350 
351   bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
352       &new_table, "android:fraction/fraction_27", ConfigDescription::DefaultConfig(), "");
353   ASSERT_THAT(bp, NotNull());
354   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_FRACTION));
355   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("27%")->value.data));
356 
357   bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:dimen/neg_2.3in",
358                                                           ConfigDescription::DefaultConfig(), "");
359   ASSERT_THAT(bp, NotNull());
360   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_DIMENSION));
361   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("-2.3in")->value.data));
362 
363   bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:integer/null",
364                                                           ConfigDescription::DefaultConfig(), "");
365   ASSERT_THAT(bp, NotNull());
366   EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_NULL));
367   EXPECT_THAT(bp->value.data, Eq(ResourceUtils::MakeEmpty()->value.data));
368 }
369 
ExpectConfigSerializes(const StringPiece & config_str)370 static void ExpectConfigSerializes(const StringPiece& config_str) {
371   const ConfigDescription expected_config = test::ParseConfigOrDie(config_str);
372   pb::Configuration pb_config;
373   SerializeConfig(expected_config, &pb_config);
374 
375   ConfigDescription actual_config;
376   std::string error;
377   ASSERT_TRUE(DeserializeConfigFromPb(pb_config, &actual_config, &error));
378   ASSERT_THAT(error, IsEmpty());
379   EXPECT_EQ(expected_config, actual_config);
380 }
381 
TEST(ProtoSerializeTest,SerializeDeserializeConfiguration)382 TEST(ProtoSerializeTest, SerializeDeserializeConfiguration) {
383   ExpectConfigSerializes("");
384 
385   ExpectConfigSerializes("mcc123");
386 
387   ExpectConfigSerializes("mnc123");
388 
389   ExpectConfigSerializes("en");
390   ExpectConfigSerializes("en-rGB");
391   ExpectConfigSerializes("b+en+GB");
392 
393   ExpectConfigSerializes("ldltr");
394   ExpectConfigSerializes("ldrtl");
395 
396   ExpectConfigSerializes("sw3600dp");
397 
398   ExpectConfigSerializes("w300dp");
399 
400   ExpectConfigSerializes("h400dp");
401 
402   ExpectConfigSerializes("small");
403   ExpectConfigSerializes("normal");
404   ExpectConfigSerializes("large");
405   ExpectConfigSerializes("xlarge");
406 
407   ExpectConfigSerializes("long");
408   ExpectConfigSerializes("notlong");
409 
410   ExpectConfigSerializes("round");
411   ExpectConfigSerializes("notround");
412 
413   ExpectConfigSerializes("widecg");
414   ExpectConfigSerializes("nowidecg");
415 
416   ExpectConfigSerializes("highdr");
417   ExpectConfigSerializes("lowdr");
418 
419   ExpectConfigSerializes("port");
420   ExpectConfigSerializes("land");
421   ExpectConfigSerializes("square");
422 
423   ExpectConfigSerializes("desk");
424   ExpectConfigSerializes("car");
425   ExpectConfigSerializes("television");
426   ExpectConfigSerializes("appliance");
427   ExpectConfigSerializes("watch");
428   ExpectConfigSerializes("vrheadset");
429 
430   ExpectConfigSerializes("night");
431   ExpectConfigSerializes("notnight");
432 
433   ExpectConfigSerializes("300dpi");
434   ExpectConfigSerializes("hdpi");
435 
436   ExpectConfigSerializes("notouch");
437   ExpectConfigSerializes("stylus");
438   ExpectConfigSerializes("finger");
439 
440   ExpectConfigSerializes("keysexposed");
441   ExpectConfigSerializes("keyshidden");
442   ExpectConfigSerializes("keyssoft");
443 
444   ExpectConfigSerializes("nokeys");
445   ExpectConfigSerializes("qwerty");
446   ExpectConfigSerializes("12key");
447 
448   ExpectConfigSerializes("navhidden");
449   ExpectConfigSerializes("navexposed");
450 
451   ExpectConfigSerializes("nonav");
452   ExpectConfigSerializes("dpad");
453   ExpectConfigSerializes("trackball");
454   ExpectConfigSerializes("wheel");
455 
456   ExpectConfigSerializes("300x200");
457 
458   ExpectConfigSerializes("v8");
459 
460   ExpectConfigSerializes(
461       "mcc123-mnc456-b+en+GB-ldltr-sw300dp-w300dp-h400dp-large-long-round-widecg-highdr-land-car-"
462       "night-xhdpi-stylus-keysexposed-qwerty-navhidden-dpad-300x200-v23");
463 }
464 
465 }  // namespace aapt
466