summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/aapt/Android.bp115
-rw-r--r--tools/aapt/Android.mk90
-rw-r--r--tools/aapt/Command.cpp18
-rw-r--r--tools/aapt/Main.cpp17
-rw-r--r--tools/aapt2/Android.bp16
-rw-r--r--tools/aapt2/link/ManifestFixer.cpp1
-rw-r--r--tools/bit/Android.bp40
-rw-r--r--tools/bit/Android.mk44
-rw-r--r--tools/bit/adb.h2
-rw-r--r--tools/incident_report/Android.bp38
-rw-r--r--tools/incident_report/Android.mk44
-rw-r--r--tools/incident_section_gen/Android.bp33
-rw-r--r--tools/incident_section_gen/Android.mk37
-rw-r--r--tools/locked_region_code_injection/Android.mk15
-rw-r--r--tools/locked_region_code_injection/manifest.txt1
-rw-r--r--tools/locked_region_code_injection/src/lockedregioncodeinjection/LockFindingClassVisitor.java262
-rw-r--r--tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTarget.java61
-rw-r--r--tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTargetState.java34
-rw-r--r--tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTargetStateAnalysis.java109
-rw-r--r--tools/locked_region_code_injection/src/lockedregioncodeinjection/Main.java104
-rw-r--r--tools/locked_region_code_injection/src/lockedregioncodeinjection/Utils.java46
-rw-r--r--tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java253
-rw-r--r--tools/locked_region_code_injection/test/lockedregioncodeinjection/TestTarget.java64
-rw-r--r--tools/obbtool/Android.bp51
-rw-r--r--tools/obbtool/Android.mk47
-rw-r--r--tools/split-select/Android.bp108
-rw-r--r--tools/split-select/Android.mk119
-rw-r--r--tools/streaming_proto/Android.bp29
-rw-r--r--tools/streaming_proto/Android.mk13
-rw-r--r--tools/validatekeymaps/Android.bp30
-rw-r--r--tools/validatekeymaps/Android.mk33
31 files changed, 1423 insertions, 451 deletions
diff --git a/tools/aapt/Android.bp b/tools/aapt/Android.bp
new file mode 100644
index 000000000000..e26c9c3fdf63
--- /dev/null
+++ b/tools/aapt/Android.bp
@@ -0,0 +1,115 @@
+//
+// Copyright (C) 2014 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.
+//
+
+// ==========================================================
+// Setup some common variables for the different build
+// targets here.
+// ==========================================================
+
+cc_defaults {
+ name: "aapt_defaults",
+
+ static_libs: [
+ "libandroidfw",
+ "libpng",
+ "libutils",
+ "liblog",
+ "libcutils",
+ "libexpat",
+ "libziparchive",
+ "libbase",
+ "libz",
+ ],
+ group_static_libs: true,
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+
+ // This tool is prebuilt if we're doing an app-only build.
+ product_variables: {
+ pdk: {
+ enabled: false,
+ },
+ unbundled_build: {
+ enabled: false,
+ },
+ },
+}
+
+// ==========================================================
+// Build the host static library: libaapt
+// ==========================================================
+cc_library_host_static {
+ name: "libaapt",
+ defaults: ["aapt_defaults"],
+ target: {
+ darwin: {
+ cflags: ["-D_DARWIN_UNLIMITED_STREAMS"],
+ },
+ },
+ cflags: [
+ "-Wno-format-y2k",
+ "-DSTATIC_ANDROIDFW_FOR_TOOLS",
+ ],
+
+ srcs: [
+ "AaptAssets.cpp",
+ "AaptConfig.cpp",
+ "AaptUtil.cpp",
+ "AaptXml.cpp",
+ "ApkBuilder.cpp",
+ "Command.cpp",
+ "CrunchCache.cpp",
+ "FileFinder.cpp",
+ "Images.cpp",
+ "Package.cpp",
+ "pseudolocalize.cpp",
+ "Resource.cpp",
+ "ResourceFilter.cpp",
+ "ResourceIdCache.cpp",
+ "ResourceTable.cpp",
+ "SourcePos.cpp",
+ "StringPool.cpp",
+ "WorkQueue.cpp",
+ "XMLNode.cpp",
+ "ZipEntry.cpp",
+ "ZipFile.cpp",
+ ],
+}
+
+// ==========================================================
+// Build the host tests: libaapt_tests
+// ==========================================================
+cc_test_host {
+ name: "libaapt_tests",
+ defaults: ["aapt_defaults"],
+ srcs: [
+ "tests/AaptConfig_test.cpp",
+ "tests/AaptGroupEntry_test.cpp",
+ "tests/Pseudolocales_test.cpp",
+ "tests/ResourceFilter_test.cpp",
+ "tests/ResourceTable_test.cpp",
+ ],
+ static_libs: ["libaapt"],
+}
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 04f46d9b27fc..7bcf631da652 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -14,7 +14,6 @@
# limitations under the License.
#
-# This tool is prebuilt if we're doing an app-only build.
ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
# ==========================================================
@@ -23,37 +22,6 @@ ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
# ==========================================================
LOCAL_PATH:= $(call my-dir)
-aaptMain := Main.cpp
-aaptSources := \
- AaptAssets.cpp \
- AaptConfig.cpp \
- AaptUtil.cpp \
- AaptXml.cpp \
- ApkBuilder.cpp \
- Command.cpp \
- CrunchCache.cpp \
- FileFinder.cpp \
- Images.cpp \
- Package.cpp \
- pseudolocalize.cpp \
- Resource.cpp \
- ResourceFilter.cpp \
- ResourceIdCache.cpp \
- ResourceTable.cpp \
- SourcePos.cpp \
- StringPool.cpp \
- WorkQueue.cpp \
- XMLNode.cpp \
- ZipEntry.cpp \
- ZipFile.cpp
-
-aaptTests := \
- tests/AaptConfig_test.cpp \
- tests/AaptGroupEntry_test.cpp \
- tests/Pseudolocales_test.cpp \
- tests/ResourceFilter_test.cpp \
- tests/ResourceTable_test.cpp
-
aaptHostStaticLibs := \
libandroidfw \
libpng \
@@ -62,35 +30,10 @@ aaptHostStaticLibs := \
libcutils \
libexpat \
libziparchive \
- libbase
-
-aaptCFlags := -DAAPT_VERSION=\"$(BUILD_NUMBER_FROM_FILE)\"
-aaptCFlags += -Wall -Werror
+ libbase \
+ libz
-aaptHostLdLibs_linux := -lrt -ldl -lpthread
-
-# Statically link libz for MinGW (Win SDK under Linux),
-# and dynamically link for all others.
-aaptHostStaticLibs_windows := libz
-aaptHostLdLibs_linux += -lz
-aaptHostLdLibs_darwin := -lz
-
-
-# ==========================================================
-# Build the host static library: libaapt
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libaapt
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_CFLAGS := -Wno-format-y2k -DSTATIC_ANDROIDFW_FOR_TOOLS $(aaptCFlags)
-LOCAL_CPPFLAGS := $(aaptCppFlags)
-LOCAL_CFLAGS_darwin := -D_DARWIN_UNLIMITED_STREAMS
-LOCAL_SRC_FILES := $(aaptSources)
-LOCAL_STATIC_LIBRARIES := $(aaptHostStaticLibs)
-LOCAL_STATIC_LIBRARIES_windows := $(aaptHostStaticLibs_windows)
-
-include $(BUILD_HOST_STATIC_LIBRARY)
+aaptCFlags := -Wall -Werror
# ==========================================================
# Build the host executable: aapt
@@ -99,33 +42,10 @@ include $(CLEAR_VARS)
LOCAL_MODULE := aapt
LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_CFLAGS := $(aaptCFlags)
-LOCAL_CPPFLAGS := $(aaptCppFlags)
-LOCAL_LDLIBS_darwin := $(aaptHostLdLibs_darwin)
-LOCAL_LDLIBS_linux := $(aaptHostLdLibs_linux)
-LOCAL_SRC_FILES := $(aaptMain)
+LOCAL_CFLAGS := -DAAPT_VERSION=\"$(BUILD_NUMBER_FROM_FILE)\" $(aaptCFlags)
+LOCAL_SRC_FILES := Main.cpp
LOCAL_STATIC_LIBRARIES := libaapt $(aaptHostStaticLibs)
-LOCAL_STATIC_LIBRARIES_windows := $(aaptHostStaticLibs_windows)
include $(BUILD_HOST_EXECUTABLE)
-
-# ==========================================================
-# Build the host tests: libaapt_tests
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libaapt_tests
-LOCAL_CFLAGS := $(aaptCFlags)
-LOCAL_CPPFLAGS := $(aaptCppFlags)
-LOCAL_LDLIBS_darwin := $(aaptHostLdLibs_darwin)
-LOCAL_LDLIBS_linux := $(aaptHostLdLibs_linux)
-LOCAL_SRC_FILES := $(aaptTests)
-LOCAL_C_INCLUDES := $(LOCAL_PATH)
-LOCAL_STATIC_LIBRARIES := libaapt $(aaptHostStaticLibs)
-LOCAL_STATIC_LIBRARIES_windows := $(aaptHostStaticLibs_windows)
-
-include $(BUILD_HOST_NATIVE_TEST)
-
-
endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index ba731801e507..5e8580255197 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -29,24 +29,6 @@
using namespace android;
-#ifndef AAPT_VERSION
- #define AAPT_VERSION ""
-#endif
-
-/*
- * Show version info. All the cool kids do it.
- */
-int doVersion(Bundle* bundle)
-{
- if (bundle->getFileSpecCount() != 0) {
- printf("(ignoring extra arguments)\n");
- }
- printf("Android Asset Packaging Tool, v0.2-" AAPT_VERSION "\n");
-
- return 0;
-}
-
-
/*
* Open the file read only. The call fails if the file doesn't exist.
*
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 417b7ae087e1..d714687ee914 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -20,6 +20,23 @@ using namespace android;
static const char* gProgName = "aapt";
+#ifndef AAPT_VERSION
+ #define AAPT_VERSION ""
+#endif
+
+/*
+ * Show version info. All the cool kids do it.
+ */
+int doVersion(Bundle* bundle)
+{
+ if (bundle->getFileSpecCount() != 0) {
+ printf("(ignoring extra arguments)\n");
+ }
+ printf("Android Asset Packaging Tool, v0.2-" AAPT_VERSION "\n");
+
+ return 0;
+}
+
/*
* When running under Cygwin on Windows, this will convert slash-based
* paths into back-slash-based ones. Otherwise the ApptAssets file comparisons
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 1dc47f88ab92..046de469c7cc 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -24,7 +24,7 @@ toolSources = [
]
cc_defaults {
- name: "aapt_defaults",
+ name: "aapt2_defaults",
cflags: [
"-Wall",
"-Werror",
@@ -39,14 +39,9 @@ cc_defaults {
windows: {
enabled: true,
cflags: ["-Wno-maybe-uninitialized"],
- static_libs: ["libz"],
},
darwin: {
cflags: ["-D_DARWIN_UNLIMITED_STREAMS"],
- host_ldlibs: ["-lz"],
- },
- linux: {
- host_ldlibs: ["-lz"],
},
},
static_libs: [
@@ -59,6 +54,7 @@ cc_defaults {
"libpng",
"libbase",
"libprotobuf-cpp-lite",
+ "libz",
],
group_static_libs: true,
}
@@ -142,7 +138,7 @@ cc_library_host_static {
proto: {
export_proto_headers: true,
},
- defaults: ["aapt_defaults"],
+ defaults: ["aapt2_defaults"],
}
// ==========================================================
@@ -152,7 +148,7 @@ cc_library_host_shared {
name: "libaapt2_jni",
srcs: toolSources + ["jni/aapt2_jni.cpp"],
static_libs: ["libaapt2"],
- defaults: ["aapt_defaults"],
+ defaults: ["aapt2_defaults"],
}
// ==========================================================
@@ -168,7 +164,7 @@ cc_test_host {
"libaapt2",
"libgmock",
],
- defaults: ["aapt_defaults"],
+ defaults: ["aapt2_defaults"],
}
// ==========================================================
@@ -178,5 +174,5 @@ cc_binary_host {
name: "aapt2",
srcs: ["Main.cpp"] + toolSources,
static_libs: ["libaapt2"],
- defaults: ["aapt_defaults"],
+ defaults: ["aapt2_defaults"],
}
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 99fd95be2571..012bb5ecdeca 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -293,6 +293,7 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
manifest_action["instrumentation"]["meta-data"] = meta_data_action;
manifest_action["original-package"];
+ manifest_action["overlay"];
manifest_action["protected-broadcast"];
manifest_action["uses-permission"];
manifest_action["uses-permission-sdk-23"];
diff --git a/tools/bit/Android.bp b/tools/bit/Android.bp
new file mode 100644
index 000000000000..258e9b517f6d
--- /dev/null
+++ b/tools/bit/Android.bp
@@ -0,0 +1,40 @@
+//
+// 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.
+//
+
+// ==========================================================
+// Build the host executable: bit
+// ==========================================================
+cc_binary_host {
+ name: "bit",
+
+ srcs: [
+ "aapt.cpp",
+ "adb.cpp",
+ "command.cpp",
+ "main.cpp",
+ "make.cpp",
+ "print.cpp",
+ "util.cpp",
+ ],
+
+ static_libs: [
+ "libexpat",
+ "libinstrumentation",
+ "libjsoncpp",
+ ],
+
+ shared_libs: ["libprotobuf-cpp-full"],
+}
diff --git a/tools/bit/Android.mk b/tools/bit/Android.mk
deleted file mode 100644
index 57f46d490f24..000000000000
--- a/tools/bit/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# 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.
-#
-LOCAL_PATH:= $(call my-dir)
-
-# ==========================================================
-# Build the host executable: protoc-gen-javastream
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := bit
-
-LOCAL_MODULE_HOST_OS := linux darwin
-
-LOCAL_SRC_FILES := \
- aapt.cpp \
- adb.cpp \
- command.cpp \
- main.cpp \
- make.cpp \
- print.cpp \
- util.cpp
-
-LOCAL_STATIC_LIBRARIES := \
- libexpat \
- libinstrumentation \
- libjsoncpp
-
-LOCAL_SHARED_LIBRARIES := \
- libprotobuf-cpp-full
-
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/bit/adb.h b/tools/bit/adb.h
index dca80c853b45..f0774db933ba 100644
--- a/tools/bit/adb.h
+++ b/tools/bit/adb.h
@@ -17,7 +17,7 @@
#ifndef ADB_H
#define ADB_H
-#include "instrumentation_data.pb.h"
+#include "proto/instrumentation_data.pb.h"
#include <string>
diff --git a/tools/incident_report/Android.bp b/tools/incident_report/Android.bp
new file mode 100644
index 000000000000..6f21605a99a4
--- /dev/null
+++ b/tools/incident_report/Android.bp
@@ -0,0 +1,38 @@
+//
+// 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.
+//
+
+// ==========================================================
+// Build the host executable: incident_report
+// ==========================================================
+cc_binary_host {
+ name: "incident_report",
+
+ srcs: [
+ "generic_message.cpp",
+ "main.cpp",
+ "printer.cpp",
+ ],
+
+ shared_libs: [
+ "libplatformprotos",
+ "libprotobuf-cpp-full",
+ ],
+
+ cflags: ["-Wno-unused-parameter"],
+
+ // b/34740546, work around clang-tidy segmentation fault.
+ tidy_checks: ["-modernize*"],
+}
diff --git a/tools/incident_report/Android.mk b/tools/incident_report/Android.mk
deleted file mode 100644
index e57a95949e5a..000000000000
--- a/tools/incident_report/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# 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.
-#
-LOCAL_PATH:= $(call my-dir)
-
-# ==========================================================
-# Build the host executable: protoc-gen-javastream
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := incident_report
-
-LOCAL_C_INCLUDES := \
- external/protobuf/src
-
-LOCAL_SRC_FILES := \
- generic_message.cpp \
- main.cpp \
- printer.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libplatformprotos \
- libprotobuf-cpp-full
-
-# b/34740546, work around clang-tidy segmentation fault.
-LOCAL_TIDY_CHECKS := -modernize*
-
-LOCAL_C_FLAGS := \
- -Wno-unused-parameter
-include $(BUILD_HOST_EXECUTABLE)
-
-
diff --git a/tools/incident_section_gen/Android.bp b/tools/incident_section_gen/Android.bp
new file mode 100644
index 000000000000..7f8151f196ae
--- /dev/null
+++ b/tools/incident_section_gen/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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.
+//
+
+// ==========================================================
+// Build the host executable: incident-section-gen
+// ==========================================================
+cc_binary_host {
+ name: "incident-section-gen",
+ // b/34740546, work around clang-tidy segmentation fault.
+ tidy_checks: ["-modernize*"],
+ cflags: [
+ "-g",
+ "-O0",
+ ],
+ srcs: ["main.cpp"],
+ shared_libs: [
+ "libplatformprotos",
+ "libprotobuf-cpp-full",
+ ],
+}
diff --git a/tools/incident_section_gen/Android.mk b/tools/incident_section_gen/Android.mk
deleted file mode 100644
index 05490266576a..000000000000
--- a/tools/incident_section_gen/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# 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.
-#
-LOCAL_PATH:= $(call my-dir)
-
-# ==========================================================
-# Build the host executable: protoc-gen-javastream
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := incident-section-gen
-# b/34740546, work around clang-tidy segmentation fault.
-LOCAL_TIDY_CHECKS := -modernize*
-LOCAL_CFLAGS += -g -O0
-LOCAL_C_INCLUDES := \
- external/protobuf/src
-LOCAL_SRC_FILES := \
- main.cpp
-LOCAL_LDFLAGS := -ldl
-LOCAL_SHARED_LIBRARIES := \
- libplatformprotos \
- libprotobuf-cpp-full
-
-include $(BUILD_HOST_EXECUTABLE)
-
diff --git a/tools/locked_region_code_injection/Android.mk b/tools/locked_region_code_injection/Android.mk
new file mode 100644
index 000000000000..77d5163c1b78
--- /dev/null
+++ b/tools/locked_region_code_injection/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_JAR_MANIFEST := manifest.txt
+LOCAL_MODULE := lockedregioncodeinjection
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ asm-5.2 \
+ asm-commons-5.2 \
+ asm-tree-5.2 \
+ asm-analysis-5.2 \
+ guava-21.0 \
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/locked_region_code_injection/manifest.txt b/tools/locked_region_code_injection/manifest.txt
new file mode 100644
index 000000000000..4b9de003d392
--- /dev/null
+++ b/tools/locked_region_code_injection/manifest.txt
@@ -0,0 +1 @@
+Main-Class: lockedregioncodeinjection.Main
diff --git a/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockFindingClassVisitor.java b/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockFindingClassVisitor.java
new file mode 100644
index 000000000000..99ef8a7b707a
--- /dev/null
+++ b/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockFindingClassVisitor.java
@@ -0,0 +1,262 @@
+/*
+ * 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.
+ */
+package lockedregioncodeinjection;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.commons.TryCatchBlockSorter;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.InsnList;
+import org.objectweb.asm.tree.LabelNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TryCatchBlockNode;
+import org.objectweb.asm.tree.analysis.Analyzer;
+import org.objectweb.asm.tree.analysis.AnalyzerException;
+import org.objectweb.asm.tree.analysis.BasicValue;
+import org.objectweb.asm.tree.analysis.Frame;
+
+import static com.google.common.base.Preconditions.checkElementIndex;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * This visitor does two things:
+ *
+ * 1. Finds all the MONITOR_ENTER / MONITOR_EXIT in the byte code and insert the corresponding pre
+ * and post methods calls should it matches one of the given target type in the Configuration.
+ *
+ * 2. Find all methods that are synchronized and insert pre method calls in the beginning and post
+ * method calls just before all return instructions.
+ */
+class LockFindingClassVisitor extends ClassVisitor {
+ private String className = null;
+ private final List<LockTarget> targets;
+
+ public LockFindingClassVisitor(List<LockTarget> targets, ClassVisitor chain) {
+ super(Utils.ASM_VERSION, chain);
+ this.targets = targets;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+ String[] exceptions) {
+ assert this.className != null;
+ MethodNode mn = new TryCatchBlockSorter(null, access, name, desc, signature, exceptions);
+ MethodVisitor chain = super.visitMethod(access, name, desc, signature, exceptions);
+ return new LockFindingMethodVisitor(this.className, mn, chain);
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature, String superName,
+ String[] interfaces) {
+ this.className = name;
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ class LockFindingMethodVisitor extends MethodVisitor {
+ private String owner;
+ private MethodVisitor chain;
+
+ public LockFindingMethodVisitor(String owner, MethodNode mn, MethodVisitor chain) {
+ super(Opcodes.ASM5, mn);
+ assert owner != null;
+ this.owner = owner;
+ this.chain = chain;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void visitEnd() {
+ MethodNode mn = (MethodNode) mv;
+
+ Analyzer a = new Analyzer(new LockTargetStateAnalysis(targets));
+
+ LockTarget ownerMonitor = null;
+ if ((mn.access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+ for (LockTarget t : targets) {
+ if (t.getTargetDesc().equals("L" + owner + ";")) {
+ ownerMonitor = t;
+ }
+ }
+ }
+
+ try {
+ a.analyze(owner, mn);
+ } catch (AnalyzerException e) {
+ e.printStackTrace();
+ }
+ InsnList instructions = mn.instructions;
+
+ Frame[] frames = a.getFrames();
+ List<Frame> frameMap = new LinkedList<>();
+ frameMap.addAll(Arrays.asList(frames));
+
+ List<List<TryCatchBlockNode>> handlersMap = new LinkedList<>();
+
+ for (int i = 0; i < instructions.size(); i++) {
+ handlersMap.add(a.getHandlers(i));
+ }
+
+ if (ownerMonitor != null) {
+ AbstractInsnNode s = instructions.getFirst();
+ MethodInsnNode call = new MethodInsnNode(Opcodes.INVOKESTATIC,
+ ownerMonitor.getPreOwner(), ownerMonitor.getPreMethod(), "()V", false);
+ insertMethodCallBefore(mn, frameMap, handlersMap, s, 0, call);
+ }
+
+ for (int i = 0; i < instructions.size(); i++) {
+ AbstractInsnNode s = instructions.get(i);
+
+ if (s.getOpcode() == Opcodes.MONITORENTER) {
+ Frame f = frameMap.get(i);
+ BasicValue operand = (BasicValue) f.getStack(f.getStackSize() - 1);
+ if (operand instanceof LockTargetState) {
+ LockTargetState state = (LockTargetState) operand;
+ for (int j = 0; j < state.getTargets().size(); j++) {
+ LockTarget target = state.getTargets().get(j);
+ MethodInsnNode call = new MethodInsnNode(Opcodes.INVOKESTATIC,
+ target.getPreOwner(), target.getPreMethod(), "()V", false);
+ insertMethodCallAfter(mn, frameMap, handlersMap, s, i, call);
+ }
+ }
+ }
+
+ if (s.getOpcode() == Opcodes.MONITOREXIT) {
+ Frame f = frameMap.get(i);
+ BasicValue operand = (BasicValue) f.getStack(f.getStackSize() - 1);
+ if (operand instanceof LockTargetState) {
+ LockTargetState state = (LockTargetState) operand;
+ for (int j = 0; j < state.getTargets().size(); j++) {
+ // The instruction after a monitor_exit should be a label for the end of the implicit
+ // catch block that surrounds the synchronized block to call monitor_exit when an exception
+ // occurs.
+ checkState(instructions.get(i + 1).getType() == AbstractInsnNode.LABEL,
+ "Expected to find label after monitor exit");
+
+ int labelIndex = i + 1;
+ checkElementIndex(labelIndex, instructions.size());
+
+ LabelNode label = (LabelNode)instructions.get(labelIndex);
+
+ checkNotNull(handlersMap.get(i));
+ checkElementIndex(0, handlersMap.get(i).size());
+ checkState(handlersMap.get(i).get(0).end == label,
+ "Expected label to be the end of monitor exit's try block");
+
+ LockTarget target = state.getTargets().get(j);
+ MethodInsnNode call = new MethodInsnNode(Opcodes.INVOKESTATIC,
+ target.getPostOwner(), target.getPostMethod(), "()V", false);
+ insertMethodCallAfter(mn, frameMap, handlersMap, label, labelIndex, call);
+ }
+ }
+ }
+
+ if (ownerMonitor != null && (s.getOpcode() == Opcodes.RETURN
+ || s.getOpcode() == Opcodes.ARETURN || s.getOpcode() == Opcodes.DRETURN
+ || s.getOpcode() == Opcodes.FRETURN || s.getOpcode() == Opcodes.IRETURN)) {
+ MethodInsnNode call =
+ new MethodInsnNode(Opcodes.INVOKESTATIC, ownerMonitor.getPostOwner(),
+ ownerMonitor.getPostMethod(), "()V", false);
+ insertMethodCallBefore(mn, frameMap, handlersMap, s, i, call);
+ i++; // Skip ahead. Otherwise, we will revisit this instruction again.
+ }
+ }
+ super.visitEnd();
+ mn.accept(chain);
+ }
+ }
+
+ public static void insertMethodCallBefore(MethodNode mn, List<Frame> frameMap,
+ List<List<TryCatchBlockNode>> handlersMap, AbstractInsnNode node, int index,
+ MethodInsnNode call) {
+ List<TryCatchBlockNode> handlers = handlersMap.get(index);
+ InsnList instructions = mn.instructions;
+ LabelNode end = new LabelNode();
+ instructions.insert(node, end);
+ frameMap.add(index, null);
+ handlersMap.add(index, null);
+ instructions.insertBefore(node, call);
+ frameMap.add(index, null);
+ handlersMap.add(index, null);
+
+ LabelNode start = new LabelNode();
+ instructions.insert(node, start);
+ frameMap.add(index, null);
+ handlersMap.add(index, null);
+ updateCatchHandler(mn, handlers, start, end, handlersMap);
+ }
+
+ public static void insertMethodCallAfter(MethodNode mn, List<Frame> frameMap,
+ List<List<TryCatchBlockNode>> handlersMap, AbstractInsnNode node, int index,
+ MethodInsnNode call) {
+ List<TryCatchBlockNode> handlers = handlersMap.get(index + 1);
+ InsnList instructions = mn.instructions;
+
+ LabelNode end = new LabelNode();
+ instructions.insert(node, end);
+ frameMap.add(index + 1, null);
+ handlersMap.add(index + 1, null);
+
+ instructions.insert(node, call);
+ frameMap.add(index + 1, null);
+ handlersMap.add(index + 1, null);
+
+ LabelNode start = new LabelNode();
+ instructions.insert(node, start);
+ frameMap.add(index + 1, null);
+ handlersMap.add(index + 1, null);
+
+ updateCatchHandler(mn, handlers, start, end, handlersMap);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static void updateCatchHandler(MethodNode mn, List<TryCatchBlockNode> handlers,
+ LabelNode start, LabelNode end, List<List<TryCatchBlockNode>> handlersMap) {
+ if (handlers == null || handlers.size() == 0) {
+ return;
+ }
+
+ InsnList instructions = mn.instructions;
+ List<TryCatchBlockNode> newNodes = new ArrayList<>(handlers.size());
+ for (TryCatchBlockNode handler : handlers) {
+ if (!(instructions.indexOf(handler.start) <= instructions.indexOf(start)
+ && instructions.indexOf(end) <= instructions.indexOf(handler.end))) {
+ TryCatchBlockNode newNode =
+ new TryCatchBlockNode(start, end, handler.handler, handler.type);
+ newNodes.add(newNode);
+ for (int i = instructions.indexOf(start); i <= instructions.indexOf(end); i++) {
+ if (handlersMap.get(i) == null) {
+ handlersMap.set(i, new ArrayList<>());
+ }
+ handlersMap.get(i).add(newNode);
+ }
+ } else {
+ for (int i = instructions.indexOf(start); i <= instructions.indexOf(end); i++) {
+ if (handlersMap.get(i) == null) {
+ handlersMap.set(i, new ArrayList<>());
+ }
+ handlersMap.get(i).add(handler);
+ }
+ }
+ }
+ mn.tryCatchBlocks.addAll(0, newNodes);
+ }
+}
diff --git a/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTarget.java b/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTarget.java
new file mode 100644
index 000000000000..c5e59e3dc64d
--- /dev/null
+++ b/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTarget.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package lockedregioncodeinjection;
+
+/**
+ * Represent a specific class that is used for synchronization. A pre and post method can be
+ * specified to by the user to be called right after monitor_enter and after monitor_exit
+ * respectively.
+ */
+public class LockTarget {
+ public static final LockTarget NO_TARGET = new LockTarget("", null, null);
+
+ private final String targetDesc;
+ private final String pre;
+ private final String post;
+
+ public LockTarget(String targetDesc, String pre, String post) {
+ this.targetDesc = targetDesc;
+ this.pre = pre;
+ this.post = post;
+ }
+
+ public String getTargetDesc() {
+ return targetDesc;
+ }
+
+ public String getPre() {
+ return pre;
+ }
+
+ public String getPreOwner() {
+ return pre.substring(0, pre.lastIndexOf('.'));
+ }
+
+ public String getPreMethod() {
+ return pre.substring(pre.lastIndexOf('.') + 1);
+ }
+
+ public String getPost() {
+ return post;
+ }
+
+ public String getPostOwner() {
+ return post.substring(0, post.lastIndexOf('.'));
+ }
+
+ public String getPostMethod() {
+ return post.substring(post.lastIndexOf('.') + 1);
+ }
+}
diff --git a/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTargetState.java b/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTargetState.java
new file mode 100644
index 000000000000..99d841829132
--- /dev/null
+++ b/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTargetState.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package lockedregioncodeinjection;
+
+import java.util.List;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.analysis.BasicValue;
+
+public class LockTargetState extends BasicValue {
+ private final List<LockTarget> lockTargets;
+
+ /**
+ * @param type
+ */
+ public LockTargetState(Type type, List<LockTarget> lockTargets) {
+ super(type);
+ this.lockTargets = lockTargets;
+ }
+
+ public List<LockTarget> getTargets() {
+ return lockTargets;
+ }
+}
diff --git a/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTargetStateAnalysis.java b/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTargetStateAnalysis.java
new file mode 100644
index 000000000000..1002c88e9281
--- /dev/null
+++ b/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTargetStateAnalysis.java
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+package lockedregioncodeinjection;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.analysis.AnalyzerException;
+import org.objectweb.asm.tree.analysis.BasicInterpreter;
+import org.objectweb.asm.tree.analysis.BasicValue;
+
+/**
+ * A simple dataflow analysis to determine if the operands on the stack must be one of target lock
+ * class type.
+ */
+public class LockTargetStateAnalysis extends BasicInterpreter {
+
+ private final List<LockTarget> targetLocks;
+
+ public LockTargetStateAnalysis(List<LockTarget> targetLocks) {
+ this.targetLocks = targetLocks;
+ }
+
+ @Override
+ public BasicValue naryOperation(AbstractInsnNode inst, @SuppressWarnings("rawtypes") List args)
+ throws AnalyzerException {
+ // We target the return type of any invocation.
+
+ @SuppressWarnings("unchecked")
+ BasicValue base = super.naryOperation(inst, args);
+ if (!(inst instanceof MethodInsnNode)) {
+ return base;
+ }
+
+ MethodInsnNode invoke = (MethodInsnNode) inst;
+ Type returnType = Type.getReturnType(invoke.desc);
+ if (returnType.equals(Type.VOID_TYPE)) {
+ return base;
+ }
+
+ List<LockTarget> types = new ArrayList<>();
+
+ for (LockTarget target : targetLocks) {
+ if (returnType.getDescriptor().equals(target.getTargetDesc())) {
+ types.add(target);
+ }
+ }
+
+ return new LockTargetState(base.getType(), types);
+ }
+
+ @Override
+ public BasicValue newValue(Type type) {
+ BasicValue base = super.newValue(type);
+ List<LockTarget> types = new ArrayList<>();
+
+ if (type == null) {
+ return base;
+ }
+ for (LockTarget target : targetLocks) {
+ if (type.getDescriptor().equals(target.getTargetDesc())) {
+ types.add(target);
+ }
+ }
+
+ if (types.isEmpty()) {
+ return base;
+ }
+
+ return new LockTargetState(base.getType(), types);
+ }
+
+ @Override
+ public BasicValue merge(BasicValue v1, BasicValue v2) {
+ BasicValue base = super.merge(v1, v2);
+
+ if (!(v1 instanceof LockTargetState)) {
+ return base;
+ }
+ if (!(v2 instanceof LockTargetState)) {
+ return base;
+ }
+
+ LockTargetState state1 = (LockTargetState) v1;
+ LockTargetState state2 = (LockTargetState) v2;
+
+ List<LockTarget> newList = new ArrayList<>(state1.getTargets());
+ for (LockTarget otherTarget : state2.getTargets()) {
+ if (!newList.contains(otherTarget)) {
+ newList.add(otherTarget);
+ }
+ }
+
+ return new LockTargetState(base.getType(), newList);
+ }
+}
diff --git a/tools/locked_region_code_injection/src/lockedregioncodeinjection/Main.java b/tools/locked_region_code_injection/src/lockedregioncodeinjection/Main.java
new file mode 100644
index 000000000000..edb9a49f4106
--- /dev/null
+++ b/tools/locked_region_code_injection/src/lockedregioncodeinjection/Main.java
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+package lockedregioncodeinjection;
+
+import java.io.BufferedInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+
+public class Main {
+ public static void main(String[] args) throws IOException {
+ String inJar = null;
+ String outJar = null;
+
+ String legacyTargets = null;
+ String legacyPreMethods = null;
+ String legacyPostMethods = null;
+ for (int i = 0; i < args.length; i++) {
+ if ("-i".equals(args[i].trim())) {
+ i++;
+ inJar = args[i].trim();
+ } else if ("-o".equals(args[i].trim())) {
+ i++;
+ outJar = args[i].trim();
+ } else if ("--targets".equals(args[i].trim())) {
+ i++;
+ legacyTargets = args[i].trim();
+ } else if ("--pre".equals(args[i].trim())) {
+ i++;
+ legacyPreMethods = args[i].trim();
+ } else if ("--post".equals(args[i].trim())) {
+ i++;
+ legacyPostMethods = args[i].trim();
+ }
+
+ }
+
+ // TODO(acleung): Better help message than asserts.
+ assert inJar != null;
+ assert outJar != null;
+ assert legacyTargets == null || (legacyPreMethods != null && legacyPostMethods != null);
+
+ ZipFile zipSrc = new ZipFile(inJar);
+ ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outJar));
+ List<LockTarget> targets = null;
+ if (legacyTargets != null) {
+ targets = Utils.getTargetsFromLegacyJackConfig(legacyTargets, legacyPreMethods,
+ legacyPostMethods);
+ } else {
+ targets = Collections.emptyList();
+ }
+
+ Enumeration<? extends ZipEntry> srcEntries = zipSrc.entries();
+ while (srcEntries.hasMoreElements()) {
+ ZipEntry entry = srcEntries.nextElement();
+ ZipEntry newEntry = new ZipEntry(entry.getName());
+ zos.putNextEntry(newEntry);
+ BufferedInputStream bis = new BufferedInputStream(zipSrc.getInputStream(entry));
+
+ if (entry.getName().endsWith(".class")) {
+ convert(bis, zos, targets);
+ } else {
+ while (bis.available() > 0) {
+ zos.write(bis.read());
+ }
+ zos.closeEntry();
+ bis.close();
+ }
+ }
+ zos.finish();
+ zos.close();
+ zipSrc.close();
+ }
+
+ private static void convert(InputStream in, OutputStream out, List<LockTarget> targets)
+ throws IOException {
+ ClassReader cr = new ClassReader(in);
+ ClassWriter cw = new ClassWriter(0);
+ LockFindingClassVisitor cv = new LockFindingClassVisitor(targets, cw);
+ cr.accept(cv, 0);
+ byte[] data = cw.toByteArray();
+ out.write(data);
+ }
+}
diff --git a/tools/locked_region_code_injection/src/lockedregioncodeinjection/Utils.java b/tools/locked_region_code_injection/src/lockedregioncodeinjection/Utils.java
new file mode 100644
index 000000000000..d2a2e7b90f2b
--- /dev/null
+++ b/tools/locked_region_code_injection/src/lockedregioncodeinjection/Utils.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package lockedregioncodeinjection;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.objectweb.asm.Opcodes;
+
+public class Utils {
+
+ public static final int ASM_VERSION = Opcodes.ASM5;
+
+ /**
+ * Reads a comma separated configuration similar to the Jack definition.
+ */
+ public static List<LockTarget> getTargetsFromLegacyJackConfig(String classList,
+ String requestList, String resetList) {
+
+ String[] classes = classList.split(",");
+ String[] requests = requestList.split(",");
+ String[] resets = resetList.split(",");
+
+ int total = classes.length;
+ assert requests.length == total;
+ assert resets.length == total;
+
+ List<LockTarget> config = new ArrayList<LockTarget>();
+
+ for (int i = 0; i < total; i++) {
+ config.add(new LockTarget(classes[i], requests[i], resets[i]));
+ }
+
+ return config;
+ }
+}
diff --git a/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java b/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java
new file mode 100644
index 000000000000..b86954d5e377
--- /dev/null
+++ b/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java
@@ -0,0 +1,253 @@
+/*
+ * 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.
+ */
+package lockedregioncodeinjection;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * To run the unit tests:
+ *
+ * <pre>
+ * <code>
+ * set -x
+ *
+ * # Clean
+ * rm -fr out/*
+ *
+ * # Make booster
+ * javac -cp lib/asm-all-5.2.jar src&#47;*&#47;*.java -d out/
+ * pushd out
+ * jar cfe lockedregioncodeinjection.jar lockedregioncodeinjection.Main *&#47;*.class
+ * popd
+ *
+ * # Make unit tests.
+ * javac -cp lib/junit-4.12.jar test&#47;*&#47;*.java -d out/
+ *
+ * pushd out
+ * jar cfe test_input.jar lockedregioncodeinjection.Test *&#47;*.class
+ * popd
+ *
+ * # Run tool on unit tests.
+ * java -ea -cp lib/asm-all-5.2.jar:out/lockedregioncodeinjection.jar \
+ * lockedregioncodeinjection.Main \
+ * -i out/test_input.jar -o out/test_output.jar \
+ * --targets 'Llockedregioncodeinjection/TestTarget;' \
+ * --pre 'lockedregioncodeinjection/TestTarget.boost' \
+ * --post 'lockedregioncodeinjection/TestTarget.unboost'
+ *
+ * # Run unit tests.
+ * java -ea -cp lib/hamcrest-core-1.3.jar:lib/junit-4.12.jar:out/test_output.jar \
+ * org.junit.runner.JUnitCore lockedregioncodeinjection.TestMain
+ * </code>
+ * </pre>
+ */
+public class TestMain {
+ @Test
+ public void testSimpleSynchronizedBlock() {
+ TestTarget.resetCount();
+ TestTarget t = new TestTarget();
+
+ Assert.assertEquals(TestTarget.boostCount, 0);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+
+ synchronized (t) {
+ Assert.assertEquals(TestTarget.boostCount, 1);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+ TestTarget.invoke();
+ }
+
+ Assert.assertEquals(TestTarget.boostCount, 1);
+ Assert.assertEquals(TestTarget.unboostCount, 1);
+ Assert.assertEquals(TestTarget.invokeCount, 1);
+ }
+
+ @Test
+ public void testSimpleSynchronizedMethod() {
+ TestTarget.resetCount();
+ TestTarget t = new TestTarget();
+
+ Assert.assertEquals(TestTarget.boostCount, 0);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+
+ t.synchronizedCall();
+
+ Assert.assertEquals(TestTarget.boostCount, 1);
+ Assert.assertEquals(TestTarget.unboostCount, 1);
+ Assert.assertEquals(TestTarget.invokeCount, 1);
+ }
+
+ @Test
+ public void testSimpleSynchronizedMethod2() {
+ TestTarget.resetCount();
+ TestTarget t = new TestTarget();
+
+ Assert.assertEquals(TestTarget.boostCount, 0);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+
+ t.synchronizedCallReturnInt();
+
+ Assert.assertEquals(TestTarget.boostCount, 1);
+ Assert.assertEquals(TestTarget.unboostCount, 1);
+ Assert.assertEquals(TestTarget.invokeCount, 1);
+ }
+
+ @Test
+ public void testSimpleSynchronizedMethod3() {
+ TestTarget.resetCount();
+ TestTarget t = new TestTarget();
+
+ Assert.assertEquals(TestTarget.boostCount, 0);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+
+ t.synchronizedCallReturnObject();
+
+ Assert.assertEquals(TestTarget.boostCount, 1);
+ Assert.assertEquals(TestTarget.unboostCount, 1);
+ Assert.assertEquals(TestTarget.invokeCount, 1);
+ }
+
+ @SuppressWarnings("unused")
+ @Test
+ public void testCaughtException() {
+ TestTarget.resetCount();
+ TestTarget t = new TestTarget();
+ boolean caughtException = false;
+
+ Assert.assertEquals(TestTarget.boostCount, 0);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+
+ try {
+ synchronized (t) {
+ Assert.assertEquals(TestTarget.boostCount, 1);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+ if (true) {
+ throw new RuntimeException();
+ }
+ TestTarget.invoke();
+ }
+ } catch (Throwable e) {
+ caughtException = true;
+ }
+
+ Assert.assertEquals(TestTarget.boostCount, 1);
+ Assert.assertEquals(TestTarget.unboostCount, 1);
+ Assert.assertEquals(TestTarget.invokeCount, 0); // Not called
+ Assert.assertTrue(caughtException);
+ }
+
+ @SuppressWarnings("unused")
+ private void testUncaughtException() {
+ TestTarget t = new TestTarget();
+ synchronized (t) {
+ if (true) {
+ throw new RuntimeException();
+ }
+ TestTarget.invoke();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @Test
+ public void testHandledFinally() {
+ TestTarget.resetCount();
+ try {
+ testUncaughtException();
+ } catch (Throwable t) {
+
+ }
+ Assert.assertEquals(TestTarget.boostCount, 1);
+ Assert.assertEquals(TestTarget.unboostCount, 1);
+ Assert.assertEquals(TestTarget.invokeCount, 0); // Not called
+ }
+
+ @Test
+ public void testNestedSynchronizedBlock() {
+ TestTarget.resetCount();
+ TestTarget t = new TestTarget();
+
+ Assert.assertEquals(TestTarget.boostCount, 0);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+
+ synchronized (t) {
+ synchronized (t) {
+ synchronized (t) {
+ synchronized (t) {
+ synchronized (t) {
+ synchronized (t) {
+ Assert.assertEquals(TestTarget.boostCount, 6);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+ TestTarget.invoke();
+ }
+ Assert.assertEquals(TestTarget.unboostCount, 1);
+ }
+ Assert.assertEquals(TestTarget.unboostCount, 2);
+ }
+ Assert.assertEquals(TestTarget.unboostCount, 3);
+ }
+ Assert.assertEquals(TestTarget.unboostCount, 4);
+ }
+ Assert.assertEquals(TestTarget.unboostCount, 5);
+ }
+
+ Assert.assertEquals(TestTarget.boostCount, 6);
+ Assert.assertEquals(TestTarget.unboostCount, 6);
+ Assert.assertEquals(TestTarget.invokeCount, 1);
+ }
+
+ @Test
+ public void testMethodWithControlFlow() {
+ TestTarget.resetCount();
+ TestTarget t = new TestTarget();
+
+ Assert.assertEquals(TestTarget.boostCount, 0);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+
+ if ((t.hashCode() + " ").contains("1")) {
+ t.synchronizedCall();
+ } else {
+ t.synchronizedCall();
+ }
+
+ // Should only be boosted once.
+ Assert.assertEquals(TestTarget.boostCount, 1);
+ Assert.assertEquals(TestTarget.unboostCount, 1);
+ Assert.assertEquals(TestTarget.invokeCount, 1);
+ }
+
+ @Test
+ public void testUnboostThatThrows() {
+ TestTarget.resetCount();
+ TestTarget t = new TestTarget();
+ boolean asserted = false;
+
+ Assert.assertEquals(TestTarget.boostCount, 0);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+
+ try {
+ t.synchronizedThrowsOnUnboost();
+ } catch (RuntimeException e) {
+ asserted = true;
+ }
+
+ Assert.assertEquals(asserted, true);
+ Assert.assertEquals(TestTarget.boostCount, 1);
+ Assert.assertEquals(TestTarget.unboostCount, 0);
+ Assert.assertEquals(TestTarget.invokeCount, 1);
+ }
+
+}
diff --git a/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestTarget.java b/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestTarget.java
new file mode 100644
index 000000000000..d1c8f340a598
--- /dev/null
+++ b/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestTarget.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+package lockedregioncodeinjection;
+
+public class TestTarget {
+ public static int boostCount = 0;
+ public static int unboostCount = 0;
+ public static int invokeCount = 0;
+ public static boolean nextUnboostThrows = false;
+
+ public static void boost() {
+ boostCount++;
+ }
+
+ public static void unboost() {
+ if (nextUnboostThrows) {
+ nextUnboostThrows = false;
+ throw new RuntimeException();
+ }
+ unboostCount++;
+ }
+
+ public static void invoke() {
+ invokeCount++;
+ }
+
+ public static void resetCount() {
+ boostCount = 0;
+ unboostCount = 0;
+ invokeCount = 0;
+ }
+
+ public synchronized void synchronizedCall() {
+ invoke();
+ }
+
+ public synchronized int synchronizedCallReturnInt() {
+ invoke();
+ return 0;
+ }
+
+ public synchronized Object synchronizedCallReturnObject() {
+ invoke();
+ return this;
+ }
+
+ public void synchronizedThrowsOnUnboost() {
+ nextUnboostThrows = true;
+ synchronized(this) {
+ invoke();
+ }
+ }
+}
diff --git a/tools/obbtool/Android.bp b/tools/obbtool/Android.bp
new file mode 100644
index 000000000000..f87965860ce1
--- /dev/null
+++ b/tools/obbtool/Android.bp
@@ -0,0 +1,51 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+// Opaque Binary Blob (OBB) Tool
+//
+
+cc_binary_host {
+ name: "obbtool",
+
+ srcs: ["Main.cpp"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-mismatched-tags",
+ ],
+
+ static_libs: [
+ "libandroidfw",
+ "libutils",
+ "libcutils",
+ "liblog",
+ ],
+
+ // This tool is prebuilt if we're doing an app-only build.
+ product_variables: {
+ unbundled_build: {
+ enabled: false,
+ },
+ },
+}
+
+//####################################################
+cc_binary_host {
+ name: "pbkdf2gen",
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-mismatched-tags",
+ ],
+ srcs: ["pbkdf2gen.cpp"],
+ static_libs: ["libcrypto"],
+
+ // This tool is prebuilt if we're doing an app-only build.
+ product_variables: {
+ unbundled_build: {
+ enabled: false,
+ },
+ },
+}
diff --git a/tools/obbtool/Android.mk b/tools/obbtool/Android.mk
deleted file mode 100644
index 6dc306e85bc6..000000000000
--- a/tools/obbtool/Android.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# Copyright 2010 The Android Open Source Project
-#
-# Opaque Binary Blob (OBB) Tool
-#
-
-# This tool is prebuilt if we're doing an app-only build.
-ifeq ($(TARGET_BUILD_APPS),)
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- Main.cpp
-
-LOCAL_CFLAGS := -Wall -Werror -Wno-mismatched-tags
-
-#LOCAL_C_INCLUDES +=
-
-LOCAL_STATIC_LIBRARIES := \
- libandroidfw \
- libutils \
- libcutils \
- liblog
-
-ifeq ($(HOST_OS),linux)
-LOCAL_LDLIBS += -ldl -lpthread
-endif
-
-LOCAL_MODULE := obbtool
-
-include $(BUILD_HOST_EXECUTABLE)
-
-#####################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := pbkdf2gen
-LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS := -Wall -Werror -Wno-mismatched-tags
-LOCAL_SRC_FILES := pbkdf2gen.cpp
-LOCAL_LDLIBS += -ldl
-LOCAL_STATIC_LIBRARIES := libcrypto
-
-include $(BUILD_HOST_EXECUTABLE)
-
-#######################################################
-endif # TARGET_BUILD_APPS
diff --git a/tools/split-select/Android.bp b/tools/split-select/Android.bp
new file mode 100644
index 000000000000..ee822b7d7fa7
--- /dev/null
+++ b/tools/split-select/Android.bp
@@ -0,0 +1,108 @@
+//
+// Copyright (C) 2014 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.
+//
+
+// ==========================================================
+// Setup some common variables for the different build
+// targets here.
+// ==========================================================
+
+cc_defaults {
+ name: "split-select_defaults",
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ include_dirs: ["frameworks/base/tools"],
+ static_libs: [
+ "libaapt",
+ "libandroidfw",
+ "libpng",
+ "libutils",
+ "liblog",
+ "libcutils",
+ "libexpat",
+ "libziparchive",
+ "libbase",
+ "libz",
+ ],
+ group_static_libs: true,
+
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+
+ // This tool is prebuilt if we're doing an app-only build.
+ product_variables: {
+ pdk: {
+ enabled: false,
+ },
+ unbundled_build: {
+ enabled: false,
+ },
+ },
+}
+
+// ==========================================================
+// Build the host static library: libsplit-select
+// ==========================================================
+cc_library_host_static {
+ name: "libsplit-select",
+ defaults: ["split-select_defaults"],
+
+ srcs: [
+ "Abi.cpp",
+ "Grouper.cpp",
+ "Rule.cpp",
+ "RuleGenerator.cpp",
+ "SplitDescription.cpp",
+ "SplitSelector.cpp",
+ ],
+ cflags: ["-D_DARWIN_UNLIMITED_STREAMS"],
+
+}
+
+// ==========================================================
+// Build the host tests: libsplit-select_tests
+// ==========================================================
+cc_test_host {
+ name: "libsplit-select_tests",
+ defaults: ["split-select_defaults"],
+
+ srcs: [
+ "Grouper_test.cpp",
+ "Rule_test.cpp",
+ "RuleGenerator_test.cpp",
+ "SplitSelector_test.cpp",
+ "TestRules.cpp",
+ ],
+
+ static_libs: ["libsplit-select"],
+
+}
+
+// ==========================================================
+// Build the host executable: split-select
+// ==========================================================
+cc_binary_host {
+ name: "split-select",
+ defaults: ["split-select_defaults"],
+ srcs: ["Main.cpp"],
+
+ static_libs: ["libsplit-select"],
+}
diff --git a/tools/split-select/Android.mk b/tools/split-select/Android.mk
deleted file mode 100644
index 4a1511eae43a..000000000000
--- a/tools/split-select/Android.mk
+++ /dev/null
@@ -1,119 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-# This tool is prebuilt if we're doing an app-only build.
-ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
-
-# ==========================================================
-# Setup some common variables for the different build
-# targets here.
-# ==========================================================
-LOCAL_PATH:= $(call my-dir)
-
-main := Main.cpp
-sources := \
- Abi.cpp \
- Grouper.cpp \
- Rule.cpp \
- RuleGenerator.cpp \
- SplitDescription.cpp \
- SplitSelector.cpp
-
-testSources := \
- Grouper_test.cpp \
- Rule_test.cpp \
- RuleGenerator_test.cpp \
- SplitSelector_test.cpp \
- TestRules.cpp
-
-cIncludes := \
- external/zlib \
- frameworks/base/tools
-
-hostStaticLibs := \
- libaapt \
- libandroidfw \
- libpng \
- libutils \
- liblog \
- libcutils \
- libexpat \
- libziparchive \
- libbase
-
-cFlags := -Wall -Werror
-
-hostLdLibs_linux := -lrt -ldl -lpthread
-
-# Statically link libz for MinGW (Win SDK under Linux),
-# and dynamically link for all others.
-hostStaticLibs_windows := libz
-hostLdLibs_darwin := -lz
-hostLdLibs_linux += -lz
-
-
-# ==========================================================
-# Build the host static library: libsplit-select
-# ==========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libsplit-select
-LOCAL_MODULE_HOST_OS := darwin linux windows
-
-LOCAL_SRC_FILES := $(sources)
-LOCAL_STATIC_LIBRARIES := $(hostStaticLibs)
-LOCAL_C_INCLUDES := $(cIncludes)
-LOCAL_CFLAGS := $(cFlags) -D_DARWIN_UNLIMITED_STREAMS
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-
-# ==========================================================
-# Build the host tests: libsplit-select_tests
-# ==========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libsplit-select_tests
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(testSources)
-
-LOCAL_C_INCLUDES := $(cIncludes)
-LOCAL_STATIC_LIBRARIES := libsplit-select $(hostStaticLibs)
-LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
-LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin)
-LOCAL_LDLIBS_linux := $(hostLdLibs_linux)
-LOCAL_CFLAGS := $(cFlags)
-
-include $(BUILD_HOST_NATIVE_TEST)
-
-# ==========================================================
-# Build the host executable: split-select
-# ==========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := split-select
-LOCAL_MODULE_HOST_OS := darwin linux windows
-
-LOCAL_SRC_FILES := $(main)
-
-LOCAL_C_INCLUDES := $(cIncludes)
-LOCAL_STATIC_LIBRARIES := libsplit-select $(hostStaticLibs)
-LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
-LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin)
-LOCAL_LDLIBS_linux := $(hostLdLibs_linux)
-LOCAL_CFLAGS := $(cFlags)
-
-include $(BUILD_HOST_EXECUTABLE)
-
-endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/streaming_proto/Android.bp b/tools/streaming_proto/Android.bp
new file mode 100644
index 000000000000..24068e9ffe92
--- /dev/null
+++ b/tools/streaming_proto/Android.bp
@@ -0,0 +1,29 @@
+//
+// 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.
+//
+
+// ==========================================================
+// Build the host executable: protoc-gen-javastream
+// ==========================================================
+cc_binary_host {
+ name: "protoc-gen-javastream",
+ srcs: [
+ "Errors.cpp",
+ "string_utils.cpp",
+ "main.cpp",
+ ],
+
+ shared_libs: ["libprotoc"],
+}
diff --git a/tools/streaming_proto/Android.mk b/tools/streaming_proto/Android.mk
index 5a54fd10415d..ebb77a197883 100644
--- a/tools/streaming_proto/Android.mk
+++ b/tools/streaming_proto/Android.mk
@@ -16,19 +16,6 @@
LOCAL_PATH:= $(call my-dir)
# ==========================================================
-# Build the host executable: protoc-gen-javastream
-# ==========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := protoc-gen-javastream
-LOCAL_SRC_FILES := \
- Errors.cpp \
- string_utils.cpp \
- main.cpp
-LOCAL_SHARED_LIBRARIES := \
- libprotoc
-include $(BUILD_HOST_EXECUTABLE)
-
-# ==========================================================
# Build the java test
# ==========================================================
include $(CLEAR_VARS)
diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp
new file mode 100644
index 000000000000..6fb278c83f0a
--- /dev/null
+++ b/tools/validatekeymaps/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+// Keymap validation tool.
+//
+
+cc_binary_host {
+ name: "validatekeymaps",
+
+ srcs: ["Main.cpp"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ static_libs: [
+ "libinput",
+ "libutils",
+ "libcutils",
+ "liblog",
+ ],
+
+ // This tool is prebuilt if we're doing an app-only build.
+ product_variables: {
+ unbundled_build: {
+ enabled: false,
+ },
+ },
+}
diff --git a/tools/validatekeymaps/Android.mk b/tools/validatekeymaps/Android.mk
deleted file mode 100644
index 9af721de97db..000000000000
--- a/tools/validatekeymaps/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Copyright 2010 The Android Open Source Project
-#
-# Keymap validation tool.
-#
-
-# This tool is prebuilt if we're doing an app-only build.
-ifeq ($(TARGET_BUILD_APPS),)
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- Main.cpp
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_STATIC_LIBRARIES := \
- libinput \
- libutils \
- libcutils \
- liblog
-
-ifeq ($(HOST_OS),linux)
-LOCAL_LDLIBS += -ldl -lpthread
-endif
-
-LOCAL_MODULE := validatekeymaps
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_EXECUTABLE)
-
-endif # TARGET_BUILD_APPS