diff options
Diffstat (limited to 'tools')
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/*/*.java -d out/ + * pushd out + * jar cfe lockedregioncodeinjection.jar lockedregioncodeinjection.Main */*.class + * popd + * + * # Make unit tests. + * javac -cp lib/junit-4.12.jar test/*/*.java -d out/ + * + * pushd out + * jar cfe test_input.jar lockedregioncodeinjection.Test */*.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 |