Merge "Revert "Remove the implementation of libaapt2_jni in build file""
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index bd0a4bc..740b44e 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -170,6 +170,16 @@
}
// ==========================================================
+// Build the host shared library: aapt2_jni
+// ==========================================================
+cc_library_host_shared {
+ name: "libaapt2_jni",
+ srcs: toolSources + ["jni/aapt2_jni.cpp"],
+ static_libs: ["libaapt2"],
+ defaults: ["aapt2_defaults"],
+}
+
+// ==========================================================
// Build the host tests: aapt2_tests
// ==========================================================
cc_test_host {
diff --git a/tools/aapt2/jni/ScopedUtfChars.h b/tools/aapt2/jni/ScopedUtfChars.h
new file mode 100644
index 0000000..a8c4b13
--- /dev/null
+++ b/tools/aapt2/jni/ScopedUtfChars.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef SCOPED_UTF_CHARS_H_included
+#define SCOPED_UTF_CHARS_H_included
+
+#include <string.h>
+#include <jni.h>
+
+#include "android-base/logging.h"
+
+// This file was copied with some minor modifications from libnativehelper.
+// As soon as libnativehelper can be compiled for Windows, this file should be
+// replaced with libnativehelper's implementation.
+class ScopedUtfChars {
+ public:
+ ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) {
+ CHECK(s != nullptr);
+ utf_chars_ = env->GetStringUTFChars(s, nullptr);
+ }
+
+ ScopedUtfChars(ScopedUtfChars&& rhs) :
+ env_(rhs.env_), string_(rhs.string_), utf_chars_(rhs.utf_chars_) {
+ rhs.env_ = nullptr;
+ rhs.string_ = nullptr;
+ rhs.utf_chars_ = nullptr;
+ }
+
+ ~ScopedUtfChars() {
+ if (utf_chars_) {
+ env_->ReleaseStringUTFChars(string_, utf_chars_);
+ }
+ }
+
+ ScopedUtfChars& operator=(ScopedUtfChars&& rhs) {
+ if (this != &rhs) {
+ // Delete the currently owned UTF chars.
+ this->~ScopedUtfChars();
+
+ // Move the rhs ScopedUtfChars and zero it out.
+ env_ = rhs.env_;
+ string_ = rhs.string_;
+ utf_chars_ = rhs.utf_chars_;
+ rhs.env_ = nullptr;
+ rhs.string_ = nullptr;
+ rhs.utf_chars_ = nullptr;
+ }
+ return *this;
+ }
+
+ const char* c_str() const {
+ return utf_chars_;
+ }
+
+ size_t size() const {
+ return strlen(utf_chars_);
+ }
+
+ const char& operator[](size_t n) const {
+ return utf_chars_[n];
+ }
+
+ private:
+ JNIEnv* env_;
+ jstring string_;
+ const char* utf_chars_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedUtfChars);
+};
+
+#endif // SCOPED_UTF_CHARS_H_included
diff --git a/tools/aapt2/jni/aapt2_jni.cpp b/tools/aapt2/jni/aapt2_jni.cpp
new file mode 100644
index 0000000..ec3c543
--- /dev/null
+++ b/tools/aapt2/jni/aapt2_jni.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "com_android_tools_aapt2_Aapt2Jni.h"
+
+#include <algorithm>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "android-base/logging.h"
+#include "ScopedUtfChars.h"
+
+#include "Diagnostics.h"
+#include "cmd/Compile.h"
+#include "cmd/Link.h"
+#include "util/Util.h"
+
+using android::StringPiece;
+
+/*
+ * Converts a java List<String> into C++ vector<ScopedUtfChars>.
+ */
+static std::vector<ScopedUtfChars> list_to_utfchars(JNIEnv *env, jobject obj) {
+ std::vector<ScopedUtfChars> converted;
+
+ // Call size() method on the list to know how many elements there are.
+ jclass list_cls = env->GetObjectClass(obj);
+ jmethodID size_method_id = env->GetMethodID(list_cls, "size", "()I");
+ CHECK(size_method_id != 0);
+ jint size = env->CallIntMethod(obj, size_method_id);
+ CHECK(size >= 0);
+
+ // Now, iterate all strings in the list
+ // (note: generic erasure means get() return an Object)
+ jmethodID get_method_id = env->GetMethodID(list_cls, "get", "(I)Ljava/lang/Object;");
+ CHECK(get_method_id != 0);
+ for (jint i = 0; i < size; i++) {
+ // Call get(i) to get the string in the ith position.
+ jobject string_obj_uncast = env->CallObjectMethod(obj, get_method_id, i);
+ CHECK(string_obj_uncast != nullptr);
+ jstring string_obj = static_cast<jstring>(string_obj_uncast);
+ converted.push_back(ScopedUtfChars(env, string_obj));
+ }
+
+ return converted;
+}
+
+/*
+ * Extracts all StringPiece from the ScopedUtfChars instances.
+ *
+ * The returned pieces can only be used while the original ones have not been
+ * destroyed.
+ */
+static std::vector<StringPiece> extract_pieces(const std::vector<ScopedUtfChars> &strings) {
+ std::vector<StringPiece> pieces;
+
+ std::for_each(
+ strings.begin(), strings.end(),
+ [&pieces](const ScopedUtfChars &p) { pieces.push_back(p.c_str()); });
+
+ return pieces;
+}
+
+class JniDiagnostics : public aapt::IDiagnostics {
+ public:
+ JniDiagnostics(JNIEnv* env, jobject diagnostics_obj)
+ : env_(env), diagnostics_obj_(diagnostics_obj) {
+ mid_ = NULL;
+ }
+
+ void Log(Level level, aapt::DiagMessageActual& actual_msg) override {
+ jint level_value;
+ switch (level) {
+ case Level::Error:
+ level_value = 3;
+ break;
+
+ case Level::Warn:
+ level_value = 2;
+ break;
+
+ case Level::Note:
+ level_value = 1;
+ break;
+ }
+ jstring message = env_->NewStringUTF(actual_msg.message.c_str());
+ jstring path = env_->NewStringUTF(actual_msg.source.path.c_str());
+ jlong line = -1;
+ if (actual_msg.source.line) {
+ line = actual_msg.source.line.value();
+ }
+ if (!mid_) {
+ jclass diagnostics_cls = env_->GetObjectClass(diagnostics_obj_);
+ mid_ = env_->GetMethodID(diagnostics_cls, "log", "(ILjava/lang/String;JLjava/lang/String;)V");
+ }
+ env_->CallVoidMethod(diagnostics_obj_, mid_, level_value, path, line, message);
+ }
+
+ private:
+ JNIEnv* env_;
+ jobject diagnostics_obj_;
+ jmethodID mid_;
+ DISALLOW_COPY_AND_ASSIGN(JniDiagnostics);
+};
+
+JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile(
+ JNIEnv* env, jclass aapt_obj, jobject arguments_obj, jobject diagnostics_obj) {
+ std::vector<ScopedUtfChars> compile_args_jni =
+ list_to_utfchars(env, arguments_obj);
+ std::vector<StringPiece> compile_args = extract_pieces(compile_args_jni);
+ JniDiagnostics diagnostics(env, diagnostics_obj);
+ return aapt::CompileCommand(&diagnostics).Execute(compile_args, &std::cerr);
+}
+
+JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink(JNIEnv* env,
+ jclass aapt_obj,
+ jobject arguments_obj,
+ jobject diagnostics_obj) {
+ std::vector<ScopedUtfChars> link_args_jni =
+ list_to_utfchars(env, arguments_obj);
+ std::vector<StringPiece> link_args = extract_pieces(link_args_jni);
+ JniDiagnostics diagnostics(env, diagnostics_obj);
+ return aapt::LinkCommand(&diagnostics).Execute(link_args, &std::cerr);
+}
+
+JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_ping(
+ JNIEnv *env, jclass aapt_obj) {
+ // This is just a no-op method to see if the library has been loaded.
+}
diff --git a/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h b/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h
new file mode 100644
index 0000000..3cd9865
--- /dev/null
+++ b/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h
@@ -0,0 +1,37 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_android_tools_aapt2_Aapt2Jni */
+
+#ifndef _Included_com_android_tools_aapt2_Aapt2Jni
+#define _Included_com_android_tools_aapt2_Aapt2Jni
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_android_tools_aapt2_Aapt2Jni
+ * Method: ping
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_ping
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_android_tools_aapt2_Aapt2Jni
+ * Method: nativeCompile
+ * Signature: (Ljava/util/List;Lcom/android/tools/aapt2/Aapt2JniDiagnostics;)I
+ */
+JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile(JNIEnv*, jclass, jobject,
+ jobject);
+
+/*
+ * Class: com_android_tools_aapt2_Aapt2Jni
+ * Method: nativeLink
+ * Signature: (Ljava/util/List;Lcom/android/tools/aapt2/Aapt2JniDiagnostics;)I
+ */
+JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink(JNIEnv*, jclass, jobject,
+ jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif