From 255960857d7682fdad4fe461ac1348b618d1dbb2 Mon Sep 17 00:00:00 2001 From: Paulo Casanova Date: Fri, 7 Oct 2016 12:00:26 +0100 Subject: [PATCH] Added JNI interface for aapt2. Test: None (tests will be made on the Android Studio Tools project) --- tools/aapt2/Android.mk | 11 ++- tools/aapt2/jni/Aapt2.java | 44 +++++++++ tools/aapt2/jni/Makefile | 25 +++++ tools/aapt2/jni/aapt2_jni.cpp | 97 +++++++++++++++++++ .../aapt2/jni/com_android_tools_aapt2_Aapt2.h | 29 ++++++ 5 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 tools/aapt2/jni/Aapt2.java create mode 100644 tools/aapt2/jni/Makefile create mode 100644 tools/aapt2/jni/aapt2_jni.cpp create mode 100644 tools/aapt2/jni/com_android_tools_aapt2_Aapt2.h diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk index 6bfedf308b9c8..284c7877d0546 100644 --- a/tools/aapt2/Android.mk +++ b/tools/aapt2/Android.mk @@ -83,7 +83,7 @@ sources := \ sources += Format.proto -sourcesJni := +sourcesJni := jni/aapt2_jni.cpp testSources := \ compile/IdAssigner_test.cpp \ @@ -194,15 +194,18 @@ 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) +LOCAL_LDLIBS := $(hostLdLibs) +LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin) +LOCAL_LDLIBS_linux := $(hostLdLibs_linux) include $(BUILD_HOST_SHARED_LIBRARY) diff --git a/tools/aapt2/jni/Aapt2.java b/tools/aapt2/jni/Aapt2.java new file mode 100644 index 0000000000000..aed23de92fba2 --- /dev/null +++ b/tools/aapt2/jni/Aapt2.java @@ -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 arguments) { + nativeCompile(arguments); + } + + /** + * Invokes {@code aapt2} to perform linking. + * + * @param arguments arguments for linking (see {@code Link.cpp}) + */ + public static void link(List arguments) { + nativeLink(arguments); + } + + /** + * JNI call. + * + * @param arguments arguments for compilation (see {@code Compile.cpp}) + */ + private static native void nativeCompile(List arguments); + + /** + * JNI call. + * + * @param arguments arguments for linking (see {@code Link.cpp}) + */ + private static native void nativeLink(List arguments); +} + diff --git a/tools/aapt2/jni/Makefile b/tools/aapt2/jni/Makefile new file mode 100644 index 0000000000000..a9e628f45ce53 --- /dev/null +++ b/tools/aapt2/jni/Makefile @@ -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 index 0000000000000..dff77b972b084 --- /dev/null +++ b/tools/aapt2/jni/aapt2_jni.cpp @@ -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 +#include +#include +#include +#include + +#include + +#include "util/Util.h" + +#include "com_android_tools_aapt2_Aapt2.h" + +namespace aapt { + extern int compile(const std::vector& args); + extern int link(const std::vector& args); +} + +/* + * Converts a java List into C++ vector. + */ +static std::vector list_to_utfchars(JNIEnv *env, jobject obj) { + std::vector 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(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 extract_pieces( + const std::vector &strings) { + std::vector 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 compile_args_jni = list_to_utfchars(env, arguments_obj); + std::vector 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 link_args_jni = list_to_utfchars(env, arguments_obj); + std::vector 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 index 0000000000000..443b98f2590d9 --- /dev/null +++ b/tools/aapt2/jni/com_android_tools_aapt2_Aapt2.h @@ -0,0 +1,29 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* 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