OSDN Git Service

Added JNI interface for aapt2.
authorPaulo Casanova <pasc@google.com>
Fri, 7 Oct 2016 11:00:26 +0000 (12:00 +0100)
committerPaulo Casanova <pasc@google.com>
Wed, 19 Oct 2016 08:56:20 +0000 (09:56 +0100)
Test: None (tests will be made on the Android Studio Tools project)

Change-Id: I8e0ba8634500df7a8d19e0b381f46c3cd4652f5b

tools/aapt2/Android.mk
tools/aapt2/jni/Aapt2.java [new file with mode: 0644]
tools/aapt2/jni/Makefile [new file with mode: 0644]
tools/aapt2/jni/aapt2_jni.cpp [new file with mode: 0644]
tools/aapt2/jni/com_android_tools_aapt2_Aapt2.h [new file with mode: 0644]

index 6bfedf3..cc43a18 100644 (file)
@@ -83,7 +83,7 @@ sources := \
 
 sources += Format.proto
 
-sourcesJni :=
+sourcesJni := jni/aapt2_jni.cpp
 
 testSources := \
        compile/IdAssigner_test.cpp \
@@ -194,14 +194,14 @@ include $(BUILD_HOST_STATIC_LIBRARY)
 include $(CLEAR_VARS)
 LOCAL_MODULE := libaapt2_jni
 LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_MODULE_HOST_OS := darwin linux
 LOCAL_CFLAGS := $(cFlags)
 LOCAL_CFLAGS_darwin := $(cFlags_darwin)
 LOCAL_CFLAGS_windows := $(cFlags_windows)
 LOCAL_CPPFLAGS := $(cppFlags)
 LOCAL_C_INCLUDES := $(protoIncludes)
-LOCAL_SRC_FILES := $(sourcesJni)
-LOCAL_STATIC_LIBRARIES := libaapt2 $(hostStaticLibs)
+LOCAL_SRC_FILES := $(toolSources) $(sourcesJni)
+LOCAL_STATIC_LIBRARIES := libaapt2 libnativehelper $(hostStaticLibs)
 LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
 include $(BUILD_HOST_SHARED_LIBRARY)
 
diff --git a/tools/aapt2/jni/Aapt2.java b/tools/aapt2/jni/Aapt2.java
new file mode 100644 (file)
index 0000000..aed23de
--- /dev/null
@@ -0,0 +1,44 @@
+package com.android.tools.aapt2;
+
+import java.util.List;
+
+/**
+ * {@code aapt2} JNI interface. To use the {@code aapt2} native interface, the
+ * shared library must first be loaded and then a new instance of this class can
+ * be used to access the library.
+ */
+public class Aapt2 {
+
+  /**
+   * Invokes {@code aapt2} to perform resource compilation.
+   *
+   * @param arguments arguments for compilation (see {@code Compile.cpp})
+   */
+  public static void compile(List<String> arguments) {
+    nativeCompile(arguments);
+  }
+
+  /**
+   * Invokes {@code aapt2} to perform linking.
+   *
+   * @param arguments arguments for linking (see {@code Link.cpp})
+   */
+  public static void link(List<String> arguments) {
+    nativeLink(arguments);
+  }
+
+  /**
+   * JNI call.
+   *
+   * @param arguments arguments for compilation (see {@code Compile.cpp})
+   */
+  private static native void nativeCompile(List<String> arguments);
+
+  /**
+   * JNI call.
+   *
+   * @param arguments arguments for linking (see {@code Link.cpp})
+   */
+  private static native void nativeLink(List<String> arguments);
+}
+
diff --git a/tools/aapt2/jni/Makefile b/tools/aapt2/jni/Makefile
new file mode 100644 (file)
index 0000000..a9e628f
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# This Makefile will generate the JNI headers for the Aapt2 class.
+#
+
+AAPT2_PKG=com.android.tools.aapt2
+AAPT2_DIR=$(shell echo -n com/android/tools/aapt2 | tr . /)
+OUT=out
+OUT_CLASSES=$(OUT)/classes
+OUT_HEADERS=.
+
+AAPT2_JAVA=Aapt2.java
+AAPT2_CLASSES=$(OUT_CLASSES)/$(AAPT2_DIR)/Aapt2.class
+
+AAPT2_HEADERS=$(OUT_HEADERS)/Aapt2.h
+
+all: $(AAPT2_HEADERS)
+
+$(AAPT2_HEADERS): $(AAPT2_JAVA) $(AAPT2_CLASSES)
+       mkdir -p $(OUT_HEADERS)
+       $(JAVA_HOME)/bin/javah -d $(OUT_HEADERS) -cp $(OUT_CLASSES) $(AAPT2_PKG).Aapt2
+
+$(AAPT2_CLASSES): $(AAPT2_JAVA)
+       mkdir -p $(OUT_CLASSES)
+       javac -d $(OUT_CLASSES) $(AAPT2_JAVA)
+
diff --git a/tools/aapt2/jni/aapt2_jni.cpp b/tools/aapt2/jni/aapt2_jni.cpp
new file mode 100644 (file)
index 0000000..dff77b9
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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 <algorithm>
+#include <cassert>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include <ScopedUtfChars.h>
+
+#include "util/Util.h"
+
+#include "com_android_tools_aapt2_Aapt2.h"
+
+namespace aapt {
+    extern int compile(const std::vector<StringPiece>& args);
+    extern int link(const std::vector<StringPiece>& args);
+}
+
+/*
+ * 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");
+    assert(size_method_id != 0);
+    jint size = env->CallIntMethod(obj, size_method_id);
+    assert(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", "()Ljava/lang/Object;");
+    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);
+        assert(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<aapt::StringPiece> extract_pieces(
+        const std::vector<ScopedUtfChars> &strings) {
+    std::vector<aapt::StringPiece> pieces;
+  
+    std::for_each(
+            strings.begin(),
+            strings.end(),
+            [&pieces](const ScopedUtfChars &p) {
+              pieces.push_back(p.c_str());
+            });
+  
+    return pieces;
+}
+
+JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2_nativeCompile(
+        JNIEnv *env,
+        jclass aapt_obj,
+        jobject arguments_obj) {
+    std::vector<ScopedUtfChars> compile_args_jni = list_to_utfchars(env, arguments_obj);
+    std::vector<aapt::StringPiece> compile_args = extract_pieces(compile_args_jni);
+    aapt::compile(compile_args);
+}
+
+JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2_nativeLink(
+        JNIEnv *env,
+        jclass aapt_obj,
+        jobject arguments_obj) {
+    std::vector<ScopedUtfChars> link_args_jni = list_to_utfchars(env, arguments_obj);
+    std::vector<aapt::StringPiece> link_args = extract_pieces(link_args_jni);
+    aapt::link(link_args);
+}
diff --git a/tools/aapt2/jni/com_android_tools_aapt2_Aapt2.h b/tools/aapt2/jni/com_android_tools_aapt2_Aapt2.h
new file mode 100644 (file)
index 0000000..443b98f
--- /dev/null
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_android_tools_aapt2_Aapt2 */
+
+#ifndef _Included_com_android_tools_aapt2_Aapt2
+#define _Included_com_android_tools_aapt2_Aapt2
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     com_android_tools_aapt2_Aapt2
+ * Method:    nativeCompile
+ * Signature: (Ljava/util/List;)V
+ */
+JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2_nativeCompile
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_android_tools_aapt2_Aapt2
+ * Method:    nativeLink
+ * Signature: (Ljava/util/List;)V
+ */
+JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2_nativeLink
+  (JNIEnv *, jclass, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif