blob: acebedafe43d17e14098fd714ad14544de846d12 [file] [log] [blame]
Adam Lesinski458b8772016-04-25 14:20:21 -07001/*
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 Lesinskice5e56e2016-10-21 17:56:45 -070017#include "android-base/macros.h"
18
Adam Lesinski458b8772016-04-25 14:20:21 -070019#include "Flags.h"
Pierre Lecesneff759e62017-02-01 00:29:25 +000020#include "LoadedApk.h"
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -070021#include "ValueVisitor.h"
Adam Lesinski458b8772016-04-25 14:20:21 -070022#include "process/IResourceTableConsumer.h"
23#include "process/SymbolTable.h"
Adam Lesinski458b8772016-04-25 14:20:21 -070024
Adam Lesinskid5083f62017-01-16 15:07:21 -080025using android::StringPiece;
26
Adam Lesinski458b8772016-04-25 14:20:21 -070027namespace aapt {
28
29class DiffContext : public IAaptContext {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070030 public:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070031 const std::string& GetCompilationPackage() override { return empty_; }
Adam Lesinski458b8772016-04-25 14:20:21 -070032
Adam Lesinskice5e56e2016-10-21 17:56:45 -070033 uint8_t GetPackageId() override { return 0x0; }
Adam Lesinski458b8772016-04-25 14:20:21 -070034
Adam Lesinskice5e56e2016-10-21 17:56:45 -070035 IDiagnostics* GetDiagnostics() override { return &diagnostics_; }
Adam Lesinski458b8772016-04-25 14:20:21 -070036
Adam Lesinskice5e56e2016-10-21 17:56:45 -070037 NameMangler* GetNameMangler() override { return &name_mangler_; }
Adam Lesinski458b8772016-04-25 14:20:21 -070038
Adam Lesinskice5e56e2016-10-21 17:56:45 -070039 SymbolTable* GetExternalSymbols() override { return &symbol_table_; }
Adam Lesinski458b8772016-04-25 14:20:21 -070040
Adam Lesinskice5e56e2016-10-21 17:56:45 -070041 bool IsVerbose() override { return false; }
Adam Lesinski458b8772016-04-25 14:20:21 -070042
Adam Lesinskice5e56e2016-10-21 17:56:45 -070043 int GetMinSdkVersion() override { return 0; }
Adam Lesinskifb6312f2016-06-28 14:40:32 -070044
Adam Lesinskicacb28f2016-10-19 12:18:14 -070045 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070046 std::string empty_;
47 StdErrDiagnostics diagnostics_;
48 NameMangler name_mangler_ = NameMangler(NameManglerPolicy{});
49 SymbolTable symbol_table_;
Adam Lesinski458b8772016-04-25 14:20:21 -070050};
51
Adam Lesinskice5e56e2016-10-21 17:56:45 -070052static void EmitDiffLine(const Source& source, const StringPiece& message) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070053 std::cerr << source << ": " << message << "\n";
Adam Lesinski458b8772016-04-25 14:20:21 -070054}
55
Adam Lesinskice5e56e2016-10-21 17:56:45 -070056static bool IsSymbolVisibilityDifferent(const Symbol& symbol_a,
57 const Symbol& symbol_b) {
58 return symbol_a.state != symbol_b.state;
Adam Lesinski458b8772016-04-25 14:20:21 -070059}
60
61template <typename Id>
Adam Lesinskice5e56e2016-10-21 17:56:45 -070062static bool IsIdDiff(const Symbol& symbol_a, const Maybe<Id>& id_a,
63 const Symbol& symbol_b, const Maybe<Id>& id_b) {
64 if (symbol_a.state == SymbolState::kPublic ||
65 symbol_b.state == SymbolState::kPublic) {
66 return id_a != id_b;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070067 }
68 return false;
Adam Lesinski458b8772016-04-25 14:20:21 -070069}
70
Adam Lesinskice5e56e2016-10-21 17:56:45 -070071static bool EmitResourceConfigValueDiff(
72 IAaptContext* context, LoadedApk* apk_a, ResourceTablePackage* pkg_a,
73 ResourceTableType* type_a, ResourceEntry* entry_a,
74 ResourceConfigValue* config_value_a, LoadedApk* apk_b,
75 ResourceTablePackage* pkg_b, ResourceTableType* type_b,
76 ResourceEntry* entry_b, ResourceConfigValue* config_value_b) {
77 Value* value_a = config_value_a->value.get();
78 Value* value_b = config_value_b->value.get();
79 if (!value_a->Equals(value_b)) {
80 std::stringstream str_stream;
81 str_stream << "value " << pkg_a->name << ":" << type_a->type << "/"
82 << entry_a->name << " config=" << config_value_a->config
83 << " does not match:\n";
84 value_a->Print(&str_stream);
85 str_stream << "\n vs \n";
86 value_b->Print(&str_stream);
87 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -070088 return true;
89 }
90 return false;
Adam Lesinski458b8772016-04-25 14:20:21 -070091}
92
Adam Lesinskice5e56e2016-10-21 17:56:45 -070093static bool EmitResourceEntryDiff(IAaptContext* context, LoadedApk* apk_a,
94 ResourceTablePackage* pkg_a,
95 ResourceTableType* type_a,
96 ResourceEntry* entry_a, LoadedApk* apk_b,
97 ResourceTablePackage* pkg_b,
98 ResourceTableType* type_b,
99 ResourceEntry* entry_b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700100 bool diff = false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700101 for (std::unique_ptr<ResourceConfigValue>& config_value_a : entry_a->values) {
102 ResourceConfigValue* config_value_b =
103 entry_b->FindValue(config_value_a->config);
104 if (!config_value_b) {
105 std::stringstream str_stream;
106 str_stream << "missing " << pkg_a->name << ":" << type_a->type << "/"
107 << entry_a->name << " config=" << config_value_a->config;
108 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700109 diff = true;
110 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700111 diff |= EmitResourceConfigValueDiff(
112 context, apk_a, pkg_a, type_a, entry_a, config_value_a.get(), apk_b,
113 pkg_b, type_b, entry_b, config_value_b);
Adam Lesinski458b8772016-04-25 14:20:21 -0700114 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700115 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700116
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700117 // Check for any newly added config values.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700118 for (std::unique_ptr<ResourceConfigValue>& config_value_b : entry_b->values) {
119 ResourceConfigValue* config_value_a =
120 entry_a->FindValue(config_value_b->config);
121 if (!config_value_a) {
122 std::stringstream str_stream;
123 str_stream << "new config " << pkg_b->name << ":" << type_b->type << "/"
124 << entry_b->name << " config=" << config_value_b->config;
125 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700126 diff = true;
Adam Lesinski458b8772016-04-25 14:20:21 -0700127 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700128 }
129 return false;
Adam Lesinski458b8772016-04-25 14:20:21 -0700130}
131
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700132static bool EmitResourceTypeDiff(IAaptContext* context, LoadedApk* apk_a,
133 ResourceTablePackage* pkg_a,
134 ResourceTableType* type_a, LoadedApk* apk_b,
135 ResourceTablePackage* pkg_b,
136 ResourceTableType* type_b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700137 bool diff = false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700138 for (std::unique_ptr<ResourceEntry>& entry_a : type_a->entries) {
139 ResourceEntry* entry_b = type_b->FindEntry(entry_a->name);
140 if (!entry_b) {
141 std::stringstream str_stream;
142 str_stream << "missing " << pkg_a->name << ":" << type_a->type << "/"
143 << entry_a->name;
144 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700145 diff = true;
146 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700147 if (IsSymbolVisibilityDifferent(entry_a->symbol_status,
148 entry_b->symbol_status)) {
149 std::stringstream str_stream;
150 str_stream << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
151 << " has different visibility (";
152 if (entry_b->symbol_status.state == SymbolState::kPublic) {
153 str_stream << "PUBLIC";
Adam Lesinski458b8772016-04-25 14:20:21 -0700154 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700155 str_stream << "PRIVATE";
Adam Lesinski458b8772016-04-25 14:20:21 -0700156 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700157 str_stream << " vs ";
158 if (entry_a->symbol_status.state == SymbolState::kPublic) {
159 str_stream << "PUBLIC";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700160 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700161 str_stream << "PRIVATE";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700162 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700163 str_stream << ")";
164 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700165 diff = true;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700166 } else if (IsIdDiff(entry_a->symbol_status, entry_a->id,
167 entry_b->symbol_status, entry_b->id)) {
168 std::stringstream str_stream;
169 str_stream << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
170 << " has different public ID (";
171 if (entry_b->id) {
172 str_stream << "0x" << std::hex << entry_b->id.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700173 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700174 str_stream << "none";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700175 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700176 str_stream << " vs ";
177 if (entry_a->id) {
178 str_stream << "0x " << std::hex << entry_a->id.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700179 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700180 str_stream << "none";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700181 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700182 str_stream << ")";
183 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700184 diff = true;
185 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700186 diff |=
187 EmitResourceEntryDiff(context, apk_a, pkg_a, type_a, entry_a.get(),
188 apk_b, pkg_b, type_b, entry_b);
Adam Lesinski458b8772016-04-25 14:20:21 -0700189 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700190 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700191
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700192 // Check for any newly added entries.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700193 for (std::unique_ptr<ResourceEntry>& entry_b : type_b->entries) {
194 ResourceEntry* entry_a = type_a->FindEntry(entry_b->name);
195 if (!entry_a) {
196 std::stringstream str_stream;
197 str_stream << "new entry " << pkg_b->name << ":" << type_b->type << "/"
198 << entry_b->name;
199 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700200 diff = true;
Adam Lesinski458b8772016-04-25 14:20:21 -0700201 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700202 }
203 return diff;
Adam Lesinski458b8772016-04-25 14:20:21 -0700204}
205
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700206static bool EmitResourcePackageDiff(IAaptContext* context, LoadedApk* apk_a,
207 ResourceTablePackage* pkg_a,
208 LoadedApk* apk_b,
209 ResourceTablePackage* pkg_b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700210 bool diff = false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700211 for (std::unique_ptr<ResourceTableType>& type_a : pkg_a->types) {
212 ResourceTableType* type_b = pkg_b->FindType(type_a->type);
213 if (!type_b) {
214 std::stringstream str_stream;
215 str_stream << "missing " << pkg_a->name << ":" << type_a->type;
216 EmitDiffLine(apk_a->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700217 diff = true;
218 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700219 if (IsSymbolVisibilityDifferent(type_a->symbol_status,
220 type_b->symbol_status)) {
221 std::stringstream str_stream;
222 str_stream << pkg_a->name << ":" << type_a->type
223 << " has different visibility (";
224 if (type_b->symbol_status.state == SymbolState::kPublic) {
225 str_stream << "PUBLIC";
Adam Lesinski458b8772016-04-25 14:20:21 -0700226 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700227 str_stream << "PRIVATE";
Adam Lesinski458b8772016-04-25 14:20:21 -0700228 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700229 str_stream << " vs ";
230 if (type_a->symbol_status.state == SymbolState::kPublic) {
231 str_stream << "PUBLIC";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700232 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700233 str_stream << "PRIVATE";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700234 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700235 str_stream << ")";
236 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700237 diff = true;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700238 } else if (IsIdDiff(type_a->symbol_status, type_a->id,
239 type_b->symbol_status, type_b->id)) {
240 std::stringstream str_stream;
241 str_stream << pkg_a->name << ":" << type_a->type
242 << " has different public ID (";
243 if (type_b->id) {
244 str_stream << "0x" << std::hex << type_b->id.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700245 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700246 str_stream << "none";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700247 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700248 str_stream << " vs ";
249 if (type_a->id) {
250 str_stream << "0x " << std::hex << type_a->id.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700251 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700252 str_stream << "none";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700253 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700254 str_stream << ")";
255 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700256 diff = true;
257 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700258 diff |= EmitResourceTypeDiff(context, apk_a, pkg_a, type_a.get(), apk_b,
259 pkg_b, type_b);
Adam Lesinski458b8772016-04-25 14:20:21 -0700260 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700261 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700262
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700263 // Check for any newly added types.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700264 for (std::unique_ptr<ResourceTableType>& type_b : pkg_b->types) {
265 ResourceTableType* type_a = pkg_a->FindType(type_b->type);
266 if (!type_a) {
267 std::stringstream str_stream;
268 str_stream << "new type " << pkg_b->name << ":" << type_b->type;
269 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700270 diff = true;
Adam Lesinski458b8772016-04-25 14:20:21 -0700271 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700272 }
273 return diff;
Adam Lesinski458b8772016-04-25 14:20:21 -0700274}
275
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700276static bool EmitResourceTableDiff(IAaptContext* context, LoadedApk* apk_a,
277 LoadedApk* apk_b) {
278 ResourceTable* table_a = apk_a->GetResourceTable();
279 ResourceTable* table_b = apk_b->GetResourceTable();
Adam Lesinski458b8772016-04-25 14:20:21 -0700280
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700281 bool diff = false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700282 for (std::unique_ptr<ResourceTablePackage>& pkg_a : table_a->packages) {
283 ResourceTablePackage* pkg_b = table_b->FindPackage(pkg_a->name);
284 if (!pkg_b) {
285 std::stringstream str_stream;
286 str_stream << "missing package " << pkg_a->name;
287 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700288 diff = true;
289 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700290 if (pkg_a->id != pkg_b->id) {
291 std::stringstream str_stream;
292 str_stream << "package '" << pkg_a->name << "' has different id (";
293 if (pkg_b->id) {
294 str_stream << "0x" << std::hex << pkg_b->id.value();
Adam Lesinski458b8772016-04-25 14:20:21 -0700295 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700296 str_stream << "none";
Adam Lesinski458b8772016-04-25 14:20:21 -0700297 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700298 str_stream << " vs ";
299 if (pkg_a->id) {
300 str_stream << "0x" << std::hex << pkg_a->id.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700301 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700302 str_stream << "none";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700303 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700304 str_stream << ")";
305 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700306 diff = true;
307 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700308 diff |=
309 EmitResourcePackageDiff(context, apk_a, pkg_a.get(), apk_b, pkg_b);
Adam Lesinski458b8772016-04-25 14:20:21 -0700310 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700311 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700312
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700313 // Check for any newly added packages.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700314 for (std::unique_ptr<ResourceTablePackage>& pkg_b : table_b->packages) {
315 ResourceTablePackage* pkg_a = table_a->FindPackage(pkg_b->name);
316 if (!pkg_a) {
317 std::stringstream str_stream;
318 str_stream << "new package " << pkg_b->name;
319 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700320 diff = true;
Adam Lesinski458b8772016-04-25 14:20:21 -0700321 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700322 }
323 return diff;
Adam Lesinski458b8772016-04-25 14:20:21 -0700324}
325
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700326class ZeroingReferenceVisitor : public ValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700327 public:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700328 using ValueVisitor::Visit;
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700329
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700330 void Visit(Reference* ref) override {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700331 if (ref->name && ref->id) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700332 if (ref->id.value().package_id() == 0x7f) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700333 ref->id = {};
334 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700335 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700336 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700337};
338
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700339static void ZeroOutAppReferences(ResourceTable* table) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700340 ZeroingReferenceVisitor visitor;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700341 VisitAllValuesInTable(table, &visitor);
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700342}
343
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700344int Diff(const std::vector<StringPiece>& args) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700345 DiffContext context;
Adam Lesinski458b8772016-04-25 14:20:21 -0700346
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700347 Flags flags;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700348 if (!flags.Parse("aapt2 diff", args, &std::cerr)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700349 return 1;
350 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700351
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700352 if (flags.GetArgs().size() != 2u) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700353 std::cerr << "must have two apks as arguments.\n\n";
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700354 flags.Usage("aapt2 diff", &std::cerr);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700355 return 1;
356 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700357
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700358 std::unique_ptr<LoadedApk> apk_a =
Pierre Lecesneff759e62017-02-01 00:29:25 +0000359 LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[0]);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700360 std::unique_ptr<LoadedApk> apk_b =
Pierre Lecesneff759e62017-02-01 00:29:25 +0000361 LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[1]);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700362 if (!apk_a || !apk_b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700363 return 1;
364 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700365
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700366 // Zero out Application IDs in references.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700367 ZeroOutAppReferences(apk_a->GetResourceTable());
368 ZeroOutAppReferences(apk_b->GetResourceTable());
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700369
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700370 if (EmitResourceTableDiff(&context, apk_a.get(), apk_b.get())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700371 // We emitted a diff, so return 1 (failure).
372 return 1;
373 }
374 return 0;
Adam Lesinski458b8772016-04-25 14:20:21 -0700375}
376
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700377} // namespace aapt