AAPT2: Follow symlinks when compiling

Bug: 62144459
Test: make AaptSymlinkTest
Change-Id: Idb3ab1ece17c52bb4fd174ec4c08a9e173289e55
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index 5adf04a..e09a3979 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -478,7 +478,8 @@
 
   {
     std::string content;
-    if (!android::base::ReadFileToString(path_data.source.path, &content)) {
+    if (!android::base::ReadFileToString(path_data.source.path, &content,
+                                         true /*follow_symlinks*/)) {
       context->GetDiagnostics()->Error(DiagMessage(path_data.source)
                                        << android::base::SystemErrorCodeToString(errno));
       return false;
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 24a687c..dd4b2ba 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -632,7 +632,7 @@
 static bool LoadStableIdMap(IDiagnostics* diag, const std::string& path,
                             std::unordered_map<ResourceName, ResourceId>* out_id_map) {
   std::string content;
-  if (!android::base::ReadFileToString(path, &content)) {
+  if (!android::base::ReadFileToString(path, &content, true /*follow_symlinks*/)) {
     diag->Error(DiagMessage(path) << "failed reading stable ID file");
     return false;
   }
diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.mk b/tools/aapt2/integration-tests/SymlinkTest/Android.mk
new file mode 100644
index 0000000..902fc65
--- /dev/null
+++ b/tools/aapt2/integration-tests/SymlinkTest/Android.mk
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_USE_AAPT2 := true
+LOCAL_PACKAGE_NAME := AaptSymlinkTest
+LOCAL_MODULE_TAGS := tests
+include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/SymlinkTest/AndroidManifest.xml b/tools/aapt2/integration-tests/SymlinkTest/AndroidManifest.xml
new file mode 100644
index 0000000..abbfa53
--- /dev/null
+++ b/tools/aapt2/integration-tests/SymlinkTest/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.aapt.symlinktest" />
diff --git a/tools/aapt2/integration-tests/SymlinkTest/res/drawable/white_3x3.9.png b/tools/aapt2/integration-tests/SymlinkTest/res/drawable/white_3x3.9.png
new file mode 120000
index 0000000..a7e8e2f
--- /dev/null
+++ b/tools/aapt2/integration-tests/SymlinkTest/res/drawable/white_3x3.9.png
@@ -0,0 +1 @@
+../../targets/white_3x3.9.png
\ No newline at end of file
diff --git a/tools/aapt2/integration-tests/SymlinkTest/res/layout/layout.xml b/tools/aapt2/integration-tests/SymlinkTest/res/layout/layout.xml
new file mode 120000
index 0000000..29c30e1
--- /dev/null
+++ b/tools/aapt2/integration-tests/SymlinkTest/res/layout/layout.xml
@@ -0,0 +1 @@
+../../targets/layout.xml
\ No newline at end of file
diff --git a/tools/aapt2/integration-tests/SymlinkTest/res/values/values.xml b/tools/aapt2/integration-tests/SymlinkTest/res/values/values.xml
new file mode 120000
index 0000000..554bb71
--- /dev/null
+++ b/tools/aapt2/integration-tests/SymlinkTest/res/values/values.xml
@@ -0,0 +1 @@
+../../targets/values.xml
\ No newline at end of file
diff --git a/tools/aapt2/integration-tests/SymlinkTest/targets/layout.xml b/tools/aapt2/integration-tests/SymlinkTest/targets/layout.xml
new file mode 100644
index 0000000..e5835ed
--- /dev/null
+++ b/tools/aapt2/integration-tests/SymlinkTest/targets/layout.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
diff --git a/tools/aapt2/integration-tests/SymlinkTest/targets/values.xml b/tools/aapt2/integration-tests/SymlinkTest/targets/values.xml
new file mode 100644
index 0000000..5b02843
--- /dev/null
+++ b/tools/aapt2/integration-tests/SymlinkTest/targets/values.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <bool name="foo">true</bool>
+</resources>
diff --git a/tools/aapt2/integration-tests/SymlinkTest/targets/white_3x3.9.png b/tools/aapt2/integration-tests/SymlinkTest/targets/white_3x3.9.png
new file mode 100644
index 0000000..1a3731b
--- /dev/null
+++ b/tools/aapt2/integration-tests/SymlinkTest/targets/white_3x3.9.png
Binary files differ
diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md
index 7e28ae7b..ac09b59 100644
--- a/tools/aapt2/readme.md
+++ b/tools/aapt2/readme.md
@@ -1,5 +1,9 @@
 # Android Asset Packaging Tool 2.0 (AAPT2) release notes
 
+## Version 2.17
+### `aapt2 compile ...`
+- Fixed an issue where symlinks would not be followed when compiling PNGs. (bug 62144459)
+
 ## Version 2.16
 ### `aapt2 link ...`
 - Versioning of XML files is more intelligent, using a small set of rules to degrade
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index d10351b..1bf2594 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -181,12 +181,13 @@
   return std::move(filemap);
 }
 
-bool AppendArgsFromFile(const StringPiece& path,
-                        std::vector<std::string>* out_arglist,
+bool AppendArgsFromFile(const StringPiece& path, std::vector<std::string>* out_arglist,
                         std::string* out_error) {
   std::string contents;
-  if (!android::base::ReadFileToString(path.to_string(), &contents)) {
-    if (out_error) *out_error = "failed to read argument-list file";
+  if (!android::base::ReadFileToString(path.to_string(), &contents, true /*follow_symlinks*/)) {
+    if (out_error) {
+      *out_error = "failed to read argument-list file";
+    }
     return false;
   }