Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 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 | |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 17 | #include "proto/ProtoSerialize.h" |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 18 | |
| 19 | #include "ResourceTable.h" |
Adam Lesinski | d0f116b | 2016-07-08 15:00:32 -0700 | [diff] [blame] | 20 | #include "test/Test.h" |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 21 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 22 | using ::google::protobuf::io::StringOutputStream; |
Adam Lesinski | a45893a | 2017-05-30 15:19:02 -0700 | [diff] [blame] | 23 | using ::testing::NotNull; |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 24 | |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 25 | namespace aapt { |
| 26 | |
| 27 | TEST(TableProtoSerializer, SerializeSinglePackage) { |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 28 | std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); |
| 29 | std::unique_ptr<ResourceTable> table = |
| 30 | test::ResourceTableBuilder() |
| 31 | .SetPackageId("com.app.a", 0x7f) |
Adam Lesinski | 4488f1c | 2017-05-26 17:33:38 -0700 | [diff] [blame] | 32 | .AddFileReference("com.app.a:layout/main", ResourceId(0x7f020000), "res/layout/main.xml") |
| 33 | .AddReference("com.app.a:layout/other", ResourceId(0x7f020001), "com.app.a:layout/main") |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 34 | .AddString("com.app.a:string/text", {}, "hi") |
| 35 | .AddValue("com.app.a:id/foo", {}, util::make_unique<Id>()) |
Adam Lesinski | 4488f1c | 2017-05-26 17:33:38 -0700 | [diff] [blame] | 36 | .SetSymbolState("com.app.a:bool/foo", {}, SymbolState::kUndefined, true /*allow_new*/) |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 37 | .Build(); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 38 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 39 | Symbol public_symbol; |
| 40 | public_symbol.state = SymbolState::kPublic; |
| 41 | ASSERT_TRUE(table->SetSymbolState( |
| 42 | test::ParseNameOrDie("com.app.a:layout/main"), ResourceId(0x7f020000), |
| 43 | public_symbol, context->GetDiagnostics())); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 44 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 45 | Id* id = test::GetValue<Id>(table.get(), "com.app.a:id/foo"); |
| 46 | ASSERT_NE(nullptr, id); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 47 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 48 | // Make a plural. |
| 49 | std::unique_ptr<Plural> plural = util::make_unique<Plural>(); |
Adam Lesinski | a45893a | 2017-05-30 15:19:02 -0700 | [diff] [blame] | 50 | plural->values[Plural::One] = util::make_unique<String>(table->string_pool.MakeRef("one")); |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 51 | ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("com.app.a:plurals/hey"), |
| 52 | ConfigDescription{}, {}, std::move(plural), |
| 53 | context->GetDiagnostics())); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 54 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 55 | // Make a resource with different products. |
| 56 | ASSERT_TRUE(table->AddResource( |
| 57 | test::ParseNameOrDie("com.app.a:integer/one"), |
| 58 | test::ParseConfigOrDie("land"), {}, |
| 59 | test::BuildPrimitive(android::Res_value::TYPE_INT_DEC, 123u), |
| 60 | context->GetDiagnostics())); |
| 61 | ASSERT_TRUE(table->AddResource( |
| 62 | test::ParseNameOrDie("com.app.a:integer/one"), |
| 63 | test::ParseConfigOrDie("land"), "tablet", |
| 64 | test::BuildPrimitive(android::Res_value::TYPE_INT_DEC, 321u), |
| 65 | context->GetDiagnostics())); |
Adam Lesinski | e4bb9eb | 2016-02-12 22:18:51 -0800 | [diff] [blame] | 66 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 67 | // Make a reference with both resource name and resource ID. |
| 68 | // The reference should point to a resource outside of this table to test that |
| 69 | // both |
| 70 | // name and id get serialized. |
| 71 | Reference expected_ref; |
| 72 | expected_ref.name = test::ParseNameOrDie("android:layout/main"); |
| 73 | expected_ref.id = ResourceId(0x01020000); |
| 74 | ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("com.app.a:layout/abc"), |
| 75 | ConfigDescription::DefaultConfig(), {}, |
| 76 | util::make_unique<Reference>(expected_ref), |
| 77 | context->GetDiagnostics())); |
Adam Lesinski | 64587af | 2016-02-18 18:33:06 -0800 | [diff] [blame] | 78 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 79 | std::unique_ptr<pb::ResourceTable> pb_table = SerializeTableToPb(table.get()); |
Adam Lesinski | a45893a | 2017-05-30 15:19:02 -0700 | [diff] [blame] | 80 | ASSERT_THAT(pb_table, NotNull()); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 81 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 82 | std::unique_ptr<ResourceTable> new_table = DeserializeTableFromPb( |
| 83 | *pb_table, Source{"test"}, context->GetDiagnostics()); |
Adam Lesinski | a45893a | 2017-05-30 15:19:02 -0700 | [diff] [blame] | 84 | ASSERT_THAT(new_table, NotNull()); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 85 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 86 | Id* new_id = test::GetValue<Id>(new_table.get(), "com.app.a:id/foo"); |
Adam Lesinski | a45893a | 2017-05-30 15:19:02 -0700 | [diff] [blame] | 87 | ASSERT_THAT(new_id, NotNull()); |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 88 | EXPECT_EQ(id->IsWeak(), new_id->IsWeak()); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 89 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 90 | Maybe<ResourceTable::SearchResult> result = |
| 91 | new_table->FindResource(test::ParseNameOrDie("com.app.a:layout/main")); |
Adam Lesinski | a45893a | 2017-05-30 15:19:02 -0700 | [diff] [blame] | 92 | ASSERT_TRUE(result); |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 93 | EXPECT_EQ(SymbolState::kPublic, result.value().type->symbol_status.state); |
| 94 | EXPECT_EQ(SymbolState::kPublic, result.value().entry->symbol_status.state); |
Adam Lesinski | e4bb9eb | 2016-02-12 22:18:51 -0800 | [diff] [blame] | 95 | |
Adam Lesinski | 4488f1c | 2017-05-26 17:33:38 -0700 | [diff] [blame] | 96 | result = new_table->FindResource(test::ParseNameOrDie("com.app.a:bool/foo")); |
| 97 | ASSERT_TRUE(result); |
| 98 | EXPECT_EQ(SymbolState::kUndefined, result.value().entry->symbol_status.state); |
| 99 | EXPECT_TRUE(result.value().entry->symbol_status.allow_new); |
| 100 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 101 | // Find the product-dependent values |
| 102 | BinaryPrimitive* prim = test::GetValueForConfigAndProduct<BinaryPrimitive>( |
Adam Lesinski | 4488f1c | 2017-05-26 17:33:38 -0700 | [diff] [blame] | 103 | new_table.get(), "com.app.a:integer/one", test::ParseConfigOrDie("land"), ""); |
Adam Lesinski | a45893a | 2017-05-30 15:19:02 -0700 | [diff] [blame] | 104 | ASSERT_THAT(prim, NotNull()); |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 105 | EXPECT_EQ(123u, prim->value.data); |
Adam Lesinski | e4bb9eb | 2016-02-12 22:18:51 -0800 | [diff] [blame] | 106 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 107 | prim = test::GetValueForConfigAndProduct<BinaryPrimitive>( |
Adam Lesinski | 4488f1c | 2017-05-26 17:33:38 -0700 | [diff] [blame] | 108 | new_table.get(), "com.app.a:integer/one", test::ParseConfigOrDie("land"), "tablet"); |
Adam Lesinski | a45893a | 2017-05-30 15:19:02 -0700 | [diff] [blame] | 109 | ASSERT_THAT(prim, NotNull()); |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 110 | EXPECT_EQ(321u, prim->value.data); |
Adam Lesinski | 64587af | 2016-02-18 18:33:06 -0800 | [diff] [blame] | 111 | |
Adam Lesinski | 4488f1c | 2017-05-26 17:33:38 -0700 | [diff] [blame] | 112 | Reference* actual_ref = test::GetValue<Reference>(new_table.get(), "com.app.a:layout/abc"); |
Adam Lesinski | a45893a | 2017-05-30 15:19:02 -0700 | [diff] [blame] | 113 | ASSERT_THAT(actual_ref, NotNull()); |
| 114 | ASSERT_TRUE(actual_ref->name); |
| 115 | ASSERT_TRUE(actual_ref->id); |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 116 | EXPECT_EQ(expected_ref.name.value(), actual_ref->name.value()); |
| 117 | EXPECT_EQ(expected_ref.id.value(), actual_ref->id.value()); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | TEST(TableProtoSerializer, SerializeFileHeader) { |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 121 | std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 122 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 123 | ResourceFile f; |
| 124 | f.config = test::ParseConfigOrDie("hdpi-v9"); |
| 125 | f.name = test::ParseNameOrDie("com.app.a:layout/main"); |
| 126 | f.source.path = "res/layout-hdpi-v9/main.xml"; |
| 127 | f.exported_symbols.push_back( |
| 128 | SourcedResourceName{test::ParseNameOrDie("id/unchecked"), 23u}); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 129 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 130 | const std::string expected_data1 = "123"; |
| 131 | const std::string expected_data2 = "1234"; |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 132 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 133 | std::string output_str; |
| 134 | { |
| 135 | std::unique_ptr<pb::CompiledFile> pb_file1 = SerializeCompiledFileToPb(f); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 136 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 137 | f.name.entry = "__" + f.name.entry + "$0"; |
| 138 | std::unique_ptr<pb::CompiledFile> pb_file2 = SerializeCompiledFileToPb(f); |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 139 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 140 | StringOutputStream out_stream(&output_str); |
| 141 | CompiledFileOutputStream out_file_stream(&out_stream); |
| 142 | out_file_stream.WriteLittleEndian32(2); |
| 143 | out_file_stream.WriteCompiledFile(pb_file1.get()); |
| 144 | out_file_stream.WriteData(expected_data1.data(), expected_data1.size()); |
| 145 | out_file_stream.WriteCompiledFile(pb_file2.get()); |
| 146 | out_file_stream.WriteData(expected_data2.data(), expected_data2.size()); |
| 147 | ASSERT_FALSE(out_file_stream.HadError()); |
| 148 | } |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 149 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 150 | CompiledFileInputStream in_file_stream(output_str.data(), output_str.size()); |
| 151 | uint32_t num_files = 0; |
| 152 | ASSERT_TRUE(in_file_stream.ReadLittleEndian32(&num_files)); |
| 153 | ASSERT_EQ(2u, num_files); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 154 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 155 | // Read the first compiled file. |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 156 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 157 | pb::CompiledFile new_pb_file; |
| 158 | ASSERT_TRUE(in_file_stream.ReadCompiledFile(&new_pb_file)); |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 159 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 160 | std::unique_ptr<ResourceFile> file = DeserializeCompiledFileFromPb( |
| 161 | new_pb_file, Source("test"), context->GetDiagnostics()); |
Adam Lesinski | a45893a | 2017-05-30 15:19:02 -0700 | [diff] [blame] | 162 | ASSERT_THAT(file, NotNull()); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 163 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 164 | uint64_t offset, len; |
| 165 | ASSERT_TRUE(in_file_stream.ReadDataMetaData(&offset, &len)); |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 166 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 167 | std::string actual_data(output_str.data() + offset, len); |
| 168 | EXPECT_EQ(expected_data1, actual_data); |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 169 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 170 | // Expect the data to be aligned. |
| 171 | EXPECT_EQ(0u, offset & 0x03); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 172 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 173 | ASSERT_EQ(1u, file->exported_symbols.size()); |
Adam Lesinski | a45893a | 2017-05-30 15:19:02 -0700 | [diff] [blame] | 174 | EXPECT_EQ(test::ParseNameOrDie("id/unchecked"), file->exported_symbols[0].name); |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 175 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 176 | // Read the second compiled file. |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 177 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 178 | ASSERT_TRUE(in_file_stream.ReadCompiledFile(&new_pb_file)); |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 179 | |
Adam Lesinski | a45893a | 2017-05-30 15:19:02 -0700 | [diff] [blame] | 180 | file = DeserializeCompiledFileFromPb(new_pb_file, Source("test"), context->GetDiagnostics()); |
| 181 | ASSERT_THAT(file, NotNull()); |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 182 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 183 | ASSERT_TRUE(in_file_stream.ReadDataMetaData(&offset, &len)); |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 184 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 185 | actual_data = std::string(output_str.data() + offset, len); |
| 186 | EXPECT_EQ(expected_data2, actual_data); |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 187 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 188 | // Expect the data to be aligned. |
| 189 | EXPECT_EQ(0u, offset & 0x03); |
Adam Lesinski | 59e04c6 | 2016-02-04 15:59:23 -0800 | [diff] [blame] | 190 | } |
| 191 | |
Adam Lesinski | 64587af | 2016-02-18 18:33:06 -0800 | [diff] [blame] | 192 | TEST(TableProtoSerializer, DeserializeCorruptHeaderSafely) { |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 193 | ResourceFile f; |
| 194 | std::unique_ptr<pb::CompiledFile> pb_file = SerializeCompiledFileToPb(f); |
Adam Lesinski | 64587af | 2016-02-18 18:33:06 -0800 | [diff] [blame] | 195 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 196 | const std::string expected_data = "1234"; |
Adam Lesinski | 64587af | 2016-02-18 18:33:06 -0800 | [diff] [blame] | 197 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 198 | std::string output_str; |
| 199 | { |
| 200 | StringOutputStream out_stream(&output_str); |
| 201 | CompiledFileOutputStream out_file_stream(&out_stream); |
| 202 | out_file_stream.WriteLittleEndian32(1); |
| 203 | out_file_stream.WriteCompiledFile(pb_file.get()); |
| 204 | out_file_stream.WriteData(expected_data.data(), expected_data.size()); |
| 205 | ASSERT_FALSE(out_file_stream.HadError()); |
| 206 | } |
Adam Lesinski | 64587af | 2016-02-18 18:33:06 -0800 | [diff] [blame] | 207 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 208 | output_str[4] = 0xff; |
Adam Lesinski | 64587af | 2016-02-18 18:33:06 -0800 | [diff] [blame] | 209 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 210 | CompiledFileInputStream in_file_stream(output_str.data(), output_str.size()); |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 211 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 212 | uint32_t num_files = 0; |
| 213 | EXPECT_TRUE(in_file_stream.ReadLittleEndian32(&num_files)); |
| 214 | EXPECT_EQ(1u, num_files); |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 215 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 216 | pb::CompiledFile new_pb_file; |
| 217 | EXPECT_FALSE(in_file_stream.ReadCompiledFile(&new_pb_file)); |
Adam Lesinski | 5eeaadd | 2016-08-25 12:26:56 -0700 | [diff] [blame] | 218 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 219 | uint64_t offset, len; |
| 220 | EXPECT_FALSE(in_file_stream.ReadDataMetaData(&offset, &len)); |
Adam Lesinski | 64587af | 2016-02-18 18:33:06 -0800 | [diff] [blame] | 221 | } |
| 222 | |
Adam Lesinski | ce5e56e | 2016-10-21 17:56:45 -0700 | [diff] [blame] | 223 | } // namespace aapt |