blob: c8774687944c3236ffd5ee3e31604f4851df256c [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 Lesinskiceb9b2f2017-02-16 12:05:42 -080031 DiffContext() : name_mangler_({}), symbol_table_(&name_mangler_) {}
32
Adam Lesinskice5e56e2016-10-21 17:56:45 -070033 const std::string& GetCompilationPackage() override { return empty_; }
Adam Lesinski458b8772016-04-25 14:20:21 -070034
Adam Lesinskice5e56e2016-10-21 17:56:45 -070035 uint8_t GetPackageId() override { return 0x0; }
Adam Lesinski458b8772016-04-25 14:20:21 -070036
Adam Lesinskice5e56e2016-10-21 17:56:45 -070037 IDiagnostics* GetDiagnostics() override { return &diagnostics_; }
Adam Lesinski458b8772016-04-25 14:20:21 -070038
Adam Lesinskice5e56e2016-10-21 17:56:45 -070039 NameMangler* GetNameMangler() override { return &name_mangler_; }
Adam Lesinski458b8772016-04-25 14:20:21 -070040
Adam Lesinskice5e56e2016-10-21 17:56:45 -070041 SymbolTable* GetExternalSymbols() override { return &symbol_table_; }
Adam Lesinski458b8772016-04-25 14:20:21 -070042
Adam Lesinskice5e56e2016-10-21 17:56:45 -070043 bool IsVerbose() override { return false; }
Adam Lesinski458b8772016-04-25 14:20:21 -070044
Adam Lesinskice5e56e2016-10-21 17:56:45 -070045 int GetMinSdkVersion() override { return 0; }
Adam Lesinskifb6312f2016-06-28 14:40:32 -070046
Adam Lesinskicacb28f2016-10-19 12:18:14 -070047 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070048 std::string empty_;
49 StdErrDiagnostics diagnostics_;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080050 NameMangler name_mangler_;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070051 SymbolTable symbol_table_;
Adam Lesinski458b8772016-04-25 14:20:21 -070052};
53
Adam Lesinskice5e56e2016-10-21 17:56:45 -070054static void EmitDiffLine(const Source& source, const StringPiece& message) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070055 std::cerr << source << ": " << message << "\n";
Adam Lesinski458b8772016-04-25 14:20:21 -070056}
57
Adam Lesinskice5e56e2016-10-21 17:56:45 -070058static bool IsSymbolVisibilityDifferent(const Symbol& symbol_a,
59 const Symbol& symbol_b) {
60 return symbol_a.state != symbol_b.state;
Adam Lesinski458b8772016-04-25 14:20:21 -070061}
62
63template <typename Id>
Adam Lesinskice5e56e2016-10-21 17:56:45 -070064static bool IsIdDiff(const Symbol& symbol_a, const Maybe<Id>& id_a,
65 const Symbol& symbol_b, const Maybe<Id>& id_b) {
66 if (symbol_a.state == SymbolState::kPublic ||
67 symbol_b.state == SymbolState::kPublic) {
68 return id_a != id_b;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070069 }
70 return false;
Adam Lesinski458b8772016-04-25 14:20:21 -070071}
72
Adam Lesinskice5e56e2016-10-21 17:56:45 -070073static bool EmitResourceConfigValueDiff(
74 IAaptContext* context, LoadedApk* apk_a, ResourceTablePackage* pkg_a,
75 ResourceTableType* type_a, ResourceEntry* entry_a,
76 ResourceConfigValue* config_value_a, LoadedApk* apk_b,
77 ResourceTablePackage* pkg_b, ResourceTableType* type_b,
78 ResourceEntry* entry_b, ResourceConfigValue* config_value_b) {
79 Value* value_a = config_value_a->value.get();
80 Value* value_b = config_value_b->value.get();
81 if (!value_a->Equals(value_b)) {
82 std::stringstream str_stream;
83 str_stream << "value " << pkg_a->name << ":" << type_a->type << "/"
84 << entry_a->name << " config=" << config_value_a->config
85 << " does not match:\n";
86 value_a->Print(&str_stream);
87 str_stream << "\n vs \n";
88 value_b->Print(&str_stream);
89 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -070090 return true;
91 }
92 return false;
Adam Lesinski458b8772016-04-25 14:20:21 -070093}
94
Adam Lesinskice5e56e2016-10-21 17:56:45 -070095static bool EmitResourceEntryDiff(IAaptContext* context, LoadedApk* apk_a,
96 ResourceTablePackage* pkg_a,
97 ResourceTableType* type_a,
98 ResourceEntry* entry_a, LoadedApk* apk_b,
99 ResourceTablePackage* pkg_b,
100 ResourceTableType* type_b,
101 ResourceEntry* entry_b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700102 bool diff = false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700103 for (std::unique_ptr<ResourceConfigValue>& config_value_a : entry_a->values) {
104 ResourceConfigValue* config_value_b =
105 entry_b->FindValue(config_value_a->config);
106 if (!config_value_b) {
107 std::stringstream str_stream;
108 str_stream << "missing " << pkg_a->name << ":" << type_a->type << "/"
109 << entry_a->name << " config=" << config_value_a->config;
110 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700111 diff = true;
112 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700113 diff |= EmitResourceConfigValueDiff(
114 context, apk_a, pkg_a, type_a, entry_a, config_value_a.get(), apk_b,
115 pkg_b, type_b, entry_b, config_value_b);
Adam Lesinski458b8772016-04-25 14:20:21 -0700116 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700117 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700118
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700119 // Check for any newly added config values.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700120 for (std::unique_ptr<ResourceConfigValue>& config_value_b : entry_b->values) {
121 ResourceConfigValue* config_value_a =
122 entry_a->FindValue(config_value_b->config);
123 if (!config_value_a) {
124 std::stringstream str_stream;
125 str_stream << "new config " << pkg_b->name << ":" << type_b->type << "/"
126 << entry_b->name << " config=" << config_value_b->config;
127 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700128 diff = true;
Adam Lesinski458b8772016-04-25 14:20:21 -0700129 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700130 }
131 return false;
Adam Lesinski458b8772016-04-25 14:20:21 -0700132}
133
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700134static bool EmitResourceTypeDiff(IAaptContext* context, LoadedApk* apk_a,
135 ResourceTablePackage* pkg_a,
136 ResourceTableType* type_a, LoadedApk* apk_b,
137 ResourceTablePackage* pkg_b,
138 ResourceTableType* type_b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700139 bool diff = false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700140 for (std::unique_ptr<ResourceEntry>& entry_a : type_a->entries) {
141 ResourceEntry* entry_b = type_b->FindEntry(entry_a->name);
142 if (!entry_b) {
143 std::stringstream str_stream;
144 str_stream << "missing " << pkg_a->name << ":" << type_a->type << "/"
145 << entry_a->name;
146 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700147 diff = true;
148 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700149 if (IsSymbolVisibilityDifferent(entry_a->symbol_status,
150 entry_b->symbol_status)) {
151 std::stringstream str_stream;
152 str_stream << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
153 << " has different visibility (";
154 if (entry_b->symbol_status.state == SymbolState::kPublic) {
155 str_stream << "PUBLIC";
Adam Lesinski458b8772016-04-25 14:20:21 -0700156 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700157 str_stream << "PRIVATE";
Adam Lesinski458b8772016-04-25 14:20:21 -0700158 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700159 str_stream << " vs ";
160 if (entry_a->symbol_status.state == SymbolState::kPublic) {
161 str_stream << "PUBLIC";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700162 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700163 str_stream << "PRIVATE";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700164 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700165 str_stream << ")";
166 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700167 diff = true;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700168 } else if (IsIdDiff(entry_a->symbol_status, entry_a->id,
169 entry_b->symbol_status, entry_b->id)) {
170 std::stringstream str_stream;
171 str_stream << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
172 << " has different public ID (";
173 if (entry_b->id) {
174 str_stream << "0x" << std::hex << entry_b->id.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700175 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700176 str_stream << "none";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700177 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700178 str_stream << " vs ";
179 if (entry_a->id) {
180 str_stream << "0x " << std::hex << entry_a->id.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700181 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700182 str_stream << "none";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700183 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700184 str_stream << ")";
185 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700186 diff = true;
187 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700188 diff |=
189 EmitResourceEntryDiff(context, apk_a, pkg_a, type_a, entry_a.get(),
190 apk_b, pkg_b, type_b, entry_b);
Adam Lesinski458b8772016-04-25 14:20:21 -0700191 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700192 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700193
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700194 // Check for any newly added entries.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700195 for (std::unique_ptr<ResourceEntry>& entry_b : type_b->entries) {
196 ResourceEntry* entry_a = type_a->FindEntry(entry_b->name);
197 if (!entry_a) {
198 std::stringstream str_stream;
199 str_stream << "new entry " << pkg_b->name << ":" << type_b->type << "/"
200 << entry_b->name;
201 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700202 diff = true;
Adam Lesinski458b8772016-04-25 14:20:21 -0700203 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700204 }
205 return diff;
Adam Lesinski458b8772016-04-25 14:20:21 -0700206}
207
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700208static bool EmitResourcePackageDiff(IAaptContext* context, LoadedApk* apk_a,
209 ResourceTablePackage* pkg_a,
210 LoadedApk* apk_b,
211 ResourceTablePackage* pkg_b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700212 bool diff = false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700213 for (std::unique_ptr<ResourceTableType>& type_a : pkg_a->types) {
214 ResourceTableType* type_b = pkg_b->FindType(type_a->type);
215 if (!type_b) {
216 std::stringstream str_stream;
217 str_stream << "missing " << pkg_a->name << ":" << type_a->type;
218 EmitDiffLine(apk_a->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700219 diff = true;
220 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700221 if (IsSymbolVisibilityDifferent(type_a->symbol_status,
222 type_b->symbol_status)) {
223 std::stringstream str_stream;
224 str_stream << pkg_a->name << ":" << type_a->type
225 << " has different visibility (";
226 if (type_b->symbol_status.state == SymbolState::kPublic) {
227 str_stream << "PUBLIC";
Adam Lesinski458b8772016-04-25 14:20:21 -0700228 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700229 str_stream << "PRIVATE";
Adam Lesinski458b8772016-04-25 14:20:21 -0700230 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700231 str_stream << " vs ";
232 if (type_a->symbol_status.state == SymbolState::kPublic) {
233 str_stream << "PUBLIC";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700234 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700235 str_stream << "PRIVATE";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700236 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700237 str_stream << ")";
238 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700239 diff = true;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700240 } else if (IsIdDiff(type_a->symbol_status, type_a->id,
241 type_b->symbol_status, type_b->id)) {
242 std::stringstream str_stream;
243 str_stream << pkg_a->name << ":" << type_a->type
244 << " has different public ID (";
245 if (type_b->id) {
246 str_stream << "0x" << std::hex << type_b->id.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700247 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700248 str_stream << "none";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700249 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700250 str_stream << " vs ";
251 if (type_a->id) {
252 str_stream << "0x " << std::hex << type_a->id.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700253 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700254 str_stream << "none";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700255 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700256 str_stream << ")";
257 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700258 diff = true;
259 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700260 diff |= EmitResourceTypeDiff(context, apk_a, pkg_a, type_a.get(), apk_b,
261 pkg_b, type_b);
Adam Lesinski458b8772016-04-25 14:20:21 -0700262 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700263 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700264
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700265 // Check for any newly added types.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700266 for (std::unique_ptr<ResourceTableType>& type_b : pkg_b->types) {
267 ResourceTableType* type_a = pkg_a->FindType(type_b->type);
268 if (!type_a) {
269 std::stringstream str_stream;
270 str_stream << "new type " << pkg_b->name << ":" << type_b->type;
271 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700272 diff = true;
Adam Lesinski458b8772016-04-25 14:20:21 -0700273 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700274 }
275 return diff;
Adam Lesinski458b8772016-04-25 14:20:21 -0700276}
277
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700278static bool EmitResourceTableDiff(IAaptContext* context, LoadedApk* apk_a,
279 LoadedApk* apk_b) {
280 ResourceTable* table_a = apk_a->GetResourceTable();
281 ResourceTable* table_b = apk_b->GetResourceTable();
Adam Lesinski458b8772016-04-25 14:20:21 -0700282
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700283 bool diff = false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700284 for (std::unique_ptr<ResourceTablePackage>& pkg_a : table_a->packages) {
285 ResourceTablePackage* pkg_b = table_b->FindPackage(pkg_a->name);
286 if (!pkg_b) {
287 std::stringstream str_stream;
288 str_stream << "missing package " << pkg_a->name;
289 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700290 diff = true;
291 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700292 if (pkg_a->id != pkg_b->id) {
293 std::stringstream str_stream;
294 str_stream << "package '" << pkg_a->name << "' has different id (";
295 if (pkg_b->id) {
296 str_stream << "0x" << std::hex << pkg_b->id.value();
Adam Lesinski458b8772016-04-25 14:20:21 -0700297 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700298 str_stream << "none";
Adam Lesinski458b8772016-04-25 14:20:21 -0700299 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700300 str_stream << " vs ";
301 if (pkg_a->id) {
302 str_stream << "0x" << std::hex << pkg_a->id.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700303 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700304 str_stream << "none";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700305 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700306 str_stream << ")";
307 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700308 diff = true;
309 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700310 diff |=
311 EmitResourcePackageDiff(context, apk_a, pkg_a.get(), apk_b, pkg_b);
Adam Lesinski458b8772016-04-25 14:20:21 -0700312 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700313 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700314
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700315 // Check for any newly added packages.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700316 for (std::unique_ptr<ResourceTablePackage>& pkg_b : table_b->packages) {
317 ResourceTablePackage* pkg_a = table_a->FindPackage(pkg_b->name);
318 if (!pkg_a) {
319 std::stringstream str_stream;
320 str_stream << "new package " << pkg_b->name;
321 EmitDiffLine(apk_b->GetSource(), str_stream.str());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700322 diff = true;
Adam Lesinski458b8772016-04-25 14:20:21 -0700323 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700324 }
325 return diff;
Adam Lesinski458b8772016-04-25 14:20:21 -0700326}
327
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700328class ZeroingReferenceVisitor : public ValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700329 public:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700330 using ValueVisitor::Visit;
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700331
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700332 void Visit(Reference* ref) override {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700333 if (ref->name && ref->id) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700334 if (ref->id.value().package_id() == 0x7f) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700335 ref->id = {};
336 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700337 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700338 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700339};
340
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700341static void ZeroOutAppReferences(ResourceTable* table) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700342 ZeroingReferenceVisitor visitor;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700343 VisitAllValuesInTable(table, &visitor);
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700344}
345
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700346int Diff(const std::vector<StringPiece>& args) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700347 DiffContext context;
Adam Lesinski458b8772016-04-25 14:20:21 -0700348
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700349 Flags flags;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700350 if (!flags.Parse("aapt2 diff", args, &std::cerr)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700351 return 1;
352 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700353
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700354 if (flags.GetArgs().size() != 2u) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700355 std::cerr << "must have two apks as arguments.\n\n";
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700356 flags.Usage("aapt2 diff", &std::cerr);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700357 return 1;
358 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700359
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700360 std::unique_ptr<LoadedApk> apk_a =
Pierre Lecesneff759e62017-02-01 00:29:25 +0000361 LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[0]);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700362 std::unique_ptr<LoadedApk> apk_b =
Pierre Lecesneff759e62017-02-01 00:29:25 +0000363 LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[1]);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700364 if (!apk_a || !apk_b) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700365 return 1;
366 }
Adam Lesinski458b8772016-04-25 14:20:21 -0700367
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700368 // Zero out Application IDs in references.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700369 ZeroOutAppReferences(apk_a->GetResourceTable());
370 ZeroOutAppReferences(apk_b->GetResourceTable());
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700371
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700372 if (EmitResourceTableDiff(&context, apk_a.get(), apk_b.get())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700373 // We emitted a diff, so return 1 (failure).
374 return 1;
375 }
376 return 0;
Adam Lesinski458b8772016-04-25 14:20:21 -0700377}
378
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700379} // namespace aapt