Merge "Ensure the correctness of fast verify"
diff --git a/Android.mk b/Android.mk
index 1a5daff..526cd59 100644
--- a/Android.mk
+++ b/Android.mk
@@ -483,6 +483,28 @@
build-art-target: $(TARGET_OUT_EXECUTABLES)/art $(ART_TARGET_DEPENDENCIES) $(TARGET_CORE_IMG_OUTS)
########################################################################
+# Workaround for not using symbolic links for linker and bionic libraries
+# in a minimal setup (eg buildbot or golem).
+########################################################################
+
+PRIVATE_BIONIC_FILES := \
+ bin/bootstrap/linker \
+ bin/bootstrap/linker64 \
+ lib/bootstrap/libc.so \
+ lib/bootstrap/libm.so \
+ lib/bootstrap/libdl.so \
+ lib64/bootstrap/libc.so \
+ lib64/bootstrap/libm.so \
+ lib64/bootstrap/libdl.so
+
+.PHONY: art-bionic-files
+art-bionic-files: libc.bootstrap libdl.bootstrap libm.bootstrap linker
+ for f in $(PRIVATE_BIONIC_FILES); do \
+ tf=$(TARGET_OUT)/$$f; \
+ if [ -f $$tf ]; then cp -f $$tf $$(echo $$tf | sed 's,bootstrap/,,'); fi; \
+ done
+
+########################################################################
# Phony target for only building what go/lem requires for pushing ART on /data.
.PHONY: build-art-target-golem
@@ -514,7 +536,8 @@
$(TARGET_CORE_IMG_OUT_BASE).art \
$(TARGET_CORE_IMG_OUT_BASE)-interpreter.art \
libc.bootstrap libdl.bootstrap libm.bootstrap \
- icu-data-art-test
+ icu-data-art-test \
+ art-bionic-files
# remove debug libraries from public.libraries.txt because golem builds
# won't have it.
sed -i '/libartd.so/d' $(TARGET_OUT)/etc/public.libraries.txt
diff --git a/adbconnection/adbconnection.cc b/adbconnection/adbconnection.cc
index b6d6600..e1b5b62 100644
--- a/adbconnection/adbconnection.cc
+++ b/adbconnection/adbconnection.cc
@@ -28,7 +28,7 @@
#include "jni/java_vm_ext.h"
#include "jni/jni_env_ext.h"
#include "mirror/throwable.h"
-#include "nativehelper/ScopedLocalRef.h"
+#include "nativehelper/scoped_local_ref.h"
#include "runtime-inl.h"
#include "runtime_callbacks.h"
#include "scoped_thread_state_change-inl.h"
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 67d85c1..bd306b6 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -384,6 +384,7 @@
art_hiddenapi_tests \
art_imgdiag_tests \
art_libartbase_tests \
+ art_libartpalette_tests \
art_libdexfile_external_tests \
art_libdexfile_support_tests \
art_libdexfile_tests \
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index d53a7f2..47a1e4b 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -13,11 +13,12 @@
]
// - Base requirements (libraries).
art_runtime_base_native_shared_libs = [
+ "libadbconnection",
"libart",
"libart-compiler",
+ "libdexfile_external",
"libopenjdkjvm",
"libopenjdkjvmti",
- "libadbconnection",
]
bionic_native_shared_libs = [
"libc",
@@ -29,17 +30,23 @@
]
// - Debug variants (binaries for which a 32-bit version is preferred).
art_runtime_debug_binaries_prefer32 = [
- "dex2oatd",
"dexoptanalyzerd",
"profmand",
]
+art_runtime_debug_binaries_prefer32_device = [
+ "dex2oatd",
+]
+art_runtime_debug_binaries_both_host = [
+ "dex2oatd",
+]
+
// - Debug variants (libraries).
art_runtime_debug_native_shared_libs = [
+ "libadbconnectiond",
"libartd",
"libartd-compiler",
"libopenjdkjvmd",
"libopenjdkjvmtid",
- "libadbconnectiond",
]
libcore_debug_native_shared_libs = [
"libopenjdkd",
@@ -165,7 +172,8 @@
},
prefer32: {
binaries: art_runtime_base_binaries_prefer32
- + art_runtime_debug_binaries_prefer32,
+ + art_runtime_debug_binaries_prefer32
+ + art_runtime_debug_binaries_prefer32_device,
},
first: {
binaries: art_tools_device_binaries,
@@ -188,6 +196,8 @@
host_supported: true,
device_supported: false,
manifest: "manifest.json",
+ java_libs: libcore_target_java_libs,
+ ignore_system_library_special_case: true,
native_shared_libs: art_runtime_base_native_shared_libs
+ art_runtime_debug_native_shared_libs
+ libcore_native_shared_libs
@@ -196,7 +206,8 @@
both: {
// TODO: Add logic to create a `dalvikvm` symlink to `dalvikvm32` or `dalvikvm64`
// (see `symlink_preferred_arch` in art/dalvikvm/Android.bp).
- binaries: art_runtime_base_binaries_both,
+ binaries: art_runtime_base_binaries_both
+ + art_runtime_debug_binaries_both_host,
},
first: {
binaries: art_tools_host_binaries
@@ -209,5 +220,14 @@
darwin: {
enabled: false,
},
+ linux_bionic: {
+ enabled: true,
+ multilib: {
+ both: {
+ native_shared_libs: bionic_native_shared_libs,
+ binaries: bionic_binaries_both,
+ }
+ }
+ },
},
}
diff --git a/build/apex/art_apex_test.py b/build/apex/art_apex_test.py
new file mode 100755
index 0000000..a8b104f
--- /dev/null
+++ b/build/apex/art_apex_test.py
@@ -0,0 +1,657 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2019 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.
+#
+
+import argparse
+import logging
+import os
+import subprocess
+import sys
+import zipfile
+
+logging.basicConfig(format='%(message)s')
+
+class FSObject:
+ def __init__(self, name, is_dir, is_exec, is_symlink):
+ self.name = name
+ self.is_dir = is_dir
+ self.is_exec = is_exec
+ self.is_symlink = is_symlink
+ def __str__(self):
+ return '%s(dir=%r,exec=%r,symlink=%r)' % (self.name, self.is_dir, self.is_exec, self.is_symlink)
+
+class TargetApexProvider:
+ def __init__(self, apex, tmpdir, debugfs):
+ self._tmpdir = tmpdir
+ self._debugfs = debugfs
+ self._folder_cache = {}
+ self._payload = os.path.join(self._tmpdir, 'apex_payload.img')
+ # Extract payload to tmpdir.
+ zip = zipfile.ZipFile(apex)
+ zip.extract('apex_payload.img', tmpdir)
+
+ def __del__(self):
+ # Delete temps.
+ if os.path.exists(self._payload):
+ os.remove(self._payload)
+
+ def get(self, path):
+ dir, name = os.path.split(path)
+ if len(dir) == 0:
+ dir = '.'
+ map = self.read_dir(dir)
+ return map[name] if name in map else None
+
+ def read_dir(self, dir):
+ if dir in self._folder_cache:
+ return self._folder_cache[dir]
+ # Cannot use check_output as it will annoy with stderr.
+ process = subprocess.Popen([self._debugfs, '-R', 'ls -l -p %s' % (dir), self._payload],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ universal_newlines=True)
+ stdout, stderr = process.communicate()
+ res = str(stdout)
+ map = {}
+ # Debugfs output looks like this:
+ # debugfs 1.44.4 (18-Aug-2018)
+ # /12/040755/0/2000/.//
+ # /2/040755/1000/1000/..//
+ # /13/100755/0/2000/dalvikvm32/28456/
+ # /14/100755/0/2000/dexoptanalyzer/20396/
+ # /15/100755/0/2000/linker/1152724/
+ # /16/100755/0/2000/dex2oat/563508/
+ # /17/100755/0/2000/linker64/1605424/
+ # /18/100755/0/2000/profman/85304/
+ # /19/100755/0/2000/dalvikvm64/28576/
+ # | | | | | |
+ # | | | #- gid #- name #- size
+ # | | #- uid
+ # | #- type and permission bits
+ # #- inode nr (?)
+ #
+ # Note: could break just on '/' to avoid names with newlines.
+ for line in res.split("\n"):
+ if not line:
+ continue
+ comps = line.split('/')
+ if len(comps) != 8:
+ logging.warn('Could not break and parse line \'%s\'', line)
+ continue
+ bits = comps[2]
+ name = comps[5]
+ if len(bits) != 6:
+ logging.warn('Dont understand bits \'%s\'', bits)
+ continue
+ is_dir = True if bits[1] == '4' else False
+ def is_exec_bit(ch):
+ return True if int(ch) & 1 == 1 else False
+ is_exec = is_exec_bit(bits[3]) and is_exec_bit(bits[4]) and is_exec_bit(bits[5])
+ is_symlink = True if bits[1] == '2' else False
+ map[name] = FSObject(name, is_dir, is_exec, is_symlink)
+ self._folder_cache[dir] = map
+ return map
+
+class HostApexProvider:
+ def __init__(self, apex, tmpdir):
+ self._tmpdir = tmpdir
+ self._folder_cache = {}
+ self._payload = os.path.join(self._tmpdir, 'apex_payload.zip')
+ # Extract payload to tmpdir.
+ zip = zipfile.ZipFile(apex)
+ zip.extract('apex_payload.zip', tmpdir)
+
+ def __del__(self):
+ # Delete temps.
+ if os.path.exists(self._payload):
+ os.remove(self._payload)
+
+ def get(self, path):
+ dir, name = os.path.split(path)
+ if len(dir) == 0:
+ dir = ''
+ map = self.read_dir(dir)
+ return map[name] if name in map else None
+
+ def read_dir(self, dir):
+ if dir in self._folder_cache:
+ return self._folder_cache[dir]
+ if not self._folder_cache:
+ self.parse_zip()
+ if dir in self._folder_cache:
+ return self._folder_cache[dir]
+ return {}
+
+ def parse_zip(self):
+ zip = zipfile.ZipFile(self._payload)
+ infos = zip.infolist()
+ for zipinfo in infos:
+ path = zipinfo.filename
+
+ # Assume no empty file is stored.
+ assert path
+
+ def get_octal(val, index):
+ return (val >> (index * 3)) & 0x7;
+ def bits_is_exec(val):
+ # TODO: Enforce group/other, too?
+ return get_octal(val, 2) & 1 == 1
+
+ is_zipinfo = True
+ while path:
+ dir, base = os.path.split(path)
+ # TODO: If directories are stored, base will be empty.
+
+ if not dir in self._folder_cache:
+ self._folder_cache[dir] = {}
+ dir_map = self._folder_cache[dir]
+ if not base in dir_map:
+ if is_zipinfo:
+ bits = (zipinfo.external_attr >> 16) & 0xFFFF
+ is_dir = get_octal(bits, 4) == 4
+ is_symlink = get_octal(bits, 4) == 2
+ is_exec = bits_is_exec(bits)
+ else:
+ is_exec = False # Seems we can't get this easily?
+ is_symlink = False
+ is_dir = True
+ dir_map[base] = FSObject(base, is_dir, is_exec, is_symlink)
+ is_zipinfo = False
+ path = dir
+
+# DO NOT USE DIRECTLY! This is an "abstract" base class.
+class Checker:
+ def __init__(self, provider):
+ self._provider = provider
+ self._errors = 0
+
+ def fail(self, msg, *args):
+ self._errors += 1
+ logging.error(msg, args)
+
+ def error_count(self):
+ return self._errors
+ def reset_errors(self):
+ self._errors = 0
+
+ def is_file(self, file):
+ fs_object = self._provider.get(file)
+ if fs_object is None:
+ return (False, 'Could not find %s')
+ if fs_object.is_dir:
+ return (False, '%s is a directory')
+ return (True, '')
+
+ def check_file(self, file):
+ chk = self.is_file(file)
+ if not chk[0]:
+ self.fail(chk[1], file)
+ return chk[0]
+ def check_no_file(self, file):
+ chk = self.is_file(file)
+ if chk[0]:
+ self.fail('File %s does exist', file)
+ return not chk[0]
+
+ def check_binary(self, file):
+ path = 'bin/%s' % (file)
+ if not self.check_file(path):
+ return False
+ if not self._provider.get(path).is_exec:
+ self.fail('%s is not executable', path)
+ return False
+ return True
+
+ def check_binary_symlink(self, file):
+ path = 'bin/%s' % (file)
+ fs_object = self._provider.get(path)
+ if fs_object is None:
+ self.fail('Could not find %s', path)
+ return False
+ if fs_object.is_dir:
+ self.fail('%s is a directory', path)
+ return False
+ if not fs_object.is_symlink:
+ self.fail('%s is not a symlink', path)
+ return False
+ return True
+
+ def check_single_library(self, file):
+ res1 = self.is_file('lib/%s' % (file))
+ res2 = self.is_file('lib64/%s' % (file))
+ if not res1[0] and not res2[0]:
+ self.fail('Library missing: %s', file)
+ return False
+ return True
+
+ def check_no_library(self, file):
+ res1 = self.is_file('lib/%s' % (file))
+ res2 = self.is_file('lib64/%s' % (file))
+ if res1[0] or res2[0]:
+ self.fail('Library exists: %s', file)
+ return False
+ return True
+
+ def check_java_library(self, file):
+ return self.check_file('javalib/%s' % (file))
+
+ # Just here for docs purposes, even if it isn't good Python style.
+
+ def check_library(self, file):
+ raise NotImplementedError
+
+ def check_first_library(self, file):
+ raise NotImplementedError
+
+ def check_multilib_binary(self, file):
+ raise NotImplementedError
+
+ def check_prefer32_binary(self, file):
+ raise NotImplementedError
+
+
+class Arch32Checker(Checker):
+ def __init__(self, provider):
+ super().__init__(provider)
+
+ def check_multilib_binary(self, file):
+ return all([self.check_binary('%s32' % (file)),
+ self.check_no_file('bin/%s64' % (file)),
+ self.check_binary_symlink(file)])
+
+ def check_library(self, file):
+ # TODO: Use $TARGET_ARCH (e.g. check whether it is "arm" or "arm64") to improve
+ # the precision of this test?
+ return all([self.check_file('lib/%s' % (file)), self.check_no_file('lib64/%s' % (file))])
+
+ def check_first_library(self, file):
+ return self.check_library(file)
+
+ def check_prefer32_binary(self, file):
+ return self.check_binary('%s32' % (file))
+
+
+class Arch64Checker(Checker):
+ def __init__(self, provider):
+ super().__init__(provider)
+
+ def check_multilib_binary(self, file):
+ return all([self.check_no_file('bin/%s32' % (file)),
+ self.check_binary('%s64' % (file)),
+ self.check_binary_symlink(file)])
+
+ def check_library(self, file):
+ # TODO: Use $TARGET_ARCH (e.g. check whether it is "arm" or "arm64") to improve
+ # the precision of this test?
+ return all([self.check_no_file('lib/%s' % (file)), self.check_file('lib64/%s' % (file))])
+
+ def check_first_library(self, file):
+ return self.check_library(file)
+
+ def check_prefer32_binary(self, file):
+ return self.check_binary('%s64' % (file))
+
+
+class MultilibChecker(Checker):
+ def __init__(self, provider):
+ super().__init__(provider)
+
+ def check_multilib_binary(self, file):
+ return all([self.check_binary('%s32' % (file)),
+ self.check_binary('%s64' % (file)),
+ self.check_binary_symlink(file)])
+
+ def check_library(self, file):
+ # TODO: Use $TARGET_ARCH (e.g. check whether it is "arm" or "arm64") to improve
+ # the precision of this test?
+ return all([self.check_file('lib/%s' % (file)), self.check_file('lib64/%s' % (file))])
+
+ def check_first_library(self, file):
+ return all([self.check_no_file('lib/%s' % (file)), self.check_file('lib64/%s' % (file))])
+
+ def check_prefer32_binary(self, file):
+ return self.check_binary('%s32' % (file))
+
+
+class ReleaseChecker:
+ def __init__(self, checker):
+ self._checker = checker
+ def __str__(self):
+ return 'Release Checker'
+
+ def run(self):
+ # Check that the mounted image contains an APEX manifest.
+ self._checker.check_file('apex_manifest.json')
+
+ # Check that the mounted image contains ART base binaries.
+ self._checker.check_multilib_binary('dalvikvm')
+ self._checker.check_binary('dex2oat')
+ self._checker.check_binary('dexoptanalyzer')
+ self._checker.check_binary('profman')
+
+ # oatdump is only in device apex's due to build rules
+ # TODO: Check for it when it is also built for host.
+ # self._checker.check_binary('oatdump')
+
+ # Check that the mounted image contains Android Runtime libraries.
+ self._checker.check_library('libart-compiler.so')
+ self._checker.check_library('libart-dexlayout.so')
+ self._checker.check_library('libart.so')
+ self._checker.check_library('libartbase.so')
+ self._checker.check_library('libartpalette.so')
+ self._checker.check_no_library('libartpalette-system.so')
+ self._checker.check_library('libdexfile.so')
+ self._checker.check_library('libdexfile_external.so')
+ self._checker.check_library('libopenjdkjvm.so')
+ self._checker.check_library('libopenjdkjvmti.so')
+ self._checker.check_library('libprofile.so')
+ # Check that the mounted image contains Android Core libraries.
+ # Note: host vs target libs are checked elsewhere.
+ self._checker.check_library('libjavacore.so')
+ self._checker.check_library('libopenjdk.so')
+ self._checker.check_library('libziparchive.so')
+ # Check that the mounted image contains additional required libraries.
+ self._checker.check_library('libadbconnection.so')
+
+ # TODO: Should we check for other libraries, such as:
+ #
+ # libbacktrace.so
+ # libbase.so
+ # liblog.so
+ # libsigchain.so
+ # libtombstoned_client.so
+ # libunwindstack.so
+ # libvixl.so
+ # libvixld.so
+ # ...
+ #
+ # ?
+
+ self._checker.check_java_library('core-oj.jar')
+ self._checker.check_java_library('core-libart.jar')
+ self._checker.check_java_library('okhttp.jar')
+ self._checker.check_java_library('bouncycastle.jar')
+ self._checker.check_java_library('apache-xml.jar')
+
+class ReleaseTargetChecker:
+ def __init__(self, checker):
+ self._checker = checker
+ def __str__(self):
+ return 'Release (Target) Checker'
+
+ def run(self):
+ # Check that the mounted image contains Android Core libraries.
+ self._checker.check_library('libexpat.so')
+ self._checker.check_library('libz.so')
+
+class ReleaseHostChecker:
+ def __init__(self, checker):
+ self._checker = checker;
+ def __str__(self):
+ return 'Release (Host) Checker'
+
+ def run(self):
+ # Check that the mounted image contains Android Core libraries.
+ self._checker.check_library('libexpat-host.so')
+ self._checker.check_library('libz-host.so')
+
+class DebugChecker:
+ def __init__(self, checker):
+ self._checker = checker
+ def __str__(self):
+ return 'Debug Checker'
+
+ def run(self):
+ # Check that the mounted image contains ART tools binaries.
+ self._checker.check_binary('dexdiag')
+ self._checker.check_binary('dexdump')
+ self._checker.check_binary('dexlist')
+
+ # Check that the mounted image contains ART debug binaries.
+ self._checker.check_binary('dex2oatd')
+ self._checker.check_binary('dexoptanalyzerd')
+ self._checker.check_binary('profmand')
+
+ # Check that the mounted image contains Android Runtime debug libraries.
+ self._checker.check_library('libartbased.so')
+ self._checker.check_library('libartd-compiler.so')
+ self._checker.check_library('libartd-dexlayout.so')
+ self._checker.check_library('libartd.so')
+ self._checker.check_library('libdexfiled.so')
+ self._checker.check_library('libopenjdkjvmd.so')
+ self._checker.check_library('libopenjdkjvmtid.so')
+ self._checker.check_library('libprofiled.so')
+ # Check that the mounted image contains Android Core debug libraries.
+ self._checker.check_library('libopenjdkd.so')
+ # Check that the mounted image contains additional required debug libraries.
+ self._checker.check_library('libadbconnectiond.so')
+
+class DebugTargetChecker:
+ def __init__(self, checker):
+ self._checker = checker
+ def __str__(self):
+ return 'Debug (Target) Checker'
+
+ def run(self):
+ # Check for files pulled in from debug target-only oatdump.
+ self._checker.check_binary('oatdump')
+ self._checker.check_first_library('libart-disassembler.so')
+
+def print_list(provider):
+ def print_list_impl(provider, path):
+ map = provider.read_dir(path)
+ if map is None:
+ return
+ map = dict(map)
+ if '.' in map:
+ del map['.']
+ if '..' in map:
+ del map['..']
+ for (_, val) in sorted(map.items()):
+ new_path = os.path.join(path, val.name)
+ print(new_path)
+ if val.is_dir:
+ print_list_impl(provider, new_path)
+ print_list_impl(provider, '')
+
+def print_tree(provider, title):
+ def get_vertical(has_next_list):
+ str = ''
+ for v in has_next_list:
+ str += '%s ' % ('│' if v else ' ')
+ return str
+ def get_last_vertical(last):
+ return '└── ' if last else '├── ';
+ def print_tree_impl(provider, path, has_next_list):
+ map = provider.read_dir(path)
+ if map is None:
+ return
+ map = dict(map)
+ if '.' in map:
+ del map['.']
+ if '..' in map:
+ del map['..']
+ key_list = list(sorted(map.keys()))
+ for i in range(0, len(key_list)):
+ val = map[key_list[i]]
+ prev = get_vertical(has_next_list)
+ last = get_last_vertical(i == len(key_list) - 1)
+ print('%s%s%s' % (prev, last, val.name))
+ if val.is_dir:
+ has_next_list.append(i < len(key_list) - 1)
+ print_tree_impl(provider, os.path.join(path, val.name), has_next_list)
+ has_next_list.pop()
+ print('%s' % (title))
+ print_tree_impl(provider, '', [])
+
+# Note: do not sys.exit early, for __del__ cleanup.
+def artApexTestMain(args):
+ if args.tree and args.debug:
+ logging.error("Both of --tree and --debug set")
+ return 1
+ if args.list and args.debug:
+ logging.error("Both of --list and --debug set")
+ return 1
+ if args.list and args.tree:
+ logging.error("Both of --list and --tree set")
+ return 1
+ if not args.tmpdir:
+ logging.error("Need a tmpdir.")
+ return 1
+ if not args.host and not args.debugfs:
+ logging.error("Need debugfs.")
+ return 1
+ if args.bitness not in ['32', '64', 'multilib', 'auto']:
+ logging.error('--bitness needs to be one of 32|64|multilib|auto')
+
+ try:
+ if args.host:
+ apex_provider = HostApexProvider(args.apex, args.tmpdir)
+ else:
+ apex_provider = TargetApexProvider(args.apex, args.tmpdir, args.debugfs)
+ except Exception as e:
+ logging.error('Failed to create provider: %s', e)
+ return 1
+
+ if args.tree:
+ print_tree(apex_provider, args.apex)
+ return 0
+ if args.list:
+ print_list(apex_provider)
+ return 0
+
+ checkers = []
+ if args.bitness == 'auto':
+ logging.warn('--bitness=auto, trying to autodetect. This may be incorrect!')
+ has_32 = apex_provider.get('lib') is not None
+ has_64 = apex_provider.get('lib64') is not None
+ if has_32 and has_64:
+ logging.warn(' Detected multilib')
+ args.bitness = 'multilib'
+ elif has_32:
+ logging.warn(' Detected 32-only')
+ args.bitness = '32'
+ elif has_64:
+ logging.warn(' Detected 64-only')
+ args.bitness = '64'
+ else:
+ logging.error(' Could not detect bitness, neither lib nor lib64 contained.')
+ print('%s' % (apex_provider._folder_cache))
+ return 1
+
+ if args.bitness == '32':
+ base_checker = Arch32Checker(apex_provider)
+ elif args.bitness == '64':
+ base_checker = Arch64Checker(apex_provider)
+ else:
+ assert args.bitness == 'multilib'
+ base_checker = MultilibChecker(apex_provider)
+
+ checkers.append(ReleaseChecker(base_checker))
+ if args.host:
+ checkers.append(ReleaseHostChecker(base_checker))
+ else:
+ checkers.append(ReleaseTargetChecker(base_checker))
+ if args.debug:
+ checkers.append(DebugChecker(base_checker))
+ if args.debug and not args.host:
+ checkers.append(DebugTargetChecker(base_checker))
+
+ failed = False
+ for checker in checkers:
+ logging.info('%s...', checker)
+ checker.run()
+ if base_checker.error_count() > 0:
+ logging.error('%s FAILED', checker)
+ failed = True
+ else:
+ logging.info('%s SUCCEEDED', checker)
+ base_checker.reset_errors()
+
+ return 1 if failed else 0
+
+def artApexTestDefault(parser):
+ if not 'ANDROID_PRODUCT_OUT' in os.environ:
+ logging.error('No-argument use requires ANDROID_PRODUCT_OUT')
+ sys.exit(1)
+ product_out = os.environ['ANDROID_PRODUCT_OUT']
+ if not 'ANDROID_HOST_OUT' in os.environ:
+ logging.error('No-argument use requires ANDROID_HOST_OUT')
+ sys.exit(1)
+ host_out = os.environ['ANDROID_HOST_OUT']
+
+ args = parser.parse_args(['dummy']) # For consistency.
+ args.debugfs = '%s/bin/debugfs' % (host_out)
+ args.tmpdir = '.'
+ args.tree = False
+ args.list = False
+ args.bitness = 'auto'
+ failed = False
+
+ if not os.path.exists(args.debugfs):
+ logging.error("Cannot find debugfs (default path %s). Please build it, e.g., m debugfs",
+ args.debugfs)
+ sys.exit(1)
+
+ # TODO: Add host support
+ configs= [
+ {'name': 'com.android.runtime.release', 'debug': False, 'host': False},
+ {'name': 'com.android.runtime.debug', 'debug': True, 'host': False},
+ ]
+
+ for config in configs:
+ logging.info(config['name'])
+ # TODO: Host will need different path.
+ args.apex = '%s/system/apex/%s.apex' % (product_out, config['name'])
+ if not os.path.exists(args.apex):
+ failed = True
+ logging.error("Cannot find APEX %s. Please build it first.", args.apex)
+ continue
+ args.debug = config['debug']
+ args.host = config['host']
+ exit_code = artApexTestMain(args)
+ if exit_code != 0:
+ failed = True
+
+ if failed:
+ sys.exit(1)
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description='Check integrity of a Runtime APEX.')
+
+ parser.add_argument('apex', help='apex file input')
+
+ parser.add_argument('--host', help='Check as host apex', action='store_true')
+
+ parser.add_argument('--debug', help='Check as debug apex', action='store_true')
+
+ parser.add_argument('--list', help='List all files', action='store_true')
+ parser.add_argument('--tree', help='Print directory tree', action='store_true')
+
+ parser.add_argument('--tmpdir', help='Directory for temp files')
+ parser.add_argument('--debugfs', help='Path to debugfs')
+
+ parser.add_argument('--bitness', help='Bitness to check, 32|64|multilib|auto', default='auto')
+
+ if len(sys.argv) == 1:
+ artApexTestDefault(parser)
+ else:
+ args = parser.parse_args()
+
+ if args is None:
+ sys.exit(1)
+
+ exit_code = artApexTestMain(args)
+ sys.exit(exit_code)
diff --git a/build/apex/ld.config.txt b/build/apex/ld.config.txt
index d0145e4..3cfda65 100644
--- a/build/apex/ld.config.txt
+++ b/build/apex/ld.config.txt
@@ -30,9 +30,21 @@
namespace.platform.asan.search.paths = /data/asan/system/${LIB}
namespace.platform.links = default
namespace.platform.link.default.shared_libs = libart.so:libartd.so
+namespace.platform.link.default.shared_libs += libdexfile_external.so
namespace.platform.link.default.shared_libs += libnativebridge.so
namespace.platform.link.default.shared_libs += libnativehelper.so
namespace.platform.link.default.shared_libs += libnativeloader.so
+# /system/lib/libc.so, etc are symlinks to /bionic/lib/libc.so, etc.
+# Add /bionic/lib to the permitted paths because linker uses realpath(3)
+# to check the accessibility of the lib. We could add this to search.paths
+# instead but that makes the resolution of bionic libs be dependent on
+# the order of /system/lib and /bionic/lib in search.paths. If /bionic/lib
+# is after /system/lib, then /bionic/lib is never tried because libc.so
+# is always found in /system/lib but fails to pass the accessibility test
+# because of its realpath. It's better to not depend on the ordering if
+# possible.
+namespace.platform.permitted.paths = /bionic/${LIB}
+namespace.platform.asan.permitted.paths = /bionic/${LIB}
# Note that we don't need to link the default namespace with conscrypt:
# the runtime Java code and binaries do not explicitly load native libraries
@@ -50,7 +62,8 @@
namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
namespace.conscrypt.asan.search.paths = /apex/com.android.conscrypt/${LIB}
-namespace.conscrypt.links = platform
+namespace.conscrypt.links = runtime,platform
+namespace.conscrypt.link.runtime.shared_libs = libjavacore.so
namespace.conscrypt.link.platform.shared_libs = libc.so
namespace.conscrypt.link.platform.shared_libs += libm.so
namespace.conscrypt.link.platform.shared_libs += libdl.so
diff --git a/build/apex/runtests.sh b/build/apex/runtests.sh
index 84c0f4f..95c1de9 100755
--- a/build/apex/runtests.sh
+++ b/build/apex/runtests.sh
@@ -17,6 +17,8 @@
# Run Android Runtime APEX tests.
+SCRIPT_DIR=$(dirname $0)
+
# Status of whole test script.
exit_status=0
# Status of current test suite.
@@ -31,17 +33,17 @@
exit 1
}
-which guestmount >/dev/null && which guestunmount >/dev/null && which virt-filesystems >/dev/null \
- || die "This script requires 'guestmount', 'guestunmount',
-and 'virt-filesystems' from libguestfs. On Debian-based systems, these tools
-can be installed with:
-
- sudo apt-get install libguestfs-tools
-"
-
[[ -n "$ANDROID_PRODUCT_OUT" ]] \
|| die "You need to source and lunch before you can use this script."
+[[ -n "$ANDROID_HOST_OUT" ]] \
+ || die "You need to source and lunch before you can use this script."
+
+if [ ! -e "$ANDROID_HOST_OUT/bin/debugfs" ] ; then
+ say "Could not find debugfs, building now."
+ make debugfs-host || die "Cannot build debugfs"
+fi
+
# Fail early.
set -e
@@ -75,15 +77,6 @@
shift
done
-if $print_image_tree_p; then
- which tree >/dev/null || die "This script requires the 'tree' tool.
-On Debian-based systems, this can be installed with:
-
- sudo apt-get install tree
-"
-fi
-
-
# build_apex APEX_MODULE
# ----------------------
# Build APEX package APEX_MODULE.
@@ -94,21 +87,22 @@
fi
}
-# maybe_list_apex_contents MOUNT_POINT
-# ------------------------------------
-# If any listing/printing option was used, honor them and display the contents
-# of the APEX payload at MOUNT_POINT.
-function maybe_list_apex_contents {
- local mount_point=$1
+# maybe_list_apex_contents_apex APEX TMPDIR [other]
+function maybe_list_apex_contents_apex {
+ local apex=$1
+ local tmpdir=$2
+ shift 2
- # List the contents of the mounted image using `find` (optional).
+ # List the contents of the apex in list form.
if $list_image_files_p; then
- say "Listing image files" && find "$mount_point"
+ say "Listing image files"
+ $SCRIPT_DIR/art_apex_test.py --list --tmpdir "$tmpdir" $@ $apex
fi
- # List the contents of the mounted image using `tree` (optional).
+ # List the contents of the apex in tree form.
if $print_image_tree_p; then
- say "Printing image tree" && ls -ld "$mount_point" && tree -aph --du "$mount_point"
+ say "Printing image tree"
+ $SCRIPT_DIR/art_apex_test.py --tree --tmpdir "$tmpdir" $@ $apex
fi
}
@@ -118,129 +112,11 @@
exit_status=1
}
-function check_file {
- [[ -f "$mount_point/$1" ]] || fail_check "Cannot find file '$1' in mounted image"
-}
-
-function check_binary {
- [[ -x "$mount_point/bin/$1" ]] || fail_check "Cannot find binary '$1' in mounted image"
-}
-
-function check_multilib_binary {
- # TODO: Use $TARGET_ARCH (e.g. check whether it is "arm" or "arm64") to improve
- # the precision of this test?
- [[ -x "$mount_point/bin/${1}32" ]] || [[ -x "$mount_point/bin/${1}64" ]] \
- || fail_check "Cannot find binary '$1' in mounted image"
-}
-
-function check_binary_symlink {
- [[ -h "$mount_point/bin/$1" ]] || fail_check "Cannot find symbolic link '$1' in mounted image"
-}
-
-function check_library {
- # TODO: Use $TARGET_ARCH (e.g. check whether it is "arm" or "arm64") to improve
- # the precision of this test?
- [[ -f "$mount_point/lib/$1" ]] || [[ -f "$mount_point/lib64/$1" ]] \
- || fail_check "Cannot find library '$1' in mounted image"
-}
-
-function check_java_library {
- [[ -x "$mount_point/javalib/$1" ]] || fail_check "Cannot find java library '$1' in mounted image"
-}
-
-# Check contents of APEX payload located in `$mount_point`.
-function check_release_contents {
- # Check that the mounted image contains an APEX manifest.
- check_file apex_manifest.json
-
- # Check that the mounted image contains ART base binaries.
- check_multilib_binary dalvikvm
- # TODO: Does not work yet (b/119942078).
- : check_binary_symlink dalvikvm
- check_binary dex2oat
- check_binary dexoptanalyzer
- check_binary profman
-
- # oatdump is only in device apex's due to build rules
- # TODO: Check for it when it is also built for host.
- : check_binary oatdump
-
- # Check that the mounted image contains Android Runtime libraries.
- check_library libart-compiler.so
- check_library libart-dexlayout.so
- check_library libart.so
- check_library libartbase.so
- check_library libdexfile.so
- check_library libopenjdkjvm.so
- check_library libopenjdkjvmti.so
- check_library libprofile.so
- # Check that the mounted image contains Android Core libraries.
- check_library "libexpat${host_suffix}.so"
- check_library libjavacore.so
- check_library libjavacrypto.so
- check_library libopenjdk.so
- check_library "libz${host_suffix}.so"
- check_library libziparchive.so
- # Check that the mounted image contains additional required libraries.
- check_library libadbconnection.so
-
- # TODO: Should we check for other libraries, such as:
- #
- # libbacktrace.so
- # libbase.so
- # liblog.so
- # libsigchain.so
- # libtombstoned_client.so
- # libunwindstack.so
- # libvixl.so
- # libvixld.so
- # ...
- #
- # ?
-
- # TODO: Enable for host
- if [ $1 != "com.android.runtime.host" ]; then
- check_java_library core-oj.jar
- check_java_library core-libart.jar
- check_java_library okhttp.jar
- check_java_library bouncycastle.jar
- check_java_library apache-xml.jar
- fi
-}
-
-# Check debug contents of APEX payload located in `$mount_point`.
-function check_debug_contents {
- # Check that the mounted image contains ART tools binaries.
- check_binary dexdiag
- check_binary dexdump
- check_binary dexlist
-
- # Check that the mounted image contains ART debug binaries.
- check_binary dex2oatd
- check_binary dexoptanalyzerd
- check_binary profmand
-
- # Check that the mounted image contains Android Runtime debug libraries.
- check_library libartbased.so
- check_library libartd-compiler.so
- check_library libartd-dexlayout.so
- check_library libartd.so
- check_library libdexfiled.so
- check_library libopenjdkjvmd.so
- check_library libopenjdkjvmtid.so
- check_library libprofiled.so
- # Check that the mounted image contains Android Core debug libraries.
- check_library libopenjdkd.so
- # Check that the mounted image contains additional required debug libraries.
- check_library libadbconnectiond.so
-}
-
# Testing target (device) APEX packages.
# ======================================
# Clean-up.
function cleanup_target {
- guestunmount "$mount_point"
rm -rf "$work_dir"
}
@@ -251,34 +127,6 @@
cleanup_target
}
-# setup_target_apex APEX_MODULE MOUNT_POINT
-# -----------------------------------------
-# Extract image from target APEX_MODULE and mount it in MOUNT_POINT.
-function setup_target_apex {
- local apex_module=$1
- local mount_point=$2
- local system_apexdir="$ANDROID_PRODUCT_OUT/system/apex"
- local apex_package="$system_apexdir/$apex_module.apex"
-
- say "Extracting and mounting image"
-
- # Extract the payload from the Android Runtime APEX.
- local image_filename="apex_payload.img"
- unzip -q "$apex_package" "$image_filename" -d "$work_dir"
- mkdir "$mount_point"
- local image_file="$work_dir/$image_filename"
-
- # Check filesystems in the image.
- local image_filesystems="$work_dir/image_filesystems"
- virt-filesystems -a "$image_file" >"$image_filesystems"
- # We expect a single partition (/dev/sda) in the image.
- local partition="/dev/sda"
- echo "$partition" | cmp "$image_filesystems" -
-
- # Mount the image from the Android Runtime APEX.
- guestmount -a "$image_file" -m "$partition" --ro "$mount_point"
-}
-
# Testing release APEX package (com.android.runtime.release).
# -----------------------------------------------------------
@@ -288,23 +136,23 @@
say "Processing APEX package $apex_module"
work_dir=$(mktemp -d)
-mount_point="$work_dir/image"
-host_suffix=""
trap finish_target EXIT
# Build the APEX package (optional).
build_apex "$apex_module"
-
-# Set up APEX package.
-setup_target_apex "$apex_module" "$mount_point"
+apex_path="$ANDROID_PRODUCT_OUT/system/apex/${apex_module}.apex"
# List the contents of the APEX image (optional).
-maybe_list_apex_contents "$mount_point"
+maybe_list_apex_contents_apex $apex_path $work_dir --debugfs $ANDROID_HOST_OUT/bin/debugfs
# Run tests on APEX package.
say "Checking APEX package $apex_module"
-check_release_contents "$apex_module"
+$SCRIPT_DIR/art_apex_test.py \
+ --tmpdir $work_dir \
+ --debugfs $ANDROID_HOST_OUT/bin/debugfs \
+ $apex_path \
+ || fail_check "Release checks failed"
# Clean up.
trap - EXIT
@@ -322,27 +170,24 @@
say "Processing APEX package $apex_module"
work_dir=$(mktemp -d)
-mount_point="$work_dir/image"
-host_suffix=""
trap finish_target EXIT
# Build the APEX package (optional).
build_apex "$apex_module"
-
-# Set up APEX package.
-setup_target_apex "$apex_module" "$mount_point"
+apex_path="$ANDROID_PRODUCT_OUT/system/apex/${apex_module}.apex"
# List the contents of the APEX image (optional).
-maybe_list_apex_contents "$mount_point"
+maybe_list_apex_contents_apex $apex_path $work_dir --debugfs $ANDROID_HOST_OUT/bin/debugfs
# Run tests on APEX package.
say "Checking APEX package $apex_module"
-check_release_contents "$apex_module"
-check_debug_contents
-# Check for files pulled in from debug target-only oatdump.
-check_binary oatdump
-check_library libart-disassembler.so
+$SCRIPT_DIR/art_apex_test.py \
+ --tmpdir $work_dir \
+ --debugfs $ANDROID_HOST_OUT/bin/debugfs \
+ --debug \
+ $apex_path \
+ || fail_check "Debug checks failed"
# Clean up.
trap - EXIT
@@ -367,51 +212,30 @@
cleanup_host
}
-# setup_host_apex APEX_MODULE MOUNT_POINT
-# ---------------------------------------
-# Extract Zip file from host APEX_MODULE and extract it in MOUNT_POINT.
-function setup_host_apex {
- local apex_module=$1
- local mount_point=$2
- local system_apexdir="$ANDROID_HOST_OUT/apex"
- local apex_package="$system_apexdir/$apex_module.zipapex"
-
- say "Extracting payload"
-
- # Extract the payload from the Android Runtime APEX.
- local image_filename="apex_payload.zip"
- unzip -q "$apex_package" "$image_filename" -d "$work_dir"
- mkdir "$mount_point"
- local image_file="$work_dir/$image_filename"
-
- # Unzipping the payload
- unzip -q "$image_file" -d "$mount_point"
-}
-
apex_module="com.android.runtime.host"
test_status=0
say "Processing APEX package $apex_module"
work_dir=$(mktemp -d)
-mount_point="$work_dir/zip"
-host_suffix="-host"
trap finish_host EXIT
# Build the APEX package (optional).
build_apex "$apex_module"
-
-# Set up APEX package.
-setup_host_apex "$apex_module" "$mount_point"
+apex_path="$ANDROID_HOST_OUT/apex/${apex_module}.zipapex"
# List the contents of the APEX image (optional).
-maybe_list_apex_contents "$mount_point"
+maybe_list_apex_contents_apex $apex_path $work_dir --host
# Run tests on APEX package.
say "Checking APEX package $apex_module"
-check_release_contents "$apex_module"
-check_debug_contents
+$SCRIPT_DIR/art_apex_test.py \
+ --tmpdir $work_dir \
+ --host \
+ --debug \
+ $apex_path \
+ || fail_check "Debug checks failed"
# Clean up.
trap - EXIT
diff --git a/build/art.go b/build/art.go
index 22f6410..5236e31 100644
--- a/build/art.go
+++ b/build/art.go
@@ -348,26 +348,7 @@
func libartDefaultsFactory() android.Module {
c := &codegenProperties{}
module := cc.DefaultsFactory(c)
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- codegen(ctx, c, true)
-
- type props struct {
- Target struct {
- Android struct {
- Shared_libs []string
- }
- }
- }
-
- p := &props{}
- // TODO: express this in .bp instead b/79671158
- if !envTrue(ctx, "ART_TARGET_LINUX") {
- p.Target.Android.Shared_libs = []string{
- "libmetricslogger",
- }
- }
- ctx.AppendProperties(p)
- })
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, true) })
return module
}
@@ -375,27 +356,7 @@
func libartStaticDefaultsFactory() android.Module {
c := &codegenProperties{}
module := cc.DefaultsFactory(c)
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- codegen(ctx, c, true)
-
- type props struct {
- Target struct {
- Android struct {
- Static_libs []string
- }
- }
- }
-
- p := &props{}
- // TODO: express this in .bp instead b/79671158
- if !envTrue(ctx, "ART_TARGET_LINUX") {
- p.Target.Android.Static_libs = []string{
- "libmetricslogger",
- "libstatssocket",
- }
- }
- ctx.AppendProperties(p)
- })
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, true) })
return module
}
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 0d92b05..0ebaa5f 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -182,7 +182,6 @@
generated_sources: ["art_compiler_operator_srcs"],
shared_libs: [
"libbase",
- "libcutils", // for atrace.
],
include_dirs: ["art/disassembler"],
header_libs: [
@@ -197,7 +196,6 @@
name: "libart-compiler_static_base_defaults",
static_libs: [
"libbase",
- "libcutils",
],
}
@@ -256,9 +254,10 @@
},
shared_libs: [
"libart",
+ "libartbase",
+ "libartpalette",
"libprofile",
"libdexfile",
- "libartbase",
],
target: {
@@ -317,10 +316,11 @@
},
},
shared_libs: [
+ "libartbased",
"libartd",
+ "libartpalette",
"libprofiled",
"libdexfiled",
- "libartbased",
],
}
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc
index 54a1ae9..e35d502 100644
--- a/compiler/optimizing/bounds_check_elimination.cc
+++ b/compiler/optimizing/bounds_check_elimination.cc
@@ -845,8 +845,10 @@
// make one more attempt to get a constant in the array range.
ValueRange* existing_range = LookupValueRange(array_length, block);
if (existing_range != nullptr &&
- existing_range->IsConstantValueRange()) {
- ValueRange constant_array_range(&allocator_, lower, existing_range->GetLower());
+ existing_range->IsConstantValueRange() &&
+ existing_range->GetLower().GetConstant() > 0) {
+ ValueBound constant_upper(nullptr, existing_range->GetLower().GetConstant() - 1);
+ ValueRange constant_array_range(&allocator_, lower, constant_upper);
if (index_range->FitsIn(&constant_array_range)) {
ReplaceInstruction(bounds_check, index);
return;
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp
index 6a4a88e..20d41b4 100644
--- a/dex2oat/Android.bp
+++ b/dex2oat/Android.bp
@@ -64,8 +64,6 @@
target: {
android: {
- // For atrace.
- shared_libs: ["libcutils"],
static_libs: [
"libz",
],
@@ -93,11 +91,6 @@
cc_defaults {
name: "libart-dex2oat_static_base_defaults",
- target: {
- android: {
- static_libs: ["libcutils"],
- },
- },
static_libs: [
"libbase",
"libz",
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index 5aa8236..838510b 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -29,16 +29,18 @@
target: {
android: {
shared_libs: [
- "libdexfile",
"libartbase",
+ "libartpalette",
+ "libdexfile",
"libprofile",
"libbase",
],
},
not_windows: {
shared_libs: [
- "libdexfile",
"libartbase",
+ "libartpalette",
+ "libdexfile",
"libprofile",
"libbase",
],
@@ -46,8 +48,9 @@
windows: {
cflags: ["-Wno-thread-safety"],
static_libs: [
- "libdexfile",
"libartbase",
+ "libartpalette",
+ "libdexfile",
"libprofile",
"libbase",
],
diff --git a/imgdiag/Android.bp b/imgdiag/Android.bp
index 972c8f7..39720a0 100644
--- a/imgdiag/Android.bp
+++ b/imgdiag/Android.bp
@@ -31,9 +31,6 @@
"libbase",
],
target: {
- android: {
- shared_libs: ["libcutils"],
- },
host: {
shared_libs: ["libziparchive"],
},
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index 509b072..1ca7011 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -61,7 +61,7 @@
shared_libs: [
"liblog",
// For ashmem.
- "libcutils",
+ "libartpalette",
// For common macros.
"libbase",
],
@@ -80,7 +80,7 @@
"libz",
"liblog",
// For ashmem.
- "libcutils",
+ "libartpalette",
// For common macros.
"libbase",
],
@@ -99,7 +99,7 @@
"libz",
"liblog",
// For ashmem.
- "libcutils",
+ "libartpalette",
// For common macros.
"libbase",
],
@@ -128,7 +128,7 @@
name: "libartbase_static_base_defaults",
static_libs: [
"libbase",
- "libcutils",
+ "libartpalette",
"liblog",
"libz",
"libziparchive",
diff --git a/libartbase/base/systrace.h b/libartbase/base/systrace.h
index d995dce..30bba49 100644
--- a/libartbase/base/systrace.h
+++ b/libartbase/base/systrace.h
@@ -17,33 +17,52 @@
#ifndef ART_LIBARTBASE_BASE_SYSTRACE_H_
#define ART_LIBARTBASE_BASE_SYSTRACE_H_
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include <cutils/trace.h>
-
#include <sstream>
#include <string>
#include "android-base/stringprintf.h"
#include "macros.h"
+#include "palette/palette.h"
namespace art {
+inline bool ATraceEnabled() {
+ int enabled = 0;
+ if (UNLIKELY(PaletteTraceEnabled(&enabled) == PaletteStatus::kOkay && enabled != 0)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+inline void ATraceBegin(const char* name) {
+ PaletteTraceBegin(name);
+}
+
+inline void ATraceEnd() {
+ PaletteTraceEnd();
+}
+
+inline void ATraceIntegerValue(const char* name, int32_t value) {
+ PaletteTraceIntegerValue(name, value);
+}
+
class ScopedTrace {
public:
explicit ScopedTrace(const char* name) {
- ATRACE_BEGIN(name);
+ ATraceBegin(name);
}
template <typename Fn>
explicit ScopedTrace(Fn fn) {
- if (ATRACE_ENABLED()) {
- ATRACE_BEGIN(fn().c_str());
+ if (UNLIKELY(ATraceEnabled())) {
+ ATraceBegin(fn().c_str());
}
}
explicit ScopedTrace(const std::string& name) : ScopedTrace(name.c_str()) {}
~ScopedTrace() {
- ATRACE_END();
+ ATraceEnd();
}
};
@@ -54,7 +73,7 @@
}
~ScopedTraceNoStart() {
- ATRACE_END();
+ ATraceEnd();
}
// Message helper for the macro. Do not use directly.
@@ -63,7 +82,7 @@
ScopedTraceMessageHelper() {
}
~ScopedTraceMessageHelper() {
- ATRACE_BEGIN(buffer_.str().c_str());
+ ATraceBegin(buffer_.str().c_str());
}
std::ostream& stream() {
@@ -77,7 +96,7 @@
#define SCOPED_TRACE \
::art::ScopedTraceNoStart APPEND_TOKENS_AFTER_EVAL(trace, __LINE__) ; \
- (ATRACE_ENABLED()) && ::art::ScopedTraceNoStart::ScopedTraceMessageHelper().stream()
+ (ATraceEnabled()) && ::art::ScopedTraceNoStart::ScopedTraceMessageHelper().stream()
} // namespace art
diff --git a/libartpalette/Android.bp b/libartpalette/Android.bp
new file mode 100644
index 0000000..778109d
--- /dev/null
+++ b/libartpalette/Android.bp
@@ -0,0 +1,116 @@
+//
+// Copyright (C) 2019 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.
+//
+
+cc_defaults {
+ name: "libartpalette_defaults",
+ defaults: ["art_defaults"],
+ host_supported: true,
+ export_include_dirs: ["include"],
+}
+
+// libartpalette-system is the implementation of the abstraction layer. It is
+// only available as a shared library on Android.
+art_cc_library {
+ name: "libartpalette-system",
+ defaults: ["libartpalette_defaults"],
+
+ target: {
+ android: {
+ srcs: ["system/palette_android.cc",],
+ header_libs: ["libbase_headers"],
+ shared_libs: [
+ "libcutils",
+ "liblog",
+ "libprocessgroup",
+ ],
+ },
+ host: {
+ header_libs: ["libbase_headers"],
+ srcs: ["system/palette_fake.cc",],
+ },
+ darwin: {
+ enabled: false,
+ },
+ windows: {
+ enabled: false,
+ },
+ },
+ static: {
+ enabled: false,
+ },
+ version_script: "libartpalette.map.txt",
+}
+
+// libartpalette is the dynamic loader of the platform abstraction
+// layer. It is only used on Android. For other targets, it just
+// implements a fake platform implementation.
+art_cc_library {
+ name: "libartpalette",
+ defaults: ["libartpalette_defaults"],
+ required: ["libartpalette-system"], // libartpalette.so dlopen()'s libartpalette-system.
+ header_libs: ["libbase_headers"],
+ target: {
+ // Targets supporting dlopen build the client library which loads
+ // and binds the methods in the libartpalette-system library.
+ android: {
+ srcs: ["apex/palette.cc"],
+ shared: {
+ shared_libs: ["liblog"],
+ },
+ static: {
+ static_libs: ["liblog"],
+ },
+ version_script: "libartpalette.map.txt",
+ },
+ linux_bionic: {
+ header_libs: ["libbase_headers"],
+ srcs: ["system/palette_fake.cc"],
+ shared: {
+ shared_libs: ["liblog"],
+ },
+ version_script: "libartpalette.map.txt",
+ },
+ linux_glibc: {
+ header_libs: ["libbase_headers"],
+ srcs: ["system/palette_fake.cc"],
+ shared: {
+ shared_libs: ["liblog"],
+ },
+ version_script: "libartpalette.map.txt",
+ },
+ // Targets without support for dlopen just use the sources for
+ // the system library which actually implements functionality.
+ darwin: {
+ enabled: true,
+ header_libs: ["libbase_headers"],
+ srcs: ["system/palette_fake.cc"],
+ },
+ windows: {
+ enabled: true,
+ header_libs: ["libbase_headers"],
+ srcs: ["system/palette_fake.cc"],
+ },
+ }
+}
+
+art_cc_test {
+ name: "art_libartpalette_tests",
+ defaults: ["art_gtest_defaults"],
+ host_supported: true,
+ srcs: ["apex/palette_test.cc"],
+ shared_libs: ["libartpalette"],
+ test_per_src: true,
+}
diff --git a/libartpalette/apex/palette.cc b/libartpalette/apex/palette.cc
new file mode 100644
index 0000000..8c17057
--- /dev/null
+++ b/libartpalette/apex/palette.cc
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "palette/palette.h"
+
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include <android/log.h>
+#include <android-base/macros.h>
+
+namespace {
+
+// Logging tag.
+static constexpr const char* kLogTag = "libartpalette";
+
+// Name of the palette library present in the /system partition.
+static constexpr const char* kPaletteSystemLibrary = "libartpalette-system.so";
+
+// Generic method used when a dynamically loaded palette instance does not
+// support a method.
+enum PaletteStatus PaletteMethodNotSupported() {
+ return PaletteStatus::kNotSupported;
+}
+
+// Declare type aliases for pointers to each function in the interface.
+#define PALETTE_METHOD_TYPE_ALIAS(Name, ...) \
+ using Name ## Method = PaletteStatus(*)(__VA_ARGS__);
+PALETTE_METHOD_LIST(PALETTE_METHOD_TYPE_ALIAS)
+#undef PALETTE_METHOD_TYPE_ALIAS
+
+// Singleton class responsible for dynamically loading the palette library and
+// binding functions there to method pointers.
+class PaletteLoader {
+ public:
+ static PaletteLoader& Instance() {
+ static PaletteLoader instance;
+ return instance;
+ }
+
+ // Accessor methods to get instances of palette methods.
+#define PALETTE_LOADER_METHOD_ACCESSOR(Name, ...) \
+ Name ## Method Get ## Name ## Method() const { return Name ## Method ## _; }
+PALETTE_METHOD_LIST(PALETTE_LOADER_METHOD_ACCESSOR)
+#undef PALETTE_LOADER_METHOD_ACCESSOR
+
+ private:
+ PaletteLoader();
+
+ static void* OpenLibrary();
+ static void* GetMethod(void* palette_lib, const char* name);
+
+ // Handle to the palette library from dlopen().
+ void* palette_lib_;
+
+ // Fields to store pointers to palette methods.
+#define PALETTE_LOADER_METHOD_FIELD(Name, ...) \
+ const Name ## Method Name ## Method ## _;
+ PALETTE_METHOD_LIST(PALETTE_LOADER_METHOD_FIELD)
+#undef PALETTE_LOADER_METHOD_FIELD
+
+ DISALLOW_COPY_AND_ASSIGN(PaletteLoader);
+};
+
+void* PaletteLoader::OpenLibrary() {
+ void* handle = dlopen(kPaletteSystemLibrary, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE);
+ if (handle == nullptr) {
+ // dlerror message includes details of error and file being opened.
+ __android_log_assert(nullptr, kLogTag, "%s", dlerror());
+ }
+ return handle;
+}
+
+void* PaletteLoader::GetMethod(void* palette_lib, const char* name) {
+ void* method = nullptr;
+ if (palette_lib != nullptr) {
+ method = dlsym(palette_lib, name);
+ }
+ if (method == nullptr) {
+ return reinterpret_cast<void*>(PaletteMethodNotSupported);
+ }
+ // TODO(oth): consider new GetMethodSignature() in the Palette API which
+ // would allow sanity checking the type signatures.
+ return method;
+}
+
+PaletteLoader::PaletteLoader() :
+ palette_lib_(OpenLibrary())
+#define PALETTE_LOADER_BIND_METHOD(Name, ...) \
+ , Name ## Method ## _(reinterpret_cast<Name ## Method>(GetMethod(palette_lib_, #Name)))
+ PALETTE_METHOD_LIST(PALETTE_LOADER_BIND_METHOD)
+#undef PALETTE_LOADER_BIND_METHOD
+{
+}
+
+} // namespace
+
+extern "C" {
+
+enum PaletteStatus PaletteGetVersion(/*out*/int32_t* version) {
+ PaletteGetVersionMethod m = PaletteLoader::Instance().GetPaletteGetVersionMethod();
+ return m(version);
+}
+
+enum PaletteStatus PaletteSchedSetPriority(int32_t tid, int32_t java_priority) {
+ PaletteSchedSetPriorityMethod m = PaletteLoader::Instance().GetPaletteSchedSetPriorityMethod();
+ return m(tid, java_priority);
+}
+
+enum PaletteStatus PaletteSchedGetPriority(int32_t tid, /*out*/int32_t* java_priority) {
+ PaletteSchedGetPriorityMethod m = PaletteLoader::Instance().GetPaletteSchedGetPriorityMethod();
+ return m(tid, java_priority);
+}
+
+enum PaletteStatus PaletteTraceEnabled(/*out*/int32_t* enabled) {
+ PaletteTraceEnabledMethod m = PaletteLoader::Instance().GetPaletteTraceEnabledMethod();
+ return m(enabled);
+}
+
+enum PaletteStatus PaletteTraceBegin(/*in*/const char* name) {
+ PaletteTraceBeginMethod m = PaletteLoader::Instance().GetPaletteTraceBeginMethod();
+ return m(name);
+}
+
+enum PaletteStatus PaletteTraceEnd() {
+ PaletteTraceEndMethod m = PaletteLoader::Instance().GetPaletteTraceEndMethod();
+ return m();
+}
+
+enum PaletteStatus PaletteTraceIntegerValue(/*in*/const char* name, int32_t value) {
+ PaletteTraceIntegerValueMethod m = PaletteLoader::Instance().GetPaletteTraceIntegerValueMethod();
+ return m(name, value);
+}
+
+} // extern "C"
diff --git a/libartpalette/apex/palette_test.cc b/libartpalette/apex/palette_test.cc
new file mode 100644
index 0000000..8bbe0ee
--- /dev/null
+++ b/libartpalette/apex/palette_test.cc
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "palette/palette.h"
+
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#include "gtest/gtest.h"
+
+namespace {
+
+pid_t GetTid() {
+#ifdef __BIONIC__
+ return gettid();
+#else // __BIONIC__
+ return syscall(__NR_gettid);
+#endif // __BIONIC__
+}
+
+} // namespace
+
+class PaletteClientTest : public testing::Test {};
+
+TEST_F(PaletteClientTest, GetVersion) {
+ int32_t version = -1;
+ PaletteStatus status = PaletteGetVersion(&version);
+ ASSERT_EQ(PaletteStatus::kOkay, status);
+ ASSERT_GE(version, 1);
+}
+
+TEST_F(PaletteClientTest, SchedPriority) {
+ int32_t tid = GetTid();
+ int32_t saved_priority;
+ EXPECT_EQ(PaletteStatus::kOkay, PaletteSchedGetPriority(tid, &saved_priority));
+
+ EXPECT_EQ(PaletteStatus::kInvalidArgument, PaletteSchedSetPriority(tid, /*java_priority=*/ 0));
+ EXPECT_EQ(PaletteStatus::kInvalidArgument, PaletteSchedSetPriority(tid, /*java_priority=*/ -1));
+ EXPECT_EQ(PaletteStatus::kInvalidArgument, PaletteSchedSetPriority(tid, /*java_priority=*/ 11));
+
+ EXPECT_EQ(PaletteStatus::kOkay, PaletteSchedSetPriority(tid, /*java_priority=*/ 1));
+ EXPECT_EQ(PaletteStatus::kOkay, PaletteSchedSetPriority(tid, saved_priority));
+}
+
+TEST_F(PaletteClientTest, Trace) {
+ int32_t enabled;
+ EXPECT_EQ(PaletteStatus::kOkay, PaletteTraceEnabled(&enabled));
+ EXPECT_EQ(PaletteStatus::kOkay, PaletteTraceBegin("Hello world!"));
+ EXPECT_EQ(PaletteStatus::kOkay, PaletteTraceEnd());
+ EXPECT_EQ(PaletteStatus::kOkay, PaletteTraceIntegerValue("Beans", /*value=*/ 3));
+}
diff --git a/libartpalette/include/palette/palette.h b/libartpalette/include/palette/palette.h
new file mode 100644
index 0000000..1f58403
--- /dev/null
+++ b/libartpalette/include/palette/palette.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_H_
+#define ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_H_
+
+#include "palette_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+// Palette method signatures are defined in palette_method_list.h.
+
+#define PALETTE_METHOD_DECLARATION(Name, ...) \
+ enum PaletteStatus Name(__VA_ARGS__);
+#include "palette_method_list.h"
+PALETTE_METHOD_LIST(PALETTE_METHOD_DECLARATION)
+#undef PALETTE_METHOD_DECLARATION
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_H_
diff --git a/libartpalette/include/palette/palette_method_list.h b/libartpalette/include/palette/palette_method_list.h
new file mode 100644
index 0000000..dc4ec52
--- /dev/null
+++ b/libartpalette/include/palette/palette_method_list.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_METHOD_LIST_H_
+#define ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_METHOD_LIST_H_
+
+#include <stdint.h>
+
+// Methods in version 1 API
+#define PALETTE_METHOD_LIST(M) \
+ M(PaletteGetVersion, /*out*/int32_t* version) \
+ M(PaletteSchedSetPriority, int32_t tid, int32_t java_priority) \
+ M(PaletteSchedGetPriority, int32_t tid, /*out*/int32_t* java_priority) \
+ M(PaletteTraceEnabled, /*out*/int32_t* enabled) \
+ M(PaletteTraceBegin, const char* name) \
+ M(PaletteTraceEnd) \
+ M(PaletteTraceIntegerValue, const char* name, int32_t value)
+
+#endif // ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_METHOD_LIST_H_
diff --git a/libartpalette/include/palette/palette_types.h b/libartpalette/include/palette/palette_types.h
new file mode 100644
index 0000000..837086e
--- /dev/null
+++ b/libartpalette/include/palette/palette_types.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_TYPES_H_
+#define ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_TYPES_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+// Return values for palette functions.
+enum PaletteStatus {
+ kOkay = 0,
+ kCheckErrno = 1,
+ kInvalidArgument = 2,
+ kNotSupported = 3,
+};
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_TYPES_H_
diff --git a/libartpalette/libartpalette.map.txt b/libartpalette/libartpalette.map.txt
new file mode 100644
index 0000000..0920835
--- /dev/null
+++ b/libartpalette/libartpalette.map.txt
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2019 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.
+#
+
+LIBARTPALETTE_1 {
+ global:
+ # --- VERSION 01 API ---
+ PaletteGetVersion;
+ PaletteSchedSetPriority;
+ PaletteSchedGetPriority;
+ PaletteTraceEnabled;
+ PaletteTraceBegin;
+ PaletteTraceEnd;
+ PaletteTraceIntegerValue;
+
+ local:
+ *;
+};
diff --git a/libartpalette/system/palette_android.cc b/libartpalette/system/palette_android.cc
new file mode 100644
index 0000000..aed3862
--- /dev/null
+++ b/libartpalette/system/palette_android.cc
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+
+#include "palette/palette.h"
+
+#include <errno.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <mutex>
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <cutils/sched_policy.h>
+#include <cutils/trace.h>
+#include <log/event_tag_map.h>
+#include <utils/Thread.h>
+
+#include "palette_system.h"
+
+enum PaletteStatus PaletteGetVersion(int32_t* version) {
+ *version = art::palette::kPaletteVersion;
+ return PaletteStatus::kOkay;
+}
+
+// Conversion map for "nice" values.
+//
+// We use Android thread priority constants to be consistent with the rest
+// of the system. In some cases adjacent entries may overlap.
+//
+static const int kNiceValues[art::palette::kNumManagedThreadPriorities] = {
+ ANDROID_PRIORITY_LOWEST, // 1 (MIN_PRIORITY)
+ ANDROID_PRIORITY_BACKGROUND + 6,
+ ANDROID_PRIORITY_BACKGROUND + 3,
+ ANDROID_PRIORITY_BACKGROUND,
+ ANDROID_PRIORITY_NORMAL, // 5 (NORM_PRIORITY)
+ ANDROID_PRIORITY_NORMAL - 2,
+ ANDROID_PRIORITY_NORMAL - 4,
+ ANDROID_PRIORITY_URGENT_DISPLAY + 3,
+ ANDROID_PRIORITY_URGENT_DISPLAY + 2,
+ ANDROID_PRIORITY_URGENT_DISPLAY // 10 (MAX_PRIORITY)
+};
+
+enum PaletteStatus PaletteSchedSetPriority(int32_t tid, int32_t managed_priority) {
+ if (managed_priority < art::palette::kMinManagedThreadPriority ||
+ managed_priority > art::palette::kMaxManagedThreadPriority) {
+ return PaletteStatus::kInvalidArgument;
+ }
+ int new_nice = kNiceValues[managed_priority - art::palette::kMinManagedThreadPriority];
+
+ // TODO: b/18249098 The code below is broken. It uses getpriority() as a proxy for whether a
+ // thread is already in the SP_FOREGROUND cgroup. This is not necessarily true for background
+ // processes, where all threads are in the SP_BACKGROUND cgroup. This means that callers will
+ // have to call setPriority twice to do what they want :
+ //
+ // Thread.setPriority(Thread.MIN_PRIORITY); // no-op wrt to cgroups
+ // Thread.setPriority(Thread.MAX_PRIORITY); // will actually change cgroups.
+ if (new_nice >= ANDROID_PRIORITY_BACKGROUND) {
+ set_sched_policy(tid, SP_BACKGROUND);
+ } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
+ set_sched_policy(tid, SP_FOREGROUND);
+ }
+
+ if (setpriority(PRIO_PROCESS, tid, new_nice) != 0) {
+ return PaletteStatus::kCheckErrno;
+ }
+ return PaletteStatus::kOkay;
+}
+
+enum PaletteStatus PaletteSchedGetPriority(int32_t tid, /*out*/int32_t* managed_priority) {
+ errno = 0;
+ int native_priority = getpriority(PRIO_PROCESS, tid);
+ if (native_priority == -1 && errno != 0) {
+ *managed_priority = art::palette::kNormalManagedThreadPriority;
+ return PaletteStatus::kCheckErrno;
+ }
+
+ for (int p = art::palette::kMinManagedThreadPriority;
+ p <= art::palette::kMaxManagedThreadPriority;
+ p = p + 1) {
+ int index = p - art::palette::kMinManagedThreadPriority;
+ if (native_priority >= kNiceValues[index]) {
+ *managed_priority = p;
+ return PaletteStatus::kOkay;
+ }
+ }
+ *managed_priority = art::palette::kMaxManagedThreadPriority;
+ return PaletteStatus::kOkay;
+}
+
+enum PaletteStatus PaletteTraceEnabled(/*out*/int32_t* enabled) {
+ *enabled = (ATRACE_ENABLED() != 0) ? 1 : 0;
+ return PaletteStatus::kOkay;
+}
+
+enum PaletteStatus PaletteTraceBegin(const char* name) {
+ ATRACE_BEGIN(name);
+ return PaletteStatus::kOkay;
+}
+
+enum PaletteStatus PaletteTraceEnd() {
+ ATRACE_END();
+ return PaletteStatus::kOkay;
+}
+
+enum PaletteStatus PaletteTraceIntegerValue(const char* name, int32_t value) {
+ ATRACE_INT(name, value);
+ return PaletteStatus::kOkay;
+}
diff --git a/libartpalette/system/palette_fake.cc b/libartpalette/system/palette_fake.cc
new file mode 100644
index 0000000..0961e77
--- /dev/null
+++ b/libartpalette/system/palette_fake.cc
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "palette/palette.h"
+
+#include <map>
+#include <mutex>
+
+#include <android-base/macros.h> // For ATTRIBUTE_UNUSED
+
+#include "palette_system.h"
+
+enum PaletteStatus PaletteGetVersion(int32_t* version) {
+ *version = art::palette::kPaletteVersion;
+ return PaletteStatus::kOkay;
+}
+
+// Cached thread priority for testing. No thread priorities are ever affected.
+static std::mutex g_tid_priority_map_mutex;
+static std::map<int32_t, int32_t> g_tid_priority_map;
+
+enum PaletteStatus PaletteSchedSetPriority(int32_t tid, int32_t priority) {
+ if (priority < art::palette::kMinManagedThreadPriority ||
+ priority > art::palette::kMaxManagedThreadPriority) {
+ return PaletteStatus::kInvalidArgument;
+ }
+ std::lock_guard guard(g_tid_priority_map_mutex);
+ g_tid_priority_map[tid] = priority;
+ return PaletteStatus::kOkay;
+}
+
+enum PaletteStatus PaletteSchedGetPriority(int32_t tid,
+ /*out*/int32_t* priority) {
+ std::lock_guard guard(g_tid_priority_map_mutex);
+ if (g_tid_priority_map.find(tid) == g_tid_priority_map.end()) {
+ g_tid_priority_map[tid] = art::palette::kNormalManagedThreadPriority;
+ }
+ *priority = g_tid_priority_map[tid];
+ return PaletteStatus::kOkay;
+}
+
+enum PaletteStatus PaletteTraceEnabled(/*out*/int32_t* enabled) {
+ *enabled = 0;
+ return PaletteStatus::kOkay;
+}
+
+enum PaletteStatus PaletteTraceBegin(const char* name ATTRIBUTE_UNUSED) {
+ return PaletteStatus::kOkay;
+}
+
+enum PaletteStatus PaletteTraceEnd() {
+ return PaletteStatus::kOkay;
+}
+
+enum PaletteStatus PaletteTraceIntegerValue(const char* name ATTRIBUTE_UNUSED,
+ int32_t value ATTRIBUTE_UNUSED) {
+ return PaletteStatus::kOkay;
+}
diff --git a/libartpalette/system/palette_system.h b/libartpalette/system/palette_system.h
new file mode 100644
index 0000000..b28e00d
--- /dev/null
+++ b/libartpalette/system/palette_system.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_LIBARTPALETTE_SYSTEM_PALETTE_SYSTEM_H_
+#define ART_LIBARTPALETTE_SYSTEM_PALETTE_SYSTEM_H_
+
+#include <stdint.h>
+
+namespace art {
+namespace palette {
+
+static constexpr int32_t kPaletteVersion = 1;
+
+// Managed thread definitions
+static constexpr int32_t kNormalManagedThreadPriority = 5;
+static constexpr int32_t kMinManagedThreadPriority = 1;
+static constexpr int32_t kMaxManagedThreadPriority = 10;
+static constexpr int32_t kNumManagedThreadPriorities =
+ kMaxManagedThreadPriority - kMinManagedThreadPriority + 1;
+
+} // namespace palette
+} // namespace art
+
+#endif // ART_LIBARTPALETTE_SYSTEM_PALETTE_SYSTEM_H_
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index 2f56a3d..feb5e38 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -47,9 +47,8 @@
shared_libs: [
// For MemMap.
"libartbase",
+ "libartpalette",
"liblog",
- // For atrace.
- "libcutils",
// For common macros.
"libbase",
],
@@ -64,9 +63,8 @@
"libz",
// For MemMap.
"libartbase",
+ "libartpalette",
"liblog",
- // For atrace.
- "libcutils",
// For common macros.
"libbase",
],
@@ -81,9 +79,8 @@
"libz",
// For MemMap.
"libartbase",
+ "libartpalette",
"liblog",
- // For atrace.
- "libcutils",
// For common macros.
"libbase",
],
@@ -102,7 +99,6 @@
name: "libdexfile_static_base_defaults",
static_libs: [
"libbase",
- "libcutils",
"liblog",
"libz",
"libziparchive",
@@ -232,28 +228,9 @@
"libdexfile",
],
- // TODO(b/120670568): Enable this when linking bug is fixed.
- // stubs: {
- // symbol_file: "external/libdexfile_external.map.txt",
- // versions: ["1"],
- // },
-
- // Hide symbols using version scripts for targets that support it, i.e. all
- // but Darwin.
- // TODO(b/120670568): Clean this up when stubs above is enabled.
- target: {
- android: {
- version_script: "external/libdexfile_external.map.txt",
- },
- linux_bionic: {
- version_script: "external/libdexfile_external.map.txt",
- },
- linux_glibc: {
- version_script: "external/libdexfile_external.map.txt",
- },
- windows: {
- version_script: "external/libdexfile_external.map.txt",
- },
+ stubs: {
+ symbol_file: "external/libdexfile_external.map.txt",
+ versions: ["1"],
},
}
diff --git a/libprofile/Android.bp b/libprofile/Android.bp
index fd32c5f..986adce 100644
--- a/libprofile/Android.bp
+++ b/libprofile/Android.bp
@@ -25,10 +25,8 @@
android: {
shared_libs: [
"libartbase",
+ "libartpalette",
"libdexfile",
- "libartbase",
- // For atrace.
- "libcutils",
"libbase",
],
static_libs: [
@@ -41,10 +39,8 @@
not_windows: {
shared_libs: [
"libartbase",
+ "libartpalette",
"libdexfile",
- "libartbase",
- // For atrace.
- "libcutils",
"libziparchive",
"libz",
"libbase",
@@ -55,10 +51,8 @@
cflags: ["-Wno-thread-safety"],
static_libs: [
"libartbase",
+ "libartpalette",
"libdexfile",
- "libartbase",
- // For atrace.
- "libcutils",
"libziparchive",
"libz",
"libbase",
@@ -78,7 +72,6 @@
name: "libprofile_static_base_defaults",
static_libs: [
"libbase",
- "libcutils",
"libz",
"libziparchive",
],
diff --git a/oatdump/Android.bp b/oatdump/Android.bp
index 45f853b..f56265c 100644
--- a/oatdump/Android.bp
+++ b/oatdump/Android.bp
@@ -19,11 +19,6 @@
defaults: ["art_defaults"],
host_supported: true,
srcs: ["oatdump.cc"],
- target: {
- android: {
- shared_libs: ["libcutils"],
- },
- },
// b/79417743, oatdump 32-bit tests failed with clang lld
use_clang_lld: false,
header_libs: [
@@ -102,6 +97,9 @@
"libart-disassembler",
"libvixl",
],
+ // TODO(b/122885634): This is necessary for the static lib ordering bug with
+ // APEX stubs.
+ group_static_libs: true,
}
art_cc_binary {
diff --git a/oatdump/oatdump_test.cc b/oatdump/oatdump_test.cc
index 7b1de01..8505b0c 100644
--- a/oatdump/oatdump_test.cc
+++ b/oatdump/oatdump_test.cc
@@ -92,7 +92,7 @@
// Test is failing on target, b/77469384.
TEST_DISABLED_FOR_TARGET();
std::string error_msg;
- ASSERT_TRUE(GenerateAppOdexFile(kDynamic, {}));
+ ASSERT_TRUE(GenerateAppOdexFile(kDynamic, {"--runtime-arg", "-Xmx64M"}));
ASSERT_TRUE(Exec(kDynamic, kModeOat, {"--export-dex-to=" + tmp_dir_}, kListOnly));
const std::string dex_location =
tmp_dir_+ "/" + android::base::Basename(GetTestDexFileName(GetAppBaseName().c_str())) +
@@ -109,7 +109,7 @@
TEST_DISABLED_FOR_ARM_AND_MIPS();
TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
std::string error_msg;
- ASSERT_TRUE(GenerateAppOdexFile(kDynamic, {}));
+ ASSERT_TRUE(GenerateAppOdexFile(kStatic, {"--runtime-arg", "-Xmx64M"}));
ASSERT_TRUE(Exec(kStatic, kModeOat, {"--export-dex-to=" + tmp_dir_}, kListOnly));
}
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index a3e06e6..079cd98 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -87,7 +87,8 @@
}
}
-std::unique_ptr<FixedUpDexFile> FixedUpDexFile::Create(const art::DexFile& original,
+std::unique_ptr<FixedUpDexFile> FixedUpDexFile::Create(jobject class_loader,
+ const art::DexFile& original,
const char* descriptor) {
// Copy the data into mutable memory.
std::vector<unsigned char> data;
@@ -100,9 +101,11 @@
// property from `original` to `new_dex_file`.
const art::DexFileLoader dex_file_loader;
- if (original.IsCompactDexFile()) {
+ if (original.IsCompactDexFile() || class_loader == nullptr) {
// Since we are supposed to return a standard dex, convert back using dexlayout. It's OK to do
// this before unquickening.
+ // We also do dex layout for boot classpath dex files, as they contain hidden API flags which
+ // we want to remove.
art::Options options;
options.compact_dex_level_ = art::CompactDexLevel::kCompactDexLevelNone;
// Add a filter to only include the class that has the matching descriptor.
diff --git a/openjdkjvmti/fixed_up_dex_file.h b/openjdkjvmti/fixed_up_dex_file.h
index 594e8a7..e09d70b 100644
--- a/openjdkjvmti/fixed_up_dex_file.h
+++ b/openjdkjvmti/fixed_up_dex_file.h
@@ -49,7 +49,8 @@
// are running on.
class FixedUpDexFile {
public:
- static std::unique_ptr<FixedUpDexFile> Create(const art::DexFile& original,
+ static std::unique_ptr<FixedUpDexFile> Create(jobject class_loader,
+ const art::DexFile& original,
const char* descriptor);
const art::DexFile& GetDexFile() {
diff --git a/openjdkjvmti/ti_class_definition.cc b/openjdkjvmti/ti_class_definition.cc
index 795a68a..2345a0a 100644
--- a/openjdkjvmti/ti_class_definition.cc
+++ b/openjdkjvmti/ti_class_definition.cc
@@ -57,7 +57,7 @@
std::string desc = std::string("L") + name_ + ";";
std::unique_ptr<FixedUpDexFile>
- fixed_dex_file(FixedUpDexFile::Create(*initial_dex_file_unquickened_, desc.c_str()));
+ fixed_dex_file(FixedUpDexFile::Create(loader_, *initial_dex_file_unquickened_, desc.c_str()));
CHECK(fixed_dex_file.get() != nullptr);
CHECK_LE(fixed_dex_file->Size(), temp_mmap_.Size());
CHECK_EQ(temp_mmap_.Size(), dex_data_mmap_.Size());
@@ -132,17 +132,20 @@
return OK;
}
-static void DequickenDexFile(const art::DexFile* dex_file,
+static void DequickenDexFile(jobject class_loader,
+ const art::DexFile* dex_file,
const char* descriptor,
/*out*/std::vector<unsigned char>* dex_data)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
- std::unique_ptr<FixedUpDexFile> fixed_dex_file(FixedUpDexFile::Create(*dex_file, descriptor));
+ std::unique_ptr<FixedUpDexFile> fixed_dex_file(
+ FixedUpDexFile::Create(class_loader, *dex_file, descriptor));
dex_data->resize(fixed_dex_file->Size());
memcpy(dex_data->data(), fixed_dex_file->Begin(), fixed_dex_file->Size());
}
// Gets the data surrounding the given class.
-static void GetDexDataForRetransformation(art::Handle<art::mirror::Class> klass,
+static void GetDexDataForRetransformation(art::ScopedObjectAccess& soa,
+ art::Handle<art::mirror::Class> klass,
/*out*/std::vector<unsigned char>* dex_data)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
art::StackHandleScope<3> hs(art::Thread::Current());
@@ -179,7 +182,8 @@
dex_file = &klass->GetDexFile();
}
std::string storage;
- DequickenDexFile(dex_file, klass->GetDescriptor(&storage), dex_data);
+ jobject loader = soa.AddLocalReference<jobject>(klass->GetClassLoader());
+ DequickenDexFile(loader, dex_file, klass->GetDescriptor(&storage), dex_data);
}
static bool DexNeedsDequickening(art::Handle<art::mirror::Class> klass,
@@ -332,7 +336,7 @@
const art::DexFile* quick_dex = GetQuickenedDexFile(m_klass);
auto get_original = [&](/*out*/std::vector<unsigned char>* dex_data)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
- GetDexDataForRetransformation(m_klass, dex_data);
+ GetDexDataForRetransformation(soa, m_klass, dex_data);
};
InitWithDex(get_original, quick_dex);
return OK;
@@ -365,7 +369,7 @@
protection_domain_ = nullptr;
auto get_original = [&](/*out*/std::vector<unsigned char>* dex_data)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
- DequickenDexFile(&dex_file, descriptor, dex_data);
+ DequickenDexFile(loader_, &dex_file, descriptor, dex_data);
};
InitWithDex(get_original, &dex_file);
}
diff --git a/runtime/Android.bp b/runtime/Android.bp
index a3081e9..a08ba70 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -392,14 +392,11 @@
"jni_platform_headers",
],
shared_libs: [
+ "libartpalette",
"libnativebridge",
"libnativeloader",
"libbacktrace",
"liblog",
- // For atrace, properties, ashmem.
- "libcutils",
- // For set_sched_policy.
- "libprocessgroup",
// For common macros.
"libbase",
],
@@ -424,9 +421,9 @@
},
},
static_libs: [
+ "libartpalette",
"libbacktrace",
"libbase",
- "libcutils",
"libdexfile_external", // libunwindstack dependency
"libdexfile_support", // libunwindstack dependency
"liblog",
diff --git a/runtime/base/locks.h b/runtime/base/locks.h
index 57719f1..b7d8e31 100644
--- a/runtime/base/locks.h
+++ b/runtime/base/locks.h
@@ -71,6 +71,7 @@
kRosAllocGlobalLock,
kRosAllocBracketLock,
kRosAllocBulkFreeLock,
+ kAllocSpaceLock,
kTaggingLockLevel,
kTransactionLogLock,
kCustomTlsLock,
@@ -84,7 +85,6 @@
kReferenceQueueClearedReferencesLock,
kReferenceProcessorLock,
kJitDebugInterfaceLock,
- kAllocSpaceLock,
kBumpPointerSpaceBlockLock,
kArenaPoolLock,
kInternTableLock,
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 5a52818..7aec661 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -107,15 +107,15 @@
blocked_tid_(kLogLockContentions ? blocked_tid : 0),
owner_tid_(kLogLockContentions ? owner_tid : 0),
start_nano_time_(kLogLockContentions ? NanoTime() : 0) {
- if (ATRACE_ENABLED()) {
+ if (ATraceEnabled()) {
std::string msg = StringPrintf("Lock contention on %s (owner tid: %" PRIu64 ")",
mutex->GetName(), owner_tid);
- ATRACE_BEGIN(msg.c_str());
+ ATraceBegin(msg.c_str());
}
}
~ScopedContentionRecorder() {
- ATRACE_END();
+ ATraceEnd();
if (kLogLockContentions) {
uint64_t end_nano_time = NanoTime();
mutex_->RecordContention(blocked_tid_, owner_tid_, end_nano_time - start_nano_time_);
diff --git a/runtime/base/timing_logger.cc b/runtime/base/timing_logger.cc
index 0a4cddd..bd39192 100644
--- a/runtime/base/timing_logger.cc
+++ b/runtime/base/timing_logger.cc
@@ -144,12 +144,12 @@
void TimingLogger::StartTiming(const char* label) {
DCHECK(label != nullptr);
timings_.push_back(Timing(kind_, label));
- ATRACE_BEGIN(label);
+ ATraceBegin(label);
}
void TimingLogger::EndTiming() {
timings_.push_back(Timing(kind_, nullptr));
- ATRACE_END();
+ ATraceEnd();
}
uint64_t TimingLogger::GetTotalNs() const {
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 5f62d75..d72003c 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2637,7 +2637,7 @@
}
void Heap::TraceHeapSize(size_t heap_size) {
- ATRACE_INT("Heap size (KB)", heap_size / KB);
+ ATraceIntegerValue("Heap size (KB)", heap_size / KB);
}
size_t Heap::GetNativeBytes() {
@@ -2878,6 +2878,15 @@
DCHECK_GE(now, last_update_time_gc_count_rate_histograms_);
uint64_t time_since_last_update = now - last_update_time_gc_count_rate_histograms_;
uint64_t num_of_windows = time_since_last_update / kGcCountRateHistogramWindowDuration;
+
+ // The computed number of windows can be incoherently high if NanoTime() is not monotonic.
+ // Setting a limit on its maximum value reduces the impact on CPU time in such cases.
+ if (num_of_windows > kGcCountRateHistogramMaxNumMissedWindows) {
+ LOG(WARNING) << "Reducing the number of considered missed Gc histogram windows from "
+ << num_of_windows << " to " << kGcCountRateHistogramMaxNumMissedWindows;
+ num_of_windows = kGcCountRateHistogramMaxNumMissedWindows;
+ }
+
if (time_since_last_update >= kGcCountRateHistogramWindowDuration) {
// Record the first window.
gc_count_rate_histogram_.AddValue(gc_count_last_window_ - 1); // Exclude the current run.
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 4c5d896..6bdba12 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -1495,6 +1495,8 @@
uint64_t blocking_gc_time_;
// The duration of the window for the GC count rate histograms.
static constexpr uint64_t kGcCountRateHistogramWindowDuration = MsToNs(10 * 1000); // 10s.
+ // Maximum number of missed histogram windows for which statistics will be collected.
+ static constexpr uint64_t kGcCountRateHistogramMaxNumMissedWindows = 100;
// The last time when the GC count rate histograms were updated.
// This is rounded by kGcCountRateHistogramWindowDuration (a multiple of 10s).
uint64_t last_update_time_gc_count_rate_histograms_;
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index af5e67a..1279997 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -29,15 +29,6 @@
#include "thread-inl.h"
#include "well_known_classes.h"
-#ifdef ART_TARGET_ANDROID
-#include <metricslogger/metrics_logger.h>
-using android::metricslogger::ComplexEventLogger;
-using android::metricslogger::ACTION_HIDDEN_API_ACCESSED;
-using android::metricslogger::FIELD_HIDDEN_API_ACCESS_METHOD;
-using android::metricslogger::FIELD_HIDDEN_API_ACCESS_DENIED;
-using android::metricslogger::FIELD_HIDDEN_API_SIGNATURE;
-#endif
-
namespace art {
namespace hiddenapi {
@@ -182,28 +173,6 @@
return member_name_ == other.member_name_ && type_signature_ == other.type_signature_;
}
-#ifdef ART_TARGET_ANDROID
-// Convert an AccessMethod enum to a value for logging from the proto enum.
-// This method may look odd (the enum values are current the same), but it
-// prevents coupling the internal enum to the proto enum (which should never
-// be changed) so that we are free to change the internal one if necessary in
-// future.
-inline static int32_t GetEnumValueForLog(AccessMethod access_method) {
- switch (access_method) {
- case AccessMethod::kNone:
- return android::metricslogger::ACCESS_METHOD_NONE;
- case AccessMethod::kReflection:
- return android::metricslogger::ACCESS_METHOD_REFLECTION;
- case AccessMethod::kJNI:
- return android::metricslogger::ACCESS_METHOD_JNI;
- case AccessMethod::kLinking:
- return android::metricslogger::ACCESS_METHOD_LINKING;
- default:
- DCHECK(false);
- }
-}
-#endif
-
void MemberSignature::LogAccessToEventLog(AccessMethod access_method, bool access_denied) {
#ifdef ART_TARGET_ANDROID
if (access_method == AccessMethod::kLinking || access_method == AccessMethod::kNone) {
@@ -213,19 +182,32 @@
// None does not correspond to actual access, so should also be ignored.
return;
}
- ComplexEventLogger log_maker(ACTION_HIDDEN_API_ACCESSED);
- log_maker.AddTaggedData(FIELD_HIDDEN_API_ACCESS_METHOD, GetEnumValueForLog(access_method));
- if (access_denied) {
- log_maker.AddTaggedData(FIELD_HIDDEN_API_ACCESS_DENIED, 1);
+ Runtime* runtime = Runtime::Current();
+ if (runtime->IsAotCompiler()) {
+ return;
}
+ JNIEnvExt* env = Thread::Current()->GetJniEnv();
const std::string& package_name = Runtime::Current()->GetProcessPackageName();
- if (!package_name.empty()) {
- log_maker.SetPackageName(package_name);
+ ScopedLocalRef<jstring> package_str(env, env->NewStringUTF(package_name.c_str()));
+ if (env->ExceptionCheck()) {
+ env->ExceptionClear();
+ LOG(ERROR) << "Unable to allocate string for package name which called hidden api";
}
std::ostringstream signature_str;
Dump(signature_str);
- log_maker.AddTaggedData(FIELD_HIDDEN_API_SIGNATURE, signature_str.str());
- log_maker.Record();
+ ScopedLocalRef<jstring> signature_jstr(env,
+ env->NewStringUTF(signature_str.str().c_str()));
+ if (env->ExceptionCheck()) {
+ env->ExceptionClear();
+ LOG(ERROR) << "Unable to allocate string for hidden api method signature";
+ }
+ env->CallStaticVoidMethod(WellKnownClasses::dalvik_system_VMRuntime,
+ WellKnownClasses::dalvik_system_VMRuntime_hiddenApiUsed, package_str.get(),
+ signature_jstr.get(), static_cast<jint>(access_method), access_denied);
+ if (env->ExceptionCheck()) {
+ env->ExceptionClear();
+ LOG(ERROR) << "Unable to report hidden api usage";
+ }
#else
UNUSED(access_method);
UNUSED(access_denied);
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index 8bd59ea..e15e9f3 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -45,11 +45,13 @@
return static_cast<EnforcementPolicy>(api_policy_int);
}
+// Hidden API access method
+// Thist must be kept in sync with VMRuntime.HiddenApiUsageLogger.ACCESS_METHOD_*
enum class AccessMethod {
- kNone, // internal test that does not correspond to an actual access by app
- kReflection,
- kJNI,
- kLinking,
+ kNone = 0, // internal test that does not correspond to an actual access by app
+ kReflection = 1,
+ kJNI = 2,
+ kLinking = 3,
};
// Represents the API domain of a caller/callee.
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 7240357..6abc8d7 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -280,7 +280,7 @@
// This function is inlined and just helps to not have the VLOG and ATRACE check at all the
// potential tracing points.
void Monitor::AtraceMonitorLock(Thread* self, mirror::Object* obj, bool is_wait) {
- if (UNLIKELY(VLOG_IS_ON(systrace_lock_logging) && ATRACE_ENABLED())) {
+ if (UNLIKELY(VLOG_IS_ON(systrace_lock_logging) && ATraceEnabled())) {
AtraceMonitorLockImpl(self, obj, is_wait);
}
}
@@ -338,12 +338,12 @@
(obj == nullptr ? -1 : static_cast<int32_t>(reinterpret_cast<uintptr_t>(obj))),
(filename != nullptr ? filename : "null"),
line_number);
- ATRACE_BEGIN(tmp.c_str());
+ ATraceBegin(tmp.c_str());
}
void Monitor::AtraceMonitorUnlock() {
if (UNLIKELY(VLOG_IS_ON(systrace_lock_logging))) {
- ATRACE_END();
+ ATraceEnd();
}
}
@@ -431,7 +431,7 @@
// If systrace logging is enabled, first look at the lock owner. Acquiring the monitor's
// lock and then re-acquiring the mutator lock can deadlock.
bool started_trace = false;
- if (ATRACE_ENABLED()) {
+ if (ATraceEnabled()) {
if (owner_ != nullptr) { // Did the owner_ give the lock up?
std::ostringstream oss;
std::string name;
@@ -450,7 +450,7 @@
oss << " blocking from "
<< ArtMethod::PrettyMethod(m) << "(" << (filename != nullptr ? filename : "null")
<< ":" << line_number << ")";
- ATRACE_BEGIN(oss.str().c_str());
+ ATraceBegin(oss.str().c_str());
started_trace = true;
}
}
@@ -581,7 +581,7 @@
}
}
if (started_trace) {
- ATRACE_END();
+ ATraceEnd();
}
self->SetMonitorEnterObject(nullptr);
monitor_lock_.Lock(self); // Reacquire locks in order.
diff --git a/runtime/native_stack_dump.cc b/runtime/native_stack_dump.cc
index 88adad0..00a0a39 100644
--- a/runtime/native_stack_dump.cc
+++ b/runtime/native_stack_dump.cc
@@ -63,6 +63,18 @@
static constexpr bool kUseAddr2line = !kIsTargetBuild;
+std::string FindAddr2line() {
+ if (!kIsTargetBuild) {
+ constexpr const char* kAddr2linePrebuiltPath =
+ "/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8/bin/x86_64-linux-addr2line";
+ const char* env_value = getenv("ANDROID_BUILD_TOP");
+ if (env_value != nullptr) {
+ return std::string(env_value) + kAddr2linePrebuiltPath;
+ }
+ }
+ return std::string("/usr/bin/addr2line");
+}
+
ALWAYS_INLINE
static inline void WritePrefix(std::ostream& os, const char* prefix, bool odd) {
if (prefix != nullptr) {
@@ -232,8 +244,9 @@
}
pipe->reset(); // Close early.
+ std::string addr2linePath = FindAddr2line();
const char* args[7] = {
- "/usr/bin/addr2line",
+ addr2linePath.c_str(),
"--functions",
"--inlines",
"--demangle",
@@ -314,7 +327,7 @@
if (kUseAddr2line) {
// Try to run it to see whether we have it. Push an argument so that it doesn't assume a.out
// and print to stderr.
- use_addr2line = (gAborting > 0) && RunCommand("addr2line -h");
+ use_addr2line = (gAborting > 0) && RunCommand(FindAddr2line() + " -h");
} else {
use_addr2line = false;
}
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 309c04e..4828aae 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -16,10 +16,6 @@
#include "thread.h"
-#if !defined(__APPLE__)
-#include <sched.h>
-#endif
-
#include <pthread.h>
#include <signal.h>
#include <sys/resource.h>
@@ -95,6 +91,7 @@
#include "oat_quick_method_header.h"
#include "obj_ptr-inl.h"
#include "object_lock.h"
+#include "palette/palette.h"
#include "quick/quick_method_frame_info.h"
#include "quick_exception_handler.h"
#include "read_barrier-inl.h"
@@ -4233,6 +4230,7 @@
Runtime::Current()->GetThreadList()->RunCheckpoint(&closure);
}
+
void Thread::ReleaseLongJumpContextInternal() {
// Each QuickExceptionHandler gets a long jump context and uses
// it for doing the long jump, after finding catch blocks/doing deoptimization.
@@ -4246,4 +4244,18 @@
delete tlsPtr_.long_jump_context;
}
+void Thread::SetNativePriority(int new_priority) {
+ // ART tests on JVM can reach this code path, use tid = 0 as shorthand for current thread.
+ PaletteStatus status = PaletteSchedSetPriority(0, new_priority);
+ CHECK(status == PaletteStatus::kOkay || status == PaletteStatus::kCheckErrno);
+}
+
+int Thread::GetNativePriority() {
+ int priority = 0;
+ // ART tests on JVM can reach this code path, use tid = 0 as shorthand for current thread.
+ PaletteStatus status = PaletteSchedGetPriority(0, &priority);
+ CHECK(status == PaletteStatus::kOkay || status == PaletteStatus::kCheckErrno);
+ return priority;
+}
+
} // namespace art
diff --git a/runtime/thread_android.cc b/runtime/thread_android.cc
index 24864f9..f333400 100644
--- a/runtime/thread_android.cc
+++ b/runtime/thread_android.cc
@@ -16,84 +16,8 @@
#include "thread.h"
-#include <errno.h>
-#include <limits.h>
-#include <sys/resource.h>
-#include <sys/time.h>
-
-#include <processgroup/sched_policy.h>
-#include <utils/threads.h>
-
-#include "base/macros.h"
-
namespace art {
-// Conversion map for "nice" values.
-//
-// We use Android thread priority constants to be consistent with the rest
-// of the system. In some cases adjacent entries may overlap.
-//
-static const int kNiceValues[10] = {
- ANDROID_PRIORITY_LOWEST, // 1 (MIN_PRIORITY)
- ANDROID_PRIORITY_BACKGROUND + 6,
- ANDROID_PRIORITY_BACKGROUND + 3,
- ANDROID_PRIORITY_BACKGROUND,
- ANDROID_PRIORITY_NORMAL, // 5 (NORM_PRIORITY)
- ANDROID_PRIORITY_NORMAL - 2,
- ANDROID_PRIORITY_NORMAL - 4,
- ANDROID_PRIORITY_URGENT_DISPLAY + 3,
- ANDROID_PRIORITY_URGENT_DISPLAY + 2,
- ANDROID_PRIORITY_URGENT_DISPLAY // 10 (MAX_PRIORITY)
-};
-
-void Thread::SetNativePriority(int newPriority) {
- if (newPriority < 1 || newPriority > 10) {
- LOG(WARNING) << "bad priority " << newPriority;
- newPriority = 5;
- }
-
- int newNice = kNiceValues[newPriority-1];
- pid_t tid = GetTid();
-
- // TODO: b/18249098 The code below is broken. It uses getpriority() as a proxy for whether a
- // thread is already in the SP_FOREGROUND cgroup. This is not necessarily true for background
- // processes, where all threads are in the SP_BACKGROUND cgroup. This means that callers will
- // have to call setPriority twice to do what they want :
- //
- // Thread.setPriority(Thread.MIN_PRIORITY); // no-op wrt to cgroups
- // Thread.setPriority(Thread.MAX_PRIORITY); // will actually change cgroups.
- if (newNice >= ANDROID_PRIORITY_BACKGROUND) {
- set_sched_policy(tid, SP_BACKGROUND);
- } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
- set_sched_policy(tid, SP_FOREGROUND);
- }
-
- if (setpriority(PRIO_PROCESS, tid, newNice) != 0) {
- PLOG(INFO) << *this << " setPriority(PRIO_PROCESS, " << tid << ", " << newNice << ") failed";
- }
-}
-
-int Thread::GetNativePriority() {
- errno = 0;
- int native_priority = getpriority(PRIO_PROCESS, 0);
- if (native_priority == -1 && errno != 0) {
- PLOG(WARNING) << "getpriority failed";
- return kNormThreadPriority;
- }
-
- int managed_priority = kMinThreadPriority;
- for (size_t i = 0; i < arraysize(kNiceValues); i++) {
- if (native_priority >= kNiceValues[i]) {
- break;
- }
- managed_priority++;
- }
- if (managed_priority > kMaxThreadPriority) {
- managed_priority = kMaxThreadPriority;
- }
- return managed_priority;
-}
-
void Thread::SetUpAlternateSignalStack() {
// Bionic does this for us.
}
diff --git a/runtime/thread_linux.cc b/runtime/thread_linux.cc
index d05fecf..3ed4276 100644
--- a/runtime/thread_linux.cc
+++ b/runtime/thread_linux.cc
@@ -23,14 +23,6 @@
namespace art {
-void Thread::SetNativePriority(int) {
- // Do nothing.
-}
-
-int Thread::GetNativePriority() {
- return kNormThreadPriority;
-}
-
static void SigAltStack(stack_t* new_stack, stack_t* old_stack) {
if (sigaltstack(new_stack, old_stack) == -1) {
PLOG(FATAL) << "sigaltstack failed";
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index 1b3b037..a5406ea 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -683,7 +683,7 @@
AssertThreadsAreSuspended(self, self);
}
}
- ATRACE_BEGIN((std::string("Mutator threads suspended for ") + cause).c_str());
+ ATraceBegin((std::string("Mutator threads suspended for ") + cause).c_str());
if (self != nullptr) {
VLOG(threads) << *self << " SuspendAll complete";
@@ -811,7 +811,7 @@
VLOG(threads) << "Thread[null] ResumeAll starting";
}
- ATRACE_END();
+ ATraceEnd();
ScopedTrace trace("Resuming mutator threads");
@@ -855,8 +855,8 @@
}
bool ThreadList::Resume(Thread* thread, SuspendReason reason) {
- // This assumes there was an ATRACE_BEGIN when we suspended the thread.
- ATRACE_END();
+ // This assumes there was an ATraceBegin when we suspended the thread.
+ ATraceEnd();
Thread* self = Thread::Current();
DCHECK_NE(thread, self);
@@ -987,10 +987,10 @@
// done.
if (thread->IsSuspended()) {
VLOG(threads) << "SuspendThreadByPeer thread suspended: " << *thread;
- if (ATRACE_ENABLED()) {
+ if (ATraceEnabled()) {
std::string name;
thread->GetThreadName(name);
- ATRACE_BEGIN(StringPrintf("SuspendThreadByPeer suspended %s for peer=%p", name.c_str(),
+ ATraceBegin(StringPrintf("SuspendThreadByPeer suspended %s for peer=%p", name.c_str(),
peer).c_str());
}
return thread;
@@ -1097,10 +1097,10 @@
// count, or else we've waited and it has self suspended) or is the current thread, we're
// done.
if (thread->IsSuspended()) {
- if (ATRACE_ENABLED()) {
+ if (ATraceEnabled()) {
std::string name;
thread->GetThreadName(name);
- ATRACE_BEGIN(StringPrintf("SuspendThreadByThreadId suspended %s id=%d",
+ ATraceBegin(StringPrintf("SuspendThreadByThreadId suspended %s id=%d",
name.c_str(), thread_id).c_str());
}
VLOG(threads) << "SuspendThreadByThreadId thread suspended: " << *thread;
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index f61faa3..955a455 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -84,6 +84,7 @@
jmethodID WellKnownClasses::dalvik_system_BaseDexClassLoader_getLdLibraryPath;
jmethodID WellKnownClasses::dalvik_system_VMRuntime_runFinalization;
+jmethodID WellKnownClasses::dalvik_system_VMRuntime_hiddenApiUsed;
jmethodID WellKnownClasses::java_lang_Boolean_valueOf;
jmethodID WellKnownClasses::java_lang_Byte_valueOf;
jmethodID WellKnownClasses::java_lang_Character_valueOf;
@@ -344,6 +345,7 @@
dalvik_system_BaseDexClassLoader_getLdLibraryPath = CacheMethod(env, dalvik_system_BaseDexClassLoader, false, "getLdLibraryPath", "()Ljava/lang/String;");
dalvik_system_VMRuntime_runFinalization = CacheMethod(env, dalvik_system_VMRuntime, true, "runFinalization", "(J)V");
+ dalvik_system_VMRuntime_hiddenApiUsed = CacheMethod(env, dalvik_system_VMRuntime, true, "hiddenApiUsed", "(Ljava/lang/String;Ljava/lang/String;IZ)V");
java_lang_ClassNotFoundException_init = CacheMethod(env, java_lang_ClassNotFoundException, false, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
java_lang_ClassLoader_loadClass = CacheMethod(env, java_lang_ClassLoader, false, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
@@ -486,6 +488,7 @@
dalvik_system_BaseDexClassLoader_getLdLibraryPath = nullptr;
dalvik_system_VMRuntime_runFinalization = nullptr;
+ dalvik_system_VMRuntime_hiddenApiUsed = nullptr;
java_lang_Boolean_valueOf = nullptr;
java_lang_Byte_valueOf = nullptr;
java_lang_Character_valueOf = nullptr;
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index f0e98a8..872b562 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -93,6 +93,7 @@
static jmethodID dalvik_system_BaseDexClassLoader_getLdLibraryPath;
static jmethodID dalvik_system_VMRuntime_runFinalization;
+ static jmethodID dalvik_system_VMRuntime_hiddenApiUsed;
static jmethodID java_lang_Boolean_valueOf;
static jmethodID java_lang_Byte_valueOf;
static jmethodID java_lang_Character_valueOf;
diff --git a/test/622-checker-bce-regressions/src/Main.java b/test/622-checker-bce-regressions/src/Main.java
index 6ba2644..595ade8 100644
--- a/test/622-checker-bce-regressions/src/Main.java
+++ b/test/622-checker-bce-regressions/src/Main.java
@@ -42,8 +42,22 @@
return j;
}
+ static public void $noinline$regressionTest123284765(String str) {
+ try {
+ int l = str.length();
+ if (l == 34) {
+ str.charAt(l);
+ fail();
+ }
+ } catch (StringIndexOutOfBoundsException expected) {
+ expectEquals(34, str.length());
+ }
+ }
+
public static void main(String[] args) {
expectEquals(8, doNotVisitAfterForwardBCE(array));
+ $noinline$regressionTest123284765("0123456789012345678901234567890123");
+ $noinline$regressionTest123284765("012345678901");
System.out.println("passed");
}
@@ -52,4 +66,8 @@
throw new Error("Expected: " + expected + ", found: " + result);
}
}
+
+ private static void fail() {
+ throw new Error("FAIL");
+ }
}
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 50d5fee..8407b49 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -761,8 +761,8 @@
if [ "$DEV_MODE" = "y" ]; then
zip_options=""
fi
- setupapex_cmdline="unzip -u ${zip_options} ${ZIPAPEX_LOC} apex_payload.zip -d ${DEX_LOCATION}"
- installapex_cmdline="unzip -u ${zip_options} ${DEX_LOCATION}/apex_payload.zip -d ${DEX_LOCATION}/zipapex"
+ setupapex_cmdline="unzip -o -f -u ${zip_options} ${ZIPAPEX_LOC} apex_payload.zip -d ${DEX_LOCATION}"
+ installapex_cmdline="unzip -o -f -u ${zip_options} ${DEX_LOCATION}/apex_payload.zip -d ${DEX_LOCATION}/zipapex"
BIN_DIR=$DEX_LOCATION/zipapex/bin
fi
@@ -1066,7 +1066,7 @@
mkdir -p ${mkdir_locations} || exit 1
$setupapex_cmdline || { echo "zipapex extraction failed." >&2 ; exit 2; }
- $installapex_cmdline || { echo "zipapex install failed." >&2 ; exit 2; }
+ $installapex_cmdline || { echo "zipapex install failed. cmd was: ${installapex_cmdline}." >&2; find ${mkdir_locations} -type f >&2; exit 2; }
$linkroot_cmdline || { echo "create symlink android-root failed." >&2 ; exit 2; }
$linkroot_overlay_cmdline || { echo "overlay android-root failed." >&2 ; exit 2; }
$profman_cmdline || { echo "Profman failed." >&2 ; exit 2; }
diff --git a/test/knownfailures.json b/test/knownfailures.json
index b97b4c1..8de9574 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -1173,6 +1173,11 @@
"description": ["Tests are expected to fail with baseline."]
},
{
+ "tests": ["1339-dead-reference-safe"],
+ "variant": "debuggable",
+ "description": [ "Fails to eliminate dead reference when debuggable." ]
+ },
+ {
"tests": ["708-jit-cache-churn"],
"variant": "jit-on-first-use",
"bug": "b/120112467",
diff --git a/test/testrunner/run_build_test_target.py b/test/testrunner/run_build_test_target.py
index 139d1af..19f03c3 100755
--- a/test/testrunner/run_build_test_target.py
+++ b/test/testrunner/run_build_test_target.py
@@ -28,6 +28,7 @@
import argparse
import os
+import pathlib
import subprocess
import sys
@@ -108,7 +109,10 @@
run_test_command = [os.path.join(env.ANDROID_BUILD_TOP,
'art/test/testrunner/testrunner.py')]
test_flags = target.get('run-test', [])
- run_test_command += list(map(lambda a: a.format(SOONG_OUT_DIR=env.SOONG_OUT_DIR), test_flags))
+ out_dir = pathlib.PurePath(env.SOONG_OUT_DIR)
+ if not out_dir.is_absolute():
+ out_dir = pathlib.PurePath(env.ANDROID_BUILD_TOP).joinpath(out_dir)
+ run_test_command += list(map(lambda a: a.format(SOONG_OUT_DIR=str(out_dir)), test_flags))
# Let testrunner compute concurrency based on #cpus.
# b/65822340
# run_test_command += ['-j', str(n_threads)]
diff --git a/tools/build_linux_bionic.sh b/tools/build_linux_bionic.sh
index d3c1912..b401071 100755
--- a/tools/build_linux_bionic.sh
+++ b/tools/build_linux_bionic.sh
@@ -35,14 +35,22 @@
# Soong needs a bunch of variables set and will not run if they are missing.
# The default values of these variables is only contained in make, so use
# nothing to create the variables then remove all the other artifacts.
-build/soong/soong_ui.bash --make-mode nothing
+
+# TODO(b/123645297) Move hiddenapi steps to soong.
+#
+# Currently hiddenapi relies on .mk to build some of it's configuration files.
+# This prevents us from just cleaning using soong and forces us to do this
+# hacky workaround where we build the targets without linux_bionic and delete
+# the build-config files before going around again. If we fix this issue we can
+# change to only building 'nothing' instead.
+build/soong/soong_ui.bash --make-mode "$@"
+
if [ $? != 0 ]; then
exit 1
fi
out_dir=$(get_build_var OUT_DIR)
host_out=$(get_build_var HOST_OUT)
-mk_product_out=$(get_build_var PRODUCT_OUT)
# TODO(b/31559095) Figure out a better way to do this.
#
@@ -51,14 +59,17 @@
tmp_soong_var=$(mktemp --tmpdir soong.variables.bak.XXXXXX)
cat $out_dir/soong/soong.variables > ${tmp_soong_var}
-build/soong/soong_ui.bash --make-mode clean
-mkdir -p $out_dir/soong
-mkdir -p $mk_product_out
-# TODO(b/31559095) Soong will panic if this file isn't present. It contains
-# information from MAKE needed to let soong handle the invocation of dex2oat.
-# This would be great to have but for now isn't needed.
-echo "{}" > $mk_product_out/dexpreopt.config
+# See comment above about b/123645297 for why we cannot just do m clean. Clear
+# out all files except for intermediates and installed files.
+find $out_dir/ -maxdepth 1 -mindepth 1 \
+ -not -name soong \
+ -not -name host \
+ -not -name target | xargs -I '{}' rm -rf '{}'
+find $out_dir/soong/ -maxdepth 1 -mindepth 1 \
+ -not -name .intermediates \
+ -not -name host \
+ -not -name target | xargs -I '{}' rm -rf '{}'
python3 <<END - ${tmp_soong_var} ${out_dir}/soong/soong.variables
import json
diff --git a/tools/buildbot-build.sh b/tools/buildbot-build.sh
index 755104b..6be243a 100755
--- a/tools/buildbot-build.sh
+++ b/tools/buildbot-build.sh
@@ -77,6 +77,7 @@
make_command+=" debuggerd su"
make_command+=" libstdc++ "
make_command+=" ${ANDROID_PRODUCT_OUT#"${ANDROID_BUILD_TOP}/"}/system/etc/public.libraries.txt"
+ make_command+=" art-bionic-files"
if [[ -n "$ART_TEST_CHROOT" ]]; then
# These targets are needed for the chroot environment.
make_command+=" crash_dump event-log-tags"
diff --git a/tools/dexanalyze/Android.bp b/tools/dexanalyze/Android.bp
index a85bf56..a232a1b 100644
--- a/tools/dexanalyze/Android.bp
+++ b/tools/dexanalyze/Android.bp
@@ -24,11 +24,6 @@
"dexanalyze_experiments.cc",
"dexanalyze_strings.cc",
],
- target: {
- android: {
- shared_libs: ["libcutils"],
- },
- },
header_libs: [
"art_cmdlineparser_headers",
],
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index 9b0873e..5177919 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -234,5 +234,12 @@
"libcore.libcore.icu.TimeZoneIntegrationTest#testTimeZoneDebugInfo",
"libcore.libcore.icu.TimeZoneIntegrationTest#testTzDataSetVersions"
]
+},
+{
+ description: "Expected networking failure on host / old systems: we expect 97 (EAFNOSUPPORT), but we get 22 (EINVAL)",
+ result: EXEC_FAILED,
+ names: [
+ "libcore.libcore.io.OsTest#testCrossFamilyBindConnectSendto"
+ ]
}
]
diff --git a/tools/timeout_dumper/timeout_dumper.cc b/tools/timeout_dumper/timeout_dumper.cc
index e04aefb..08d2f4c 100644
--- a/tools/timeout_dumper/timeout_dumper.cc
+++ b/tools/timeout_dumper/timeout_dumper.cc
@@ -93,7 +93,7 @@
namespace addr2line {
constexpr const char* kAddr2linePath =
- "/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/bin/x86_64-linux-addr2line";
+ "/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8/bin/x86_64-linux-addr2line";
std::unique_ptr<std::string> FindAddr2line() {
const char* env_value = getenv("ANDROID_BUILD_TOP");
diff --git a/tools/tracefast-plugin/Android.bp b/tools/tracefast-plugin/Android.bp
index 1d7dd30..b7ae6c6 100644
--- a/tools/tracefast-plugin/Android.bp
+++ b/tools/tracefast-plugin/Android.bp
@@ -30,11 +30,6 @@
"libbase",
],
target: {
- android: {
- shared_libs: [
- "libcutils",
- ],
- },
darwin: {
enabled: false,
},
diff --git a/tools/veridex/hidden_api.cc b/tools/veridex/hidden_api.cc
index 1dae93a..efb01f7 100644
--- a/tools/veridex/hidden_api.cc
+++ b/tools/veridex/hidden_api.cc
@@ -37,7 +37,7 @@
CHECK(success) << "Unknown ApiList flag: " << str;
CHECK(membership.IsValid()) << "Invalid ApiList: " << membership;
- if (sdk_uses_only != (membership == hiddenapi::ApiList::Whitelist())) {
+ if (sdk_uses_only != membership.Contains(hiddenapi::ApiList::Whitelist())) {
// Either we want only SDK uses and this is not a whitelist entry,
// or we want only non-SDK uses and this is a whitelist entry.
continue;