diff options
781 files changed, 25609 insertions, 11240 deletions
diff --git a/Android.bp b/Android.bp index e57045fc5b..d205aeb802 100644 --- a/Android.bp +++ b/Android.bp @@ -1,3 +1,21 @@ +// Copyright (C) 2017 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_visibility: ["//visibility:private"], +} + build = [ "JavaLibrary.bp", "NativeCode.bp", @@ -5,6 +23,9 @@ build = [ genrule { name: "notices-for-framework-stubs", + visibility: [ + "//frameworks/base", + ], tool_files: [ "NOTICE", "ojluni/NOTICE", diff --git a/Android.mk b/Android.mk deleted file mode 100644 index 465c964339..0000000000 --- a/Android.mk +++ /dev/null @@ -1,35 +0,0 @@ -# -*- mode: makefile -*- -# Copyright (C) 2009 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -LOCAL_PATH := $(call my-dir) - -# -# Subprojects with separate makefiles -# - -subdirs := benchmarks tzdata ojluni tools/upstream metrictests -subdir_makefiles := $(call all-named-subdir-makefiles,$(subdirs)) - -# -# Disable test modules if LIBCORE_SKIP_TESTS environment variable is set. -# - -ifneq ($(LIBCORE_SKIP_TESTS),) -$(info ********************************************************************************) -$(info * libcore tests are skipped because environment variable LIBCORE_SKIP_TESTS=$(LIBCORE_SKIP_TESTS)) -$(info ********************************************************************************) -endif - -include $(subdir_makefiles) diff --git a/JavaLibrary.bp b/JavaLibrary.bp index 2066c42bee..8b0ab3ba8e 100644 --- a/JavaLibrary.bp +++ b/JavaLibrary.bp @@ -19,8 +19,8 @@ // The Android core library provides low-level APIs for use by the rest of the // Android software stack. It is made up of various parts, some of which can be // found in libcore/ and other parts that can be found in various external/ -// directories. See the "core-system-modules" definition for the parts. - +// directories. +// // libcore has some sub-directories that follow a common structure: // e.g. dalvik, dom, harmony-tests, json, jsr166-tests, luni, libart, ojluni, // support, xml, xmlpull. @@ -45,14 +45,40 @@ build = [ ] // The Java files and their associated resources. -core_resource_dirs = [ - "luni/src/main/java", - "ojluni/src/main/resources/", +filegroup { + name: "core-luni-resources", + visibility: [ + "//libcore:__subpackages__", + ], + path: "luni/src/main/java/", + srcs: [ + "luni/src/main/java/java/util/logging/logging.properties", + "luni/src/main/java/java/security/security.properties", + ], +} + +filegroup { + name: "core-ojluni-resources", + visibility: [ + "//libcore:__subpackages__", + ], + path: "ojluni/src/main/resources/", + srcs: [ + "ojluni/src/main/resources/**/*", + ], +} + +core_resources = [ + ":core-luni-resources", + ":core-ojluni-resources", ] // The source files that go into core-oj. filegroup { name: "core_oj_java_files", + visibility: [ + "//libcore:__subpackages__", + ], srcs: [":openjdk_java_files"], } @@ -66,9 +92,11 @@ filegroup { // The source files that go into core-libart. filegroup { name: "core_libart_java_files", + visibility: [ + "//libcore:__subpackages__", + ], srcs: [ ":non_openjdk_java_files", - ":android_icu4j_src_files", ], } @@ -78,36 +106,26 @@ filegroup { name: "core_libart_api_files", srcs: [ ":non_openjdk_javadoc_files", - ":android_icu4j_src_files", ], } -// The set of files for the core library that have been marked up with @hide -// for the public SDK APIs. Used from frameworks/base/ to indicate the source -// files for inclusion in the public SDK docs. -filegroup { - name: "core_public_api_files", - srcs: [ - ":core_oj_api_files", - ":core_libart_api_files", - ":conscrypt_public_api_files", - ], -} - -// The set of files for the core library that have been marked up with @hide and -// API-related annotations. Note that this includes the intra-core and -// core-platform APIs as well as the public APIs. +// The set of files for the ART module that contribute to one or more API +// surfaces. This includes files that are in the public API as well as those +// that are not but which have been marked up with @hide plus one or more of +// the API defining annotations. // // Some source files in :core_oj_api_files and :openjdk_mmodule_extra_files are // annotated by applying annotations to the .annotated.java stubs files in // ojluni/annotated/mmodules and rather than in the original source. See the comments // in openjdk_java_files.bp for more details. filegroup { - name: "core_api_files", + name: "art_module_api_files", + visibility: [ + "//libcore:__subpackages__", + ], srcs: [ ":apache-xml_api_files", ":bouncycastle_java_files", - ":conscrypt_java_files", ":core_oj_api_files", ":core_libart_api_files", ":okhttp_api_files", @@ -124,8 +142,8 @@ java_defaults { dxflags: ["--core-library"], errorprone: { javacflags: [ - "-Xep:MissingOverride:OFF", // Ignore missing @Override. - "-Xep:ConstantOverflow:WARN", // Known constant overflow in SplittableRandom + "-Xep:MissingOverride:OFF", // Ignore missing @Override. + "-Xep:ConstantOverflow:WARN", // Known constant overflow in SplittableRandom ], }, } @@ -134,41 +152,46 @@ java_defaults { // Build for the target (device). // -// Rule generating resource lib for android_icu4j. -// In the downstream branch master-icu-dev, the resource files are generated. -// This rule can't be moved external/icu because soong enforces that no_standard_libs:true can only -// be used in libcore/ or development/ -java_library { - name: "android_icu4j_resources_lib", - java_resources: [":android_icu4j_resources"], - no_standard_libs: true, - system_modules: "none", -} - // A target used to bootstrap compilation for the core library. +// // See core-all-system-modules for more details. java_library { name: "core-all", defaults: ["libcore_java_defaults"], srcs: [ + // Use the source code for the I18N module intra core API as using the + // compiled version does not work due to limitations in either soong or the javac + // toolchain. See http://b/142056316 for more details. + ":i18n-module-intra-core-api-stubs-source", ":core_oj_java_files", ":core_libart_java_files", ":openjdk_lambda_stub_files", + ":openjdk_generated_annotation_stub_files", + ":app-compat-annotations-source", ], - no_standard_libs: true, + sdk_version: "none", system_modules: "none", + patch_module: "java.base", openjdk9: { srcs: ["luni/src/module/java/module-info.java"], - javacflags: ["--patch-module=java.base=."], }, - java_resource_dirs: core_resource_dirs, - static_libs: ["android_icu4j_resources_lib"], + java_resources: core_resources, java_version: "1.9", installable: false, + + plugins: [ + "compat-changeid-annotation-processor", + "unsupportedappusage-annotation-processor", + ], +} + +platform_compat_config { + name: "libcore-platform-compat-config", + src: ":core-all", } // A system modules definition for use by core library targets only. It only @@ -178,30 +201,43 @@ java_library { // etc. This system_modules definition is used to bootstrap compilation for // other parts of the core library like core-oj, core-libart, conscrypt, // bouncycastle, etc. -// -// If you want to compile against the entire core library implementation, for -// example to build core library tests, see "core-system-modules" instead. java_system_modules { name: "core-all-system-modules", + + // Visibility is deliberately restricted to a small set of build modules that + // the core library team control. + visibility: [ + "//external/apache-harmony:__subpackages__", + "//external/apache-xml", + "//external/okhttp", + "//libcore:__subpackages__", + ], + libs: ["core-all"], } // Contains the parts of core library associated with OpenJDK. java_library { name: "core-oj", + visibility: [ + "//art/build/apex", + "//external/wycheproof", + "//libcore/benchmarks", + ], + apex_available: [ + "com.android.art.release", + "com.android.art.debug", + ], defaults: ["libcore_java_defaults"], installable: true, hostdex: true, srcs: [":core_oj_java_files"], - java_resource_dirs: core_resource_dirs, + java_resources: core_resources, - no_standard_libs: true, - libs: ["core-all"], + sdk_version: "none", system_modules: "core-all-system-modules", - openjdk9: { - javacflags: ["--patch-module=java.base=."], - }, + patch_module: "java.base", jacoco: { exclude_filter: [ @@ -225,24 +261,31 @@ java_library { } // Contains parts of core library not associated with OpenJDK. Contains not -// just java.*, javax.* code but also android.icu.*, android.system.* and -// various internal libcore.* packages. +// just java.*, javax.* code but also android.system.* and various internal +// libcore.* packages. java_library { name: "core-libart", + visibility: [ + "//art/build/apex", + "//external/robolectric-shadows", + "//external/wycheproof", + "//libcore/benchmarks", + "//frameworks/layoutlib", + ], + apex_available: [ + "com.android.art.release", + "com.android.art.debug", + ], defaults: ["libcore_java_defaults"], installable: true, hostdex: true, srcs: [":core_libart_java_files"], - static_libs: ["android_icu4j_resources_lib"], java_version: "1.9", - no_standard_libs: true, - libs: ["core-all"], + sdk_version: "none", system_modules: "core-all-system-modules", - openjdk9: { - javacflags: ["--patch-module=java.base=."], - }, + patch_module: "java.base", jacoco: { exclude_filter: [ @@ -251,35 +294,55 @@ java_library { ], }, - required: [ - // Device files put in /system. - "tzdata", - "tz_version", - // Files used to simulate the /system and runtime APEX dir - // structure on host. - "tzdata_host", - "tzdata_host_runtime_apex", - "tzlookup.xml_host_runtime_apex", - "tz_version_host", - "tz_version_host_runtime_apex", - ], + target: { + hostdex: { + required: [ + // Files used to simulate the /system, runtime APEX and tzdata + // APEX dir structure on host. + "icu_tzdata.dat_host_tzdata_apex", + "tzdata_host", + "tzdata_host_tzdata_apex", + "tzlookup.xml_host_tzdata_apex", + "tz_version_host", + "tz_version_host_tzdata_apex", + ], + }, + }, } // Provided solely to contribute information about which hidden parts of the // core-oj API are used by apps. +// +// The build system determines that this library provides hiddenapi information +// for the core-oj bootjar because its name is of the form <x>-hiddenapi, where +// <x> is the name of a boot jar. That triggers the generation of a flags.csv +// file which encapsulates information extracted from the UnsupportedAppUsage +// annotations in the dex. The information from that file is then encoded into +// the core-oj file. +// +// Usually, e.g. for core-libart, the UnsupportedAppUsage annotations are +// added to the source that is compiled directly into the bootjar and the build +// system extracts the information about UnsupportedAppUsage directly from +// there. +// +// This approach of having separate annotated source and a separate build +// target was taken for ojluni to avoid having to maintain local patches in the +// ojluni source for UnsupportedAppUsage annotations as that would make it more +// difficult to pull down changes from upstream. +// java_library { name: "core-oj-hiddenapi", + // Do not allow this to be accessed from outside this directory. + visibility: ["//visibility:private"], defaults: ["libcore_java_defaults"], compile_dex: true, srcs: [":openjdk_hiddenapi_javadoc_files"], - no_standard_libs: true, - libs: ["core-all"], + sdk_version: "none", system_modules: "core-all-system-modules", - openjdk9: { - javacflags: ["--patch-module=java.base=."], - }, + patch_module: "java.base", + plugins: ["unsupportedappusage-annotation-processor"], } // @@ -293,8 +356,7 @@ java_library { name: "core-oj-testdex", installable: true, static_libs: ["core-oj"], - no_standard_libs: true, - libs: ["core-all"], + sdk_version: "none", system_modules: "core-all-system-modules", dxflags: ["--core-library"], dex_preopt: { @@ -308,8 +370,7 @@ java_library { name: "core-libart-testdex", installable: true, static_libs: ["core-libart"], - no_standard_libs: true, - libs: ["core-all"], + sdk_version: "none", system_modules: "core-all-system-modules", dxflags: ["--core-library"], dex_preopt: { @@ -318,18 +379,14 @@ java_library { notice: "ojluni/NOTICE", } - java_defaults { name: "core_lambda_stubs_defaults", defaults: ["libcore_java_defaults"], hostdex: true, - no_standard_libs: true, - libs: ["core-all"], + sdk_version: "none", system_modules: "core-all-system-modules", - openjdk9: { - javacflags: ["--patch-module=java.base=."], - }, + patch_module: "java.base", notice: "ojluni/NOTICE", @@ -343,11 +400,15 @@ java_defaults { // are also in the public SDK API from API level 26 onwards. java_library { name: "core-lambda-stubs", + visibility: ["//visibility:public"], defaults: ["core_lambda_stubs_defaults"], srcs: [ ":openjdk_lambda_stub_files", ":openjdk_lambda_duplicate_stub_files", ], + // This jar is packaged as part of the SDK, use -target 8 so that it works + // with old JDKs. + java_version: "1.8", } // An alternative to core-lambda-stubs that omits openjdk_lambda_duplicate_stub_files @@ -355,41 +416,50 @@ java_library { // (since API level 26). java_library { name: "core-lambda-stubs-for-system-modules", + visibility: [ + "//libcore/mmodules/core_platform_api", + ], defaults: ["core_lambda_stubs_defaults"], srcs: [ ":openjdk_lambda_stub_files", ], + include_srcs: true, } -// A system modules definition containing the implementations for the various -// parts that make up the core library. -// -// This system module is intended for use by tests that may need access to -// core library internals. It should not be generally used; most of the -// platform build should build against API stubs instead. See -// "core-platform-api-stubs-system-modules", which is the default used by the -// Android build. -// -// This module also includes lambda stubs for compiling source containing -// Java lambdas. -java_system_modules { - name: "core-system-modules", - libs: [ - "core-oj", - "core-libart", - "bouncycastle", - "conscrypt", - "okhttp", - "apache-xml", - // This one is not on device but it's needed when javac compiles code - // containing lambdas. - "core-lambda-stubs-for-system-modules", +// Creates a jar that exists to satisfy javac when compiling source code that +// contains @Generated annotations, which are produced by some code generation +// tools (notably dagger) but aren't part of the Android API. +// See http://b/123891440. +java_library { + name: "core-generated-annotation-stubs", + visibility: [ + "//libcore/mmodules/core_platform_api", + ], + defaults: ["libcore_java_defaults"], + srcs: [ + ":openjdk_generated_annotation_stub_files", ], + hostdex: true, + sdk_version: "none", + system_modules: "core-all-system-modules", + patch_module: "java.base", + notice: "ojluni/NOTICE", + installable: false, + include_srcs: true, } // Builds libcore test rules java_library_static { name: "core-test-rules", + visibility: [ + "//art/build/sdk", + "//external/conscrypt", + "//external/conscrypt/apex/tests", + "//frameworks/base/location/tests/locationtests", + "//frameworks/base/core/tests/coretests", + "//frameworks/base/wifi/tests", + "//cts/tests/tests/util", + ], hostdex: true, srcs: [ "dalvik/test-rules/src/main/**/*.java", @@ -397,18 +467,53 @@ java_library_static { ], static_libs: ["junit"], - no_standard_libs: true, - libs: ["core-all"], + sdk_version: "none", system_modules: "core-all-system-modules", } +// Builds platform_compat test rules +java_library_static { + name: "core-compat-test-rules", + visibility: [ + "//art/build/sdk", + "//frameworks/base/tests/PlatformCompatGating/test-rules", + ], + srcs: [ + "luni/src/main/java/android/compat/**/*.java", + "test-rules/src/platform_compat/**/*.java", + "luni/src/main/java/libcore/api/CorePlatformApi.java", + "luni/src/main/java/libcore/api/IntraCoreApi.java", + ], + static_libs: [ + "junit", + "guava", + ], + sdk_version: "none", + system_modules: "core-all-system-modules", + // This builds classes that are in the java.base Java module: + patch_module: "java.base", + hostdex: true, +} + // Builds the core-tests-support library used by various tests. java_library_static { name: "core-tests-support", + visibility: [ + "//art/build/sdk", + "//cts/apps/CtsVerifier", + "//cts/tests/tests/keystore", + "//cts/tests/tests/net", + "//cts/tests/tests/net/api23Test", + "//external/apache-harmony", + "//frameworks/base/core/tests/coretests", + "//libcore/benchmarks", + "//packages/apps/KeyChain/tests", + "//system/timezone/distro/core", + ], hostdex: true, srcs: ["support/src/test/java/**/*.java"], - no_framework_libs: true, + sdk_version: "core_platform", libs: ["junit"], static_libs: [ "bouncycastle-unbundled", @@ -420,44 +525,39 @@ java_library_static { // Builds the jsr166-tests library. java_test { name: "jsr166-tests", + visibility: [ + "//cts/tests/libcore/jsr166", + ], srcs: ["jsr166-tests/src/test/java/**/*.java"], - no_standard_libs: true, + sdk_version: "none", + system_modules: "core-all-system-modules", libs: [ - "core-all", "junit", ], - system_modules: "core-all-system-modules", } -// Builds a library just containing files from luni/src/test/filesystems -// for use in tests. -java_library { - name: "filesystemstest", - compile_dex: true, - srcs: ["luni/src/test/filesystems/src/**/*.java"], - java_resource_dirs: ["luni/src/test/filesystems/resources"], - no_framework_libs: true, - errorprone: { - javacflags: ["-Xep:MissingOverride:OFF"], - }, +// A filegroup that provides access to a source file for a toolchain test that +// checks Java 9 language features are handled properly by JarJar. +filegroup { + name: "core-java-9-language-features-source", + srcs: ["luni/src/main/java/libcore/internal/Java9LanguageFeatures.java"], + visibility: ["//libcore/luni/src/test/java9language"], } -// Builds a library just containing files from luni/src/test/parameter_metadata -// for use in tests. -java_library { - name: "parameter-metadata-test", - compile_dex: true, - srcs: ["luni/src/test/parameter_metadata/src/**/*.java"], - no_framework_libs: true, - javacflags: ["-parameters"], - errorprone: { - javacflags: ["-Xep:MissingOverride:OFF"], - }, +genrule { + name: "core-tests-smali-dex", + srcs: ["luni/src/test/java/**/*.smali"], + cmd: "$(location smali) ass --api 28 -o $(out) $(in)", + out: ["core-tests-smali.dex"], + tools: ["smali"], } // Builds the core-tests library. java_test { name: "core-tests", + visibility: [ + "//cts/tests/libcore/luni", + ], defaults: ["libcore_java_defaults"], hostdex: true, srcs: [ @@ -471,8 +571,12 @@ java_test { "xml/src/test/java/**/*.java", ], exclude_srcs: [ + "harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/*.java", "luni/src/test/java/libcore/java/util/zip/Zip64Test.java", "luni/src/test/java/libcore/java/util/zip/Zip64FileTest.java", + "luni/src/test/java/libcore/javax/crypto/**/*.java", + "luni/src/test/java/libcore/javax/net/ssl/**/*.java", + "luni/src/test/java/org/apache/harmony/crypto/**/*.java", ], java_resource_dirs: [ @@ -485,23 +589,26 @@ java_test { ], java_resources: [ + ":annotations-test", ":filesystemstest", ":parameter-metadata-test", + ":core-tests-smali-dex", ], - no_standard_libs: true, + sdk_version: "none", + system_modules: "core-all-system-modules", libs: [ - "core-all", "okhttp", "bouncycastle", ], - system_modules: "core-all-system-modules", static_libs: [ - "archive-patcher", + "core-compat-test-rules", + "core-java-9-language-tests", "core-test-rules", "core-tests-support", "junit-params", + "libcore-crypto-tests", "mockftpserver", "mockito-target", "mockwebserver", @@ -509,7 +616,7 @@ java_test { "slf4j-jdk14", "sqlite-jdbc", "tzdata-testing", - "truth-prebuilt", + "truth-prebuilt-jar", ], errorprone: { @@ -522,6 +629,40 @@ java_test { test_config: "AndroidTest-core-tests.xml", } +java_test { + name: "libcore-crypto-tests", + + visibility: [ + "//art/build/sdk", + "//external/conscrypt/apex/tests", + ], + srcs: [ + "harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/*.java", + "luni/src/test/java/libcore/javax/crypto/**/*.java", + "luni/src/test/java/libcore/javax/net/ssl/**/*.java", + "luni/src/test/java/org/apache/harmony/crypto/**/*.java", + ], + exclude_srcs: [ + "luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/SealedObjectTest.java", + ], + + java_resource_dirs: [ + "luni/src/test/java", + "luni/src/test/resources", + "support/src/test/java", + ], + + sdk_version: "none", + system_modules: "core-all-system-modules", + + static_libs: [ + "core-test-rules", + "core-tests-support", + "junit-params", + "mockito-target", + ], +} + // Builds the core-ojtests library that contains test code from OpenJDK. java_test { name: "core-ojtests", @@ -536,13 +677,12 @@ java_test { "ojluni/src/test/resources", ], - no_standard_libs: true, + sdk_version: "none", + system_modules: "core-all-system-modules", libs: [ - "core-all", "okhttp", "bouncycastle", ], - system_modules: "core-all-system-modules", static_libs: ["testng"], @@ -552,7 +692,7 @@ java_test { // code if it's declared to also be in java.base at // compile time. // - // For now, we use --patch-module to put all sources + // For now, we use patch_module to put all sources // and dependencies from this make target into java.base; // other source directories in this make target are in // packages not from java.base; if this becomes a problem @@ -567,6 +707,9 @@ java_test { // Like core-ojtests but smaller. java_test { name: "core-ojtests-public", + visibility: [ + "//cts/tests/libcore/ojluni", + ], defaults: ["libcore_java_defaults"], srcs: [ "ojluni/src/test/java/**/*.java", @@ -588,14 +731,13 @@ java_test { "ojluni/src/test/dist", ], - no_standard_libs: true, + sdk_version: "none", + system_modules: "core-all-system-modules", libs: [ - "core-all", "bouncycastle", "okhttp", "testng", ], - system_modules: "core-all-system-modules", } // Exports annotated stubs source files in ojluni/annotations/sdk to make them @@ -604,16 +746,21 @@ droiddoc_exported_dir { name: "ojluni-annotated-sdk-stubs", path: "ojluni/annotations/sdk", } + droiddoc_exported_dir { name: "ojluni-annotated-nullability-stubs", path: "ojluni/annotations/sdk/nullability", } // Exports annotated stubs source files in ojluni/annotations/mmodules to make -// them available to metalava. Used for core platform API and intra-code API +// them available to metalava. Used for core platform API and intra-core API // annotations in OpenJDK source. droiddoc_exported_dir { name: "ojluni-annotated-mmodule-stubs", + visibility: [ + "//libcore/mmodules/core_platform_api", + "//libcore/mmodules/intracoreapi", + ], path: "ojluni/annotations/mmodule", } @@ -621,42 +768,178 @@ droiddoc_exported_dir { // source code and so should not cause an error or warning. filegroup { name: "known-oj-tags", + visibility: [ + "//frameworks/base", + ], srcs: [ "known_oj_tags.txt", ], } -// Generates stubs for the parts of the public SDK API provided by the core -// library. +// A special set of stubs containing the minimal set of self consistent +// classes for which a system module can be created. Every system module must +// contain the java.lang classes so the set was constructed by starting with +// the java.lang classes and then adding their transitive dependencies without +// splitting packages. So, if one class from a package is used then all classes +// in that package were added to the set. // -// Only for use by core.current.stubs target below. +// Needed for java-current-stubs-system-modules. droidstubs { - name: "core-current-stubs-gen", - srcs: [":core_api_files"], + name: "java-current-stubs-source", + srcs: [ + ":core_oj_api_files", + ":core_libart_api_files", + ], java_version: "1.9", installable: false, - no_framework_libs: true, - args: " --exclude-annotations " - + "--hide-annotation libcore.api.Hide", - merge_inclusion_annotations_dirs: ["ojluni-annotated-mmodule-stubs"], + sdk_version: "none", + system_modules: "none", + + args: "--stub-packages java.*:javax.*:org.w3c.dom.*:org.xml.sax.*", } -// A stubs target containing the parts of the public SDK API provided by the -// core library. -// -// Don't use this directly, use "sdk_version: core_current". java_library { - name: "core.current.stubs", - srcs: [":core-current-stubs-gen"], + name: "java.current.stubs", + srcs: [":java-current-stubs-source"], errorprone: { javacflags: [ "-Xep:MissingOverride:OFF", ], }, - openjdk9: { - javacflags: ["--patch-module=java.base=."], + patch_module: "java.base", + sdk_version: "none", + system_modules: "none", +} + +// A special set of system modules needed to build art.module.public.api.stubs +// that contain nullability annotations when targeting java language level 1.9 +// and above. +java_system_modules { + name: "java-current-stubs-system-modules", + libs: [ + // Minimal set of classes required for a system module. + "java.current.stubs", + + // The nullability annotations used by the generated stubs. + "stub-annotations", + ], +} + +// http://b/129765390 Rewrite links to "platform" or "technotes" folders +// which are siblings (and thus outside of) {@docRoot}. +// +// We have to escape \ as \\ and $ as $$ here because they get resolved by +// different layers of the build tooling. The arguments are wrapped in '' so +// that the shell doesn't add yet another level of escaping. +rewrite_openjdk_doc_args = "--replace-documentation " + + // packages whose descendants to apply replacement to (all packages from + // libcore/ojluni/src/main/java that contribute to documentation). + "com.sun:java:javax:jdk.net:sun " + + // regex of the string to replace + "'(<a\\s+href\\s?=[\\*\\s]*\")(?:(?:\\{@docRoot\\}/\\.\\./)|(?:(?:\\.\\./)+))((?:platform|technotes).+)\">' " + + // replacement (with $1, $2 backreferences to the regex groups) + "'$$1https://docs.oracle.com/javase/8/docs/$$2\">' " + +// Generates stubs for the parts of the public SDK API provided by the ART module. +// +// Only for use by art.module.public.api.stubs target below and the building of the +// public API. +droidstubs { + name: "art-module-public-api-stubs-source", + visibility: [ + "//frameworks/base", + ], + srcs: [ + ":core_oj_api_files", + ":core_libart_api_files", + ], + java_version: "1.9", + installable: false, + sdk_version: "none", + system_modules: "java-current-stubs-system-modules", + libs: [ + // Provide access to I18N constants that are used to initialize + // constants in the public API. i.e. to allow the value of the + // java.text.CollectionElementIterator.NULLORDER to be initialized from + // android.icu.text.CollationElementIterator.NULLORDER. + "i18n.module.intra.core.api.stubs", + ], + + args: rewrite_openjdk_doc_args, + + create_doc_stubs: true, + + // Emit nullability annotations from the source to the stub files. + annotations_enabled: true, + + merge_annotations_dirs: [ + "ojluni-annotated-sdk-stubs", + ], +} + +// A stubs target containing the parts of the public SDK API provided by the ART module. +java_library { + name: "art.module.public.api.stubs", + srcs: [":art-module-public-api-stubs-source"], + errorprone: { + javacflags: [ + "-Xep:MissingOverride:OFF", + ], }, - no_standard_libs: true, + patch_module: "java.base", + sdk_version: "none", + system_modules: "java-current-stubs-system-modules", +} + +// Used when compiling higher-level code against art.module.public.api.stubs. +// +// This is only intended for use within core libraries and must not be used +// from outside. +java_system_modules { + name: "art-module-public-api-stubs-system-modules", + visibility: [ + "//art/build/sdk", + "//external/conscrypt", + "//external/icu/android_icu4j", + "//external/wycheproof", + ], + libs: [ + "art.module.public.api.stubs", + // This one is not on device but it's needed when javac compiles code + // containing lambdas. + "core-lambda-stubs-for-system-modules", + // This one is not on device but it's needed when javac compiles code + // containing @Generated annotations produced by some code generation + // tools. + // See http://b/123891440. + "core-generated-annotation-stubs", + + // Ensure that core libraries that depend on the public API can access + // the UnsupportedAppUsage, CorePlatformApi and IntraCoreApi + // annotations. + "art.module.api.annotations.for.system.modules", + + // Make nullability annotations available when compiling public stubs. + // They are provided as a separate library because while the + // annotations are not themselves part of the public API provided by + // this module they are used in the stubs. + "stub-annotations", + ], +} + +// A stubs target containing the parts of the public SDK API provided by the +// core library. +// +// Don't use this directly, use "sdk_version: core_current". +java_library { + name: "core.current.stubs", + visibility: ["//visibility:public"], + static_libs: [ + "art.module.public.api.stubs", + "conscrypt.module.public.api.stubs", + "i18n.module.public.api.stubs", + ], + sdk_version: "none", system_modules: "none", dist: { @@ -667,24 +950,60 @@ java_library { }, } +// Distributed with the SDK for turning into system modules to compile apps +// against. +java_library { + name: "core-current-stubs-for-system-modules", + visibility: ["//development/sdk"], + static_libs: [ + "core.current.stubs", + // This one is not on device but it's needed when javac compiles code + // containing lambdas. + "core-lambda-stubs-for-system-modules", + // This one is not on device but it's needed when javac compiles code + // containing @Generated annotations produced by some code generation + // tools. + // See http://b/123891440. + "core-generated-annotation-stubs", + ], + sdk_version: "none", + system_modules: "none", + dist: { + dest: "core-for-system-modules.jar", + targets: [ + "sdk", + "win_sdk", + ], + }, +} + +// Used when compiling higher-level code against core.current.stubs. +java_system_modules { + name: "core-current-stubs-system-modules", + visibility: ["//visibility:public"], + libs: [ + "core-current-stubs-for-system-modules", + ], +} + // Target for validating nullability annotations for correctness and // completeness. To check that there are no nullability errors: -// make core-current-stubs-nullability-validation +// m art-module-public-api-stubs-nullability-validation // To check that there are only the expected nullability warnings: -// make core-current-stubs-nullability-validation-check-nullability-warnings -// To update the the list of known expected nullability warnings: -// make core-current-stubs-nullability-validation-update-nullability-warnings +// m art-module-public-api-stubs-nullability-validation-check-nullability-warnings +// (If that check fails, it will provide instructions on how to proceed, +// including the command to run to update the expected warnings file.) droidstubs { - name: "core-current-stubs-nullability-validation", - srcs: [":core_api_files"], + name: "art-module-public-api-stubs-nullability-validation", + srcs: [":art_module_api_files"], installable: false, - no_framework_libs: true, + sdk_version: "none", + system_modules: "none", annotations_enabled: true, args: "--hide-annotation libcore.api.Hide " + "--validate-nullability-from-merged-stubs ", merge_inclusion_annotations_dirs: ["ojluni-annotated-mmodule-stubs"], merge_annotations_dirs: [ - "metalava-manual", // N.B. Stubs in this filegroup will be validated: "ojluni-annotated-nullability-stubs", ], @@ -700,5 +1019,50 @@ droidstubs { // time zone data. java_library_host { name: "timezone-host", + visibility: [ + "//art/build/sdk", + "//system/timezone/distro/core", + ], srcs: [":timezone_host_files"], } + +// A special set of system modules for building the following library for use +// in the art-module-public-api-system-modules. +java_system_modules { + name: "api-annotations-system-modules", + libs: [ + "art.module.public.api.stubs", + ], +} + +// A library that contains annotations that define API surfaces (core +// platform, intra core and the hidden API) along with some supporting +// constants. The annotations are source only and do not introduce any runtime +// dependencies. Specially built for use in system modules definitions to +// avoid introducing compile time cycles. +java_library { + name: "art.module.api.annotations.for.system.modules", + srcs: [ + ":api_surface_annotation_files", + ], + + installable: false, + sdk_version: "none", + system_modules: "api-annotations-system-modules", + patch_module: "java.base", +} + +// Create a library containing the api surface annotations, built against +// core_current for use by the annotation processor in frameworks/base. +java_library { + name: "art.module.api.annotations", + visibility: [ + "//frameworks/base", + ], + host_supported: true, + srcs: [ + ":api_surface_annotation_files", + ], + java_version: "1.9", + sdk_version: "core_current", +} diff --git a/NativeCode.bp b/NativeCode.bp index 38f57b364f..9619420c20 100644 --- a/NativeCode.bp +++ b/NativeCode.bp @@ -47,6 +47,13 @@ cc_defaults { cc_library_shared { name: "libjavacore", + visibility: [ + "//art/build/apex", + ], + apex_available: [ + "com.android.art.release", + "com.android.art.debug", + ], defaults: [ "core_native_default_flags", "core_native_default_libs", @@ -66,6 +73,7 @@ cc_library_shared { "libz", ], static_libs: [ + "libandroidicuinit", "libziparchive", ], target: { @@ -82,6 +90,18 @@ cc_library_shared { cc_library_shared { name: "libandroidio", + visibility: [ + "//art/build/apex", + "//external/conscrypt", + ], + apex_available: [ + "com.android.art.release", + "com.android.art.debug", + // TODO(b/147813447) remove this. This is currently due to the 'runtime_libs' + // dependency from libjavacrypto in the conscrypt APEX. + "com.android.conscrypt", + "test_com.android.conscrypt", + ], defaults: [ "core_native_default_flags", ], @@ -104,8 +124,8 @@ cc_defaults { "core_native_default_libs", ], srcs: [":libopenjdk_native_srcs"], - include_dirs: [ - "libcore/luni/src/main/native", + local_include_dirs: [ + "luni/src/main/native", ], cflags: [ // TODO(narayan): Prune down this list of exclusions once the underlying @@ -154,6 +174,13 @@ cc_defaults { cc_library_shared { name: "libopenjdk", + visibility: [ + "//art/build/apex", + ], + apex_available: [ + "com.android.art.release", + "com.android.art.debug", + ], defaults: ["libopenjdk_native_defaults"], shared_libs: [ "libopenjdkjvm", @@ -163,6 +190,12 @@ cc_library_shared { // Debug version of libopenjdk. Depends on libopenjdkjvmd. cc_library_shared { name: "libopenjdkd", + visibility: [ + "//art/build/apex", + ], + apex_available: [ + "com.android.art.debug", + ], defaults: ["libopenjdk_native_defaults"], shared_libs: [ "libopenjdkjvmd", @@ -172,6 +205,10 @@ cc_library_shared { // Test JNI library. cc_library_shared { name: "libjavacoretests", + visibility: [ + "//art/build/sdk", + "//cts/tests/libcore/luni", + ], defaults: ["core_native_default_flags"], host_supported: true, @@ -219,8 +256,3 @@ cc_benchmark { shared_libs: ["libnativehelper"], } - -subdirs = [ - "luni/src/main/native", - "ojluni/src/main/native", -] @@ -1,9 +1,11 @@ +# Bug component: 24949 + # Use this reviewer by default. android-libcore-team+review@google.com # People who can approve changes for submission; don't send review emails to them # unless you know what you're doing. -flooey@google.com +dauletz@google.com narayan@google.com nfuller@google.com nikitai@google.com diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 3a75225b6e..d5d57d7a26 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -8,3 +8,6 @@ checkstyle-luni-json-xml = java -jar ${REPO_ROOT}/prebuilts/checkstyle/checkstyl # Ensure there are no Apache-licensed files under: # * ojluni/src/main/java checkstyle-ojluni = java -jar ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.jar -c tools/checkstyle/checkstyle-forbid-apache.xml ojluni/src/main/java + +[Builtin Hooks] +bpfmt = true diff --git a/apex/Android.bp b/apex/Android.bp new file mode 100644 index 0000000000..51a7335f34 --- /dev/null +++ b/apex/Android.bp @@ -0,0 +1,45 @@ +// +// 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. + +// i18n APEX is intended as a home for ICU as of July 2019. +// Various parts and dependencies of ICU would be gradually moved into this APEX, +// and the below build rules should reflect the latest status. +// TODO(b/138434658): Move the apex declaration back to external/icu +// The apex is declared in libcore/ to workaround new dependency from external/icu +// to system/sepolicy in a downstream branch. +apex { + name: "com.android.i18n", + defaults: ["com.android.i18n-defaults"], + certificate: ":com.android.i18n.certificate", +} + +apex_defaults { + name: "com.android.i18n-defaults", + compile_multilib: "both", + manifest: "manifest.json", + prebuilts: ["apex_icu.dat"], + key: "com.android.i18n.key", +} + +apex_key { + name: "com.android.i18n.key", + public_key: "com.android.i18n.avbpubkey", + private_key: "com.android.i18n.pem", +} + +android_app_certificate { + name: "com.android.i18n.certificate", + certificate: "com.android.i18n", +} diff --git a/apex/com.android.i18n.avbpubkey b/apex/com.android.i18n.avbpubkey Binary files differnew file mode 100644 index 0000000000..f1c97a0898 --- /dev/null +++ b/apex/com.android.i18n.avbpubkey diff --git a/apex/com.android.i18n.pem b/apex/com.android.i18n.pem new file mode 100644 index 0000000000..7676453e99 --- /dev/null +++ b/apex/com.android.i18n.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKwIBAAKCAgEA89VXuQrlqB0L731Es2ud65k5XkyGn0FjQfynPYRPz3nkpNaF +3LbJ6JXIGKUQMY2pVQFNl2wUtylTJohNv8SWu/hPBMOmHu2zGvvfErKN7QD25y12 +D9jws3VlPhCWQsEZSjloYKI1MvMPcvtLgHoSuMl6JlT8mngC+uR8WLGtDKZYGICf +I2rhQ5ugzDp00tGJJV9HKAXHx7zA9X+29HbMte57ibOrO4Xs7zLankV3rVEc0ZcD +phA1RYh6lg9KYfsq/zbEbCRGPLTlqKa3zDPrnXTKInR//5fW7tWgqqRyXGumM8pA +B1Huba878WnMwcWWYLjxRMQ6hOOCnGY7167JoAnX+NRmUZWXrrSiaCr6o61ingb6 +6BvQTN0f1q2lXIf1bOPRkeNkxBB7q3YFa4XaF9ZpQs7V4vlrvE/uLWDmhTQ6snML +zWYbD+/nQ6u5BIdh+1rNk5RWp53IoNTGyJQnTpSkA2u+rtDuyKG4av6Vx2cPJ5Mu +8vAALAyEOqlZr0CeJR0h3m6XVt0PpDxNUvQU53tlzIKD2BuELWeRSJ79DkYf+Soh +vc0upDbdsy1r4C/Df5UpKnOKCmrYmJ1tdiigVeDH3y0B0ilD2dUqubqlc5Tw0a13 +PkpWPdJV7QpTyb3GDWa4DRpYRxCGDylCsS2rsXbsiMGqJFL3G0w06ahTmFUCAwEA +AQKCAgEA4nVbQsXHI8rOYgADBWxGwCCPsm/6fABbslZ38N9ozHYWD64ZpzKw9W3e +6FytXIiIIyXRrXe5CZ+81UW0iA2KPUvR/8fCCmmTddVFifUBcYP6zBxh0TgX3WSD +wg/frmHvHguRUGZ2aDpsN8sChXFa3/pnkyBNdx1NDz2T60AhS2VW3nLe2iMS0hrB +Tcxg4cevy2DhEl/D+1LoF1olTojjeXjjjbGrr92jf0jI2EQGcZaq4FGUFvBouYqW +57WNzNBcT6nK5fEOtqT/wxIMFACIrLViYnu2wWiBO1J3JOUUPZfRRbpqmyHSAlbE +omMzwyfCkVRS6B4jh3ZRwPYGUDvKjyNLeXXEr7Q6sAiwhvgz8Z5DIyzZr9SkExuQ +5jfjfYCNsFaA/QmA34hV5KsPLfLFbW3hvDc6ApOn3yvOkIP3Cb2JM/mfyHh7cRpz +y/UTep2e3uNj7fDkdrqp2oj/EOSKa0KSJCpqkgUwEFFCEvxeYeUgwlM+axSZNXEx +ocRgQpui/2tVH8rgny3ayYDknleVaWtzxg7QLH7vV90ztjh4XjmZgl4R6N6vO1IT +G2XN05vySoE+8ZdQVz3Ko3w3NLon4gwyXv8K+PmHBUsIoY37OPpZoj24n/Uajcuh +crr5zSGlXhC+OzNk1tJ1NosHF70b/sYwdSIRpxEzA7QggSi6iAUCggEBAP5yHpkr +BZB/C95zT4xd8ugYAw/5rFQXgwYkf1CYUp/lEXBUJGnimIwo5Gr9tGAAxTwXTTJH +TI25EhAFu/WEh4h31SkL2b3S6jqupCqYwZdrl5TAY/35FBpGZN+ZirTHPP6ZobxX +8zhHTl+7mKN/neA6sbLwH4WDZa+LUHScTnVSjzyL2PorPdsolFjOLILQE6LZjinB +5bX972wjK4Q72gfdkia/Csq8Wo2/k53A2ur0fFojRHHI1M9Fthe6OI4RX/RwyHih +R9S68xrz2bcYQ8XpoaaNpLY/FXev8WcBicjApN+eQQCK2ZGA9+UxgQRld317Wvqf +zAyKp5idtRJUbb8CggEBAPVSoNyrghZFfaWGDe3pCnKkeZhqNsLbI5YrQohX6Quy +BhRCP5t5wyNuMQX5rRZqeb3VgbW/06faVwZZ+bwA0KT7RYy0zgJhfD6bZ7WmzQMc +HmAVqvN8iZIIjpMeN/174yYdqq0ShUYmra151ReL/CWs32kBWNKT6l487J7DAoYR +ZHtec9nbs2ZFqea+PNAP8VAcsmsemwXe1w63RxDgdZccJmMj0TWmBj47RstMWTLE +CrCGfXW9qmvs/Itzbuy589DS0AXZfTW+U0TD4RnCcjV7JDyEZASA3V7lMiyKXDTJ +6+CUcgzOWzdTfAeVcG0olXXNCdCePX8uiqkwSCaXpusCggEBAI4tHkPf8kAHfY5T +SIPaizx9DlkC3fQvHxtzkWBrfN+zk8b8fUxdPXgz8U6HbR6nz44ARzZs+K3IV/tz ++M77uu/aZdWFtamIDTG1HC5hJOuDRzPrPPRRFZaI9xyqIwNYwRBSsDkZu+IalgSQ +Qn45dPIyWdDus+5auZsZcV93Z6/O7hKa4icHuoyXZC0rJ1wBALficLmMitrihcIa +9Nnyx6XVfTEBVvppvP+vqMBhXvIiosmLI1ehLKiU/2bKu4dG1iM0UhB1rjmELQtG +bsUMXfJc1eLHCt566XfzbCRui5sNahM5zoCLFX9kXSBIRRs7x0TqhK++Uro/T97L +YL5ZRukCggEBAOaEpB93EZ/34F7/HmumBWlAX/n2JErpPAFJ2RTg9l1FBS1YKwjf +W5wZWPtyZ1Ce8JKO43lzLWGWaxvOxDoC0guVCP90jffyvprd0JACkrYPYAONmLt/ +FI4ieEaJqLcKCKGyUsSamJ0Yjy5pQvEDWwXT8YJr/5iv4RR4TyfHusFb6n16fYYD +SgoZ/9KQg/hGYsySipzZf3X+tTpgweh74kMB8phJ+bZdsZQcgyNZNJ/dUuYZGh7f +ABq174DiESNkgFSDI3G7skoj8360SPq5mjPi6GPtS0ZoCJu45nKv+ICqFHlNQ/YA +mfnc+rjtlV0dO4QcDNL5PnQZubXNZp7M9c0CggEBAIrfxdeELSqeVld3nhHFty0b +ZdmFJWRj6k9zjoOYe8LPkAiue0Zm10sCiLFiRgTH6msnfBloYJ2iiDgSSnIlUvaH +HFxoLWtv2az2B3g6gfJ5KbdE8mqfz0hGMOUBPFBarC4HrPslR28Cwn8mD5CvN4a/ +oAz3kOlaGokVF6Ikwd606JBFTVKSwr2niTJUwGXgn85tViCWqUm4v24BntbZZ9Rs +k6ffBUl/k02zw/U405I3qTjCAnetNY3wHmjvdqkCcoWTAmG04IfGlqVE3NMjjLQD +h9Xx2Nr5SV6djWbmYfT0Ox4Ha/IPuCCAZbBv6Or2wQSOQwb5fUgFcu3NrXU1rQQ= +-----END RSA PRIVATE KEY----- diff --git a/apex/com.android.i18n.pk8 b/apex/com.android.i18n.pk8 Binary files differnew file mode 100644 index 0000000000..100ed14456 --- /dev/null +++ b/apex/com.android.i18n.pk8 diff --git a/apex/com.android.i18n.x509.pem b/apex/com.android.i18n.x509.pem new file mode 100644 index 0000000000..fcf1a53d13 --- /dev/null +++ b/apex/com.android.i18n.x509.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFUTCCAzmgAwIBAgIUHufr9X4LD87MyuJ/8AaMvsIhXjUwDQYJKoZIhvcNAQEL +BQAwNzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmcm9uaWExEzARBgNVBAoM +Ckdvb2dsZSBMTEMwIBcNMTkwNzA1MTU0ODM2WhgPNDc1NzA1MzExNTQ4MzZaMDcx +CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZnJvbmlhMRMwEQYDVQQKDApHb29n +bGUgTExDMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsUMFBc1QNyhj +gU47F2O3kUrZhATA6Gz644sXvrqUg03retG3jsIEFmBXgbXngvF2yq9sRiGm4D5j +9Sf5fguDqy9C/Q8MiUEAqQo1ygy9MubMfdGVLb2dcFoKXwyig8KzSS03+73IiUnF +iCy5GzPO6ltga4nsbXUE6egexE3WGLQ0Lu7gCLNZn1Zd20p4BlTUl64CEu9zt6NN +D6okd7IGceipBbpK9WDMW6ygXJ5sTJohZYSrSOPkoQFVilWFd5VryBxboTmxhSyo +4dvNavnNCKOhsCCi8QIHOlXMDWxN970giv60FzoXoD2QwD5o+3I6SIIutEnGmh/d +SECcK9yK+YECqw2XhvoBR4NH4RltaWKZsy62YPSYZXJXZ4H1P+9L9Q5dwLlI2Itt +IWtYY88T8P2w8e2KzYewkE/XM4kRUw8pNWod1Hok2WuvZxdbPJ0+Hhvo1FVTwV1K +kdtUuVPut6fpA2hEfGmwdKpK18Qe5ZLBZ1r1lSrjlfct+BWelADaZRNNyJey0u/s +DgZGbiJG6tJqDESN229/eMTRt9gDncIx7S37RFgOv8jlUul5miKH3QP6neotofWw +EWEKFjaDNhqU83rdpk48Br/HTiXA6pvaGlN0RQyBVB7uavvTYKTp8cGU11hkIx8p +Vkp0EOCs9ajlt1+GyMCrPOk8A10rrOcCAwEAAaNTMFEwHQYDVR0OBBYEFMXzY0Gf +eAdY8RjzwPnOou8VgjD3MB8GA1UdIwQYMBaAFMXzY0GfeAdY8RjzwPnOou8VgjD3 +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBABrAExrvMkg26gQg +rUh170Ms8T5jvIpWyIb7fSLjsA0c2q+zZiIUViO1t2eNQtdExGcmEOBF1+LqAIbT +zA8nz9ZHweGZi01VodPaGKuz2VWWMzQaENW2RQGaxO9g8nCHGrbwchE7IbNOT1FD +jzVYWcCKydr4niJWjSy9ey8eNDv/Iqto64/nPI7PxtBVfH7G8hgamyVtwWhhciTH +nlg6X0EAxq5VwZSK4G8n+gsozPQHRjvBrSzt0A187vh/g6LQPLDZjPnzbZVtfFtM +pv+hImxyDN3DZYrna2aGxWBIXEFjH61xueBGWaCo8TwvR8NIHM/i4s/zyhUxGUYL +307i940cEF3rYJ/urzZzXJlxiu8p0Y12i/t+vXRqXM8d65QSMLqDDBHqZ3mPkcBp +U7hWVi5HuyWGQF4FMK8sdemJITJpg1xztybsvRJ9kDeWxPNQllC4dREaKVhI/3WM +eP7bpMmZxngoHbAB2f11lQf1A0fWFkng/Gntqnw0Dd6J+++NuuoFUjZLAWzUpoje +J6J9CuxBjng0n94ZN+E8E5zsAtaO9WvhSQwTvNbHZmERxvtSm6mIH1XEBTi5tOHZ +PBAAJuzZrFFZWevI44vgpCrF4lO3F9qE+sKn+2sARGuAjGCNV+jJCD+7tySjf7js +2uaWgWOl7EexciIHD9FbZ3ANsiRU +-----END CERTIFICATE----- diff --git a/apex/manifest.json b/apex/manifest.json new file mode 100644 index 0000000000..4d1b2b6e35 --- /dev/null +++ b/apex/manifest.json @@ -0,0 +1,4 @@ +{ + "name": "com.android.i18n", + "version": 1 +}
\ No newline at end of file diff --git a/benchmarks/Android.bp b/benchmarks/Android.bp new file mode 100644 index 0000000000..4f2f157b7d --- /dev/null +++ b/benchmarks/Android.bp @@ -0,0 +1,28 @@ +// 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. + +java_test { + name: "benchmarks", + srcs: ["src/**/*.java"], + static_libs: [ + "mockwebserver", + "core-tests-support", + ], + sdk_version: "none", + system_modules: "core-all-system-modules", + libs: [ + "caliper-api-target", + "android.test.base", + ], +} diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk deleted file mode 100644 index 623ba9c6fc..0000000000 --- a/benchmarks/Android.mk +++ /dev/null @@ -1,36 +0,0 @@ -# -*- mode: makefile -*- -# Copyright (C) 2013 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -LOCAL_PATH:= $(call my-dir) - -ifeq ($(LIBCORE_SKIP_TESTS),) - -################################################## -include $(CLEAR_VARS) -LOCAL_MODULE := benchmarks -LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_STATIC_JAVA_LIBRARIES := mockwebserver core-tests-support -LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_JAVA_LIBRARIES := \ - caliper-api-target \ - core-oj \ - core-libart \ - android.test.base -LOCAL_MODULE_TAGS := tests -LOCAL_MODULE_PATH := $(PRODUCT_OUT)/data/caliperperf -LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk -include $(BUILD_JAVA_LIBRARY) - -endif diff --git a/dalvik/src/main/java/dalvik/annotation/codegen/CovariantReturnType.java b/dalvik/src/main/java/dalvik/annotation/codegen/CovariantReturnType.java index f3028506ac..b43600d93a 100644 --- a/dalvik/src/main/java/dalvik/annotation/codegen/CovariantReturnType.java +++ b/dalvik/src/main/java/dalvik/annotation/codegen/CovariantReturnType.java @@ -21,6 +21,7 @@ import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import libcore.api.CorePlatformApi; /** * Indicates to the platform toolchain that there is an upcoming public SDK API change for a method. @@ -60,24 +61,29 @@ import java.lang.annotation.Target; @Repeatable(CovariantReturnType.CovariantReturnTypes.class) @Retention(RetentionPolicy.CLASS) @Target({ ElementType.METHOD}) +@CorePlatformApi public @interface CovariantReturnType { /** * The return type of the synthetic method to generate. Must be a subclass of the return type * of the method being annotated. */ + @CorePlatformApi Class<?> returnType(); /** * The last Android API level not to have the generated synthetic method. The annotation can be * removed and the actual return type updated when support for this API level is dropped. */ + @CorePlatformApi int presentAfter(); /** @hide */ @Retention(RetentionPolicy.CLASS) @Target({ElementType.METHOD}) + @CorePlatformApi @interface CovariantReturnTypes { + @CorePlatformApi CovariantReturnType[] value(); } } diff --git a/dalvik/src/main/java/dalvik/annotation/compat/UnsupportedAppUsage.java b/dalvik/src/main/java/dalvik/annotation/compat/UnsupportedAppUsage.java deleted file mode 100644 index 82b2f103e9..0000000000 --- a/dalvik/src/main/java/dalvik/annotation/compat/UnsupportedAppUsage.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dalvik.annotation.compat; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.CLASS; - -import dalvik.system.VersionCodes; -import java.lang.annotation.Repeatable; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import libcore.api.CorePlatformApi; -import libcore.api.IntraCoreApi; - -/** - * Indicates that a class member, that is not part of the SDK, is used by apps. - * Since the member is not part of the SDK, such use is not supported. - * - * <p>This annotation acts as a heads up that changing a given method or field - * may affect apps, potentially breaking them when the next Android version is - * released. In some cases, for members that are heavily used, this annotation - * may imply restrictions on changes to the member. - * - * <p>This annotation also results in access to the member being permitted by the - * runtime, with a warning being generated in debug builds. - * - * <p>For more details, see go/UnsupportedAppUsage. - * - * {@hide} - */ -@Retention(CLASS) -@Target({CONSTRUCTOR, METHOD, FIELD, TYPE}) -@Repeatable(UnsupportedAppUsage.Container.class) -@CorePlatformApi -@IntraCoreApi -public @interface UnsupportedAppUsage { - - /** - * Associates a bug tracking the work to add a public alternative to this API. Optional. - * - * @return ID of the associated tracking bug - */ - @CorePlatformApi - @IntraCoreApi - long trackingBug() default 0; - - /** - * Indicates that usage of this API is limited to apps based on their target SDK version. - * - * <p>Access to the API is allowed if the targetSdkVersion in the apps manifest is no greater - * than this value. Access checks are performed at runtime. - * - * <p>This is used to give app developers a grace period to migrate off a non-SDK interface. - * When making Android version N, existing APIs can have a maxTargetSdk of N-1 added to them. - * Developers must then migrate off the API when their app is updated in future, but it will - * continue working in the meantime. - * - * <p>Possible values are: - * <ul> - * <li> - * {@link VersionCodes#O} - in which case the API is available up to and including the - * O release and all intermediate releases between O and P. Or in other words the API - * is blacklisted (unavailable) from P onwards. - * </li> - * <li> - * {@link VersionCodes#P} - in which case the API is available up to and including the - * P release and all intermediate releases between P and Q. Or in other words the API - * is blacklisted (unavailable) from Q onwards. - * </li> - * <li> - * absent (default value) - All apps can access this API, but doing so may result in - * warnings in the log, UI warnings (on developer builds) and/or strictmode violations. - * The API is likely to be further restricted in future. - * </li> - * - * </ul> - * - * @return The maximum value for an apps targetSdkVersion in order to access this API. - */ - @CorePlatformApi - @IntraCoreApi - int maxTargetSdk() default Integer.MAX_VALUE; - - /** - * For debug use only. The expected dex signature to be generated for this API, used to verify - * parts of the build process. - * - * @return A dex API signature. - */ - @CorePlatformApi - @IntraCoreApi - String expectedSignature() default ""; - - /** - * The signature of an implicit (not present in the source) member that forms part of the - * hiddenapi. - * - * <p>Allows access to non-SDK API elements that are not represented in the input source to be - * managed. - * - * <p>This must only be used when applying the annotation to a type, using it in any other - * situation is an error. - * - * @return A dex API signature. - */ - @CorePlatformApi - @IntraCoreApi - String implicitMember() default ""; - - /** - * Container for {@link UnsupportedAppUsage} that allows it to be applied repeatedly to types. - */ - @Retention(CLASS) - @Target(TYPE) - @CorePlatformApi - @IntraCoreApi - @interface Container { - @CorePlatformApi - @IntraCoreApi - UnsupportedAppUsage[] value(); - } -} diff --git a/dalvik/src/main/java/dalvik/system/VersionCodes.java b/dalvik/src/main/java/dalvik/annotation/compat/VersionCodes.java index 670db0f9c6..8f7bcd2f89 100644 --- a/dalvik/src/main/java/dalvik/system/VersionCodes.java +++ b/dalvik/src/main/java/dalvik/annotation/compat/VersionCodes.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package dalvik.system; +package dalvik.annotation.compat; import libcore.api.CorePlatformApi; import libcore.api.IntraCoreApi; @@ -50,4 +50,11 @@ public class VersionCodes { @CorePlatformApi @IntraCoreApi public static final int P = 28; + + /** + * The version code for Android Q (API version 29). + */ + @CorePlatformApi + @IntraCoreApi + public static final int Q = 29; } diff --git a/dalvik/src/main/java/dalvik/annotation/optimization/FastNative.java b/dalvik/src/main/java/dalvik/annotation/optimization/FastNative.java index a5c0dc5ea9..f25233c9a0 100644 --- a/dalvik/src/main/java/dalvik/annotation/optimization/FastNative.java +++ b/dalvik/src/main/java/dalvik/annotation/optimization/FastNative.java @@ -57,6 +57,16 @@ import java.lang.annotation.Target; * </p> * * <p> + * Note that even in FastNative methods you <b>are</b> allowed to + * allocate objects and make upcalls into Java code. A call from Java to + * a FastNative function and back to Java is equivalent to a call from one Java + * method to another. What's forbidden in a FastNative method is blocking + * the calling thread in some non-Java code and thereby preventing the thread + * from responding to requests from the garbage collector to enter the suspended + * state. + * </p> + * + * <p> * Has no effect when used with non-native methods. * </p> * diff --git a/dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java b/dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java index 4eea1a58e2..7b82c3cf9a 100644 --- a/dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java +++ b/dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java @@ -79,6 +79,7 @@ import java.lang.annotation.Target; * * @hide */ +@libcore.api.IntraCoreApi @Retention(RetentionPolicy.RUNTIME) // Let the GC or interpreter ask, if they need to. // TODO(b/72332040): Reconsider retention later. @Target({ElementType.FIELD, ElementType.METHOD}) diff --git a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java index 9cf5f80257..ee20d802a0 100644 --- a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java +++ b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java @@ -16,7 +16,7 @@ package dalvik.system; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.io.File; import java.io.IOException; import java.net.URL; @@ -24,8 +24,11 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Enumeration; +import java.util.HashMap; import java.util.List; +import java.util.Map; import sun.misc.CompoundEnumeration; /** @@ -125,40 +128,48 @@ public class BaseDexClassLoader extends ClassLoader { : Arrays.copyOf(sharedLibraryLoaders, sharedLibraryLoaders.length); this.pathList = new DexPathList(this, dexPath, librarySearchPath, null, isTrusted); - if (reporter != null) { - reportClassLoaderChain(); - } + reportClassLoaderChain(); } /** * Reports the current class loader chain to the registered {@code reporter}. + * + * @hide */ - private void reportClassLoaderChain() { - ArrayList<ClassLoader> classLoadersChain = new ArrayList<>(); - ArrayList<String> classPaths = new ArrayList<>(); - - classLoadersChain.add(this); - classPaths.add(String.join(File.pathSeparator, pathList.getDexPaths())); - - ClassLoader bootClassLoader = ClassLoader.getSystemClassLoader().getParent(); - ClassLoader current = getParent(); - - while (current != null && current != bootClassLoader) { - classLoadersChain.add(current); - if (current instanceof BaseDexClassLoader) { - BaseDexClassLoader bdcCurrent = (BaseDexClassLoader) current; - classPaths.add(String.join(File.pathSeparator, bdcCurrent.pathList.getDexPaths())); - } else { - // We can't determine the classpath for arbitrary class loaders. - classPaths.add(null); - } - current = current.getParent(); + @libcore.api.CorePlatformApi + public void reportClassLoaderChain() { + if (reporter == null) { + return; } - reporter.report(classLoadersChain, classPaths); + String[] classPathAndClassLoaderContexts = computeClassLoaderContextsNative(); + if (classPathAndClassLoaderContexts.length == 0) { + return; + } + Map<String, String> dexFileMapping = + new HashMap<>(classPathAndClassLoaderContexts.length / 2); + for (int i = 0; i < classPathAndClassLoaderContexts.length; i += 2) { + dexFileMapping.put(classPathAndClassLoaderContexts[i], + classPathAndClassLoaderContexts[i + 1]); + } + reporter.report(Collections.unmodifiableMap(dexFileMapping)); } /** + * Computes the classloader contexts for each classpath entry in {@code pathList.getDexPaths()}. + * + * Note that this method is not thread safe, i.e. it is the responsibility of the caller to + * ensure that {@code pathList.getDexPaths()} is not modified concurrently with this method + * being called. + * + * @return A non-null array of non-null strings of length + * {@code 2 * pathList.getDexPaths().size()}. Every even index (0 is even here) is a dex file + * path and every odd entry is the class loader context used to load the previously listed dex + * file. E.g. a result might be {@code { "foo.dex", "PCL[]", "bar.dex", "PCL[foo.dex]" } }. + */ + private native String[] computeClassLoaderContextsNative(); + + /** * Constructs an instance. * * dexFile must be an in-memory representation of a full dexFile. @@ -359,19 +370,16 @@ public class BaseDexClassLoader extends ClassLoader { @libcore.api.CorePlatformApi public interface Reporter { /** - * Reports the construction of a BaseDexClassLoader and provides information about the - * class loader chain. + * Reports the construction of a BaseDexClassLoader and provides opaque information about + * the class loader chain. For example, if the childmost ClassLoader in the chain: + * {@quote BaseDexClassLoader { foo.dex } -> BaseDexClassLoader { base.apk } + * -> BootClassLoader } was just initialized then the load of {@code "foo.dex"} would be + * reported with a classLoaderContext of {@code "PCL[];PCL[base.apk]"}. * - * @param classLoadersChain the chain of class loaders used during the construction of the - * class loader. The first element is the BaseDexClassLoader being constructed, - * the second element is its parent, and so on. - * @param classPaths the class paths of the class loaders present in - * {@param classLoadersChain}. The first element corresponds to the first class - * loader and so on. A classpath is represented as a list of dex files separated by - * {@code File.pathSeparator}. If the class loader is not a BaseDexClassLoader the - * classpath will be null. + * @param contextsMap A map from dex file paths to the class loader context used to load + * each dex file. */ @libcore.api.CorePlatformApi - void report(List<ClassLoader> classLoadersChain, List<String> classPaths); + void report(Map<String, String> contextsMap); } } diff --git a/dalvik/src/main/java/dalvik/system/BlockGuard.java b/dalvik/src/main/java/dalvik/system/BlockGuard.java index c608407dd5..192e450b67 100644 --- a/dalvik/src/main/java/dalvik/system/BlockGuard.java +++ b/dalvik/src/main/java/dalvik/system/BlockGuard.java @@ -16,10 +16,10 @@ package dalvik.system; -import libcore.util.NonNull; +import android.compat.annotation.UnsupportedAppUsage; -import dalvik.annotation.compat.UnsupportedAppUsage; import java.util.Objects; +import libcore.util.NonNull; /** * Interface that enables {@code StrictMode} to install callbacks to implement diff --git a/dalvik/src/main/java/dalvik/system/CloseGuard.java b/dalvik/src/main/java/dalvik/system/CloseGuard.java index 6fe94a94e3..99ddf3eda4 100644 --- a/dalvik/src/main/java/dalvik/system/CloseGuard.java +++ b/dalvik/src/main/java/dalvik/system/CloseGuard.java @@ -16,7 +16,7 @@ package dalvik.system; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * CloseGuard is a mechanism for flagging implicit finalizer cleanup of @@ -134,11 +134,14 @@ public final class CloseGuard { */ private static volatile Tracker currentTracker = null; // Disabled by default. + private static final String MESSAGE = "A resource was acquired at attached stack trace but never released. " + + "See java.io.Closeable for information on avoiding resource leaks."; + /** * Returns a CloseGuard instance. {@code #open(String)} can be used to set * up the instance to warn on failure to close. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(trackingBug=111170242) @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static CloseGuard get() { @@ -220,10 +223,25 @@ public final class CloseGuard { * @param closer non-null name of explicit termination method. Printed by warnIfOpen. * @throws NullPointerException if closer is null. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(trackingBug=111170242) @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public void open(String closer) { + openWithCallSite(closer, null /* callsite */); + } + + /** + * Like {@link #open(String)}, but with explicit callsite string being passed in for better + * performance. + * <p> + * This only has better performance than {@link #open(String)} if {@link #isEnabled()} returns {@code true}, which + * usually shouldn't happen on release builds. + * + * @param closer Non-null name of explicit termination method. Printed by warnIfOpen. + * @param callsite Non-null string uniquely identifying the callsite. + */ + @libcore.api.CorePlatformApi + public void openWithCallSite(String closer, String callsite) { // always perform the check for valid API usage... if (closer == null) { throw new NullPointerException("closer == null"); @@ -233,12 +251,18 @@ public final class CloseGuard { closerNameOrAllocationInfo = closer; return; } - String message = "Explicit termination method '" + closer + "' not called"; - Throwable stack = new Throwable(message); - closerNameOrAllocationInfo = stack; + // Always record stack trace when tracker installed, which only happens in tests. Otherwise, skip expensive + // stack trace creation when explicit callsite is passed in for better performance. Tracker tracker = currentTracker; - if (tracker != null) { - tracker.open(stack); + if (callsite == null || tracker != null) { + String message = "Explicit termination method '" + closer + "' not called"; + Throwable stack = new Throwable(message); + closerNameOrAllocationInfo = stack; + if (tracker != null) { + tracker.open(stack); + } + } else { + closerNameOrAllocationInfo = callsite; } } @@ -270,24 +294,23 @@ public final class CloseGuard { * the allocation to the current reporter. If it was not enabled, it just * directly logs a brief message. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(trackingBug=111170242) @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public void warnIfOpen() { if (closerNameOrAllocationInfo != null) { - if (closerNameOrAllocationInfo instanceof String) { + if (closerNameOrAllocationInfo instanceof Throwable) { + reporter.report(MESSAGE, (Throwable) closerNameOrAllocationInfo); + } else if (stackAndTrackingEnabled) { + reporter.report(MESSAGE + " Callsite: " + closerNameOrAllocationInfo); + } else { System.logW("A resource failed to call " + (String) closerNameOrAllocationInfo + ". "); - } else { - String message = - "A resource was acquired at attached stack trace but never released. "; - message += "See java.io.Closeable for information on avoiding resource leaks."; - Throwable stack = (Throwable) closerNameOrAllocationInfo; - reporter.report(message, stack); } } } + /** * Interface to allow customization of tracking behaviour. * @@ -308,6 +331,9 @@ public final class CloseGuard { @UnsupportedAppUsage @libcore.api.CorePlatformApi void report(String message, Throwable allocationSite); + + @libcore.api.CorePlatformApi + default void report(String message) {} } /** @@ -320,5 +346,10 @@ public final class CloseGuard { @Override public void report (String message, Throwable allocationSite) { System.logW(message, allocationSite); } + + @Override + public void report(String message) { + System.logW(message); + } } } diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java index 486ee90830..176fde4610 100644 --- a/dalvik/src/main/java/dalvik/system/DexFile.java +++ b/dalvik/src/main/java/dalvik/system/DexFile.java @@ -16,9 +16,9 @@ package dalvik.system; +import android.compat.annotation.UnsupportedAppUsage; import android.system.ErrnoException; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.annotation.optimization.ReachabilitySensitive; + import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -28,6 +28,8 @@ import java.util.Enumeration; import java.util.List; import libcore.io.Libcore; +import dalvik.annotation.optimization.ReachabilitySensitive; + /** * Loads DEX files. This class is meant for internal use and should not be used * by applications. diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/dalvik/src/main/java/dalvik/system/DexPathList.java index c63bb13477..798166c572 100644 --- a/dalvik/src/main/java/dalvik/system/DexPathList.java +++ b/dalvik/src/main/java/dalvik/system/DexPathList.java @@ -16,11 +16,13 @@ package dalvik.system; +import android.compat.annotation.UnsupportedAppUsage; import android.system.ErrnoException; import android.system.StructStat; -import dalvik.annotation.compat.UnsupportedAppUsage; + import java.io.File; import java.io.IOException; +import java.lang.reflect.Array; import java.net.MalformedURLException; import java.net.URL; import java.nio.ByteBuffer; @@ -219,32 +221,25 @@ public final class DexPathList { suppressedExceptionList, definingContext, isTrusted); if (newElements != null && newElements.length > 0) { - final Element[] oldElements = dexElements; - dexElements = new Element[oldElements.length + newElements.length]; - System.arraycopy( - oldElements, 0, dexElements, 0, oldElements.length); - System.arraycopy( - newElements, 0, dexElements, oldElements.length, newElements.length); + dexElements = concat(Element.class, dexElements, newElements); } if (suppressedExceptionList.size() > 0) { - final IOException[] newSuppressedExceptions = suppressedExceptionList.toArray( + final IOException[] newSuppExceptions = suppressedExceptionList.toArray( new IOException[suppressedExceptionList.size()]); - if (dexElementsSuppressedExceptions != null) { - final IOException[] oldSuppressedExceptions = dexElementsSuppressedExceptions; - final int suppressedExceptionsLength = oldSuppressedExceptions.length + - newSuppressedExceptions.length; - dexElementsSuppressedExceptions = new IOException[suppressedExceptionsLength]; - System.arraycopy(oldSuppressedExceptions, 0, dexElementsSuppressedExceptions, - 0, oldSuppressedExceptions.length); - System.arraycopy(newSuppressedExceptions, 0, dexElementsSuppressedExceptions, - oldSuppressedExceptions.length, newSuppressedExceptions.length); - } else { - dexElementsSuppressedExceptions = newSuppressedExceptions; - } + dexElementsSuppressedExceptions = dexElementsSuppressedExceptions != null + ? concat(IOException.class, dexElementsSuppressedExceptions, newSuppExceptions) + : newSuppExceptions; } } + private static<T> T[] concat(Class<T> componentType, T[] inputA, T[] inputB) { + T[] output = (T[]) Array.newInstance(componentType, inputA.length + inputB.length); + System.arraycopy(inputA, 0, output, 0, inputA.length); + System.arraycopy(inputB, 0, output, inputA.length, inputB.length); + return output; + } + /** * For InMemoryDexClassLoader. Initializes {@code dexElements} with dex files * loaded from {@code dexFiles} buffers. diff --git a/dalvik/src/main/java/dalvik/system/EmulatedStackFrame.java b/dalvik/src/main/java/dalvik/system/EmulatedStackFrame.java index b479d6fd88..7a1c20b64b 100644 --- a/dalvik/src/main/java/dalvik/system/EmulatedStackFrame.java +++ b/dalvik/src/main/java/dalvik/system/EmulatedStackFrame.java @@ -346,20 +346,29 @@ public class EmulatedStackFrame { return this; } - protected void checkType(Class<?> type) { + private Class<?> getCurrentArgumentType() { if (argumentIdx >= numArgs || argumentIdx == (RETURN_VALUE_IDX + 1)) { throw new IllegalArgumentException("Invalid argument index: " + argumentIdx); } - - final Class<?> expectedType = (argumentIdx == RETURN_VALUE_IDX) ? + return (argumentIdx == RETURN_VALUE_IDX) ? frame.type.rtype() : frame.type.ptypes()[argumentIdx]; + } - if (expectedType != type) { - throw new IllegalArgumentException("Incorrect type: " + type + - ", expected: " + expectedType); + private static void checkAssignable(Class<?> expectedType, Class<?> actualType) { + if (!expectedType.isAssignableFrom(actualType)) { + throw new IllegalArgumentException("Incorrect type: " + actualType + + ", expected: " + expectedType); } } + protected void checkWriteType(Class<?> type) { + checkAssignable(getCurrentArgumentType(), type); + } + + protected void checkReadType(Class<?> expectedType) { + checkAssignable(expectedType, getCurrentArgumentType()); + } + /** * Positions the cursor at the return value location, either in the references array * or in the stack frame array. The next put* or next* call will result in a read or @@ -408,55 +417,55 @@ public class EmulatedStackFrame { */ public static class StackFrameWriter extends StackFrameAccessor { public void putNextByte(byte value) { - checkType(byte.class); + checkWriteType(byte.class); argumentIdx++; frameBuf.putInt(value); } public void putNextInt(int value) { - checkType(int.class); + checkWriteType(int.class); argumentIdx++; frameBuf.putInt(value); } public void putNextLong(long value) { - checkType(long.class); + checkWriteType(long.class); argumentIdx++; frameBuf.putLong(value); } public void putNextChar(char value) { - checkType(char.class); + checkWriteType(char.class); argumentIdx++; frameBuf.putInt((int) value); } public void putNextBoolean(boolean value) { - checkType(boolean.class); + checkWriteType(boolean.class); argumentIdx++; frameBuf.putInt(value ? 1 : 0); } public void putNextShort(short value) { - checkType(short.class); + checkWriteType(short.class); argumentIdx++; frameBuf.putInt((int) value); } public void putNextFloat(float value) { - checkType(float.class); + checkWriteType(float.class); argumentIdx++; frameBuf.putFloat(value); } public void putNextDouble(double value) { - checkType(double.class); + checkWriteType(double.class); argumentIdx++; frameBuf.putDouble(value); } public void putNextReference(Object value, Class<?> expectedType) { - checkType(expectedType); + checkWriteType(expectedType); argumentIdx++; frame.references[referencesOffset++] = value; } @@ -468,55 +477,55 @@ public class EmulatedStackFrame { */ public static class StackFrameReader extends StackFrameAccessor { public byte nextByte() { - checkType(byte.class); + checkReadType(byte.class); argumentIdx++; return (byte) frameBuf.getInt(); } public int nextInt() { - checkType(int.class); + checkReadType(int.class); argumentIdx++; return frameBuf.getInt(); } public long nextLong() { - checkType(long.class); + checkReadType(long.class); argumentIdx++; return frameBuf.getLong(); } public char nextChar() { - checkType(char.class); + checkReadType(char.class); argumentIdx++; return (char) frameBuf.getInt(); } public boolean nextBoolean() { - checkType(boolean.class); + checkReadType(boolean.class); argumentIdx++; return (frameBuf.getInt() != 0); } public short nextShort() { - checkType(short.class); + checkReadType(short.class); argumentIdx++; return (short) frameBuf.getInt(); } public float nextFloat() { - checkType(float.class); + checkReadType(float.class); argumentIdx++; return frameBuf.getFloat(); } public double nextDouble() { - checkType(double.class); + checkReadType(double.class); argumentIdx++; return frameBuf.getDouble(); } public <T> T nextReference(Class<T> expectedType) { - checkType(expectedType); + checkReadType(expectedType); argumentIdx++; return (T) frame.references[referencesOffset++]; } diff --git a/dalvik/src/main/java/dalvik/system/RuntimeHooks.java b/dalvik/src/main/java/dalvik/system/RuntimeHooks.java index 320ea28253..f1af86790c 100644 --- a/dalvik/src/main/java/dalvik/system/RuntimeHooks.java +++ b/dalvik/src/main/java/dalvik/system/RuntimeHooks.java @@ -16,10 +16,15 @@ package dalvik.system; +import dalvik.system.ThreadPrioritySetter; + import java.util.Objects; import java.util.TimeZone; import java.util.function.Supplier; +import libcore.util.NonNull; +import libcore.util.Nullable; + /** * Provides lifecycle methods and other hooks for an Android runtime "container" to call into the * runtime and core libraries during initialization. For example, from @@ -35,6 +40,10 @@ public final class RuntimeHooks { private static Supplier<String> zoneIdSupplier; + // BEGIN Android-added: Customize behavior of Thread.setPriority(). http://b/139521784 + private static volatile ThreadPrioritySetter threadPrioritySetter; + // END Android-added: Customize behavior of Thread.setPriority(). http://b/139521784 + private RuntimeHooks() { // No need to construct an instance. All methods are static. } @@ -77,4 +86,27 @@ public final class RuntimeHooks { Thread.UncaughtExceptionHandler uncaughtExceptionHandler) { Thread.setUncaughtExceptionPreHandler(uncaughtExceptionHandler); } + + // BEGIN Android-added: Customize behavior of Thread.setPriority(). http://b/139521784 + /** + * Sets a {@link ThreadPrioritySetter} that will be invoked instead of + * the default implementation during {@link Thread.setPriority(int)}. + * @hide + */ + @libcore.api.CorePlatformApi + public static void setThreadPrioritySetter(@NonNull ThreadPrioritySetter threadPrioritySetter) { + RuntimeHooks.threadPrioritySetter = Objects.requireNonNull(threadPrioritySetter); + } + + /** + * Returns the last {@code ThreadPrioritySetter} that has been + * {@code #setThreadPrioritySetter(ThreadPrioritySetter) set}, or + * null if the setter has not yet been called. + * @hide + */ + @libcore.api.CorePlatformApi + public static @Nullable ThreadPrioritySetter getThreadPrioritySetter() { + return threadPrioritySetter; + } + // END Android-added: Customize behavior of Thread.setPriority(). http://b/139521784 } diff --git a/dalvik/src/main/java/dalvik/system/SocketTagger.java b/dalvik/src/main/java/dalvik/system/SocketTagger.java index 54ede15253..0493daa90a 100644 --- a/dalvik/src/main/java/dalvik/system/SocketTagger.java +++ b/dalvik/src/main/java/dalvik/system/SocketTagger.java @@ -16,7 +16,7 @@ package dalvik.system; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.io.FileDescriptor; import java.net.DatagramSocket; import java.net.Socket; diff --git a/dalvik/src/main/java/dalvik/system/TEST_MAPPING b/dalvik/src/main/java/dalvik/system/TEST_MAPPING new file mode 100644 index 0000000000..5f4d46ceb2 --- /dev/null +++ b/dalvik/src/main/java/dalvik/system/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.dalvik.system" + } + ] + } + ] +}
\ No newline at end of file diff --git a/dalvik/src/main/java/dalvik/system/ThreadPrioritySetter.java b/dalvik/src/main/java/dalvik/system/ThreadPrioritySetter.java new file mode 100644 index 0000000000..484784b380 --- /dev/null +++ b/dalvik/src/main/java/dalvik/system/ThreadPrioritySetter.java @@ -0,0 +1,28 @@ +/* + * 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. + */ + +package dalvik.system; + +/** + * Interface for hooking to thread priority runtime setting + * @hide + */ +@libcore.api.CorePlatformApi +@FunctionalInterface +public interface ThreadPrioritySetter { + @libcore.api.CorePlatformApi + void setPriority(int nativeTid, int priority); +} diff --git a/dalvik/src/main/java/dalvik/system/VMDebug.java b/dalvik/src/main/java/dalvik/system/VMDebug.java index 2a0e4ef586..4436e3f723 100644 --- a/dalvik/src/main/java/dalvik/system/VMDebug.java +++ b/dalvik/src/main/java/dalvik/system/VMDebug.java @@ -16,13 +16,15 @@ package dalvik.system; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.annotation.optimization.FastNative; +import android.compat.annotation.UnsupportedAppUsage; + import java.io.FileDescriptor; import java.io.IOException; import java.util.HashMap; import java.util.Map; +import dalvik.annotation.optimization.FastNative; + /** * Provides access to some VM-specific debug features. Though this class and * many of its members are public, this class is meant to be wrapped in a more diff --git a/dalvik/src/main/java/dalvik/system/ZygoteHooks.java b/dalvik/src/main/java/dalvik/system/ZygoteHooks.java index 13769e137e..7e8fe3651e 100644 --- a/dalvik/src/main/java/dalvik/system/ZygoteHooks.java +++ b/dalvik/src/main/java/dalvik/system/ZygoteHooks.java @@ -21,6 +21,7 @@ import android.icu.text.DecimalFormatSymbols; import android.icu.util.ULocale; import java.io.File; +import java.io.FileDescriptor; /** * Provides hooks for the zygote to call back into the runtime to perform @@ -58,6 +59,12 @@ public final class ZygoteHooks { for (ULocale uLocale : localesToPin) { new DecimalFormatSymbols(uLocale); } + + // Framework's LocalLog is used during app start-up. It indirectly uses the current ICU time + // zone. Pre-loading the current time zone in ICU improves app startup time. b/150605074 + // We're being explicit about the fully qualified name of the TimeZone class to avoid + // confusion with java.util.TimeZome.getDefault(). + android.icu.util.TimeZone.getDefault(); } /** @@ -67,6 +74,11 @@ public final class ZygoteHooks { public static void onEndPreload() { // All cache references created by ICU from this point will be soft. CacheValue.setStrength(CacheValue.Strength.SOFT); + + // Clone standard descriptors as originals closed / rebound during zygote post fork. + FileDescriptor.in.cloneForFork(); + FileDescriptor.out.cloneForFork(); + FileDescriptor.err.cloneForFork(); } /** @@ -112,8 +124,8 @@ public final class ZygoteHooks { * before {@code postForkChild} for system server. */ @libcore.api.CorePlatformApi - public static void postForkSystemServer() { - nativePostForkSystemServer(); + public static void postForkSystemServer(int runtimeFlags) { + nativePostForkSystemServer(runtimeFlags); } /** @@ -136,13 +148,14 @@ public final class ZygoteHooks { */ @libcore.api.CorePlatformApi public static void postForkCommon() { - Daemons.startPostZygoteFork(); + // Notify the runtime before creating new threads. nativePostZygoteFork(); + Daemons.startPostZygoteFork(); } // Hook for SystemServer specific early initialization post-forking. - private static native void nativePostForkSystemServer(); + private static native void nativePostForkSystemServer(int runtimeFlags); private static native long nativePreFork(); private static native void nativePostZygoteFork(); diff --git a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/Chunk.java b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/Chunk.java index 373364bf42..292e967959 100644 --- a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/Chunk.java +++ b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/Chunk.java @@ -16,7 +16,7 @@ package org.apache.harmony.dalvik.ddmc; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.nio.ByteBuffer; /** diff --git a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/ChunkHandler.java b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/ChunkHandler.java index d7f370d0e8..0fb74f8e5a 100644 --- a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/ChunkHandler.java +++ b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/ChunkHandler.java @@ -16,7 +16,7 @@ package org.apache.harmony.dalvik.ddmc; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.nio.ByteBuffer; import java.nio.ByteOrder; diff --git a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmServer.java b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmServer.java index e961d56e46..f1f58b6d53 100644 --- a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmServer.java +++ b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmServer.java @@ -16,12 +16,14 @@ package org.apache.harmony.dalvik.ddmc; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.annotation.optimization.FastNative; +import android.compat.annotation.UnsupportedAppUsage; + import java.util.Collection; import java.util.HashMap; import java.util.Iterator; +import dalvik.annotation.optimization.FastNative; + /** * This represents our connection to the DDM Server. diff --git a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmVmInternal.java b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmVmInternal.java index ac994bb22b..2c961da811 100644 --- a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmVmInternal.java +++ b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmVmInternal.java @@ -16,7 +16,7 @@ package org.apache.harmony.dalvik.ddmc; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import dalvik.annotation.optimization.FastNative; /** diff --git a/dalvik/src/test/java/libcore/dalvik/system/CloseGuardTest.java b/dalvik/src/test/java/libcore/dalvik/system/CloseGuardTest.java index f7f58bdbb1..92c29460cc 100644 --- a/dalvik/src/test/java/libcore/dalvik/system/CloseGuardTest.java +++ b/dalvik/src/test/java/libcore/dalvik/system/CloseGuardTest.java @@ -64,6 +64,14 @@ public class CloseGuardTest { } @Test + public void testEnabled_OpenWithCallsiteNotClosed() throws Throwable { + CloseGuard.setEnabled(true); + ResourceOwner owner = new ResourceOwner(); + owner.openWithCallsite("testEnabled_OpoenWIthCallsiteNotClosed"); + assertUnreleasedResources(owner, 1); + } + + @Test public void testEnabled_OpenThenClosed() throws Throwable { CloseGuard.setEnabled(true); ResourceOwner owner = new ResourceOwner(); @@ -73,6 +81,15 @@ public class CloseGuardTest { } @Test + public void testEnabled_OpenWithCallsiteThenClosed() throws Throwable { + CloseGuard.setEnabled(true); + ResourceOwner owner = new ResourceOwner(); + owner.openWithCallsite("testEnabled_OpenWithCallsiteThenClosed"); + owner.close(); + assertUnreleasedResources(owner, 0); + } + + @Test public void testEnabledWhenCreated_DisabledWhenOpen() throws Throwable { CloseGuard.setEnabled(true); ResourceOwner owner = new ResourceOwner(); @@ -111,6 +128,14 @@ public class CloseGuardTest { } @Test + public void testDisabled_OpenWithCallsiteNotClosed() throws Throwable { + CloseGuard.setEnabled(false); + ResourceOwner owner = new ResourceOwner(); + owner.openWithCallsite("testDisabled_OpenWithCallsiteNotClosed"); + assertUnreleasedResources(owner, 0); + } + + @Test public void testDisabled_OpenThenClosed() throws Throwable { CloseGuard.setEnabled(false); ResourceOwner owner = new ResourceOwner(); @@ -120,6 +145,15 @@ public class CloseGuardTest { } @Test + public void testDisabled_OpenWithCallsiteThenClosed() throws Throwable { + CloseGuard.setEnabled(false); + ResourceOwner owner = new ResourceOwner(); + owner.openWithCallsite("testDisabled_OpenWithCallsiteThenClosed"); + owner.close(); + assertUnreleasedResources(owner, 0); + } + + @Test public void testDisabledWhenCreated_EnabledWhenOpen() throws Throwable { CloseGuard.setEnabled(false); ResourceOwner owner = new ResourceOwner(); @@ -156,6 +190,10 @@ public class CloseGuardTest { closeGuard.open("close"); } + public void openWithCallsite(String callsite) { + closeGuard.openWithCallSite("close", callsite); + } + public void close() { closeGuard.close(); } diff --git a/dalvik/test-rules/src/main/java/libcore/dalvik/system/CloseGuardSupport.java b/dalvik/test-rules/src/main/java/libcore/dalvik/system/CloseGuardSupport.java index ca007a8f46..e419f16c75 100644 --- a/dalvik/test-rules/src/main/java/libcore/dalvik/system/CloseGuardSupport.java +++ b/dalvik/test-rules/src/main/java/libcore/dalvik/system/CloseGuardSupport.java @@ -261,6 +261,7 @@ public class CloseGuardSupport { private final Thread callingThread = Thread.currentThread(); private final List<Throwable> unreleasedResourceAllocationSites = new ArrayList<>(); + private final List<String> unreleasedResourceAllocationCallsites = new ArrayList<>(); @Override public void report(String message, Throwable allocationSite) { @@ -270,8 +271,17 @@ public class CloseGuardSupport { } } + @Override + public void report(String message) { + // Only care about resources that are not reported on this thread. + if (callingThread == Thread.currentThread()) { + unreleasedResourceAllocationCallsites.add(message); + } + } + void assertUnreleasedResources(int expectedCount) { - int unreleasedResourceCount = unreleasedResourceAllocationSites.size(); + int unreleasedResourceCount = unreleasedResourceAllocationSites.size() + + unreleasedResourceAllocationCallsites.size(); if (unreleasedResourceCount == expectedCount) { return; } @@ -282,6 +292,9 @@ public class CloseGuardSupport { for (Throwable unreleasedResourceAllocationSite : unreleasedResourceAllocationSites) { error.addSuppressed(unreleasedResourceAllocationSite); } + for (String unreleasedResourceAllocationCallsite : unreleasedResourceAllocationCallsites) { + error.addSuppressed(new Throwable(unreleasedResourceAllocationCallsite)); + } throw error; } } diff --git a/expectations/Android.bp b/expectations/Android.bp new file mode 100644 index 0000000000..c2667d3980 --- /dev/null +++ b/expectations/Android.bp @@ -0,0 +1,29 @@ +// 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. + +expectations_visibility = [ + "//cts/tests/libcore:__subpackages__", +] + +filegroup { + name: "libcore-expectations-knownfailures", + visibility: expectations_visibility, + srcs: ["knownfailures.txt"], +} + +filegroup { + name: "libcore-expectations-virtualdeviceknownfailures", + visibility: expectations_visibility, + srcs: ["virtualdeviceknownfailures.txt"], +} diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt index 6c146608b7..80e1c971eb 100644 --- a/expectations/knownfailures.txt +++ b/expectations/knownfailures.txt @@ -1312,12 +1312,6 @@ ] }, { - description: "Known failure in MathTest 1^NAN should be NAN", - bug: 11669804, - result: EXEC_FAILED, - name: "org.apache.harmony.tests.java.lang.MathTest#test_powDD" -}, -{ description: "Known failures in URLTest and URLDecoderTest", bug: 11686814, names: [ @@ -1336,80 +1330,63 @@ description: "external/apache-harmony tests for java.sql are broken for various reasons. java.sql is not a high enough priority to fix.", bug: 17342415, names: [ - "com.android.org.apache.harmony.sql.tests.java.sql.DataTruncationTest#testGetDataSize", - "com.android.org.apache.harmony.sql.tests.java.sql.DataTruncationTest#testGetIndex", - "com.android.org.apache.harmony.sql.tests.java.sql.DataTruncationTest#testGetParameter", - "com.android.org.apache.harmony.sql.tests.java.sql.DataTruncationTest#testGetRead", - "com.android.org.apache.harmony.sql.tests.java.sql.DataTruncationTest#testGetTransferSize", - "com.android.org.apache.harmony.sql.tests.java.sql.DataTruncationTest#testDataTruncationintbooleanbooleanintint", - "com.android.org.apache.harmony.sql.tests.java.sql.DateTest#test_valueOf_IllegalArgumentException", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testDeregisterDriver", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testGetConnectionString", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testGetConnectionStringProperties", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testGetConnectionStringStringString", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testGetDriver", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testGetDrivers", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testGetLogStream", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testGetLogWriter", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testGetLoginTimeout", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testPrintln", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testRegisterDriver", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testSetLogStream", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testSetLogWriter", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#testSetLoginTimeout", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#test_getConnection_LStringLProperties", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#test_initClass", - "com.android.org.apache.harmony.sql.tests.java.sql.DriverManagerTest#test_registerDriver_MultiTimes", - "com.android.org.apache.harmony.sql.tests.java.sql.TimestampTest#testCompareToDate", - "com.android.org.apache.harmony.sql.tests.java.sql.TimestampTest#testOverridingTimestamp" + "org.apache.harmony.sql.tests.java.sql.DataTruncationTest#testGetDataSize", + "org.apache.harmony.sql.tests.java.sql.DataTruncationTest#testGetIndex", + "org.apache.harmony.sql.tests.java.sql.DataTruncationTest#testGetParameter", + "org.apache.harmony.sql.tests.java.sql.DataTruncationTest#testGetRead", + "org.apache.harmony.sql.tests.java.sql.DataTruncationTest#testGetTransferSize", + "org.apache.harmony.sql.tests.java.sql.DataTruncationTest#testDataTruncationintbooleanbooleanintint", + "org.apache.harmony.sql.tests.java.sql.DateTest#test_valueOf_IllegalArgumentException", + "org.apache.harmony.sql.tests.java.sql.TimestampTest#testCompareToDate", + "org.apache.harmony.sql.tests.java.sql.TimestampTest#testOverridingTimestamp" ] }, { description: "java.util.logging: Android introduced config fallback behavior in LogManager.readConfiguration()", bug: 13882147, names: [ - "com.android.org.apache.harmony.logging.tests.java.util.logging.LogManagerTest#testNotExistConfigFile", - "com.android.org.apache.harmony.logging.tests.java.util.logging.LoggerTest#testGetLogger_Empty", - "com.android.org.apache.harmony.logging.tests.java.util.logging.LoggerTest#testGetLogger_Null", - "com.android.org.apache.harmony.logging.tests.java.util.logging.LoggerTest#testGetLoggerWithRes_InvalidRes", - "com.android.org.apache.harmony.logging.tests.java.util.logging.LoggerTest#testGetLoggerWithRes_Empty" + "org.apache.harmony.logging.tests.java.util.logging.LogManagerTest#testNotExistConfigFile", + "org.apache.harmony.logging.tests.java.util.logging.LoggerTest#testGetLogger_Empty", + "org.apache.harmony.logging.tests.java.util.logging.LoggerTest#testGetLogger_Null", + "org.apache.harmony.logging.tests.java.util.logging.LoggerTest#testGetLoggerWithRes_InvalidRes", + "org.apache.harmony.logging.tests.java.util.logging.LoggerTest#testGetLoggerWithRes_Empty" ] }, { description: "java.util.logging: Android's user.home system property cannot be cleared", bug: 13882147, names: [ - "com.android.org.apache.harmony.logging.tests.java.util.logging.FileHandlerTest#testConstructor_NoUsrHome", - "com.android.org.apache.harmony.logging.tests.java.util.logging.FileHandlerTest#testConstructor_NoTmpDir_NoUsrHome" + "org.apache.harmony.logging.tests.java.util.logging.FileHandlerTest#testConstructor_NoUsrHome", + "org.apache.harmony.logging.tests.java.util.logging.FileHandlerTest#testConstructor_NoTmpDir_NoUsrHome" ] }, { description: "java.util.logging: Android's user.home system property points to root (/) dir", bug: 13882147, - name: "com.android.org.apache.harmony.logging.tests.java.util.logging.FileHandlerTest#testConstructor_NoTmpDir" + name: "org.apache.harmony.logging.tests.java.util.logging.FileHandlerTest#testConstructor_NoTmpDir" }, { description: "java.util.logging: The defaults for FileHandler don't work on Android because they try to write to the read-only user.home dir", bug: 13882147, - name: "com.android.org.apache.harmony.logging.tests.java.util.logging.FileHandlerTest#testDefaultValue" + name: "org.apache.harmony.logging.tests.java.util.logging.FileHandlerTest#testDefaultValue" }, { description: "java.util.logging: Android's classes have been stubbed in places.", bug: 13882147, names: [ - "com.android.org.apache.harmony.logging.tests.java.util.logging.LogManagerTest#testGetLoggingMXBean" + "org.apache.harmony.logging.tests.java.util.logging.LogManagerTest#testGetLoggingMXBean" ] }, { - description: "java.util.logging: the serialized form references org.apache not com.android.org.apache", + description: "java.util.logging: the serialized form references org.apache not org.apache", bug: 13882147, - name: "com.android.org.apache.harmony.logging.tests.java.util.logging.LevelTest#testSerializationCompatibility" + name: "org.apache.harmony.logging.tests.java.util.logging.LevelTest#testSerializationCompatibility" }, { - description: "java.util.beans: the serialized form references org.apache not com.android.org.apache", + description: "java.util.beans: the serialized form references org.apache not org.apache", bug: 17394106, names: [ - "com.android.org.apache.harmony.beans.tests.java.beans.PropertyChangeSupportTest#testSerializationCompatibility" + "org.apache.harmony.beans.tests.java.beans.PropertyChangeSupportTest#testSerializationCompatibility" ] }, { @@ -1513,7 +1490,7 @@ bug: 28536847, result: EXEC_FAILED, names: [ - "com.android.org.apache.harmony.luni.tests.java.net.UnixNetworkInterfaceTest" + "org.apache.harmony.luni.tests.java.net.UnixNetworkInterfaceTest" ] }, { @@ -1521,7 +1498,7 @@ bug: 28535349, result: EXEC_FAILED, names: [ - "com.android.org.apache.harmony.luni.tests.java.net.URLClassLoaderImplTest#test_Constructor$Ljava_net_URLLjava_lang_ClassLoaderLjava_net_URLStreamHandlerFactory" + "org.apache.harmony.luni.tests.java.net.URLClassLoaderImplTest#test_Constructor$Ljava_net_URLLjava_lang_ClassLoaderLjava_net_URLStreamHandlerFactory" ] }, { @@ -1721,7 +1698,7 @@ description: "Some tests (ExcludedProxyTest) connect to a public webserver to check that the HTTP client works", result: EXEC_FAILED, names: [ - "com.android.org.apache.harmony.luni.tests.java.net.ExcludedProxyTest" + "org.apache.harmony.luni.tests.java.net.ExcludedProxyTest" ] }, { @@ -1749,14 +1726,6 @@ ] }, { - description: "The ResourceBundle code under test is probably not used much on Android and needs a lot of attention.", - modes: [device], - bug: 13747957, - names: [ - "org.apache.harmony.tests.java.util.ControlTest#test_needsReload_LStringLLocaleLStringLClassLoaderResourceBundleJ" - ] -}, -{ description: "Fails in CTS, passes in CoreTestRunner.", result: EXEC_FAILED, modes: [device], @@ -1814,15 +1783,7 @@ bug: 28535961, result: EXEC_FAILED, names: [ - "com.android.org.apache.harmony.luni.tests.java.net.URLClassLoaderTest" - ] -}, -{ - description: "Unable to execute Support_AvailTest", - result: EXEC_FAILED, - bug: 28535603, - names: [ - "com.android.org.apache.harmony.luni.tests.internal.process.SystemProcessTest#test_interrupt" + "org.apache.harmony.luni.tests.java.net.URLClassLoaderTest" ] }, { diff --git a/expectations/virtualdeviceknownfailures.txt b/expectations/virtualdeviceknownfailures.txt index 66b67e4588..b6891339f8 100644 --- a/expectations/virtualdeviceknownfailures.txt +++ b/expectations/virtualdeviceknownfailures.txt @@ -1,5 +1,14 @@ /* * List of test cases known to fail on a virtual device. + * + * Many are because of the network environment used by some or all of the + * virtual devices during CTS runs. + * + * See: https://cloud.google.com/vpc/docs/vpc + * As of 2019-05: "VPC networks only support IPv4 unicast traffic. They do not + * support broadcast, multicast, or IPv6 traffic within the network: VMs in the + * VPC network can only send to IPv4 destinations and only receive traffic from + * IPv4 sources. */ [ { @@ -15,15 +24,19 @@ }, { description: "multicast not supported in virtual device testing infra", - names: ["org.apache.harmony.tests.java.net.MulticastSocketTest#test_joinGroupLjava_net_InetAddress_IPv4", - "org.apache.harmony.tests.java.net.MulticastSocketTest#test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4_nullInterface", - "org.apache.harmony.tests.java.net.MulticastSocketTest#test_leaveGroupLjava_net_InetAddress_IPv4", - "org.apache.harmony.tests.java.net.MulticastSocketTest#test_sendLjava_net_DatagramPacketB_IPv4", - "org.apache.harmony.tests.java.net.MulticastSocketTest#test_setLoopbackModeSendReceive_IPv4" + names: ["org.apache.harmony.tests.java.net.MulticastSocketTest", + "libcore.java.net.MulticastSocketTest#testGroupReceiveIPv6", + "libcore.java.nio.channels.DatagramChannelMulticastTest#test_joinAnySource_IPv4", + "libcore.java.nio.channels.DatagramChannelMulticastTest#test_joinAnySource_multicastLoopOption_IPv4" ], bug: 35922755 }, { + description: "DNS lookups of {1.2.3.4.} do not reliably fail on GCE networks", + names: ["libcore.java.net.InetAddressTest#test_getByName_invalid[1]"], + bug: 35922755 +}, +{ description: "Kernels between 4.4 and 4.9 interpret the backlog parameter differently than we expect, causing this test to fail, and our emulators currently use those kernel versions. See b/31960002 for a full discussion and references to the upstream diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FilterOutputStreamTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FilterOutputStreamTest.java index 666955d8ca..2ba710b42c 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FilterOutputStreamTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FilterOutputStreamTest.java @@ -17,14 +17,16 @@ package org.apache.harmony.tests.java.io; +import junit.framework.TestCase; + +import org.mockito.Mockito; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; -import junit.framework.TestCase; - public class FilterOutputStreamTest extends TestCase { private OutputStream os; @@ -59,6 +61,29 @@ public class FilterOutputStreamTest extends TestCase { } /** + * java.io.FilterOutputStream#close() + */ + public void test_doubleClose() throws IOException { + OutputStream outputStream = Mockito.mock(OutputStream.class); + IOException testException = new IOException("test exception"); + Mockito.doThrow(testException).when(outputStream).flush(); + FilterOutputStream filterOutputStream = new FilterOutputStream(outputStream); + // FilterOutputStream.close() flushes and closes the underlying stream. + try { + filterOutputStream.close(); + fail(); + } catch (IOException expected) { + assertEquals(testException, expected); + } + Mockito.verify(outputStream, Mockito.times(1)).flush(); + Mockito.verify(outputStream, Mockito.times(1)).close(); + // A second close() does not delegate to the already-closed underlying stream again. + filterOutputStream.close(); + Mockito.verify(outputStream, Mockito.times(1)).flush(); + Mockito.verify(outputStream, Mockito.times(1)).close(); + } + + /** * java.io.FilterOutputStream#flush() */ public void test_flush() throws IOException { diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/CharacterTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/CharacterTest.java index eaaae86d94..2465071107 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/CharacterTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/CharacterTest.java @@ -747,8 +747,13 @@ public class CharacterTest extends TestCase { assertTrue(Character.getType((int) '$') == Character.CURRENCY_SYMBOL); assertTrue(Character.getType((int) '\u2029') == Character.PARAGRAPH_SEPARATOR); + // Unicode 13 defines a new range 0x30000–0x3134A + assertTrue(Character.getType(0x30000) == Character.DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR); + assertTrue(Character.getType(0x3134A) == Character.DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR); + assertTrue(Character.getType(0x2FFFF) == Character.UNASSIGNED); + assertTrue(Character.getType(0x3134B) == Character.UNASSIGNED); + assertTrue(Character.getType(0x9FFF) == Character.UNASSIGNED); - assertTrue(Character.getType(0x30000) == Character.UNASSIGNED); assertTrue(Character.getType(0x110000) == Character.UNASSIGNED); assertTrue(Character.getType(0x0041) == Character.UPPERCASE_LETTER); @@ -860,9 +865,14 @@ public class CharacterTest extends TestCase { assertTrue(Character.isDefined((int) '\u6039')); assertTrue(Character.isDefined(0x10300)); - assertFalse(Character.isDefined(0x30000)); assertFalse(Character.isDefined(0x3FFFF)); assertFalse(Character.isDefined(0x110000)); + + // Unicode 13 adds a new range 0x30000–0x3134A + assertTrue(Character.isDefined(0x30000)); + assertTrue(Character.isDefined(0x3134A)); + assertFalse(Character.isDefined(0x2FFFF)); + assertFalse(Character.isDefined(0x3134B)); } /** @@ -1101,16 +1111,16 @@ public class CharacterTest extends TestCase { assertTrue(Character.isJavaIdentifierStart(0x01BB)); assertTrue(Character.isJavaIdentifierStart(0x2F888)); - assertTrue(Character.isJavaIdentifierPart(0x0024)); - assertTrue(Character.isJavaIdentifierPart(0xFFE6)); + assertTrue(Character.isJavaIdentifierStart(0x0024)); + assertTrue(Character.isJavaIdentifierStart(0xFFE6)); - assertTrue(Character.isJavaIdentifierPart(0x005F)); - assertTrue(Character.isJavaIdentifierPart(0xFF3F)); + assertTrue(Character.isJavaIdentifierStart(0x005F)); + assertTrue(Character.isJavaIdentifierStart(0xFF3F)); - assertTrue(Character.isJavaIdentifierPart(0x2160)); - assertTrue(Character.isJavaIdentifierPart(0x1034A)); + assertTrue(Character.isJavaIdentifierStart(0x2160)); + assertTrue(Character.isJavaIdentifierStart(0x1034A)); - assertFalse(Character.isJavaIdentifierPart(0x110000)); + assertFalse(Character.isJavaIdentifierStart(0x110000)); } /** @@ -1557,10 +1567,15 @@ public class CharacterTest extends TestCase { */ public void test_isDirectionaliy_I() { assertEquals(Character.DIRECTIONALITY_UNDEFINED, Character.getDirectionality(0xFFFE)); - assertEquals(Character.DIRECTIONALITY_UNDEFINED, Character.getDirectionality(0x30000)); assertEquals(Character.DIRECTIONALITY_UNDEFINED, Character.getDirectionality(0x110000)); assertEquals(Character.DIRECTIONALITY_UNDEFINED, Character.getDirectionality(-1)); + // Unicode 13 adds a new range 0x30000–0x3134A + assertEquals(Character.DIRECTIONALITY_LEFT_TO_RIGHT, Character.getDirectionality(0x30000)); + assertEquals(Character.DIRECTIONALITY_LEFT_TO_RIGHT, Character.getDirectionality(0x3134A)); + assertEquals(Character.DIRECTIONALITY_UNDEFINED, Character.getDirectionality(0x2FFFF)); + assertEquals(Character.DIRECTIONALITY_UNDEFINED, Character.getDirectionality(0x3134B)); + assertEquals(Character.DIRECTIONALITY_LEFT_TO_RIGHT, Character.getDirectionality(0x0041)); assertEquals(Character.DIRECTIONALITY_LEFT_TO_RIGHT, Character.getDirectionality(0x10000)); assertEquals(Character.DIRECTIONALITY_LEFT_TO_RIGHT, Character.getDirectionality(0x104A9)); diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/MathTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/MathTest.java index ed0a094d0d..e3dc9fc803 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/MathTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/MathTest.java @@ -1165,9 +1165,16 @@ public class MathTest extends junit.framework.TestCase { assertEquals("Result should be Math.pow(" + negateDval + "," + 1.0 + ")=" + negateDval, negateDval, Math.pow(negateDval, 1.0)); + // The libm implementation of pow() has the following set of special case behaviors: + // If the first argument is 1.0, then the result is 1.0. + // i.e. the answer for the following case is not Double.NaN. http://b/11669804 + { + double answer = dval == 1.0d ? 1.0d : Double.NaN; + assertEquals("Result should be Math.pow(" + dval + "," + Double.NaN + + ")=" + answer, answer, Math.pow(dval, Double.NaN)); + } + // If the second argument is NaN, then the result is NaN. - assertEquals("Result should be Math.pow(" + dval + "," + Double.NaN - + ")=" + Double.NaN, Double.NaN, Math.pow(dval, Double.NaN)); assertEquals("Result should be Math.pow(" + negateDval + "," + Double.NaN + ")=" + Double.NaN, Double.NaN, Math.pow(negateDval, Double.NaN)); @@ -1301,21 +1308,23 @@ public class MathTest extends junit.framework.TestCase { } } - // If the absolute value of the first argument equals 1 and the - // second argument is infinite, then the result is NaN. if (dval == 1) { + // The libm implementation of pow() has the following set of special case behaviors: + // 1.0 or -1.0 to the power of positive or negative infinity is 1.0. + // i.e. the answer for the following cases is not Double.NaN. http://b/11669804 + assertEquals("Result should be Math.pow(" + dval + "," - + Double.POSITIVE_INFINITY + ")=" + Double.NaN, Double.NaN, Math + + Double.POSITIVE_INFINITY + ")=" + 1.0d, 1.0d, Math .pow(dval, Double.POSITIVE_INFINITY)); assertEquals("Result should be Math.pow(" + dval + "," - + Double.NEGATIVE_INFINITY + ")=" + Double.NaN, Double.NaN, Math + + Double.NEGATIVE_INFINITY + ")=" + 1.0d, 1.0d, Math .pow(dval, Double.NEGATIVE_INFINITY)); assertEquals("Result should be Math.pow(" + negateDval + "," - + Double.POSITIVE_INFINITY + ")=" + Double.NaN, Double.NaN, Math + + Double.POSITIVE_INFINITY + ")=" + 1.0d, 1.0d, Math .pow(negateDval, Double.POSITIVE_INFINITY)); assertEquals("Result should be Math.pow(" + negateDval + "," - + Double.NEGATIVE_INFINITY + ")=" + Double.NaN, Double.NaN, Math + + Double.NEGATIVE_INFINITY + ")=" + 1.0d, 1.0d, Math .pow(negateDval, Double.NEGATIVE_INFINITY)); } diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/DecimalFormatTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/DecimalFormatTest.java index 29470d1127..8b36163437 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/DecimalFormatTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/DecimalFormatTest.java @@ -689,8 +689,12 @@ public class DecimalFormatTest extends TestCase { format.setPositivePrefix(""); assertEquals("", format.getPositivePrefix()); - format.setPositivePrefix(null); - assertNull(format.getPositivePrefix()); + try { + format.setPositivePrefix(null); + fail(); + } catch (NullPointerException expected) { + } + assertNotNull(format.getPositivePrefix()); } public void test_setPositiveSuffix() throws Exception { @@ -704,8 +708,12 @@ public class DecimalFormatTest extends TestCase { format.setPositiveSuffix(""); assertEquals("", format.getPositiveSuffix()); - format.setPositiveSuffix(null); - assertNull(format.getPositiveSuffix()); + try { + format.setPositiveSuffix(null); + fail(); + } catch (NullPointerException expected) { + } + assertNotNull(format.getPositiveSuffix()); } public void test_setNegativePrefix() throws Exception { @@ -718,8 +726,12 @@ public class DecimalFormatTest extends TestCase { format.setNegativePrefix(""); assertEquals("", format.getNegativePrefix()); - format.setNegativePrefix(null); - assertNull(format.getNegativePrefix()); + try { + format.setNegativePrefix(null); + fail(); + } catch (NullPointerException expected) { + } + assertNotNull(format.getNegativePrefix()); } public void test_setNegativeSuffix() throws Exception { @@ -733,8 +745,12 @@ public class DecimalFormatTest extends TestCase { format.setNegativeSuffix(""); assertEquals("", format.getNegativeSuffix()); - format.setNegativeSuffix(null); - assertNull(format.getNegativeSuffix()); + try { + format.setNegativeSuffix(null); + fail(); + } catch (NullPointerException expected) { + } + assertNotNull(format.getNegativeSuffix()); } public void test_setGroupingUsed() { @@ -867,13 +883,18 @@ public class DecimalFormatTest extends TestCase { } } + /** + * Test the constructor and applyPattern with various format patterns and what toPattern() + * returns. These have changed on Android over time: we are not particularly opinionated about + * the output of toPattern() in invalid cases. + */ public void test_applyPattern() { DecimalFormat format = new DecimalFormat("#.#"); - assertEquals("Wrong pattern 1", "#0.#", format.toPattern()); + assertEquals("Wrong pattern 1", "0.#", format.toPattern()); format = new DecimalFormat("#."); - assertEquals("Wrong pattern 2", "#0.", format.toPattern()); + assertEquals("Wrong pattern 2", "0.", format.toPattern()); format = new DecimalFormat("#"); - assertEquals("Wrong pattern 3", "#", format.toPattern()); + assertEquals("Wrong pattern 3", "0", format.toPattern()); format = new DecimalFormat(".#"); assertEquals("Wrong pattern 4", "#.0", format.toPattern()); @@ -906,7 +927,10 @@ public class DecimalFormatTest extends TestCase { } } - // AndroidOnly: icu supports 2 grouping sizes + /** + * Test applyPattern() with different grouping sizes and what toPattern() returns. + * AndroidOnly: icu supports 2 grouping sizes + */ public void test_applyPattern_icu2GroupingSizes() { DecimalFormat decFormat = new DecimalFormat("#.#"); String[] patterns = { @@ -917,12 +941,12 @@ public class DecimalFormatTest extends TestCase { }; String[] expResult = { - "#0.##", "#0.######", "#000000.000000", - "#.000000", "#000000.######", " #0.###", "$#0.######", - "$$#0.######", - "%#,###,####", // icu only. icu supports two grouping sizes + "0.##", "0.######", "000000.000000", + "#.000000", "000000.######", " 0.###", "$0.######", + "$$0.######", + "%#,###,###0", // icu only. icu supports two grouping sizes "#,##0.00;(#,##0.00)", - "#0.##-E" + "0.##-E" // icu only. E in the suffix does not need to be quoted. }; @@ -940,11 +964,11 @@ public class DecimalFormatTest extends TestCase { // case 1: Try to apply correct variants of pattern. format.applyLocalizedPattern("#.#"); - assertEquals("Wrong pattern 1", "#0.#", format.toLocalizedPattern()); + assertEquals("Wrong pattern 1", "0.#", format.toLocalizedPattern()); format.applyLocalizedPattern("#."); - assertEquals("Wrong pattern 2", "#0.", format.toLocalizedPattern()); + assertEquals("Wrong pattern 2", "0.", format.toLocalizedPattern()); format.applyLocalizedPattern("#"); - assertEquals("Wrong pattern 3", "#", format.toLocalizedPattern()); + assertEquals("Wrong pattern 3", "0", format.toLocalizedPattern()); format.applyLocalizedPattern(".#"); assertEquals("Wrong pattern 4", "#.0", format.toLocalizedPattern()); @@ -966,11 +990,11 @@ public class DecimalFormatTest extends TestCase { public void test_toPattern() { DecimalFormat format = new DecimalFormat(); format.applyPattern("#.#"); - assertEquals("Wrong pattern 1", "#0.#", format.toPattern()); + assertEquals("Wrong pattern 1", "0.#", format.toPattern()); format.applyPattern("#."); - assertEquals("Wrong pattern 2", "#0.", format.toPattern()); + assertEquals("Wrong pattern 2", "0.", format.toPattern()); format.applyPattern("#"); - assertEquals("Wrong pattern 3", "#", format.toPattern()); + assertEquals("Wrong pattern 3", "0", format.toPattern()); format.applyPattern(".#"); assertEquals("Wrong pattern 4", "#.0", format.toPattern()); } @@ -979,11 +1003,11 @@ public class DecimalFormatTest extends TestCase { DecimalFormat format = new DecimalFormat(); format.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US)); format.applyLocalizedPattern("#.#"); - assertEquals("Wrong pattern 1", "#0.#", format.toLocalizedPattern()); + assertEquals("Wrong pattern 1", "0.#", format.toLocalizedPattern()); format.applyLocalizedPattern("#."); - assertEquals("Wrong pattern 2", "#0.", format.toLocalizedPattern()); + assertEquals("Wrong pattern 2", "0.", format.toLocalizedPattern()); format.applyLocalizedPattern("#"); - assertEquals("Wrong pattern 3", "#", format.toLocalizedPattern()); + assertEquals("Wrong pattern 3", "0", format.toLocalizedPattern()); format.applyLocalizedPattern(".#"); assertEquals("Wrong pattern 4", "#.0", format.toLocalizedPattern()); } @@ -1136,12 +1160,12 @@ public class DecimalFormatTest extends TestCase { // Scientific notation => use significant digit logic // '@' not present: Significant digits: Min: 1, // Max: "min integer digits" (0) + "max fractional digits (1) == 1 - formatTester.format(df, "0.0E0", 0.0); - formatTester.format(df, "1.0E0", 1.0); - formatTester.format(df, "1.0E1", 12.0); - formatTester.format(df, "1.0E2", 123.0); - formatTester.format(df, "1.0E3", 1234.0); - formatTester.format(df, "1.0E4", 9999.0); + formatTester.format(df, "0E0", 0.0); + formatTester.format(df, "1E0", 1.0); + formatTester.format(df, "1E1", 12.0); + formatTester.format(df, "1E2", 123.0); + formatTester.format(df, "1E3", 1234.0); + formatTester.format(df, "1E4", 9999.0); df = new DecimalFormat("0.E0", dfs); // ["0.E0",isDecimalSeparatorAlwaysShown=true,groupingSize=0,multiplier=1,negativePrefix=-, @@ -1308,8 +1332,8 @@ public class DecimalFormatTest extends TestCase { // Because maximum integer digit count is set: The exponent must be a multiple of it (1). // Scientific notation => use significant digit logic // '@' not present: Significant digits: Min: 1, - // Max: "min integer digits" (0) + "max fractional digits (1) == 2 - formatTester.format(df, "-0.0E0", -0.0); + // Max: "min integer digits" (0) + "max fractional digits (1) == 1 + formatTester.format(df, "-0E0", -0.0); df = new DecimalFormat("0.#E0", dfs); // ["0.#E0",isDecimalSeparatorAlwaysShown=false,groupingSize=0,multiplier=1, @@ -1425,12 +1449,12 @@ public class DecimalFormatTest extends TestCase { // Scientific notation => use significant digit logic // '@' not present: Significant digits: Min: 1, // Max: "min integer digits" (0) + "max fractional digits (1) == 1 - formatTester.format(df, "0.0E0", 0); - formatTester.format(df, "1.0E0", 1); - formatTester.format(df, "1.0E1", 12); - formatTester.format(df, "1.0E2", 123); - formatTester.format(df, "1.0E3", 1234); - formatTester.format(df, "1.0E4", 9999); + formatTester.format(df, "0E0", 0); + formatTester.format(df, "1E0", 1); + formatTester.format(df, "1E1", 12); + formatTester.format(df, "1E2", 123); + formatTester.format(df, "1E3", 1234); + formatTester.format(df, "1E4", 9999); df = new DecimalFormat("0.#E0", dfs); // ["0.#E0",isDecimalSeparatorAlwaysShown=false,groupingSize=0,multiplier=1, diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ControlTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ControlTest.java index d0b236d6fc..717e7d9bf9 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ControlTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ControlTest.java @@ -27,6 +27,7 @@ import java.io.PrintWriter; import java.io.Reader; import java.io.Writer; import java.net.URL; +import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -45,6 +46,8 @@ import static java.util.ResourceBundle.Control.*; */ public class ControlTest extends TestCase { + public static final String RESOURCE_PACKAGE_NAME = "tests.resources.control_test"; + /** * Control with format:FORMAT_PROPERTIES */ @@ -374,13 +377,9 @@ public class ControlTest extends TestCase { } @SuppressWarnings("nls") - static File copyFile(final URL src) throws IOException { + static File copyFile(final URL src, final String targetDir) throws IOException { String tail = src.getFile().split("hyts_resource")[1]; - String tmpdir = System.getProperty("java.io.tmpdir"); - if (null == tmpdir) { - return null; - } - String copyName = tmpdir + File.separator + "hyts_resource_copy" + tail; + String copyName = targetDir + File.separator + "hyts_resource_copy" + tail; File copy = new File(copyName); if (copy.exists()) { copy.delete(); @@ -454,23 +453,27 @@ public class ControlTest extends TestCase { public void test_needsReload_LStringLLocaleLStringLClassLoaderResourceBundleJ() throws Exception { String className = "tests.support.Support_TestResource"; - String propertiesName = Support_Resources.RESOURCE_PACKAGE_NAME - + ".hyts_resource"; + String propertiesName = RESOURCE_PACKAGE_NAME + ".hyts_resource"; String propertiesNameCopy = "hyts_resource_copy"; String CLASS = "java.class"; String PROPERTIES = "java.properties"; Locale frFR = new Locale("fr", "FR"); - ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); - ClassLoader URLLoader = systemLoader; + ClassLoader testCodeClassLoader = this.getClass().getClassLoader(); ResourceBundle bundle = null; long time = 0L; - final URL srcFile = URLLoader.getResource(control.toResourceName( + final URL srcFile = testCodeClassLoader.getResource(control.toResourceName( control.toBundleName(propertiesName, frFR), "properties")); assertNotNull(srcFile); - final File copyFile = copyFile(srcFile); + + String tmpdir = System.getProperty("java.io.tmpdir"); + assertNotNull(tmpdir); + final File copyFile = copyFile(srcFile, tmpdir); + ClassLoader URLLoader = new URLClassLoader( + new URL[] { new File(tmpdir).toURL() }, + testCodeClassLoader); // 1. format = "java.properties" - if (null != URLLoader.getResourceAsStream(copyFile.toURL().toString())) { + if (null != URLLoader.getResourceAsStream(copyFile.getName())) { Thread.sleep(1000); bundle = control.newBundle(propertiesNameCopy, frFR, PROPERTIES, URLLoader, false); @@ -492,15 +495,10 @@ public class ControlTest extends TestCase { PROPERTIES, URLLoader, bundle, 2006L)); // other loader assertFalse(control.needsReload(propertiesNameCopy, frFR, - PROPERTIES, systemLoader, bundle, time)); + PROPERTIES, testCodeClassLoader, bundle, time)); // other bundle ResourceBundle otherBundle = control.newBundle(propertiesName, - Locale.ROOT, PROPERTIES, systemLoader, false); - assertEquals("parent", otherBundle.getString("property")); - assertTrue(control.needsReload(propertiesNameCopy, frFR, - PROPERTIES, URLLoader, otherBundle, time)); - otherBundle = control.newBundle(propertiesName, Locale.ROOT, - PROPERTIES, URLLoader, false); + Locale.ROOT, PROPERTIES, URLLoader, false); assertEquals("resource", otherBundle.getString("property")); assertTrue(control.needsReload(propertiesNameCopy, frFR, PROPERTIES, URLLoader, otherBundle, time)); @@ -508,16 +506,14 @@ public class ControlTest extends TestCase { assertFalse(control.needsReload(propertiesNameCopy, frFR, PROPERTIES, URLLoader, bundle, System.currentTimeMillis())); } else { - System.err - .println("Can not find the test file, some code of this test 'test_needsReload_LStringLLocaleLStringLClassLoaderResourceBundleJ' did not run."); - + fail("Can not find the test file:" + copyFile); } // 2. format = "java.class" - bundle = control.newBundle(className, frFR, CLASS, systemLoader, false); + bundle = control.newBundle(className, frFR, CLASS, testCodeClassLoader, false); time = System.currentTimeMillis(); assertEquals("frFRValue3", bundle.getString("parent3")); - assertFalse(control.needsReload(className, frFR, CLASS, systemLoader, + assertFalse(control.needsReload(className, frFR, CLASS, testCodeClassLoader, bundle, time)); // exceptions control.needsReload(propertiesName, frFR, PROPERTIES, URLLoader, diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ScannerTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ScannerTest.java index 4a5c80366c..85899f3f3c 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ScannerTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ScannerTest.java @@ -5694,13 +5694,15 @@ public class ScannerTest extends TestCase { } // http://code.google.com/p/android/issues/detail?id=57050 - public void testPerformance() throws Exception { + // Disable this test since it causes oom failures in follow on + // tests. See b/160171148 for details. + public void disableTestPerformance() throws Exception { int count = 100000; ByteArrayOutputStream baos = new ByteArrayOutputStream(); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(baos)); for (int i = 0; i < count; ++i) { - out.write(Integer.toString(123) + " "); + out.write("123 "); } out.close(); @@ -5709,7 +5711,16 @@ public class ScannerTest extends TestCase { Scanner s = new Scanner(new BufferedReader(new InputStreamReader(bais))); for (int i = 0; i < count; ++i) { - if (s.nextInt() != 123) { + final int value; + try { + value = s.nextInt(); + } catch (RuntimeException e) { + String msg = String.format(Locale.US, + "Failed to parse float on item %d/%d with locale %s: %s", + (i+1), count, s.locale(), s); + throw new RuntimeException(msg, e); + } + if (value != 123) { fail(); } } @@ -5717,9 +5728,19 @@ public class ScannerTest extends TestCase { bais.reset(); s = new Scanner(new BufferedReader(new InputStreamReader(bais))); for (int i = 0; i < count; ++i) { - if (s.nextFloat() != 123.0) { + final float value; + try { + value = s.nextFloat(); + } catch (RuntimeException e) { + String msg = String.format(Locale.US, + "Failed to parse float on item %d/%d with locale %s: %s", + (i+1), count, s.locale(), s); + throw new RuntimeException(msg, e); + } + if (value != 123.0) { fail(); } } + System.gc(); } } diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/HandshakeCompletedEventTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/HandshakeCompletedEventTest.java index 74c3a7faff..d82068929f 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/HandshakeCompletedEventTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/HandshakeCompletedEventTest.java @@ -431,8 +431,6 @@ public class HandshakeCompletedEventTest extends TestCase { assertEquals(i, j); } - istream.close(); - OutputStream ostream = clientSocket.getOutputStream(); for (int i = 0; i < 256; i++) { @@ -503,7 +501,6 @@ public class HandshakeCompletedEventTest extends TestCase { } ostream.flush(); - ostream.close(); InputStream istream = socket.getInputStream(); diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/SSLContextSpiTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/SSLContextSpiTest.java index 45e9d40cc4..f688b9b230 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/SSLContextSpiTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/SSLContextSpiTest.java @@ -15,9 +15,16 @@ */ package org.apache.harmony.tests.javax.net.ssl; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContextSpi; import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSessionContext; import javax.net.ssl.SSLSocketFactory; @@ -28,18 +35,20 @@ import java.security.KeyManagementException; import java.security.KeyStore; import java.security.SecureRandom; -import java.security.Security; - -import junit.framework.TestCase; import org.apache.harmony.xnet.tests.support.SSLContextSpiImpl; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; -public class SSLContextSpiTest extends TestCase { +@RunWith(JUnit4.class) +public class SSLContextSpiTest { /** * javax.net.ssl.SSLContextSpi#SSLContextSpi() */ - public void test_Constructor() { + @Test + public void constructor() { try { SSLContextSpiImpl ssl = new SSLContextSpiImpl(); assertTrue(ssl instanceof SSLContextSpi); @@ -52,7 +61,8 @@ public class SSLContextSpiTest extends TestCase { * javax.net.ssl.SSLContextSpi#engineCreateSSLEngine() * Verify exception when SSLContextSpi object wasn't initialiazed. */ - public void test_engineCreateSSLEngine_01() { + @Test + public void engineCreateSSLEngine_01() { SSLContextSpiImpl ssl = new SSLContextSpiImpl(); try { SSLEngine sleng = ssl.engineCreateSSLEngine(); @@ -70,7 +80,8 @@ public class SSLContextSpiTest extends TestCase { * javax.net.ssl.SSLContextSpi#engineCreateSSLEngine(String host, int port) * Verify exception when SSLContextSpi object wasn't initialiazed. */ - public void test_engineCreateSSLEngine_02() { + @Test + public void engineCreateSSLEngine_02() { int[] invalid_port = {Integer.MIN_VALUE, -65535, -1, 65536, Integer.MAX_VALUE}; SSLContextSpiImpl ssl = new SSLContextSpiImpl(); try { @@ -101,7 +112,8 @@ public class SSLContextSpiTest extends TestCase { * SSLContextSpi#engineGetSocketFactory() * Verify exception when SSLContextSpi object wasn't initialiazed. */ - public void test_commonTest_01() { + @Test + public void commonTest_01() { SSLContextSpiImpl ssl = new SSLContextSpiImpl(); try { @@ -152,34 +164,19 @@ public class SSLContextSpiTest extends TestCase { /** * SSLContextSpi#engineInit(KeyManager[] km, TrustManager[] tm, SecureRandom sr) */ - public void test_engineInit() { + @Test + public void engineInit() throws Exception { SSLContextSpiImpl ssl = new SSLContextSpiImpl(); - String defaultAlgorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm"); + KeyManager[] km = getKeyManagers(); + TrustManager[] tm = getTrustManagers(); + SecureRandom sr = getSecureRandom(); + ssl.engineInit(km, tm, sr); + try { - KeyManagerFactory kmf = KeyManagerFactory.getInstance(defaultAlgorithm); - char[] pass = "password".toCharArray(); - kmf.init(null, pass); - KeyManager[] km = kmf.getKeyManagers(); - defaultAlgorithm = Security.getProperty("ssl.TrustManagerFactory.algorithm"); - TrustManagerFactory trustMF = TrustManagerFactory.getInstance(defaultAlgorithm); - KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - ks.load(null, null); - trustMF.init(ks); - TrustManager[] tm = trustMF.getTrustManagers(); - SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); - try { - ssl.engineInit(km, tm, sr); - } catch (KeyManagementException kme) { - fail(kme + " was throw for engineInit method"); - } - try { - ssl.engineInit(km, tm, null); - fail("KeyManagementException wasn't thrown"); - } catch (KeyManagementException kme) { - //expected - } - } catch (Exception ex) { - fail(ex + " unexpected exception"); + ssl.engineInit(km, tm, null); + fail("KeyManagementException wasn't thrown"); + } catch (KeyManagementException kme) { + //expected } } @@ -191,39 +188,77 @@ public class SSLContextSpiTest extends TestCase { * SSLContextSpi#engineGetServerSocketFactory() * SSLContextSpi#engineGetSocketFactory() */ - public void test_commonTest_02() { + @Test + public void commonTest_02() throws Exception { SSLContextSpiImpl ssl = new SSLContextSpiImpl(); - String defaultAlgorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm"); - try { - KeyManagerFactory kmf = KeyManagerFactory.getInstance(defaultAlgorithm); - char[] pass = "password".toCharArray(); - kmf.init(null, pass); - KeyManager[] km = kmf.getKeyManagers(); - defaultAlgorithm = Security.getProperty("ssl.TrustManagerFactory.algorithm"); - TrustManagerFactory trustMF = TrustManagerFactory.getInstance(defaultAlgorithm); - KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - ks.load(null, null); - trustMF.init(ks); - TrustManager[] tm = trustMF.getTrustManagers(); - SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); - ssl.engineInit(km, tm, sr); - } catch (Exception ex) { - fail(ex + " unexpected exception"); - } + ssl.engineInit(getKeyManagers(), getTrustManagers(), getSecureRandom()); - try { - assertNotNull("Subtest_01: Object is NULL", ssl.engineCreateSSLEngine()); - SSLEngine sleng = ssl.engineCreateSSLEngine("localhost", 1080); - assertNotNull("Subtest_02: Object is NULL", sleng); - assertEquals(sleng.getPeerPort(), 1080); - assertEquals(sleng.getPeerHost(), "localhost"); - assertNull("Subtest_03: Object not NULL", ssl.engineGetClientSessionContext()); - assertNull("Subtest_04: Object not NULL", ssl.engineGetServerSessionContext()); - assertNull("Subtest_05: Object not NULL", ssl.engineGetServerSocketFactory()); - assertNull("Subtest_06: Object not NULL", ssl.engineGetSocketFactory()); - } catch (Exception e) { - fail("Unexpected exception " + e); + assertNotNull("Subtest_01: Object is NULL", ssl.engineCreateSSLEngine()); + SSLEngine sleng = ssl.engineCreateSSLEngine("localhost", 1080); + assertNotNull("Subtest_02: Object is NULL", sleng); + assertEquals(sleng.getPeerPort(), 1080); + assertEquals(sleng.getPeerHost(), "localhost"); + assertNull("Subtest_03: Object not NULL", ssl.engineGetClientSessionContext()); + assertNull("Subtest_04: Object not NULL", ssl.engineGetServerSessionContext()); + assertNull("Subtest_05: Object not NULL", ssl.engineGetServerSocketFactory()); + assertNull("Subtest_06: Object not NULL", ssl.engineGetSocketFactory()); + } + + private static class SpiWithSocketFactory extends SSLContextSpiImpl { + @Override + public SSLSocketFactory engineGetSocketFactory() { + super.engineGetSocketFactory(); + return (SSLSocketFactory) SSLSocketFactory.getDefault(); } } + /** + * Tests the default implementations of SSLContextSpi.engineGetDefaultSSLParameters() + * and SSLContextSpi.engineGetSupportedSSLParameters(). Requires a subclass which + * returns non-null from engineGetSocketFactory() for the base class to work. + * + * Verifies the returned SSLParameters for consistency. + */ + @Test + public void getSslParameters() throws Exception { + SpiWithSocketFactory spi = new SpiWithSocketFactory(); + spi.engineInit(getKeyManagers(), getTrustManagers(), getSecureRandom()); + + SSLParameters defaultParams = spi.engineGetDefaultSSLParameters(); + assertNotNull(defaultParams); + String[] protocols = defaultParams.getProtocols(); + assertNotNull(protocols); + assertTrue(protocols.length > 0); + String[] cipherSuites = defaultParams.getCipherSuites(); + assertNotNull(cipherSuites); + assertTrue(cipherSuites.length > 0); + + SSLParameters supportedParams = spi.engineGetSupportedSSLParameters(); + assertNotNull(supportedParams); + protocols = supportedParams.getProtocols(); + assertNotNull(protocols); + assertTrue(protocols.length > 0); + cipherSuites = supportedParams.getCipherSuites(); + assertNotNull(cipherSuites); + assertTrue(cipherSuites.length > 0); + } + + private SecureRandom getSecureRandom() throws Exception { + return SecureRandom.getInstance("SHA1PRNG"); + } + + private TrustManager[] getTrustManagers() throws Exception { + TrustManagerFactory tmf = TrustManagerFactory + .getInstance(TrustManagerFactory.getDefaultAlgorithm()); + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + tmf.init(ks); + return tmf.getTrustManagers(); + } + + private KeyManager[] getKeyManagers() throws Exception { + KeyManagerFactory kmf = KeyManagerFactory + .getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(null, "password".toCharArray()); + return kmf.getKeyManagers(); + } } diff --git a/harmony-tests/src/test/resources/tests/resources/control_test/hyts_resource.properties b/harmony-tests/src/test/resources/tests/resources/control_test/hyts_resource.properties new file mode 100644 index 0000000000..eae054e84b --- /dev/null +++ b/harmony-tests/src/test/resources/tests/resources/control_test/hyts_resource.properties @@ -0,0 +1,3 @@ +property=resource +propertyInURLParent=valueInURLParent +
\ No newline at end of file diff --git a/harmony-tests/src/test/resources/tests/resources/control_test/hyts_resource_fr_FR.properties b/harmony-tests/src/test/resources/tests/resources/control_test/hyts_resource_fr_FR.properties new file mode 100644 index 0000000000..0ac2c73167 --- /dev/null +++ b/harmony-tests/src/test/resources/tests/resources/control_test/hyts_resource_fr_FR.properties @@ -0,0 +1,3 @@ +property=fr_FR_resource +propertyInFRFR=valueInFRFR +
\ No newline at end of file diff --git a/json/src/main/java/org/json/JSONArray.java b/json/src/main/java/org/json/JSONArray.java index 5e758d73bd..df0b2437cd 100644 --- a/json/src/main/java/org/json/JSONArray.java +++ b/json/src/main/java/org/json/JSONArray.java @@ -16,7 +16,7 @@ package org.json; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; diff --git a/json/src/main/java/org/json/JSONObject.java b/json/src/main/java/org/json/JSONObject.java index 0565b25c12..40d15bbc31 100644 --- a/json/src/main/java/org/json/JSONObject.java +++ b/json/src/main/java/org/json/JSONObject.java @@ -16,7 +16,8 @@ package org.json; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; + import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; diff --git a/json/src/main/java/org/json/JSONStringer.java b/json/src/main/java/org/json/JSONStringer.java index 3d1738ce60..ef1b47c2fe 100644 --- a/json/src/main/java/org/json/JSONStringer.java +++ b/json/src/main/java/org/json/JSONStringer.java @@ -16,7 +16,7 @@ package org.json; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/json/src/main/java/org/json/JSONTokener.java b/json/src/main/java/org/json/JSONTokener.java index 55667b0ae6..6266860a3c 100644 --- a/json/src/main/java/org/json/JSONTokener.java +++ b/json/src/main/java/org/json/JSONTokener.java @@ -16,7 +16,7 @@ package org.json; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; // Note: this class was written without inspecting the non-free org.json sourcecode. diff --git a/json/src/main/java/org/json/TEST_MAPPING b/json/src/main/java/org/json/TEST_MAPPING new file mode 100644 index 0000000000..22c9a265ed --- /dev/null +++ b/json/src/main/java/org/json/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.org.json" + } + ] + } + ] +}
\ No newline at end of file diff --git a/libart/src/main/java/dalvik/system/ClassExt.java b/libart/src/main/java/dalvik/system/ClassExt.java index 9180d96c38..e52303536d 100644 --- a/libart/src/main/java/dalvik/system/ClassExt.java +++ b/libart/src/main/java/dalvik/system/ClassExt.java @@ -27,6 +27,28 @@ package dalvik.system; */ public final class ClassExt { /** + * A Pointer-sized-array of instance jfieldIDs in the same order as the ifields_ array. + * The jfieldID is associated with the ArtField at the corresonding index in the ifields_ array. + */ + private Object instanceJfieldIDs; + + /** + * A Pointer-sized-array of jmethodIDS in the same order as the methods_ + * array. The jmethodID is associated with the ArtField at the corresonding + * index in the methods_ array. + */ + private Object jmethodIDs; + + /** + * If the class has undergone structural redefinition, the now obsolete class object. + * + * Needed to ensure that the class isn't unloaded before its jit code is. Normally this is + * handled by the classloader but since the class is now obsolete it's no longer held live + * there and instead we must do so manually. This class should not be used for anything. + */ + private Class<?> obsoleteClass; + + /** * An array of all obsolete DexCache objects that are needed for obsolete methods. * * These entries are associated with the obsolete ArtMethod pointers at the same indexes in the @@ -63,6 +85,12 @@ public final class ClassExt { private Object originalDexFile; /** + * A Pointer-sized-array of static jfieldIDs in the same order as the sfields_ array. + * The jfieldID is associated with the ArtField at the corresonding index in the sfields_ array. + */ + private Object staticJfieldIDs; + + /** * If class verify fails, we must return same error on subsequent tries. We may store either * the class of the error, or an actual instance of Throwable here. * @@ -95,6 +123,7 @@ public final class ClassExt { */ private int preRedefineClassDefIndex; + /** * Private constructor. * diff --git a/libart/src/main/java/dalvik/system/TEST_MAPPING b/libart/src/main/java/dalvik/system/TEST_MAPPING new file mode 100644 index 0000000000..f9e6606634 --- /dev/null +++ b/libart/src/main/java/dalvik/system/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "imports": [ + { + "path": "libcore/dalvik/src/main/java/dalvik/system" + } + ] +}
\ No newline at end of file diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java index 7d70680298..321f4e3304 100644 --- a/libart/src/main/java/dalvik/system/VMRuntime.java +++ b/libart/src/main/java/dalvik/system/VMRuntime.java @@ -16,14 +16,21 @@ package dalvik.system; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.annotation.optimization.FastNative; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; +import android.compat.annotation.UnsupportedAppUsage; + +import dalvik.annotation.compat.VersionCodes; + import java.lang.ref.FinalizerReference; -import java.util.concurrent.atomic.AtomicInteger; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; +import dalvik.annotation.optimization.CriticalNative; +import dalvik.annotation.optimization.FastNative; + /** * Provides an interface to VM-global, Dalvik-specific features. * An application cannot create its own Runtime instance, and must obtain @@ -53,9 +60,34 @@ public final class VMRuntime { ABI_TO_INSTRUCTION_SET_MAP.put("x86", "x86"); ABI_TO_INSTRUCTION_SET_MAP.put("x86_64", "x86_64"); ABI_TO_INSTRUCTION_SET_MAP.put("arm64-v8a", "arm64"); + ABI_TO_INSTRUCTION_SET_MAP.put("arm64-v8a-hwasan", "arm64"); } /** + * Remove meta-reflection workaround for hidden api usage for apps targeting R+. This allowed + * apps to obtain references to blacklisted fields and methods through an extra layer of + * reflection. + */ + @ChangeId + @EnabledAfter(targetSdkVersion = VersionCodes.Q) + private static final long + PREVENT_META_REFLECTION_BLACKLIST_ACCESS = 142365358; // This is a bug id. + + /** + * Gating access to greylist-max-p APIs. + */ + @ChangeId + @EnabledAfter(targetSdkVersion = VersionCodes.P) + private static final long HIDE_MAXTARGETSDK_P_HIDDEN_APIS = 149997251; // This is a bug id. + + /** + * Gating access to greylist-max-q APIs. + */ + @ChangeId + @EnabledAfter(targetSdkVersion = VersionCodes.Q) + private static final long HIDE_MAXTARGETSDK_Q_HIDDEN_APIS = 149994052; // This is a bug id. + + /** * Interface for logging hidden API usage events. */ @libcore.api.CorePlatformApi @@ -148,6 +180,8 @@ public final class VMRuntime { // Allocations since last call to native layer. See notifyNativeAllocation(). private final AtomicInteger allocationCount = new AtomicInteger(0); + private long[] disabledCompatChanges = new long[0]; + /** * Prevents this class from being instantiated. */ @@ -272,12 +306,26 @@ public final class VMRuntime { * app starts to run, because it may change the VM's behavior in * dangerous ways. Defaults to {@link #SDK_VERSION_CUR_DEVELOPMENT}. */ + @UnsupportedAppUsage(maxTargetSdk=0, publicAlternatives="Use the {@code targetSdkVersion}" + +" attribute in the {@code uses-sdk} manifest tag instead.") @libcore.api.CorePlatformApi public synchronized void setTargetSdkVersion(int targetSdkVersion) { this.targetSdkVersion = targetSdkVersion; setTargetSdkVersionNative(this.targetSdkVersion); } + + /** + * Sets the disabled compat changes. Should only be called before the + * app starts to run, because it may change the VM's behavior in + * dangerous ways. Defaults to empty. + */ + @libcore.api.CorePlatformApi + public synchronized void setDisabledCompatChanges(long[] disabledCompatChanges) { + this.disabledCompatChanges = disabledCompatChanges; + setDisabledCompatChangesNative(this.disabledCompatChanges); + } + /** * Gets the target SDK version. See {@link #setTargetSdkVersion} for * special values. @@ -288,6 +336,7 @@ public final class VMRuntime { } private native void setTargetSdkVersionNative(int targetSdkVersion); + private native void setDisabledCompatChangesNative(long[] disabledCompatChanges); /** * This method exists for binary compatibility. It was part of a @@ -441,12 +490,6 @@ public final class VMRuntime { public native void clampGrowthLimit(); /** - * Returns true if either a Java debugger or native debugger is active. - */ - @FastNative - public native boolean isDebuggerActive(); - - /** * Returns true if native debugging is on. */ @libcore.api.CorePlatformApi @@ -631,6 +674,16 @@ public final class VMRuntime { } /** + * Prevent initialization of the caller's class if they are calling + * from their clinit method. This works because calling a JNI method + * from clinit causes the transactional runtime to abort the current + * transaction. + * @hide + */ + @CriticalNative + public static native void doNotInitializeInAot(); + + /** * Return false if the boot class path for the given instruction * set mapped from disk storage, versus being interpretted from * dirty pages in memory. @@ -649,6 +702,20 @@ public final class VMRuntime { public static native boolean hasBootImageSpaces(); /** + * Used to notify the runtime that boot completed. + */ + @libcore.api.CorePlatformApi + public static native void bootCompleted(); + + /** + * Used to notify the runtime to reset Jit counters. This is done for the boot image + * profiling configuration to avoid samples during class preloading. This helps avoid + * the regression from disabling class profiling. + */ + @libcore.api.CorePlatformApi + public static native void resetJitCounters(); + + /** * Returns the instruction set of the current runtime. */ @UnsupportedAppUsage @@ -702,4 +769,15 @@ public final class VMRuntime { */ @libcore.api.CorePlatformApi public static native void setProcessDataDirectory(String dataDir); + + /** + * Returns whether {@code encodedClassLoaderContext} is a valid encoded class loader context. + * A class loader context is an internal opaque format used by the runtime to encode the + * class loader hierarchy (including each ClassLoader's classpath) used to load a dex file. + * + * @return True if encodedClassLoaderContext is a non-null valid encoded class loader context. + * Throws NullPointerException if encodedClassLoaderContext is null. + */ + @libcore.api.CorePlatformApi + public static native boolean isValidClassLoaderContext(String encodedClassLoaderContext); } diff --git a/libart/src/main/java/dalvik/system/VMStack.java b/libart/src/main/java/dalvik/system/VMStack.java index d84fef677f..89ce215ad9 100644 --- a/libart/src/main/java/dalvik/system/VMStack.java +++ b/libart/src/main/java/dalvik/system/VMStack.java @@ -16,7 +16,8 @@ package dalvik.system; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; + import dalvik.annotation.optimization.FastNative; /** diff --git a/libart/src/main/java/java/lang/CaseMapper.java b/libart/src/main/java/java/lang/CaseMapper.java index 66d5030857..04eef0939a 100644 --- a/libart/src/main/java/java/lang/CaseMapper.java +++ b/libart/src/main/java/java/lang/CaseMapper.java @@ -17,8 +17,8 @@ package java.lang; import android.icu.text.Transliterator; +import com.android.icu.util.CaseMapperNative; import java.util.Locale; -import libcore.icu.ICU; /** * Performs case operations as described by http://unicode.org/reports/tr21/tr21-5.html. @@ -47,7 +47,7 @@ class CaseMapper { // Note that Greek isn't a particularly hard case for toLowerCase, only toUpperCase. String languageCode = locale.getLanguage(); if (languageCode.equals("tr") || languageCode.equals("az") || languageCode.equals("lt")) { - return ICU.toLowerCase(s, locale); + return CaseMapperNative.toLowerCase(s, locale); } char[] newValue = null; @@ -56,7 +56,7 @@ class CaseMapper { char newCh; if (ch == LATIN_CAPITAL_I_WITH_DOT || Character.isHighSurrogate(ch)) { // Punt these hard cases. - return ICU.toLowerCase(s, locale); + return CaseMapperNative.toLowerCase(s, locale); } else if (ch == GREEK_CAPITAL_SIGMA && isFinalSigma(s, i)) { newCh = GREEK_SMALL_FINAL_SIGMA; } else { @@ -146,7 +146,7 @@ class CaseMapper { public static String toUpperCase(Locale locale, String s, int count) { String languageCode = locale.getLanguage(); if (languageCode.equals("tr") || languageCode.equals("az") || languageCode.equals("lt")) { - return ICU.toUpperCase(s, locale); + return CaseMapperNative.toUpperCase(s, locale); } if (languageCode.equals("el")) { return EL_UPPER.get().transliterate(s); @@ -157,7 +157,7 @@ class CaseMapper { for (int o = 0; o < count; o++) { char ch = s.charAt(o); if (Character.isHighSurrogate(ch)) { - return ICU.toUpperCase(s, locale); + return CaseMapperNative.toUpperCase(s, locale); } int index = upperIndex(ch); if (index == -1) { diff --git a/libart/src/main/java/java/lang/Daemons.java b/libart/src/main/java/java/lang/Daemons.java index 7d0eca2f08..6e05cea805 100644 --- a/libart/src/main/java/java/lang/Daemons.java +++ b/libart/src/main/java/java/lang/Daemons.java @@ -16,19 +16,21 @@ package java.lang; +import android.compat.annotation.UnsupportedAppUsage; import android.system.Os; import android.system.OsConstants; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VMRuntime; + import java.lang.ref.FinalizerReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; import libcore.util.EmptyArray; +import dalvik.system.VMRuntime; +import dalvik.system.VMDebug; + /** * Calls Object.finalize() on objects in the finalizer reference queue. The VM * will abort if any finalize() call takes more than the maximum finalize time @@ -308,7 +310,7 @@ public final class Daemons { private boolean needToWork = true; // Only accessed in synchronized methods. - private long finalizerTimeoutMs = 0; // Lazily initialized. + private long finalizerTimeoutNs = 0; // Lazily initialized. FinalizerWatchdogDaemon() { super("FinalizerWatchdogDaemon"); @@ -321,7 +323,7 @@ public final class Daemons { continue; } final Object finalizing = waitForFinalization(); - if (finalizing != null && !VMRuntime.getRuntime().isDebuggerActive()) { + if (finalizing != null && !VMDebug.isDebuggerConnected()) { finalizerTimedOut(finalizing); break; } @@ -368,17 +370,22 @@ public final class Daemons { } /** - * Sleep for the given number of milliseconds. + * Sleep for the given number of nanoseconds, or slightly longer. * @return false if we were interrupted. */ - private boolean sleepForMillis(long durationMillis) { - long startMillis = System.currentTimeMillis(); + private boolean sleepForNanos(long durationNanos) { + // It's important to base this on nanoTime(), not currentTimeMillis(), since + // the former stops counting when the processor isn't running. + long startNanos = System.nanoTime(); while (true) { - long elapsedMillis = System.currentTimeMillis() - startMillis; - long sleepMillis = durationMillis - elapsedMillis; - if (sleepMillis <= 0) { + long elapsedNanos = System.nanoTime() - startNanos; + long sleepNanos = durationNanos - elapsedNanos; + if (sleepNanos <= 0) { return true; } + // Ensure the nano time is always rounded up to the next whole millisecond, + // ensuring the delay is >= the requested delay. + long sleepMillis = (sleepNanos + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI; try { Thread.sleep(sleepMillis); } catch (InterruptedException e) { @@ -401,14 +408,15 @@ public final class Daemons { * null. Only called from a single thread. */ private Object waitForFinalization() { - if (finalizerTimeoutMs == 0) { - finalizerTimeoutMs = VMRuntime.getRuntime().getFinalizerTimeoutMs(); + if (finalizerTimeoutNs == 0) { + finalizerTimeoutNs = + NANOS_PER_MILLI * VMRuntime.getRuntime().getFinalizerTimeoutMs(); // Temporary app backward compatibility. Remove eventually. - MAX_FINALIZE_NANOS = NANOS_PER_MILLI * finalizerTimeoutMs; + MAX_FINALIZE_NANOS = finalizerTimeoutNs; } long startCount = FinalizerDaemon.INSTANCE.progressCounter.get(); // Avoid remembering object being finalized, so as not to keep it alive. - if (!sleepForMillis(finalizerTimeoutMs)) { + if (!sleepForNanos(finalizerTimeoutNs)) { // Don't report possibly spurious timeout if we are interrupted. return null; } @@ -429,7 +437,7 @@ public final class Daemons { // just finished as we were timing out, in which case we may get null or a later // one. In this last case, we are very likely to discard it below. Object finalizing = FinalizerDaemon.INSTANCE.finalizingObject; - sleepForMillis(500); + sleepForNanos(500 * NANOS_PER_MILLI); // Recheck to make it even less likely we report the wrong finalizing object in // the case which a very slow finalization just finished as we were timing out. if (getNeedToWork() diff --git a/libart/src/main/java/java/lang/DexCache.java b/libart/src/main/java/java/lang/DexCache.java index 7c4a6edb71..e35a69d05c 100644 --- a/libart/src/main/java/java/lang/DexCache.java +++ b/libart/src/main/java/java/lang/DexCache.java @@ -32,13 +32,16 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import dalvik.annotation.optimization.FastNative; /** * A dex cache holds resolved copies of strings, fields, methods, and classes from the dexfile. */ final class DexCache { + /** The classloader this dex cache is for. */ + private ClassLoader classLoader; + /** The location of the associated dex file. */ private String location; @@ -125,4 +128,3 @@ final class DexCache { // Only created by the VM. private DexCache() {} } - diff --git a/libart/src/main/java/java/lang/TEST_MAPPING b/libart/src/main/java/java/lang/TEST_MAPPING new file mode 100644 index 0000000000..06575f3247 --- /dev/null +++ b/libart/src/main/java/java/lang/TEST_MAPPING @@ -0,0 +1,18 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "tests.java.lang" + }, + { + "include-filter": "org.apache.harmony.tests.java.lang" + }, + { + "include-filter": "libcore.java.lang" + } + ] + } + ] +}
\ No newline at end of file diff --git a/libart/src/main/java/java/lang/invoke/TEST_MAPPING b/libart/src/main/java/java/lang/invoke/TEST_MAPPING new file mode 100644 index 0000000000..2b6135dd91 --- /dev/null +++ b/libart/src/main/java/java/lang/invoke/TEST_MAPPING @@ -0,0 +1,20 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.lang.invoke" + } + ] + }, + { + "name": "CtsLibcoreOjTestCases", + "options": [ + { + "include-filter": "org.openjdk.tests.java.lang.invoke" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/android/compat/Compatibility.java b/luni/src/main/java/android/compat/Compatibility.java new file mode 100644 index 0000000000..9b4b1afe83 --- /dev/null +++ b/luni/src/main/java/android/compat/Compatibility.java @@ -0,0 +1,236 @@ +/* + * 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 + */ + +package android.compat; + +import android.compat.annotation.ChangeId; + +import libcore.api.CorePlatformApi; +import libcore.api.IntraCoreApi; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +/** + * Internal APIs for logging and gating compatibility changes. + * + * @see ChangeId + * + * @hide + */ +@CorePlatformApi +@IntraCoreApi +public final class Compatibility { + + private Compatibility() {} + + /** + * Reports that a compatibility change is affecting the current process now. + * + * <p>Calls to this method from a non-app process are ignored. This allows code implementing + * APIs that are used by apps and by other code (e.g. the system server) to report changes + * regardless of the process it's running in. When called in a non-app process, this method is + * a no-op. + * + * <p>Note: for changes that are gated using {@link #isChangeEnabled(long)}, you do not need to + * call this API directly. The change will be reported for you in the case that + * {@link #isChangeEnabled(long)} returns {@code true}. + * + * @param changeId The ID of the compatibility change taking effect. + */ + @CorePlatformApi + @IntraCoreApi + public static void reportChange(@ChangeId long changeId) { + sCallbacks.reportChange(changeId); + } + + /** + * Query if a given compatibility change is enabled for the current process. This method should + * only be called by code running inside a process of the affected app. + * + * <p>If this method returns {@code true}, the calling code should implement the compatibility + * change, resulting in differing behaviour compared to earlier releases. If this method returns + * {@code false}, the calling code should behave as it did in earlier releases. + * + * <p>When this method returns {@code true}, it will also report the change as + * {@link #reportChange(long)} would, so there is no need to call that method directly. + * + * @param changeId The ID of the compatibility change in question. + * @return {@code true} if the change is enabled for the current app. + */ + @CorePlatformApi + @IntraCoreApi + public static boolean isChangeEnabled(@ChangeId long changeId) { + return sCallbacks.isChangeEnabled(changeId); + } + + private volatile static Callbacks sCallbacks = new Callbacks(); + + @CorePlatformApi + public static void setCallbacks(Callbacks callbacks) { + sCallbacks = Objects.requireNonNull(callbacks); + } + + @CorePlatformApi + public static void setOverrides(ChangeConfig overrides) { + // Setting overrides twice in a row does not need to be supported because + // this method is only for enabling/disabling changes for the duration of + // a single test. + // In production, the app is restarted when changes get enabled or disabled, + // and the ChangeConfig is then set exactly once on that app process. + if (sCallbacks instanceof OverrideCallbacks) { + throw new IllegalStateException("setOverrides has already been called!"); + } + sCallbacks = new OverrideCallbacks(sCallbacks, overrides); + } + + @CorePlatformApi + public static void clearOverrides() { + if (!(sCallbacks instanceof OverrideCallbacks)) { + throw new IllegalStateException("No overrides set"); + } + sCallbacks = ((OverrideCallbacks) sCallbacks).delegate; + } + + /** + * Base class for compatibility API implementations. The default implementation logs a warning + * to logcat. + * + * This is provided as a class rather than an interface to allow new methods to be added without + * breaking @CorePlatformApi binary compatibility. + */ + @CorePlatformApi + public static class Callbacks { + @CorePlatformApi + protected Callbacks() { + } + @CorePlatformApi + protected void reportChange(long changeId) { + // Do not use String.format here (b/160912695) + System.logW("No Compatibility callbacks set! Reporting change " + changeId); + } + @CorePlatformApi + protected boolean isChangeEnabled(long changeId) { + // Do not use String.format here (b/160912695) + System.logW("No Compatibility callbacks set! Querying change " + changeId); + return true; + } + } + + @CorePlatformApi + @IntraCoreApi + public static final class ChangeConfig { + private final Set<Long> enabled; + private final Set<Long> disabled; + + public ChangeConfig(Set<Long> enabled, Set<Long> disabled) { + this.enabled = Objects.requireNonNull(enabled); + this.disabled = Objects.requireNonNull(disabled); + if (enabled.contains(null)) { + throw new NullPointerException(); + } + if (disabled.contains(null)) { + throw new NullPointerException(); + } + Set<Long> intersection = new HashSet<>(enabled); + intersection.retainAll(disabled); + if (!intersection.isEmpty()) { + throw new IllegalArgumentException("Cannot have changes " + intersection + + " enabled and disabled!"); + } + } + + public boolean isEmpty() { + return enabled.isEmpty() && disabled.isEmpty(); + } + + private static long[] toLongArray(Set<Long> values) { + long[] result = new long[values.size()]; + int idx = 0; + for (Long value: values) { + result[idx++] = value; + } + return result; + } + + public long[] forceEnabledChangesArray() { + return toLongArray(enabled); + } + + public long[] forceDisabledChangesArray() { + return toLongArray(disabled); + } + + public Set<Long> forceEnabledSet() { + return Collections.unmodifiableSet(enabled); + } + + public Set<Long> forceDisabledSet() { + return Collections.unmodifiableSet(disabled); + } + + public boolean isForceEnabled(long changeId) { + return enabled.contains(changeId); + } + + public boolean isForceDisabled(long changeId) { + return disabled.contains(changeId); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ChangeConfig)) { + return false; + } + ChangeConfig that = (ChangeConfig) o; + return enabled.equals(that.enabled) && + disabled.equals(that.disabled); + } + + @Override + public int hashCode() { + return Objects.hash(enabled, disabled); + } + + @Override + public String toString() { + return "ChangeConfig{enabled=" + enabled + ", disabled=" + disabled + '}'; + } + } + + private static class OverrideCallbacks extends Callbacks { + private final Callbacks delegate; + private final ChangeConfig changeConfig; + + private OverrideCallbacks(Callbacks delegate, ChangeConfig changeConfig) { + this.delegate = Objects.requireNonNull(delegate); + this.changeConfig = Objects.requireNonNull(changeConfig); + } + @Override + protected boolean isChangeEnabled(long changeId) { + if (changeConfig.isForceEnabled(changeId)) { + return true; + } + if (changeConfig.isForceDisabled(changeId)) { + return false; + } + return delegate.isChangeEnabled(changeId); + } + } +} diff --git a/luni/src/main/java/android/compat/TEST_MAPPING b/luni/src/main/java/android/compat/TEST_MAPPING new file mode 100644 index 0000000000..c8b07b41a1 --- /dev/null +++ b/luni/src/main/java/android/compat/TEST_MAPPING @@ -0,0 +1,17 @@ +{ + "presubmit": [ + // Unit tests for CoreCompatChangeRule + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.junit.util.compat" + } + ] + }, + // CTS test for CompatChanges System + { + "name": "CtsAppCompatHostTestCases" + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/android/system/ErrnoException.java b/luni/src/main/java/android/system/ErrnoException.java index 02a529fc02..a5edf4798e 100644 --- a/luni/src/main/java/android/system/ErrnoException.java +++ b/luni/src/main/java/android/system/ErrnoException.java @@ -19,6 +19,7 @@ package android.system; import java.io.IOException; import java.net.SocketException; import libcore.io.Libcore; +import libcore.util.NonNull; /** * A checked exception thrown when {@link Os} methods fail. This exception contains the native @@ -65,21 +66,26 @@ public final class ErrnoException extends Exception { } /** - * @hide - internal use only. + * Throws an {@link IOException} with a message based on {@link #getMessage()} and with this + * instance as the cause. + * + * <p>This method always terminates by throwing the exception. Callers can write + * {@code throw e.rethrowAsIOException()} to make that clear to the compiler. */ - @libcore.api.CorePlatformApi - public IOException rethrowAsIOException() throws IOException { + public @NonNull IOException rethrowAsIOException() throws IOException { IOException newException = new IOException(getMessage()); newException.initCause(this); throw newException; } /** - * @hide - internal use only. + * Throws a {@link SocketException} with a message based on {@link #getMessage()} and with this + * instance as the cause. + * + * <p>This method always terminates by throwing the exception. Callers can write + * {@code throw e.rethrowAsIOException()} to make that clear to the compiler. */ - @libcore.api.CorePlatformApi - @libcore.api.IntraCoreApi - public SocketException rethrowAsSocketException() throws SocketException { + public @NonNull SocketException rethrowAsSocketException() throws SocketException { throw new SocketException(getMessage(), this); } } diff --git a/luni/src/main/java/android/system/StructIcmpHdr.java b/luni/src/main/java/android/system/IcmpHeaders.java index 87ae679da6..2203d4095d 100644 --- a/luni/src/main/java/android/system/StructIcmpHdr.java +++ b/luni/src/main/java/android/system/IcmpHeaders.java @@ -19,22 +19,26 @@ package android.system; import static android.system.OsConstants.ICMP6_ECHO_REQUEST; import static android.system.OsConstants.ICMP_ECHO; +import java.io.FileDescriptor; +import java.net.SocketAddress; + /** - * Corresponds to C's {@code struct icmphdr} from linux/icmp.h and {@code struct icmp6hdr} from - * linux/icmpv6.h + * A utility class that can create ICMP header bytes corresponding to C's {@code struct icmphdr} + * from linux/icmp.h and {@code struct icmp6hdr} from linux/icmpv6.h. The bytes can be passed to + * methods like {@link Os#sendto(FileDescriptor, byte[], int, int, int, SocketAddress)}. * * @hide */ -public final class StructIcmpHdr { - private byte[] packet; +public final class IcmpHeaders { - private StructIcmpHdr() { - packet = new byte[8]; - } + private IcmpHeaders() {} - /* - * Echo or Echo Reply Message + /** + * Creates the header bytes for an {@link OsConstants#ICMP_ECHO} or + * {@link OsConstants#ICMP6_ECHO_REQUEST} message. Code, checksum and identifier are left as + * zeros. * + * <pre> * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -42,21 +46,16 @@ public final class StructIcmpHdr { * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Identifier | Sequence Number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Data ... - * +-+-+-+-+- + * </pre> */ - public static StructIcmpHdr IcmpEchoHdr(boolean ipv4, int seq) { - StructIcmpHdr hdr = new StructIcmpHdr(); - hdr.packet[0] = ipv4 ? (byte) ICMP_ECHO : (byte) ICMP6_ECHO_REQUEST; + public static byte[] createIcmpEchoHdr(boolean ipv4, int seq) { + byte[] bytes = new byte[8]; + bytes[0] = ipv4 ? (byte) ICMP_ECHO : (byte) ICMP6_ECHO_REQUEST; // packet[1]: Code is always zero. // packet[2,3]: Checksum is computed by kernel. // packet[4,5]: ID (= port) inserted by kernel. - hdr.packet[6] = (byte) (seq >> 8); - hdr.packet[7] = (byte) seq; - return hdr; - } - - public byte[] getBytes() { - return packet.clone(); + bytes[6] = (byte) (seq >> 8); + bytes[7] = (byte) seq; + return bytes; } } diff --git a/luni/src/main/java/android/system/Int32Ref.java b/luni/src/main/java/android/system/Int32Ref.java index 8f4a9496ef..c43c796229 100644 --- a/luni/src/main/java/android/system/Int32Ref.java +++ b/luni/src/main/java/android/system/Int32Ref.java @@ -16,7 +16,9 @@ package android.system; -import dalvik.annotation.compat.UnsupportedAppUsage; +import libcore.util.Objects; + +import android.compat.annotation.UnsupportedAppUsage; /** * @hide @@ -32,4 +34,8 @@ public class Int32Ref { public Int32Ref(int value) { this.value = value; } + + @Override public String toString() { + return Objects.toString(this); + } } diff --git a/luni/src/main/java/android/system/Int64Ref.java b/luni/src/main/java/android/system/Int64Ref.java index f42450d868..77edaf0876 100644 --- a/luni/src/main/java/android/system/Int64Ref.java +++ b/luni/src/main/java/android/system/Int64Ref.java @@ -16,6 +16,8 @@ package android.system; +import libcore.util.Objects; + /** * A signed 64bit integer reference suitable for passing to lower-level system calls. */ @@ -25,4 +27,8 @@ public class Int64Ref { public Int64Ref(long value) { this.value = value; } + + @Override public String toString() { + return Objects.toString(this); + } } diff --git a/luni/src/main/java/android/system/NetlinkSocketAddress.java b/luni/src/main/java/android/system/NetlinkSocketAddress.java index 64b0eabe7d..b4f6e74754 100644 --- a/luni/src/main/java/android/system/NetlinkSocketAddress.java +++ b/luni/src/main/java/android/system/NetlinkSocketAddress.java @@ -16,9 +16,10 @@ package android.system; -import dalvik.annotation.compat.UnsupportedAppUsage; -import libcore.util.Objects; +import android.compat.annotation.UnsupportedAppUsage; + import java.net.SocketAddress; +import libcore.util.Objects; /** * Netlink socket address. diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java index ded3b1c5ca..70fdce5c16 100644 --- a/luni/src/main/java/android/system/Os.java +++ b/luni/src/main/java/android/system/Os.java @@ -16,11 +16,7 @@ package android.system; -import dalvik.annotation.compat.UnsupportedAppUsage; - -import libcore.io.Libcore; -import libcore.util.NonNull; -import libcore.util.Nullable; +import android.compat.annotation.UnsupportedAppUsage; import java.io.FileDescriptor; import java.io.InterruptedIOException; @@ -29,6 +25,9 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; +import libcore.io.Libcore; +import libcore.util.NonNull; +import libcore.util.Nullable; /** * Access to low-level system functionality. Most of these are system calls. Most users will want @@ -152,12 +151,10 @@ public final class Os { */ public static void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException { Libcore.os.fchown(fd, uid, gid); } - /** @hide */ - public static int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException, InterruptedIOException { return Libcore.os.fcntlFlock(fd, cmd, arg); } - - /** @hide */ - @libcore.api.CorePlatformApi - public static int fcntlInt(FileDescriptor fd, int cmd, int arg) throws ErrnoException { return Libcore.os.fcntlInt(fd, cmd, arg); } + /** + * See <a href="http://man7.org/linux/man-pages/man2/fcntl.2.html">fcntl(2)</a>. + */ + public static int fcntlInt(@NonNull FileDescriptor fd, int cmd, int arg) throws ErrnoException { return Libcore.os.fcntlInt(fd, cmd, arg); } /** @hide */ public static int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException { return Libcore.os.fcntlVoid(fd, cmd); } @@ -365,6 +362,11 @@ public final class Os { public static StructStat lstat(String path) throws ErrnoException { return Libcore.os.lstat(path); } /** + * See <a href="http://man7.org/linux/man-pages/man2/memfd_create.2.html">memfd_create(2)</a>. + */ + public static @NonNull FileDescriptor memfd_create(@NonNull String name, int flags) throws ErrnoException { return Libcore.os.memfd_create(name, flags); } + + /** * See <a href="http://man7.org/linux/man-pages/man2/mincore.2.html">mincore(2)</a>. */ public static void mincore(long address, long byteCount, byte[] vector) throws ErrnoException { Libcore.os.mincore(address, byteCount, vector); } diff --git a/luni/src/main/java/android/system/OsConstants.java b/luni/src/main/java/android/system/OsConstants.java index a119ec7a46..1b0dc16d85 100644 --- a/luni/src/main/java/android/system/OsConstants.java +++ b/luni/src/main/java/android/system/OsConstants.java @@ -16,7 +16,7 @@ package android.system; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * Constants and helper functions for use with {@link Os}. @@ -130,6 +130,7 @@ public final class OsConstants { public static final int ARPHRD_ETHER = placeholder(); /** @hide */ @UnsupportedAppUsage + @libcore.api.CorePlatformApi public static final int ARPHRD_LOOPBACK = placeholder(); public static final int CAP_AUDIT_CONTROL = placeholder(); public static final int CAP_AUDIT_WRITE = placeholder(); @@ -358,6 +359,7 @@ public final class OsConstants { @libcore.api.CorePlatformApi public static final int _LINUX_CAPABILITY_VERSION_3 = placeholder(); public static final int MAP_FIXED = placeholder(); + public static final int MAP_ANONYMOUS = placeholder(); /** @hide */ @UnsupportedAppUsage @libcore.api.CorePlatformApi @@ -372,6 +374,7 @@ public final class OsConstants { public static final int MCAST_UNBLOCK_SOURCE = placeholder(); public static final int MCL_CURRENT = placeholder(); public static final int MCL_FUTURE = placeholder(); + public static final int MFD_CLOEXEC = placeholder(); public static final int MSG_CTRUNC = placeholder(); public static final int MSG_DONTROUTE = placeholder(); public static final int MSG_EOR = placeholder(); @@ -382,9 +385,6 @@ public final class OsConstants { public static final int MS_ASYNC = placeholder(); public static final int MS_INVALIDATE = placeholder(); public static final int MS_SYNC = placeholder(); - /** @hide */ - @UnsupportedAppUsage - @libcore.api.CorePlatformApi public static final int NETLINK_NETFILTER = placeholder(); public static final int NETLINK_ROUTE = placeholder(); /** diff --git a/luni/src/main/java/android/system/PacketSocketAddress.java b/luni/src/main/java/android/system/PacketSocketAddress.java index d3752268af..c3f15a6301 100644 --- a/luni/src/main/java/android/system/PacketSocketAddress.java +++ b/luni/src/main/java/android/system/PacketSocketAddress.java @@ -16,9 +16,10 @@ package android.system; -import dalvik.annotation.compat.UnsupportedAppUsage; -import libcore.util.Objects; +import android.compat.annotation.UnsupportedAppUsage; + import java.net.SocketAddress; +import libcore.util.Objects; /** * Packet socket address. @@ -29,24 +30,29 @@ import java.net.SocketAddress; */ @libcore.api.CorePlatformApi public final class PacketSocketAddress extends SocketAddress { - /** Protocol. An Ethernet protocol type, e.g., {@code ETH_P_IPV6}. */ - public short sll_protocol; + /** Protocol. An Ethernet protocol type, e.g., {@link OsConstants#ETH_P_IPV6}. */ + public final int sll_protocol; /** Interface index. */ - public int sll_ifindex; + public final int sll_ifindex; - /** ARP hardware type. One of the {@code ARPHRD_*} constants. */ - public short sll_hatype; + /** + * ARP hardware type. One of the {@code ARPHRD_*} constants, such as + * {@link OsConstants#ARPHRD_ETHER}. + */ + public final int sll_hatype; - /** Packet type. One of the {@code PACKET_*} constants, such as {@code PACKET_OTHERHOST}. */ - public byte sll_pkttype; + /** + * Packet type. + */ + public final int sll_pkttype; /** Hardware address. */ - public byte[] sll_addr; + public final byte[] sll_addr; - /** Constructs a new PacketSocketAddress. */ - public PacketSocketAddress(short sll_protocol, int sll_ifindex, - short sll_hatype, byte sll_pkttype, byte[] sll_addr) { + /** Constructs a new PacketSocketAddress. Used from native code. */ + public PacketSocketAddress(int sll_protocol, int sll_ifindex, int sll_hatype, int sll_pkttype, + byte[] sll_addr) { this.sll_protocol = sll_protocol; this.sll_ifindex = sll_ifindex; this.sll_hatype = sll_hatype; @@ -54,17 +60,38 @@ public final class PacketSocketAddress extends SocketAddress { this.sll_addr = sll_addr; } - /** Constructs a new PacketSocketAddress suitable for binding to. */ - @UnsupportedAppUsage + /** Constructs a new PacketSocketAddress with all the "in" parameters. */ @libcore.api.CorePlatformApi + public PacketSocketAddress(int sll_protocol, int sll_ifindex, byte[] sll_addr) { + this.sll_protocol = sll_protocol; + this.sll_ifindex = sll_ifindex; + this.sll_hatype = 0; + this.sll_pkttype = 0; + this.sll_addr = sll_addr; + } + + /** Legacy constructor. Kept for @UnsupportedAppUsage only. */ + @UnsupportedAppUsage public PacketSocketAddress(short sll_protocol, int sll_ifindex) { - this(sll_protocol, sll_ifindex, (short) 0, (byte) 0, null); + this.sll_protocol = sll_protocol; + this.sll_ifindex = sll_ifindex; + this.sll_hatype = 0; + this.sll_pkttype = 0; + this.sll_addr = null; } - /** Constructs a new PacketSocketAddress suitable for sending to. */ + /** Legacy constructor. Kept for @UnsupportedAppUsage only. */ @UnsupportedAppUsage - @libcore.api.CorePlatformApi public PacketSocketAddress(int sll_ifindex, byte[] sll_addr) { - this((short) 0, sll_ifindex, (short) 0, (byte) 0, sll_addr); + this.sll_protocol = 0; + this.sll_ifindex = sll_ifindex; + this.sll_hatype = 0; + this.sll_pkttype = 0; + this.sll_addr = sll_addr; + } + + @Override + public String toString() { + return Objects.toString(this); } } diff --git a/luni/src/main/java/android/system/StructFlock.java b/luni/src/main/java/android/system/StructFlock.java deleted file mode 100644 index 0d9342503f..0000000000 --- a/luni/src/main/java/android/system/StructFlock.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.system; - -import libcore.util.Objects; - -/** - * Information returned/taken by fcntl(2) F_GETFL and F_SETFL. Corresponds to C's - * {@code struct flock} from - * <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html"><fcntl.h></a> - * - * @hide - */ -public final class StructFlock { - /** The operation type, one of F_RDLCK, F_WRLCK, or F_UNLCK. */ - public short l_type; - - /** How to interpret l_start, one of SEEK_CUR, SEEK_END, SEEK_SET. */ - public short l_whence; - - /** Start offset. */ - public long l_start; /*off_t*/ - - /** Byte count to operate on. */ - public long l_len; /*off_t*/ - - /** Process blocking our lock (filled in by F_GETLK, otherwise unused). */ - public int l_pid; /*pid_t*/ - - @Override public String toString() { - return Objects.toString(this); - } -} diff --git a/luni/src/main/java/android/system/StructIfaddrs.java b/luni/src/main/java/android/system/StructIfaddrs.java index 7769f282a2..81d180abf5 100644 --- a/luni/src/main/java/android/system/StructIfaddrs.java +++ b/luni/src/main/java/android/system/StructIfaddrs.java @@ -16,6 +16,8 @@ package android.system; +import libcore.util.Objects; + import java.net.InetAddress; /** @@ -44,4 +46,8 @@ public final class StructIfaddrs { this.ifa_broadaddr = ifa_broadaddr; this.hwaddr = hwaddr; } + + @Override public String toString() { + return Objects.toString(this); + } } diff --git a/luni/src/main/java/android/system/TEST_MAPPING b/luni/src/main/java/android/system/TEST_MAPPING new file mode 100644 index 0000000000..66e8d786df --- /dev/null +++ b/luni/src/main/java/android/system/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.android.system" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/android/system/UnixSocketAddress.java b/luni/src/main/java/android/system/UnixSocketAddress.java index be689b36de..993cc5bb1f 100644 --- a/luni/src/main/java/android/system/UnixSocketAddress.java +++ b/luni/src/main/java/android/system/UnixSocketAddress.java @@ -35,7 +35,8 @@ public final class UnixSocketAddress extends SocketAddress { // 1) pathname: 0 < sun_path.length <= NAMED_PATH_LENGTH, sun_path[0] != 0. // 2) unnamed: sun_path = []. // 3) abstract: 0 < sun_path.length <= NAMED_PATH_LENGTH, sun_path[0] == 0. - private byte[] sun_path; + // Note that the array referenced by this field can be modified from JNI (libcore_io_Linux.cpp). + private final byte[] sun_path; /** This constructor is also used from JNI. */ private UnixSocketAddress(byte[] sun_path) { @@ -56,6 +57,9 @@ public final class UnixSocketAddress extends SocketAddress { /** * Creates a named, abstract AF_UNIX socket address. + * + * @throws NullPointerException if {@code name} is null + * @throws IllegalArgumentException if {@code name} is invalid, e.g. too long */ public static UnixSocketAddress createAbstract(String name) { byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8); @@ -67,6 +71,9 @@ public final class UnixSocketAddress extends SocketAddress { /** * Creates a named, filesystem AF_UNIX socket address. + * + * @throws NullPointerException if {@code name} is null + * @throws IllegalArgumentException if {@code name} is invalid, e.g. too long */ @libcore.api.CorePlatformApi public static UnixSocketAddress createFileSystem(String pathName) { diff --git a/luni/src/main/java/java/lang/TEST_MAPPING b/luni/src/main/java/java/lang/TEST_MAPPING new file mode 100644 index 0000000000..9374f92dae --- /dev/null +++ b/luni/src/main/java/java/lang/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "imports": [ + { + "path": "libcore/libart/src/main/java/java/lang" + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/java/lang/ref/FinalizerReference.java b/luni/src/main/java/java/lang/ref/FinalizerReference.java index 9589a9d0a6..037af4a25b 100644 --- a/luni/src/main/java/java/lang/ref/FinalizerReference.java +++ b/luni/src/main/java/java/lang/ref/FinalizerReference.java @@ -16,7 +16,7 @@ package java.lang.ref; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import dalvik.annotation.optimization.FastNative; /** diff --git a/luni/src/main/java/java/lang/ref/TEST_MAPPING b/luni/src/main/java/java/lang/ref/TEST_MAPPING new file mode 100644 index 0000000000..0614a12f8b --- /dev/null +++ b/luni/src/main/java/java/lang/ref/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.lang.ref" + }, + { + "include-filter": "org.apache.harmony.tests.java.lang.ref" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/java/math/BigInteger.java b/luni/src/main/java/java/math/BigInteger.java index f7c0be2034..b96fdb2f7d 100644 --- a/luni/src/main/java/java/math/BigInteger.java +++ b/luni/src/main/java/java/math/BigInteger.java @@ -885,6 +885,26 @@ public class BigInteger extends Number * @throws NullPointerException if {@code value == null}. */ @NonNull public BigInteger gcd(@NonNull BigInteger value) { + // First optimize the case in which the two arguments have very different + // length. + int thisLen = bitLength(); + int valueLen = value.bitLength(); + final int gcdDirectRatio = 16; + if (thisLen > gcdDirectRatio * valueLen) { + // A division-based step reduces the length of this by a factor of at + // least gcdDirectRatio, thus ensuring that a division-based step will + // easily pay for itself. + if (value.signum() == 0) { + return this.abs(); + } + return value.gcd(this.mod(value.abs())); + } else if (valueLen > gcdDirectRatio * thisLen) { + if (signum() == 0) { + return value.abs(); + } + return this.gcd(value.mod(this.abs())); + } + return new BigInteger(BigInt.gcd(getBigInt(), value.getBigInt())); } diff --git a/luni/src/main/java/java/math/TEST_MAPPING b/luni/src/main/java/java/math/TEST_MAPPING new file mode 100644 index 0000000000..1038858691 --- /dev/null +++ b/luni/src/main/java/java/math/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.java.math" + }, + { + "include-filter": "libcore.java.math" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/java/net/AddressCache.java b/luni/src/main/java/java/net/AddressCache.java index ac5a029247..3026923179 100644 --- a/luni/src/main/java/java/net/AddressCache.java +++ b/luni/src/main/java/java/net/AddressCache.java @@ -16,7 +16,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import libcore.util.BasicLruCache; /** diff --git a/luni/src/main/java/java/net/DefaultFileNameMap.java b/luni/src/main/java/java/net/DefaultFileNameMap.java index 6222d7576a..da67d14c00 100644 --- a/luni/src/main/java/java/net/DefaultFileNameMap.java +++ b/luni/src/main/java/java/net/DefaultFileNameMap.java @@ -16,27 +16,40 @@ package java.net; -import java.util.Locale; -import libcore.net.MimeUtils; +import libcore.content.type.MimeMap; /** - * Implements {@link FileNameMap} in terms of {@link libcore.net.MimeUtils}. + * Implements {@link FileNameMap} in terms of {@link MimeMap}. */ class DefaultFileNameMap implements FileNameMap { + public String getContentTypeFor(String filename) { - if (filename.endsWith("/")) { - // a directory, return html - return MimeUtils.guessMimeTypeFromExtension("html"); + int fragmentIndex = filename.indexOf('#'); + if (fragmentIndex >= 0) { + filename = filename.substring(0, fragmentIndex); } - int lastCharInExtension = filename.lastIndexOf('#'); - if (lastCharInExtension < 0) { - lastCharInExtension = filename.length(); + if (filename.endsWith("/")) { // a directory + return "text/html"; } - int firstCharInExtension = filename.lastIndexOf('.') + 1; - String ext = ""; - if (firstCharInExtension > filename.lastIndexOf('/')) { - ext = filename.substring(firstCharInExtension, lastCharInExtension); + + int slashIndex = filename.lastIndexOf('/'); + if (slashIndex >= 0) { + filename = filename.substring(slashIndex); } - return MimeUtils.guessMimeTypeFromExtension(ext); + + MimeMap mimeMap = MimeMap.getDefault(); + int dotIndex = -1; + do { + String ext = filename.substring(dotIndex + 1); + String result = mimeMap.guessMimeTypeFromExtension(ext); + if ((result != null) && + // Compat behavior: If there's a '/', then extension must not be the + // whole string. http://b/144977800 + (slashIndex < 0 || dotIndex >= 0)) { + return result; + } + dotIndex = filename.indexOf('.', dotIndex + 1); + } while (dotIndex >= 0); + return null; } } diff --git a/luni/src/main/java/java/net/TEST_MAPPING b/luni/src/main/java/java/net/TEST_MAPPING new file mode 100644 index 0000000000..3573294297 --- /dev/null +++ b/luni/src/main/java/java/net/TEST_MAPPING @@ -0,0 +1,29 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.net" + }, + { + "include-filter": "org.apache.harmony.luni.tests.internal.net.www.protocol.http" + }, + { + "include-filter": "org.apache.harmony.tests.java.net" + }, + { + "include-filter": "org.apache.harmony.luni.tests.java.net" + } + ] + }, + { + "name": "CtsLibcoreOjTestCases", + "options": [ + { + "include-filter": "test.java.net" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/java/nio/NIOAccess.java b/luni/src/main/java/java/nio/NIOAccess.java index 7a07e3d307..734537980f 100644 --- a/luni/src/main/java/java/nio/NIOAccess.java +++ b/luni/src/main/java/java/nio/NIOAccess.java @@ -16,13 +16,15 @@ package java.nio; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** - * This class is used via JNI by code in frameworks/base/. + * This class is used via JNI by code in frameworks/base/ and + * by the JniConstants cache in libnativehelper/. * @hide */ // @VisibleForTesting : was default +@libcore.api.CorePlatformApi public final class NIOAccess { /** @@ -46,7 +48,8 @@ public final class NIOAccess { * given Buffer, or null if the Buffer is not backed by a Java array. */ @UnsupportedAppUsage - static Object getBaseArray(Buffer b) { + @libcore.api.CorePlatformApi + public static Object getBaseArray(Buffer b) { return b.hasArray() ? b.array() : null; } @@ -58,7 +61,8 @@ public final class NIOAccess { * meaningful if getBaseArray() returns non-null. */ @UnsupportedAppUsage - static int getBaseArrayOffset(Buffer b) { + @libcore.api.CorePlatformApi + public static int getBaseArrayOffset(Buffer b) { return b.hasArray() ? ((b.arrayOffset() + b.position) << b._elementSizeShift) : 0; } } diff --git a/luni/src/main/java/java/nio/NioUtils.java b/luni/src/main/java/java/nio/NioUtils.java index 678382dd8d..aca91b0291 100644 --- a/luni/src/main/java/java/nio/NioUtils.java +++ b/luni/src/main/java/java/nio/NioUtils.java @@ -16,19 +16,19 @@ package java.nio; +import android.compat.annotation.UnsupportedAppUsage; + import java.io.Closeable; import java.io.FileDescriptor; -import java.io.IOException; -import java.nio.channels.ClosedChannelException; import java.nio.channels.FileChannel; -import java.util.Set; -import static android.system.OsConstants.*; -import dalvik.annotation.compat.UnsupportedAppUsage; -import sun.misc.Cleaner; -import sun.nio.ch.DirectBuffer; import sun.nio.ch.FileChannelImpl; +import static android.system.OsConstants.O_ACCMODE; +import static android.system.OsConstants.O_APPEND; +import static android.system.OsConstants.O_RDONLY; +import static android.system.OsConstants.O_WRONLY; + /** * @hide internal use only */ @@ -64,8 +64,8 @@ public final class NioUtils { * Helps bridge between io and nio. */ public static FileChannel newFileChannel(Closeable ioObject, FileDescriptor fd, int mode) { - boolean readable = (mode & (O_RDONLY | O_RDWR | O_SYNC)) != 0; - boolean writable = (mode & (O_WRONLY | O_RDWR | O_SYNC)) != 0; + boolean readable = (mode & O_ACCMODE) != O_WRONLY; + boolean writable = (mode & O_ACCMODE) != O_RDONLY; boolean append = (mode & O_APPEND) != 0; return FileChannelImpl.open(fd, null, readable, writable, append, ioObject); } diff --git a/luni/src/main/java/java/nio/TEST_MAPPING b/luni/src/main/java/java/nio/TEST_MAPPING new file mode 100644 index 0000000000..3fe450ed9f --- /dev/null +++ b/luni/src/main/java/java/nio/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.java.nio" + }, + { + "include-filter": "libcore.java.nio" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java b/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java deleted file mode 100644 index f695694e46..0000000000 --- a/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java +++ /dev/null @@ -1,215 +0,0 @@ -/** -******************************************************************************* -* Copyright (C) 1996-2006, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -* -******************************************************************************* -*/ - /** - * A JNI interface for ICU converters. - * - * - * @author Ram Viswanadha, IBM - */ -package java.nio.charset; - -import dalvik.annotation.optimization.ReachabilitySensitive; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import libcore.icu.ICU; -import libcore.icu.NativeConverter; -import libcore.util.EmptyArray; - -final class CharsetDecoderICU extends CharsetDecoder { - private static final int MAX_CHARS_PER_BYTE = 2; - - private static final int INPUT_OFFSET = 0; - private static final int OUTPUT_OFFSET = 1; - private static final int INVALID_BYTE_COUNT = 2; - /* - * data[INPUT_OFFSET] = on input contains the start of input and on output the number of input bytes consumed - * data[OUTPUT_OFFSET] = on input contains the start of output and on output the number of output chars written - * data[INVALID_BYTE_COUNT] = number of invalid bytes - */ - private final int[] data = new int[3]; - - /* Handle to the ICU converter that is opened, cleaned up via NativeAllocationRegistry. */ - @ReachabilitySensitive - private long converterHandle = 0; - - private byte[] input = null; - private char[] output= null; - - private byte[] allocatedInput = null; - private char[] allocatedOutput = null; - - // These instance variables are always assigned in the methods before being used. This class - // is inherently thread-unsafe so we don't have to worry about synchronization. - private int inEnd; - private int outEnd; - - public static CharsetDecoderICU newInstance(Charset cs, String icuCanonicalName) { - // This complexity is necessary to ensure that even if the constructor, superclass - // constructor, or call to updateCallback throw, we still free the native peer. - long address = 0; - CharsetDecoderICU result; - try { - address = NativeConverter.openConverter(icuCanonicalName); - float averageCharsPerByte = NativeConverter.getAveCharsPerByte(address); - result = new CharsetDecoderICU(cs, averageCharsPerByte, address); - } catch (Throwable t) { - if (address != 0) { - NativeConverter.closeConverter(address); - } - throw t; - } - // An exception in registerConverter() will deallocate address: - NativeConverter.registerConverter(result, address); - result.updateCallback(); - return result; - } - - private CharsetDecoderICU(Charset cs, float averageCharsPerByte, long address) { - super(cs, averageCharsPerByte, MAX_CHARS_PER_BYTE); - this.converterHandle = address; - } - - @Override protected void implReplaceWith(String newReplacement) { - updateCallback(); - } - - @Override protected final void implOnMalformedInput(CodingErrorAction newAction) { - updateCallback(); - } - - @Override protected final void implOnUnmappableCharacter(CodingErrorAction newAction) { - updateCallback(); - } - - private void updateCallback() { - NativeConverter.setCallbackDecode(converterHandle, this); - } - - @Override protected void implReset() { - NativeConverter.resetByteToChar(converterHandle); - data[INPUT_OFFSET] = 0; - data[OUTPUT_OFFSET] = 0; - data[INVALID_BYTE_COUNT] = 0; - output = null; - input = null; - allocatedInput = null; - allocatedOutput = null; - inEnd = 0; - outEnd = 0; - } - - @Override protected final CoderResult implFlush(CharBuffer out) { - try { - // ICU needs to see an empty input. - input = EmptyArray.BYTE; - inEnd = 0; - data[INPUT_OFFSET] = 0; - - data[OUTPUT_OFFSET] = getArray(out); - data[INVALID_BYTE_COUNT] = 0; // Make sure we don't see earlier errors. - - int error = NativeConverter.decode(converterHandle, input, inEnd, output, outEnd, data, true); - if (ICU.U_FAILURE(error)) { - if (error == ICU.U_BUFFER_OVERFLOW_ERROR) { - return CoderResult.OVERFLOW; - } else if (error == ICU.U_TRUNCATED_CHAR_FOUND) { - if (data[INVALID_BYTE_COUNT] > 0) { - return CoderResult.malformedForLength(data[INVALID_BYTE_COUNT]); - } - } - } - return CoderResult.UNDERFLOW; - } finally { - setPosition(out); - implReset(); - } - } - - @Override protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) { - if (!in.hasRemaining()) { - return CoderResult.UNDERFLOW; - } - - data[INPUT_OFFSET] = getArray(in); - data[OUTPUT_OFFSET]= getArray(out); - - try { - int error = NativeConverter.decode(converterHandle, input, inEnd, output, outEnd, data, false); - if (ICU.U_FAILURE(error)) { - if (error == ICU.U_BUFFER_OVERFLOW_ERROR) { - return CoderResult.OVERFLOW; - } else if (error == ICU.U_INVALID_CHAR_FOUND) { - return CoderResult.unmappableForLength(data[INVALID_BYTE_COUNT]); - } else if (error == ICU.U_ILLEGAL_CHAR_FOUND) { - return CoderResult.malformedForLength(data[INVALID_BYTE_COUNT]); - } else { - throw new AssertionError(error); - } - } - // Decoding succeeded: give us more data. - return CoderResult.UNDERFLOW; - } finally { - setPosition(in); - setPosition(out); - } - } - - - private int getArray(CharBuffer out) { - if (out.hasArray()) { - output = out.array(); - outEnd = out.arrayOffset() + out.limit(); - return out.arrayOffset() + out.position(); - } else { - outEnd = out.remaining(); - if (allocatedOutput == null || outEnd > allocatedOutput.length) { - allocatedOutput = new char[outEnd]; - } - // The array's start position is 0. - output = allocatedOutput; - return 0; - } - } - - private int getArray(ByteBuffer in) { - if (in.hasArray()) { - input = in.array(); - inEnd = in.arrayOffset() + in.limit(); - return in.arrayOffset() + in.position(); - } else { - inEnd = in.remaining(); - if (allocatedInput == null || inEnd > allocatedInput.length) { - allocatedInput = new byte[inEnd]; - } - // Copy the input buffer into the allocated array. - int pos = in.position(); - in.get(allocatedInput, 0, inEnd); - in.position(pos); - // The array's start position is 0. - input = allocatedInput; - return 0; - } - } - - private void setPosition(CharBuffer out) { - if (out.hasArray()) { - out.position(out.position() + data[OUTPUT_OFFSET]); - } else { - out.put(output, 0, data[OUTPUT_OFFSET]); - } - // release reference to output array, which may not be ours - output = null; - } - - private void setPosition(ByteBuffer in) { - in.position(in.position() + data[INPUT_OFFSET]); - // release reference to input array, which may not be ours - input = null; - } -} diff --git a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java deleted file mode 100644 index c57aafd03f..0000000000 --- a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java +++ /dev/null @@ -1,253 +0,0 @@ -/** -******************************************************************************* -* Copyright (C) 1996-2006, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -* -******************************************************************************* -*/ -/** - * A JNI interface for ICU converters. - * - * - * @author Ram Viswanadha, IBM - */ -package java.nio.charset; - -import dalvik.annotation.optimization.ReachabilitySensitive; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.util.HashMap; -import java.util.Map; -import libcore.icu.ICU; -import libcore.icu.NativeConverter; -import libcore.util.EmptyArray; - -final class CharsetEncoderICU extends CharsetEncoder { - private static final Map<String, byte[]> DEFAULT_REPLACEMENTS = new HashMap<String, byte[]>(); - static { - // ICU has different default replacements to the RI in some cases. There are many - // additional cases, but this covers all the charsets that Java guarantees will be - // available, which is where compatibility seems most important. (The RI even uses - // the byte corresponding to '?' in ASCII as the replacement byte for charsets where that - // byte corresponds to an entirely different character.) - // It's odd that UTF-8 doesn't use U+FFFD, given that (unlike ISO-8859-1 and US-ASCII) it - // can represent it, but this is what the RI does... - byte[] questionMark = new byte[] { (byte) '?' }; - DEFAULT_REPLACEMENTS.put("UTF-8", questionMark); - DEFAULT_REPLACEMENTS.put("ISO-8859-1", questionMark); - DEFAULT_REPLACEMENTS.put("US-ASCII", questionMark); - } - - private static final int INPUT_OFFSET = 0; - private static final int OUTPUT_OFFSET = 1; - private static final int INVALID_CHAR_COUNT = 2; - /* - * data[INPUT_OFFSET] = on input contains the start of input and on output the number of input chars consumed - * data[OUTPUT_OFFSET] = on input contains the start of output and on output the number of output bytes written - * data[INVALID_CHARS] = number of invalid chars - */ - private int[] data = new int[3]; - - /* handle to the ICU converter that is opened */ - @ReachabilitySensitive - private final long converterHandle; - - private char[] input = null; - private byte[] output = null; - - private char[] allocatedInput = null; - private byte[] allocatedOutput = null; - - // These instance variables are always assigned in the methods before being used. This class - // is inherently thread-unsafe so we don't have to worry about synchronization. - private int inEnd; - private int outEnd; - - public static CharsetEncoderICU newInstance(Charset cs, String icuCanonicalName) { - // This complexity is necessary to ensure that even if the constructor, superclass - // constructor, or call to updateCallback throw, we still free the native peer. - long address = 0; - CharsetEncoderICU result; - try { - address = NativeConverter.openConverter(icuCanonicalName); - float averageBytesPerChar = NativeConverter.getAveBytesPerChar(address); - float maxBytesPerChar = NativeConverter.getMaxBytesPerChar(address); - byte[] replacement = makeReplacement(icuCanonicalName, address); - result = new CharsetEncoderICU(cs, averageBytesPerChar, maxBytesPerChar, replacement, address); - } catch (Throwable t) { - if (address != 0) { - NativeConverter.closeConverter(address); - } - throw t; - } - // An exception in registerConverter() will deallocate address: - NativeConverter.registerConverter(result, address); - result.updateCallback(); - return result; - } - - private static byte[] makeReplacement(String icuCanonicalName, long address) { - // We have our own map of RI-compatible default replacements (where ICU disagrees)... - byte[] replacement = DEFAULT_REPLACEMENTS.get(icuCanonicalName); - if (replacement != null) { - return replacement.clone(); - } - // ...but fall back to asking ICU. - return NativeConverter.getSubstitutionBytes(address); - } - - private CharsetEncoderICU(Charset cs, float averageBytesPerChar, float maxBytesPerChar, byte[] replacement, long address) { - super(cs, averageBytesPerChar, maxBytesPerChar, replacement, true); - // Our native peer needs to know what just happened... - this.converterHandle = address; - } - - @Override protected void implReplaceWith(byte[] newReplacement) { - updateCallback(); - } - - @Override protected void implOnMalformedInput(CodingErrorAction newAction) { - updateCallback(); - } - - @Override protected void implOnUnmappableCharacter(CodingErrorAction newAction) { - updateCallback(); - } - - private void updateCallback() { - NativeConverter.setCallbackEncode(converterHandle, this); - } - - @Override protected void implReset() { - NativeConverter.resetCharToByte(converterHandle); - data[INPUT_OFFSET] = 0; - data[OUTPUT_OFFSET] = 0; - data[INVALID_CHAR_COUNT] = 0; - output = null; - input = null; - allocatedInput = null; - allocatedOutput = null; - inEnd = 0; - outEnd = 0; - } - - @Override protected CoderResult implFlush(ByteBuffer out) { - try { - // ICU needs to see an empty input. - input = EmptyArray.CHAR; - inEnd = 0; - data[INPUT_OFFSET] = 0; - - data[OUTPUT_OFFSET] = getArray(out); - data[INVALID_CHAR_COUNT] = 0; // Make sure we don't see earlier errors. - - int error = NativeConverter.encode(converterHandle, input, inEnd, output, outEnd, data, true); - if (ICU.U_FAILURE(error)) { - if (error == ICU.U_BUFFER_OVERFLOW_ERROR) { - return CoderResult.OVERFLOW; - } else if (error == ICU.U_TRUNCATED_CHAR_FOUND) { - if (data[INVALID_CHAR_COUNT] > 0) { - return CoderResult.malformedForLength(data[INVALID_CHAR_COUNT]); - } - } - } - return CoderResult.UNDERFLOW; - } finally { - setPosition(out); - implReset(); - } - } - - @Override protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { - if (!in.hasRemaining()) { - return CoderResult.UNDERFLOW; - } - - data[INPUT_OFFSET] = getArray(in); - data[OUTPUT_OFFSET]= getArray(out); - data[INVALID_CHAR_COUNT] = 0; // Make sure we don't see earlier errors. - - try { - int error = NativeConverter.encode(converterHandle, input, inEnd, output, outEnd, data, false); - if (ICU.U_FAILURE(error)) { - if (error == ICU.U_BUFFER_OVERFLOW_ERROR) { - return CoderResult.OVERFLOW; - } else if (error == ICU.U_INVALID_CHAR_FOUND) { - return CoderResult.unmappableForLength(data[INVALID_CHAR_COUNT]); - } else if (error == ICU.U_ILLEGAL_CHAR_FOUND) { - return CoderResult.malformedForLength(data[INVALID_CHAR_COUNT]); - } else { - throw new AssertionError(error); - } - } - // Decoding succeeded: give us more data. - return CoderResult.UNDERFLOW; - } finally { - setPosition(in); - setPosition(out); - } - } - - private int getArray(ByteBuffer out) { - if (out.hasArray()) { - output = out.array(); - outEnd = out.arrayOffset() + out.limit(); - return out.arrayOffset() + out.position(); - } else { - outEnd = out.remaining(); - if (allocatedOutput == null || outEnd > allocatedOutput.length) { - allocatedOutput = new byte[outEnd]; - } - // The array's start position is 0 - output = allocatedOutput; - return 0; - } - } - - private int getArray(CharBuffer in) { - if (in.hasArray()) { - input = in.array(); - inEnd = in.arrayOffset() + in.limit(); - return in.arrayOffset() + in.position(); - } else { - inEnd = in.remaining(); - if (allocatedInput == null || inEnd > allocatedInput.length) { - allocatedInput = new char[inEnd]; - } - // Copy the input buffer into the allocated array. - int pos = in.position(); - in.get(allocatedInput, 0, inEnd); - in.position(pos); - // The array's start position is 0 - input = allocatedInput; - return 0; - } - } - - private void setPosition(ByteBuffer out) { - if (out.hasArray()) { - out.position(data[OUTPUT_OFFSET] - out.arrayOffset()); - } else { - out.put(output, 0, data[OUTPUT_OFFSET]); - } - // release reference to output array, which may not be ours - output = null; - } - - private void setPosition(CharBuffer in) { - int position = in.position() + data[INPUT_OFFSET] - data[INVALID_CHAR_COUNT]; - if (position < 0) { - // The calculated position might be negative if we encountered an - // invalid char that spanned input buffers. We adjust it to 0 in this case. - // - // NOTE: The API doesn't allow us to adjust the position of the previous - // input buffer. (Doing that wouldn't serve any useful purpose anyway.) - position = 0; - } - - in.position(position); - // release reference to input array, which may not be ours - input = null; - } -} diff --git a/luni/src/main/java/java/nio/charset/CharsetICU.java b/luni/src/main/java/java/nio/charset/CharsetICU.java deleted file mode 100644 index 63ffd3e0f4..0000000000 --- a/luni/src/main/java/java/nio/charset/CharsetICU.java +++ /dev/null @@ -1,41 +0,0 @@ -/** -******************************************************************************* -* Copyright (C) 1996-2005, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -* -******************************************************************************* -*/ - -package java.nio.charset; - -import libcore.icu.NativeConverter; - -/** - * This class is used from native code associated with {@link NativeConverter}. - */ -final class CharsetICU extends Charset { - private final String icuCanonicalName; - - protected CharsetICU(String canonicalName, String icuCanonName, String[] aliases) { - super(canonicalName, aliases); - icuCanonicalName = icuCanonName; - } - - public CharsetDecoder newDecoder() { - return CharsetDecoderICU.newInstance(this, icuCanonicalName); - } - - public CharsetEncoder newEncoder() { - return CharsetEncoderICU.newInstance(this, icuCanonicalName); - } - - public boolean contains(Charset cs) { - if (cs == null) { - return false; - } else if (this.equals(cs)) { - return true; - } - return NativeConverter.contains(this.name(), cs.name()); - } -} diff --git a/luni/src/main/java/java/nio/charset/ModifiedUtf8.java b/luni/src/main/java/java/nio/charset/ModifiedUtf8.java deleted file mode 100644 index 51638ee4e8..0000000000 --- a/luni/src/main/java/java/nio/charset/ModifiedUtf8.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package java.nio.charset; - -import java.io.UTFDataFormatException; - -/** - * Encoding and decoding methods for Modified UTF-8 - * - * <p>Modified UTF-8 is a simple variation of UTF-8 in which {@code \u0000} is encoded as - * 0xc0 0x80 . This avoids the presence of bytes 0 in the output. - * - * @hide - */ -public class ModifiedUtf8 { - - /** - * Count the number of bytes in the modified UTF-8 representation of {@code s}. - * - * <p>Additionally, if {@code shortLength} is true, throw a {@code UTFDataFormatException} if - * the size cannot be presented in an (unsigned) java short. - */ - public static long countBytes(String s, boolean shortLength) throws UTFDataFormatException { - long counter = 0; - int strLen = s.length(); - for (int i = 0; i < strLen; i++) { - char c = s.charAt(i); - if (c < '\u0080') { - counter++; - if (c == '\u0000') { - counter++; - } - } else if (c < '\u0800') { - counter += 2; - } else { - counter += 3; - } - } - // Allow up to the maximum value of an unsigned short (as the value is known to be - // unsigned. - if (shortLength && counter > 0xffff) { - throw new UTFDataFormatException( - "Size of the encoded string doesn't fit in two bytes"); - } - return counter; - } - - /** - * Encode {@code s} into {@code dst} starting at offset {@code offset}. - * - * <p>The output buffer is guaranteed to have enough space. - */ - public static void encode(byte[] dst, int offset, String s) { - int strLen = s.length(); - for (int i = 0; i < strLen; i++) { - char c = s.charAt(i); - if (c < '\u0080') { - if (c == 0) { - dst[offset++] = (byte) 0xc0; - dst[offset++] = (byte) 0x80; - } else { - dst[offset++] = (byte) c; - } - } else if (c < '\u0800') { - dst[offset++] = (byte) ((c >>> 6) | 0xc0); - dst[offset++] = (byte) ((c & 0x3f) | 0x80); - } else { - dst[offset++] = (byte) ((c >>> 12) | 0xe0); - dst[offset++] = (byte) (((c >>> 6) & 0x3f) | 0x80); - dst[offset++] = (byte) ((c & 0x3f) | 0x80); - } - } - } - - /** - * Encodes {@code s} into a buffer with the following format: - * - * <p>- the first two bytes of the buffer are the length of the modified-utf8 output - * (as a big endian short. A UTFDataFormatException is thrown if the encoded size cannot be - * represented as a short. - * - * <p>- the remainder of the buffer contains the modified-utf8 output (equivalent to - * {@code encode(buf, 2, s)}). - */ - public static byte[] encode(String s) throws UTFDataFormatException { - long size = countBytes(s, true); - byte[] output = new byte[(int) size + 2]; - encode(output, 2, s); - output[0] = (byte) (size >>> 8); - output[1] = (byte) size; - return output; - } - - /** - * Decodes {@code length} utf-8 bytes from {@code in} starting at offset {@code offset} to - * {@code out}, - * - * <p>A maximum of {@code length} chars are written to the output starting at offset 0. - * {@code out} is assumed to have enough space for the output (a standard - * {@code ArrayIndexOutOfBoundsException} is thrown otherwise). - * - * <p>If a ‘0’ byte is encountered, it is converted to U+0000. - */ - public static String decode(byte[] in, char[] out, int offset, int length) - throws UTFDataFormatException { - if (offset < 0 || length < 0) { - throw new IllegalArgumentException("Illegal arguments: offset " + offset - + ". Length: " + length); - } - int outputIndex = 0; - int limitIndex = offset + length; - while (offset < limitIndex) { - int i = in[offset] & 0xff; - offset++; - if (i < 0x80) { - out[outputIndex] = (char) i; - outputIndex++; - continue; - } - if (0xc0 <= i && i < 0xe0) { - // This branch covers the case 0 = 0xc080. - - // The result is: 5 least-significant bits of i + 6 l-s bits of next input byte. - i = (i & 0x1f) << 6; - if(offset == limitIndex) { - throw new UTFDataFormatException("unexpected end of input"); - } - // Include 6 least-significant bits of the input byte. - if ((in[offset] & 0xc0) != 0x80) { - throw new UTFDataFormatException("bad second byte at " + offset); - } - out[outputIndex] = (char) (i | (in[offset] & 0x3f)); - offset++; - outputIndex++; - } else if(i < 0xf0) { - // The result is: 5 least-significant bits of i + 6 l-s bits of next input byte - // + 6 l-s of next to next input byte. - i = (i & 0x1f) << 12; - // Make sure there are are at least two bytes left. - if (offset + 1 >= limitIndex) { - throw new UTFDataFormatException("unexpected end of input"); - } - // Include 6 least-significant bits of the input byte, with 6 bits of room - // for the next byte. - if ((in[offset] & 0xc0) != 0x80) { - throw new UTFDataFormatException("bad second byte at " + offset); - } - i = i | (in[offset] & 0x3f) << 6; - offset++; - // Include 6 least-significant bits of the input byte. - if ((in[offset] & 0xc0) != 0x80) { - throw new UTFDataFormatException("bad third byte at " + offset); - } - out[outputIndex] = (char) (i | (in[offset] & 0x3f)); - offset++; - outputIndex++; - } else { - throw new UTFDataFormatException("Invalid UTF8 byte " - + (int) i + " at position " + (offset - 1)); - } - } - return String.valueOf(out, 0, outputIndex); - } -} diff --git a/luni/src/main/java/javax/xml/TEST_MAPPING b/luni/src/main/java/javax/xml/TEST_MAPPING new file mode 100644 index 0000000000..d8c9759fae --- /dev/null +++ b/luni/src/main/java/javax/xml/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.xml" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/javax/xml/parsers/TEST_MAPPING b/luni/src/main/java/javax/xml/parsers/TEST_MAPPING new file mode 100644 index 0000000000..a630fe1baf --- /dev/null +++ b/luni/src/main/java/javax/xml/parsers/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.javax.xml.parsers" + }, + { + "include-filter": "libcore.javax.xml.parsers" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/libcore/content/type/MimeMap.java b/luni/src/main/java/libcore/content/type/MimeMap.java new file mode 100644 index 0000000000..51e792fdaf --- /dev/null +++ b/luni/src/main/java/libcore/content/type/MimeMap.java @@ -0,0 +1,408 @@ +/* + * 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. + */ + +package libcore.content.type; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Supplier; +import libcore.api.CorePlatformApi; +import libcore.util.NonNull; +import libcore.util.Nullable; + +/** + * Maps from MIME types to file extensions and back. + * + * @hide + */ +@libcore.api.CorePlatformApi +public final class MimeMap { + + @CorePlatformApi + public static Builder builder() { + return new Builder(); + } + + @CorePlatformApi + public Builder buildUpon() { + return new Builder(mimeToExt, extToMime); + } + + // Contain only lowercase, valid keys/values. + private final Map<String, String> mimeToExt; + private final Map<String, String> extToMime; + + /** + * A basic implementation of MimeMap used if a new default isn't explicitly + * {@link MimeMap#setDefaultSupplier(Supplier) installed}. Hard-codes enough + * mappings to satisfy libcore tests. Android framework code is expected to + * replace this implementation during runtime initialization. + */ + private static volatile MemoizingSupplier<@NonNull MimeMap> instanceSupplier = + new MemoizingSupplier<>( + () -> builder() + .put("application/pdf", "pdf") + .put("image/jpeg", "jpg") + .put("image/x-ms-bmp", "bmp") + .put("text/html", Arrays.asList("htm", "html")) + .put("text/plain", Arrays.asList("text", "txt")) + .put("text/x-java", "java") + .build()); + + private MimeMap(Map<String, String> mimeToExt, Map<String, String> extToMime) { + this.mimeToExt = Objects.requireNonNull(mimeToExt); + this.extToMime = Objects.requireNonNull(extToMime); + for (Map.Entry<String, String> entry : this.mimeToExt.entrySet()) { + checkValidMimeType(entry.getKey()); + checkValidExtension(entry.getValue()); + } + for (Map.Entry<String, String> entry : this.extToMime.entrySet()) { + checkValidExtension(entry.getKey()); + checkValidMimeType(entry.getValue()); + } + } + + /** + * @return The system's current default {@link MimeMap}. + */ + @libcore.api.CorePlatformApi + public static @NonNull MimeMap getDefault() { + return Objects.requireNonNull(instanceSupplier.get()); + } + + /** + * Sets the {@link Supplier} of the {@link #getDefault() default MimeMap + * instance} to be used from now on. + * + * {@code mimeMapSupplier.get()} will be invoked only the first time that + * {@link #getDefault()} is called after this method call; that + * {@link MimeMap} instance is memoized such that subsequent calls to + * {@link #getDefault()} without an intervening call to + * {@link #setDefaultSupplier(Supplier)} will return that same instance + * without consulting {@code mimeMapSupplier} a second time. + */ + @libcore.api.CorePlatformApi + public static void setDefaultSupplier(@NonNull Supplier<@NonNull MimeMap> mimeMapSupplier) { + instanceSupplier = new MemoizingSupplier<>(Objects.requireNonNull(mimeMapSupplier)); + } + + /** + * Returns whether the given case insensitive extension has a registered MIME type. + * + * @param extension A file extension without the leading '.' + * @return Whether a MIME type has been registered for the given case insensitive file + * extension. + */ + @libcore.api.CorePlatformApi + public final boolean hasExtension(@Nullable String extension) { + return guessMimeTypeFromExtension(extension) != null; + } + + /** + * Returns the MIME type for the given case insensitive file extension, or null + * if the extension isn't mapped to any. + * + * @param extension A file extension without the leading '.' + * @return The lower-case MIME type registered for the given case insensitive file extension, + * or null if there is none. + */ + @libcore.api.CorePlatformApi + public final @Nullable String guessMimeTypeFromExtension(@Nullable String extension) { + if (extension == null) { + return null; + } + extension = toLowerCase(extension); + return extToMime.get(extension); + } + + /** + * @param mimeType A MIME type (i.e. {@code "text/plain") + * @return Whether the given case insensitive MIME type is + * {@link #guessMimeTypeFromExtension(String) mapped} to a file extension. + */ + @libcore.api.CorePlatformApi + public final boolean hasMimeType(@Nullable String mimeType) { + return guessExtensionFromMimeType(mimeType) != null; + } + + /** + * Returns the registered extension for the given case insensitive MIME type. Note that some + * MIME types map to multiple extensions. This call will return the most + * common extension for the given MIME type. + * @param mimeType A MIME type (i.e. text/plain) + * @return The lower-case file extension (without the leading "." that has been registered for + * the given case insensitive MIME type, or null if there is none. + */ + @libcore.api.CorePlatformApi + public final @Nullable String guessExtensionFromMimeType(@Nullable String mimeType) { + if (mimeType == null) { + return null; + } + mimeType = toLowerCase(mimeType); + return mimeToExt.get(mimeType); + } + + /** + * Returns the set of MIME types that this {@link MimeMap} + * {@link #hasMimeType(String) maps to some extension}. Note that the + * reverse mapping might not exist. + * + * @hide + */ + @libcore.api.CorePlatformApi + public @NonNull Set<String> mimeTypes() { + return Collections.unmodifiableSet(mimeToExt.keySet()); + } + + /** + * Returns the set of extensions that this {@link MimeMap} + * {@link #hasExtension(String) maps to some MIME type}. Note that the + * reverse mapping might not exist. + * + * @hide + */ + @libcore.api.CorePlatformApi + public @NonNull Set<String> extensions() { + return Collections.unmodifiableSet(extToMime.keySet()); + } + + /** + * Returns the canonical (lowercase) form of the given extension or MIME type. + */ + private static @NonNull String toLowerCase(@NonNull String s) { + return s.toLowerCase(Locale.ROOT); + } + + private volatile int hashCode = 0; + + @Override + public int hashCode() { + if (hashCode == 0) { // potentially uninitialized + hashCode = mimeToExt.hashCode() + 31 * extToMime.hashCode(); + } + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof MimeMap)) { + return false; + } + MimeMap that = (MimeMap) obj; + if (hashCode() != that.hashCode()) { + return false; + } + return mimeToExt.equals(that.mimeToExt) && extToMime.equals(that.extToMime); + } + + @Override + public String toString() { + return "MimeMap[" + mimeToExt + ", " + extToMime + "]"; + } + + /** + * @hide + */ + @libcore.api.CorePlatformApi + public static final class Builder { + private final Map<String, String> mimeToExt; + private final Map<String, String> extToMime; + + /** + * Constructs a Builder that starts with an empty mapping. + */ + Builder() { + this.mimeToExt = new HashMap<>(); + this.extToMime = new HashMap<>(); + } + + /** + * Constructs a Builder that starts with the given mapping. + * @param mimeToExt + * @param extToMime + */ + Builder(Map<String, String> mimeToExt, Map<String, String> extToMime) { + this.mimeToExt = new HashMap<>(mimeToExt); + this.extToMime = new HashMap<>(extToMime); + } + + /** + * An element of a *mime.types file. + */ + static class Element { + final String mimeOrExt; + final boolean keepExisting; + + /** + * @param spec A MIME type or an extension, with an optional + * prefix of "?" (if not overriding an earlier value). + * @param isMimeSpec whether this Element denotes a MIME type (as opposed to an + * extension). + */ + private Element(String spec, boolean isMimeSpec) { + if (spec.startsWith("?")) { + this.keepExisting = true; + this.mimeOrExt = toLowerCase(spec.substring(1)); + } else { + this.keepExisting = false; + this.mimeOrExt = toLowerCase(spec); + } + if (isMimeSpec) { + checkValidMimeType(mimeOrExt); + } else { + checkValidExtension(mimeOrExt); + } + } + + public static Element ofMimeSpec(String s) { return new Element(s, true); } + public static Element ofExtensionSpec(String s) { return new Element(s, false); } + } + + private static String maybePut(Map<String, String> map, Element keyElement, String value) { + if (keyElement.keepExisting) { + return map.putIfAbsent(keyElement.mimeOrExt, value); + } else { + return map.put(keyElement.mimeOrExt, value); + } + } + + /** + * Puts the mapping {@quote mimeType -> first extension}, and also the mappings + * {@quote extension -> mimeType} for each given extension. + * + * The values passed to this function are carry an optional prefix of {@quote "?"} + * which is stripped off in any case before any such key/value is added to a mapping. + * The prefix {@quote "?"} controls whether the mapping <i>from></i> the corresponding + * value is added via {@link Map#putIfAbsent} semantics ({@quote "?"} + * present) vs. {@link Map#put} semantics ({@quote "?" absent}), + * + * For example, {@code put("text/html", "?htm", "html")} would add the following + * mappings: + * <ol> + * <li>MIME type "text/html" -> extension "htm", overwriting any earlier mapping + * from MIME type "text/html" that might already have existed.</li> + * <li>extension "htm" -> MIME type "text/html", but only if no earlier mapping + * for extension "htm" existed.</li> + * <li>extension "html" -> MIME type "text/html", overwriting any earlier mapping + * from extension "html" that might already have existed.</li> + * </ol> + * {@code put("?text/html", "?htm", "html")} would have the same effect except + * that an earlier mapping from MIME type {@code "text/html"} would not be + * overwritten. + * + * @param mimeSpec A MIME type carrying an optional prefix of {@code "?"}. If present, + * the {@code "?"} is stripped off and mapping for the resulting MIME + * type is only added to the map if no mapping had yet existed for that + * type. + * @param extensionSpecs The extensions from which to add mappings back to + * the {@code "?"} is stripped off and mapping for the resulting extension + * is only added to the map if no mapping had yet existed for that + * extension. + * If {@code extensionSpecs} is empty, then calling this method has no + * effect on the mapping that is being constructed. + * @throws IllegalArgumentException if {@code mimeSpec} or any of the {@code extensionSpecs} + * are invalid (null, empty, contain ' ', or '?' after an initial '?' has + * been stripped off). + * @return This builder. + */ + @CorePlatformApi + public Builder put(@NonNull String mimeSpec, @NonNull List<@NonNull String> extensionSpecs) + { + Element mimeElement = Element.ofMimeSpec(mimeSpec); // validate mimeSpec unconditionally + if (extensionSpecs.isEmpty()) { + return this; + } + Element firstExtensionElement = Element.ofExtensionSpec(extensionSpecs.get(0)); + maybePut(mimeToExt, mimeElement, firstExtensionElement.mimeOrExt); + maybePut(extToMime, firstExtensionElement, mimeElement.mimeOrExt); + for (String spec : extensionSpecs.subList(1, extensionSpecs.size())) { + Element element = Element.ofExtensionSpec(spec); + maybePut(extToMime, element, mimeElement.mimeOrExt); + } + return this; + } + + /** + * Convenience method. + * + * @hide + */ + public Builder put(@NonNull String mimeSpec, @NonNull String extensionSpec) { + return put(mimeSpec, Collections.singletonList(extensionSpec)); + } + + @CorePlatformApi + public MimeMap build() { + return new MimeMap(mimeToExt, extToMime); + } + + @Override + public String toString() { + return "MimeMap.Builder[" + mimeToExt + ", " + extToMime + "]"; + } + } + + private static boolean isValidMimeTypeOrExtension(String s) { + return s != null + && !s.isEmpty() + && s.indexOf('?') < 0 + && s.indexOf(' ') < 0 + && s.indexOf('\t') < 0 + && s.equals(toLowerCase(s)); + } + + static void checkValidMimeType(String s) { + if (!isValidMimeTypeOrExtension(s) || s.indexOf('/') < 0) { + throw new IllegalArgumentException("Invalid MIME type: " + s); + } + } + + static void checkValidExtension(String s) { + if (!isValidMimeTypeOrExtension(s) || s.indexOf('/') >= 0) { + throw new IllegalArgumentException("Invalid extension: " + s); + } + } + + private static final class MemoizingSupplier<T> implements Supplier<T> { + private volatile Supplier<T> mDelegate; + private volatile T mInstance; + private volatile boolean mInitialized = false; + + public MemoizingSupplier(Supplier<T> delegate) { + this.mDelegate = delegate; + } + + @Override + public T get() { + if (!mInitialized) { + synchronized (this) { + if (!mInitialized) { + mInstance = mDelegate.get(); + mDelegate = null; + mInitialized = true; + } + } + } + return mInstance; + } + } +} diff --git a/luni/src/main/java/libcore/content/type/TEST_MAPPING b/luni/src/main/java/libcore/content/type/TEST_MAPPING new file mode 100644 index 0000000000..712f4a287e --- /dev/null +++ b/luni/src/main/java/libcore/content/type/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.libcore.content.type" + } + ] + }, + { + "name": "CtsMimeMapTestCases" + } + ] +} diff --git a/luni/src/main/java/libcore/icu/DateIntervalFormat.java b/luni/src/main/java/libcore/icu/DateIntervalFormat.java index 9a4f9a0f6f..74aca081c0 100644 --- a/luni/src/main/java/libcore/icu/DateIntervalFormat.java +++ b/luni/src/main/java/libcore/icu/DateIntervalFormat.java @@ -16,10 +16,10 @@ package libcore.icu; +import android.compat.annotation.UnsupportedAppUsage; import android.icu.util.Calendar; import android.icu.util.ULocale; -import dalvik.annotation.compat.UnsupportedAppUsage; import java.text.FieldPosition; import java.util.TimeZone; import libcore.util.BasicLruCache; diff --git a/luni/src/main/java/libcore/icu/ICU.java b/luni/src/main/java/libcore/icu/ICU.java index d8d878dfd3..f6e5fed3ad 100644 --- a/luni/src/main/java/libcore/icu/ICU.java +++ b/luni/src/main/java/libcore/icu/ICU.java @@ -16,7 +16,9 @@ package libcore.icu; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; +import android.icu.util.ULocale; + import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -266,34 +268,6 @@ public final class ICU { return availableLocalesCache.clone(); } - public static Locale[] getAvailableBreakIteratorLocales() { - return localesFromStrings(getAvailableBreakIteratorLocalesNative()); - } - - public static Locale[] getAvailableCalendarLocales() { - return localesFromStrings(getAvailableCalendarLocalesNative()); - } - - public static Locale[] getAvailableCollatorLocales() { - return localesFromStrings(getAvailableCollatorLocalesNative()); - } - - public static Locale[] getAvailableDateFormatLocales() { - return localesFromStrings(getAvailableDateFormatLocalesNative()); - } - - public static Locale[] getAvailableDateFormatSymbolsLocales() { - return getAvailableDateFormatLocales(); - } - - public static Locale[] getAvailableDecimalFormatSymbolsLocales() { - return getAvailableNumberFormatLocales(); - } - - public static Locale[] getAvailableNumberFormatLocales() { - return localesFromStrings(getAvailableNumberFormatLocalesNative()); - } - @UnsupportedAppUsage @libcore.api.CorePlatformApi public static String getBestDateTimePattern(String skeleton, Locale locale) { @@ -355,115 +329,38 @@ public final class ICU { return result; } - /** - * Returns the version of the CLDR data in use, such as "22.1.1". - */ - public static native String getCldrVersion(); - - /** - * Returns the icu4c version in use, such as "50.1.1". - */ - public static native String getIcuVersion(); - - /** - * Returns the Unicode version our ICU supports, such as "6.2". - */ - public static native String getUnicodeVersion(); - - // --- Case mapping. - - public static String toLowerCase(String s, Locale locale) { - return toLowerCase(s, locale.toLanguageTag()); - } - - private static native String toLowerCase(String s, String languageTag); - - public static String toUpperCase(String s, Locale locale) { - return toUpperCase(s, locale.toLanguageTag()); - } - - private static native String toUpperCase(String s, String languageTag); - // --- Errors. - // Just the subset of error codes needed by CharsetDecoderICU/CharsetEncoderICU. - public static final int U_ZERO_ERROR = 0; - public static final int U_INVALID_CHAR_FOUND = 10; - public static final int U_TRUNCATED_CHAR_FOUND = 11; - public static final int U_ILLEGAL_CHAR_FOUND = 12; - public static final int U_BUFFER_OVERFLOW_ERROR = 15; - - public static boolean U_FAILURE(int error) { - return error > U_ZERO_ERROR; - } - // --- Native methods accessing ICU's database. - private static native String[] getAvailableBreakIteratorLocalesNative(); - private static native String[] getAvailableCalendarLocalesNative(); - private static native String[] getAvailableCollatorLocalesNative(); - private static native String[] getAvailableDateFormatLocalesNative(); private static native String[] getAvailableLocalesNative(); - private static native String[] getAvailableNumberFormatLocalesNative(); - public static native String[] getAvailableCurrencyCodes(); public static native String getCurrencyCode(String countryCode); - public static String getCurrencyDisplayName(Locale locale, String currencyCode) { - return getCurrencyDisplayName(locale.toLanguageTag(), currencyCode); - } - - private static native String getCurrencyDisplayName(String languageTag, String currencyCode); - - public static native int getCurrencyFractionDigits(String currencyCode); - public static native int getCurrencyNumericCode(String currencyCode); - - public static String getCurrencySymbol(Locale locale, String currencyCode) { - return getCurrencySymbol(locale.toLanguageTag(), currencyCode); - } - - private static native String getCurrencySymbol(String languageTag, String currencyCode); - - public static String getDisplayCountry(Locale targetLocale, Locale locale) { - return getDisplayCountryNative(targetLocale.toLanguageTag(), locale.toLanguageTag()); - } - - private static native String getDisplayCountryNative(String targetLanguageTag, String languageTag); - - public static String getDisplayLanguage(Locale targetLocale, Locale locale) { - return getDisplayLanguageNative(targetLocale.toLanguageTag(), locale.toLanguageTag()); - } - - private static native String getDisplayLanguageNative(String targetLanguageTag, String languageTag); - - public static String getDisplayVariant(Locale targetLocale, Locale locale) { - return getDisplayVariantNative(targetLocale.toLanguageTag(), locale.toLanguageTag()); - } - - private static native String getDisplayVariantNative(String targetLanguageTag, String languageTag); - - public static String getDisplayScript(Locale targetLocale, Locale locale) { - return getDisplayScriptNative(targetLocale.toLanguageTag(), locale.toLanguageTag()); - } - - private static native String getDisplayScriptNative(String targetLanguageTag, String languageTag); - public static native String getISO3Country(String languageTag); public static native String getISO3Language(String languageTag); + /** + * @deprecated Use {@link android.icu.util.ULocale#addLikelySubtags(ULocale)} instead. + * The method is only kept for @UnsupportedAppUsage. + */ @UnsupportedAppUsage - @libcore.api.CorePlatformApi + @Deprecated public static Locale addLikelySubtags(Locale locale) { - return Locale.forLanguageTag(addLikelySubtags(locale.toLanguageTag()).replace('_', '-')); + return ULocale.addLikelySubtags(ULocale.forLocale(locale)).toLocale(); } /** - * @deprecated use {@link #addLikelySubtags(java.util.Locale)} instead. + * @return ICU localeID + * @deprecated Use {@link android.icu.util.ULocale#addLikelySubtags(ULocale)} instead. + * The method is only kept for @UnsupportedAppUsage. */ @UnsupportedAppUsage @Deprecated - public static native String addLikelySubtags(String locale); + public static String addLikelySubtags(String locale) { + return ULocale.addLikelySubtags(new ULocale(locale)).getName(); + } /** * @deprecated use {@link java.util.Locale#getScript()} instead. This has been kept @@ -487,8 +384,4 @@ public final class ICU { * Returns a locale name, not a BCP-47 language tag. e.g. en_US not en-US. */ public static native String getDefaultLocale(); - - /** Returns the TZData version as reported by ICU4C. */ - @libcore.api.CorePlatformApi - public static native String getTZDataVersion(); } diff --git a/luni/src/main/java/libcore/icu/LocaleData.java b/luni/src/main/java/libcore/icu/LocaleData.java index cf3fec0115..12b978de15 100644 --- a/luni/src/main/java/libcore/icu/LocaleData.java +++ b/luni/src/main/java/libcore/icu/LocaleData.java @@ -16,11 +16,17 @@ package libcore.icu; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; +import android.compat.annotation.UnsupportedAppUsage; +import android.compat.Compatibility; import android.icu.impl.ICUData; import android.icu.impl.ICUResourceBundle; import android.icu.text.NumberingSystem; import android.icu.util.UResourceBundle; -import dalvik.annotation.compat.UnsupportedAppUsage; + +import dalvik.system.VMRuntime; + import java.text.DateFormat; import java.util.HashMap; import java.util.Locale; @@ -37,6 +43,44 @@ import libcore.util.Objects; */ @libcore.api.CorePlatformApi public final class LocaleData { + + /** + * @see #USE_REAL_ROOT_LOCALE + */ + private static final Locale LOCALE_EN_US_POSIX = new Locale("en", "US", "POSIX"); + + // In Android Q or before, when this class tries to load {@link Locale#ROOT} data, en_US_POSIX + // locale data is incorrectly loaded due to a bug b/159514442 (public bug b/159047832). + // + // This class used to pass "und" string as BCP47 language tag to our jni code, which then + // passes the string as as ICU Locale ID to ICU4C. ICU4C 63 or older version doesn't recognize + // "und" as a valid locale id, and fallback the default locale. The default locale is + // normally selected in the Locale picker in the Settings app by the user and set via + // frameworks. But this class statically cached the ROOT locale data before the + // default locale being set by framework, and without initialization, ICU4C uses en_US_POSIX + // as default locale. Thus, in Q or before, en_US_POSIX data is loaded. + // + // ICU version 64.1 resolved inconsistent behavior of + // "root", "und" and "" (empty) Locale ID which libcore previously relied on, and they are + // recognized correctly as {@link Locale#ROOT} since Android R. This ChangeId gated the change, + // and fallback to the old behavior by checking targetSdkVersion version. + // + // The below javadoc is shown in http://developer.android.com for consumption by app developers. + /** + * Since Android 11, formatter classes, e.g. java.text.SimpleDateFormat, no longer + * provide English data when Locale.ROOT format is requested. Please use + * Locale.ENGLISH to format in English. + * + * Note that Locale.ROOT is used as language/country neutral locale or fallback locale, + * and does not guarantee to represent English locale. + * + * This flag is only for documentation and can't be overridden by app. Please use + * {@code targetSdkVersion} to enable the new behavior. + */ + @ChangeId + @EnabledAfter(targetSdkVersion=29 /* Android Q */) + public static final long USE_REAL_ROOT_LOCALE = 159047832L; + // A cache for the locale-specific data. private static final HashMap<String, LocaleData> localeDataCache = new HashMap<String, LocaleData>(); static { @@ -170,6 +214,25 @@ public final class LocaleData { } /** + * Normally, this utility function is used by secondary cache above {@link LocaleData}, + * because the cache needs a correct key. + * @see #USE_REAL_ROOT_LOCALE + * @return a compatible locale for the bug b/159514442 + */ + public static Locale getCompatibleLocaleForBug159514442(Locale locale) { + if (Locale.ROOT.equals(locale)) { + int targetSdkVersion = VMRuntime.getRuntime().getTargetSdkVersion(); + // Don't use Compatibility.isChangeEnabled(USE_REAL_ROOT_LOCALE) because the app compat + // framework lives in libcore and can depend on this class via various format methods, + // e.g. String.format(). See b/160912695. + if (targetSdkVersion <= 29 /* Android Q */) { + locale = LOCALE_EN_US_POSIX; + } + } + return locale; + } + + /** * Returns a shared LocaleData for the given locale. */ @UnsupportedAppUsage @@ -179,6 +242,8 @@ public final class LocaleData { throw new NullPointerException("locale == null"); } + locale = getCompatibleLocaleForBug159514442(locale); + final String languageTag = locale.toLanguageTag(); synchronized (localeDataCache) { LocaleData localeData = localeDataCache.get(languageTag); diff --git a/luni/src/main/java/libcore/icu/NativeConverter.java b/luni/src/main/java/libcore/icu/NativeConverter.java deleted file mode 100644 index 956c7017ca..0000000000 --- a/luni/src/main/java/libcore/icu/NativeConverter.java +++ /dev/null @@ -1,82 +0,0 @@ -/** -******************************************************************************* -* Copyright (C) 1996-2006, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -* -******************************************************************************* -*/ - -package libcore.icu; - -import libcore.util.NativeAllocationRegistry; - -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CodingErrorAction; - -public final class NativeConverter { - private static final NativeAllocationRegistry registry = new NativeAllocationRegistry( - NativeConverter.class.getClassLoader(), getNativeFinalizer(), getNativeSize()); - - public static native int decode(long converterHandle, byte[] input, int inEnd, - char[] output, int outEnd, int[] data, boolean flush); - - public static native int encode(long converterHandle, char[] input, int inEnd, - byte[] output, int outEnd, int[] data, boolean flush); - - public static native long openConverter(String charsetName); - public static native void closeConverter(long converterHandle); - - public static void registerConverter(Object referrent, long converterHandle) { - registry.registerNativeAllocation(referrent, converterHandle); - } - - public static native void resetByteToChar(long converterHandle); - public static native void resetCharToByte(long converterHandle); - - public static native byte[] getSubstitutionBytes(long converterHandle); - - public static native int getMaxBytesPerChar(long converterHandle); - public static native int getMinBytesPerChar(long converterHandle); - public static native float getAveBytesPerChar(long converterHandle); - public static native float getAveCharsPerByte(long converterHandle); - - public static native boolean contains(String converterName1, String converterName2); - - public static native String[] getAvailableCharsetNames(); - public static native Charset charsetForName(String charsetName); - - // Translates from Java's enum to the magic numbers #defined in "NativeConverter.cpp". - private static int translateCodingErrorAction(CodingErrorAction action) { - if (action == CodingErrorAction.REPORT) { - return 0; - } else if (action == CodingErrorAction.IGNORE) { - return 1; - } else if (action == CodingErrorAction.REPLACE) { - return 2; - } else { - throw new AssertionError(); // Someone changed the enum. - } - } - - public static void setCallbackDecode(long converterHandle, CharsetDecoder decoder) { - setCallbackDecode(converterHandle, - translateCodingErrorAction(decoder.malformedInputAction()), - translateCodingErrorAction(decoder.unmappableCharacterAction()), - decoder.replacement()); - } - private static native void setCallbackDecode(long converterHandle, int onMalformedInput, int onUnmappableInput, String subChars); - - public static void setCallbackEncode(long converterHandle, CharsetEncoder encoder) { - setCallbackEncode(converterHandle, - translateCodingErrorAction(encoder.malformedInputAction()), - translateCodingErrorAction(encoder.unmappableCharacterAction()), - encoder.replacement()); - } - private static native void setCallbackEncode(long converterHandle, int onMalformedInput, int onUnmappableInput, byte[] subBytes); - - public static native long getNativeFinalizer(); - public static native long getNativeSize(); -} diff --git a/luni/src/main/java/libcore/icu/TEST_MAPPING b/luni/src/main/java/libcore/icu/TEST_MAPPING new file mode 100644 index 0000000000..f3a0de8714 --- /dev/null +++ b/luni/src/main/java/libcore/icu/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.libcore.icu" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/libcore/icu/TimeZoneNames.java b/luni/src/main/java/libcore/icu/TimeZoneNames.java index caeaefd163..ec0fb8e5be 100644 --- a/luni/src/main/java/libcore/icu/TimeZoneNames.java +++ b/luni/src/main/java/libcore/icu/TimeZoneNames.java @@ -16,7 +16,6 @@ package libcore.icu; -import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; @@ -24,7 +23,6 @@ import java.util.Locale; import java.util.TimeZone; import java.util.concurrent.TimeUnit; import libcore.util.BasicLruCache; -import libcore.timezone.ZoneInfoDB; /** * Provides access to ICU's time zone name data. @@ -36,17 +34,16 @@ public final class TimeZoneNames { /* * Offsets into the arrays returned by DateFormatSymbols.getZoneStrings. */ - public static final int OLSON_NAME = 0; - public static final int LONG_NAME = 1; - public static final int SHORT_NAME = 2; - public static final int LONG_NAME_DST = 3; - public static final int SHORT_NAME_DST = 4; - public static final int NAME_COUNT = 5; + private static final int OLSON_NAME = 0; + private static final int LONG_NAME = 1; + private static final int SHORT_NAME = 2; + private static final int LONG_NAME_DST = 3; + private static final int SHORT_NAME_DST = 4; + private static final int NAME_COUNT = 5; private static final ZoneStringsCache cachedZoneStrings = new ZoneStringsCache(); - /** @hide */ - public static class ZoneStringsCache extends BasicLruCache<Locale, String[][]> { + private static class ZoneStringsCache extends BasicLruCache<Locale, String[][]> { public ZoneStringsCache() { super(5); // Room for a handful of locales. } diff --git a/luni/src/main/java/libcore/internal/TEST_MAPPING b/luni/src/main/java/libcore/internal/TEST_MAPPING new file mode 100644 index 0000000000..3ddd13a8da --- /dev/null +++ b/luni/src/main/java/libcore/internal/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.libcore.internal" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/libcore/io/AsynchronousCloseMonitor.java b/luni/src/main/java/libcore/io/AsynchronousCloseMonitor.java index 76ef5e448f..49d71a0421 100644 --- a/luni/src/main/java/libcore/io/AsynchronousCloseMonitor.java +++ b/luni/src/main/java/libcore/io/AsynchronousCloseMonitor.java @@ -16,13 +16,21 @@ package libcore.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.io.FileDescriptor; +import libcore.api.IntraCoreApi; +/** + * Implements interruption of threads blocked in I/O system calls. + * + * @hide + */ +@IntraCoreApi public final class AsynchronousCloseMonitor { private AsynchronousCloseMonitor() { } @UnsupportedAppUsage + @IntraCoreApi public static native void signalBlockedThreads(FileDescriptor fd); } diff --git a/luni/src/main/java/libcore/io/BlockGuardOs.java b/luni/src/main/java/libcore/io/BlockGuardOs.java index bd95a93b8d..f3793d6ed2 100644 --- a/luni/src/main/java/libcore/io/BlockGuardOs.java +++ b/luni/src/main/java/libcore/io/BlockGuardOs.java @@ -16,6 +16,7 @@ package libcore.io; +import android.compat.annotation.UnsupportedAppUsage; import android.system.ErrnoException; import android.system.GaiException; import android.system.Int64Ref; @@ -25,9 +26,7 @@ import android.system.StructLinger; import android.system.StructPollfd; import android.system.StructStat; import android.system.StructStatVfs; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.BlockGuard; -import dalvik.system.SocketTagger; + import java.io.FileDescriptor; import java.io.InterruptedIOException; import java.net.InetAddress; @@ -36,6 +35,9 @@ import java.net.SocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; +import dalvik.system.BlockGuard; +import dalvik.system.SocketTagger; + import static android.system.OsConstants.*; /** diff --git a/luni/src/main/java/libcore/io/BufferIterator.java b/luni/src/main/java/libcore/io/BufferIterator.java index b7c5b38af2..fb97250912 100644 --- a/luni/src/main/java/libcore/io/BufferIterator.java +++ b/luni/src/main/java/libcore/io/BufferIterator.java @@ -16,7 +16,7 @@ package libcore.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * Iterates over big- or little-endian bytes. See {@link MemoryMappedFile#bigEndianIterator} and @@ -44,13 +44,13 @@ public abstract class BufferIterator { public abstract int pos(); /** - * Copies {@code byteCount} bytes from the current position into {@code dst}, starting at - * {@code dstOffset}, and advances the current position {@code byteCount} bytes. + * Copies {@code byteCount} bytes from the current position into {@code bytes}, starting at + * {@code arrayOffset}, and advances the current position {@code byteCount} bytes. * * @throws IndexOutOfBoundsException if the read / write would be outside of the buffer / array */ @UnsupportedAppUsage - public abstract void readByteArray(byte[] dst, int dstOffset, int byteCount); + public abstract void readByteArray(byte[] bytes, int arrayOffset, int byteCount); /** * Returns the byte at the current position, and advances the current position one byte. @@ -69,13 +69,21 @@ public abstract class BufferIterator { public abstract int readInt(); /** - * Copies {@code intCount} 32-bit ints from the current position into {@code dst}, starting at - * {@code dstOffset}, and advances the current position {@code 4 * intCount} bytes. + * Copies {@code intCount} 32-bit ints from the current position into {@code ints}, starting at + * {@code arrayOffset}, and advances the current position {@code 4 * intCount} bytes. * * @throws IndexOutOfBoundsException if the read / write would be outside of the buffer / array */ @UnsupportedAppUsage - public abstract void readIntArray(int[] dst, int dstOffset, int intCount); + public abstract void readIntArray(int[] ints, int arrayOffset, int intCount); + + /** + * Copies {@code longCount} 64-bit ints from the current position into {@code longs}, starting + * at {@code arrayOffset}, and advances the current position {@code 8 * longCount} bytes. + * + * @throws IndexOutOfBoundsException if the read / write would be outside of the buffer / array + */ + public abstract void readLongArray(long[] longs, int arrayOffset, int longCount); /** * Returns the 16-bit short at the current position, and advances the current position two bytes. diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java index 1c1dec22ee..f9fb2d43dd 100644 --- a/luni/src/main/java/libcore/io/ForwardingOs.java +++ b/luni/src/main/java/libcore/io/ForwardingOs.java @@ -23,7 +23,6 @@ import android.system.Int64Ref; import android.system.StructAddrinfo; import android.system.StructCapUserData; import android.system.StructCapUserHeader; -import android.system.StructFlock; import android.system.StructGroupReq; import android.system.StructIfaddrs; import android.system.StructLinger; @@ -36,7 +35,7 @@ import android.system.StructTimeval; import android.system.StructUcred; import android.system.StructUtsname; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.io.FileDescriptor; import java.io.InterruptedIOException; import java.net.InetAddress; @@ -101,7 +100,6 @@ public class ForwardingOs implements Os { public void execve(String filename, String[] argv, String[] envp) throws ErrnoException { os.execve(filename, argv, envp); } public void fchmod(FileDescriptor fd, int mode) throws ErrnoException { os.fchmod(fd, mode); } public void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException { os.fchown(fd, uid, gid); } - public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException, InterruptedIOException { return os.fcntlFlock(fd, cmd, arg); } public int fcntlInt(FileDescriptor fd, int cmd, int arg) throws ErrnoException { return os.fcntlInt(fd, cmd, arg); } public int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException { return os.fcntlVoid(fd, cmd); } public void fdatasync(FileDescriptor fd) throws ErrnoException { os.fdatasync(fd); } @@ -152,6 +150,7 @@ public class ForwardingOs implements Os { public long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException { return os.lseek(fd, offset, whence); } @UnsupportedAppUsage public StructStat lstat(String path) throws ErrnoException { return os.lstat(path); } + public FileDescriptor memfd_create(String name, int flags) throws ErrnoException { return os.memfd_create(name, flags); } public void mincore(long address, long byteCount, byte[] vector) throws ErrnoException { os.mincore(address, byteCount, vector); } @UnsupportedAppUsage public void mkdir(String path, int mode) throws ErrnoException { os.mkdir(path, mode); } diff --git a/luni/src/main/java/libcore/io/IoBridge.java b/luni/src/main/java/libcore/io/IoBridge.java index 06311767b8..0554d6da4d 100644 --- a/luni/src/main/java/libcore/io/IoBridge.java +++ b/luni/src/main/java/libcore/io/IoBridge.java @@ -16,6 +16,7 @@ package libcore.io; +import android.compat.annotation.UnsupportedAppUsage; import android.system.ErrnoException; import android.system.Int32Ref; import android.system.StructGroupReq; @@ -23,9 +24,6 @@ import android.system.StructLinger; import android.system.StructPollfd; import android.system.StructTimeval; -import libcore.util.ArrayUtils; - -import dalvik.annotation.compat.UnsupportedAppUsage; import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; @@ -46,6 +44,7 @@ import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.util.concurrent.TimeUnit; +import libcore.util.ArrayUtils; import static android.system.OsConstants.*; @@ -470,16 +469,13 @@ public final class IoBridge { /** * java.io only throws FileNotFoundException when opening files, regardless of what actually * went wrong. Additionally, java.io is more restrictive than POSIX when it comes to opening - * directories: POSIX says read-only is okay, but java.io doesn't even allow that. We also - * have an Android-specific hack to alter the default permissions. + * directories: POSIX says read-only is okay, but java.io doesn't even allow that. */ @libcore.api.CorePlatformApi public static FileDescriptor open(String path, int flags) throws FileNotFoundException { FileDescriptor fd = null; try { - // On Android, we don't want default permissions to allow global access. - int mode = ((flags & O_ACCMODE) == O_RDONLY) ? 0 : 0600; - fd = Libcore.os.open(path, flags, mode); + fd = Libcore.os.open(path, flags, 0666); // Posix open(2) fails with EISDIR only if you ask for write permission. // Java disallows reading directories too. if (S_ISDIR(Libcore.os.fstat(fd).st_mode)) { diff --git a/luni/src/main/java/libcore/io/IoUtils.java b/luni/src/main/java/libcore/io/IoUtils.java index 564393b547..4b4870b1b9 100644 --- a/luni/src/main/java/libcore/io/IoUtils.java +++ b/luni/src/main/java/libcore/io/IoUtils.java @@ -16,8 +16,10 @@ package libcore.io; +import android.compat.annotation.UnsupportedAppUsage; import android.system.ErrnoException; import android.system.StructStat; + import java.io.File; import java.io.FileDescriptor; import java.io.FileNotFoundException; @@ -27,10 +29,12 @@ import java.net.Socket; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Objects; - -import dalvik.annotation.compat.UnsupportedAppUsage; import libcore.util.NonNull; -import static android.system.OsConstants.*; + +import static android.system.OsConstants.F_GETFL; +import static android.system.OsConstants.F_SETFL; +import static android.system.OsConstants.O_NONBLOCK; +import static android.system.OsConstants.O_RDONLY; /** @hide */ @libcore.api.CorePlatformApi @@ -257,23 +261,6 @@ public final class IoUtils { } /** - * Creates a unique new temporary directory under "java.io.tmpdir". - * - * @deprecated Use {@link TestIoUtils#createTemporaryDirectory} instead. - */ - @libcore.api.CorePlatformApi - @Deprecated - public static File createTemporaryDirectory(String prefix) { - while (true) { - String candidateName = prefix + Math.randomIntInternal(); - File result = new File(System.getProperty("java.io.tmpdir"), candidateName); - if (result.mkdir()) { - return result; - } - } - } - - /** * Do not use. This is for System.loadLibrary use only. * * Checks whether {@code path} can be opened read-only. Similar to File.exists, but doesn't diff --git a/luni/src/main/java/libcore/io/Libcore.java b/luni/src/main/java/libcore/io/Libcore.java index 823d8668ac..29b5f7fda7 100644 --- a/luni/src/main/java/libcore/io/Libcore.java +++ b/luni/src/main/java/libcore/io/Libcore.java @@ -16,7 +16,7 @@ package libcore.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.util.Objects; /** @hide */ diff --git a/luni/src/main/java/libcore/io/Linux.java b/luni/src/main/java/libcore/io/Linux.java index 3766ac1642..74608d392a 100644 --- a/luni/src/main/java/libcore/io/Linux.java +++ b/luni/src/main/java/libcore/io/Linux.java @@ -23,7 +23,6 @@ import android.system.Int64Ref; import android.system.StructAddrinfo; import android.system.StructCapUserData; import android.system.StructCapUserHeader; -import android.system.StructFlock; import android.system.StructGroupReq; import android.system.StructIfaddrs; import android.system.StructLinger; @@ -76,7 +75,6 @@ public final class Linux implements Os { public native void execve(String filename, String[] argv, String[] envp) throws ErrnoException; public native void fchmod(FileDescriptor fd, int mode) throws ErrnoException; public native void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException; - public native int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException, InterruptedIOException; public native int fcntlInt(FileDescriptor fd, int cmd, int arg) throws ErrnoException; public native int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException; public native void fdatasync(FileDescriptor fd) throws ErrnoException; @@ -123,6 +121,7 @@ public final class Linux implements Os { public native String[] listxattr(String path) throws ErrnoException; public native long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException; public native StructStat lstat(String path) throws ErrnoException; + public native FileDescriptor memfd_create(String name, int flags) throws ErrnoException; public native void mincore(long address, long byteCount, byte[] vector) throws ErrnoException; public native void mkdir(String path, int mode) throws ErrnoException; public native void mkfifo(String path, int mode) throws ErrnoException; diff --git a/luni/src/main/java/libcore/io/Memory.java b/luni/src/main/java/libcore/io/Memory.java index 40423002a3..9e7f4ea5c8 100644 --- a/luni/src/main/java/libcore/io/Memory.java +++ b/luni/src/main/java/libcore/io/Memory.java @@ -17,13 +17,12 @@ package libcore.io; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.annotation.optimization.FastNative; -import java.io.FileDescriptor; -import java.io.IOException; -import java.nio.ByteBuffer; +import android.compat.annotation.UnsupportedAppUsage; + import java.nio.ByteOrder; +import dalvik.annotation.optimization.FastNative; + /** * Unsafe access to memory. * diff --git a/luni/src/main/java/libcore/io/MemoryMappedFile.java b/luni/src/main/java/libcore/io/MemoryMappedFile.java index 20b08e5779..5e003ea5e1 100644 --- a/luni/src/main/java/libcore/io/MemoryMappedFile.java +++ b/luni/src/main/java/libcore/io/MemoryMappedFile.java @@ -16,17 +16,15 @@ package libcore.io; +import android.compat.annotation.UnsupportedAppUsage; import android.system.ErrnoException; -import dalvik.annotation.compat.UnsupportedAppUsage; + import java.io.FileDescriptor; -import java.io.IOException; -import java.io.RandomAccessFile; import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.nio.NioUtils; -import libcore.io.Libcore; -import libcore.io.Memory; -import static android.system.OsConstants.*; + +import static android.system.OsConstants.MAP_SHARED; +import static android.system.OsConstants.O_RDONLY; +import static android.system.OsConstants.PROT_READ; /** * A memory-mapped file. Use {@link #mmapRO} to map a file, {@link #close} to unmap a file, diff --git a/luni/src/main/java/libcore/io/NioBufferIterator.java b/luni/src/main/java/libcore/io/NioBufferIterator.java index 263666d445..1554519a09 100644 --- a/luni/src/main/java/libcore/io/NioBufferIterator.java +++ b/luni/src/main/java/libcore/io/NioBufferIterator.java @@ -50,10 +50,12 @@ public final class NioBufferIterator extends BufferIterator { this.swap = swap; } + @Override public void seek(int offset) { position = offset; } + @Override public void skip(int byteCount) { position += byteCount; } @@ -63,14 +65,16 @@ public final class NioBufferIterator extends BufferIterator { return position; } - public void readByteArray(byte[] dst, int dstOffset, int byteCount) { - checkDstBounds(dstOffset, dst.length, byteCount); + @Override + public void readByteArray(byte[] bytes, int arrayOffset, int byteCount) { + checkArrayBounds(arrayOffset, bytes.length, byteCount); file.checkNotClosed(); checkReadBounds(position, length, byteCount); - Memory.peekByteArray(address + position, dst, dstOffset, byteCount); + Memory.peekByteArray(address + position, bytes, arrayOffset, byteCount); position += byteCount; } + @Override public byte readByte() { file.checkNotClosed(); checkReadBounds(position, length, 1); @@ -79,6 +83,7 @@ public final class NioBufferIterator extends BufferIterator { return result; } + @Override public int readInt() { file.checkNotClosed(); checkReadBounds(position, length, Integer.BYTES); @@ -87,15 +92,27 @@ public final class NioBufferIterator extends BufferIterator { return result; } - public void readIntArray(int[] dst, int dstOffset, int intCount) { - checkDstBounds(dstOffset, dst.length, intCount); + @Override + public void readIntArray(int[] ints, int arrayOffset, int intCount) { + checkArrayBounds(arrayOffset, ints.length, intCount); file.checkNotClosed(); final int byteCount = Integer.BYTES * intCount; checkReadBounds(position, length, byteCount); - Memory.peekIntArray(address + position, dst, dstOffset, intCount, swap); + Memory.peekIntArray(address + position, ints, arrayOffset, intCount, swap); position += byteCount; } + @Override + public void readLongArray(long[] longs, int arrayOffset, int longCount) { + checkArrayBounds(arrayOffset, longs.length, longCount); + file.checkNotClosed(); + final int byteCount = Long.BYTES * longCount; + checkReadBounds(position, length, byteCount); + Memory.peekLongArray(address + position, longs, arrayOffset, longCount, swap); + position += byteCount; + } + + @Override public short readShort() { file.checkNotClosed(); checkReadBounds(position, length, Short.BYTES); @@ -118,18 +135,18 @@ public final class NioBufferIterator extends BufferIterator { } } - private static void checkDstBounds(int dstOffset, int dstLength, int count) { - if (dstOffset < 0 || count < 0) { + private static void checkArrayBounds(int arrayOffset, int arrayLength, int count) { + if (arrayOffset < 0 || count < 0) { throw new IndexOutOfBoundsException( - "Invalid dst args: offset=" + dstLength + ", count=" + count); + "Invalid args: arrayOffset=" + arrayOffset + ", count=" + count); } - // Use of int here relies on dstLength being an int <= Integer.MAX_VALUE, which it has to + // Use of int here relies on arrayLength being an int <= Integer.MAX_VALUE, which it has to // be because it's an array length. - final int targetPos = dstOffset + count; - if (targetPos < 0 || targetPos > dstLength) { + final int targetPos = arrayOffset + count; + if (targetPos < 0 || targetPos > arrayLength) { throw new IndexOutOfBoundsException( - "Write outside range: dst.length=" + dstLength + ", offset=" - + dstOffset + ", count=" + count); + "Write outside range: arrayLength=" + arrayLength + ", arrayOffset=" + + arrayOffset + ", count=" + count); } } } diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java index e1ffa48ce7..4953186d45 100644 --- a/luni/src/main/java/libcore/io/Os.java +++ b/luni/src/main/java/libcore/io/Os.java @@ -23,7 +23,6 @@ import android.system.Int64Ref; import android.system.StructAddrinfo; import android.system.StructCapUserData; import android.system.StructCapUserHeader; -import android.system.StructFlock; import android.system.StructGroupReq; import android.system.StructIfaddrs; import android.system.StructLinger; @@ -36,7 +35,7 @@ import android.system.StructTimeval; import android.system.StructUcred; import android.system.StructUtsname; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.io.FileDescriptor; import java.io.InterruptedIOException; import java.net.InetAddress; @@ -76,7 +75,6 @@ public interface Os { public void execve(String filename, String[] argv, String[] envp) throws ErrnoException; public void fchmod(FileDescriptor fd, int mode) throws ErrnoException; public void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException; - public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException, InterruptedIOException; public int fcntlInt(FileDescriptor fd, int cmd, int arg) throws ErrnoException; public int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException; public void fdatasync(FileDescriptor fd) throws ErrnoException; @@ -125,6 +123,7 @@ public interface Os { public String[] listxattr(String path) throws ErrnoException; public long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException; public StructStat lstat(String path) throws ErrnoException; + public FileDescriptor memfd_create(String name, int flags) throws ErrnoException; public void mincore(long address, long byteCount, byte[] vector) throws ErrnoException; public void mkdir(String path, int mode) throws ErrnoException; public void mkfifo(String path, int mode) throws ErrnoException; diff --git a/luni/src/main/java/libcore/io/Streams.java b/luni/src/main/java/libcore/io/Streams.java index 427439915d..f83f5c1101 100644 --- a/luni/src/main/java/libcore/io/Streams.java +++ b/luni/src/main/java/libcore/io/Streams.java @@ -16,9 +16,8 @@ package libcore.io; -import libcore.util.ArrayUtils; +import android.compat.annotation.UnsupportedAppUsage; -import dalvik.annotation.compat.UnsupportedAppUsage; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.IOException; @@ -27,6 +26,7 @@ import java.io.OutputStream; import java.io.Reader; import java.io.StringWriter; import java.util.concurrent.atomic.AtomicReference; +import libcore.util.ArrayUtils; /** @hide */ @libcore.api.CorePlatformApi diff --git a/luni/src/main/java/libcore/io/TEST_MAPPING b/luni/src/main/java/libcore/io/TEST_MAPPING new file mode 100644 index 0000000000..1e25459b5f --- /dev/null +++ b/luni/src/main/java/libcore/io/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.libcore.io" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/libcore/net/MimeUtils.java b/luni/src/main/java/libcore/net/MimeUtils.java deleted file mode 100644 index 8cd0147c12..0000000000 --- a/luni/src/main/java/libcore/net/MimeUtils.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package libcore.net; - -import dalvik.annotation.compat.UnsupportedAppUsage; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.regex.Pattern; - -/** - * Utilities for dealing with MIME types. - * Used to implement java.net.URLConnection and android.webkit.MimeTypeMap. - * @hide - */ -@libcore.api.CorePlatformApi -public final class MimeUtils { - - private static final Pattern splitPattern = Pattern.compile("\\s+"); - - /** - * Note: These maps only contain lowercase keys/values, regarded as the - * {@link #canonicalize(String) canonical form}. - * - * <p>This is the case for both extensions and MIME types. The mime.types - * data file contains examples of mixed-case MIME types, but some applications - * use the lowercase version of these same types. RFC 2045 section 2 states - * that MIME types are case insensitive. - */ - private static final Map<String, String> mimeTypeToExtensionMap = new HashMap<>(); - private static final Map<String, String> extensionToMimeTypeMap = new HashMap<>(); - - static { - parseTypes("mime.types"); - parseTypes("android.mime.types"); - } - - private static void parseTypes(String resource) { - try (BufferedReader r = new BufferedReader( - new InputStreamReader(MimeUtils.class.getResourceAsStream(resource)))) { - String line; - while ((line = r.readLine()) != null) { - int commentPos = line.indexOf('#'); - if (commentPos >= 0) { - line = line.substring(0, commentPos); - } - line = line.trim(); - if (line.equals("")) { - continue; - } - - final String[] split = splitPattern.split(line); - final String mimeType = canonicalize(split[0]); - if (!allowedInMap(mimeType)) { - throw new IllegalArgumentException( - "Invalid mimeType " + mimeType + " in: " + line); - } - for (int i = 1; i < split.length; i++) { - String extension = canonicalize(split[i]); - if (!allowedInMap(extension)) { - throw new IllegalArgumentException( - "Invalid extension " + extension + " in: " + line); - } - - // Normally the first MIME type definition wins, and the - // last extension definition wins. However, a file can - // override a MIME type definition by adding the "!" suffix - // to an extension. - - if (extension.endsWith("!")) { - extension = extension.substring(0, extension.length() - 1); - - // Overriding MIME definition wins - mimeTypeToExtensionMap.put(mimeType, extension); - } else { - // First MIME definition wins - if (!mimeTypeToExtensionMap.containsKey(mimeType)) { - mimeTypeToExtensionMap.put(mimeType, extension); - } - } - - // Last extension definition wins - extensionToMimeTypeMap.put(extension, mimeType); - } - } - } catch (IOException e) { - throw new RuntimeException("Failed to parse " + resource, e); - } - } - - private MimeUtils() { - } - - /** - * Returns the canonical (lowercase) form of the given extension or MIME type. - */ - private static String canonicalize(String s) { - return s.toLowerCase(Locale.ROOT); - } - - /** - * Checks whether the given extension or MIME type might be valid and - * therefore may appear in the mimeType <-> extension maps. - */ - private static boolean allowedInMap(String s) { - return s != null && !s.isEmpty(); - } - - /** - * Returns true if the given case insensitive MIME type has an entry in the map. - * @param mimeType A MIME type (i.e. text/plain) - * @return True if a extension has been registered for - * the given case insensitive MIME type. - */ - @libcore.api.CorePlatformApi - public static boolean hasMimeType(String mimeType) { - return (guessExtensionFromMimeType(mimeType) != null); - } - - /** - * Returns the MIME type for the given case insensitive file extension. - * @param extension A file extension without the leading '.' - * @return The MIME type has been registered for - * the given case insensitive file extension or null if there is none. - */ - @UnsupportedAppUsage - @libcore.api.CorePlatformApi - public static String guessMimeTypeFromExtension(String extension) { - if (!allowedInMap(extension)) { - return null; - } - extension = canonicalize(extension); - return extensionToMimeTypeMap.get(extension); - } - - /** - * Returns true if the given case insensitive extension has a registered MIME type. - * @param extension A file extension without the leading '.' - * @return True if a MIME type has been registered for - * the given case insensitive file extension. - */ - @libcore.api.CorePlatformApi - public static boolean hasExtension(String extension) { - return (guessMimeTypeFromExtension(extension) != null); - } - - /** - * Returns the registered extension for the given case insensitive MIME type. Note that some - * MIME types map to multiple extensions. This call will return the most - * common extension for the given MIME type. - * @param mimeType A MIME type (i.e. text/plain) - * @return The extension has been registered for - * the given case insensitive MIME type or null if there is none. - */ - @UnsupportedAppUsage - @libcore.api.CorePlatformApi - public static String guessExtensionFromMimeType(String mimeType) { - if (!allowedInMap(mimeType)) { - return null; - } - mimeType = canonicalize(mimeType); - return mimeTypeToExtensionMap.get(mimeType); - } -} diff --git a/luni/src/main/java/libcore/net/NetworkSecurityPolicy.java b/luni/src/main/java/libcore/net/NetworkSecurityPolicy.java index 3a3a5d99a3..1ce58d9e48 100644 --- a/luni/src/main/java/libcore/net/NetworkSecurityPolicy.java +++ b/luni/src/main/java/libcore/net/NetworkSecurityPolicy.java @@ -16,7 +16,7 @@ package libcore.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * Network security policy for this process/application. diff --git a/luni/src/main/java/libcore/net/TEST_MAPPING b/luni/src/main/java/libcore/net/TEST_MAPPING new file mode 100644 index 0000000000..f31705e02e --- /dev/null +++ b/luni/src/main/java/libcore/net/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.libcore.net" + }, + { + "include-filter": "org.apache.harmony.tests.java.net" + } + ] + } + ] +} diff --git a/luni/src/main/java/libcore/net/android.mime.types b/luni/src/main/java/libcore/net/android.mime.types deleted file mode 100644 index 6332489a41..0000000000 --- a/luni/src/main/java/libcore/net/android.mime.types +++ /dev/null @@ -1,99 +0,0 @@ - -############################################################################### -# -# Android-specific MIME type mappings -# -# MIME types that Android has manually added or historically chosen to -# override, and which take precidence over any upstream mime.types. -# -############################################################################### - -application/epub+zip epub -application/pkix-cert cer -application/rss+xml rss -application/vnd.apple.mpegurl m3u8 -application/vnd.ms-pki.stl stl -application/vnd.ms-powerpoint pot -application/vnd.ms-wpl wpl -application/vnd.stardivision.impress sdp -application/vnd.stardivision.writer vor -application/vnd.youtube.yt yt -application/x-android-drm-fl fl -application/x-flac flac -application/x-font pcf -application/x-mpegurl m3u m3u8 -application/x-pem-file pem -application/x-pkcs12 p12 pfx -application/x-webarchive webarchive -application/x-webarchive-xml webarchivexml -# Note: We rely here on the fact that we're declaring this mapping before the -# line "text/xml xml" below, because we don't want to change the mapping from -# extension "xml" back to MIME type "text/xml". -application/x-wifi-config xml -application/x-x509-server-cert crt -application/x-x509-user-cert crt - -audio/3gpp 3gpp -audio/aac-adts aac -audio/imelody imy -audio/midi ota rtttl xmf -audio/mobile-xmf mxmf -audio/mp4 m4a -audio/mpegurl m3u -audio/sp-midi smf -audio/x-matroska mka -audio/x-pn-realaudio ra - -image/bmp bmp -image/heic heic -image/heic-sequence heics -image/heif heif hif -image/heif-sequence heifs -image/ico cur -image/webp webp -image/x-adobe-dng dng -image/x-fuji-raf raf -image/x-icon ico -image/x-nikon-nrw nrw -image/x-panasonic-rw2 rw2 -image/x-pentax-pef pef -image/x-samsung-srw srw -image/x-sony-arw arw - -text/comma-separated-values csv -text/plain diff po -text/rtf rtf -text/text phps -text/xml xml -text/x-vcard vcf - -video/3gpp2 3gpp2 3g2 -video/3gpp 3gpp -video/avi avi -video/m4v m4v -video/mp2p mpeg -video/mp2ts ts -video/MP2T m2ts MTS -video/x-webex wrf - -# Special cases where Android has a strong opinion about mappings, so we -# define them very last and use "!" to ensure that we force the mapping -# in both directions. -application/pgp-signature pgp! -application/x-x509-ca-cert crt! -audio/aac aac! -audio/basic snd! -audio/flac flac! -audio/midi rtx! -audio/mpeg mp3! m4a m4r -audio/x-mpegurl m3u8! m3u! -image/jpeg jpg! -image/x-ms-bmp bmp! -text/plain txt! -text/x-c++hdr hpp! -text/x-c++src cpp! -video/3gpp 3gpp! -video/mpeg mpeg! -video/quicktime mov! -video/vnd.youtube.yt yt -video/x-matroska mkv! diff --git a/luni/src/main/java/libcore/net/event/NetworkEventDispatcher.java b/luni/src/main/java/libcore/net/event/NetworkEventDispatcher.java index 5399e8966c..4c2aceeeac 100644 --- a/luni/src/main/java/libcore/net/event/NetworkEventDispatcher.java +++ b/luni/src/main/java/libcore/net/event/NetworkEventDispatcher.java @@ -16,7 +16,7 @@ package libcore.net.event; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; diff --git a/luni/src/main/java/libcore/net/event/NetworkEventListener.java b/luni/src/main/java/libcore/net/event/NetworkEventListener.java index d7d011b4e7..07c62c5ecd 100644 --- a/luni/src/main/java/libcore/net/event/NetworkEventListener.java +++ b/luni/src/main/java/libcore/net/event/NetworkEventListener.java @@ -16,7 +16,7 @@ package libcore.net.event; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * A base class for objects interested in network events. diff --git a/luni/src/main/java/libcore/net/event/TEST_MAPPING b/luni/src/main/java/libcore/net/event/TEST_MAPPING new file mode 100644 index 0000000000..866b320922 --- /dev/null +++ b/luni/src/main/java/libcore/net/event/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.libcore.net.event" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/libcore/net/http/HttpDate.java b/luni/src/main/java/libcore/net/http/HttpDate.java index c295503757..de05ceacb1 100644 --- a/luni/src/main/java/libcore/net/http/HttpDate.java +++ b/luni/src/main/java/libcore/net/http/HttpDate.java @@ -16,7 +16,7 @@ package libcore.net.http; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; diff --git a/luni/src/main/java/libcore/net/http/ResponseUtils.java b/luni/src/main/java/libcore/net/http/ResponseUtils.java deleted file mode 100644 index c892b53a33..0000000000 --- a/luni/src/main/java/libcore/net/http/ResponseUtils.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package libcore.net.http; - -import java.nio.charset.Charset; -import java.nio.charset.IllegalCharsetNameException; -import java.nio.charset.StandardCharsets; -import java.nio.charset.UnsupportedCharsetException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * @hide - */ -public class ResponseUtils { - /** - * Returns the response charset of a HTTP response based on the {@code Content-Type} of - * the response (see RFC 7230). If the {@code Content-Type} header is missing or invalid, - * the response is assumed to be encoded as {@code UTF-8}. Note that a charset usually - * makes sense only for {@code "text/plain"} and other "text based" responses. - * - * @throws IllegalCharsetNameException if the response specified charset is illegal. - * @throws UnsupportedCharsetException if the response specified charset is unsupported. - */ - public static Charset responseCharset(String contentTypeHeader) - throws IllegalCharsetNameException, UnsupportedCharsetException { - Charset responseCharset = StandardCharsets.UTF_8; - if (contentTypeHeader != null) { - Map<String, String> contentTypeParams = parseContentTypeParameters(contentTypeHeader); - String charsetParameter = contentTypeParams.get("charset"); - if (charsetParameter != null) { - responseCharset = Charset.forName(charsetParameter); - } - } - - return responseCharset; - } - - /** - * Parse content-type parameters. The format of this header is roughly : - * {@code type/subtype; param1=value1; param2=value2 ...} where each of the - * parameters are optional. Parsing is lenient, malformed parameters are ignored. - * - * Parameter keys & values are trimmed of whitespace and keys are converted to - * lower case. - */ - private static Map<String, String> parseContentTypeParameters(String contentTypeHeader) { - Map<String, String> parameters = Collections.EMPTY_MAP; - - String[] fields = contentTypeHeader.split(";"); - if (fields.length > 1) { - parameters = new HashMap<>(); - // Ignore the first element in the array (the type/subtype). - for (int i = 1; i < fields.length; ++i) { - final String parameter = fields[i]; - if (!parameter.isEmpty()) { - final String[] components = parameter.split("="); - if (components.length != 2) { - continue; - } - - final String key = components[0].trim().toLowerCase(); - final String value = components[1].trim(); - if (key.isEmpty() || value.isEmpty()) { - continue; - } - - parameters.put(key, value); - } - } - } - - return parameters; - } -} diff --git a/luni/src/main/java/libcore/net/mime.types b/luni/src/main/java/libcore/net/mime.types deleted file mode 100644 index dfa7a425fc..0000000000 --- a/luni/src/main/java/libcore/net/mime.types +++ /dev/null @@ -1,844 +0,0 @@ -############################################################################### -# -# MIME media types and the extensions that represent them. -# -# The format of this file is a media type on the left and zero or more -# filename extensions on the right. Programs using this file will map -# files ending with those extensions to the associated type. -# -# This file is part of the "mime-support" package. Please report a bug using -# the "reportbug" command of the "reportbug" package if you would like new -# types or extensions to be added. -# -# The reason that all types are managed by the mime-support package instead -# allowing individual packages to install types in much the same way as they -# add entries in to the mailcap file is so these types can be referenced by -# other programs (such as a web server) even if the specific support package -# for that type is not installed. -# -# Users can add their own types if they wish by creating a ".mime.types" -# file in their home directory. Definitions included there will take -# precedence over those listed here. -# -############################################################################### - - -application/activemessage -application/andrew-inset ez -application/annodex anx -application/applefile -application/atom+xml atom -application/atomcat+xml atomcat -application/atomicmail -application/atomserv+xml atomsrv -application/batch-SMTP -application/bbolin lin -application/beep+xml -application/cals-1840 -application/commonground -application/cu-seeme cu -application/cybercash -application/davmount+xml davmount -application/dca-rft -application/dec-dx -application/dicom dcm -application/docbook+xml -application/dsptype tsp -application/dvcs -application/ecmascript es -application/edi-consent -application/edi-x12 -application/edifact -application/epub+zip epub -application/eshop -application/font-sfnt otf ttf -application/font-tdpfr pfr -application/font-woff woff -application/futuresplash spl -application/ghostview -application/gzip gz -application/hta hta -application/http -application/hyperstudio -application/iges -application/index -application/index.cmd -application/index.obj -application/index.response -application/index.vnd -application/iotp -application/ipp -application/isup -application/java-archive jar -application/java-serialized-object ser -application/java-vm class -application/javascript js -application/json json -application/m3g m3g -application/mac-binhex40 hqx -application/mac-compactpro cpt -application/macwriteii -application/marc -application/mathematica nb nbp -application/mbox mbox -application/ms-tnef -application/msaccess mdb -application/msword doc dot -application/mxf mxf -application/news-message-id -application/news-transmission -application/ocsp-request -application/ocsp-response -application/octet-stream bin deploy msu msp -application/oda oda -application/oebps-package+xml opf -application/ogg ogx -application/onenote one onetoc2 onetmp onepkg -application/parityfec -application/pdf pdf -application/pgp-encrypted pgp -application/pgp-keys key -application/pgp-signature sig -application/pics-rules prf -application/pkcs10 -application/pkcs7-mime -application/pkcs7-signature -application/pkix-cert -application/pkix-crl -application/pkixcmp -application/postscript ps ai eps epsi epsf eps2 eps3 -application/prs.alvestrand.titrax-sheet -application/prs.cww -application/prs.nprend -application/qsig -application/rar rar -application/rdf+xml rdf -application/remote-printing -application/riscos -application/rtf rtf -application/sdp -application/set-payment -application/set-payment-initiation -application/set-registration -application/set-registration-initiation -application/sgml -application/sgml-open-catalog -application/sieve -application/sla stl -application/slate -application/smil+xml smi smil -application/timestamp-query -application/timestamp-reply -application/vemmi -application/whoispp-query -application/whoispp-response -application/wita -application/x400-bp -application/xhtml+xml xhtml xht -application/xml xml xsd -application/xml-dtd -application/xml-external-parsed-entity -application/xslt+xml xsl xslt -application/xspf+xml xspf -application/zip zip -application/vnd.3M.Post-it-Notes -application/vnd.accpac.simply.aso -application/vnd.accpac.simply.imp -application/vnd.acucobol -application/vnd.aether.imp -application/vnd.android.package-archive apk -application/vnd.anser-web-certificate-issue-initiation -application/vnd.anser-web-funds-transfer-initiation -application/vnd.audiograph -application/vnd.bmi -application/vnd.businessobjects -application/vnd.canon-cpdl -application/vnd.canon-lips -application/vnd.cinderella cdy -application/vnd.claymore -application/vnd.commerce-battelle -application/vnd.commonspace -application/vnd.comsocaller -application/vnd.contact.cmsg -application/vnd.cosmocaller -application/vnd.ctc-posml -application/vnd.cups-postscript -application/vnd.cups-raster -application/vnd.cups-raw -application/vnd.cybank -application/vnd.debian.binary-package deb ddeb udeb -application/vnd.dna -application/vnd.dpgraph -application/vnd.dxr -application/vnd.ecdis-update -application/vnd.ecowin.chart -application/vnd.ecowin.filerequest -application/vnd.ecowin.fileupdate -application/vnd.ecowin.series -application/vnd.ecowin.seriesrequest -application/vnd.ecowin.seriesupdate -application/vnd.enliven -application/vnd.epson.esf -application/vnd.epson.msf -application/vnd.epson.quickanime -application/vnd.epson.salt -application/vnd.epson.ssf -application/vnd.ericsson.quickcall -application/vnd.eudora.data -application/vnd.fdf -application/vnd.ffsns -application/vnd.flographit -application/vnd.font-fontforge-sfd sfd -application/vnd.framemaker -application/vnd.fsc.weblaunch -application/vnd.fujitsu.oasys -application/vnd.fujitsu.oasys2 -application/vnd.fujitsu.oasys3 -application/vnd.fujitsu.oasysgp -application/vnd.fujitsu.oasysprs -application/vnd.fujixerox.ddd -application/vnd.fujixerox.docuworks -application/vnd.fujixerox.docuworks.binder -application/vnd.fut-misnet -application/vnd.google-earth.kml+xml kml -application/vnd.google-earth.kmz kmz -application/vnd.grafeq -application/vnd.groove-account -application/vnd.groove-identity-message -application/vnd.groove-injector -application/vnd.groove-tool-message -application/vnd.groove-tool-template -application/vnd.groove-vcard -application/vnd.hhe.lesson-player -application/vnd.hp-HPGL -application/vnd.hp-PCL -application/vnd.hp-PCLXL -application/vnd.hp-hpid -application/vnd.hp-hps -application/vnd.httphone -application/vnd.hzn-3d-crossword -application/vnd.ibm.MiniPay -application/vnd.ibm.afplinedata -application/vnd.ibm.modcap -application/vnd.informix-visionary -application/vnd.intercon.formnet -application/vnd.intertrust.digibox -application/vnd.intertrust.nncp -application/vnd.intu.qbo -application/vnd.intu.qfx -application/vnd.irepository.package+xml -application/vnd.is-xpr -application/vnd.japannet-directory-service -application/vnd.japannet-jpnstore-wakeup -application/vnd.japannet-payment-wakeup -application/vnd.japannet-registration -application/vnd.japannet-registration-wakeup -application/vnd.japannet-setstore-wakeup -application/vnd.japannet-verification -application/vnd.japannet-verification-wakeup -application/vnd.koan -application/vnd.lotus-1-2-3 -application/vnd.lotus-approach -application/vnd.lotus-freelance -application/vnd.lotus-notes -application/vnd.lotus-organizer -application/vnd.lotus-screencam -application/vnd.lotus-wordpro -application/vnd.mcd -application/vnd.mediastation.cdkey -application/vnd.meridian-slingshot -application/vnd.mif -application/vnd.minisoft-hp3000-save -application/vnd.mitsubishi.misty-guard.trustweb -application/vnd.mobius.daf -application/vnd.mobius.dis -application/vnd.mobius.msl -application/vnd.mobius.plc -application/vnd.mobius.txf -application/vnd.motorola.flexsuite -application/vnd.motorola.flexsuite.adsi -application/vnd.motorola.flexsuite.fis -application/vnd.motorola.flexsuite.gotap -application/vnd.motorola.flexsuite.kmr -application/vnd.motorola.flexsuite.ttc -application/vnd.motorola.flexsuite.wem -application/vnd.mozilla.xul+xml xul -application/vnd.ms-artgalry -application/vnd.ms-asf -application/vnd.ms-excel xls xlb xlt -application/vnd.ms-excel.addin.macroEnabled.12 xlam -application/vnd.ms-excel.sheet.binary.macroEnabled.12 xlsb -application/vnd.ms-excel.sheet.macroEnabled.12 xlsm -application/vnd.ms-excel.template.macroEnabled.12 xltm -application/vnd.ms-fontobject eot -application/vnd.ms-lrm -application/vnd.ms-officetheme thmx -application/vnd.ms-pki.seccat cat -#application/vnd.ms-pki.stl stl -application/vnd.ms-powerpoint ppt pps -application/vnd.ms-powerpoint.addin.macroEnabled.12 ppam -application/vnd.ms-powerpoint.presentation.macroEnabled.12 pptm -application/vnd.ms-powerpoint.slide.macroEnabled.12 sldm -application/vnd.ms-powerpoint.slideshow.macroEnabled.12 ppsm -application/vnd.ms-powerpoint.template.macroEnabled.12 potm -application/vnd.ms-project -application/vnd.ms-tnef -application/vnd.ms-word.document.macroEnabled.12 docm -application/vnd.ms-word.template.macroEnabled.12 dotm -application/vnd.ms-works -application/vnd.mseq -application/vnd.msign -application/vnd.music-niff -application/vnd.musician -application/vnd.netfpx -application/vnd.noblenet-directory -application/vnd.noblenet-sealer -application/vnd.noblenet-web -application/vnd.novadigm.EDM -application/vnd.novadigm.EDX -application/vnd.novadigm.EXT -application/vnd.oasis.opendocument.chart odc -application/vnd.oasis.opendocument.database odb -application/vnd.oasis.opendocument.formula odf -application/vnd.oasis.opendocument.graphics odg -application/vnd.oasis.opendocument.graphics-template otg -application/vnd.oasis.opendocument.image odi -application/vnd.oasis.opendocument.presentation odp -application/vnd.oasis.opendocument.presentation-template otp -application/vnd.oasis.opendocument.spreadsheet ods -application/vnd.oasis.opendocument.spreadsheet-template ots -application/vnd.oasis.opendocument.text odt -application/vnd.oasis.opendocument.text-master odm -application/vnd.oasis.opendocument.text-template ott -application/vnd.oasis.opendocument.text-web oth -application/vnd.openxmlformats-officedocument.presentationml.presentation pptx -application/vnd.openxmlformats-officedocument.presentationml.slide sldx -application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx -application/vnd.openxmlformats-officedocument.presentationml.template potx -application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx -application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx -application/vnd.openxmlformats-officedocument.wordprocessingml.document docx -application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx -application/vnd.osa.netdeploy -application/vnd.palm -application/vnd.pg.format -application/vnd.pg.osasli -application/vnd.powerbuilder6 -application/vnd.powerbuilder6-s -application/vnd.powerbuilder7 -application/vnd.powerbuilder7-s -application/vnd.powerbuilder75 -application/vnd.powerbuilder75-s -application/vnd.previewsystems.box -application/vnd.publishare-delta-tree -application/vnd.pvi.ptid1 -application/vnd.pwg-xhtml-print+xml -application/vnd.rapid -application/vnd.rim.cod cod -application/vnd.s3sms -application/vnd.seemail -application/vnd.shana.informed.formdata -application/vnd.shana.informed.formtemplate -application/vnd.shana.informed.interchange -application/vnd.shana.informed.package -application/vnd.smaf mmf -application/vnd.sss-cod -application/vnd.sss-dtf -application/vnd.sss-ntf -application/vnd.stardivision.calc sdc -application/vnd.stardivision.chart sds -application/vnd.stardivision.draw sda -application/vnd.stardivision.impress sdd -application/vnd.stardivision.math sdf -application/vnd.stardivision.writer sdw -application/vnd.stardivision.writer-global sgl -application/vnd.street-stream -application/vnd.sun.xml.calc sxc -application/vnd.sun.xml.calc.template stc -application/vnd.sun.xml.draw sxd -application/vnd.sun.xml.draw.template std -application/vnd.sun.xml.impress sxi -application/vnd.sun.xml.impress.template sti -application/vnd.sun.xml.math sxm -application/vnd.sun.xml.writer sxw -application/vnd.sun.xml.writer.global sxg -application/vnd.sun.xml.writer.template stw -application/vnd.svd -application/vnd.swiftview-ics -application/vnd.symbian.install sis -application/vnd.tcpdump.pcap cap pcap -application/vnd.triscape.mxs -application/vnd.trueapp -application/vnd.truedoc -application/vnd.tve-trigger -application/vnd.ufdl -application/vnd.uplanet.alert -application/vnd.uplanet.alert-wbxml -application/vnd.uplanet.bearer-choice -application/vnd.uplanet.bearer-choice-wbxml -application/vnd.uplanet.cacheop -application/vnd.uplanet.cacheop-wbxml -application/vnd.uplanet.channel -application/vnd.uplanet.channel-wbxml -application/vnd.uplanet.list -application/vnd.uplanet.list-wbxml -application/vnd.uplanet.listcmd -application/vnd.uplanet.listcmd-wbxml -application/vnd.uplanet.signal -application/vnd.vcx -application/vnd.vectorworks -application/vnd.vidsoft.vidconference -application/vnd.visio vsd vst vsw vss -application/vnd.vividence.scriptfile -application/vnd.wap.sic -application/vnd.wap.slc -application/vnd.wap.wbxml wbxml -application/vnd.wap.wmlc wmlc -application/vnd.wap.wmlscriptc wmlsc -application/vnd.webturbo -application/vnd.wordperfect wpd -application/vnd.wordperfect5.1 wp5 -application/vnd.wrq-hp3000-labelled -application/vnd.wt.stf -application/vnd.xara -application/vnd.xfdl -application/vnd.yellowriver-custom-menu -application/zlib -application/x-123 wk -application/x-7z-compressed 7z -application/x-abiword abw -application/x-apple-diskimage dmg -application/x-bcpio bcpio -application/x-bittorrent torrent -application/x-cab cab -application/x-cbr cbr -application/x-cbz cbz -application/x-cdf cdf cda -application/x-cdlink vcd -application/x-chess-pgn pgn -application/x-comsol mph -application/x-core -application/x-cpio cpio -application/x-csh csh -application/x-debian-package deb udeb -application/x-director dcr dir dxr -application/x-dms dms -application/x-doom wad -application/x-dvi dvi -application/x-executable -application/x-font pfa pfb gsf -application/x-font-pcf pcf pcf.Z -application/x-freemind mm -application/x-futuresplash spl -application/x-ganttproject gan -application/x-gnumeric gnumeric -application/x-go-sgf sgf -application/x-graphing-calculator gcf -application/x-gtar gtar -application/x-gtar-compressed tgz taz -application/x-hdf hdf -#application/x-httpd-eruby rhtml -#application/x-httpd-php phtml pht php -#application/x-httpd-php-source phps -#application/x-httpd-php3 php3 -#application/x-httpd-php3-preprocessed php3p -#application/x-httpd-php4 php4 -#application/x-httpd-php5 php5 -application/x-hwp hwp -application/x-ica ica -application/x-info info -application/x-internet-signup ins isp -application/x-iphone iii -application/x-iso9660-image iso -application/x-jam jam -application/x-java-applet -application/x-java-bean -application/x-java-jnlp-file jnlp -application/x-jmol jmz -application/x-kchart chrt -application/x-kdelnk -application/x-killustrator kil -application/x-koan skp skd skt skm -application/x-kpresenter kpr kpt -application/x-kspread ksp -application/x-kword kwd kwt -application/x-latex latex -application/x-lha lha -application/x-lyx lyx -application/x-lzh lzh -application/x-lzx lzx -application/x-maker frm maker frame fm fb book fbdoc -application/x-mif mif -application/x-mpegURL m3u8 -application/x-ms-application application -application/x-ms-manifest manifest -application/x-ms-wmd wmd -application/x-ms-wmz wmz -application/x-msdos-program com exe bat dll -application/x-msi msi -application/x-netcdf nc -application/x-ns-proxy-autoconfig pac -application/x-nwc nwc -application/x-object o -application/x-oz-application oza -application/x-pkcs7-certreqresp p7r -application/x-pkcs7-crl crl -application/x-python-code pyc pyo -application/x-qgis qgs shp shx -application/x-quicktimeplayer qtl -application/x-rdp rdp -application/x-redhat-package-manager rpm -application/x-rss+xml rss -application/x-ruby rb -application/x-rx -application/x-scilab sci sce -application/x-scilab-xcos xcos -application/x-sh sh -application/x-shar shar -application/x-shellscript -application/x-shockwave-flash swf swfl -application/x-silverlight scr -application/x-sql sql -application/x-stuffit sit sitx -application/x-sv4cpio sv4cpio -application/x-sv4crc sv4crc -application/x-tar tar -application/x-tcl tcl -application/x-tex-gf gf -application/x-tex-pk pk -application/x-texinfo texinfo texi -application/x-trash ~ % bak old sik -application/x-troff t tr roff -application/x-troff-man man -application/x-troff-me me -application/x-troff-ms ms -application/x-ustar ustar -application/x-videolan -application/x-wais-source src -application/x-wingz wz -application/x-x509-ca-cert crt -application/x-xcf xcf -application/x-xfig fig -application/x-xpinstall xpi -application/x-xz xz - -audio/32kadpcm -audio/3gpp -audio/amr amr -audio/amr-wb awb -audio/annodex axa -audio/basic au snd -audio/csound csd orc sco -audio/flac flac -audio/g.722.1 -audio/l16 -audio/midi mid midi kar -audio/mp4a-latm -audio/mpa-robust -audio/mpeg mpga mpega mp2 mp3 m4a -audio/mpegurl m3u -audio/ogg oga ogg opus spx -audio/parityfec -audio/prs.sid sid -audio/telephone-event -audio/tone -audio/vnd.cisco.nse -audio/vnd.cns.anp1 -audio/vnd.cns.inf1 -audio/vnd.digital-winds -audio/vnd.everad.plj -audio/vnd.lucent.voice -audio/vnd.nortel.vbk -audio/vnd.nuera.ecelp4800 -audio/vnd.nuera.ecelp7470 -audio/vnd.nuera.ecelp9600 -audio/vnd.octel.sbc -audio/vnd.qcelp -audio/vnd.rhetorex.32kadpcm -audio/vnd.vmx.cvsd -audio/x-aiff aif aiff aifc -audio/x-gsm gsm -audio/x-mpegurl m3u -audio/x-ms-wma wma -audio/x-ms-wax wax -audio/x-pn-realaudio-plugin -audio/x-pn-realaudio ra rm ram -audio/x-realaudio ra -audio/x-scpls pls -audio/x-sd2 sd2 -audio/x-wav wav - -chemical/x-alchemy alc -chemical/x-cache cac cache -chemical/x-cache-csf csf -chemical/x-cactvs-binary cbin cascii ctab -chemical/x-cdx cdx -chemical/x-cerius cer -chemical/x-chem3d c3d -chemical/x-chemdraw chm -chemical/x-cif cif -chemical/x-cmdf cmdf -chemical/x-cml cml -chemical/x-compass cpa -chemical/x-crossfire bsd -chemical/x-csml csml csm -chemical/x-ctx ctx -chemical/x-cxf cxf cef -#chemical/x-daylight-smiles smi -chemical/x-embl-dl-nucleotide emb embl -chemical/x-galactic-spc spc -chemical/x-gamess-input inp gam gamin -chemical/x-gaussian-checkpoint fch fchk -chemical/x-gaussian-cube cub -chemical/x-gaussian-input gau gjc gjf -chemical/x-gaussian-log gal -chemical/x-gcg8-sequence gcg -chemical/x-genbank gen -chemical/x-hin hin -chemical/x-isostar istr ist -chemical/x-jcamp-dx jdx dx -chemical/x-kinemage kin -chemical/x-macmolecule mcm -chemical/x-macromodel-input mmd mmod -chemical/x-mdl-molfile mol -chemical/x-mdl-rdfile rd -chemical/x-mdl-rxnfile rxn -chemical/x-mdl-sdfile sd sdf -chemical/x-mdl-tgf tgf -#chemical/x-mif mif -chemical/x-mmcif mcif -chemical/x-mol2 mol2 -chemical/x-molconn-Z b -chemical/x-mopac-graph gpt -chemical/x-mopac-input mop mopcrt mpc zmt -chemical/x-mopac-out moo -chemical/x-mopac-vib mvb -chemical/x-ncbi-asn1 asn -chemical/x-ncbi-asn1-ascii prt ent -chemical/x-ncbi-asn1-binary val aso -chemical/x-ncbi-asn1-spec asn -chemical/x-pdb pdb ent -chemical/x-rosdal ros -chemical/x-swissprot sw -chemical/x-vamas-iso14976 vms -chemical/x-vmd vmd -chemical/x-xtel xtel -chemical/x-xyz xyz - -font/collection ttc -font/otf ttf otf -font/sfnt ttf otf -font/ttf ttf otf -font/woff woff -font/woff2 woff2 - -image/cgm -image/g3fax -image/gif gif -image/ief ief -image/jp2 jp2 jpg2 -image/jpeg jpeg jpg jpe -image/jpm jpm -image/jpx jpx jpf -image/naplps -image/pcx pcx -image/png png -image/prs.btif -image/prs.pti -image/svg+xml svg svgz -image/tiff tiff tif -image/vnd.cns.inf2 -image/vnd.djvu djvu djv -image/vnd.dwg -image/vnd.dxf -image/vnd.fastbidsheet -image/vnd.fpx -image/vnd.fst -image/vnd.fujixerox.edmics-mmr -image/vnd.fujixerox.edmics-rlc -image/vnd.microsoft.icon ico -image/vnd.mix -image/vnd.net-fpx -image/vnd.svf -image/vnd.wap.wbmp wbmp -image/vnd.xiff -image/x-canon-cr2 cr2 -image/x-canon-crw crw -image/x-cmu-raster ras -image/x-coreldraw cdr -image/x-coreldrawpattern pat -image/x-coreldrawtemplate cdt -image/x-corelphotopaint cpt -image/x-epson-erf erf -image/x-icon -image/x-jg art -image/x-jng jng -image/x-ms-bmp bmp -image/x-nikon-nef nef -image/x-olympus-orf orf -image/x-photoshop psd -image/x-portable-anymap pnm -image/x-portable-bitmap pbm -image/x-portable-graymap pgm -image/x-portable-pixmap ppm -image/x-rgb rgb -image/x-xbitmap xbm -image/x-xpixmap xpm -image/x-xwindowdump xwd - -inode/chardevice -inode/blockdevice -inode/directory-locked -inode/directory -inode/fifo -inode/socket - -message/delivery-status -message/disposition-notification -message/external-body -message/http -message/s-http -message/news -message/partial -message/rfc822 eml - -model/iges igs iges -model/mesh msh mesh silo -model/vnd.dwf -model/vnd.flatland.3dml -model/vnd.gdl -model/vnd.gs-gdl -model/vnd.gtw -model/vnd.mts -model/vnd.vtu -model/vrml wrl vrml -model/x3d+vrml x3dv -model/x3d+xml x3d -model/x3d+binary x3db - -multipart/alternative -multipart/appledouble -multipart/byteranges -multipart/digest -multipart/encrypted -multipart/form-data -multipart/header-set -multipart/mixed -multipart/parallel -multipart/related -multipart/report -multipart/signed -multipart/voice-message - -text/cache-manifest appcache -text/calendar ics icz -text/css css -text/csv csv -text/directory -text/english -text/enriched -text/h323 323 -text/html html htm shtml -text/iuls uls -text/mathml mml -text/markdown md markdown -text/parityfec -text/plain asc txt text pot brf srt -text/prs.lines.tag -text/rfc822-headers -text/richtext rtx -text/rtf -text/scriptlet sct wsc -text/t140 -text/texmacs tm -text/tab-separated-values tsv -text/turtle ttl -text/uri-list -text/vcard vcf vcard -text/vnd.abc -text/vnd.curl -text/vnd.debian.copyright -text/vnd.DMClientScript -text/vnd.flatland.3dml -text/vnd.fly -text/vnd.fmi.flexstor -text/vnd.in3d.3dml -text/vnd.in3d.spot -text/vnd.IPTC.NewsML -text/vnd.IPTC.NITF -text/vnd.latex-z -text/vnd.motorola.reflex -text/vnd.ms-mediapackage -text/vnd.sun.j2me.app-descriptor jad -text/vnd.wap.si -text/vnd.wap.sl -text/vnd.wap.wml wml -text/vnd.wap.wmlscript wmls -text/x-bibtex bib -text/x-boo boo -text/x-c++hdr h++ hpp hxx hh -text/x-c++src c++ cpp cxx cc -text/x-chdr h -text/x-component htc -text/x-crontab -text/x-csh csh -text/x-csrc c -text/x-dsrc d -text/x-diff diff patch -text/x-haskell hs -text/x-java java -text/x-lilypond ly -text/x-literate-haskell lhs -text/x-makefile -text/x-moc moc -text/x-pascal p pas -text/x-pcs-gcd gcd -text/x-perl pl pm -text/x-python py -text/x-scala scala -text/x-server-parsed-html -text/x-setext etx -text/x-sfv sfv -text/x-sh sh -text/x-tcl tcl tk -text/x-tex tex ltx sty cls -text/x-vcalendar vcs - -video/3gpp 3gp -video/annodex axv -video/dl dl -video/dv dif dv -video/fli fli -video/gl gl -video/mpeg mpeg mpg mpe -video/MP2T ts -video/mp4 mp4 -video/quicktime qt mov -video/mp4v-es -video/ogg ogv -video/parityfec -video/pointer -video/webm webm -video/vnd.fvt -video/vnd.motorola.video -video/vnd.motorola.videop -video/vnd.mpegurl mxu -video/vnd.mts -video/vnd.nokia.interleaved-multimedia -video/vnd.vivo -video/x-flv flv -video/x-la-asf lsf lsx -video/x-mng mng -video/x-ms-asf asf asx -video/x-ms-wm wm -video/x-ms-wmv wmv -video/x-ms-wmx wmx -video/x-ms-wvx wvx -video/x-msvideo avi -video/x-sgi-movie movie -video/x-matroska mpv mkv - -x-conference/x-cooltalk ice - -x-epoc/x-sisx-app sisx -x-world/x-vrml vrm vrml wrl diff --git a/luni/src/main/java/libcore/net/mime.types.README b/luni/src/main/java/libcore/net/mime.types.README deleted file mode 100644 index 3479703a0f..0000000000 --- a/luni/src/main/java/libcore/net/mime.types.README +++ /dev/null @@ -1,13 +0,0 @@ - -Debian is the upstream for this mapping file: -https://salsa.debian.org/debian/mime-support - -Last updated as of commit d4bbcca4ba04582ad1d253d82fc139bb23841a43. - -Copyright: public-domain -License: ad-hoc - This package was written by Brian White <bcwhite@pobox.com> and others. - It contains public information compiled from around the 'net and many people. - . - The "update-mime" program was written by Brian White and has been - placed in the public domain. diff --git a/luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java b/luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java index 5919a19216..5593ad4909 100644 --- a/luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java +++ b/luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java @@ -28,11 +28,10 @@ public final class GenericArrayTypeImpl implements GenericArrayType { } public Type getGenericComponentType() { - try { + if (componentType instanceof ParameterizedTypeImpl) { return ((ParameterizedTypeImpl)componentType).getResolvedType(); - } catch (ClassCastException e) { - return componentType; } + return componentType; } @Override diff --git a/luni/src/main/java/libcore/reflect/GenericSignatureParser.java b/luni/src/main/java/libcore/reflect/GenericSignatureParser.java index 5e86c495fd..2216cd6a46 100644 --- a/luni/src/main/java/libcore/reflect/GenericSignatureParser.java +++ b/luni/src/main/java/libcore/reflect/GenericSignatureParser.java @@ -315,18 +315,18 @@ public final class GenericSignatureParser { qualIdent.append(this.identifier); ListOfTypes typeArgs = parseOptTypeArguments(); - ParameterizedTypeImpl parentType = - new ParameterizedTypeImpl(null, qualIdent.toString(), typeArgs, loader); - ParameterizedTypeImpl type = parentType; + ParameterizedTypeImpl type = new ParameterizedTypeImpl( + null /* ownerType */, qualIdent.toString(), typeArgs, loader); + ParameterizedTypeImpl ownerType; while (symbol == '.') { // Deal with Member Classes: scanSymbol(); scanIdentifier(); qualIdent.append("$").append(identifier); // FIXME: is "$" correct? typeArgs = parseOptTypeArguments(); - type = new ParameterizedTypeImpl(parentType, qualIdent.toString(), typeArgs, - loader); + ownerType = type; + type = new ParameterizedTypeImpl(ownerType, qualIdent.toString(), typeArgs, loader); } expect(';'); diff --git a/luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java b/luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java index 2cd5ac37a2..47f64a8a13 100644 --- a/luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java +++ b/luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java @@ -40,11 +40,12 @@ public final class ParameterizedTypeImpl implements ParameterizedType { this.loader = loader; } - + @Override public Type[] getActualTypeArguments() { return args.getResolvedTypes().clone(); } + @Override public Type getOwnerType() { if (ownerTypeRes == null) { if (ownerType0 != null) { @@ -56,6 +57,7 @@ public final class ParameterizedTypeImpl implements ParameterizedType { return ownerTypeRes; } + @Override public Class getRawType() { if (rawType == null) { // Here the actual loading of the class has to be performed and the @@ -70,9 +72,8 @@ public final class ParameterizedTypeImpl implements ParameterizedType { return rawType; } - Type getResolvedType() { - if (args.getResolvedTypes().length == 0) { + if (ownerType0 == null && args.getResolvedTypes().length == 0) { return getRawType(); } else { return this; @@ -99,7 +100,15 @@ public final class ParameterizedTypeImpl implements ParameterizedType { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append(rawTypeName); + if (ownerType0 != null) { + // For nested types, use the ownerType because it or its parents may have their own + // type arguments. + sb.append(ownerType0); + sb.append('$'); + sb.append(getRawType().getSimpleName()); + } else { + sb.append(rawTypeName); + } if (args.length() > 0) { sb.append("<").append(args).append(">"); } diff --git a/luni/src/main/java/libcore/reflect/TEST_MAPPING b/luni/src/main/java/libcore/reflect/TEST_MAPPING new file mode 100644 index 0000000000..b57dc5557c --- /dev/null +++ b/luni/src/main/java/libcore/reflect/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.libcore.reflect" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/libcore/timezone/CountryTimeZones.java b/luni/src/main/java/libcore/timezone/CountryTimeZones.java index 66119d7320..4ff8470e0c 100644 --- a/luni/src/main/java/libcore/timezone/CountryTimeZones.java +++ b/luni/src/main/java/libcore/timezone/CountryTimeZones.java @@ -38,27 +38,35 @@ public final class CountryTimeZones { * @hide */ @libcore.api.CorePlatformApi - public final static class OffsetResult { + public static final class OffsetResult { - /** A zone that matches the supplied criteria. See also {@link #mOneMatch}. */ - @libcore.api.CorePlatformApi - public final TimeZone mTimeZone; + /** A zone that matches the supplied criteria. See also {@link #isOnlyMatch}. */ + private final TimeZone timeZone; /** True if there is one match for the supplied criteria */ + private final boolean isOnlyMatch; + + public OffsetResult(TimeZone timeZone, boolean isOnlyMatch) { + this.timeZone = java.util.Objects.requireNonNull(timeZone); + this.isOnlyMatch = isOnlyMatch; + } + @libcore.api.CorePlatformApi - public final boolean mOneMatch; + public TimeZone getTimeZone() { + return timeZone; + } - public OffsetResult(TimeZone timeZone, boolean oneMatch) { - mTimeZone = java.util.Objects.requireNonNull(timeZone); - mOneMatch = oneMatch; + @libcore.api.CorePlatformApi + public boolean isOnlyMatch() { + return isOnlyMatch; } @Override public String toString() { - return "Result{" + - "mTimeZone='" + mTimeZone + '\'' + - ", mOneMatch=" + mOneMatch + - '}'; + return "Result{" + + "timeZone='" + timeZone + '\'' + + ", isOnlyMatch=" + isOnlyMatch + + '}'; } } @@ -68,18 +76,64 @@ public final class CountryTimeZones { * @hide */ @libcore.api.CorePlatformApi - public final static class TimeZoneMapping { + public static final class TimeZoneMapping { + private final String timeZoneId; + private final boolean shownInPicker; + private final Long notUsedAfter; + + /** Memoized TimeZone object for {@link #timeZoneId}. */ + private TimeZone timeZone; + + TimeZoneMapping(String timeZoneId, boolean shownInPicker, Long notUsedAfter) { + this.timeZoneId = Objects.requireNonNull(timeZoneId); + this.shownInPicker = shownInPicker; + this.notUsedAfter = notUsedAfter; + } + @libcore.api.CorePlatformApi - public final String timeZoneId; + public String getTimeZoneId() { + return timeZoneId; + } + + @libcore.api.CorePlatformApi + public boolean isShownInPicker() { + return shownInPicker; + } + @libcore.api.CorePlatformApi - public final boolean showInPicker; + public Long getNotUsedAfter() { + return notUsedAfter; + } + + /** + * Returns a {@link TimeZone} object for this mapping, or {@code null} if the ID is unknown. + */ @libcore.api.CorePlatformApi - public final Long notUsedAfter; + public TimeZone getTimeZone() { + synchronized (this) { + if (timeZone == null) { + TimeZone tz = TimeZone.getFrozenTimeZone(timeZoneId); + timeZone = tz; + if (TimeZone.UNKNOWN_ZONE_ID.equals(timeZone.getID())) { + // This shouldn't happen given the validation that takes place in + // createValidatedCountryTimeZones(). + throw new IllegalStateException("Invalid zone in TimeZoneMapping: " + this); + } + } + } - TimeZoneMapping(String timeZoneId, boolean showInPicker, Long notUsedAfter) { - this.timeZoneId = timeZoneId; - this.showInPicker = showInPicker; - this.notUsedAfter = notUsedAfter; + return TimeZone.UNKNOWN_ZONE_ID.equals(timeZone.getID()) ? null : timeZone; + } + + /** + * Returns {@code true} if the mapping is "effective" after {@code whenMillis}, i.e. + * it is distinct from other "effective" times zones used in the country at/after that + * time. This uses the {@link #notUsedAfter} metadata which ensures there is one time + * zone remaining when there are multiple candidate zones with the same rules. The one + * kept is based on country specific factors like population covered. + */ + boolean isEffectiveAt(long whenMillis) { + return notUsedAfter == null || whenMillis <= notUsedAfter; } // VisibleForTesting @@ -98,21 +152,21 @@ public final class CountryTimeZones { return false; } TimeZoneMapping that = (TimeZoneMapping) o; - return showInPicker == that.showInPicker && + return shownInPicker == that.shownInPicker && Objects.equals(timeZoneId, that.timeZoneId) && Objects.equals(notUsedAfter, that.notUsedAfter); } @Override public int hashCode() { - return Objects.hash(timeZoneId, showInPicker, notUsedAfter); + return Objects.hash(timeZoneId, shownInPicker, notUsedAfter); } @Override public String toString() { return "TimeZoneMapping{" + "timeZoneId='" + timeZoneId + '\'' - + ", showInPicker=" + showInPicker + + ", shownInPicker=" + shownInPicker + ", notUsedAfter=" + notUsedAfter + '}'; } @@ -121,7 +175,7 @@ public final class CountryTimeZones { * Returns {@code true} if one of the supplied {@link TimeZoneMapping} objects is for the * specified time zone ID. */ - public static boolean containsTimeZoneId( + static boolean containsTimeZoneId( List<TimeZoneMapping> timeZoneMappings, String timeZoneId) { for (TimeZoneMapping timeZoneMapping : timeZoneMappings) { if (timeZoneMapping.timeZoneId.equals(timeZoneId)) { @@ -134,18 +188,26 @@ public final class CountryTimeZones { private final String countryIso; private final String defaultTimeZoneId; + /** + * {@code true} indicates the default time zone for a country is a good choice if a time zone + * cannot be determined by other means. + */ + private final boolean defaultTimeZoneBoosted; private final List<TimeZoneMapping> timeZoneMappings; private final boolean everUsesUtc; - // Memoized frozen ICU TimeZone object for the default. - private TimeZone icuDefaultTimeZone; - // Memoized frozen ICU TimeZone objects for the timeZoneIds. - private List<TimeZone> icuTimeZones; + /** + * Memoized frozen ICU TimeZone object for the default. Can be {@link TimeZone#UNKNOWN_ZONE} if + * the {@link #defaultTimeZoneId} is missing or unrecognized. + */ + private TimeZone defaultTimeZone; - private CountryTimeZones(String countryIso, String defaultTimeZoneId, boolean everUsesUtc, + private CountryTimeZones(String countryIso, String defaultTimeZoneId, + boolean defaultTimeZoneBoosted, boolean everUsesUtc, List<TimeZoneMapping> timeZoneMappings) { this.countryIso = java.util.Objects.requireNonNull(countryIso); this.defaultTimeZoneId = defaultTimeZoneId; + this.defaultTimeZoneBoosted = defaultTimeZoneBoosted; this.everUsesUtc = everUsesUtc; // Create a defensive copy of the mapping list. this.timeZoneMappings = Collections.unmodifiableList(new ArrayList<>(timeZoneMappings)); @@ -155,12 +217,13 @@ public final class CountryTimeZones { * Creates a {@link CountryTimeZones} object containing only known time zone IDs. */ public static CountryTimeZones createValidated(String countryIso, String defaultTimeZoneId, - boolean everUsesUtc, List<TimeZoneMapping> timeZoneMappings, String debugInfo) { + boolean defaultTimeZoneBoosted, boolean everUsesUtc, + List<TimeZoneMapping> timeZoneMappings, String debugInfo) { // We rely on ZoneInfoDB to tell us what the known valid time zone IDs are. ICU may // recognize more but we want to be sure that zone IDs can be used with java.util as well as // android.icu and ICU is expected to have a superset. - String[] validTimeZoneIdsArray = ZoneInfoDB.getInstance().getAvailableIDs(); + String[] validTimeZoneIdsArray = ZoneInfoDb.getInstance().getAvailableIDs(); HashSet<String> validTimeZoneIdsSet = new HashSet<>(Arrays.asList(validTimeZoneIdsArray)); List<TimeZoneMapping> validCountryTimeZoneMappings = new ArrayList<>(); for (TimeZoneMapping timeZoneMapping : timeZoneMappings) { @@ -184,7 +247,8 @@ public final class CountryTimeZones { String normalizedCountryIso = normalizeCountryIso(countryIso); return new CountryTimeZones( - normalizedCountryIso, defaultTimeZoneId, everUsesUtc, validCountryTimeZoneMappings); + normalizedCountryIso, defaultTimeZoneId, defaultTimeZoneBoosted, everUsesUtc, + validCountryTimeZoneMappings); } /** @@ -204,27 +268,28 @@ public final class CountryTimeZones { } /** - * Returns the default time zone ID for the country. Can return null in cases when no data is + * Returns the default time zone for the country. Can return null in cases when no data is * available or the time zone ID provided to - * {@link #createValidated(String, String, boolean, List, String)} was not recognized. + * {@link #createValidated(String, String, boolean, boolean, List, String)} was not recognized. */ + @libcore.api.CorePlatformApi public synchronized TimeZone getDefaultTimeZone() { - if (icuDefaultTimeZone == null) { - TimeZone defaultTimeZone; + if (defaultTimeZone == null) { + TimeZone timeZone; if (defaultTimeZoneId == null) { - defaultTimeZone = null; + timeZone = TimeZone.UNKNOWN_ZONE; } else { - defaultTimeZone = getValidFrozenTimeZoneOrNull(defaultTimeZoneId); + timeZone = TimeZone.getFrozenTimeZone(defaultTimeZoneId); } - icuDefaultTimeZone = defaultTimeZone; + this.defaultTimeZone = timeZone; } - return icuDefaultTimeZone; + return TimeZone.UNKNOWN_ZONE_ID.equals(defaultTimeZone.getID()) ? null : defaultTimeZone; } /** * Returns the default time zone ID for the country. Can return null in cases when no data is * available or the time zone ID provided to - * {@link #createValidated(String, String, boolean, List, String)} was not recognized. + * {@link #createValidated(String, String, boolean, boolean, List, String)} was not recognized. */ @libcore.api.CorePlatformApi public String getDefaultTimeZoneId() { @@ -232,6 +297,15 @@ public final class CountryTimeZones { } /** + * Qualifier for a country's default time zone. {@code true} indicates whether the default + * would be a good choice <em>generally</em> when there's no other information available. + */ + @libcore.api.CorePlatformApi + public boolean isDefaultTimeZoneBoosted() { + return defaultTimeZoneBoosted; + } + + /** * Returns an immutable, ordered list of time zone mappings for the country in an undefined but * "priority" order. The list can be empty if there were no zones configured or the configured * zone IDs were not recognized. @@ -241,6 +315,24 @@ public final class CountryTimeZones { return timeZoneMappings; } + /** + * Returns an immutable, ordered list of time zone mappings for the country in an undefined but + * "priority" order, filtered so that only "effective" time zone IDs are returned. An + * "effective" time zone is one that differs from another time zone used in the country after + * {@code whenMillis}. The list can be empty if there were no zones configured or the configured + * zone IDs were not recognized. + */ + @libcore.api.CorePlatformApi + public List<TimeZoneMapping> getEffectiveTimeZoneMappingsAt(long whenMillis) { + ArrayList<TimeZoneMapping> filteredList = new ArrayList<>(timeZoneMappings.size()); + for (TimeZoneMapping timeZoneMapping : timeZoneMappings) { + if (timeZoneMapping.isEffectiveAt(whenMillis)) { + filteredList.add(timeZoneMapping); + } + } + return Collections.unmodifiableList(filteredList); + } + @Override public boolean equals(Object o) { if (this == o) { @@ -249,58 +341,30 @@ public final class CountryTimeZones { if (o == null || getClass() != o.getClass()) { return false; } - CountryTimeZones that = (CountryTimeZones) o; - - if (everUsesUtc != that.everUsesUtc) { - return false; - } - if (!countryIso.equals(that.countryIso)) { - return false; - } - if (defaultTimeZoneId != null ? !defaultTimeZoneId.equals(that.defaultTimeZoneId) - : that.defaultTimeZoneId != null) { - return false; - } - return timeZoneMappings.equals(that.timeZoneMappings); + return defaultTimeZoneBoosted == that.defaultTimeZoneBoosted + && everUsesUtc == that.everUsesUtc + && countryIso.equals(that.countryIso) + && Objects.equals(defaultTimeZoneId, that.defaultTimeZoneId) + && timeZoneMappings.equals(that.timeZoneMappings); } @Override public int hashCode() { - int result = countryIso.hashCode(); - result = 31 * result + (defaultTimeZoneId != null ? defaultTimeZoneId.hashCode() : 0); - result = 31 * result + timeZoneMappings.hashCode(); - result = 31 * result + (everUsesUtc ? 1 : 0); - return result; + return Objects.hash( + countryIso, defaultTimeZoneId, defaultTimeZoneBoosted, timeZoneMappings, + everUsesUtc); } - /** - * Returns an ordered list of time zones for the country in an undefined but "priority" - * order for a country. The list can be empty if there were no zones configured or the - * configured zone IDs were not recognized. - */ - public synchronized List<TimeZone> getIcuTimeZones() { - if (icuTimeZones == null) { - ArrayList<TimeZone> mutableList = new ArrayList<>(timeZoneMappings.size()); - for (TimeZoneMapping timeZoneMapping : timeZoneMappings) { - String timeZoneId = timeZoneMapping.timeZoneId; - TimeZone timeZone; - if (timeZoneId.equals(defaultTimeZoneId)) { - timeZone = getDefaultTimeZone(); - } else { - timeZone = getValidFrozenTimeZoneOrNull(timeZoneId); - } - // This shouldn't happen given the validation that takes place in - // createValidatedCountryTimeZones(). - if (timeZone == null) { - System.logW("Skipping invalid zone: " + timeZoneId); - continue; - } - mutableList.add(timeZone); - } - icuTimeZones = Collections.unmodifiableList(mutableList); - } - return icuTimeZones; + @Override + public String toString() { + return "CountryTimeZones{" + + "countryIso='" + countryIso + '\'' + + ", defaultTimeZoneId='" + defaultTimeZoneId + '\'' + + ", defaultTimeZoneBoosted=" + defaultTimeZoneBoosted + + ", timeZoneMappings=" + timeZoneMappings + + ", everUsesUtc=" + everUsesUtc + + '}'; } /** @@ -313,8 +377,9 @@ public final class CountryTimeZones { return false; } - for (TimeZone zone : getIcuTimeZones()) { - if (zone.getOffset(whenMillis) == 0) { + for (TimeZoneMapping timeZoneMapping : getEffectiveTimeZoneMappingsAt(whenMillis)) { + TimeZone timeZone = timeZoneMapping.getTimeZone(); + if (timeZone != null && timeZone.getOffset(whenMillis) == 0) { return true; } } @@ -322,132 +387,70 @@ public final class CountryTimeZones { } /** - * Returns {@code true} if the default time zone for the country is either the only zone used or - * if it has the same offsets as all other zones used by the country <em>at the specified time - * </em> making the default equivalent to all other zones used by the country <em>at that time - * </em>. + * Returns a time zone for the country, if there is one, that matches the supplied properties. + * If there are multiple matches and the {@code bias} is one of them then it is returned, + * otherwise an arbitrary match is returned based on the {@link + * #getEffectiveTimeZoneMappingsAt(long)} ordering. + * + * @param whenMillis the UTC time to match against + * @param bias the time zone to prefer, can be {@code null} to indicate there is no preference + * @param totalOffsetMillis the offset from UTC at {@code whenMillis} + * @param isDst the Daylight Savings Time state at {@code whenMillis}. {@code true} means DST, + * {@code false} means not DST + * @return an {@link OffsetResult} with information about a matching zone, or {@code null} if + * there is no match */ @libcore.api.CorePlatformApi - public boolean isDefaultOkForCountryTimeZoneDetection(long whenMillis) { - if (timeZoneMappings.isEmpty()) { - // Should never happen unless there's been an error loading the data. - return false; - } else if (timeZoneMappings.size() == 1) { - // The default is the only zone so it's a good candidate. - return true; - } else { - TimeZone countryDefault = getDefaultTimeZone(); - if (countryDefault == null) { - return false; - } - - int countryDefaultOffset = countryDefault.getOffset(whenMillis); - List<TimeZone> candidates = getIcuTimeZones(); - for (TimeZone candidate : candidates) { - if (candidate == countryDefault) { - continue; - } - - int candidateOffset = candidate.getOffset(whenMillis); - if (countryDefaultOffset != candidateOffset) { - // Multiple different offsets means the default should not be used. - return false; - } - } - return true; - } + public OffsetResult lookupByOffsetWithBias(long whenMillis, TimeZone bias, + int totalOffsetMillis, boolean isDst) { + return lookupByOffsetWithBiasInternal(whenMillis, bias, totalOffsetMillis, isDst); } /** - * Returns a time zone for the country, if there is one, that has the desired properties. If - * there are multiple matches and the {@code bias} is one of them then it is returned, otherwise - * an arbitrary match is returned based on the {@link #getTimeZoneMappings()} ordering. + * Returns a time zone for the country, if there is one, that matches the supplied properties. + * If there are multiple matches and the {@code bias} is one of them then it is returned, + * otherwise an arbitrary match is returned based on the {@link + * #getEffectiveTimeZoneMappingsAt(long)} ordering. * - * @param offsetMillis the offset from UTC at {@code whenMillis} - * @param isDst whether the zone is in DST * @param whenMillis the UTC time to match against - * @param bias the time zone to prefer, can be null - * @deprecated Use {@link #lookupByOffsetWithBias(int, Integer, long, TimeZone)} instead + * @param bias the time zone to prefer, can be {@code null} to indicate there is no preference + * @param totalOffsetMillis the offset from UTC at {@code whenMillis} + * @return an {@link OffsetResult} with information about a matching zone, or {@code null} if + * there is no match */ @libcore.api.CorePlatformApi - @Deprecated - public OffsetResult lookupByOffsetWithBias(int offsetMillis, boolean isDst, long whenMillis, - TimeZone bias) { - if (timeZoneMappings == null || timeZoneMappings.isEmpty()) { - return null; - } - - List<TimeZone> candidates = getIcuTimeZones(); - - TimeZone firstMatch = null; - boolean biasMatched = false; - boolean oneMatch = true; - for (TimeZone match : candidates) { - if (!offsetMatchesAtTime(match, offsetMillis, isDst, whenMillis)) { - continue; - } - - if (firstMatch == null) { - firstMatch = match; - } else { - oneMatch = false; - } - if (bias != null && match.getID().equals(bias.getID())) { - biasMatched = true; - } - if (firstMatch != null && !oneMatch && (bias == null || biasMatched)) { - break; - } - } - if (firstMatch == null) { - return null; - } - - TimeZone toReturn = biasMatched ? bias : firstMatch; - return new OffsetResult(toReturn, oneMatch); + public OffsetResult lookupByOffsetWithBias(long whenMillis, TimeZone bias, + int totalOffsetMillis) { + final Boolean isDst = null; + return lookupByOffsetWithBiasInternal(whenMillis, bias, totalOffsetMillis, isDst); } /** - * Returns {@code true} if the specified offset, DST state and time would be valid in the - * timeZone. - */ - private static boolean offsetMatchesAtTime(TimeZone timeZone, int offsetMillis, boolean isDst, - long whenMillis) { - int[] offsets = new int[2]; - timeZone.getOffset(whenMillis, false /* local */, offsets); - - // offsets[1] == 0 when the zone is not in DST. - boolean zoneIsDst = offsets[1] != 0; - if (isDst != zoneIsDst) { - return false; - } - return offsetMillis == (offsets[0] + offsets[1]); - } - - /** - * Returns a time zone for the country, if there is one, that has the desired properties. If - * there are multiple matches and the {@code bias} is one of them then it is returned, otherwise - * an arbitrary match is returned based on the {@link #getTimeZoneMappings()} ordering. + * Returns a time zone for the country, if there is one, that matches the supplied properties. + * If there are multiple matches and the {@code bias} is one of them then it is returned, + * otherwise an arbitrary match is returned based on the {@link + * #getEffectiveTimeZoneMappingsAt(long)} ordering. * - * @param offsetMillis the offset from UTC at {@code whenMillis} - * @param dstOffsetMillis the part of {@code offsetMillis} contributed by DST, {@code null} - * means unknown * @param whenMillis the UTC time to match against - * @param bias the time zone to prefer, can be null + * @param bias the time zone to prefer, can be {@code null} + * @param totalOffsetMillis the offset from UTC at {@code whenMillis} + * @param isDst the Daylight Savings Time state at {@code whenMillis}. {@code true} means DST, + * {@code false} means not DST, {@code null} means unknown */ - public OffsetResult lookupByOffsetWithBias(int offsetMillis, Integer dstOffsetMillis, - long whenMillis, TimeZone bias) { - if (timeZoneMappings == null || timeZoneMappings.isEmpty()) { + private OffsetResult lookupByOffsetWithBiasInternal(long whenMillis, TimeZone bias, + int totalOffsetMillis, Boolean isDst) { + List<TimeZoneMapping> timeZoneMappings = getEffectiveTimeZoneMappingsAt(whenMillis); + if (timeZoneMappings.isEmpty()) { return null; } - List<TimeZone> candidates = getIcuTimeZones(); - TimeZone firstMatch = null; boolean biasMatched = false; boolean oneMatch = true; - for (TimeZone match : candidates) { - if (!offsetMatchesAtTime(match, offsetMillis, dstOffsetMillis, whenMillis)) { + for (TimeZoneMapping timeZoneMapping : timeZoneMappings) { + TimeZone match = timeZoneMapping.getTimeZone(); + if (match == null + || !offsetMatchesAtTime(whenMillis, match, totalOffsetMillis, isDst)) { continue; } @@ -472,28 +475,23 @@ public final class CountryTimeZones { } /** - * Returns {@code true} if the specified offset, DST and time would be valid in the - * timeZone. + * Returns {@code true} if the specified {@code totalOffset} and {@code isDst} would be valid in + * the {@code timeZone} at time {@code whenMillis}. + * {@code totalOffetMillis} is always matched. + * If {@code isDst} is {@code null}, this means the DST state is unknown. + * If {@code isDst} is {@code false}, this means the zone must not be in DST. + * If {@code isDst} is {@code true}, this means the zone must be in DST. */ - private static boolean offsetMatchesAtTime(TimeZone timeZone, int offsetMillis, - Integer dstOffsetMillis, long whenMillis) { + private static boolean offsetMatchesAtTime(long whenMillis, TimeZone timeZone, + int totalOffsetMillis, Boolean isDst) { int[] offsets = new int[2]; timeZone.getOffset(whenMillis, false /* local */, offsets); - if (dstOffsetMillis != null) { - if (dstOffsetMillis.intValue() != offsets[1]) { - return false; - } + if (totalOffsetMillis != (offsets[0] + offsets[1])) { + return false; } - return offsetMillis == (offsets[0] + offsets[1]); - } - private static TimeZone getValidFrozenTimeZoneOrNull(String timeZoneId) { - TimeZone timeZone = TimeZone.getFrozenTimeZone(timeZoneId); - if (timeZone.getID().equals(TimeZone.UNKNOWN_ZONE_ID)) { - return null; - } - return timeZone; + return isDst == null || (isDst == (offsets[1] != 0)); } private static String normalizeCountryIso(String countryIso) { diff --git a/luni/src/main/java/libcore/timezone/CountryZonesFinder.java b/luni/src/main/java/libcore/timezone/CountryZonesFinder.java index 92f6631653..1a9d6a65fb 100644 --- a/luni/src/main/java/libcore/timezone/CountryZonesFinder.java +++ b/luni/src/main/java/libcore/timezone/CountryZonesFinder.java @@ -16,6 +16,8 @@ package libcore.timezone; +import static libcore.timezone.XmlUtils.normalizeCountryIso; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -76,7 +78,7 @@ public final class CountryZonesFinder { */ @libcore.api.CorePlatformApi public CountryTimeZones lookupCountryTimeZones(String countryIso) { - String normalizedCountryIso = TimeZoneFinder.normalizeCountryIso(countryIso); + String normalizedCountryIso = normalizeCountryIso(countryIso); for (CountryTimeZones countryTimeZones : countryTimeZonesList) { if (countryTimeZones.getCountryIso().equals(normalizedCountryIso)) { return countryTimeZones; diff --git a/luni/src/main/java/libcore/timezone/TEST_MAPPING b/luni/src/main/java/libcore/timezone/TEST_MAPPING new file mode 100644 index 0000000000..7f731bb6d8 --- /dev/null +++ b/luni/src/main/java/libcore/timezone/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.libcore.timezone" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/libcore/timezone/TelephonyLookup.java b/luni/src/main/java/libcore/timezone/TelephonyLookup.java new file mode 100644 index 0000000000..10d9a35b98 --- /dev/null +++ b/luni/src/main/java/libcore/timezone/TelephonyLookup.java @@ -0,0 +1,325 @@ +/* + * 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. + */ + +package libcore.timezone; + +import static libcore.timezone.XmlUtils.checkOnEndTag; +import static libcore.timezone.XmlUtils.consumeUntilEndTag; +import static libcore.timezone.XmlUtils.findNextStartTagOrEndTagNoRecurse; +import static libcore.timezone.XmlUtils.findNextStartTagOrThrowNoRecurse; +import static libcore.timezone.XmlUtils.normalizeCountryIso; + +import libcore.timezone.TelephonyNetwork.MccMnc; +import libcore.timezone.XmlUtils.ReaderSupplier; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; + +import java.io.IOException; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * A class that can find time zone-related information about telephony networks by loading data from + * the telephonylookup.xml file. + * + * @hide + */ +@libcore.api.CorePlatformApi +public final class TelephonyLookup { + + // VisibleForTesting + public static final String TELEPHONYLOOKUP_FILE_NAME = "telephonylookup.xml"; + + // Root element. e.g. <telephony_lookup> + private static final String TELEPHONY_LOOKUP_ELEMENT = "telephony_lookup"; + + // Networks section. e.g. <networks> + private static final String NETWORKS_ELEMENT = "networks"; + + // Network data. e.g. + // <network mcc="310" mnc="370" country="gu"> + private static final String NETWORK_ELEMENT = "network"; + private static final String MOBILE_COUNTRY_CODE_ATTRIBUTE = "mcc"; + private static final String MOBILE_NETWORK_CODE_ATTRIBUTE = "mnc"; + // This is the ISO 3166 alpha-2 code (in lower case). + private static final String COUNTRY_ISO_CODE_ATTRIBUTE = "country"; + + private static TelephonyLookup instance; + + private final ReaderSupplier xmlSource; + + private TelephonyLookup(ReaderSupplier xmlSource) { + this.xmlSource = xmlSource; + } + + /** + * Obtains an instance for use when resolving networks. This method handles using the correct + * file when there are several to choose from. This method never returns {@code null}. No + * in-depth validation is performed on the file content, see {@link #validate()}. + */ + @libcore.api.CorePlatformApi + public static TelephonyLookup getInstance() { + synchronized(TelephonyLookup.class) { + if (instance == null) { + String[] telephonyLookupFilePaths = + TimeZoneDataFiles.getTimeZoneFilePaths(TELEPHONYLOOKUP_FILE_NAME); + instance = createInstanceWithFallback(telephonyLookupFilePaths); + } + } + return instance; + } + + // VisibleForTesting + public static TelephonyLookup createInstanceWithFallback(String... telephonyLookupFilePaths) { + IOException lastException = null; + for (String tzLookupFilePath : telephonyLookupFilePaths) { + try { + // We assume that any file in /data was validated before install, and the system + // file was validated before the device shipped. Therefore, we do not pay the + // validation cost here. + return createInstance(tzLookupFilePath); + } catch (IOException e) { + // There's expected to be two files, and it's normal for the first file not to + // exist so we don't log, but keep the lastException so we can log it if there + // are no valid files available. + if (lastException != null) { + e.addSuppressed(lastException); + } + lastException = e; + } + } + + System.logE("No valid file found in set: " + Arrays.toString(telephonyLookupFilePaths) + + " Printing exceptions and falling back to empty map.", lastException); + return createInstanceForTests("<telephony_lookup><networks /></telephony_lookup>"); + } + + /** + * Obtains an instance using a specific data file, throwing an IOException if the file does not + * exist or is not readable. This method never returns {@code null}. No in-depth validation is + * performed on the file content, see {@link #validate()}. + */ + @libcore.api.CorePlatformApi + public static TelephonyLookup createInstance(String path) throws IOException { + ReaderSupplier xmlSupplier = ReaderSupplier.forFile(path, StandardCharsets.UTF_8); + return new TelephonyLookup(xmlSupplier); + } + + /** Used to create an instance using an in-memory XML String instead of a file. */ + // VisibleForTesting + public static TelephonyLookup createInstanceForTests(String xml) { + return new TelephonyLookup(ReaderSupplier.forString(xml)); + } + + /** + * Parses the data file, throws an exception if it is invalid or cannot be read. + */ + @libcore.api.CorePlatformApi + public void validate() throws IOException { + try { + processXml(new TelephonyNetworkValidator()); + } catch (XmlPullParserException e) { + throw new IOException("Parsing error", e); + } + } + + /** + * Loads all the network <-> country mapping data into memory. This method can return + * {@code null} in the event of an error while reading the underlying data files. + */ + @libcore.api.CorePlatformApi + public TelephonyNetworkFinder getTelephonyNetworkFinder() { + TelephonyNetworksExtractor extractor = new TelephonyNetworksExtractor(); + try { + processXml(extractor); + + return extractor.getTelephonyNetworkFinder(); + } catch (XmlPullParserException | IOException e) { + System.logW("Error reading telephony networks", e); + return null; + } + } + + /** + * Processes the XML, applying the {@link TelephonyNetworkProcessor} to the <countryzones> + * element. Processing can terminate early if {@link TelephonyNetworkProcessor + * #processNetwork(int, int, String, String)} it throws an exception. + */ + private void processXml(TelephonyNetworkProcessor processor) + throws XmlPullParserException, IOException { + try (Reader reader = xmlSource.get()) { + XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance(); + xmlPullParserFactory.setNamespaceAware(false); + + XmlPullParser parser = xmlPullParserFactory.newPullParser(); + parser.setInput(reader); + + /* + * The expected XML structure is: + * <telephony_lookup> + * <networks> + * <network mcc="123" mnc="456" country="ab"/> + * <network mcc="123" mnc="567" country="cd"/> + * </networks> + * </telephony_lookup> + */ + + findNextStartTagOrThrowNoRecurse(parser, TELEPHONY_LOOKUP_ELEMENT); + + // There is only one expected sub-element <telephony_lookup> in the format currently, + // skip over anything before it. + findNextStartTagOrThrowNoRecurse(parser, NETWORKS_ELEMENT); + + processNetworks(parser, processor); + + // Make sure we are on the </networks> tag. + checkOnEndTag(parser, NETWORKS_ELEMENT); + + // Advance to the next event. + parser.next(); + + // Skip anything until </telephony_lookup>, and make sure the file is not truncated and + // we can find the end. + consumeUntilEndTag(parser, TELEPHONY_LOOKUP_ELEMENT); + + // Make sure we are on the </telephony_lookup> tag. + checkOnEndTag(parser, TELEPHONY_LOOKUP_ELEMENT); + } + } + + private static void processNetworks(XmlPullParser parser, + TelephonyNetworkProcessor processor) throws IOException, XmlPullParserException { + + // Skip over any unexpected elements and process <network> elements. + while (findNextStartTagOrEndTagNoRecurse(parser, NETWORK_ELEMENT)) { + String mcc = parser.getAttributeValue( + null /* namespace */, MOBILE_COUNTRY_CODE_ATTRIBUTE); + if (mcc == null) { + throw new XmlPullParserException( + "Unable to find mcc: " + parser.getPositionDescription()); + } + + String mnc = parser.getAttributeValue( + null /* namespace */, MOBILE_NETWORK_CODE_ATTRIBUTE); + if (mnc == null) { + throw new XmlPullParserException( + "Unable to find mnc: " + parser.getPositionDescription()); + } + + String countryCode = + parser.getAttributeValue(null /* namespace */, COUNTRY_ISO_CODE_ATTRIBUTE); + if (countryCode == null) { + throw new XmlPullParserException( + "Unable to find country: " + parser.getPositionDescription()); + } + + String debugInfo = parser.getPositionDescription(); + processor.processNetwork(mcc, mnc, countryCode, debugInfo); + // Advance to the next event. + parser.next(); + + // Skip anything until </network>. + consumeUntilEndTag(parser, NETWORK_ELEMENT); + } + } + + /** + * Processes <network> data. + */ + private interface TelephonyNetworkProcessor { + + boolean CONTINUE = true; + boolean HALT = false; + + /** + * Process network data. Problems with the data are reported as an exception. + */ + void processNetwork(String mcc, String mnc, String countryIso, String debugInfo) + throws XmlPullParserException; + } + + /** + * Validates <network> elements. Intended to be used before a proposed installation of new + * data. To be valid the MCC + MNC combination must generate a unique ID, country ISO code must + * be normalized. + */ + private static class TelephonyNetworkValidator implements TelephonyNetworkProcessor { + + private final Set<MccMnc> knownMccMncs = new HashSet<>(); + + @Override + public void processNetwork(String mcc, String mnc, String countryIso, String debugInfo) + throws XmlPullParserException { + if (mcc == null || mcc.length() != 3 || !isAsciiNumeric(mcc)) { + throw new XmlPullParserException( + "MCC is not valid: mcc=" + mcc + " at " + debugInfo); + } + + if (mnc == null || !(mnc.length() == 2 || mnc.length() == 3) || !isAsciiNumeric(mnc)) { + throw new XmlPullParserException( + "MNC is not valid: mnc=" + mnc + " at " + debugInfo); + } + + if (!normalizeCountryIso(countryIso).equals(countryIso)) { + throw new XmlPullParserException("Country code: " + countryIso + + " is not normalized at " + debugInfo); + } + + MccMnc mccMnc = new MccMnc(mcc, mnc); + if (knownMccMncs.contains(mccMnc)) { + throw new XmlPullParserException("Second entry for MCC + MNC: " + mccMnc + + " at " + debugInfo); + } + knownMccMncs.add(mccMnc); + } + + private static boolean isAsciiNumeric(String string) { + for (int i = 0; i < string.length(); i++) { + char character = string.charAt(i); + if (character < '0' || character > '9') { + return false; + } + } + return true; + } + } + + /** + * Reads all telephony network time zone information into memory and makes it available as a + * {@link TelephonyNetworkFinder}. + */ + private static class TelephonyNetworksExtractor implements TelephonyNetworkProcessor { + private List<TelephonyNetwork> networksList = new ArrayList<>(10 /* default */); + + @Override + public void processNetwork(String mcc, String mnc, String countryIso, String debugInfo) + throws XmlPullParserException { + TelephonyNetwork network = TelephonyNetwork.create(mcc, mnc, countryIso); + networksList.add(network); + } + + TelephonyNetworkFinder getTelephonyNetworkFinder() { + return TelephonyNetworkFinder.create(networksList); + } + } +} diff --git a/luni/src/main/java/libcore/timezone/TelephonyNetwork.java b/luni/src/main/java/libcore/timezone/TelephonyNetwork.java new file mode 100644 index 0000000000..e0f26ad43c --- /dev/null +++ b/luni/src/main/java/libcore/timezone/TelephonyNetwork.java @@ -0,0 +1,130 @@ +/* + * 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. + */ + +package libcore.timezone; + +import static libcore.timezone.XmlUtils.normalizeCountryIso; + +import java.util.Objects; + +/** + * Information about a telephony network. + * + * @hide + */ +@libcore.api.CorePlatformApi +public final class TelephonyNetwork { + + /** + * A numeric network identifier consisting of the Mobile Country Code (MCC) and the Mobile + * Network Code (MNC). + * + * @hide + */ + public static final class MccMnc { + final String mcc; + final String mnc; + + public MccMnc(String mcc, String mnc) { + this.mcc = mcc; + this.mnc = mnc; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MccMnc mccMnc = (MccMnc) o; + return Objects.equals(mcc, mccMnc.mcc) + && Objects.equals(mnc, mccMnc.mnc); + } + + @Override + public int hashCode() { + return Objects.hash(mcc, mnc); + } + + @Override + public String toString() { + return "MccMnc{" + + "mcc=" + mcc + + ", mnc=" + mnc + + '}'; + } + } + + private final MccMnc mccMnc; + private final String countryIsoCode; + + public static TelephonyNetwork create(String mcc, String mnc, String countryIsoCode) { + String normalizedCountryIso = normalizeCountryIso(countryIsoCode); + return new TelephonyNetwork(new MccMnc(mcc, mnc), normalizedCountryIso); + } + + private TelephonyNetwork(MccMnc mccMnc, String countryIsoCode) { + this.mccMnc = mccMnc; + this.countryIsoCode = Objects.requireNonNull(countryIsoCode); + } + + public MccMnc getMccMnc() { + return mccMnc; + } + + @libcore.api.CorePlatformApi + public String getMcc() { + return mccMnc.mcc; + } + + @libcore.api.CorePlatformApi + public String getMnc() { + return mccMnc.mnc; + } + + @libcore.api.CorePlatformApi + public String getCountryIsoCode() { + return countryIsoCode; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TelephonyNetwork that = (TelephonyNetwork) o; + return mccMnc.equals(that.mccMnc) && + countryIsoCode.equals(that.countryIsoCode); + } + + @Override + public int hashCode() { + return Objects.hash(mccMnc, countryIsoCode); + } + + @Override + public String toString() { + return "TelephonyNetwork{" + + "mccMnc=" + mccMnc + + ", countryIsoCode='" + countryIsoCode + '\'' + + '}'; + } +} diff --git a/luni/src/main/java/libcore/timezone/TelephonyNetworkFinder.java b/luni/src/main/java/libcore/timezone/TelephonyNetworkFinder.java new file mode 100644 index 0000000000..f2441594f2 --- /dev/null +++ b/luni/src/main/java/libcore/timezone/TelephonyNetworkFinder.java @@ -0,0 +1,82 @@ +/* + * 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. + */ + +package libcore.timezone; + +import static libcore.timezone.XmlUtils.normalizeCountryIso; + +import libcore.timezone.TelephonyNetwork.MccMnc; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * A class that can find telephony networks loaded via {@link TelephonyLookup}. + * @hide + */ +@libcore.api.CorePlatformApi +public final class TelephonyNetworkFinder { + + private final Map<MccMnc, TelephonyNetwork> networksMap; + private final List<TelephonyNetwork> networksList; + + public static TelephonyNetworkFinder create(List<TelephonyNetwork> networksList) { + Set<String> validCountryIsoCodes = new HashSet<>(); + for (String validCountryIsoCode : Locale.getISOCountries()) { + validCountryIsoCodes.add(normalizeCountryIso(validCountryIsoCode)); + } + + Map<MccMnc, TelephonyNetwork> networksMap = new HashMap<>(); + for (TelephonyNetwork network : networksList) { + if (!validCountryIsoCodes.contains(network.getCountryIsoCode())) { + System.logW("Unrecognized country code: " + network.getCountryIsoCode() + + " for telephony network=" + network); + } + + MccMnc mccMnc = network.getMccMnc(); + TelephonyNetwork existingEntry = networksMap.put(mccMnc, network); + if (existingEntry != null) { + System.logW("Duplicate MccMnc detected for " + mccMnc + + ". New entry=" + network + " replacing previous entry."); + } + } + return new TelephonyNetworkFinder( + Collections.unmodifiableList(new ArrayList<>(networksList)), + networksMap); + } + + private TelephonyNetworkFinder(List<TelephonyNetwork> networksList, + Map<MccMnc, TelephonyNetwork> networksMap) { + this.networksList = networksList; + this.networksMap = networksMap; + } + + @libcore.api.CorePlatformApi + public TelephonyNetwork findNetworkByMccMnc(String mcc, String mnc) { + return networksMap.get(new MccMnc(mcc, mnc)); + } + + // @VisibleForTesting + public List<TelephonyNetwork> getAll() { + return networksList; + } +} diff --git a/luni/src/main/java/libcore/timezone/TimeZoneDataFiles.java b/luni/src/main/java/libcore/timezone/TimeZoneDataFiles.java index 592fac18c4..b4c89761b2 100644 --- a/luni/src/main/java/libcore/timezone/TimeZoneDataFiles.java +++ b/luni/src/main/java/libcore/timezone/TimeZoneDataFiles.java @@ -27,7 +27,7 @@ import java.util.List; @libcore.api.CorePlatformApi public final class TimeZoneDataFiles { private static final String ANDROID_ROOT_ENV = "ANDROID_ROOT"; - private static final String ANDROID_RUNTIME_ROOT_ENV = "ANDROID_RUNTIME_ROOT"; + private static final String ANDROID_I18N_ROOT_ENV = "ANDROID_I18N_ROOT"; private static final String ANDROID_TZDATA_ROOT_ENV = "ANDROID_TZDATA_ROOT"; private static final String ANDROID_DATA_ENV = "ANDROID_DATA"; @@ -38,19 +38,14 @@ public final class TimeZoneDataFiles { * should be tried. See {@link #generateIcuDataPath()} for ICU files instead. * <ul> * <li>[0] - the location of the file in the /data partition (may not exist).</li> - * <li>[1] - the location of the file from the time zone module under /apex (may not exist). - * </li> - * <li>[2] - the location of the file from the runtime module under /apex (should exist).</li> + * <li>[1] - the location of the file from the time zone module under /apex (must exist).</li> * </ul> - * <li>[3] - the location of the file in the /system partition (should exist).</li> */ // VisibleForTesting public static String[] getTimeZoneFilePaths(String fileName) { return new String[] { getDataTimeZoneFile(fileName), - getTimeZoneModuleFile("tz/" + fileName), - getRuntimeModuleFile("tz/" + fileName), - getSystemTimeZoneFile(fileName) + getTimeZoneModuleTzFile(fileName), }; } @@ -60,26 +55,40 @@ public final class TimeZoneDataFiles { return System.getenv(ANDROID_DATA_ENV) + "/misc/zoneinfo/"; } + // Remove from CorePlatformApi when all users in platform code are removed. http://b/123398797 @libcore.api.CorePlatformApi public static String getDataTimeZoneFile(String fileName) { return getDataTimeZoneRootDir() + "current/" + fileName; } - public static String getTimeZoneModuleFile(String fileName) { - return System.getenv(ANDROID_TZDATA_ROOT_ENV) + "/etc/" + fileName; + public static String getTimeZoneModuleTzFile(String fileName) { + return getTimeZoneModuleFile("tz/" + fileName); + } + + public static String getTimeZoneModuleIcuFile(String fileName) { + return getTimeZoneModuleFile("icu/" + fileName); } // Remove from CorePlatformApi when all users in platform code are removed. http://b/123398797 @libcore.api.CorePlatformApi - public static String getRuntimeModuleTzVersionFile() { - return getRuntimeModuleFile("tz/" + TzDataSetVersion.DEFAULT_FILE_NAME); + public static String getTimeZoneModuleTzVersionFile() { + return getTimeZoneModuleTzFile(TzDataSetVersion.DEFAULT_FILE_NAME); + } + + // VisibleForTesting + public static String getTimeZoneModuleFile(String fileName) { + return System.getenv(ANDROID_TZDATA_ROOT_ENV) + "/etc/" + fileName; + } + + public static String getI18nModuleIcuFile(String fileName) { + return getI18nModuleFile("icu/" + fileName); } - public static String getRuntimeModuleFile(String fileName) { - return System.getenv(ANDROID_RUNTIME_ROOT_ENV) + "/etc/" + fileName; + private static String getI18nModuleFile(String fileName) { + return System.getenv(ANDROID_I18N_ROOT_ENV) + "/etc/" + fileName; } - public static String getSystemTimeZoneFile(String fileName) { + public static String getSystemTzFile(String fileName) { return getEnvironmentPath(ANDROID_ROOT_ENV, "/usr/share/zoneinfo/" + fileName); } @@ -90,6 +99,9 @@ public final class TimeZoneDataFiles { public static String generateIcuDataPath() { List<String> paths = new ArrayList<>(3); + // Note: This logic below should match the logic in IcuRegistration.cpp in external/icu/ + // to ensure consistent behavior between ICU4C and ICU4J. + // ICU should first look in ANDROID_DATA. This is used for (optional) time zone data // delivered by APK (https://source.android.com/devices/tech/config/timezone-rules) String dataIcuDataPath = @@ -100,17 +112,14 @@ public final class TimeZoneDataFiles { // ICU should then look for a mounted time zone module file in /apex. This is used for // (optional) time zone data that can be updated with an APEX file. - String timeZoneModuleIcuDataPath = getTimeZoneModuleFile("icu/"); - if (timeZoneModuleIcuDataPath != null) { - paths.add(timeZoneModuleIcuDataPath); - } + String timeZoneModuleIcuDataPath = getTimeZoneModuleIcuFile(""); + paths.add(timeZoneModuleIcuDataPath); - // ICU should always look in the runtime module path as this is where most of the data + // ICU should always look in the i18n module path as this is where most of the data // can be found. - String runtimeModuleIcuDataPath = getRuntimeModuleFile("icu/"); - if (runtimeModuleIcuDataPath != null) { - paths.add(runtimeModuleIcuDataPath); - } + String i18nModuleIcuDataPath = getI18nModuleIcuFile(""); + paths.add(i18nModuleIcuDataPath); + return String.join(":", paths); } diff --git a/luni/src/main/java/libcore/timezone/TimeZoneFinder.java b/luni/src/main/java/libcore/timezone/TimeZoneFinder.java index eebe8cc49f..3f18e36ae0 100644 --- a/luni/src/main/java/libcore/timezone/TimeZoneFinder.java +++ b/luni/src/main/java/libcore/timezone/TimeZoneFinder.java @@ -16,30 +16,31 @@ package libcore.timezone; +import static libcore.timezone.XmlUtils.checkOnEndTag; +import static libcore.timezone.XmlUtils.consumeText; +import static libcore.timezone.XmlUtils.consumeUntilEndTag; +import static libcore.timezone.XmlUtils.findNextStartTagOrEndTagNoRecurse; +import static libcore.timezone.XmlUtils.findNextStartTagOrThrowNoRecurse; +import static libcore.timezone.XmlUtils.normalizeCountryIso; +import static libcore.timezone.XmlUtils.parseBooleanAttribute; +import static libcore.timezone.XmlUtils.parseLongAttribute; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; -import android.icu.util.TimeZone; - -import java.io.FileNotFoundException; import java.io.IOException; import java.io.Reader; -import java.io.StringReader; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Set; import libcore.timezone.CountryTimeZones.TimeZoneMapping; +import libcore.timezone.XmlUtils.ReaderSupplier; /** * A class that can find matching time zones by loading data from the tzlookup.xml file. @@ -48,7 +49,8 @@ import libcore.timezone.CountryTimeZones.TimeZoneMapping; @libcore.api.CorePlatformApi public final class TimeZoneFinder { - private static final String TZLOOKUP_FILE_NAME = "tzlookup.xml"; + // VisibleForTesting + public static final String TZLOOKUP_FILE_NAME = "tzlookup.xml"; // Root element. e.g. <timezones ianaversion="2017b"> private static final String TIMEZONES_ELEMENT = "timezones"; @@ -57,10 +59,12 @@ public final class TimeZoneFinder { // Country zones section. e.g. <countryzones> private static final String COUNTRY_ZONES_ELEMENT = "countryzones"; - // Country data. e.g. <country code="gb" default="Europe/London" everutc="y"> + // Country data. e.g. + // <country code="gb" default="Europe/London" defaultBoost="y" everutc="y"> private static final String COUNTRY_ELEMENT = "country"; private static final String COUNTRY_CODE_ATTRIBUTE = "code"; private static final String DEFAULT_TIME_ZONE_ID_ATTRIBUTE = "default"; + private static final String DEFAULT_TIME_ZONE_BOOST_ATTRIBUTE = "defaultBoost"; private static final String EVER_USES_UTC_ATTRIBUTE = "everutc"; // Country -> Time zone mapping. e.g. <id>ZoneId</id>, <id picker="n">ZoneId</id>, @@ -73,9 +77,6 @@ public final class TimeZoneFinder { private static final String ZONE_SHOW_IN_PICKER_ATTRIBUTE = "picker"; private static final String ZONE_NOT_USED_AFTER_ATTRIBUTE = "notafter"; - private static final String TRUE_ATTRIBUTE_VALUE = "y"; - private static final String FALSE_ATTRIBUTE_VALUE = "n"; - private static TimeZoneFinder instance; private final ReaderSupplier xmlSource; @@ -191,72 +192,6 @@ public final class TimeZoneFinder { } /** - * Returns a frozen ICU time zone that has / would have had the specified offset and DST value - * at the specified moment in the specified country. - * - * <p>In order to be considered a configured zone must match the supplied offset information. - * - * <p>Matches are considered in a well-defined order. If multiple zones match and one of them - * also matches the (optional) bias parameter then the bias time zone will be returned. - * Otherwise the first match found is returned. - */ - @libcore.api.CorePlatformApi - public TimeZone lookupTimeZoneByCountryAndOffset( - String countryIso, int offsetMillis, boolean isDst, long whenMillis, TimeZone bias) { - - CountryTimeZones countryTimeZones = lookupCountryTimeZones(countryIso); - if (countryTimeZones == null) { - return null; - } - CountryTimeZones.OffsetResult offsetResult = - countryTimeZones.lookupByOffsetWithBias(offsetMillis, isDst, whenMillis, bias); - return offsetResult != null ? offsetResult.mTimeZone : null; - } - - /** - * Returns a "default" time zone ID known to be used in the specified country. This is - * the time zone ID that can be used if only the country code is known and can be presumed to be - * the "best" choice in the absence of other information. For countries with more than one zone - * the time zone will not be correct for everybody. - * - * <p>If the country code is not recognized or there is an error during lookup this can return - * null. - */ - @libcore.api.CorePlatformApi - public String lookupDefaultTimeZoneIdByCountry(String countryIso) { - CountryTimeZones countryTimeZones = lookupCountryTimeZones(countryIso); - return countryTimeZones == null ? null : countryTimeZones.getDefaultTimeZoneId(); - } - - /** - * Returns an immutable list of frozen ICU time zones known to be used in the specified country. - * If the country code is not recognized or there is an error during lookup this can return - * null. The TimeZones returned will never contain {@link TimeZone#UNKNOWN_ZONE}. This method - * can return an empty list in a case when the underlying data files reference only unknown - * zone IDs. - */ - @libcore.api.CorePlatformApi - public List<TimeZone> lookupTimeZonesByCountry(String countryIso) { - CountryTimeZones countryTimeZones = lookupCountryTimeZones(countryIso); - return countryTimeZones == null ? null : countryTimeZones.getIcuTimeZones(); - } - - /** - * Returns an immutable list of time zone IDs known to be used in the specified country. - * If the country code is not recognized or there is an error during lookup this can return - * null. The IDs returned will all be valid for use with - * {@link java.util.TimeZone#getTimeZone(String)} and - * {@link android.icu.util.TimeZone#getTimeZone(String)}. This method can return an empty list - * in a case when the underlying data files reference only unknown zone IDs. - */ - @libcore.api.CorePlatformApi - public List<String> lookupTimeZoneIdsByCountry(String countryIso) { - CountryTimeZones countryTimeZones = lookupCountryTimeZones(countryIso); - return countryTimeZones == null - ? null : extractTimeZoneIds(countryTimeZones.getTimeZoneMappings()); - } - - /** * Returns a {@link CountryTimeZones} object associated with the specified country code. * Caching is handled as needed. If the country code is not recognized or there is an error * during lookup this method can return null. @@ -295,9 +230,9 @@ public final class TimeZoneFinder { /** * Processes the XML, applying the {@link TimeZonesProcessor} to the <countryzones> - * element. Processing can terminate early if the - * {@link TimeZonesProcessor#processCountryZones(String, String, boolean, List, String)} returns - * {@link TimeZonesProcessor#HALT} or it throws an exception. + * element. Processing can terminate early if the {@link TimeZonesProcessor#processCountryZones( + * String, String, boolean, boolean, List, String)} returns {@link TimeZonesProcessor#HALT} or + * it throws an exception. */ private void processXml(TimeZonesProcessor processor) throws XmlPullParserException, IOException { @@ -319,14 +254,14 @@ public final class TimeZoneFinder { * ... * <id>America/Los_Angeles</id> * </country> - * <country code="gb" default="Europe/London"> + * <country code="gb" default="Europe/London" defaultBoost="y"> * <id>Europe/London</id> * </country> * </countryzones> * </timezones> */ - findRequiredStartTag(parser, TIMEZONES_ELEMENT); + findNextStartTagOrThrowNoRecurse(parser, TIMEZONES_ELEMENT); // We do not require the ianaversion attribute be present. It is metadata that helps // with versioning but is not required. @@ -338,7 +273,7 @@ public final class TimeZoneFinder { // There is only one expected sub-element <countryzones> in the format currently, skip // over anything before it. - findRequiredStartTag(parser, COUNTRY_ZONES_ELEMENT); + findNextStartTagOrThrowNoRecurse(parser, COUNTRY_ZONES_ELEMENT); if (processCountryZones(parser, processor) == TimeZonesProcessor.HALT) { return; @@ -363,38 +298,39 @@ public final class TimeZoneFinder { TimeZonesProcessor processor) throws IOException, XmlPullParserException { // Skip over any unexpected elements and process <country> elements. - while (findOptionalStartTag(parser, COUNTRY_ELEMENT)) { - if (processor == null) { - consumeUntilEndTag(parser, COUNTRY_ELEMENT); - } else { - String code = parser.getAttributeValue( - null /* namespace */, COUNTRY_CODE_ATTRIBUTE); - if (code == null || code.isEmpty()) { - throw new XmlPullParserException( - "Unable to find country code: " + parser.getPositionDescription()); - } - String defaultTimeZoneId = parser.getAttributeValue( - null /* namespace */, DEFAULT_TIME_ZONE_ID_ATTRIBUTE); - if (defaultTimeZoneId == null || defaultTimeZoneId.isEmpty()) { - throw new XmlPullParserException("Unable to find default time zone ID: " - + parser.getPositionDescription()); - } - Boolean everUsesUtc = parseBooleanAttribute( - parser, EVER_USES_UTC_ATTRIBUTE, null /* defaultValue */); - if (everUsesUtc == null) { - // There is no valid default: we require this to be specified. - throw new XmlPullParserException( - "Unable to find UTC hint attribute (" + EVER_USES_UTC_ATTRIBUTE + "): " - + parser.getPositionDescription()); - } + while (findNextStartTagOrEndTagNoRecurse(parser, COUNTRY_ELEMENT)) { + String code = parser.getAttributeValue( + null /* namespace */, COUNTRY_CODE_ATTRIBUTE); + if (code == null || code.isEmpty()) { + throw new XmlPullParserException( + "Unable to find country code: " + parser.getPositionDescription()); + } - String debugInfo = parser.getPositionDescription(); - List<TimeZoneMapping> timeZoneMappings = parseTimeZoneMappings(parser); - boolean result = processor.processCountryZones(code, defaultTimeZoneId, everUsesUtc, - timeZoneMappings, debugInfo); - if (result == TimeZonesProcessor.HALT) { - return TimeZonesProcessor.HALT; - } + String defaultTimeZoneId = parser.getAttributeValue( + null /* namespace */, DEFAULT_TIME_ZONE_ID_ATTRIBUTE); + if (defaultTimeZoneId == null || defaultTimeZoneId.isEmpty()) { + throw new XmlPullParserException("Unable to find default time zone ID: " + + parser.getPositionDescription()); + } + + boolean defaultTimeZoneBoost = parseBooleanAttribute(parser, + DEFAULT_TIME_ZONE_BOOST_ATTRIBUTE, false); + + Boolean everUsesUtc = parseBooleanAttribute( + parser, EVER_USES_UTC_ATTRIBUTE, null /* defaultValue */); + if (everUsesUtc == null) { + // There is no valid default: we require this to be specified. + throw new XmlPullParserException( + "Unable to find UTC hint attribute (" + EVER_USES_UTC_ATTRIBUTE + "): " + + parser.getPositionDescription()); + } + + String debugInfo = parser.getPositionDescription(); + List<TimeZoneMapping> timeZoneMappings = parseTimeZoneMappings(parser); + boolean result = processor.processCountryZones(code, defaultTimeZoneId, + defaultTimeZoneBoost, everUsesUtc, timeZoneMappings, debugInfo); + if (result == TimeZonesProcessor.HALT) { + return TimeZonesProcessor.HALT; } // Make sure we are on the </country> element. @@ -409,7 +345,7 @@ public final class TimeZoneFinder { List<TimeZoneMapping> timeZoneMappings = new ArrayList<>(); // Skip over any unexpected elements and process <id> elements. - while (findOptionalStartTag(parser, ZONE_ID_ELEMENT)) { + while (findNextStartTagOrEndTagNoRecurse(parser, ZONE_ID_ELEMENT)) { // The picker attribute is optional and defaulted to true. boolean showInPicker = parseBooleanAttribute( parser, ZONE_SHOW_IN_PICKER_ATTRIBUTE, true /* defaultValue */); @@ -436,177 +372,6 @@ public final class TimeZoneFinder { } /** - * Parses an attribute value, which must be either {@code null} or a valid signed long value. - * If the attribute value is {@code null} then {@code defaultValue} is returned. If the - * attribute is present but not a valid long value then an XmlPullParserException is thrown. - */ - private static Long parseLongAttribute(XmlPullParser parser, String attributeName, - Long defaultValue) throws XmlPullParserException { - String attributeValueString = parser.getAttributeValue(null /* namespace */, attributeName); - if (attributeValueString == null) { - return defaultValue; - } - try { - return Long.parseLong(attributeValueString); - } catch (NumberFormatException e) { - throw new XmlPullParserException("Attribute \"" + attributeName - + "\" is not a long value: " + parser.getPositionDescription()); - } - } - - /** - * Parses an attribute value, which must be either {@code null}, {@code "y"} or {@code "n"}. - * If the attribute value is {@code null} then {@code defaultValue} is returned. If the - * attribute is present but not "y" or "n" then an XmlPullParserException is thrown. - */ - private static Boolean parseBooleanAttribute(XmlPullParser parser, - String attributeName, Boolean defaultValue) throws XmlPullParserException { - String attributeValueString = parser.getAttributeValue(null /* namespace */, attributeName); - if (attributeValueString == null) { - return defaultValue; - } - boolean isTrue = TRUE_ATTRIBUTE_VALUE.equals(attributeValueString); - if (!(isTrue || FALSE_ATTRIBUTE_VALUE.equals(attributeValueString))) { - throw new XmlPullParserException("Attribute \"" + attributeName - + "\" is not \"y\" or \"n\": " + parser.getPositionDescription()); - } - return isTrue; - } - - private static void findRequiredStartTag(XmlPullParser parser, String elementName) - throws IOException, XmlPullParserException { - findStartTag(parser, elementName, true /* elementRequired */); - } - - /** Called when on a START_TAG. When returning false, it leaves the parser on the END_TAG. */ - private static boolean findOptionalStartTag(XmlPullParser parser, String elementName) - throws IOException, XmlPullParserException { - return findStartTag(parser, elementName, false /* elementRequired */); - } - - /** - * Find a START_TAG with the specified name without decreasing the depth, or increasing the - * depth by more than one. More deeply nested elements and text are skipped, even START_TAGs - * with matching names. Returns when the START_TAG is found or the next (non-nested) END_TAG is - * encountered. The return can take the form of an exception or a false if the START_TAG is not - * found. True is returned when it is. - */ - private static boolean findStartTag( - XmlPullParser parser, String elementName, boolean elementRequired) - throws IOException, XmlPullParserException { - - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { - switch (type) { - case XmlPullParser.START_TAG: - String currentElementName = parser.getName(); - if (elementName.equals(currentElementName)) { - return true; - } - - // It was not the START_TAG we were looking for. Consume until the end. - parser.next(); - consumeUntilEndTag(parser, currentElementName); - break; - case XmlPullParser.END_TAG: - if (elementRequired) { - throw new XmlPullParserException( - "No child element found with name " + elementName); - } - return false; - default: - // Ignore. - break; - } - } - throw new XmlPullParserException("Unexpected end of document while looking for " - + elementName); - } - - /** - * Consume the remaining contents of an element and move to the END_TAG. Used when processing - * within an element can stop. The parser must be pointing at either the END_TAG we are looking - * for, a TEXT, or a START_TAG nested within the element to be consumed. - */ - private static void consumeUntilEndTag(XmlPullParser parser, String elementName) - throws IOException, XmlPullParserException { - - if (parser.getEventType() == XmlPullParser.END_TAG - && elementName.equals(parser.getName())) { - // Early return - we are already there. - return; - } - - // Keep track of the required depth in case there are nested elements to be consumed. - // Both the name and the depth must match our expectation to complete. - - int requiredDepth = parser.getDepth(); - // A TEXT tag would be at the same depth as the END_TAG we are looking for. - if (parser.getEventType() == XmlPullParser.START_TAG) { - // A START_TAG would have incremented the depth, so we're looking for an END_TAG one - // higher than the current tag. - requiredDepth--; - } - - while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { - int type = parser.next(); - - int currentDepth = parser.getDepth(); - if (currentDepth < requiredDepth) { - throw new XmlPullParserException( - "Unexpected depth while looking for end tag: " - + parser.getPositionDescription()); - } else if (currentDepth == requiredDepth) { - if (type == XmlPullParser.END_TAG) { - if (elementName.equals(parser.getName())) { - return; - } - throw new XmlPullParserException( - "Unexpected eng tag: " + parser.getPositionDescription()); - } - } - // Everything else is either a type we are not interested in or is too deep and so is - // ignored. - } - throw new XmlPullParserException("Unexpected end of document"); - } - - /** - * Reads the text inside the current element. Should be called when the parser is currently - * on the START_TAG before the TEXT. The parser will be positioned on the END_TAG after this - * call when it completes successfully. - */ - private static String consumeText(XmlPullParser parser) - throws IOException, XmlPullParserException { - - int type = parser.next(); - String text; - if (type == XmlPullParser.TEXT) { - text = parser.getText(); - } else { - throw new XmlPullParserException("Text not found. Found type=" + type - + " at " + parser.getPositionDescription()); - } - - type = parser.next(); - if (type != XmlPullParser.END_TAG) { - throw new XmlPullParserException( - "Unexpected nested tag or end of document when expecting text: type=" + type - + " at " + parser.getPositionDescription()); - } - return text; - } - - private static void checkOnEndTag(XmlPullParser parser, String elementName) - throws XmlPullParserException { - if (!(parser.getEventType() == XmlPullParser.END_TAG - && parser.getName().equals(elementName))) { - throw new XmlPullParserException( - "Unexpected tag encountered: " + parser.getPositionDescription()); - } - } - - /** * Processes <timezones> data. */ private interface TimeZonesProcessor { @@ -633,7 +398,8 @@ public final class TimeZoneFinder { * <p>The default implementation returns {@link #CONTINUE}. */ default boolean processCountryZones(String countryIso, String defaultTimeZoneId, - boolean everUsesUtc, List<TimeZoneMapping> timeZoneMappings, String debugInfo) + boolean defaultTimeZoneBoost, boolean everUsesUtc, + List<TimeZoneMapping> timeZoneMappings, String debugInfo) throws XmlPullParserException { return CONTINUE; } @@ -653,7 +419,8 @@ public final class TimeZoneFinder { @Override public boolean processCountryZones(String countryIso, String defaultTimeZoneId, - boolean everUsesUtc, List<TimeZoneMapping> timeZoneMappings, String debugInfo) + boolean defaultTimeZoneBoost, boolean everUsesUtc, + List<TimeZoneMapping> timeZoneMappings, String debugInfo) throws XmlPullParserException { if (!normalizeCountryIso(countryIso).equals(countryIso)) { throw new XmlPullParserException("Country code: " + countryIso @@ -706,11 +473,13 @@ public final class TimeZoneFinder { @Override public boolean processCountryZones(String countryIso, String defaultTimeZoneId, - boolean everUsesUtc, List<TimeZoneMapping> timeZoneMappings, String debugInfo) + boolean defaultTimeZoneBoost, boolean everUsesUtc, + List<TimeZoneMapping> timeZoneMappings, String debugInfo) throws XmlPullParserException { CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - countryIso, defaultTimeZoneId, everUsesUtc, timeZoneMappings, debugInfo); + countryIso, defaultTimeZoneId, defaultTimeZoneBoost, everUsesUtc, + timeZoneMappings, debugInfo); countryTimeZonesList.add(countryTimeZones); return CONTINUE; } @@ -736,13 +505,15 @@ public final class TimeZoneFinder { @Override public boolean processCountryZones(String countryIso, String defaultTimeZoneId, - boolean everUsesUtc, List<TimeZoneMapping> timeZoneMappings, String debugInfo) { + boolean defaultTimeZoneBoost, boolean everUsesUtc, + List<TimeZoneMapping> timeZoneMappings, String debugInfo) { countryIso = normalizeCountryIso(countryIso); if (!countryCodeToMatch.equals(countryIso)) { return CONTINUE; } validatedCountryTimeZones = CountryTimeZones.createValidated(countryIso, - defaultTimeZoneId, everUsesUtc, timeZoneMappings, debugInfo); + defaultTimeZoneId, defaultTimeZoneBoost, everUsesUtc, timeZoneMappings, + debugInfo); return HALT; } @@ -755,40 +526,4 @@ public final class TimeZoneFinder { } } - /** - * A source of Readers that can be used repeatedly. - */ - private interface ReaderSupplier { - /** Returns a Reader. Throws an IOException if the Reader cannot be created. */ - Reader get() throws IOException; - - static ReaderSupplier forFile(String fileName, Charset charSet) throws IOException { - Path file = Paths.get(fileName); - if (!Files.exists(file)) { - throw new FileNotFoundException(fileName + " does not exist"); - } - if (!Files.isRegularFile(file) && Files.isReadable(file)) { - throw new IOException(fileName + " must be a regular readable file."); - } - return () -> Files.newBufferedReader(file, charSet); - } - - static ReaderSupplier forString(String xml) { - return () -> new StringReader(xml); - } - } - - private static List<String> extractTimeZoneIds(List<TimeZoneMapping> timeZoneMappings) { - List<String> zoneIds = new ArrayList<>(timeZoneMappings.size()); - for (TimeZoneMapping timeZoneMapping : timeZoneMappings) { - zoneIds.add(timeZoneMapping.timeZoneId); - } - return Collections.unmodifiableList(zoneIds); - } - - static String normalizeCountryIso(String countryIso) { - // Lowercase ASCII is normalized for the purposes of the input files and the code in this - // class and related classes. - return countryIso.toLowerCase(Locale.US); - } } diff --git a/luni/src/main/java/libcore/timezone/TzDataSetVersion.java b/luni/src/main/java/libcore/timezone/TzDataSetVersion.java index 2ba64a01f3..8b97069bac 100644 --- a/luni/src/main/java/libcore/timezone/TzDataSetVersion.java +++ b/luni/src/main/java/libcore/timezone/TzDataSetVersion.java @@ -29,7 +29,7 @@ import java.util.regex.Pattern; * @hide */ @libcore.api.CorePlatformApi -public class TzDataSetVersion { +public final class TzDataSetVersion { // Remove from CorePlatformApi when all users in platform code are removed. http://b/123398797 /** @@ -45,7 +45,7 @@ public class TzDataSetVersion { * version to 1 when doing so. */ // @VisibleForTesting : Keep this inline-able: it is used from CTS tests. - public static final int CURRENT_FORMAT_MAJOR_VERSION = 3; // Android Q + public static final int CURRENT_FORMAT_MAJOR_VERSION = 4; // Android R /** * Returns the major tz data format version supported by this device. @@ -102,14 +102,10 @@ public class TzDataSetVersion { + REVISION_PATTERN.pattern() + ".*" /* ignore trailing */); - public final int formatMajorVersion; - public final int formatMinorVersion; - - // Remove from CorePlatformApi when all users in platform code are removed. http://b/123398797 - @libcore.api.CorePlatformApi - public final String rulesVersion; - - public final int revision; + private final int formatMajorVersion; + private final int formatMinorVersion; + private final String rulesVersion; + private final int revision; @libcore.api.CorePlatformApi public TzDataSetVersion(int formatMajorVersion, int formatMinorVersion, String rulesVersion, @@ -155,6 +151,38 @@ public class TzDataSetVersion { return fromBytes(versionBytes); } + /** + * Reads the version of time zone data supplied by the time zone data module. + */ + @libcore.api.CorePlatformApi + public static TzDataSetVersion readTimeZoneModuleVersion() + throws IOException, TzDataSetException { + String tzVersionFileName = + TimeZoneDataFiles.getTimeZoneModuleTzFile(TzDataSetVersion.DEFAULT_FILE_NAME); + return readFromFile(new File(tzVersionFileName)); + } + + @libcore.api.CorePlatformApi + public int getFormatMajorVersion() { + return formatMajorVersion; + } + + @libcore.api.CorePlatformApi + public int getFormatMinorVersion() { + return formatMinorVersion; + } + + @libcore.api.CorePlatformApi + public String getRulesVersion() { + return rulesVersion; + } + + // Remove from CorePlatformApi when all users in platform code are removed. http://b/123398797 + @libcore.api.CorePlatformApi + public int getRevision() { + return revision; + } + // Remove from CorePlatformApi when all users in platform code are removed. http://b/123398797 @libcore.api.CorePlatformApi public byte[] toBytes() { diff --git a/luni/src/main/java/libcore/timezone/XmlUtils.java b/luni/src/main/java/libcore/timezone/XmlUtils.java new file mode 100644 index 0000000000..a9616f96e9 --- /dev/null +++ b/luni/src/main/java/libcore/timezone/XmlUtils.java @@ -0,0 +1,254 @@ +/* + * 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. + */ + +package libcore.timezone; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Locale; + +class XmlUtils { + + private static final String TRUE_ATTRIBUTE_VALUE = "y"; + + private static final String FALSE_ATTRIBUTE_VALUE = "n"; + + private XmlUtils() {} + + /** + * Parses an attribute value, which must be either {@code null} or a valid signed long value. + * If the attribute value is {@code null} then {@code defaultValue} is returned. If the + * attribute is present but not a valid long value then an XmlPullParserException is thrown. + */ + static Long parseLongAttribute(XmlPullParser parser, String attributeName, + Long defaultValue) throws XmlPullParserException { + String attributeValueString = parser.getAttributeValue(null /* namespace */, attributeName); + if (attributeValueString == null) { + return defaultValue; + } + try { + return Long.parseLong(attributeValueString); + } catch (NumberFormatException e) { + throw new XmlPullParserException("Attribute \"" + attributeName + + "\" is not a long value: " + parser.getPositionDescription()); + } + } + + /** + * Parses an attribute value, which must be either {@code null}, {@code "y"} or {@code "n"}. + * If the attribute value is {@code null} then {@code defaultValue} is returned. If the + * attribute is present but not "y" or "n" then an XmlPullParserException is thrown. + */ + static Boolean parseBooleanAttribute(XmlPullParser parser, + String attributeName, Boolean defaultValue) throws XmlPullParserException { + String attributeValueString = parser.getAttributeValue(null /* namespace */, attributeName); + if (attributeValueString == null) { + return defaultValue; + } + boolean isTrue = TRUE_ATTRIBUTE_VALUE.equals(attributeValueString); + if (!(isTrue || FALSE_ATTRIBUTE_VALUE.equals(attributeValueString))) { + throw new XmlPullParserException("Attribute \"" + attributeName + + "\" is not \"y\" or \"n\": " + parser.getPositionDescription()); + } + return isTrue; + } + + /** + * Advances the the parser to the START_TAG for the specified element without decreasing the + * depth, or increasing the depth by more than one (i.e. no recursion into child nodes). + * If the next (non-nested) END_TAG an exception is thrown. Throws an exception if the end of + * the document is encountered unexpectedly. + */ + static void findNextStartTagOrThrowNoRecurse(XmlPullParser parser, String elementName) + throws IOException, XmlPullParserException { + if (!findNextStartTagOrEndTagNoRecurse(parser, elementName)) { + throw new XmlPullParserException("No next element found with name " + elementName); + } + } + + /** + * Advances the the parser to the START_TAG for the specified element without decreasing the + * depth, or increasing the depth by more than one (i.e. no recursion into child nodes). + * Returns {@code true} if the requested START_TAG is found, or {@code false} when the next + * (non-nested) END_TAG is encountered instead. Throws an exception if the end of the document + * is encountered unexpectedly. + */ + static boolean findNextStartTagOrEndTagNoRecurse(XmlPullParser parser, String elementName) + throws IOException, XmlPullParserException { + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { + switch (type) { + case XmlPullParser.START_TAG: + String currentElementName = parser.getName(); + if (elementName.equals(currentElementName)) { + return true; + } + + // It was not the START_TAG we were looking for. Consume until the end. + parser.next(); + consumeUntilEndTag(parser, currentElementName); + break; + case XmlPullParser.END_TAG: + return false; + default: + // Ignore. + break; + } + } + throw new XmlPullParserException("Unexpected end of document while looking for " + + elementName); + } + + /** + * Consume any remaining contents of an element and move to the END_TAG. Used when processing + * within an element can stop. + * + * <p>When called, the parser must be pointing at one of: + * <ul> + * <li>the END_TAG we are looking for</li> + * <li>a TEXT</li> + * <li>a START_TAG nested within the element that can be consumed</li> + * </ul> + * Note: The parser synthesizes an END_TAG for self-closing tags so this works for them too. + */ + static void consumeUntilEndTag(XmlPullParser parser, String elementName) + throws IOException, XmlPullParserException { + + if (isEndTag(parser, elementName)) { + // Early return - we are already there. + return; + } + + // Keep track of the required depth in case there are nested elements to be consumed. + // Both the name and the depth must match our expectation to complete. + + int requiredDepth = parser.getDepth(); + // A TEXT tag would be at the same depth as the END_TAG we are looking for. + if (parser.getEventType() == XmlPullParser.START_TAG) { + // A START_TAG would have incremented the depth, so we're looking for an END_TAG one + // higher than the current tag. + requiredDepth--; + } + + while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { + int type = parser.next(); + + int currentDepth = parser.getDepth(); + if (currentDepth < requiredDepth) { + throw new XmlPullParserException( + "Unexpected depth while looking for end tag: " + + parser.getPositionDescription()); + } else if (currentDepth == requiredDepth) { + if (type == XmlPullParser.END_TAG) { + if (elementName.equals(parser.getName())) { + return; + } + throw new XmlPullParserException( + "Unexpected eng tag: " + parser.getPositionDescription()); + } + } + // Everything else is either a type we are not interested in or is too deep and so is + // ignored. + } + throw new XmlPullParserException("Unexpected end of document"); + } + + /** + * Throws an exception if the current element is not an end tag. + * Note: The parser synthesizes an END_TAG for self-closing tags so this works for them too. + */ + static void checkOnEndTag(XmlPullParser parser, String elementName) + throws XmlPullParserException { + if (!isEndTag(parser, elementName)) { + throw new XmlPullParserException( + "Unexpected tag encountered: " + parser.getPositionDescription()); + } + } + + /** + * Returns true if the current tag is an end tag. + * Note: The parser synthesizes an END_TAG for self-closing tags so this works for them too. + */ + private static boolean isEndTag(XmlPullParser parser, String elementName) + throws XmlPullParserException { + return parser.getEventType() == XmlPullParser.END_TAG + && parser.getName().equals(elementName); + } + + static String normalizeCountryIso(String countryIso) { + // Lowercase ASCII is normalized for the purposes of the input files and the code in this + // class and related classes. + return countryIso.toLowerCase(Locale.US); + } + + /** + * Reads the text inside the current element. Should be called when the parser is currently + * on the START_TAG before the TEXT. The parser will be positioned on the END_TAG after this + * call when it completes successfully. + */ + static String consumeText(XmlPullParser parser) + throws IOException, XmlPullParserException { + + int type = parser.next(); + String text; + if (type == XmlPullParser.TEXT) { + text = parser.getText(); + } else { + throw new XmlPullParserException("Text not found. Found type=" + type + + " at " + parser.getPositionDescription()); + } + + type = parser.next(); + if (type != XmlPullParser.END_TAG) { + throw new XmlPullParserException( + "Unexpected nested tag or end of document when expecting text: type=" + type + + " at " + parser.getPositionDescription()); + } + return text; + } + + /** + * A source of Readers that can be used repeatedly. + */ + interface ReaderSupplier { + /** Returns a Reader. Throws an IOException if the Reader cannot be created. */ + Reader get() throws IOException; + + static ReaderSupplier forFile(String fileName, Charset charSet) throws IOException { + Path file = Paths.get(fileName); + if (!Files.exists(file)) { + throw new FileNotFoundException(fileName + " does not exist"); + } + if (!Files.isRegularFile(file) && Files.isReadable(file)) { + throw new IOException(fileName + " must be a regular readable file."); + } + return () -> Files.newBufferedReader(file, charSet); + } + + static ReaderSupplier forString(String xml) { + return () -> new StringReader(xml); + } + } +} diff --git a/luni/src/main/java/libcore/timezone/ZoneInfoDB.java b/luni/src/main/java/libcore/timezone/ZoneInfoDB.java deleted file mode 100644 index ca29319cee..0000000000 --- a/luni/src/main/java/libcore/timezone/ZoneInfoDB.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package libcore.timezone; - -import android.system.ErrnoException; -import dalvik.annotation.optimization.ReachabilitySensitive; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import libcore.io.BufferIterator; -import libcore.io.MemoryMappedFile; -import libcore.util.BasicLruCache; -import libcore.util.ZoneInfo; - -/** - * A class used to initialize the time zone database. This implementation uses the - * Olson tzdata as the source of time zone information. However, to conserve - * disk space (inodes) and reduce I/O, all the data is concatenated into a single file, - * with an index to indicate the starting position of each time zone record. - * - * @hide - used to implement TimeZone - */ -@libcore.api.CorePlatformApi -public final class ZoneInfoDB { - - // VisibleForTesting - public static final String TZDATA_FILE = "tzdata"; - - private static final TzData DATA = - TzData.loadTzDataWithFallback(TimeZoneDataFiles.getTimeZoneFilePaths(TZDATA_FILE)); - - /** @hide */ - @libcore.api.CorePlatformApi - public static class TzData implements AutoCloseable { - - // The database reserves 40 bytes for each id. - private static final int SIZEOF_TZNAME = 40; - - // The database uses 32-bit (4 byte) integers. - private static final int SIZEOF_TZINT = 4; - - // Each index entry takes up this number of bytes. - public static final int SIZEOF_INDEX_ENTRY = SIZEOF_TZNAME + 3 * SIZEOF_TZINT; - - /** - * {@code true} if {@link #close()} has been called meaning the instance cannot provide any - * data. - */ - private boolean closed; - - /** - * Rather than open, read, and close the big data file each time we look up a time zone, - * we map the big data file during startup, and then just use the MemoryMappedFile. - * - * At the moment, this "big" data file is about 500 KiB. At some point, that will be small - * enough that we could just keep the byte[] in memory, but using mmap(2) like this has the - * nice property that even if someone replaces the file under us (because multiple gservices - * updates have gone out, say), we still get a consistent (if outdated) view of the world. - */ - // Android-added: @ReachabilitySensitive - @ReachabilitySensitive - private MemoryMappedFile mappedFile; - - private String version; - private String zoneTab; - - /** - * The 'ids' array contains time zone ids sorted alphabetically, for binary searching. - * The other two arrays are in the same order. 'byteOffsets' gives the byte offset - * of each time zone, and 'rawUtcOffsetsCache' gives the time zone's raw UTC offset. - */ - private String[] ids; - private int[] byteOffsets; - private int[] rawUtcOffsetsCache; // Access this via getRawUtcOffsets instead. - - /** - * ZoneInfo objects are worth caching because they are expensive to create. - * See http://b/8270865 for context. - */ - private final static int CACHE_SIZE = 1; - private final BasicLruCache<String, ZoneInfo> cache = - new BasicLruCache<String, ZoneInfo>(CACHE_SIZE) { - @Override - protected ZoneInfo create(String id) { - try { - return makeTimeZoneUncached(id); - } catch (IOException e) { - throw new IllegalStateException("Unable to load timezone for ID=" + id, e); - } - } - }; - - /** - * Loads the data at the specified paths in order, returning the first valid one as a - * {@link TzData} object. If there is no valid one found a basic fallback instance is created - * containing just GMT. - */ - public static TzData loadTzDataWithFallback(String... paths) { - for (String path : paths) { - TzData tzData = new TzData(); - if (tzData.loadData(path)) { - return tzData; - } - } - - // We didn't find any usable tzdata on disk, so let's just hard-code knowledge of "GMT". - // This is actually implemented in TimeZone itself, so if this is the only time zone - // we report, we won't be asked any more questions. - System.logE("Couldn't find any " + TZDATA_FILE + " file!"); - return TzData.createFallback(); - } - - /** - * Loads the data at the specified path and returns the {@link TzData} object if it is valid, - * otherwise {@code null}. - */ - @libcore.api.CorePlatformApi - public static TzData loadTzData(String path) { - TzData tzData = new TzData(); - if (tzData.loadData(path)) { - return tzData; - } - return null; - } - - private static TzData createFallback() { - TzData tzData = new TzData(); - tzData.populateFallback(); - return tzData; - } - - private TzData() { - } - - /** - * Visible for testing. - */ - public BufferIterator getBufferIterator(String id) { - checkNotClosed(); - - // Work out where in the big data file this time zone is. - int index = Arrays.binarySearch(ids, id); - if (index < 0) { - return null; - } - - int byteOffset = byteOffsets[index]; - BufferIterator it = mappedFile.bigEndianIterator(); - it.skip(byteOffset); - return it; - } - - private void populateFallback() { - version = "missing"; - zoneTab = "# Emergency fallback data.\n"; - ids = new String[] { "GMT" }; - byteOffsets = rawUtcOffsetsCache = new int[1]; - } - - /** - * Loads the data file at the specified path. If the data is valid {@code true} will be - * returned and the {@link TzData} instance can be used. If {@code false} is returned then the - * TzData instance is left in a closed state and must be discarded. - */ - private boolean loadData(String path) { - try { - mappedFile = MemoryMappedFile.mmapRO(path); - } catch (ErrnoException errnoException) { - return false; - } - try { - readHeader(); - return true; - } catch (Exception ex) { - close(); - - // Something's wrong with the file. - // Log the problem and return false so we try the next choice. - System.logE(TZDATA_FILE + " file \"" + path + "\" was present but invalid!", ex); - return false; - } - } - - private void readHeader() throws IOException { - // byte[12] tzdata_version -- "tzdata2012f\0" - // int index_offset - // int data_offset - // int zonetab_offset - BufferIterator it = mappedFile.bigEndianIterator(); - - try { - byte[] tzdata_version = new byte[12]; - it.readByteArray(tzdata_version, 0, tzdata_version.length); - String magic = new String(tzdata_version, 0, 6, StandardCharsets.US_ASCII); - if (!magic.equals("tzdata") || tzdata_version[11] != 0) { - throw new IOException("bad tzdata magic: " + Arrays.toString(tzdata_version)); - } - version = new String(tzdata_version, 6, 5, StandardCharsets.US_ASCII); - - final int fileSize = mappedFile.size(); - int index_offset = it.readInt(); - validateOffset(index_offset, fileSize); - int data_offset = it.readInt(); - validateOffset(data_offset, fileSize); - int zonetab_offset = it.readInt(); - validateOffset(zonetab_offset, fileSize); - - if (index_offset >= data_offset || data_offset >= zonetab_offset) { - throw new IOException("Invalid offset: index_offset=" + index_offset - + ", data_offset=" + data_offset + ", zonetab_offset=" + zonetab_offset - + ", fileSize=" + fileSize); - } - - readIndex(it, index_offset, data_offset); - readZoneTab(it, zonetab_offset, fileSize - zonetab_offset); - } catch (IndexOutOfBoundsException e) { - throw new IOException("Invalid read from data file", e); - } - } - - private static void validateOffset(int offset, int size) throws IOException { - if (offset < 0 || offset >= size) { - throw new IOException("Invalid offset=" + offset + ", size=" + size); - } - } - - private void readZoneTab(BufferIterator it, int zoneTabOffset, int zoneTabSize) { - byte[] bytes = new byte[zoneTabSize]; - it.seek(zoneTabOffset); - it.readByteArray(bytes, 0, bytes.length); - zoneTab = new String(bytes, 0, bytes.length, StandardCharsets.US_ASCII); - } - - private void readIndex(BufferIterator it, int indexOffset, int dataOffset) throws IOException { - it.seek(indexOffset); - - byte[] idBytes = new byte[SIZEOF_TZNAME]; - int indexSize = (dataOffset - indexOffset); - if (indexSize % SIZEOF_INDEX_ENTRY != 0) { - throw new IOException("Index size is not divisible by " + SIZEOF_INDEX_ENTRY - + ", indexSize=" + indexSize); - } - int entryCount = indexSize / SIZEOF_INDEX_ENTRY; - - byteOffsets = new int[entryCount]; - ids = new String[entryCount]; - - for (int i = 0; i < entryCount; i++) { - // Read the fixed length timezone ID. - it.readByteArray(idBytes, 0, idBytes.length); - - // Read the offset into the file where the data for ID can be found. - byteOffsets[i] = it.readInt(); - byteOffsets[i] += dataOffset; - - int length = it.readInt(); - if (length < 44) { - throw new IOException("length in index file < sizeof(tzhead)"); - } - it.skip(4); // Skip the unused 4 bytes that used to be the raw offset. - - // Calculate the true length of the ID. - int len = 0; - while (idBytes[len] != 0 && len < idBytes.length) { - len++; - } - if (len == 0) { - throw new IOException("Invalid ID at index=" + i); - } - ids[i] = new String(idBytes, 0, len, StandardCharsets.US_ASCII); - if (i > 0) { - if (ids[i].compareTo(ids[i - 1]) <= 0) { - throw new IOException("Index not sorted or contains multiple entries with the same ID" - + ", index=" + i + ", ids[i]=" + ids[i] + ", ids[i - 1]=" + ids[i - 1]); - } - } - } - } - - @libcore.api.CorePlatformApi - public void validate() throws IOException { - checkNotClosed(); - // Validate the data in the tzdata file by loading each and every zone. - for (String id : getAvailableIDs()) { - ZoneInfo zoneInfo = makeTimeZoneUncached(id); - if (zoneInfo == null) { - throw new IOException("Unable to find data for ID=" + id); - } - } - } - - ZoneInfo makeTimeZoneUncached(String id) throws IOException { - BufferIterator it = getBufferIterator(id); - if (it == null) { - return null; - } - - return ZoneInfo.readTimeZone(id, it, System.currentTimeMillis()); - } - - public String[] getAvailableIDs() { - checkNotClosed(); - return ids.clone(); - } - - public String[] getAvailableIDs(int rawUtcOffset) { - checkNotClosed(); - List<String> matches = new ArrayList<String>(); - int[] rawUtcOffsets = getRawUtcOffsets(); - for (int i = 0; i < rawUtcOffsets.length; ++i) { - if (rawUtcOffsets[i] == rawUtcOffset) { - matches.add(ids[i]); - } - } - return matches.toArray(new String[matches.size()]); - } - - private synchronized int[] getRawUtcOffsets() { - if (rawUtcOffsetsCache != null) { - return rawUtcOffsetsCache; - } - rawUtcOffsetsCache = new int[ids.length]; - for (int i = 0; i < ids.length; ++i) { - // This creates a TimeZone, which is quite expensive. Hence the cache. - // Note that icu4c does the same (without the cache), so if you're - // switching this code over to icu4j you should check its performance. - // Telephony shouldn't care, but someone converting a bunch of calendar - // events might. - rawUtcOffsetsCache[i] = cache.get(ids[i]).getRawOffset(); - } - return rawUtcOffsetsCache; - } - - @libcore.api.CorePlatformApi - public String getVersion() { - checkNotClosed(); - return version; - } - - public String getZoneTab() { - checkNotClosed(); - return zoneTab; - } - - @libcore.api.CorePlatformApi - public ZoneInfo makeTimeZone(String id) throws IOException { - checkNotClosed(); - ZoneInfo zoneInfo = cache.get(id); - // The object from the cache is cloned because TimeZone / ZoneInfo are mutable. - return zoneInfo == null ? null : (ZoneInfo) zoneInfo.clone(); - } - - @libcore.api.CorePlatformApi - public boolean hasTimeZone(String id) throws IOException { - checkNotClosed(); - return cache.get(id) != null; - } - - public void close() { - if (!closed) { - closed = true; - - // Clear state that takes up appreciable heap. - ids = null; - byteOffsets = null; - rawUtcOffsetsCache = null; - cache.evictAll(); - - // Remove the mapped file (if needed). - if (mappedFile != null) { - try { - mappedFile.close(); - } catch (ErrnoException ignored) { - } - mappedFile = null; - } - } - } - - private void checkNotClosed() throws IllegalStateException { - if (closed) { - throw new IllegalStateException("TzData is closed"); - } - } - - @Override protected void finalize() throws Throwable { - try { - close(); - } finally { - super.finalize(); - } - } - } - - private ZoneInfoDB() { - } - - @libcore.api.CorePlatformApi - public static TzData getInstance() { - return DATA; - } -} diff --git a/luni/src/main/java/libcore/timezone/ZoneInfoDb.java b/luni/src/main/java/libcore/timezone/ZoneInfoDb.java new file mode 100644 index 0000000000..a94d2933c9 --- /dev/null +++ b/luni/src/main/java/libcore/timezone/ZoneInfoDb.java @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.timezone; + +import android.system.ErrnoException; +import dalvik.annotation.optimization.ReachabilitySensitive; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import libcore.io.BufferIterator; +import libcore.io.MemoryMappedFile; +import libcore.util.BasicLruCache; +import libcore.util.ZoneInfo; + +/** + * A class used to initialize the time zone database. This implementation uses the + * Olson tzdata as the source of time zone information. However, to conserve + * disk space (inodes) and reduce I/O, all the data is concatenated into a single file, + * with an index to indicate the starting position of each time zone record. + * + * @hide - used to implement TimeZone + */ +@libcore.api.CorePlatformApi +public final class ZoneInfoDb implements AutoCloseable { + + // VisibleForTesting + public static final String TZDATA_FILE_NAME = "tzdata"; + + private static final ZoneInfoDb DATA = ZoneInfoDb.loadTzDataWithFallback( + TimeZoneDataFiles.getTimeZoneFilePaths(TZDATA_FILE_NAME)); + + // The database reserves 40 bytes for each id. + private static final int SIZEOF_TZNAME = 40; + + // The database uses 32-bit (4 byte) integers. + private static final int SIZEOF_TZINT = 4; + + // Each index entry takes up this number of bytes. + public static final int SIZEOF_INDEX_ENTRY = SIZEOF_TZNAME + 3 * SIZEOF_TZINT; + + /** + * {@code true} if {@link #close()} has been called meaning the instance cannot provide any + * data. + */ + private boolean closed; + + /** + * Rather than open, read, and close the big data file each time we look up a time zone, + * we map the big data file during startup, and then just use the MemoryMappedFile. + * + * At the moment, this "big" data file is about 500 KiB. At some point, that will be small + * enough that we could just keep the byte[] in memory, but using mmap(2) like this has the + * nice property that even if someone replaces the file under us (because multiple gservices + * updates have gone out, say), we still get a consistent (if outdated) view of the world. + */ + // Android-added: @ReachabilitySensitive + @ReachabilitySensitive + private MemoryMappedFile mappedFile; + + private String version; + private String zoneTab; + + /** + * The 'ids' array contains time zone ids sorted alphabetically, for binary searching. + * The other two arrays are in the same order. 'byteOffsets' gives the byte offset + * of each time zone, and 'rawUtcOffsetsCache' gives the time zone's raw UTC offset. + */ + private String[] ids; + private int[] byteOffsets; + private int[] rawUtcOffsetsCache; // Access this via getRawUtcOffsets instead. + + /** + * ZoneInfo objects are worth caching because they are expensive to create. + * See http://b/8270865 for context. + */ + private final static int CACHE_SIZE = 1; + private final BasicLruCache<String, ZoneInfo> cache = + new BasicLruCache<String, ZoneInfo>(CACHE_SIZE) { + @Override + protected ZoneInfo create(String id) { + try { + return makeTimeZoneUncached(id); + } catch (IOException e) { + throw new IllegalStateException("Unable to load timezone for ID=" + id, e); + } + } + }; + + @libcore.api.CorePlatformApi + public static ZoneInfoDb getInstance() { + return DATA; + } + + /** + * Loads the data at the specified paths in order, returning the first valid one as a + * {@link ZoneInfoDb} object. If there is no valid one found a basic fallback instance is created + * containing just GMT. + */ + public static ZoneInfoDb loadTzDataWithFallback(String... paths) { + for (String path : paths) { + ZoneInfoDb tzData = new ZoneInfoDb(); + if (tzData.loadData(path)) { + return tzData; + } + } + + // We didn't find any usable tzdata on disk, so let's just hard-code knowledge of "GMT". + // This is actually implemented in TimeZone itself, so if this is the only time zone + // we report, we won't be asked any more questions. + System.logE("Couldn't find any " + TZDATA_FILE_NAME + " file!"); + return ZoneInfoDb.createFallback(); + } + + /** + * Loads the data at the specified path and returns the {@link ZoneInfoDb} object if it is valid, + * otherwise {@code null}. + */ + @libcore.api.CorePlatformApi + public static ZoneInfoDb loadTzData(String path) { + ZoneInfoDb tzData = new ZoneInfoDb(); + if (tzData.loadData(path)) { + return tzData; + } + return null; + } + + private static ZoneInfoDb createFallback() { + ZoneInfoDb tzData = new ZoneInfoDb(); + tzData.populateFallback(); + return tzData; + } + + private ZoneInfoDb() { + } + + /** + * Visible for testing. + */ + public BufferIterator getBufferIterator(String id) { + checkNotClosed(); + + // Work out where in the big data file this time zone is. + int index = Arrays.binarySearch(ids, id); + if (index < 0) { + return null; + } + + int byteOffset = byteOffsets[index]; + BufferIterator it = mappedFile.bigEndianIterator(); + it.skip(byteOffset); + return it; + } + + private void populateFallback() { + version = "missing"; + zoneTab = "# Emergency fallback data.\n"; + ids = new String[] { "GMT" }; + byteOffsets = rawUtcOffsetsCache = new int[1]; + } + + /** + * Loads the data file at the specified path. If the data is valid {@code true} will be + * returned and the {@link ZoneInfoDb} instance can be used. If {@code false} is returned then the + * ZoneInfoDB instance is left in a closed state and must be discarded. + */ + private boolean loadData(String path) { + try { + mappedFile = MemoryMappedFile.mmapRO(path); + } catch (ErrnoException errnoException) { + return false; + } + try { + readHeader(); + return true; + } catch (Exception ex) { + close(); + + // Something's wrong with the file. + // Log the problem and return false so we try the next choice. + System.logE(TZDATA_FILE_NAME + " file \"" + path + "\" was present but invalid!", ex); + return false; + } + } + + private void readHeader() throws IOException { + // byte[12] tzdata_version -- "tzdata2012f\0" + // int index_offset + // int data_offset + // int zonetab_offset + BufferIterator it = mappedFile.bigEndianIterator(); + + try { + byte[] tzdata_version = new byte[12]; + it.readByteArray(tzdata_version, 0, tzdata_version.length); + String magic = new String(tzdata_version, 0, 6, StandardCharsets.US_ASCII); + if (!magic.equals("tzdata") || tzdata_version[11] != 0) { + throw new IOException("bad tzdata magic: " + Arrays.toString(tzdata_version)); + } + version = new String(tzdata_version, 6, 5, StandardCharsets.US_ASCII); + + final int fileSize = mappedFile.size(); + int index_offset = it.readInt(); + validateOffset(index_offset, fileSize); + int data_offset = it.readInt(); + validateOffset(data_offset, fileSize); + int zonetab_offset = it.readInt(); + validateOffset(zonetab_offset, fileSize); + + if (index_offset >= data_offset || data_offset >= zonetab_offset) { + throw new IOException("Invalid offset: index_offset=" + index_offset + + ", data_offset=" + data_offset + ", zonetab_offset=" + zonetab_offset + + ", fileSize=" + fileSize); + } + + readIndex(it, index_offset, data_offset); + readZoneTab(it, zonetab_offset, fileSize - zonetab_offset); + } catch (IndexOutOfBoundsException e) { + throw new IOException("Invalid read from data file", e); + } + } + + private static void validateOffset(int offset, int size) throws IOException { + if (offset < 0 || offset >= size) { + throw new IOException("Invalid offset=" + offset + ", size=" + size); + } + } + + private void readZoneTab(BufferIterator it, int zoneTabOffset, int zoneTabSize) { + byte[] bytes = new byte[zoneTabSize]; + it.seek(zoneTabOffset); + it.readByteArray(bytes, 0, bytes.length); + zoneTab = new String(bytes, 0, bytes.length, StandardCharsets.US_ASCII); + } + + private void readIndex(BufferIterator it, int indexOffset, int dataOffset) throws IOException { + it.seek(indexOffset); + + byte[] idBytes = new byte[SIZEOF_TZNAME]; + int indexSize = (dataOffset - indexOffset); + if (indexSize % SIZEOF_INDEX_ENTRY != 0) { + throw new IOException("Index size is not divisible by " + SIZEOF_INDEX_ENTRY + + ", indexSize=" + indexSize); + } + int entryCount = indexSize / SIZEOF_INDEX_ENTRY; + + byteOffsets = new int[entryCount]; + ids = new String[entryCount]; + + for (int i = 0; i < entryCount; i++) { + // Read the fixed length timezone ID. + it.readByteArray(idBytes, 0, idBytes.length); + + // Read the offset into the file where the data for ID can be found. + byteOffsets[i] = it.readInt(); + byteOffsets[i] += dataOffset; + + int length = it.readInt(); + if (length < 44) { + throw new IOException("length in index file < sizeof(tzhead)"); + } + it.skip(4); // Skip the unused 4 bytes that used to be the raw offset. + + // Calculate the true length of the ID. + int len = 0; + while (idBytes[len] != 0 && len < idBytes.length) { + len++; + } + if (len == 0) { + throw new IOException("Invalid ID at index=" + i); + } + ids[i] = new String(idBytes, 0, len, StandardCharsets.US_ASCII); + if (i > 0) { + if (ids[i].compareTo(ids[i - 1]) <= 0) { + throw new IOException("Index not sorted or contains multiple entries with the same ID" + + ", index=" + i + ", ids[i]=" + ids[i] + ", ids[i - 1]=" + ids[i - 1]); + } + } + } + } + + @libcore.api.CorePlatformApi + public void validate() throws IOException { + checkNotClosed(); + // Validate the data in the tzdata file by loading each and every zone. + for (String id : getAvailableIDs()) { + ZoneInfo zoneInfo = makeTimeZoneUncached(id); + if (zoneInfo == null) { + throw new IOException("Unable to find data for ID=" + id); + } + } + } + + ZoneInfo makeTimeZoneUncached(String id) throws IOException { + BufferIterator it = getBufferIterator(id); + if (it == null) { + return null; + } + + return ZoneInfo.readTimeZone(id, it, System.currentTimeMillis()); + } + + public String[] getAvailableIDs() { + checkNotClosed(); + return ids.clone(); + } + + public String[] getAvailableIDs(int rawUtcOffset) { + checkNotClosed(); + List<String> matches = new ArrayList<String>(); + int[] rawUtcOffsets = getRawUtcOffsets(); + for (int i = 0; i < rawUtcOffsets.length; ++i) { + if (rawUtcOffsets[i] == rawUtcOffset) { + matches.add(ids[i]); + } + } + return matches.toArray(new String[matches.size()]); + } + + private synchronized int[] getRawUtcOffsets() { + if (rawUtcOffsetsCache != null) { + return rawUtcOffsetsCache; + } + rawUtcOffsetsCache = new int[ids.length]; + for (int i = 0; i < ids.length; ++i) { + // This creates a TimeZone, which is quite expensive. Hence the cache. + // Note that icu4c does the same (without the cache), so if you're + // switching this code over to icu4j you should check its performance. + // Telephony shouldn't care, but someone converting a bunch of calendar + // events might. + rawUtcOffsetsCache[i] = cache.get(ids[i]).getRawOffset(); + } + return rawUtcOffsetsCache; + } + + @libcore.api.CorePlatformApi + public String getVersion() { + checkNotClosed(); + return version; + } + + public String getZoneTab() { + checkNotClosed(); + return zoneTab; + } + + @libcore.api.CorePlatformApi + public ZoneInfo makeTimeZone(String id) throws IOException { + checkNotClosed(); + ZoneInfo zoneInfo = cache.get(id); + // The object from the cache is cloned because TimeZone / ZoneInfo are mutable. + return zoneInfo == null ? null : (ZoneInfo) zoneInfo.clone(); + } + + @libcore.api.CorePlatformApi + public boolean hasTimeZone(String id) throws IOException { + checkNotClosed(); + return cache.get(id) != null; + } + + public void close() { + if (!closed) { + closed = true; + + // Clear state that takes up appreciable heap. + ids = null; + byteOffsets = null; + rawUtcOffsetsCache = null; + cache.evictAll(); + + // Remove the mapped file (if needed). + if (mappedFile != null) { + try { + mappedFile.close(); + } catch (ErrnoException ignored) { + } + mappedFile = null; + } + } + } + + private void checkNotClosed() throws IllegalStateException { + if (closed) { + throw new IllegalStateException("ZoneInfoDB instance is closed"); + } + } + + @Override protected void finalize() throws Throwable { + try { + close(); + } finally { + super.finalize(); + } + } +} diff --git a/luni/src/main/java/libcore/util/BasicLruCache.java b/luni/src/main/java/libcore/util/BasicLruCache.java index 20a3bee0d5..e3ddc6437d 100644 --- a/luni/src/main/java/libcore/util/BasicLruCache.java +++ b/luni/src/main/java/libcore/util/BasicLruCache.java @@ -16,7 +16,7 @@ package libcore.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.util.LinkedHashMap; import java.util.Map; diff --git a/luni/src/main/java/libcore/util/CoreLibraryDebug.java b/luni/src/main/java/libcore/util/CoreLibraryDebug.java index c39017f477..0d6ee4668f 100644 --- a/luni/src/main/java/libcore/util/CoreLibraryDebug.java +++ b/luni/src/main/java/libcore/util/CoreLibraryDebug.java @@ -16,10 +16,12 @@ package libcore.util; +import com.android.icu.util.Icu4cMetadata; + import libcore.timezone.TimeZoneDataFiles; import libcore.timezone.TzDataSetVersion; import libcore.timezone.TzDataSetVersion.TzDataSetException; -import libcore.timezone.ZoneInfoDB; +import libcore.timezone.ZoneInfoDb; import java.io.File; import java.io.IOException; @@ -59,44 +61,36 @@ public class CoreLibraryDebug { // Time zone module tz data set. { String tzDataModulePrefix = debugKeyPrefix + "tzdata_module_"; - String versionFileName = TimeZoneDataFiles.getTimeZoneModuleFile( - "tz/" + TzDataSetVersion.DEFAULT_FILE_NAME); - addTzDataSetVersionDebugInfo(versionFileName, tzDataModulePrefix, debugInfo); - } - - // Runtime module tz data set. - { - String runtimeModulePrefix = debugKeyPrefix + "runtime_module_"; - String versionFileName = TimeZoneDataFiles.getRuntimeModuleFile( - "tz/" + TzDataSetVersion.DEFAULT_FILE_NAME); - addTzDataSetVersionDebugInfo(versionFileName, runtimeModulePrefix, debugInfo); + String versionFile = + TimeZoneDataFiles.getTimeZoneModuleTzFile(TzDataSetVersion.DEFAULT_FILE_NAME); + addTzDataSetVersionDebugInfo(versionFile, tzDataModulePrefix, debugInfo); } // /system tz data set. { String systemDirPrefix = debugKeyPrefix + "system_"; - String versionFileName = - TimeZoneDataFiles.getSystemTimeZoneFile(TzDataSetVersion.DEFAULT_FILE_NAME); - addTzDataSetVersionDebugInfo(versionFileName, systemDirPrefix, debugInfo); + String versionFile = + TimeZoneDataFiles.getSystemTzFile(TzDataSetVersion.DEFAULT_FILE_NAME); + addTzDataSetVersionDebugInfo(versionFile, systemDirPrefix, debugInfo); } } - private static void addTzDataSetVersionDebugInfo(String tzDataSetVersionFileName, + private static void addTzDataSetVersionDebugInfo(String tzDataSetVersionFile, String debugKeyPrefix, DebugInfo debugInfo) { - File file = new File(tzDataSetVersionFileName); + File file = new File(tzDataSetVersionFile); String statusKey = debugKeyPrefix + "status"; if (file.exists()) { try { TzDataSetVersion tzDataSetVersion = TzDataSetVersion.readFromFile(file); - String formatVersionString = tzDataSetVersion.formatMajorVersion + "." - + tzDataSetVersion.formatMinorVersion; + String formatVersionString = tzDataSetVersion.getFormatMajorVersion() + "." + + tzDataSetVersion.getFormatMinorVersion(); debugInfo.addStringEntry(statusKey, "OK") .addStringEntry(debugKeyPrefix + "formatVersion", formatVersionString) .addStringEntry(debugKeyPrefix + "rulesVersion", - tzDataSetVersion.rulesVersion) + tzDataSetVersion.getRulesVersion()) .addStringEntry(debugKeyPrefix + "revision", - tzDataSetVersion.revision); + tzDataSetVersion.getRevision()); } catch (IOException | TzDataSetException e) { debugInfo.addStringEntry(statusKey, "ERROR"); debugInfo.addStringEntry(debugKeyPrefix + "exception_class", e.getClass().getName()); @@ -115,9 +109,9 @@ public class CoreLibraryDebug { android.icu.util.TimeZone.getTZDataVersion()); debugInfo.addStringEntry( debugKeyPrefix + "libcore.tzdb_version", - ZoneInfoDB.getInstance().getVersion()); + ZoneInfoDb.getInstance().getVersion()); debugInfo.addStringEntry( debugKeyPrefix + "icu4c.tzdb_version", - libcore.icu.ICU.getTZDataVersion()); + Icu4cMetadata.getTzdbVersion()); } } diff --git a/luni/src/main/java/libcore/util/EmptyArray.java b/luni/src/main/java/libcore/util/EmptyArray.java index 5b60683f2a..0d1e3217d6 100644 --- a/luni/src/main/java/libcore/util/EmptyArray.java +++ b/luni/src/main/java/libcore/util/EmptyArray.java @@ -16,7 +16,8 @@ package libcore.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; +import dalvik.annotation.compat.VersionCodes; /** @hide */ @libcore.api.CorePlatformApi @@ -25,22 +26,26 @@ public final class EmptyArray { @libcore.api.CorePlatformApi public static final boolean[] BOOLEAN = new boolean[0]; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk=VersionCodes.Q, + publicAlternatives="Use {@code new byte[0]} instead.") @libcore.api.CorePlatformApi public static final byte[] BYTE = new byte[0]; public static final char[] CHAR = new char[0]; public static final double[] DOUBLE = new double[0]; @libcore.api.CorePlatformApi public static final float[] FLOAT = new float[0]; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk=VersionCodes.Q, + publicAlternatives="Use {@code new int[0]} instead.") @libcore.api.CorePlatformApi public static final int[] INT = new int[0]; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk=VersionCodes.Q, + publicAlternatives="Use {@code new long[0]} instead.") @libcore.api.CorePlatformApi public static final long[] LONG = new long[0]; public static final Class<?>[] CLASS = new Class[0]; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk=VersionCodes.Q, + publicAlternatives="Use {@code new Object[0]} instead.") @libcore.api.CorePlatformApi public static final Object[] OBJECT = new Object[0]; @libcore.api.CorePlatformApi diff --git a/luni/src/main/java/libcore/util/FP16.java b/luni/src/main/java/libcore/util/FP16.java new file mode 100644 index 0000000000..602e1d4c86 --- /dev/null +++ b/luni/src/main/java/libcore/util/FP16.java @@ -0,0 +1,750 @@ +/* + * 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. + */ + +package libcore.util; + +/** + * <p>The {@code FP16} class is a wrapper and a utility class to manipulate half-precision 16-bit + * <a href="https://en.wikipedia.org/wiki/Half-precision_floating-point_format">IEEE 754</a> + * floating point data types (also called fp16 or binary16). A half-precision float can be + * created from or converted to single-precision floats, and is stored in a short data type. + * + * <p>The IEEE 754 standard specifies an fp16 as having the following format:</p> + * <ul> + * <li>Sign bit: 1 bit</li> + * <li>Exponent width: 5 bits</li> + * <li>Significand: 10 bits</li> + * </ul> + * + * <p>The format is laid out as follows:</p> + * <pre> + * 1 11111 1111111111 + * ^ --^-- -----^---- + * sign | |_______ significand + * | + * -- exponent + * </pre> + * + * <p>Half-precision floating points can be useful to save memory and/or + * bandwidth at the expense of range and precision when compared to single-precision + * floating points (fp32).</p> + * <p>To help you decide whether fp16 is the right storage type for you need, please + * refer to the table below that shows the available precision throughout the range of + * possible values. The <em>precision</em> column indicates the step size between two + * consecutive numbers in a specific part of the range.</p> + * + * <table summary="Precision of fp16 across the range"> + * <tr><th>Range start</th><th>Precision</th></tr> + * <tr><td>0</td><td>1 ⁄ 16,777,216</td></tr> + * <tr><td>1 ⁄ 16,384</td><td>1 ⁄ 16,777,216</td></tr> + * <tr><td>1 ⁄ 8,192</td><td>1 ⁄ 8,388,608</td></tr> + * <tr><td>1 ⁄ 4,096</td><td>1 ⁄ 4,194,304</td></tr> + * <tr><td>1 ⁄ 2,048</td><td>1 ⁄ 2,097,152</td></tr> + * <tr><td>1 ⁄ 1,024</td><td>1 ⁄ 1,048,576</td></tr> + * <tr><td>1 ⁄ 512</td><td>1 ⁄ 524,288</td></tr> + * <tr><td>1 ⁄ 256</td><td>1 ⁄ 262,144</td></tr> + * <tr><td>1 ⁄ 128</td><td>1 ⁄ 131,072</td></tr> + * <tr><td>1 ⁄ 64</td><td>1 ⁄ 65,536</td></tr> + * <tr><td>1 ⁄ 32</td><td>1 ⁄ 32,768</td></tr> + * <tr><td>1 ⁄ 16</td><td>1 ⁄ 16,384</td></tr> + * <tr><td>1 ⁄ 8</td><td>1 ⁄ 8,192</td></tr> + * <tr><td>1 ⁄ 4</td><td>1 ⁄ 4,096</td></tr> + * <tr><td>1 ⁄ 2</td><td>1 ⁄ 2,048</td></tr> + * <tr><td>1</td><td>1 ⁄ 1,024</td></tr> + * <tr><td>2</td><td>1 ⁄ 512</td></tr> + * <tr><td>4</td><td>1 ⁄ 256</td></tr> + * <tr><td>8</td><td>1 ⁄ 128</td></tr> + * <tr><td>16</td><td>1 ⁄ 64</td></tr> + * <tr><td>32</td><td>1 ⁄ 32</td></tr> + * <tr><td>64</td><td>1 ⁄ 16</td></tr> + * <tr><td>128</td><td>1 ⁄ 8</td></tr> + * <tr><td>256</td><td>1 ⁄ 4</td></tr> + * <tr><td>512</td><td>1 ⁄ 2</td></tr> + * <tr><td>1,024</td><td>1</td></tr> + * <tr><td>2,048</td><td>2</td></tr> + * <tr><td>4,096</td><td>4</td></tr> + * <tr><td>8,192</td><td>8</td></tr> + * <tr><td>16,384</td><td>16</td></tr> + * <tr><td>32,768</td><td>32</td></tr> + * </table> + * + * <p>This table shows that numbers higher than 1024 lose all fractional precision.</p> + * + * @hide + */ + +@libcore.api.CorePlatformApi +public class FP16 { + /** + * The number of bits used to represent a half-precision float value. + */ + @libcore.api.CorePlatformApi + public static final int SIZE = 16; + + /** + * Epsilon is the difference between 1.0 and the next value representable + * by a half-precision floating-point. + */ + @libcore.api.CorePlatformApi + public static final short EPSILON = (short) 0x1400; + + /** + * Maximum exponent a finite half-precision float may have. + */ + @libcore.api.CorePlatformApi + public static final int MAX_EXPONENT = 15; + /** + * Minimum exponent a normalized half-precision float may have. + */ + @libcore.api.CorePlatformApi + public static final int MIN_EXPONENT = -14; + + /** + * Smallest negative value a half-precision float may have. + */ + @libcore.api.CorePlatformApi + public static final short LOWEST_VALUE = (short) 0xfbff; + /** + * Maximum positive finite value a half-precision float may have. + */ + @libcore.api.CorePlatformApi + public static final short MAX_VALUE = (short) 0x7bff; + /** + * Smallest positive normal value a half-precision float may have. + */ + @libcore.api.CorePlatformApi + public static final short MIN_NORMAL = (short) 0x0400; + /** + * Smallest positive non-zero value a half-precision float may have. + */ + @libcore.api.CorePlatformApi + public static final short MIN_VALUE = (short) 0x0001; + /** + * A Not-a-Number representation of a half-precision float. + */ + @libcore.api.CorePlatformApi + public static final short NaN = (short) 0x7e00; + /** + * Negative infinity of type half-precision float. + */ + @libcore.api.CorePlatformApi + public static final short NEGATIVE_INFINITY = (short) 0xfc00; + /** + * Negative 0 of type half-precision float. + */ + @libcore.api.CorePlatformApi + public static final short NEGATIVE_ZERO = (short) 0x8000; + /** + * Positive infinity of type half-precision float. + */ + @libcore.api.CorePlatformApi + public static final short POSITIVE_INFINITY = (short) 0x7c00; + /** + * Positive 0 of type half-precision float. + */ + @libcore.api.CorePlatformApi + public static final short POSITIVE_ZERO = (short) 0x0000; + + @libcore.api.CorePlatformApi + public static final int SIGN_SHIFT = 15; + @libcore.api.CorePlatformApi + public static final int EXPONENT_SHIFT = 10; + @libcore.api.CorePlatformApi + public static final int SIGN_MASK = 0x8000; + @libcore.api.CorePlatformApi + public static final int SHIFTED_EXPONENT_MASK = 0x1f; + @libcore.api.CorePlatformApi + public static final int SIGNIFICAND_MASK = 0x3ff; + @libcore.api.CorePlatformApi + public static final int EXPONENT_SIGNIFICAND_MASK = 0x7fff; + @libcore.api.CorePlatformApi + public static final int EXPONENT_BIAS = 15; + + private static final int FP32_SIGN_SHIFT = 31; + private static final int FP32_EXPONENT_SHIFT = 23; + private static final int FP32_SHIFTED_EXPONENT_MASK = 0xff; + private static final int FP32_SIGNIFICAND_MASK = 0x7fffff; + private static final int FP32_EXPONENT_BIAS = 127; + private static final int FP32_QNAN_MASK = 0x400000; + private static final int FP32_DENORMAL_MAGIC = 126 << 23; + private static final float FP32_DENORMAL_FLOAT = Float.intBitsToFloat(FP32_DENORMAL_MAGIC); + + /** Hidden constructor to prevent instantiation. */ + private FP16() {} + + /** + * <p>Compares the two specified half-precision float values. The following + * conditions apply during the comparison:</p> + * + * <ul> + * <li>{@link #NaN} is considered by this method to be equal to itself and greater + * than all other half-precision float values (including {@code #POSITIVE_INFINITY})</li> + * <li>{@link #POSITIVE_ZERO} is considered by this method to be greater than + * {@link #NEGATIVE_ZERO}.</li> + * </ul> + * + * @param x The first half-precision float value to compare. + * @param y The second half-precision float value to compare + * + * @return The value {@code 0} if {@code x} is numerically equal to {@code y}, a + * value less than {@code 0} if {@code x} is numerically less than {@code y}, + * and a value greater than {@code 0} if {@code x} is numerically greater + * than {@code y} + */ + @libcore.api.CorePlatformApi + public static int compare(short x, short y) { + if (less(x, y)) return -1; + if (greater(x, y)) return 1; + + // Collapse NaNs, akin to halfToIntBits(), but we want to keep + // (signed) short value types to preserve the ordering of -0.0 + // and +0.0 + short xBits = isNaN(x) ? NaN : x; + short yBits = isNaN(y) ? NaN : y; + + return (xBits == yBits ? 0 : (xBits < yBits ? -1 : 1)); + } + + /** + * Returns the closest integral half-precision float value to the specified + * half-precision float value. Special values are handled in the + * following ways: + * <ul> + * <li>If the specified half-precision float is NaN, the result is NaN</li> + * <li>If the specified half-precision float is infinity (negative or positive), + * the result is infinity (with the same sign)</li> + * <li>If the specified half-precision float is zero (negative or positive), + * the result is zero (with the same sign)</li> + * </ul> + * + * @param h A half-precision float value + * @return The value of the specified half-precision float rounded to the nearest + * half-precision float value + */ + @libcore.api.CorePlatformApi + public static short rint(short h) { + int bits = h & 0xffff; + int abs = bits & EXPONENT_SIGNIFICAND_MASK; + int result = bits; + + if (abs < 0x3c00) { + result &= SIGN_MASK; + if (abs > 0x3800){ + result |= 0x3c00; + } + } else if (abs < 0x6400) { + int exp = 25 - (abs >> 10); + int mask = (1 << exp) - 1; + result += ((1 << (exp - 1)) - (~(abs >> exp) & 1)); + result &= ~mask; + } + if (isNaN((short) result)) { + // if result is NaN mask with qNaN + // (i.e. mask the most significant mantissa bit with 1) + // to comply with hardware implementations (ARM64, Intel, etc). + result |= NaN; + } + + return (short) result; + } + + /** + * Returns the smallest half-precision float value toward negative infinity + * greater than or equal to the specified half-precision float value. + * Special values are handled in the following ways: + * <ul> + * <li>If the specified half-precision float is NaN, the result is NaN</li> + * <li>If the specified half-precision float is infinity (negative or positive), + * the result is infinity (with the same sign)</li> + * <li>If the specified half-precision float is zero (negative or positive), + * the result is zero (with the same sign)</li> + * </ul> + * + * @param h A half-precision float value + * @return The smallest half-precision float value toward negative infinity + * greater than or equal to the specified half-precision float value + */ + @libcore.api.CorePlatformApi + public static short ceil(short h) { + int bits = h & 0xffff; + int abs = bits & EXPONENT_SIGNIFICAND_MASK; + int result = bits; + + if (abs < 0x3c00) { + result &= SIGN_MASK; + result |= 0x3c00 & -(~(bits >> 15) & (abs != 0 ? 1 : 0)); + } else if (abs < 0x6400) { + abs = 25 - (abs >> 10); + int mask = (1 << abs) - 1; + result += mask & ((bits >> 15) - 1); + result &= ~mask; + } + if (isNaN((short) result)) { + // if result is NaN mask with qNaN + // (i.e. mask the most significant mantissa bit with 1) + // to comply with hardware implementations (ARM64, Intel, etc). + result |= NaN; + } + + return (short) result; + } + + /** + * Returns the largest half-precision float value toward positive infinity + * less than or equal to the specified half-precision float value. + * Special values are handled in the following ways: + * <ul> + * <li>If the specified half-precision float is NaN, the result is NaN</li> + * <li>If the specified half-precision float is infinity (negative or positive), + * the result is infinity (with the same sign)</li> + * <li>If the specified half-precision float is zero (negative or positive), + * the result is zero (with the same sign)</li> + * </ul> + * + * @param h A half-precision float value + * @return The largest half-precision float value toward positive infinity + * less than or equal to the specified half-precision float value + */ + @libcore.api.CorePlatformApi + public static short floor(short h) { + int bits = h & 0xffff; + int abs = bits & EXPONENT_SIGNIFICAND_MASK; + int result = bits; + + if (abs < 0x3c00) { + result &= SIGN_MASK; + result |= 0x3c00 & (bits > 0x8000 ? 0xffff : 0x0); + } else if (abs < 0x6400) { + abs = 25 - (abs >> 10); + int mask = (1 << abs) - 1; + result += mask & -(bits >> 15); + result &= ~mask; + } + if (isNaN((short) result)) { + // if result is NaN mask with qNaN + // i.e. (Mask the most significant mantissa bit with 1) + result |= NaN; + } + + return (short) result; + } + + /** + * Returns the truncated half-precision float value of the specified + * half-precision float value. Special values are handled in the following ways: + * <ul> + * <li>If the specified half-precision float is NaN, the result is NaN</li> + * <li>If the specified half-precision float is infinity (negative or positive), + * the result is infinity (with the same sign)</li> + * <li>If the specified half-precision float is zero (negative or positive), + * the result is zero (with the same sign)</li> + * </ul> + * + * @param h A half-precision float value + * @return The truncated half-precision float value of the specified + * half-precision float value + */ + @libcore.api.CorePlatformApi + public static short trunc(short h) { + int bits = h & 0xffff; + int abs = bits & EXPONENT_SIGNIFICAND_MASK; + int result = bits; + + if (abs < 0x3c00) { + result &= SIGN_MASK; + } else if (abs < 0x6400) { + abs = 25 - (abs >> 10); + int mask = (1 << abs) - 1; + result &= ~mask; + } + + return (short) result; + } + + /** + * Returns the smaller of two half-precision float values (the value closest + * to negative infinity). Special values are handled in the following ways: + * <ul> + * <li>If either value is NaN, the result is NaN</li> + * <li>{@link #NEGATIVE_ZERO} is smaller than {@link #POSITIVE_ZERO}</li> + * </ul> + * + * @param x The first half-precision value + * @param y The second half-precision value + * @return The smaller of the two specified half-precision values + */ + @libcore.api.CorePlatformApi + public static short min(short x, short y) { + if (isNaN(x)) return NaN; + if (isNaN(y)) return NaN; + + if ((x & EXPONENT_SIGNIFICAND_MASK) == 0 && (y & EXPONENT_SIGNIFICAND_MASK) == 0) { + return (x & SIGN_MASK) != 0 ? x : y; + } + + return ((x & SIGN_MASK) != 0 ? 0x8000 - (x & 0xffff) : x & 0xffff) < + ((y & SIGN_MASK) != 0 ? 0x8000 - (y & 0xffff) : y & 0xffff) ? x : y; + } + + /** + * Returns the larger of two half-precision float values (the value closest + * to positive infinity). Special values are handled in the following ways: + * <ul> + * <li>If either value is NaN, the result is NaN</li> + * <li>{@link #POSITIVE_ZERO} is greater than {@link #NEGATIVE_ZERO}</li> + * </ul> + * + * @param x The first half-precision value + * @param y The second half-precision value + * + * @return The larger of the two specified half-precision values + */ + @libcore.api.CorePlatformApi + public static short max(short x, short y) { + if (isNaN(x)) return NaN; + if (isNaN(y)) return NaN; + + if ((x & EXPONENT_SIGNIFICAND_MASK) == 0 && (y & EXPONENT_SIGNIFICAND_MASK) == 0) { + return (x & SIGN_MASK) != 0 ? y : x; + } + + return ((x & SIGN_MASK) != 0 ? 0x8000 - (x & 0xffff) : x & 0xffff) > + ((y & SIGN_MASK) != 0 ? 0x8000 - (y & 0xffff) : y & 0xffff) ? x : y; + } + + /** + * Returns true if the first half-precision float value is less (smaller + * toward negative infinity) than the second half-precision float value. + * If either of the values is NaN, the result is false. + * + * @param x The first half-precision value + * @param y The second half-precision value + * + * @return True if x is less than y, false otherwise + */ + @libcore.api.CorePlatformApi + public static boolean less(short x, short y) { + if (isNaN(x)) return false; + if (isNaN(y)) return false; + + return ((x & SIGN_MASK) != 0 ? 0x8000 - (x & 0xffff) : x & 0xffff) < + ((y & SIGN_MASK) != 0 ? 0x8000 - (y & 0xffff) : y & 0xffff); + } + + /** + * Returns true if the first half-precision float value is less (smaller + * toward negative infinity) than or equal to the second half-precision + * float value. If either of the values is NaN, the result is false. + * + * @param x The first half-precision value + * @param y The second half-precision value + * + * @return True if x is less than or equal to y, false otherwise + */ + @libcore.api.CorePlatformApi + public static boolean lessEquals(short x, short y) { + if (isNaN(x)) return false; + if (isNaN(y)) return false; + + return ((x & SIGN_MASK) != 0 ? 0x8000 - (x & 0xffff) : x & 0xffff) <= + ((y & SIGN_MASK) != 0 ? 0x8000 - (y & 0xffff) : y & 0xffff); + } + + /** + * Returns true if the first half-precision float value is greater (larger + * toward positive infinity) than the second half-precision float value. + * If either of the values is NaN, the result is false. + * + * @param x The first half-precision value + * @param y The second half-precision value + * + * @return True if x is greater than y, false otherwise + */ + @libcore.api.CorePlatformApi + public static boolean greater(short x, short y) { + if (isNaN(x)) return false; + if (isNaN(y)) return false; + + return ((x & SIGN_MASK) != 0 ? 0x8000 - (x & 0xffff) : x & 0xffff) > + ((y & SIGN_MASK) != 0 ? 0x8000 - (y & 0xffff) : y & 0xffff); + } + + /** + * Returns true if the first half-precision float value is greater (larger + * toward positive infinity) than or equal to the second half-precision float + * value. If either of the values is NaN, the result is false. + * + * @param x The first half-precision value + * @param y The second half-precision value + * + * @return True if x is greater than y, false otherwise + */ + @libcore.api.CorePlatformApi + public static boolean greaterEquals(short x, short y) { + if (isNaN(x)) return false; + if (isNaN(y)) return false; + + return ((x & SIGN_MASK) != 0 ? 0x8000 - (x & 0xffff) : x & 0xffff) >= + ((y & SIGN_MASK) != 0 ? 0x8000 - (y & 0xffff) : y & 0xffff); + } + + /** + * Returns true if the two half-precision float values are equal. + * If either of the values is NaN, the result is false. {@link #POSITIVE_ZERO} + * and {@link #NEGATIVE_ZERO} are considered equal. + * + * @param x The first half-precision value + * @param y The second half-precision value + * + * @return True if x is equal to y, false otherwise + */ + @libcore.api.CorePlatformApi + public static boolean equals(short x, short y) { + if (isNaN(x)) return false; + if (isNaN(y)) return false; + + return x == y || ((x | y) & EXPONENT_SIGNIFICAND_MASK) == 0; + } + + /** + * Returns true if the specified half-precision float value represents + * infinity, false otherwise. + * + * @param h A half-precision float value + * @return True if the value is positive infinity or negative infinity, + * false otherwise + */ + @libcore.api.CorePlatformApi + public static boolean isInfinite(short h) { + return (h & EXPONENT_SIGNIFICAND_MASK) == POSITIVE_INFINITY; + } + + /** + * Returns true if the specified half-precision float value represents + * a Not-a-Number, false otherwise. + * + * @param h A half-precision float value + * @return True if the value is a NaN, false otherwise + */ + @libcore.api.CorePlatformApi + public static boolean isNaN(short h) { + return (h & EXPONENT_SIGNIFICAND_MASK) > POSITIVE_INFINITY; + } + + /** + * Returns true if the specified half-precision float value is normalized + * (does not have a subnormal representation). If the specified value is + * {@link #POSITIVE_INFINITY}, {@link #NEGATIVE_INFINITY}, + * {@link #POSITIVE_ZERO}, {@link #NEGATIVE_ZERO}, NaN or any subnormal + * number, this method returns false. + * + * @param h A half-precision float value + * @return True if the value is normalized, false otherwise + */ + @libcore.api.CorePlatformApi + public static boolean isNormalized(short h) { + return (h & POSITIVE_INFINITY) != 0 && (h & POSITIVE_INFINITY) != POSITIVE_INFINITY; + } + + /** + * <p>Converts the specified half-precision float value into a + * single-precision float value. The following special cases are handled:</p> + * <ul> + * <li>If the input is {@link #NaN}, the returned value is {@link Float#NaN}</li> + * <li>If the input is {@link #POSITIVE_INFINITY} or + * {@link #NEGATIVE_INFINITY}, the returned value is respectively + * {@link Float#POSITIVE_INFINITY} or {@link Float#NEGATIVE_INFINITY}</li> + * <li>If the input is 0 (positive or negative), the returned value is +/-0.0f</li> + * <li>Otherwise, the returned value is a normalized single-precision float value</li> + * </ul> + * + * @param h The half-precision float value to convert to single-precision + * @return A normalized single-precision float value + */ + @libcore.api.CorePlatformApi + public static float toFloat(short h) { + int bits = h & 0xffff; + int s = bits & SIGN_MASK; + int e = (bits >>> EXPONENT_SHIFT) & SHIFTED_EXPONENT_MASK; + int m = (bits ) & SIGNIFICAND_MASK; + + int outE = 0; + int outM = 0; + + if (e == 0) { // Denormal or 0 + if (m != 0) { + // Convert denorm fp16 into normalized fp32 + float o = Float.intBitsToFloat(FP32_DENORMAL_MAGIC + m); + o -= FP32_DENORMAL_FLOAT; + return s == 0 ? o : -o; + } + } else { + outM = m << 13; + if (e == 0x1f) { // Infinite or NaN + outE = 0xff; + if (outM != 0) { // SNaNs are quieted + outM |= FP32_QNAN_MASK; + } + } else { + outE = e - EXPONENT_BIAS + FP32_EXPONENT_BIAS; + } + } + + int out = (s << 16) | (outE << FP32_EXPONENT_SHIFT) | outM; + return Float.intBitsToFloat(out); + } + + /** + * <p>Converts the specified single-precision float value into a + * half-precision float value. The following special cases are handled:</p> + * <ul> + * <li>If the input is NaN (see {@link Float#isNaN(float)}), the returned + * value is {@link #NaN}</li> + * <li>If the input is {@link Float#POSITIVE_INFINITY} or + * {@link Float#NEGATIVE_INFINITY}, the returned value is respectively + * {@link #POSITIVE_INFINITY} or {@link #NEGATIVE_INFINITY}</li> + * <li>If the input is 0 (positive or negative), the returned value is + * {@link #POSITIVE_ZERO} or {@link #NEGATIVE_ZERO}</li> + * <li>If the input is a less than {@link #MIN_VALUE}, the returned value + * is flushed to {@link #POSITIVE_ZERO} or {@link #NEGATIVE_ZERO}</li> + * <li>If the input is a less than {@link #MIN_NORMAL}, the returned value + * is a denorm half-precision float</li> + * <li>Otherwise, the returned value is rounded to the nearest + * representable half-precision float value</li> + * </ul> + * + * @param f The single-precision float value to convert to half-precision + * @return A half-precision float value + */ + @libcore.api.CorePlatformApi + public static short toHalf(float f) { + int bits = Float.floatToRawIntBits(f); + int s = (bits >>> FP32_SIGN_SHIFT ); + int e = (bits >>> FP32_EXPONENT_SHIFT) & FP32_SHIFTED_EXPONENT_MASK; + int m = (bits ) & FP32_SIGNIFICAND_MASK; + + int outE = 0; + int outM = 0; + + if (e == 0xff) { // Infinite or NaN + outE = 0x1f; + outM = m != 0 ? 0x200 : 0; + } else { + e = e - FP32_EXPONENT_BIAS + EXPONENT_BIAS; + if (e >= 0x1f) { // Overflow + outE = 0x1f; + } else if (e <= 0) { // Underflow + if (e < -10) { + // The absolute fp32 value is less than MIN_VALUE, flush to +/-0 + } else { + // The fp32 value is a normalized float less than MIN_NORMAL, + // we convert to a denorm fp16 + m = m | 0x800000; + int shift = 14 - e; + outM = m >> shift; + + int lowm = m & ((1 << shift) - 1); + int hway = 1 << (shift - 1); + // if above halfway or exactly halfway and outM is odd + if (lowm + (outM & 1) > hway){ + // Round to nearest even + // Can overflow into exponent bit, which surprisingly is OK. + // This increment relies on the +outM in the return statement below + outM++; + } + } + } else { + outE = e; + outM = m >> 13; + // if above halfway or exactly halfway and outM is odd + if ((m & 0x1fff) + (outM & 0x1) > 0x1000) { + // Round to nearest even + // Can overflow into exponent bit, which surprisingly is OK. + // This increment relies on the +outM in the return statement below + outM++; + } + } + } + // The outM is added here as the +1 increments for outM above can + // cause an overflow in the exponent bit which is OK. + return (short) ((s << SIGN_SHIFT) | (outE << EXPONENT_SHIFT) + outM); + } + + /** + * <p>Returns a hexadecimal string representation of the specified half-precision + * float value. If the value is a NaN, the result is <code>"NaN"</code>, + * otherwise the result follows this format:</p> + * <ul> + * <li>If the sign is positive, no sign character appears in the result</li> + * <li>If the sign is negative, the first character is <code>'-'</code></li> + * <li>If the value is inifinity, the string is <code>"Infinity"</code></li> + * <li>If the value is 0, the string is <code>"0x0.0p0"</code></li> + * <li>If the value has a normalized representation, the exponent and + * significand are represented in the string in two fields. The significand + * starts with <code>"0x1."</code> followed by its lowercase hexadecimal + * representation. Trailing zeroes are removed unless all digits are 0, then + * a single zero is used. The significand representation is followed by the + * exponent, represented by <code>"p"</code>, itself followed by a decimal + * string of the unbiased exponent</li> + * <li>If the value has a subnormal representation, the significand starts + * with <code>"0x0."</code> followed by its lowercase hexadecimal + * representation. Trailing zeroes are removed unless all digits are 0, then + * a single zero is used. The significand representation is followed by the + * exponent, represented by <code>"p-14"</code></li> + * </ul> + * + * @param h A half-precision float value + * @return A hexadecimal string representation of the specified value + */ + @libcore.api.CorePlatformApi + public static String toHexString(short h) { + StringBuilder o = new StringBuilder(); + + int bits = h & 0xffff; + int s = (bits >>> SIGN_SHIFT ); + int e = (bits >>> EXPONENT_SHIFT) & SHIFTED_EXPONENT_MASK; + int m = (bits ) & SIGNIFICAND_MASK; + + if (e == 0x1f) { // Infinite or NaN + if (m == 0) { + if (s != 0) o.append('-'); + o.append("Infinity"); + } else { + o.append("NaN"); + } + } else { + if (s == 1) o.append('-'); + if (e == 0) { + if (m == 0) { + o.append("0x0.0p0"); + } else { + o.append("0x0."); + String significand = Integer.toHexString(m); + o.append(significand.replaceFirst("0{2,}$", "")); + o.append("p-14"); + } + } else { + o.append("0x1."); + String significand = Integer.toHexString(m); + o.append(significand.replaceFirst("0{2,}$", "")); + o.append('p'); + o.append(Integer.toString(e - EXPONENT_BIAS)); + } + } + + return o.toString(); + } +} diff --git a/luni/src/main/java/libcore/util/HexEncoding.java b/luni/src/main/java/libcore/util/HexEncoding.java index eceec6b8f8..6d00074678 100644 --- a/luni/src/main/java/libcore/util/HexEncoding.java +++ b/luni/src/main/java/libcore/util/HexEncoding.java @@ -23,17 +23,43 @@ package libcore.util; @libcore.api.CorePlatformApi public class HexEncoding { + private static final char[] LOWER_CASE_DIGITS = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + + private static final char[] UPPER_CASE_DIGITS = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + /** Hidden constructor to prevent instantiation. */ private HexEncoding() {} - private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); + /** + * Encodes the provided byte as a two-digit hexadecimal String value. + */ + @libcore.api.CorePlatformApi + public static String encodeToString(byte b, boolean upperCase) { + char[] digits = upperCase ? UPPER_CASE_DIGITS : LOWER_CASE_DIGITS; + char[] buf = new char[2]; // We always want two digits. + buf[0] = digits[(b >> 4) & 0xf]; + buf[1] = digits[b & 0xf]; + return new String(buf, 0, 2); + } /** * Encodes the provided data as a sequence of hexadecimal characters. */ @libcore.api.CorePlatformApi public static char[] encode(byte[] data) { - return encode(data, 0, data.length); + return encode(data, 0, data.length, true /* upperCase */); + } + + /** + * Encodes the provided data as a sequence of hexadecimal characters. + */ + @libcore.api.CorePlatformApi + public static char[] encode(byte[] data, boolean upperCase) { + return encode(data, 0, data.length, upperCase); } /** @@ -41,12 +67,20 @@ public class HexEncoding { */ @libcore.api.CorePlatformApi public static char[] encode(byte[] data, int offset, int len) { + return encode(data, offset, len, true /* upperCase */); + } + + /** + * Encodes the provided data as a sequence of hexadecimal characters. + */ + private static char[] encode(byte[] data, int offset, int len, boolean upperCase) { + char[] digits = upperCase ? UPPER_CASE_DIGITS : LOWER_CASE_DIGITS; char[] result = new char[len * 2]; for (int i = 0; i < len; i++) { byte b = data[offset + i]; int resultIndex = 2 * i; - result[resultIndex] = (HEX_DIGITS[(b >>> 4) & 0x0f]); - result[resultIndex + 1] = (HEX_DIGITS[b & 0x0f]); + result[resultIndex] = (digits[(b >> 4) & 0x0f]); + result[resultIndex + 1] = (digits[b & 0x0f]); } return result; @@ -57,7 +91,15 @@ public class HexEncoding { */ @libcore.api.CorePlatformApi public static String encodeToString(byte[] data) { - return new String(encode(data)); + return encodeToString(data, true /* upperCase */); + } + + /** + * Encodes the provided data as a sequence of hexadecimal characters. + */ + @libcore.api.CorePlatformApi + public static String encodeToString(byte[] data, boolean upperCase) { + return new String(encode(data, upperCase)); } /** @@ -78,7 +120,9 @@ public class HexEncoding { * * Throws an {@code IllegalArgumentException} if the input is malformed. */ - public static byte[] decode(String encoded, boolean allowSingleChar) throws IllegalArgumentException { + @libcore.api.CorePlatformApi + public static byte[] decode(String encoded, boolean allowSingleChar) + throws IllegalArgumentException { return decode(encoded.toCharArray(), allowSingleChar); } @@ -101,25 +145,28 @@ public class HexEncoding { * Throws an {@code IllegalArgumentException} if the input is malformed. */ @libcore.api.CorePlatformApi - public static byte[] decode(char[] encoded, boolean allowSingleChar) throws IllegalArgumentException { - int resultLengthBytes = (encoded.length + 1) / 2; + public static byte[] decode(char[] encoded, boolean allowSingleChar) + throws IllegalArgumentException { + int encodedLength = encoded.length; + int resultLengthBytes = (encodedLength + 1) / 2; byte[] result = new byte[resultLengthBytes]; int resultOffset = 0; int i = 0; if (allowSingleChar) { - if ((encoded.length % 2) != 0) { - // Odd number of digits -- the first digit is the lower 4 bits of the first result byte. + if ((encodedLength % 2) != 0) { + // Odd number of digits -- the first digit is the lower 4 bits of the first result + // byte. result[resultOffset++] = (byte) toDigit(encoded, i); i++; } } else { - if ((encoded.length % 2) != 0) { - throw new IllegalArgumentException("Invalid input length: " + encoded.length); + if ((encodedLength % 2) != 0) { + throw new IllegalArgumentException("Invalid input length: " + encodedLength); } } - for (int len = encoded.length; i < len; i += 2) { + for (; i < encodedLength; i += 2) { result[resultOffset++] = (byte) ((toDigit(encoded, i) << 4) | toDigit(encoded, i + 1)); } @@ -139,7 +186,6 @@ public class HexEncoding { return 10 + (pseudoCodePoint - 'A'); } - throw new IllegalArgumentException("Illegal char: " + str[offset] + - " at offset " + offset); + throw new IllegalArgumentException("Illegal char: " + str[offset] + " at offset " + offset); } } diff --git a/luni/src/main/java/libcore/util/NativeAllocationRegistry.java b/luni/src/main/java/libcore/util/NativeAllocationRegistry.java index 5dc1e98334..e114ebe35d 100644 --- a/luni/src/main/java/libcore/util/NativeAllocationRegistry.java +++ b/luni/src/main/java/libcore/util/NativeAllocationRegistry.java @@ -41,6 +41,7 @@ import java.lang.ref.Reference; * @hide */ @libcore.api.CorePlatformApi +@libcore.api.IntraCoreApi public class NativeAllocationRegistry { private final ClassLoader classLoader; @@ -118,6 +119,7 @@ public class NativeAllocationRegistry { * kind of native allocation */ @libcore.api.CorePlatformApi + @libcore.api.IntraCoreApi public static NativeAllocationRegistry createMalloced( ClassLoader classLoader, long freeFunction) { return new NativeAllocationRegistry(classLoader, freeFunction, 0, true); @@ -227,6 +229,7 @@ public class NativeAllocationRegistry { * thrown. */ @libcore.api.CorePlatformApi + @libcore.api.IntraCoreApi public Runnable registerNativeAllocation(Object referent, long nativePtr) { if (referent == null) { throw new IllegalArgumentException("referent is null"); diff --git a/luni/src/main/java/libcore/util/NonNull.java b/luni/src/main/java/libcore/util/NonNull.java index 900e58162b..db3cd8ed71 100644 --- a/luni/src/main/java/libcore/util/NonNull.java +++ b/luni/src/main/java/libcore/util/NonNull.java @@ -15,6 +15,9 @@ */ package libcore.util; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -30,7 +33,7 @@ import java.lang.annotation.Target; */ @Documented @Retention(SOURCE) -@Target({TYPE_USE}) +@Target({FIELD, METHOD, PARAMETER, TYPE_USE}) @libcore.api.IntraCoreApi public @interface NonNull { /** diff --git a/luni/src/main/java/libcore/util/Nullable.java b/luni/src/main/java/libcore/util/Nullable.java index c8cbe38514..3371978b05 100644 --- a/luni/src/main/java/libcore/util/Nullable.java +++ b/luni/src/main/java/libcore/util/Nullable.java @@ -15,6 +15,9 @@ */ package libcore.util; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -30,7 +33,7 @@ import java.lang.annotation.Target; */ @Documented @Retention(SOURCE) -@Target({TYPE_USE}) +@Target({FIELD, METHOD, PARAMETER, TYPE_USE}) @libcore.api.IntraCoreApi public @interface Nullable { /** diff --git a/luni/src/main/java/libcore/util/TEST_MAPPING b/luni/src/main/java/libcore/util/TEST_MAPPING new file mode 100644 index 0000000000..670cd00f0a --- /dev/null +++ b/luni/src/main/java/libcore/util/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.libcore.util" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/libcore/util/ZoneInfo.java b/luni/src/main/java/libcore/util/ZoneInfo.java index abd98b13a3..85bf1bcdf4 100644 --- a/luni/src/main/java/libcore/util/ZoneInfo.java +++ b/luni/src/main/java/libcore/util/ZoneInfo.java @@ -22,7 +22,8 @@ */ package libcore.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; + import java.io.IOException; import java.io.ObjectInputStream; import java.util.Arrays; @@ -31,7 +32,7 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; import libcore.io.BufferIterator; -import libcore.timezone.ZoneInfoDB; +import libcore.timezone.ZoneInfoDb; /** * Our concrete TimeZone implementation, backed by zoneinfo data. @@ -42,26 +43,15 @@ import libcore.timezone.ZoneInfoDB; * {@code man 8 zic}) and an index by long name, e.g. Europe/London. * * <p>The compacted form is created by {@code external/icu/tools/ZoneCompactor.java} and is used - * by both this and Bionic. {@link ZoneInfoDB} is responsible for mapping the binary file, and + * by both this and Bionic. {@link ZoneInfoDb} is responsible for mapping the binary file, and * reading the index and creating a {@link BufferIterator} that provides access to an entry for a * specific file. This class is responsible for reading the data from that {@link BufferIterator} * and storing it a representation to support the {@link TimeZone} and {@link GregorianCalendar} * implementations. See {@link ZoneInfo#readTimeZone(String, BufferIterator, long)}. * - * <p>The main difference between {@code tzfile} and the compacted form is that the - * {@code struct ttinfo} only uses a single byte for {@code tt_isdst} and {@code tt_abbrind}. - * * <p>This class does not use all the information from the {@code tzfile}; it uses: * {@code tzh_timecnt} and the associated transition times and type information. For each type - * (described by {@code struct ttinfo}) it uses {@code tt_gmtoff} and {@code tt_isdst}. Note, that - * the definition of {@code struct ttinfo} uses {@code long}, and {@code int} but they do not have - * the same meaning as Java. The prose following the definition makes it clear that the {@code long} - * is 4 bytes and the {@code int} fields are 1 byte. - * - * <p>As the data uses 32 bits to store the time in seconds the time range is limited to roughly - * 69 years either side of the epoch (1st Jan 1970 00:00:00) that means that it cannot handle any - * dates before 1900 and after 2038. There is an extended version of the table that uses 64 bits - * to store the data but that information is not used by this. + * (described by {@code struct ttinfo}) it uses {@code tt_gmtoff} and {@code tt_isdst}. * * <p>This class should be in libcore.timezone but this class is Serializable so cannot * be moved there without breaking apps that have (for some reason) serialized TimeZone objects. @@ -197,6 +187,19 @@ public final class ZoneInfo extends TimeZone { public static ZoneInfo readTimeZone(String id, BufferIterator it, long currentTimeMillis) throws IOException { + + // Skip over the superseded 32-bit header and data. + skipOver32BitData(id, it); + + // Read the v2+ 64-bit header and data. + return read64BitData(id, it, currentTimeMillis); + } + + /** + * Skip over the 32-bit data with some minimal validation to make sure sure we reading a valid + * and supported file. + */ + private static void skipOver32BitData(String id, BufferIterator it) throws IOException { // Variable names beginning tzh_ correspond to those in "tzfile.h". // Check tzh_magic. @@ -205,24 +208,82 @@ public final class ZoneInfo extends TimeZone { throw new IOException("Timezone id=" + id + " has an invalid header=" + tzh_magic); } - // Skip the uninteresting part of the header. - it.skip(28); + byte tzh_version = it.readByte(); + checkTzifVersionAcceptable(id, tzh_version); + + // Skip the unused bytes. + it.skip(15); + + // Read the header values necessary to read through all the 32-bit data. + int tzh_ttisgmtcnt = it.readInt(); + int tzh_ttisstdcnt = it.readInt(); + int tzh_leapcnt = it.readInt(); + int tzh_timecnt = it.readInt(); + int tzh_typecnt = it.readInt(); + int tzh_charcnt = it.readInt(); + + // Skip transitions data, 4 bytes for each 32-bit time + 1 byte for isDst. + final int transitionInfoSize = 4 + 1; + it.skip(tzh_timecnt * transitionInfoSize); + + // Skip ttinfos. + // struct ttinfo { + // int32_t tt_gmtoff; + // unsigned char tt_isdst; + // unsigned char tt_abbrind; + // }; + final int ttinfoSize = 4 + 1 + 1; + it.skip(tzh_typecnt * ttinfoSize); + + // Skip tzh_charcnt time zone abbreviations. + it.skip(tzh_charcnt); + + // Skip tzh_leapcnt repetitions of a 32-bit time + a 32-bit correction. + int leapInfoSize = 4 + 4; + it.skip(tzh_leapcnt * leapInfoSize); + + // Skip ttisstds and ttisgmts information. These can be ignored for our usecases as per + // https://mm.icann.org/pipermail/tz/2006-February/013359.html + it.skip(tzh_ttisstdcnt + tzh_ttisgmtcnt); + } + + /** + * Read the 64-bit header and data for {@code id} from the current position of {@code it} and + * return a ZoneInfo. + */ + private static ZoneInfo read64BitData(String id, BufferIterator it, long currentTimeMillis) + throws IOException { + // Variable names beginning tzh_ correspond to those in "tzfile.h". + + // Check tzh_magic. + int tzh_magic = it.readInt(); + if (tzh_magic != 0x545a6966) { // "TZif" + throw new IOException("Timezone id=" + id + " has an invalid header=" + tzh_magic); + } + + byte tzh_version = it.readByte(); + checkTzifVersionAcceptable(id, tzh_version); + + // Skip the uninteresting parts of the header. + it.skip(27); // Read the sizes of the arrays we're about to read. int tzh_timecnt = it.readInt(); + // Arbitrary ceiling to prevent allocating memory for corrupt data. - // 2 per year with 2^32 seconds would give ~272 transitions. final int MAX_TRANSITIONS = 2000; if (tzh_timecnt < 0 || tzh_timecnt > MAX_TRANSITIONS) { throw new IOException( - "Timezone id=" + id + " has an invalid number of transitions=" + tzh_timecnt); + "Timezone id=" + id + " has an invalid number of transitions=" + + tzh_timecnt); } int tzh_typecnt = it.readInt(); final int MAX_TYPES = 256; if (tzh_typecnt < 1) { throw new IOException("ZoneInfo requires at least one type " - + "to be provided for each timezone but could not find one for '" + id + "'"); + + "to be provided for each timezone but could not find one for '" + id + + "'"); } else if (tzh_typecnt > MAX_TYPES) { throw new IOException( "Timezone with id " + id + " has too many types=" + tzh_typecnt); @@ -230,18 +291,9 @@ public final class ZoneInfo extends TimeZone { it.skip(4); // Skip tzh_charcnt. - // Transitions are signed 32 bit integers, but we store them as signed 64 bit - // integers since it's easier to compare them against 64 bit inputs (see getOffset - // and isDaylightTime) with much less risk of an overflow in our calculations. - // - // The alternative of checking the input against the first and last transition in - // the array is far more awkward and error prone. - int[] transitions32 = new int[tzh_timecnt]; - it.readIntArray(transitions32, 0, transitions32.length); - long[] transitions64 = new long[tzh_timecnt]; + it.readLongArray(transitions64, 0, transitions64.length); for (int i = 0; i < tzh_timecnt; ++i) { - transitions64[i] = transitions32[i]; if (i > 0 && transitions64[i] <= transitions64[i - 1]) { throw new IOException( id + " transition at " + i + " is not sorted correctly, is " @@ -249,13 +301,14 @@ public final class ZoneInfo extends TimeZone { } } - byte[] type = new byte[tzh_timecnt]; - it.readByteArray(type, 0, type.length); - for (int i = 0; i < type.length; i++) { - int typeIndex = type[i] & 0xff; + byte[] types = new byte[tzh_timecnt]; + it.readByteArray(types, 0, types.length); + for (int i = 0; i < types.length; i++) { + int typeIndex = types[i] & 0xff; if (typeIndex >= tzh_typecnt) { throw new IOException( - id + " type at " + i + " is not < " + tzh_typecnt + ", is " + typeIndex); + id + " type at " + i + " is not < " + tzh_typecnt + ", is " + + typeIndex); } } @@ -277,8 +330,19 @@ public final class ZoneInfo extends TimeZone { // for any locale. (The RI doesn't do any better than us here either.) it.skip(1); } + return new ZoneInfo(id, transitions64, types, gmtOffsets, isDsts, currentTimeMillis); + } - return new ZoneInfo(id, transitions64, type, gmtOffsets, isDsts, currentTimeMillis); + private static void checkTzifVersionAcceptable(String id, byte tzh_version) throws IOException { + char tzh_version_char = (char) tzh_version; + // Version >= 2 is required because the 64-bit time section is required. v3 is the latest + // version known at the time of writing and is identical to v2 in the parts used by this + // class. + if (tzh_version_char != '2' && tzh_version_char != '3') { + throw new IOException( + "Timezone id=" + id + " has an invalid format version=\'" + tzh_version_char + + "\' (" + tzh_version + ")"); + } } private ZoneInfo(String name, long[] transitions, byte[] types, int[] gmtOffsets, byte[] isDsts, diff --git a/luni/src/main/java/org/apache/harmony/xml/ExpatAttributes.java b/luni/src/main/java/org/apache/harmony/xml/ExpatAttributes.java index 3368f9214c..22ee4a2f59 100644 --- a/luni/src/main/java/org/apache/harmony/xml/ExpatAttributes.java +++ b/luni/src/main/java/org/apache/harmony/xml/ExpatAttributes.java @@ -16,9 +16,10 @@ package org.apache.harmony.xml; -import dalvik.annotation.compat.UnsupportedAppUsage; import org.xml.sax.Attributes; +import android.compat.annotation.UnsupportedAppUsage; + /** * Wraps native attribute array. */ diff --git a/luni/src/main/java/org/apache/harmony/xml/ExpatParser.java b/luni/src/main/java/org/apache/harmony/xml/ExpatParser.java index 71c94f9e28..8872e1d1fb 100644 --- a/luni/src/main/java/org/apache/harmony/xml/ExpatParser.java +++ b/luni/src/main/java/org/apache/harmony/xml/ExpatParser.java @@ -16,15 +16,6 @@ package org.apache.harmony.xml; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.annotation.optimization.ReachabilitySensitive; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.net.URI; -import java.net.URL; -import java.net.URLConnection; -import libcore.io.IoUtils; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; @@ -35,6 +26,18 @@ import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.ext.LexicalHandler; +import android.compat.annotation.UnsupportedAppUsage; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import libcore.io.IoUtils; + +import dalvik.annotation.optimization.ReachabilitySensitive; + /** * Adapts SAX API to the Expat native XML parser. Not intended for reuse * across documents. diff --git a/luni/src/main/java/org/apache/harmony/xml/ExpatReader.java b/luni/src/main/java/org/apache/harmony/xml/ExpatReader.java index 510a889b3a..a69f364e93 100644 --- a/luni/src/main/java/org/apache/harmony/xml/ExpatReader.java +++ b/luni/src/main/java/org/apache/harmony/xml/ExpatReader.java @@ -16,11 +16,6 @@ package org.apache.harmony.xml; -import dalvik.annotation.compat.UnsupportedAppUsage; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import libcore.io.IoUtils; import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; import org.xml.sax.EntityResolver; @@ -32,6 +27,13 @@ import org.xml.sax.SAXNotSupportedException; import org.xml.sax.XMLReader; import org.xml.sax.ext.LexicalHandler; +import android.compat.annotation.UnsupportedAppUsage; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import libcore.io.IoUtils; + /** * SAX wrapper around Expat. Interns strings. Does not support validation. * Does not support {@link DTDHandler}. diff --git a/luni/src/main/java/org/apache/harmony/xml/TEST_MAPPING b/luni/src/main/java/org/apache/harmony/xml/TEST_MAPPING new file mode 100644 index 0000000000..d8c9759fae --- /dev/null +++ b/luni/src/main/java/org/apache/harmony/xml/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.xml" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java b/luni/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java index a0da24d602..b522265568 100644 --- a/luni/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java +++ b/luni/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java @@ -16,10 +16,6 @@ package org.apache.harmony.xml.dom; -import dalvik.annotation.compat.UnsupportedAppUsage; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; import org.w3c.dom.Attr; import org.w3c.dom.DOMException; import org.w3c.dom.Element; @@ -28,6 +24,12 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.TypeInfo; +import android.compat.annotation.UnsupportedAppUsage; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + /** * Provides a straightforward implementation of the corresponding W3C DOM * interface. The class is used internally only, thus only notable members that diff --git a/luni/src/main/java/org/w3c/dom/TEST_MAPPING b/luni/src/main/java/org/w3c/dom/TEST_MAPPING new file mode 100644 index 0000000000..00e68f7854 --- /dev/null +++ b/luni/src/main/java/org/w3c/dom/TEST_MAPPING @@ -0,0 +1,18 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.xml" + }, + { + "include-filter": "tests.org.w3c.dom" + }, + { + "include-filter": "org.w3c.domts" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/org/w3c/dom/ls/LSSerializerFilter.java b/luni/src/main/java/org/w3c/dom/ls/LSSerializerFilter.java index 554807c619..9f22f2b4cb 100644 --- a/luni/src/main/java/org/w3c/dom/ls/LSSerializerFilter.java +++ b/luni/src/main/java/org/w3c/dom/ls/LSSerializerFilter.java @@ -12,9 +12,10 @@ package org.w3c.dom.ls; -import dalvik.annotation.compat.UnsupportedAppUsage; import org.w3c.dom.traversal.NodeFilter; +import android.compat.annotation.UnsupportedAppUsage; + /** * <code>LSSerializerFilter</code>s provide applications the ability to * examine nodes as they are being serialized and decide what nodes should diff --git a/luni/src/main/java/org/w3c/dom/traversal/NodeFilter.java b/luni/src/main/java/org/w3c/dom/traversal/NodeFilter.java index 24f75993fb..8263d5bd36 100644 --- a/luni/src/main/java/org/w3c/dom/traversal/NodeFilter.java +++ b/luni/src/main/java/org/w3c/dom/traversal/NodeFilter.java @@ -12,9 +12,10 @@ package org.w3c.dom.traversal; -import dalvik.annotation.compat.UnsupportedAppUsage; import org.w3c.dom.Node; +import android.compat.annotation.UnsupportedAppUsage; + /** * Filters are objects that know how to "filter out" nodes. If a * <code>NodeIterator</code> or <code>TreeWalker</code> is given a diff --git a/luni/src/main/java/org/w3c/dom/traversal/NodeIterator.java b/luni/src/main/java/org/w3c/dom/traversal/NodeIterator.java index 686beb7726..3d1f3af890 100644 --- a/luni/src/main/java/org/w3c/dom/traversal/NodeIterator.java +++ b/luni/src/main/java/org/w3c/dom/traversal/NodeIterator.java @@ -12,10 +12,11 @@ package org.w3c.dom.traversal; -import dalvik.annotation.compat.UnsupportedAppUsage; import org.w3c.dom.DOMException; import org.w3c.dom.Node; +import android.compat.annotation.UnsupportedAppUsage; + /** * <code>NodeIterators</code> are used to step through a set of nodes, e.g. * the set of nodes in a <code>NodeList</code>, the document subtree diff --git a/luni/src/main/java/org/xml/sax/InputSource.java b/luni/src/main/java/org/xml/sax/InputSource.java index 3750cfed29..26e027bbfa 100644 --- a/luni/src/main/java/org/xml/sax/InputSource.java +++ b/luni/src/main/java/org/xml/sax/InputSource.java @@ -5,7 +5,7 @@ package org.xml.sax; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.io.InputStream; import java.io.Reader; diff --git a/luni/src/main/java/org/xml/sax/SAXException.java b/luni/src/main/java/org/xml/sax/SAXException.java index ea69d3f2eb..383b4a0569 100644 --- a/luni/src/main/java/org/xml/sax/SAXException.java +++ b/luni/src/main/java/org/xml/sax/SAXException.java @@ -5,7 +5,7 @@ package org.xml.sax; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * Encapsulate a general SAX error or warning. diff --git a/luni/src/main/java/org/xml/sax/SAXParseException.java b/luni/src/main/java/org/xml/sax/SAXParseException.java index 72b16cf904..67cb78a95c 100644 --- a/luni/src/main/java/org/xml/sax/SAXParseException.java +++ b/luni/src/main/java/org/xml/sax/SAXParseException.java @@ -5,7 +5,7 @@ package org.xml.sax; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * Encapsulate an XML parse error or warning. diff --git a/luni/src/main/java/org/xml/sax/TEST_MAPPING b/luni/src/main/java/org/xml/sax/TEST_MAPPING new file mode 100644 index 0000000000..afedf2c13b --- /dev/null +++ b/luni/src/main/java/org/xml/sax/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.xml" + }, + { + "include-filter": "org.apache.harmony.tests.org.xml.sax" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/org/xml/sax/ext/Attributes2Impl.java b/luni/src/main/java/org/xml/sax/ext/Attributes2Impl.java index b3702a4844..6b4ea18d4e 100644 --- a/luni/src/main/java/org/xml/sax/ext/Attributes2Impl.java +++ b/luni/src/main/java/org/xml/sax/ext/Attributes2Impl.java @@ -5,11 +5,13 @@ package org.xml.sax.ext; -import dalvik.annotation.compat.UnsupportedAppUsage; -import libcore.util.EmptyArray; import org.xml.sax.Attributes; import org.xml.sax.helpers.AttributesImpl; +import android.compat.annotation.UnsupportedAppUsage; + +import libcore.util.EmptyArray; + /** * SAX2 extension helper for additional Attributes information, * implementing the {@link Attributes2} interface. diff --git a/luni/src/main/java/org/xml/sax/ext/Locator2Impl.java b/luni/src/main/java/org/xml/sax/ext/Locator2Impl.java index bb9582f02a..711639b8f7 100644 --- a/luni/src/main/java/org/xml/sax/ext/Locator2Impl.java +++ b/luni/src/main/java/org/xml/sax/ext/Locator2Impl.java @@ -5,10 +5,11 @@ package org.xml.sax.ext; -import dalvik.annotation.compat.UnsupportedAppUsage; import org.xml.sax.Locator; import org.xml.sax.helpers.LocatorImpl; +import android.compat.annotation.UnsupportedAppUsage; + /** * SAX2 extension helper for holding additional Entity information, diff --git a/luni/src/main/java/org/xml/sax/ext/TEST_MAPPING b/luni/src/main/java/org/xml/sax/ext/TEST_MAPPING new file mode 100644 index 0000000000..50687abb9c --- /dev/null +++ b/luni/src/main/java/org/xml/sax/ext/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.org.xml.sax.ext" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/org/xml/sax/helpers/AttributesImpl.java b/luni/src/main/java/org/xml/sax/helpers/AttributesImpl.java index 9193075bb9..dcc6ff038b 100644 --- a/luni/src/main/java/org/xml/sax/helpers/AttributesImpl.java +++ b/luni/src/main/java/org/xml/sax/helpers/AttributesImpl.java @@ -6,9 +6,10 @@ package org.xml.sax.helpers; -import dalvik.annotation.compat.UnsupportedAppUsage; import org.xml.sax.Attributes; +import android.compat.annotation.UnsupportedAppUsage; + /** * Default implementation of the Attributes interface. diff --git a/luni/src/main/java/org/xml/sax/helpers/LocatorImpl.java b/luni/src/main/java/org/xml/sax/helpers/LocatorImpl.java index 944c41aa87..9997375d4d 100644 --- a/luni/src/main/java/org/xml/sax/helpers/LocatorImpl.java +++ b/luni/src/main/java/org/xml/sax/helpers/LocatorImpl.java @@ -5,9 +5,10 @@ package org.xml.sax.helpers; -import dalvik.annotation.compat.UnsupportedAppUsage; import org.xml.sax.Locator; +import android.compat.annotation.UnsupportedAppUsage; + /** * Provide an optional convenience implementation of Locator. diff --git a/luni/src/main/java/org/xml/sax/helpers/NamespaceSupport.java b/luni/src/main/java/org/xml/sax/helpers/NamespaceSupport.java index 820f8d275a..5322467dac 100644 --- a/luni/src/main/java/org/xml/sax/helpers/NamespaceSupport.java +++ b/luni/src/main/java/org/xml/sax/helpers/NamespaceSupport.java @@ -6,7 +6,7 @@ package org.xml.sax.helpers; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.util.ArrayList; import java.util.Collections; import java.util.EmptyStackException; diff --git a/luni/src/main/java/org/xml/sax/helpers/ParserAdapter.java b/luni/src/main/java/org/xml/sax/helpers/ParserAdapter.java index 5acc659ae6..f6a7a519d3 100644 --- a/luni/src/main/java/org/xml/sax/helpers/ParserAdapter.java +++ b/luni/src/main/java/org/xml/sax/helpers/ParserAdapter.java @@ -6,10 +6,6 @@ package org.xml.sax.helpers; -import dalvik.annotation.compat.UnsupportedAppUsage; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Enumeration; import org.xml.sax.AttributeList; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; @@ -26,6 +22,12 @@ import org.xml.sax.SAXNotSupportedException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; +import android.compat.annotation.UnsupportedAppUsage; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Enumeration; + /** * Adapt a SAX1 Parser as a SAX2 XMLReader. diff --git a/luni/src/main/java/org/xml/sax/helpers/TEST_MAPPING b/luni/src/main/java/org/xml/sax/helpers/TEST_MAPPING new file mode 100644 index 0000000000..f13e3f9cb8 --- /dev/null +++ b/luni/src/main/java/org/xml/sax/helpers/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.org.xml.sax.helpers" + } + ] + } + ] +}
\ No newline at end of file diff --git a/luni/src/main/java/org/xml/sax/helpers/XMLFilterImpl.java b/luni/src/main/java/org/xml/sax/helpers/XMLFilterImpl.java index 95ae356354..9ad32af28c 100644 --- a/luni/src/main/java/org/xml/sax/helpers/XMLFilterImpl.java +++ b/luni/src/main/java/org/xml/sax/helpers/XMLFilterImpl.java @@ -6,8 +6,6 @@ package org.xml.sax.helpers; -import dalvik.annotation.compat.UnsupportedAppUsage; -import java.io.IOException; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; @@ -22,6 +20,10 @@ import org.xml.sax.SAXParseException; import org.xml.sax.XMLFilter; import org.xml.sax.XMLReader; +import android.compat.annotation.UnsupportedAppUsage; + +import java.io.IOException; + /** * Base class for deriving an XML filter. diff --git a/luni/src/main/java/org/xml/sax/helpers/XMLReaderAdapter.java b/luni/src/main/java/org/xml/sax/helpers/XMLReaderAdapter.java index 0ef4d6fca1..5f0789fbcb 100644 --- a/luni/src/main/java/org/xml/sax/helpers/XMLReaderAdapter.java +++ b/luni/src/main/java/org/xml/sax/helpers/XMLReaderAdapter.java @@ -6,9 +6,6 @@ package org.xml.sax.helpers; -import dalvik.annotation.compat.UnsupportedAppUsage; -import java.io.IOException; -import java.util.Locale; import org.xml.sax.AttributeList; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; @@ -23,6 +20,11 @@ import org.xml.sax.SAXException; import org.xml.sax.SAXNotSupportedException; import org.xml.sax.XMLReader; +import android.compat.annotation.UnsupportedAppUsage; + +import java.io.IOException; +import java.util.Locale; + /** * Adapt a SAX2 XMLReader as a SAX1 Parser. diff --git a/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java b/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java index b95728f944..08d1664079 100644 --- a/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java +++ b/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java @@ -7,13 +7,15 @@ package org.xml.sax.helpers; -import dalvik.annotation.compat.UnsupportedAppUsage; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + +import android.compat.annotation.UnsupportedAppUsage; + import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; /** diff --git a/luni/src/main/native/Android.bp b/luni/src/main/native/Android.bp index 8621752f41..423cdd11a8 100644 --- a/luni/src/main/native/Android.bp +++ b/luni/src/main/native/Android.bp @@ -1,5 +1,22 @@ +// Copyright (C) 2017 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + filegroup { name: "luni_native_srcs", + visibility: [ + "//libcore", + ], srcs: [ "ExecStrings.cpp", "IcuUtilities.cpp", @@ -14,10 +31,7 @@ filegroup { "java_lang_invoke_MethodHandle.cpp", "java_lang_invoke_VarHandle.cpp", "java_math_NativeBN.cpp", - "java_util_regex_Matcher.cpp", - "java_util_regex_Pattern.cpp", "libcore_icu_ICU.cpp", - "libcore_icu_NativeConverter.cpp", "libcore_icu_TimeZoneNames.cpp", "libcore_io_AsynchronousCloseMonitor.cpp", "libcore_io_Linux.cpp", @@ -31,6 +45,9 @@ filegroup { filegroup { name: "libandroidio_srcs", + visibility: [ + "//libcore", + ], srcs: [ "AsynchronousCloseMonitor.cpp", ], diff --git a/luni/src/main/native/IcuUtilities.cpp b/luni/src/main/native/IcuUtilities.cpp index ed10d04fd7..0db59f95f5 100644 --- a/luni/src/main/native/IcuUtilities.cpp +++ b/luni/src/main/native/IcuUtilities.cpp @@ -29,28 +29,6 @@ #include "unicode/ustring.h" #include "unicode/uloc.h" -jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, icu::StringEnumeration* se) { - if (maybeThrowIcuException(env, provider, status)) { - return NULL; - } - - int32_t count = se->count(status); - if (maybeThrowIcuException(env, "StringEnumeration::count", status)) { - return NULL; - } - - jobjectArray result = env->NewObjectArray(count, JniConstants::GetStringClass(env), NULL); - for (int32_t i = 0; i < count; ++i) { - const icu::UnicodeString* string = se->snext(status); - if (maybeThrowIcuException(env, "StringEnumeration::snext", status)) { - return NULL; - } - ScopedLocalRef<jstring> javaString(env, jniCreateString(env, string->getBuffer(), string->length())); - env->SetObjectArrayElement(result, i, javaString.get()); - } - return result; -} - bool maybeThrowIcuException(JNIEnv* env, const char* function, UErrorCode error) { if (U_SUCCESS(error)) { return false; diff --git a/luni/src/main/native/IcuUtilities.h b/luni/src/main/native/IcuUtilities.h index c64de308a2..451dc3240b 100644 --- a/luni/src/main/native/IcuUtilities.h +++ b/luni/src/main/native/IcuUtilities.h @@ -18,10 +18,8 @@ #define ICU_UTILITIES_H_included #include "jni.h" -#include "ustrenum.h" // For UStringEnumeration. #include "unicode/utypes.h" // For UErrorCode. -extern jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, icu::StringEnumeration*); bool maybeThrowIcuException(JNIEnv* env, const char* function, UErrorCode error); #endif // ICU_UTILITIES_H_included diff --git a/luni/src/main/native/JniConstants.cpp b/luni/src/main/native/JniConstants.cpp index 84273539a0..478d015791 100644 --- a/luni/src/main/native/JniConstants.cpp +++ b/luni/src/main/native/JniConstants.cpp @@ -45,7 +45,6 @@ static bool g_constants_valid = false; // Constants jclass booleanClass; -jclass charsetICUClass; jclass doubleClass; jclass errnoExceptionClass; jclass fileDescriptorClass; @@ -61,10 +60,8 @@ jclass localeDataClass; jclass longClass; jclass netlinkSocketAddressClass; jclass packetSocketAddressClass; -jclass patternSyntaxExceptionClass; jclass stringClass; jclass structAddrinfoClass; -jclass structFlockClass; jclass structGroupReqClass; jclass structIfaddrsClass; jclass structLingerClass; @@ -93,7 +90,6 @@ void EnsureJniConstantsInitialized(JNIEnv* env) { } booleanClass = findClass(env, "java/lang/Boolean"); - charsetICUClass = findClass(env, "java/nio/charset/CharsetICU"); doubleClass = findClass(env, "java/lang/Double"); errnoExceptionClass = findClass(env, "android/system/ErrnoException"); fileDescriptorClass = findClass(env, "java/io/FileDescriptor"); @@ -109,10 +105,8 @@ void EnsureJniConstantsInitialized(JNIEnv* env) { longClass = findClass(env, "java/lang/Long"); netlinkSocketAddressClass = findClass(env, "android/system/NetlinkSocketAddress"); packetSocketAddressClass = findClass(env, "android/system/PacketSocketAddress"); - patternSyntaxExceptionClass = findClass(env, "java/util/regex/PatternSyntaxException"); stringClass = findClass(env, "java/lang/String"); structAddrinfoClass = findClass(env, "android/system/StructAddrinfo"); - structFlockClass = findClass(env, "android/system/StructFlock"); structGroupReqClass = findClass(env, "android/system/StructGroupReq"); structIfaddrsClass = findClass(env, "android/system/StructIfaddrs"); structLingerClass = findClass(env, "android/system/StructLinger"); @@ -136,6 +130,15 @@ void JniConstants::Initialize(JNIEnv* env) { } void JniConstants::Invalidate() { + // This method is called when a new runtime instance is created. There is no + // notification of a runtime instance being destroyed in the JNI interface + // so we piggyback on creation. Since only one runtime is supported at a + // time, we know the constants are invalid when JNI_CreateJavaVM() is + // called. + // + // Clean shutdown would require calling DeleteGlobalRef() for each of the + // class references, but JavaVM is unavailable because ART only calls this + // once all threads are unregistered. std::lock_guard guard(g_constants_mutex); g_constants_valid = false; } @@ -145,11 +148,6 @@ jclass JniConstants::GetBooleanClass(JNIEnv* env) { return booleanClass; } -jclass JniConstants::GetCharsetICUClass(JNIEnv* env) { - EnsureJniConstantsInitialized(env); - return charsetICUClass; -} - jclass JniConstants::GetDoubleClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return doubleClass; @@ -225,11 +223,6 @@ jclass JniConstants::GetPacketSocketAddressClass(JNIEnv* env) { return packetSocketAddressClass; } -jclass JniConstants::GetPatternSyntaxExceptionClass(JNIEnv* env) { - EnsureJniConstantsInitialized(env); - return patternSyntaxExceptionClass; -} - jclass JniConstants::GetStringClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return stringClass; @@ -240,11 +233,6 @@ jclass JniConstants::GetStructAddrinfoClass(JNIEnv* env) { return structAddrinfoClass; } -jclass JniConstants::GetStructFlockClass(JNIEnv* env) { - EnsureJniConstantsInitialized(env); - return structFlockClass; -} - jclass JniConstants::GetStructGroupReqClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structGroupReqClass; diff --git a/luni/src/main/native/JniConstants.h b/luni/src/main/native/JniConstants.h index 021dc53455..868e928825 100644 --- a/luni/src/main/native/JniConstants.h +++ b/luni/src/main/native/JniConstants.h @@ -30,7 +30,6 @@ struct JniConstants { static void Invalidate(); static jclass GetBooleanClass(JNIEnv* env); - static jclass GetCharsetICUClass(JNIEnv* env); static jclass GetDoubleClass(JNIEnv* env); static jclass GetErrnoExceptionClass(JNIEnv* env); static jclass GetFileDescriptorClass(JNIEnv* env); @@ -46,7 +45,6 @@ struct JniConstants { static jclass GetLongClass(JNIEnv* env); static jclass GetNetlinkSocketAddressClass(JNIEnv* env); static jclass GetPacketSocketAddressClass(JNIEnv* env); - static jclass GetPatternSyntaxExceptionClass(JNIEnv* env); static jclass GetStringClass(JNIEnv* env); static jclass GetStructAddrinfoClass(JNIEnv* env); static jclass GetStructFlockClass(JNIEnv* env); diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp index 0b4a94a5a1..17ca83960c 100644 --- a/luni/src/main/native/Register.cpp +++ b/luni/src/main/native/Register.cpp @@ -40,10 +40,7 @@ jint JNI_OnLoad(JavaVM* vm, void*) { REGISTER(register_java_lang_invoke_MethodHandle); REGISTER(register_java_lang_invoke_VarHandle); REGISTER(register_java_math_NativeBN); - REGISTER(register_java_util_regex_Matcher); - REGISTER(register_java_util_regex_Pattern); REGISTER(register_libcore_icu_ICU); - REGISTER(register_libcore_icu_NativeConverter); REGISTER(register_libcore_icu_TimeZoneNames); REGISTER(register_libcore_io_AsynchronousCloseMonitor); REGISTER(register_libcore_io_Linux); diff --git a/luni/src/main/native/ScopedIcuULoc.h b/luni/src/main/native/ScopedIcuULoc.h new file mode 100644 index 0000000000..5de5e36605 --- /dev/null +++ b/luni/src/main/native/ScopedIcuULoc.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <nativehelper/JNIHelp.h> +#include <nativehelper/ScopedUtfChars.h> + +#include "unicode/uloc.h" + + +static void getLocale(const char* localeName, std::string& locale, UErrorCode* status) { + int length; + { + // Most common locale name should fit the max capacity. + char buffer[ULOC_FULLNAME_CAPACITY]; + UErrorCode err = U_ZERO_ERROR; + + length = uloc_getName(localeName, buffer, ULOC_FULLNAME_CAPACITY, &err); + if (U_SUCCESS(err)) { + locale = buffer; + *status = err; + return; + } else if (err != U_BUFFER_OVERFLOW_ERROR) { + *status = err; + return; + } + } + + // Case U_BUFFER_OVERFLOW_ERROR + std::unique_ptr<char[]> buffer(new char[length+1]); + UErrorCode err = U_ZERO_ERROR; + uloc_getName(localeName, buffer.get(), length+1, &err); + if (U_SUCCESS(err)) { + locale = buffer.get(); + } + *status = err; + return; +} + +class ScopedIcuULoc { + public: + ScopedIcuULoc(JNIEnv* env, jstring javaLocaleName) { + isValid = false; + + if (javaLocaleName == NULL) { + jniThrowNullPointerException(env, "javaLocaleName == null"); + return; + } + + const ScopedUtfChars localeName(env, javaLocaleName); + if (localeName.c_str() == NULL) { + return; + } + + UErrorCode status = U_ZERO_ERROR; + getLocale(localeName.c_str(), mLocale, &status); + isValid = U_SUCCESS(status); + } + + ~ScopedIcuULoc() { + } + + bool valid() const { + return isValid; + } + + const char* locale() const { + return mLocale.c_str(); + } + + int32_t locale_length() const { + return mLocale.length(); + } + + private: + bool isValid; + std::string mLocale; + + // Disallow copy and assignment. + ScopedIcuULoc(const ScopedIcuULoc&); + void operator=(const ScopedIcuULoc&); +}; diff --git a/luni/src/main/native/android_system_OsConstants.cpp b/luni/src/main/native/android_system_OsConstants.cpp index bb19f6e04f..6cf2c8b30b 100644 --- a/luni/src/main/native/android_system_OsConstants.cpp +++ b/luni/src/main/native/android_system_OsConstants.cpp @@ -351,6 +351,7 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) { initConstant(env, c, "_LINUX_CAPABILITY_VERSION_3", _LINUX_CAPABILITY_VERSION_3); #endif initConstant(env, c, "MAP_FIXED", MAP_FIXED); + initConstant(env, c, "MAP_ANONYMOUS", MAP_ANONYMOUS); initConstant(env, c, "MAP_POPULATE", MAP_POPULATE); initConstant(env, c, "MAP_PRIVATE", MAP_PRIVATE); initConstant(env, c, "MAP_SHARED", MAP_SHARED); @@ -374,6 +375,9 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) { #endif initConstant(env, c, "MCL_CURRENT", MCL_CURRENT); initConstant(env, c, "MCL_FUTURE", MCL_FUTURE); +#if defined(MFD_CLOEXEC) + initConstant(env, c, "MFD_CLOEXEC", MFD_CLOEXEC); +#endif initConstant(env, c, "MSG_CTRUNC", MSG_CTRUNC); initConstant(env, c, "MSG_DONTROUTE", MSG_DONTROUTE); initConstant(env, c, "MSG_EOR", MSG_EOR); diff --git a/luni/src/main/native/java_util_regex_Matcher.cpp b/luni/src/main/native/java_util_regex_Matcher.cpp deleted file mode 100644 index 12fb764c6e..0000000000 --- a/luni/src/main/native/java_util_regex_Matcher.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (C) 2010 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 LOG_TAG "Matcher" - -#include <memory> -#include <stdlib.h> - -#include <android-base/logging.h> -#include <nativehelper/JNIHelp.h> -#include <nativehelper/ScopedPrimitiveArray.h> -#include <nativehelper/ScopedStringChars.h> -#include <nativehelper/jni_macros.h> - -#include "IcuUtilities.h" -#include "JniException.h" -#include "ScopedJavaUnicodeString.h" -#include "unicode/parseerr.h" -#include "unicode/regex.h" - -// ICU documentation: http://icu-project.org/apiref/icu4c/classRegexMatcher.html - -/** - * Encapsulates an instance of ICU4C's RegexMatcher class along with a copy of - * the input it's currently operating on in the native heap. - * - * Rationale: We choose to make a copy here because it turns out to be a lot - * cheaper when a moving GC and/or string compression is enabled. This is - * because env->GetStringChars() always copies in this scenario. This becomes - * especially bad when the String in question is long and/or contains a large - * number of matches. - * - * Drawbacks: The native allocation associated with this class is no longer - * fixed size, so we're effectively lying to the NativeAllocationRegistry about - * the size of the object(s) we're allocating on the native heap. The peak - * memory usage doesn't change though, given that GetStringChars would have - * made an allocation of precisely the same size. - */ -class MatcherState { -public: - MatcherState(icu::RegexMatcher* matcher) : - mMatcher(matcher), - mUChars(nullptr), - mUText(nullptr), - mStatus(U_ZERO_ERROR) { - } - - bool updateInput(JNIEnv* env, jstring input) { - // First, close the UText struct, since we're about to allocate a new one. - if (mUText != nullptr) { - utext_close(mUText); - mUText = nullptr; - } - - // Then delete the UChar* associated with the UText struct.. - mUChars.reset(nullptr); - - // TODO: We should investigate whether we can avoid an additional copy - // in the native heap when is_copy == JNI_TRUE. The problem with doing - // that is that we might call ReleaseStringChars with a different - // JNIEnv* on a different downcall. This is currently safe as - // implemented in ART, but is unlikely to be portable and the spec stays - // silent on the matter. - ScopedStringChars inputChars(env, input); - if (inputChars.get() == nullptr) { - // There will be an exception pending if we get here. - return false; - } - - // Make a copy of |input| on the native heap. This copy will be live - // until the next call to updateInput or close. - mUChars.reset(new (std::nothrow) UChar[inputChars.size()]); - if (mUChars.get() == nullptr) { - env->ThrowNew(env->FindClass("Ljava/lang/OutOfMemoryError;"), "Out of memory"); - return false; - } - - static_assert(sizeof(UChar) == sizeof(jchar), "sizeof(Uchar) != sizeof(jchar)"); - memcpy(mUChars.get(), inputChars.get(), inputChars.size() * sizeof(jchar)); - - // Reset any errors that might have occurred on previous patches. - mStatus = U_ZERO_ERROR; - mUText = utext_openUChars(nullptr, mUChars.get(), inputChars.size(), &mStatus); - if (mUText == nullptr) { - CHECK(maybeThrowIcuException(env, "utext_openUChars", mStatus)); - return false; - } - - // It is an error for ICU to have returned a non-null mUText but to - // still have indicated an error. - CHECK(U_SUCCESS(mStatus)); - - mMatcher->reset(mUText); - return true; - } - - ~MatcherState() { - if (mUText != nullptr) { - utext_close(mUText); - } - } - - icu::RegexMatcher* matcher() { - return mMatcher.get(); - } - - UErrorCode& status() { - return mStatus; - } - - void updateOffsets(JNIEnv* env, jintArray javaOffsets) { - ScopedIntArrayRW offsets(env, javaOffsets); - if (offsets.get() == NULL) { - return; - } - - for (size_t i = 0, groupCount = mMatcher->groupCount(); i <= groupCount; ++i) { - offsets[2*i + 0] = mMatcher->start(i, mStatus); - offsets[2*i + 1] = mMatcher->end(i, mStatus); - } - } - -private: - std::unique_ptr<icu::RegexMatcher> mMatcher; - std::unique_ptr<UChar[]> mUChars; - UText* mUText; - UErrorCode mStatus; - - // Disallow copy and assignment. - MatcherState(const MatcherState&); - void operator=(const MatcherState&); -}; - -static inline MatcherState* toMatcherState(jlong address) { - return reinterpret_cast<MatcherState*>(static_cast<uintptr_t>(address)); -} - -static void Matcher_free(void* address) { - MatcherState* state = reinterpret_cast<MatcherState*>(address); - delete state; -} - -static jlong Matcher_getNativeFinalizer(JNIEnv*, jclass) { - return reinterpret_cast<jlong>(&Matcher_free); -} - -static jboolean Matcher_findImpl(JNIEnv* env, jclass, jlong addr, jint startIndex, jintArray offsets) { - MatcherState* state = toMatcherState(addr); - UBool result = state->matcher()->find(startIndex, state->status()); - if (result) { - state->updateOffsets(env, offsets); - return JNI_TRUE; - } else { - return JNI_FALSE; - } -} - -static jboolean Matcher_findNextImpl(JNIEnv* env, jclass, jlong addr, jintArray offsets) { - MatcherState* state = toMatcherState(addr); - UBool result = state->matcher()->find(); - if (result) { - state->updateOffsets(env, offsets); - return JNI_TRUE; - } else { - return JNI_FALSE; - } -} - -static jint Matcher_groupCountImpl(JNIEnv*, jclass, jlong addr) { - MatcherState* state = toMatcherState(addr); - return state->matcher()->groupCount(); -} - -static jboolean Matcher_hitEndImpl(JNIEnv*, jclass, jlong addr) { - MatcherState* state = toMatcherState(addr); - if (state->matcher()->hitEnd() != 0) { - return JNI_TRUE; - } else { - return JNI_FALSE; - } -} - -static jboolean Matcher_lookingAtImpl(JNIEnv* env, jclass, jlong addr, jintArray offsets) { - MatcherState* state = toMatcherState(addr); - UBool result = state->matcher()->lookingAt(state->status()); - if (result) { - state->updateOffsets(env, offsets); - return JNI_TRUE; - } else { - return JNI_FALSE; - } -} - -static jboolean Matcher_matchesImpl(JNIEnv* env, jclass, jlong addr, jintArray offsets) { - MatcherState* state = toMatcherState(addr); - UBool result = state->matcher()->matches(state->status()); - if (result) { - state->updateOffsets(env, offsets); - return JNI_TRUE; - } else { - return JNI_FALSE; - } -} - -static jlong Matcher_openImpl(JNIEnv* env, jclass, jlong patternAddr) { - icu::RegexPattern* pattern = reinterpret_cast<icu::RegexPattern*>(static_cast<uintptr_t>(patternAddr)); - UErrorCode status = U_ZERO_ERROR; - icu::RegexMatcher* result = pattern->matcher(status); - if (maybeThrowIcuException(env, "RegexPattern::matcher", status)) { - return 0; - } - - return reinterpret_cast<uintptr_t>(new MatcherState(result)); -} - -static jboolean Matcher_requireEndImpl(JNIEnv*, jclass, jlong addr) { - MatcherState* state = toMatcherState(addr); - if (state->matcher()->requireEnd() != 0) { - return JNI_TRUE; - } else { - return JNI_FALSE; - } -} - -static void Matcher_setInputImpl(JNIEnv* env, jclass, jlong addr, jstring javaText, jint start, jint end) { - MatcherState* state = toMatcherState(addr); - if (state->updateInput(env, javaText)) { - state->matcher()->region(start, end, state->status()); - } -} - -static void Matcher_useAnchoringBoundsImpl(JNIEnv*, jclass, jlong addr, jboolean value) { - MatcherState* state = toMatcherState(addr); - state->matcher()->useAnchoringBounds(value); -} - -static void Matcher_useTransparentBoundsImpl(JNIEnv*, jclass, jlong addr, jboolean value) { - MatcherState* state = toMatcherState(addr); - state->matcher()->useTransparentBounds(value); -} - -static jint Matcher_getMatchedGroupIndex0(JNIEnv* env, jclass, jlong patternAddr, jstring javaGroupName) { - icu::RegexPattern* pattern = reinterpret_cast<icu::RegexPattern*>(static_cast<uintptr_t>(patternAddr)); - ScopedJavaUnicodeString groupName(env, javaGroupName); - UErrorCode status = U_ZERO_ERROR; - - jint result = pattern->groupNumberFromName(groupName.unicodeString(), status); - if (U_SUCCESS(status)) { - return result; - } - if (status == U_REGEX_INVALID_CAPTURE_GROUP_NAME) { - return -1; - } - maybeThrowIcuException(env, "RegexPattern::groupNumberFromName", status); - return -1; -} - - -static JNINativeMethod gMethods[] = { - NATIVE_METHOD(Matcher, getMatchedGroupIndex0, "(JLjava/lang/String;)I"), - NATIVE_METHOD(Matcher, findImpl, "(JI[I)Z"), - NATIVE_METHOD(Matcher, findNextImpl, "(J[I)Z"), - NATIVE_METHOD(Matcher, getNativeFinalizer, "()J"), - NATIVE_METHOD(Matcher, groupCountImpl, "(J)I"), - NATIVE_METHOD(Matcher, hitEndImpl, "(J)Z"), - NATIVE_METHOD(Matcher, lookingAtImpl, "(J[I)Z"), - NATIVE_METHOD(Matcher, matchesImpl, "(J[I)Z"), - NATIVE_METHOD(Matcher, openImpl, "(J)J"), - NATIVE_METHOD(Matcher, requireEndImpl, "(J)Z"), - NATIVE_METHOD(Matcher, setInputImpl, "(JLjava/lang/String;II)V"), - NATIVE_METHOD(Matcher, useAnchoringBoundsImpl, "(JZ)V"), - NATIVE_METHOD(Matcher, useTransparentBoundsImpl, "(JZ)V"), -}; -void register_java_util_regex_Matcher(JNIEnv* env) { - jniRegisterNativeMethods(env, "java/util/regex/Matcher", gMethods, NELEM(gMethods)); -} diff --git a/luni/src/main/native/java_util_regex_Pattern.cpp b/luni/src/main/native/java_util_regex_Pattern.cpp deleted file mode 100644 index a893bab9f3..0000000000 --- a/luni/src/main/native/java_util_regex_Pattern.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2010 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 LOG_TAG "Pattern" - -#include <stdlib.h> - -#include <nativehelper/JNIHelp.h> -#include <nativehelper/jni_macros.h> - -#include "unicode/parseerr.h" -#include "unicode/regex.h" - -#include "JniConstants.h" -#include "ScopedJavaUnicodeString.h" - -// ICU documentation: http://icu-project.org/apiref/icu4c/classRegexPattern.html - -static const char* regexDetailMessage(UErrorCode status) { - // These human-readable error messages were culled from "utypes.h", and then slightly tuned - // to make more sense in context. - // If we don't have a special-case, we'll just return the textual name of - // the enum value (such as U_REGEX_RULE_SYNTAX), which is better than nothing. - switch (status) { - case U_REGEX_INTERNAL_ERROR: return "An internal error was detected"; - case U_REGEX_RULE_SYNTAX: return "Syntax error in regexp pattern"; - case U_REGEX_INVALID_STATE: return "Matcher in invalid state for requested operation"; - case U_REGEX_BAD_ESCAPE_SEQUENCE: return "Unrecognized backslash escape sequence in pattern"; - case U_REGEX_PROPERTY_SYNTAX: return "Incorrect Unicode property"; - case U_REGEX_UNIMPLEMENTED: return "Use of unimplemented feature"; - case U_REGEX_MISMATCHED_PAREN: return "Incorrectly nested parentheses in regexp pattern"; - case U_REGEX_NUMBER_TOO_BIG: return "Decimal number is too large"; - case U_REGEX_BAD_INTERVAL: return "Error in {min,max} interval"; - case U_REGEX_MAX_LT_MIN: return "In {min,max}, max is less than min"; - case U_REGEX_INVALID_BACK_REF: return "Back-reference to a non-existent capture group"; - case U_REGEX_INVALID_FLAG: return "Invalid value for match mode flags"; - case U_REGEX_LOOK_BEHIND_LIMIT: return "Look-behind pattern matches must have a bounded maximum length"; - case U_REGEX_SET_CONTAINS_STRING: return "Regular expressions cannot have UnicodeSets containing strings"; - case U_REGEX_OCTAL_TOO_BIG: return "Octal character constants must be <= 0377."; - case U_REGEX_MISSING_CLOSE_BRACKET: return "Missing closing bracket in character class"; - case U_REGEX_INVALID_RANGE: return "In a character range [x-y], x is greater than y"; - case U_REGEX_STACK_OVERFLOW: return "Regular expression backtrack stack overflow"; - case U_REGEX_TIME_OUT: return "Maximum allowed match time exceeded"; - case U_REGEX_STOPPED_BY_CALLER: return "Matching operation aborted by user callback function"; - default: - return u_errorName(status); - } -} - -static void throwPatternSyntaxException(JNIEnv* env, UErrorCode status, jstring pattern, UParseError error) { - static jmethodID method = env->GetMethodID(JniConstants::GetPatternSyntaxExceptionClass(env), - "<init>", "(Ljava/lang/String;Ljava/lang/String;I)V"); - jstring message = env->NewStringUTF(regexDetailMessage(status)); - jclass exceptionClass = JniConstants::GetPatternSyntaxExceptionClass(env); - jobject exception = env->NewObject(exceptionClass, method, message, pattern, error.offset); - env->Throw(reinterpret_cast<jthrowable>(exception)); -} - -static void Pattern_free(void* addr) { - delete reinterpret_cast<icu::RegexPattern*>(addr); -} - -static jlong Pattern_getNativeFinalizer(JNIEnv*, jclass) { - return reinterpret_cast<jlong>(&Pattern_free); -} - -static jlong Pattern_compileImpl(JNIEnv* env, jclass, jstring javaRegex, jint flags) { - flags |= UREGEX_ERROR_ON_UNKNOWN_ESCAPES; - - UErrorCode status = U_ZERO_ERROR; - UParseError error; - error.offset = -1; - - ScopedJavaUnicodeString regex(env, javaRegex); - if (!regex.valid()) { - return 0; - } - icu::UnicodeString& regexString(regex.unicodeString()); - icu::RegexPattern* result = icu::RegexPattern::compile(regexString, flags, error, status); - if (!U_SUCCESS(status)) { - throwPatternSyntaxException(env, status, javaRegex, error); - } - return static_cast<jlong>(reinterpret_cast<uintptr_t>(result)); -} - -static JNINativeMethod gMethods[] = { - NATIVE_METHOD(Pattern, compileImpl, "(Ljava/lang/String;I)J"), - NATIVE_METHOD(Pattern, getNativeFinalizer, "()J"), -}; - -void register_java_util_regex_Pattern(JNIEnv* env) { - jniRegisterNativeMethods(env, "java/util/regex/Pattern", gMethods, NELEM(gMethods)); -} diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp index 8a571fddd8..9879761e80 100644 --- a/luni/src/main/native/libcore_icu_ICU.cpp +++ b/luni/src/main/native/libcore_icu_ICU.cpp @@ -23,19 +23,18 @@ #include <string.h> #include <string> #include <sys/mman.h> -#include <sys/stat.h> #include <sys/time.h> -#include <sys/types.h> #include <time.h> #include <unistd.h> #include <memory> #include <vector> -#include <android-base/unique_fd.h> +#include <androidicuinit/IcuRegistration.h> #include <log/log.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedLocalRef.h> +#include <nativehelper/ScopedStringChars.h> #include <nativehelper/ScopedUtfChars.h> #include <nativehelper/jni_macros.h> #include <nativehelper/toStringArray.h> @@ -44,28 +43,27 @@ #include "JniConstants.h" #include "JniException.h" #include "ScopedIcuLocale.h" +#include "ScopedIcuULoc.h" #include "ScopedJavaUnicodeString.h" #include "unicode/brkiter.h" +#include "unicode/char16ptr.h" #include "unicode/calendar.h" #include "unicode/datefmt.h" #include "unicode/dcfmtsym.h" #include "unicode/decimfmt.h" #include "unicode/dtfmtsym.h" -#include "unicode/dtptngen.h" #include "unicode/gregocal.h" #include "unicode/locid.h" #include "unicode/numfmt.h" #include "unicode/strenum.h" -#include "unicode/timezone.h" #include "unicode/ubrk.h" #include "unicode/ucal.h" #include "unicode/ucasemap.h" -#include "unicode/uclean.h" #include "unicode/ucol.h" #include "unicode/ucurr.h" #include "unicode/udat.h" +#include "unicode/udatpg.h" #include "unicode/uloc.h" -#include "unicode/ulocdata.h" #include "unicode/ures.h" #include "unicode/ustring.h" #include "ureslocs.h" @@ -97,42 +95,21 @@ class ScopedResourceBundle { DISALLOW_COPY_AND_ASSIGN(ScopedResourceBundle); }; -static jstring ICU_addLikelySubtags(JNIEnv* env, jclass, jstring javaLocaleName) { - UErrorCode status = U_ZERO_ERROR; - ScopedUtfChars localeID(env, javaLocaleName); - char maximizedLocaleID[ULOC_FULLNAME_CAPACITY]; - uloc_addLikelySubtags(localeID.c_str(), maximizedLocaleID, sizeof(maximizedLocaleID), &status); - if (U_FAILURE(status)) { - return javaLocaleName; - } - return env->NewStringUTF(maximizedLocaleID); -} - static jstring ICU_getScript(JNIEnv* env, jclass, jstring javaLocaleName) { - ScopedIcuLocale icuLocale(env, javaLocaleName); + ScopedIcuULoc icuLocale(env, javaLocaleName); if (!icuLocale.valid()) { return NULL; } - return env->NewStringUTF(icuLocale.locale().getScript()); -} - -static jint ICU_getCurrencyFractionDigits(JNIEnv* env, jclass, jstring javaCurrencyCode) { - ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode); - if (!currencyCode.valid()) { - return 0; - } - icu::UnicodeString icuCurrencyCode(currencyCode.unicodeString()); + // Normal script part is 4-char long. Being conservative for allocation size + // because if the locale contains script part, it should not be longer than the locale itself. + int32_t capacity = std::max(ULOC_SCRIPT_CAPACITY, icuLocale.locale_length() + 1); + std::unique_ptr<char[]> buffer(new char(capacity)); UErrorCode status = U_ZERO_ERROR; - return ucurr_getDefaultFractionDigits(icuCurrencyCode.getTerminatedBuffer(), &status); -} - -static jint ICU_getCurrencyNumericCode(JNIEnv* env, jclass, jstring javaCurrencyCode) { - ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode); - if (!currencyCode.valid()) { - return 0; + uloc_getScript(icuLocale.locale(), buffer.get(), capacity, &status); + if (U_FAILURE(status)) { + return NULL; } - icu::UnicodeString icuCurrencyCode(currencyCode.unicodeString()); - return ucurr_getNumericCode(icuCurrencyCode.getTerminatedBuffer()); + return env->NewStringUTF(buffer.get()); } // TODO: rewrite this with int32_t ucurr_forLocale(const char* locale, UChar* buff, int32_t buffCapacity, UErrorCode* ec)... @@ -210,122 +187,34 @@ static jstring getCurrencyName(JNIEnv* env, jstring javaLanguageTag, jstring jav return (charCount == 0) ? NULL : jniCreateString(env, chars, charCount); } -static jstring ICU_getCurrencyDisplayName(JNIEnv* env, jclass, jstring javaLanguageTag, jstring javaCurrencyCode) { - return getCurrencyName(env, javaLanguageTag, javaCurrencyCode, UCURR_LONG_NAME); -} - -static jstring ICU_getCurrencySymbol(JNIEnv* env, jclass, jstring javaLanguageTag, jstring javaCurrencyCode) { - return getCurrencyName(env, javaLanguageTag, javaCurrencyCode, UCURR_SYMBOL_NAME); -} - -static jstring ICU_getDisplayCountryNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) { - ScopedIcuLocale icuLocale(env, javaLanguageTag); - if (!icuLocale.valid()) { - return NULL; - } - ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag); - if (!icuTargetLocale.valid()) { - return NULL; - } - - icu::UnicodeString str; - icuTargetLocale.locale().getDisplayCountry(icuLocale.locale(), str); - return jniCreateString(env, str.getBuffer(), str.length()); -} - -static jstring ICU_getDisplayLanguageNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) { - ScopedIcuLocale icuLocale(env, javaLanguageTag); - if (!icuLocale.valid()) { - return NULL; - } - ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag); - if (!icuTargetLocale.valid()) { - return NULL; - } - - icu::UnicodeString str; - icuTargetLocale.locale().getDisplayLanguage(icuLocale.locale(), str); - return jniCreateString(env, str.getBuffer(), str.length()); -} - -static jstring ICU_getDisplayScriptNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) { - ScopedIcuLocale icuLocale(env, javaLanguageTag); - if (!icuLocale.valid()) { - return NULL; - } - ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag); - if (!icuTargetLocale.valid()) { - return NULL; - } - - icu::UnicodeString str; - icuTargetLocale.locale().getDisplayScript(icuLocale.locale(), str); - return jniCreateString(env, str.getBuffer(), str.length()); -} - -static jstring ICU_getDisplayVariantNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) { - ScopedIcuLocale icuLocale(env, javaLanguageTag); - if (!icuLocale.valid()) { - return NULL; - } - ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag); - if (!icuTargetLocale.valid()) { - return NULL; - } - - icu::UnicodeString str; - icuTargetLocale.locale().getDisplayVariant(icuLocale.locale(), str); - return jniCreateString(env, str.getBuffer(), str.length()); -} - static jstring ICU_getISO3Country(JNIEnv* env, jclass, jstring javaLanguageTag) { - ScopedIcuLocale icuLocale(env, javaLanguageTag); + ScopedIcuULoc icuLocale(env, javaLanguageTag); if (!icuLocale.valid()) { return NULL; } - return env->NewStringUTF(icuLocale.locale().getISO3Country()); + return env->NewStringUTF(uloc_getISO3Country(icuLocale.locale())); } static jstring ICU_getISO3Language(JNIEnv* env, jclass, jstring javaLanguageTag) { - ScopedIcuLocale icuLocale(env, javaLanguageTag); + ScopedIcuULoc icuLocale(env, javaLanguageTag); if (!icuLocale.valid()) { return NULL; } - return env->NewStringUTF(icuLocale.locale().getISO3Language()); + return env->NewStringUTF(uloc_getISO3Language(icuLocale.locale())); } static jobjectArray ICU_getISOCountriesNative(JNIEnv* env, jclass) { - return toStringArray(env, icu::Locale::getISOCountries()); + return toStringArray(env, uloc_getISOCountries()); } static jobjectArray ICU_getISOLanguagesNative(JNIEnv* env, jclass) { - return toStringArray(env, icu::Locale::getISOLanguages()); + return toStringArray(env, uloc_getISOLanguages()); } static jobjectArray ICU_getAvailableLocalesNative(JNIEnv* env, jclass) { return toStringArray(env, uloc_countAvailable, uloc_getAvailable); } -static jobjectArray ICU_getAvailableBreakIteratorLocalesNative(JNIEnv* env, jclass) { - return toStringArray(env, ubrk_countAvailable, ubrk_getAvailable); -} - -static jobjectArray ICU_getAvailableCalendarLocalesNative(JNIEnv* env, jclass) { - return toStringArray(env, ucal_countAvailable, ucal_getAvailable); -} - -static jobjectArray ICU_getAvailableCollatorLocalesNative(JNIEnv* env, jclass) { - return toStringArray(env, ucol_countAvailable, ucol_getAvailable); -} - -static jobjectArray ICU_getAvailableDateFormatLocalesNative(JNIEnv* env, jclass) { - return toStringArray(env, udat_countAvailable, udat_getAvailable); -} - -static jobjectArray ICU_getAvailableNumberFormatLocalesNative(JNIEnv* env, jclass) { - return toStringArray(env, unum_countAvailable, unum_getAvailable); -} - static bool setIntegerField(JNIEnv* env, jobject obj, const char* fieldName, int value) { ScopedLocalRef<jobject> integerValue(env, integerValueOf(env, value)); if (integerValue.get() == NULL) return false; @@ -684,7 +573,7 @@ static jboolean ICU_initLocaleDataNative(JNIEnv* env, jclass, jstring javaLangua jstring currencySymbol = NULL; if (internationalCurrencySymbol != NULL) { - currencySymbol = ICU_getCurrencySymbol(env, NULL, javaLanguageTag, internationalCurrencySymbol); + currencySymbol = getCurrencyName(env, javaLanguageTag, internationalCurrencySymbol, UCURR_SYMBOL_NAME); } else { internationalCurrencySymbol = env->NewStringUTF("XXX"); } @@ -698,148 +587,82 @@ static jboolean ICU_initLocaleDataNative(JNIEnv* env, jclass, jstring javaLangua return JNI_TRUE; } -static jstring ICU_toLowerCase(JNIEnv* env, jclass, jstring javaString, jstring javaLanguageTag) { - ScopedJavaUnicodeString scopedString(env, javaString); - if (!scopedString.valid()) { - return NULL; - } - ScopedIcuLocale icuLocale(env, javaLanguageTag); - if (!icuLocale.valid()) { - return NULL; - } - icu::UnicodeString& s(scopedString.unicodeString()); - icu::UnicodeString original(s); - s.toLower(icuLocale.locale()); - return s == original ? javaString : jniCreateString(env, s.getBuffer(), s.length()); -} - -static jstring ICU_toUpperCase(JNIEnv* env, jclass, jstring javaString, jstring javaLanguageTag) { - ScopedJavaUnicodeString scopedString(env, javaString); - if (!scopedString.valid()) { - return NULL; - } - ScopedIcuLocale icuLocale(env, javaLanguageTag); - if (!icuLocale.valid()) { - return NULL; - } - icu::UnicodeString& s(scopedString.unicodeString()); - icu::UnicodeString original(s); - s.toUpper(icuLocale.locale()); - return s == original ? javaString : jniCreateString(env, s.getBuffer(), s.length()); -} - -static jstring versionString(JNIEnv* env, const UVersionInfo& version) { - char versionString[U_MAX_VERSION_STRING_LENGTH]; - u_versionToString(const_cast<UVersionInfo&>(version), &versionString[0]); - return env->NewStringUTF(versionString); -} - -static jstring ICU_getCldrVersion(JNIEnv* env, jclass) { - UErrorCode status = U_ZERO_ERROR; - UVersionInfo cldrVersion; - ulocdata_getCLDRVersion(cldrVersion, &status); - return versionString(env, cldrVersion); -} - -static jstring ICU_getIcuVersion(JNIEnv* env, jclass) { - UVersionInfo icuVersion; - u_getVersion(icuVersion); - return versionString(env, icuVersion); -} - -static jstring ICU_getUnicodeVersion(JNIEnv* env, jclass) { - UVersionInfo unicodeVersion; - u_getUnicodeVersion(unicodeVersion); - return versionString(env, unicodeVersion); -} - -static jstring ICU_getTZDataVersion(JNIEnv* env, jclass) { - UErrorCode status = U_ZERO_ERROR; - const char* version = icu::TimeZone::getTZDataVersion(status); - if (maybeThrowIcuException(env, "icu::TimeZone::getTZDataVersion", status)) { - return NULL; - } - return env->NewStringUTF(version); -} - -static jobjectArray ICU_getAvailableCurrencyCodes(JNIEnv* env, jclass) { - UErrorCode status = U_ZERO_ERROR; - icu::UStringEnumeration e(ucurr_openISOCurrencies(UCURR_COMMON|UCURR_NON_DEPRECATED, &status)); - return fromStringEnumeration(env, status, "ucurr_openISOCurrencies", &e); -} - static jstring ICU_getBestDateTimePatternNative(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLanguageTag) { - ScopedIcuLocale icuLocale(env, javaLanguageTag); + ScopedIcuULoc icuLocale(env, javaLanguageTag); if (!icuLocale.valid()) { return NULL; } UErrorCode status = U_ZERO_ERROR; - std::unique_ptr<icu::DateTimePatternGenerator> generator(icu::DateTimePatternGenerator::createInstance(icuLocale.locale(), status)); - if (maybeThrowIcuException(env, "DateTimePatternGenerator::createInstance", status)) { + std::unique_ptr<UDateTimePatternGenerator, decltype(&udatpg_close)> generator( + udatpg_open(icuLocale.locale(), &status), &udatpg_close); + if (maybeThrowIcuException(env, "udatpg_open", status)) { return NULL; } - ScopedJavaUnicodeString skeletonHolder(env, javaSkeleton); - if (!skeletonHolder.valid()) { - return NULL; - } - icu::UnicodeString result(generator->getBestPattern(skeletonHolder.unicodeString(), status)); - if (maybeThrowIcuException(env, "DateTimePatternGenerator::getBestPattern", status)) { + const ScopedStringChars skeletonHolder(env, javaSkeleton); + // Convert jchar* to UChar* with the inline-able utility provided by char16ptr.h + // which prevents certain compiler optimization than reinterpret_cast. + icu::ConstChar16Ptr skeletonPtr(skeletonHolder.get()); + const UChar* skeleton = icu::toUCharPtr(skeletonPtr.get()); + + int32_t patternLength; + // Try with fixed-size buffer. 128 chars should be enough for most patterns. + // If the buffer is not sufficient, run the below case of U_BUFFER_OVERFLOW_ERROR. + #define PATTERN_BUFFER_SIZE 128 + { + UChar buffer[PATTERN_BUFFER_SIZE]; + status = U_ZERO_ERROR; + patternLength = udatpg_getBestPattern(generator.get(), skeleton, + skeletonHolder.size(), buffer, PATTERN_BUFFER_SIZE, &status); + if (U_SUCCESS(status)) { + return jniCreateString(env, buffer, patternLength); + } else if (status != U_BUFFER_OVERFLOW_ERROR) { + maybeThrowIcuException(env, "udatpg_getBestPattern", status); + return NULL; + } + } + #undef PATTERN_BUFFER_SIZE + + // Case U_BUFFER_OVERFLOW_ERROR + std::unique_ptr<UChar[]> buffer(new UChar[patternLength+1]); + status = U_ZERO_ERROR; + patternLength = udatpg_getBestPattern(generator.get(), skeleton, + skeletonHolder.size(), buffer.get(), patternLength+1, &status); + if (maybeThrowIcuException(env, "udatpg_getBestPattern", status)) { return NULL; } - return jniCreateString(env, result.getBuffer(), result.length()); + return jniCreateString(env, buffer.get(), patternLength); } static void ICU_setDefaultLocale(JNIEnv* env, jclass, jstring javaLanguageTag) { - ScopedIcuLocale icuLocale(env, javaLanguageTag); + ScopedIcuULoc icuLocale(env, javaLanguageTag); if (!icuLocale.valid()) { return; } UErrorCode status = U_ZERO_ERROR; - icu::Locale::setDefault(icuLocale.locale(), status); - maybeThrowIcuException(env, "Locale::setDefault", status); + uloc_setDefault(icuLocale.locale(), &status); + maybeThrowIcuException(env, "uloc_setDefault", status); } static jstring ICU_getDefaultLocale(JNIEnv* env, jclass) { - return env->NewStringUTF(icu::Locale::getDefault().getName()); + return env->NewStringUTF(uloc_getDefault()); } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(ICU, addLikelySubtags, "(Ljava/lang/String;)Ljava/lang/String;"), - NATIVE_METHOD(ICU, getAvailableBreakIteratorLocalesNative, "()[Ljava/lang/String;"), - NATIVE_METHOD(ICU, getAvailableCalendarLocalesNative, "()[Ljava/lang/String;"), - NATIVE_METHOD(ICU, getAvailableCollatorLocalesNative, "()[Ljava/lang/String;"), - NATIVE_METHOD(ICU, getAvailableCurrencyCodes, "()[Ljava/lang/String;"), - NATIVE_METHOD(ICU, getAvailableDateFormatLocalesNative, "()[Ljava/lang/String;"), NATIVE_METHOD(ICU, getAvailableLocalesNative, "()[Ljava/lang/String;"), - NATIVE_METHOD(ICU, getAvailableNumberFormatLocalesNative, "()[Ljava/lang/String;"), NATIVE_METHOD(ICU, getBestDateTimePatternNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), - NATIVE_METHOD(ICU, getCldrVersion, "()Ljava/lang/String;"), NATIVE_METHOD(ICU, getCurrencyCode, "(Ljava/lang/String;)Ljava/lang/String;"), - NATIVE_METHOD(ICU, getCurrencyDisplayName, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), - NATIVE_METHOD(ICU, getCurrencyFractionDigits, "(Ljava/lang/String;)I"), - NATIVE_METHOD(ICU, getCurrencyNumericCode, "(Ljava/lang/String;)I"), - NATIVE_METHOD(ICU, getCurrencySymbol, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), NATIVE_METHOD(ICU, getDefaultLocale, "()Ljava/lang/String;"), - NATIVE_METHOD(ICU, getDisplayCountryNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), - NATIVE_METHOD(ICU, getDisplayLanguageNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), - NATIVE_METHOD(ICU, getDisplayScriptNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), - NATIVE_METHOD(ICU, getDisplayVariantNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), NATIVE_METHOD(ICU, getISO3Country, "(Ljava/lang/String;)Ljava/lang/String;"), NATIVE_METHOD(ICU, getISO3Language, "(Ljava/lang/String;)Ljava/lang/String;"), NATIVE_METHOD(ICU, getISOCountriesNative, "()[Ljava/lang/String;"), NATIVE_METHOD(ICU, getISOLanguagesNative, "()[Ljava/lang/String;"), - NATIVE_METHOD(ICU, getIcuVersion, "()Ljava/lang/String;"), NATIVE_METHOD(ICU, getScript, "(Ljava/lang/String;)Ljava/lang/String;"), - NATIVE_METHOD(ICU, getTZDataVersion, "()Ljava/lang/String;"), - NATIVE_METHOD(ICU, getUnicodeVersion, "()Ljava/lang/String;"), NATIVE_METHOD(ICU, initLocaleDataNative, "(Ljava/lang/String;Llibcore/icu/LocaleData;)Z"), NATIVE_METHOD(ICU, setDefaultLocale, "(Ljava/lang/String;)V"), - NATIVE_METHOD(ICU, toLowerCase, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), - NATIVE_METHOD(ICU, toUpperCase, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), }; // @@ -847,241 +670,17 @@ static JNINativeMethod gMethods[] = { // - Contains handlers for JNI_OnLoad and JNI_OnUnload // -#define FAIL_WITH_STRERROR(s) \ - ALOGE("Couldn't " s " '%s': %s", path_.c_str(), strerror(errno)); \ - return FALSE; - -#define MAYBE_FAIL_WITH_ICU_ERROR(s) \ - if (status != U_ZERO_ERROR) {\ - ALOGE("Couldn't initialize ICU (" s "): %s (%s)", u_errorName(status), path_.c_str()); \ - return FALSE; \ - } - -// Contain the memory map for ICU data files. -// Automatically adds the data file to ICU's list of data files upon constructing. -// -// - Automatically unmaps in the destructor. -struct IcuDataMap { - // Map in ICU data at the path, returning null if it failed (prints error to ALOGE). - static std::unique_ptr<IcuDataMap> Create(const std::string& path) { - std::unique_ptr<IcuDataMap> map(new IcuDataMap(path)); - - if (!map->TryMap()) { - // madvise or ICU could fail but mmap still succeeds. - // Destructor will take care of cleaning up a partial init. - return nullptr; - } - - return map; - } - - // Unmap the ICU data. - ~IcuDataMap() { - TryUnmap(); - } - - private: - IcuDataMap(const std::string& path) - : path_(path), - data_(MAP_FAILED), - data_length_(0) - {} - - bool TryMap() { - // Open the file and get its length. - android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path_.c_str(), O_RDONLY))); - - if (fd.get() == -1) { - FAIL_WITH_STRERROR("open"); - } - - struct stat sb; - if (fstat(fd.get(), &sb) == -1) { - FAIL_WITH_STRERROR("stat"); - } - - data_length_ = sb.st_size; - - // Map it. - data_ = mmap(NULL, data_length_, PROT_READ, MAP_SHARED, fd.get(), 0 /* offset */); - if (data_ == MAP_FAILED) { - FAIL_WITH_STRERROR("mmap"); - } - - // Tell the kernel that accesses are likely to be random rather than sequential. - if (madvise(data_, data_length_, MADV_RANDOM) == -1) { - FAIL_WITH_STRERROR("madvise(MADV_RANDOM)"); - } - - UErrorCode status = U_ZERO_ERROR; - - // Tell ICU to use our memory-mapped data. - udata_setCommonData(data_, &status); - MAYBE_FAIL_WITH_ICU_ERROR("udata_setCommonData"); - - return true; - } - - bool TryUnmap() { - // Don't need to do opposite of udata_setCommonData, - // u_cleanup (performed in unregister_libcore_icu_ICU) takes care of it. - - // Don't need to opposite of madvise, munmap will take care of it. - - if (data_ != MAP_FAILED) { - if (munmap(data_, data_length_) == -1) { - FAIL_WITH_STRERROR("munmap"); - } - } - - // Don't need to close the file, it was closed automatically during TryMap. - return true; - } - - std::string path_; // Save for error messages. - void* data_; // Save for munmap. - size_t data_length_; // Save for munmap. -}; - -struct ICURegistration { - // Init ICU, configuring it and loading the data files. - ICURegistration(JNIEnv* env) { - UErrorCode status = U_ZERO_ERROR; - // Tell ICU it can *only* use our memory-mapped data. - udata_setFileAccess(UDATA_NO_FILES, &status); - if (status != U_ZERO_ERROR) { - ALOGE("Couldn't initialize ICU (s_setFileAccess): %s", u_errorName(status)); - abort(); - } - - // Check the timezone /data override file exists from the "Time zone update via APK" feature. - // https://source.android.com/devices/tech/config/timezone-rules - // If it does, map it first so we use its data in preference to later ones. - std::string dataPath = getDataTimeZonePath(); - if (pathExists(dataPath)) { - ALOGD("Time zone override file found: %s", dataPath.c_str()); - if ((icu_datamap_from_data_ = IcuDataMap::Create(dataPath)) == nullptr) { - ALOGW("TZ override /data file %s exists but could not be loaded. Skipping.", - dataPath.c_str()); - } - } else { - ALOGV("No timezone override /data file found: %s", dataPath.c_str()); - } - - // Check the timezone override file exists from a mounted APEX file. - // If it does, map it next so we use its data in preference to later ones. - std::string tzModulePath = getTimeZoneModulePath(); - if (pathExists(tzModulePath)) { - ALOGD("Time zone APEX file found: %s", tzModulePath.c_str()); - if ((icu_datamap_from_tz_module_ = IcuDataMap::Create(tzModulePath)) == nullptr) { - ALOGW("TZ module override file %s exists but could not be loaded. Skipping.", - tzModulePath.c_str()); - } - } else { - ALOGV("No time zone module override file found: %s", tzModulePath.c_str()); - } - - // Use the ICU data files that shipped with the runtime module for everything else. - icu_datamap_from_runtime_module_ = IcuDataMap::Create(getRuntimeModulePath()); - if (icu_datamap_from_runtime_module_ == nullptr) { - abort(); - } - - // Failures to find the ICU data tend to be somewhat obscure because ICU loads its data on first - // use, which can be anywhere. Force initialization up front so we can report a nice clear error - // and bail. - u_init(&status); - if (status != U_ZERO_ERROR) {\ - ALOGE("Couldn't initialize ICU (u_init): %s", u_errorName(status)); - abort(); - } - - jniRegisterNativeMethods(env, "libcore/icu/ICU", gMethods, NELEM(gMethods)); - } - - // De-init ICU, unloading the data files. Do the opposite of the above function. - ~ICURegistration() { - // Skip unregistering JNI methods explicitly, class unloading takes care of it. - - // Reset libicu state to before it was loaded. - u_cleanup(); - - // Unmap ICU data files from the runtime module. - icu_datamap_from_runtime_module_.reset(); - - // Unmap optional TZ module files from /apex. - icu_datamap_from_tz_module_.reset(); - - // Unmap optional TZ /data file. - icu_datamap_from_data_.reset(); - - // We don't need to call udata_setFileAccess because u_cleanup takes care of it. - } - - static bool pathExists(const std::string path) { - struct stat sb; - return stat(path.c_str(), &sb) == 0; - } - - // Returns a string containing the expected path of the (optional) /data tz data file - static std::string getDataTimeZonePath() { - const char* dataPathPrefix = getenv("ANDROID_DATA"); - if (dataPathPrefix == NULL) { - ALOGE("ANDROID_DATA environment variable not set"); \ - abort(); - } - std::string dataPath; - dataPath = dataPathPrefix; - dataPath += "/misc/zoneinfo/current/icu/icu_tzdata.dat"; - - return dataPath; - } - - // Returns a string containing the expected path of the (optional) /apex tz module data file - static std::string getTimeZoneModulePath() { - const char* tzdataModulePathPrefix = getenv("ANDROID_TZDATA_ROOT"); - if (tzdataModulePathPrefix == NULL) { - ALOGE("ANDROID_TZDATA_ROOT environment variable not set"); \ - abort(); - } - - std::string tzdataModulePath; - tzdataModulePath = tzdataModulePathPrefix; - tzdataModulePath += "/etc/icu/icu_tzdata.dat"; - return tzdataModulePath; - } - - static std::string getRuntimeModulePath() { - const char* runtimeModulePathPrefix = getenv("ANDROID_RUNTIME_ROOT"); - if (runtimeModulePathPrefix == NULL) { - ALOGE("ANDROID_RUNTIME_ROOT environment variable not set"); \ - abort(); - } - - std::string runtimeModulePath; - runtimeModulePath = runtimeModulePathPrefix; - runtimeModulePath += "/etc/icu/"; - runtimeModulePath += U_ICUDATA_NAME; - runtimeModulePath += ".dat"; - return runtimeModulePath; - } - - std::unique_ptr<IcuDataMap> icu_datamap_from_data_; - std::unique_ptr<IcuDataMap> icu_datamap_from_tz_module_; - std::unique_ptr<IcuDataMap> icu_datamap_from_runtime_module_; -}; - -// Use RAII-style initialization/teardown so that we can get unregistered -// when dlclose is called (even if JNI_OnUnload is not). -static std::unique_ptr<ICURegistration> sIcuRegistration; - // Init ICU, configuring it and loading the data files. void register_libcore_icu_ICU(JNIEnv* env) { - sIcuRegistration.reset(new ICURegistration(env)); + androidicuinit::IcuRegistration::Register(); + + jniRegisterNativeMethods(env, "libcore/icu/ICU", gMethods, NELEM(gMethods)); } // De-init ICU, unloading the data files. Do the opposite of the above function. void unregister_libcore_icu_ICU() { - // Explicitly calling this is optional. Dlclose will take care of it as well. - sIcuRegistration.reset(); + // Skip unregistering JNI methods explicitly, class unloading takes care of + // it. + + androidicuinit::IcuRegistration::Deregister(); } diff --git a/luni/src/main/native/libcore_icu_NativeConverter.cpp b/luni/src/main/native/libcore_icu_NativeConverter.cpp deleted file mode 100644 index 9ccfabd119..0000000000 --- a/luni/src/main/native/libcore_icu_NativeConverter.cpp +++ /dev/null @@ -1,700 +0,0 @@ -/** -******************************************************************************* -* Copyright (C) 1996-2006, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -* -* -******************************************************************************* -*/ -/* - * (C) Copyright IBM Corp. 2000 - All Rights Reserved - * A JNI wrapper to ICU native converter Interface - * @author: Ram Viswanadha - */ - -#define LOG_TAG "NativeConverter" - -#include <stdlib.h> -#include <string.h> - -#include <memory> -#include <vector> - -#include <android/log.h> -#include <nativehelper/JNIHelp.h> -#include <nativehelper/ScopedLocalRef.h> -#include <nativehelper/ScopedPrimitiveArray.h> -#include <nativehelper/ScopedStringChars.h> -#include <nativehelper/ScopedUtfChars.h> -#include <nativehelper/jni_macros.h> -#include <nativehelper/toStringArray.h> - -#include "IcuUtilities.h" -#include "JniConstants.h" -#include "JniException.h" -#include "unicode/ucnv.h" -#include "unicode/ucnv_cb.h" -#include "unicode/uniset.h" -#include "unicode/ustring.h" -#include "unicode/utypes.h" - -#define NativeConverter_REPORT 0 -#define NativeConverter_IGNORE 1 -#define NativeConverter_REPLACE 2 - -#define MAX_REPLACEMENT_LENGTH 32 // equivalent to UCNV_ERROR_BUFFER_LENGTH - -struct DecoderCallbackContext { - UChar replacementChars[MAX_REPLACEMENT_LENGTH]; - size_t replacementCharCount; - UConverterToUCallback onUnmappableInput; - UConverterToUCallback onMalformedInput; -}; - -struct EncoderCallbackContext { - char replacementBytes[MAX_REPLACEMENT_LENGTH]; - size_t replacementByteCount; - UConverterFromUCallback onUnmappableInput; - UConverterFromUCallback onMalformedInput; -}; - -static UConverter* toUConverter(jlong address) { - return reinterpret_cast<UConverter*>(static_cast<uintptr_t>(address)); -} - -static bool collectStandardNames(JNIEnv* env, const char* canonicalName, const char* standard, - std::vector<std::string>& result) { - UErrorCode status = U_ZERO_ERROR; - icu::UStringEnumeration e(ucnv_openStandardNames(canonicalName, standard, &status)); - if (maybeThrowIcuException(env, "ucnv_openStandardNames", status)) { - return false; - } - - int32_t count = e.count(status); - if (maybeThrowIcuException(env, "StringEnumeration::count", status)) { - return false; - } - - for (int32_t i = 0; i < count; ++i) { - const icu::UnicodeString* string = e.snext(status); - if (maybeThrowIcuException(env, "StringEnumeration::snext", status)) { - return false; - } - std::string s; - string->toUTF8String(s); - if (s.find_first_of("+,") == std::string::npos) { - result.push_back(s); - } - } - - return true; -} - -static const char* getICUCanonicalName(const char* name) { - UErrorCode error = U_ZERO_ERROR; - const char* canonicalName = NULL; - if ((canonicalName = ucnv_getCanonicalName(name, "MIME", &error)) != NULL) { - return canonicalName; - } else if ((canonicalName = ucnv_getCanonicalName(name, "IANA", &error)) != NULL) { - return canonicalName; - } else if ((canonicalName = ucnv_getCanonicalName(name, "", &error)) != NULL) { - return canonicalName; - } else if ((canonicalName = ucnv_getAlias(name, 0, &error)) != NULL) { - // We have some aliases in the form x-blah .. match those first. - return canonicalName; - } else if (strstr(name, "x-") == name) { - // Check if the converter can be opened with the name given. - error = U_ZERO_ERROR; - icu::LocalUConverterPointer cnv(ucnv_open(name + 2, &error)); - if (U_SUCCESS(error)) { - return name + 2; - } - } - return NULL; -} - -// If a charset listed in the IANA Charset Registry is supported by an implementation -// of the Java platform then its canonical name must be the name listed in the registry. -// Many charsets are given more than one name in the registry, in which case the registry -// identifies one of the names as MIME-preferred. If a charset has more than one registry -// name then its canonical name must be the MIME-preferred name and the other names in -// the registry must be valid aliases. If a supported charset is not listed in the IANA -// registry then its canonical name must begin with one of the strings "X-" or "x-". -static jstring getJavaCanonicalName(JNIEnv* env, const char* icuCanonicalName) { - UErrorCode status = U_ZERO_ERROR; - - // Check to see if this is a well-known MIME or IANA name. - const char* cName = NULL; - if ((cName = ucnv_getStandardName(icuCanonicalName, "MIME", &status)) != NULL) { - return env->NewStringUTF(cName); - } else if ((cName = ucnv_getStandardName(icuCanonicalName, "IANA", &status)) != NULL) { - return env->NewStringUTF(cName); - } - - // Check to see if an alias already exists with "x-" prefix, if yes then - // make that the canonical name. - int32_t aliasCount = ucnv_countAliases(icuCanonicalName, &status); - for (int i = 0; i < aliasCount; ++i) { - const char* name = ucnv_getAlias(icuCanonicalName, i, &status); - if (name != NULL && name[0] == 'x' && name[1] == '-') { - return env->NewStringUTF(name); - } - } - - // As a last resort, prepend "x-" to any alias and make that the canonical name. - status = U_ZERO_ERROR; - const char* name = ucnv_getStandardName(icuCanonicalName, "UTR22", &status); - if (name == NULL && strchr(icuCanonicalName, ',') != NULL) { - name = ucnv_getAlias(icuCanonicalName, 1, &status); - } - // If there is no UTR22 canonical name then just return the original name. - if (name == NULL) { - name = icuCanonicalName; - } - std::unique_ptr<char[]> result(new char[2 + strlen(name) + 1]); - strcpy(&result[0], "x-"); - strcat(&result[0], name); - return env->NewStringUTF(&result[0]); -} - -// Returns a canonical ICU converter name which may have a version number appended to it, based on -// the normal canonical name. This is used to determine the actual native converter to use (the -// normal unversioned name is used to determine the aliases and the Java name). -static char const * getVersionedIcuCanonicalName(char const * icuCanonicalName) { - if (strcmp(icuCanonicalName, "UTF-16") == 0) { - // The ICU UTF-16 converter encodes strings as platform-endian bytes with a BOM. The - // UTF-16,version=2 one encodes as big-endian with a BOM, as what the Charset javadoc requires. - return "UTF-16,version=2"; - } else { - return icuCanonicalName; - } -} - -static jlong NativeConverter_openConverter(JNIEnv* env, jclass, jstring converterName) { - ScopedUtfChars converterNameChars(env, converterName); - if (converterNameChars.c_str() == NULL) { - // Extra debugging check that we do have an exception if the we could not - // create a string. See b/62612946. - if (env->ExceptionCheck()) { - return 0; - } - maybeThrowIcuException(env, "openConverter", U_ILLEGAL_ARGUMENT_ERROR); - return 0; - } - UErrorCode status = U_ZERO_ERROR; - UConverter* cnv = ucnv_open(converterNameChars.c_str(), &status); - maybeThrowIcuException(env, "ucnv_open", status); - if (env->ExceptionCheck()) { - return 0; - } - if (cnv == NULL) { - // Extra debugging exception in case cnv is null but ICU did not report - // an error. See b/62612946. - maybeThrowIcuException(env, "openConverter", U_ILLEGAL_ARGUMENT_ERROR); - return 0; - } - return reinterpret_cast<uintptr_t>(cnv); -} - -static void NativeConverter_closeConverter(JNIEnv*, jclass, jlong address) { - ucnv_close(toUConverter(address)); -} - -static bool shouldCodecThrow(jboolean flush, UErrorCode error) { - if (flush) { - return (error != U_BUFFER_OVERFLOW_ERROR && error != U_TRUNCATED_CHAR_FOUND); - } else { - return (error != U_BUFFER_OVERFLOW_ERROR && error != U_INVALID_CHAR_FOUND && error != U_ILLEGAL_CHAR_FOUND); - } -} - -static jint NativeConverter_encode(JNIEnv* env, jclass, jlong address, - jcharArray source, jint sourceEnd, jbyteArray target, jint targetEnd, - jintArray data, jboolean flush) { - - UConverter* cnv = toUConverter(address); - if (cnv == NULL) { - maybeThrowIcuException(env, "toUConverter", U_ILLEGAL_ARGUMENT_ERROR); - return U_ILLEGAL_ARGUMENT_ERROR; - } - ScopedCharArrayRO uSource(env, source); - if (uSource.get() == NULL) { - maybeThrowIcuException(env, "uSource", U_ILLEGAL_ARGUMENT_ERROR); - return U_ILLEGAL_ARGUMENT_ERROR; - } - ScopedByteArrayRW uTarget(env, target); - if (uTarget.get() == NULL) { - maybeThrowIcuException(env, "uTarget", U_ILLEGAL_ARGUMENT_ERROR); - return U_ILLEGAL_ARGUMENT_ERROR; - } - ScopedIntArrayRW myData(env, data); - if (myData.get() == NULL) { - maybeThrowIcuException(env, "myData", U_ILLEGAL_ARGUMENT_ERROR); - return U_ILLEGAL_ARGUMENT_ERROR; - } - - // Do the conversion. - jint* sourceOffset = &myData[0]; - jint* targetOffset = &myData[1]; - const jchar* mySource = uSource.get() + *sourceOffset; - const UChar* mySourceLimit= reinterpret_cast<const UChar*>(uSource.get()) + sourceEnd; - char* cTarget = reinterpret_cast<char*>(uTarget.get() + *targetOffset); - const char* cTargetLimit = reinterpret_cast<const char*>(uTarget.get() + targetEnd); - UErrorCode errorCode = U_ZERO_ERROR; - ucnv_fromUnicode(cnv, &cTarget, cTargetLimit, reinterpret_cast<const UChar**>(&mySource), mySourceLimit, NULL, (UBool) flush, &errorCode); - *sourceOffset = (mySource - uSource.get()) - *sourceOffset; - *targetOffset = (reinterpret_cast<jbyte*>(cTarget) - uTarget.get()); - - // If there was an error, count the problematic characters. - if (errorCode == U_ILLEGAL_CHAR_FOUND || errorCode == U_INVALID_CHAR_FOUND || - errorCode == U_TRUNCATED_CHAR_FOUND) { - int8_t invalidUCharCount = 32; - UChar invalidUChars[32]; - UErrorCode minorErrorCode = U_ZERO_ERROR; - ucnv_getInvalidUChars(cnv, invalidUChars, &invalidUCharCount, &minorErrorCode); - if (U_SUCCESS(minorErrorCode)) { - myData[2] = invalidUCharCount; - } - } - - // Managed code handles some cases; throw all other errors. - if (shouldCodecThrow(flush, errorCode)) { - maybeThrowIcuException(env, "ucnv_fromUnicode", errorCode); - } - return errorCode; -} - -static jint NativeConverter_decode(JNIEnv* env, jclass, jlong address, - jbyteArray source, jint sourceEnd, jcharArray target, jint targetEnd, - jintArray data, jboolean flush) { - - UConverter* cnv = toUConverter(address); - if (cnv == NULL) { - maybeThrowIcuException(env, "toUConverter", U_ILLEGAL_ARGUMENT_ERROR); - return U_ILLEGAL_ARGUMENT_ERROR; - } - ScopedByteArrayRO uSource(env, source); - if (uSource.get() == NULL) { - maybeThrowIcuException(env, "uSource", U_ILLEGAL_ARGUMENT_ERROR); - return U_ILLEGAL_ARGUMENT_ERROR; - } - ScopedCharArrayRW uTarget(env, target); - if (uTarget.get() == NULL) { - maybeThrowIcuException(env, "uTarget", U_ILLEGAL_ARGUMENT_ERROR); - return U_ILLEGAL_ARGUMENT_ERROR; - } - ScopedIntArrayRW myData(env, data); - if (myData.get() == NULL) { - maybeThrowIcuException(env, "myData", U_ILLEGAL_ARGUMENT_ERROR); - return U_ILLEGAL_ARGUMENT_ERROR; - } - - // Do the conversion. - jint* sourceOffset = &myData[0]; - jint* targetOffset = &myData[1]; - const char* mySource = reinterpret_cast<const char*>(uSource.get() + *sourceOffset); - const char* mySourceLimit = reinterpret_cast<const char*>(uSource.get() + sourceEnd); - UChar* cTarget = reinterpret_cast<UChar*>(uTarget.get()) + *targetOffset; - const UChar* cTargetLimit = reinterpret_cast<UChar*>(uTarget.get()) + targetEnd; - UErrorCode errorCode = U_ZERO_ERROR; - ucnv_toUnicode(cnv, &cTarget, cTargetLimit, &mySource, mySourceLimit, NULL, flush, &errorCode); - *sourceOffset = mySource - reinterpret_cast<const char*>(uSource.get()) - *sourceOffset; - *targetOffset = cTarget - reinterpret_cast<UChar*>(uTarget.get()) - *targetOffset; - - // If there was an error, count the problematic bytes. - if (errorCode == U_ILLEGAL_CHAR_FOUND || errorCode == U_INVALID_CHAR_FOUND || - errorCode == U_TRUNCATED_CHAR_FOUND) { - int8_t invalidByteCount = 32; - char invalidBytes[32] = {'\0'}; - UErrorCode minorErrorCode = U_ZERO_ERROR; - ucnv_getInvalidChars(cnv, invalidBytes, &invalidByteCount, &minorErrorCode); - if (U_SUCCESS(minorErrorCode)) { - myData[2] = invalidByteCount; - } - } - - // Managed code handles some cases; throw all other errors. - if (shouldCodecThrow(flush, errorCode)) { - maybeThrowIcuException(env, "ucnv_toUnicode", errorCode); - } - return errorCode; -} - -static void NativeConverter_resetByteToChar(JNIEnv*, jclass, jlong address) { - UConverter* cnv = toUConverter(address); - if (cnv) { - ucnv_resetToUnicode(cnv); - } -} - -static void NativeConverter_resetCharToByte(JNIEnv*, jclass, jlong address) { - UConverter* cnv = toUConverter(address); - if (cnv) { - ucnv_resetFromUnicode(cnv); - } -} - -static jint NativeConverter_getMaxBytesPerChar(JNIEnv*, jclass, jlong address) { - UConverter* cnv = toUConverter(address); - return (cnv != NULL) ? ucnv_getMaxCharSize(cnv) : -1; -} - -static jint NativeConverter_getMinBytesPerChar(JNIEnv*, jclass, jlong address) { - UConverter* cnv = toUConverter(address); - return (cnv != NULL) ? ucnv_getMinCharSize(cnv) : -1; -} - -static jfloat NativeConverter_getAveBytesPerChar(JNIEnv*, jclass, jlong address) { - UConverter* cnv = toUConverter(address); - return (cnv != NULL) ? ((ucnv_getMaxCharSize(cnv) + ucnv_getMinCharSize(cnv)) / 2.0) : -1; -} - -static jobjectArray NativeConverter_getAvailableCharsetNames(JNIEnv* env, jclass) { - int32_t num = ucnv_countAvailable(); - jobjectArray result = env->NewObjectArray(num, JniConstants::GetStringClass(env), NULL); - if (result == NULL) { - return NULL; - } - for (int i = 0; i < num; ++i) { - const char* name = ucnv_getAvailableName(i); - ScopedLocalRef<jstring> javaCanonicalName(env, getJavaCanonicalName(env, name)); - if (javaCanonicalName.get() == NULL) { - return NULL; - } - env->SetObjectArrayElement(result, i, javaCanonicalName.get()); - if (env->ExceptionCheck()) { - return NULL; - } - } - return result; -} - -static void CHARSET_ENCODER_CALLBACK(const void* rawContext, UConverterFromUnicodeArgs* args, - const UChar* codeUnits, int32_t length, UChar32 codePoint, UConverterCallbackReason reason, - UErrorCode* status) { - if (!rawContext) { - return; - } - const EncoderCallbackContext* ctx = reinterpret_cast<const EncoderCallbackContext*>(rawContext); - switch(reason) { - case UCNV_UNASSIGNED: - ctx->onUnmappableInput(ctx, args, codeUnits, length, codePoint, reason, status); - return; - case UCNV_ILLEGAL: - case UCNV_IRREGULAR: - ctx->onMalformedInput(ctx, args, codeUnits, length, codePoint, reason, status); - return; - case UCNV_CLOSE: - delete ctx; - return; - default: - *status = U_ILLEGAL_ARGUMENT_ERROR; - return; - } -} - -static void encoderReplaceCallback(const void* rawContext, - UConverterFromUnicodeArgs* fromArgs, const UChar*, int32_t, UChar32, - UConverterCallbackReason, UErrorCode * err) { - if (rawContext == NULL) { - return; - } - const EncoderCallbackContext* context = reinterpret_cast<const EncoderCallbackContext*>(rawContext); - *err = U_ZERO_ERROR; - ucnv_cbFromUWriteBytes(fromArgs, context->replacementBytes, context->replacementByteCount, 0, err); -} - -static UConverterFromUCallback getFromUCallback(int32_t mode) { - switch(mode) { - case NativeConverter_IGNORE: return UCNV_FROM_U_CALLBACK_SKIP; - case NativeConverter_REPLACE: return encoderReplaceCallback; - case NativeConverter_REPORT: return UCNV_FROM_U_CALLBACK_STOP; - } - abort(); -} - -static void NativeConverter_setCallbackEncode(JNIEnv* env, jclass, jlong address, - jint onMalformedInput, jint onUnmappableInput, jbyteArray javaReplacement) { - UConverter* cnv = toUConverter(address); - if (cnv == NULL) { - maybeThrowIcuException(env, "toUConverter", U_ILLEGAL_ARGUMENT_ERROR); - return; - } - - UConverterFromUCallback oldCallback = NULL; - const void* oldCallbackContext = NULL; - ucnv_getFromUCallBack(cnv, &oldCallback, const_cast<const void**>(&oldCallbackContext)); - - EncoderCallbackContext* callbackContext = const_cast<EncoderCallbackContext*>( - reinterpret_cast<const EncoderCallbackContext*>(oldCallbackContext)); - // Hold the reference to any new callbackContext we create in a unique_ptr - // so that the default behavior is to collect it automatically if we exit - // early. - std::unique_ptr<EncoderCallbackContext> callbackContextDeleter; - if (callbackContext == NULL) { - callbackContext = new EncoderCallbackContext; - callbackContextDeleter.reset(callbackContext); - } - - callbackContext->onMalformedInput = getFromUCallback(onMalformedInput); - callbackContext->onUnmappableInput = getFromUCallback(onUnmappableInput); - - ScopedByteArrayRO replacementBytes(env, javaReplacement); - if (replacementBytes.get() == NULL - || replacementBytes.size() > sizeof(callbackContext->replacementBytes)) { - maybeThrowIcuException(env, "replacementBytes", U_ILLEGAL_ARGUMENT_ERROR); - return; - } - memcpy(callbackContext->replacementBytes, replacementBytes.get(), replacementBytes.size()); - callbackContext->replacementByteCount = replacementBytes.size(); - - UErrorCode errorCode = U_ZERO_ERROR; - ucnv_setFromUCallBack(cnv, CHARSET_ENCODER_CALLBACK, callbackContext, NULL, NULL, &errorCode); - // Iff callbackContextDeleter holds a reference to a callbackContext we can - // prevent it being automatically deleted here as responsibility for deletion - // has passed to the code that closes the NativeConverter. - callbackContextDeleter.release(); - maybeThrowIcuException(env, "ucnv_setFromUCallBack", errorCode); -} - -static void decoderIgnoreCallback(const void*, UConverterToUnicodeArgs*, const char*, int32_t, UConverterCallbackReason, UErrorCode* err) { - // The icu4c UCNV_FROM_U_CALLBACK_SKIP callback requires that the context is NULL, which is - // never true for us. - *err = U_ZERO_ERROR; -} - -static void decoderReplaceCallback(const void* rawContext, - UConverterToUnicodeArgs* toArgs, const char*, int32_t, UConverterCallbackReason, - UErrorCode* err) { - if (!rawContext) { - return; - } - const DecoderCallbackContext* context = reinterpret_cast<const DecoderCallbackContext*>(rawContext); - *err = U_ZERO_ERROR; - ucnv_cbToUWriteUChars(toArgs,context->replacementChars, context->replacementCharCount, 0, err); -} - -static UConverterToUCallback getToUCallback(int32_t mode) { - switch (mode) { - case NativeConverter_IGNORE: return decoderIgnoreCallback; - case NativeConverter_REPLACE: return decoderReplaceCallback; - case NativeConverter_REPORT: return UCNV_TO_U_CALLBACK_STOP; - } - abort(); -} - -static void CHARSET_DECODER_CALLBACK(const void* rawContext, UConverterToUnicodeArgs* args, - const char* codeUnits, int32_t length, - UConverterCallbackReason reason, UErrorCode* status) { - if (!rawContext) { - return; - } - const DecoderCallbackContext* ctx = reinterpret_cast<const DecoderCallbackContext*>(rawContext); - switch(reason) { - case UCNV_UNASSIGNED: - ctx->onUnmappableInput(ctx, args, codeUnits, length, reason, status); - return; - case UCNV_ILLEGAL: - case UCNV_IRREGULAR: - ctx->onMalformedInput(ctx, args, codeUnits, length, reason, status); - return; - case UCNV_CLOSE: - delete ctx; - return; - default: - *status = U_ILLEGAL_ARGUMENT_ERROR; - return; - } -} - -static void NativeConverter_setCallbackDecode(JNIEnv* env, jclass, jlong address, - jint onMalformedInput, jint onUnmappableInput, jstring javaReplacement) { - UConverter* cnv = toUConverter(address); - if (cnv == NULL) { - maybeThrowIcuException(env, "toConverter", U_ILLEGAL_ARGUMENT_ERROR); - return; - } - - UConverterToUCallback oldCallback; - const void* oldCallbackContext; - ucnv_getToUCallBack(cnv, &oldCallback, &oldCallbackContext); - - DecoderCallbackContext* callbackContext = const_cast<DecoderCallbackContext*>( - reinterpret_cast<const DecoderCallbackContext*>(oldCallbackContext)); - // Hold the reference to any new callbackContext we create in a unique_ptr - // so that the default behavior is to collect it automatically if we exit - // early. - std::unique_ptr<DecoderCallbackContext> callbackContextDeleter; - if (callbackContext == NULL) { - callbackContext = new DecoderCallbackContext; - callbackContextDeleter.reset(callbackContext); - } - - callbackContext->onMalformedInput = getToUCallback(onMalformedInput); - callbackContext->onUnmappableInput = getToUCallback(onUnmappableInput); - - ScopedStringChars replacement(env, javaReplacement); - if (replacement.get() == NULL - || replacement.size() > sizeof(callbackContext->replacementChars) / sizeof(UChar)) { - maybeThrowIcuException(env, "replacement", U_ILLEGAL_ARGUMENT_ERROR); - return; - } - u_strncpy(callbackContext->replacementChars, reinterpret_cast<const UChar*>(replacement.get()), replacement.size()); - callbackContext->replacementCharCount = replacement.size(); - - UErrorCode errorCode = U_ZERO_ERROR; - ucnv_setToUCallBack(cnv, CHARSET_DECODER_CALLBACK, callbackContext, NULL, NULL, &errorCode); - // Iff callbackContextDeleter holds a reference to a callbackContext we can - // prevent it being automatically deleted here as responsibility for deletion - // has passed to the code that closes the NativeConverter. - callbackContextDeleter.release(); - maybeThrowIcuException(env, "ucnv_setToUCallBack", errorCode); -} - -static jfloat NativeConverter_getAveCharsPerByte(JNIEnv* env, jclass, jlong handle) { - return (1 / (jfloat) NativeConverter_getMaxBytesPerChar(env, NULL, handle)); -} - -static jbyteArray NativeConverter_getSubstitutionBytes(JNIEnv* env, jclass, jlong address) { - UConverter* cnv = toUConverter(address); - if (cnv == NULL) { - return NULL; - } - UErrorCode status = U_ZERO_ERROR; - char replacementBytes[MAX_REPLACEMENT_LENGTH]; - int8_t len = sizeof(replacementBytes); - ucnv_getSubstChars(cnv, replacementBytes, &len, &status); - if (!U_SUCCESS(status)) { - return env->NewByteArray(0); - } - jbyteArray result = env->NewByteArray(len); - if (result == NULL) { - return NULL; - } - env->SetByteArrayRegion(result, 0, len, reinterpret_cast<jbyte*>(replacementBytes)); - return result; -} - -static jboolean NativeConverter_contains(JNIEnv* env, jclass, jstring name1, jstring name2) { - ScopedUtfChars name1Chars(env, name1); - if (name1Chars.c_str() == NULL) { - return JNI_FALSE; - } - ScopedUtfChars name2Chars(env, name2); - if (name2Chars.c_str() == NULL) { - return JNI_FALSE; - } - - UErrorCode errorCode = U_ZERO_ERROR; - icu::LocalUConverterPointer converter1(ucnv_open(name1Chars.c_str(), &errorCode)); - icu::UnicodeSet set1; - ucnv_getUnicodeSet(&*converter1, set1.toUSet(), UCNV_ROUNDTRIP_SET, &errorCode); - - icu::LocalUConverterPointer converter2(ucnv_open(name2Chars.c_str(), &errorCode)); - icu::UnicodeSet set2; - ucnv_getUnicodeSet(&*converter2, set2.toUSet(), UCNV_ROUNDTRIP_SET, &errorCode); - - return U_SUCCESS(errorCode) && set1.containsAll(set2); -} - -static jobject NativeConverter_charsetForName(JNIEnv* env, jclass, jstring charsetName) { - ScopedUtfChars charsetNameChars(env, charsetName); - if (charsetNameChars.c_str() == NULL) { - return NULL; - } - - // Get ICU's canonical name for this charset. - const char* icuCanonicalName = getICUCanonicalName(charsetNameChars.c_str()); - if (icuCanonicalName == NULL) { - return NULL; - } - - // Get Java's canonical name for this charset. - jstring javaCanonicalName = getJavaCanonicalName(env, icuCanonicalName); - if (env->ExceptionCheck()) { - return NULL; - } - - // Check that this charset is supported. - { - // ICU doesn't offer any "isSupported", so we just open and immediately close. - UErrorCode error = U_ZERO_ERROR; - icu::LocalUConverterPointer cnv(ucnv_open(icuCanonicalName, &error)); - if (!U_SUCCESS(error)) { - return NULL; - } - } - - // Get the aliases for this charset. - std::vector<std::string> aliases; - if (!collectStandardNames(env, icuCanonicalName, "IANA", aliases)) { - return NULL; - } - if (!collectStandardNames(env, icuCanonicalName, "MIME", aliases)) { - return NULL; - } - if (!collectStandardNames(env, icuCanonicalName, "JAVA", aliases)) { - return NULL; - } - if (!collectStandardNames(env, icuCanonicalName, "WINDOWS", aliases)) { - return NULL; - } - jobjectArray javaAliases = toStringArray(env, aliases); - if (env->ExceptionCheck()) { - return NULL; - } - - // Construct the CharsetICU object. - static jmethodID charsetConstructor = env->GetMethodID(JniConstants::GetCharsetICUClass(env), "<init>", - "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V"); - if (env->ExceptionCheck()) { - return NULL; - } - - char const * versionedIcuCanonicalName = getVersionedIcuCanonicalName(icuCanonicalName); - jstring versionedIcuCanonicalNameStr = env->NewStringUTF(versionedIcuCanonicalName); - if (env->ExceptionCheck()) { - return NULL; - } - - return env->NewObject(JniConstants::GetCharsetICUClass(env), charsetConstructor, - javaCanonicalName, versionedIcuCanonicalNameStr, javaAliases); -} - -static void FreeNativeConverter(void *converter) { - ucnv_close(reinterpret_cast<UConverter*>(converter)); -} - -static jlong NativeConverter_getNativeFinalizer(JNIEnv*, jclass) { - return reinterpret_cast<jlong>(&FreeNativeConverter); -} - -static jlong NativeConverter_getNativeSize(JNIEnv*, jclass) { - // TODO: Improve estimate. - return 200; -} - -static JNINativeMethod gMethods[] = { - NATIVE_METHOD(NativeConverter, charsetForName, "(Ljava/lang/String;)Ljava/nio/charset/Charset;"), - NATIVE_METHOD(NativeConverter, closeConverter, "(J)V"), - NATIVE_METHOD(NativeConverter, contains, "(Ljava/lang/String;Ljava/lang/String;)Z"), - NATIVE_METHOD(NativeConverter, decode, "(J[BI[CI[IZ)I"), - NATIVE_METHOD(NativeConverter, encode, "(J[CI[BI[IZ)I"), - NATIVE_METHOD(NativeConverter, getAvailableCharsetNames, "()[Ljava/lang/String;"), - NATIVE_METHOD(NativeConverter, getAveBytesPerChar, "(J)F"), - NATIVE_METHOD(NativeConverter, getAveCharsPerByte, "(J)F"), - NATIVE_METHOD(NativeConverter, getMaxBytesPerChar, "(J)I"), - NATIVE_METHOD(NativeConverter, getMinBytesPerChar, "(J)I"), - NATIVE_METHOD(NativeConverter, getSubstitutionBytes, "(J)[B"), - NATIVE_METHOD(NativeConverter, openConverter, "(Ljava/lang/String;)J"), - NATIVE_METHOD(NativeConverter, resetByteToChar, "(J)V"), - NATIVE_METHOD(NativeConverter, resetCharToByte, "(J)V"), - NATIVE_METHOD(NativeConverter, setCallbackDecode, "(JIILjava/lang/String;)V"), - NATIVE_METHOD(NativeConverter, setCallbackEncode, "(JII[B)V"), - NATIVE_METHOD(NativeConverter, getNativeFinalizer, "()J"), - NATIVE_METHOD(NativeConverter, getNativeSize, "()J") -}; -void register_libcore_icu_NativeConverter(JNIEnv* env) { - jniRegisterNativeMethods(env, "libcore/icu/NativeConverter", gMethods, NELEM(gMethods)); -} diff --git a/luni/src/main/native/libcore_io_Linux.cpp b/luni/src/main/native/libcore_io_Linux.cpp index 6b8ee085df..9e44e63fe4 100644 --- a/luni/src/main/native/libcore_io_Linux.cpp +++ b/luni/src/main/native/libcore_io_Linux.cpp @@ -418,7 +418,7 @@ static jobject makeSocketAddress(JNIEnv* env, const sockaddr_storage& ss, const } else if (ss.ss_family == AF_PACKET) { const struct sockaddr_ll* sll = reinterpret_cast<const struct sockaddr_ll*>(&ss); static jmethodID ctor = env->GetMethodID(JniConstants::GetPacketSocketAddressClass(env), - "<init>", "(SISB[B)V"); + "<init>", "(IIII[B)V"); if (ctor == NULL) { return NULL; } @@ -429,10 +429,10 @@ static jobject makeSocketAddress(JNIEnv* env, const sockaddr_storage& ss, const env->SetByteArrayRegion(byteArray.get(), 0, sll->sll_halen, reinterpret_cast<const jbyte*>(sll->sll_addr)); jobject packetSocketAddress = env->NewObject(JniConstants::GetPacketSocketAddressClass(env), ctor, - static_cast<jshort>(ntohs(sll->sll_protocol)), + static_cast<jint>(ntohs(sll->sll_protocol)), static_cast<jint>(sll->sll_ifindex), - static_cast<jshort>(sll->sll_hatype), - static_cast<jbyte>(sll->sll_pkttype), + static_cast<jint>(sll->sll_hatype), + static_cast<jint>(sll->sll_pkttype), byteArray.get()); return packetSocketAddress; } @@ -686,22 +686,22 @@ static bool javaUnixSocketAddressToSockaddr( static bool javaPacketSocketAddressToSockaddr( JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) { static jfieldID protocolFid = env->GetFieldID( - JniConstants::GetPacketSocketAddressClass(env), "sll_protocol", "S"); + JniConstants::GetPacketSocketAddressClass(env), "sll_protocol", "I"); static jfieldID ifindexFid = env->GetFieldID( JniConstants::GetPacketSocketAddressClass(env), "sll_ifindex", "I"); static jfieldID hatypeFid = env->GetFieldID( - JniConstants::GetPacketSocketAddressClass(env), "sll_hatype", "S"); + JniConstants::GetPacketSocketAddressClass(env), "sll_hatype", "I"); static jfieldID pkttypeFid = env->GetFieldID( - JniConstants::GetPacketSocketAddressClass(env), "sll_pkttype", "B"); + JniConstants::GetPacketSocketAddressClass(env), "sll_pkttype", "I"); static jfieldID addrFid = env->GetFieldID( JniConstants::GetPacketSocketAddressClass(env), "sll_addr", "[B"); sockaddr_ll *sll = reinterpret_cast<sockaddr_ll *>(&ss); sll->sll_family = AF_PACKET; - sll->sll_protocol = htons(env->GetShortField(javaSocketAddress, protocolFid)); + sll->sll_protocol = htons(env->GetIntField(javaSocketAddress, protocolFid)); sll->sll_ifindex = env->GetIntField(javaSocketAddress, ifindexFid); - sll->sll_hatype = env->GetShortField(javaSocketAddress, hatypeFid); - sll->sll_pkttype = env->GetByteField(javaSocketAddress, pkttypeFid); + sll->sll_hatype = env->GetIntField(javaSocketAddress, hatypeFid); + sll->sll_pkttype = env->GetIntField(javaSocketAddress, pkttypeFid); jbyteArray sllAddr = (jbyteArray) env->GetObjectField(javaSocketAddress, addrFid); if (sllAddr == NULL) { @@ -1242,32 +1242,6 @@ static void Linux_fchown(JNIEnv* env, jobject, jobject javaFd, jint uid, jint gi throwIfMinusOne(env, "fchown", TEMP_FAILURE_RETRY(fchown(fd, uid, gid))); } -static jint Linux_fcntlFlock(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaFlock) { - static jfieldID typeFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_type", "S"); - static jfieldID whenceFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_whence", "S"); - static jfieldID startFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_start", "J"); - static jfieldID lenFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_len", "J"); - static jfieldID pidFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_pid", "I"); - - struct flock64 lock; - memset(&lock, 0, sizeof(lock)); - lock.l_type = env->GetShortField(javaFlock, typeFid); - lock.l_whence = env->GetShortField(javaFlock, whenceFid); - lock.l_start = env->GetLongField(javaFlock, startFid); - lock.l_len = env->GetLongField(javaFlock, lenFid); - lock.l_pid = env->GetIntField(javaFlock, pidFid); - - int rc = IO_FAILURE_RETRY(env, int, fcntl, javaFd, cmd, &lock); - if (rc != -1) { - env->SetShortField(javaFlock, typeFid, lock.l_type); - env->SetShortField(javaFlock, whenceFid, lock.l_whence); - env->SetLongField(javaFlock, startFid, lock.l_start); - env->SetLongField(javaFlock, lenFid, lock.l_len); - env->SetIntField(javaFlock, pidFid, lock.l_pid); - } - return rc; -} - static jint Linux_fcntlInt(JNIEnv* env, jobject, jobject javaFd, jint cmd, jint arg) { int fd = jniGetFDFromFileDescriptor(env, javaFd); return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd, arg))); @@ -1863,6 +1837,21 @@ static jobject Linux_lstat(JNIEnv* env, jobject, jstring javaPath) { return doStat(env, javaPath, true); } +static jobject Linux_memfd_create(JNIEnv* env, jobject, jstring javaName, jint flags) { +#if defined(__BIONIC__) + ScopedUtfChars name(env, javaName); + if (name.c_str() == NULL) { + return NULL; + } + + int fd = throwIfMinusOne(env, "memfd_create", memfd_create(name.c_str(), flags)); + return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL; +#else + UNUSED(env, javaName, flags); + return NULL; +#endif +} + static void Linux_mincore(JNIEnv* env, jobject, jlong address, jlong byteCount, jbyteArray javaVector) { ScopedByteArrayRW vector(env, javaVector); if (vector.get() == NULL) { @@ -2603,7 +2592,6 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Linux, execve, "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V"), NATIVE_METHOD(Linux, fchmod, "(Ljava/io/FileDescriptor;I)V"), NATIVE_METHOD(Linux, fchown, "(Ljava/io/FileDescriptor;II)V"), - NATIVE_METHOD(Linux, fcntlFlock, "(Ljava/io/FileDescriptor;ILandroid/system/StructFlock;)I"), NATIVE_METHOD(Linux, fcntlInt, "(Ljava/io/FileDescriptor;II)I"), NATIVE_METHOD(Linux, fcntlVoid, "(Ljava/io/FileDescriptor;I)I"), NATIVE_METHOD(Linux, fdatasync, "(Ljava/io/FileDescriptor;)V"), @@ -2650,6 +2638,7 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Linux, listxattr, "(Ljava/lang/String;)[Ljava/lang/String;"), NATIVE_METHOD(Linux, lseek, "(Ljava/io/FileDescriptor;JI)J"), NATIVE_METHOD(Linux, lstat, "(Ljava/lang/String;)Landroid/system/StructStat;"), + NATIVE_METHOD(Linux, memfd_create, "(Ljava/lang/String;I)Ljava/io/FileDescriptor;"), NATIVE_METHOD(Linux, mincore, "(JJ[B)V"), NATIVE_METHOD(Linux, mkdir, "(Ljava/lang/String;I)V"), NATIVE_METHOD(Linux, mkfifo, "(Ljava/lang/String;I)V"), diff --git a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp index 9d23837a5b..6df5bddf3b 100644 --- a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp +++ b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp @@ -33,7 +33,8 @@ #include "JniConstants.h" #include "JniException.h" -#include "unicode/unistr.h" +#include "unicode/char16ptr.h" +#include "unicode/ustring.h" #define BUCKET_COUNT 128 @@ -428,11 +429,11 @@ static void jniThrowExpatException(JNIEnv* env, XML_Error error) { * * @returns number of UTF-16 characters which were copied */ -static size_t fillBuffer(ParsingContext* parsingContext, const char* utf8, int byteCount) { +static size_t fillBuffer(ParsingContext* parsingContext, const char* utf8, int byteLength) { JNIEnv* env = parsingContext->env; // Grow buffer if necessary (the length in bytes is always >= the length in chars). - jcharArray javaChars = parsingContext->ensureCapacity(byteCount); + jcharArray javaChars = parsingContext->ensureCapacity(byteLength); if (javaChars == NULL) { return -1; } @@ -443,8 +444,19 @@ static size_t fillBuffer(ParsingContext* parsingContext, const char* utf8, int b return -1; } UErrorCode status = U_ZERO_ERROR; - icu::UnicodeString utf16(icu::UnicodeString::fromUTF8(icu::StringPiece(utf8, byteCount))); - return utf16.extract(chars.get(), byteCount, status); + int32_t length16; + // Use inline C++ class provided by ICU + icu::Char16Ptr dest(chars.get()); // Convert jchar (aka uint16_t*) to char16_t* + // Avoid icu::UnicodeString due to unstable C++ ABI. + u_strFromUTF8WithSub(dest.get(), // dest + byteLength, // destCapacity + &length16, // pDestLength + utf8, // src + byteLength, // srcLength + 0xfffd, // 0xfffd is the standard substitution character for malformed input sequence. + NULL, // Don't care about number of substitutions. + &status); + return length16; } /** diff --git a/luni/src/module/java/module-info.java b/luni/src/module/java/module-info.java index 8a290d9b14..6c2bc125fc 100644 --- a/luni/src/module/java/module-info.java +++ b/luni/src/module/java/module-info.java @@ -69,6 +69,8 @@ module java.base { exports javax.security.auth.x500; exports javax.security.cert; exports javax.sql; + exports jdk.internal.util; + exports jdk.internal.vm.annotation; exports jdk.net; exports sun.invoke.util; exports sun.misc; diff --git a/luni/src/test/annotations/Android.bp b/luni/src/test/annotations/Android.bp new file mode 100644 index 0000000000..437d7c4cde --- /dev/null +++ b/luni/src/test/annotations/Android.bp @@ -0,0 +1,29 @@ +// 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. + +// Build this separately with the --intermediate flag to preserve class +// retention annotations which are otherwise removed by the dexer. +// +// Included as a resource by //libcore:core-tests and loaded into its own +// class loader by libcore.java.lang.reflect.annotations.RetentionPolicyTest. +java_library { + name: "annotations-test", + visibility: [ + "//libcore", + ], + compile_dex: true, + srcs: ["src/**/*.java"], + sdk_version: "core_platform", + dxflags: ["--intermediate"], +} diff --git a/luni/src/test/annotations/src/libcore/tests/annotations/ClassRetentionAnnotation.java b/luni/src/test/annotations/src/libcore/tests/annotations/ClassRetentionAnnotation.java new file mode 100644 index 0000000000..061590f419 --- /dev/null +++ b/luni/src/test/annotations/src/libcore/tests/annotations/ClassRetentionAnnotation.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +package libcore.tests.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.CLASS) +public @interface ClassRetentionAnnotation { +} diff --git a/luni/src/test/annotations/src/libcore/tests/annotations/RetentionAnnotations.java b/luni/src/test/annotations/src/libcore/tests/annotations/RetentionAnnotations.java new file mode 100644 index 0000000000..dd2d85816c --- /dev/null +++ b/luni/src/test/annotations/src/libcore/tests/annotations/RetentionAnnotations.java @@ -0,0 +1,26 @@ +/* + * 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. + */ +package libcore.tests.annotations; + +/** + * A class that exists so it can be annotated with annotations of different retention + * types. + */ +@ClassRetentionAnnotation +@RuntimeRetentionAnnotation +@SourceRetentionAnnotation +public class RetentionAnnotations { +} diff --git a/luni/src/test/annotations/src/libcore/tests/annotations/RuntimeRetentionAnnotation.java b/luni/src/test/annotations/src/libcore/tests/annotations/RuntimeRetentionAnnotation.java new file mode 100644 index 0000000000..8030c10f6e --- /dev/null +++ b/luni/src/test/annotations/src/libcore/tests/annotations/RuntimeRetentionAnnotation.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +package libcore.tests.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface RuntimeRetentionAnnotation { +} diff --git a/luni/src/test/annotations/src/libcore/tests/annotations/SourceRetentionAnnotation.java b/luni/src/test/annotations/src/libcore/tests/annotations/SourceRetentionAnnotation.java new file mode 100644 index 0000000000..901ad5a519 --- /dev/null +++ b/luni/src/test/annotations/src/libcore/tests/annotations/SourceRetentionAnnotation.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +package libcore.tests.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.SOURCE) +public @interface SourceRetentionAnnotation { +} diff --git a/luni/src/test/filesystems/Android.bp b/luni/src/test/filesystems/Android.bp new file mode 100644 index 0000000000..83cb936af5 --- /dev/null +++ b/luni/src/test/filesystems/Android.bp @@ -0,0 +1,31 @@ +// 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. + +// Contains classes for testing loading FileSystemProvider from a custom ClassLoader. +// +// Included as a resource by //libcore:core-tests and loaded into its own +// class loader by libcore.java.nio.file.FileSystemsTest. +java_library { + name: "filesystemstest", + visibility: [ + "//libcore", + ], + compile_dex: true, + srcs: ["src/**/*.java"], + java_resource_dirs: ["resources"], + sdk_version: "core_platform", + errorprone: { + javacflags: ["-Xep:MissingOverride:OFF"], + }, +} diff --git a/luni/src/test/java/libcore/android/system/OsTest.java b/luni/src/test/java/libcore/android/system/OsTest.java index 7536885c20..35019dbe09 100644 --- a/luni/src/test/java/libcore/android/system/OsTest.java +++ b/luni/src/test/java/libcore/android/system/OsTest.java @@ -56,6 +56,7 @@ import java.util.concurrent.atomic.AtomicReference; import junit.framework.TestCase; import libcore.io.IoUtils; +import libcore.testing.io.TestIoUtils; import static android.system.OsConstants.*; @@ -81,11 +82,50 @@ public class OsTest extends TestCase { int flags = Os.fcntlVoid(fis.getFD(), F_GETFD); assertTrue((flags & FD_CLOEXEC) != 0); } finally { - IoUtils.closeQuietly(fis); + TestIoUtils.closeQuietly(fis); f.delete(); } } + public void testFcntlInt_udpSocket() throws Exception { + final FileDescriptor fd = Os.socket(AF_INET, SOCK_DGRAM, 0); + try { + assertEquals(0, (Os.fcntlVoid(fd, F_GETFL) & O_NONBLOCK)); + + // Verify that we can set file descriptor flags on sockets + Os.fcntlInt(fd, F_SETFL, SOCK_DGRAM | O_NONBLOCK); + assertTrue((Os.fcntlVoid(fd, F_GETFL) & O_NONBLOCK) != 0); + + // Check that we can turn it off also. + Os.fcntlInt(fd, F_SETFL, SOCK_DGRAM); + assertEquals(0, (Os.fcntlVoid(fd, F_GETFL) & O_NONBLOCK)); + } finally { + Os.close(fd); + } + } + + public void testFcntlInt_invalidCmd() throws Exception { + final FileDescriptor fd = Os.socket(AF_INET, SOCK_DGRAM, 0); + try { + final int unknownCmd = -1; + Os.fcntlInt(fd, unknownCmd, 0); + fail("Expected failure due to invalid cmd"); + } catch (ErrnoException expected) { + assertEquals(EINVAL, expected.errno); + } finally { + Os.close(fd); + } + } + + public void testFcntlInt_nullFd() throws Exception { + try { + Os.fcntlInt(null, F_SETFL, O_NONBLOCK); + fail("Expected failure due to null file descriptor"); + } catch (ErrnoException expected) { + assertEquals(EBADF, expected.errno); + } + } + public void testUnixDomainSockets_in_file_system() throws Exception { String path = System.getProperty("java.io.tmpdir") + "/test_unix_socket"; new File(path).delete(); @@ -537,10 +577,14 @@ public class OsTest extends TestCase { public void test_NetlinkSocket() throws Exception { FileDescriptor nlSocket = Os.socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - Os.bind(nlSocket, new NetlinkSocketAddress()); - NetlinkSocketAddress address = (NetlinkSocketAddress) Os.getsockname(nlSocket); - assertTrue(address.getPortId() > 0); - assertEquals(0, address.getGroupsMask()); + try { + Os.bind(nlSocket, new NetlinkSocketAddress()); + // Non-system processes should not be allowed to bind() to NETLINK_ROUTE sockets. + // http://b/141455849 + fail("bind() on NETLINK_ROUTE socket succeeded"); + } catch (ErrnoException expectedException) { + assertEquals(expectedException.errno, EACCES); + } NetlinkSocketAddress nlKernel = new NetlinkSocketAddress(); Os.connect(nlSocket, nlKernel); @@ -550,14 +594,18 @@ public class OsTest extends TestCase { Os.close(nlSocket); } + // This test is excluded from CTS via the knownfailures.txt because it requires extra + // permissions not available in CTS. To run it you have to use an -eng build and use a tool like + // vogar that runs the Android runtime as a privileged user. public void test_PacketSocketAddress() throws Exception { NetworkInterface lo = NetworkInterface.getByName("lo"); FileDescriptor fd = Os.socket(AF_PACKET, SOCK_DGRAM, ETH_P_IPV6); - PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6, lo.getIndex()); + PacketSocketAddress addr = + new PacketSocketAddress(ETH_P_IPV6, lo.getIndex(), null /* sll_addr */); Os.bind(fd, addr); PacketSocketAddress bound = (PacketSocketAddress) Os.getsockname(fd); - assertEquals((short) ETH_P_IPV6, bound.sll_protocol); // ETH_P_IPV6 is an int. + assertEquals(ETH_P_IPV6, bound.sll_protocol); assertEquals(lo.getIndex(), bound.sll_ifindex); assertEquals(ARPHRD_LOOPBACK, bound.sll_hatype); assertEquals(0, bound.sll_pkttype); @@ -568,6 +616,57 @@ public class OsTest extends TestCase { for (int i = 0; i < 6; i++) { assertEquals(0, bound.sll_addr[i]); } + + // The following checks that the packet socket address was constructed correctly in a form + // that the kernel understands. If the address is correct, the bind should result in a + // socket that is listening only for IPv6 packets, and only on loopback. + + // Send an IPv4 packet on loopback. + // We send ourselves an IPv4 packet first. If we don't receive it, that (with high + // probability) ensures that the packet socket does not see IPv4 packets. + try (DatagramSocket s = new DatagramSocket()) { + byte[] packet = new byte[64]; + s.send(new DatagramPacket(packet, 0, packet.length, Inet4Address.LOOPBACK, + 53 /* arbitrary port */)); + } + + // Send an IPv6 packet on loopback. + // Sending ourselves an IPv6 packet should cause the socket to receive a packet. + // The idea is that if the code gets sll_protocol wrong, then the packet socket will receive + // no packets and the test will fail. + try (DatagramSocket s = new DatagramSocket()) { + byte[] packet = new byte[64]; + s.send(new DatagramPacket(packet, 0, packet.length, Inet6Address.LOOPBACK, + 53 /* arbitrary port */)); + } + + // Check that the socket associated with fd has received an IPv6 packet, not necessarily the + // UDP one we sent above. IPv6 packets always begin with the nibble 6. If we get anything + // else it means we're catching non-IPv6 or non-loopback packets unexpectedly. Since the + // socket is not discriminating it may catch packets unrelated to this test from things + // happening on the device at the same time, so we can't assert too much about the received + // packet, i.e. no length / content check. + { + byte[] receivedPacket = new byte[4096]; + Os.read(fd, receivedPacket, 0, receivedPacket.length); + assertEquals(6, (receivedPacket[0] & 0xf0) >> 4); + + byte[] sourceAddress = getIPv6AddressBytesAtOffset(receivedPacket, 8); + assertArrayEquals(Inet6Address.LOOPBACK.getAddress(), sourceAddress); + + byte[] destAddress = getIPv6AddressBytesAtOffset(receivedPacket, 24); + assertArrayEquals(Inet6Address.LOOPBACK.getAddress(), destAddress); + } + + Os.close(fd); + } + + private static byte[] getIPv6AddressBytesAtOffset(byte[] packet, int offsetIndex) { + byte[] address = new byte[16]; + for (int i = 0; i < 16; i++) { + address[i] = packet[i + offsetIndex]; + } + return address; } public void test_byteBufferPositions_sendto_recvfrom_af_inet() throws Exception { @@ -885,7 +984,7 @@ public class OsTest extends TestCase { // ENOTSUP, Extended attributes are not supported by the filesystem, or are disabled. // Since kernel version 4.9 (or some other version after 4.4), *xattr() methods - // may set errno to EACCESS instead. This behavior change is likely related to + // may set errno to EACCES instead. This behavior change is likely related to // https://patchwork.kernel.org/patch/9294421/ which reimplemented getxattr, setxattr, // and removexattr on top of generic handlers. final String path = "/proc/self/stat"; @@ -1133,7 +1232,7 @@ public class OsTest extends TestCase { } public void test_readlink() throws Exception { - File path = new File(IoUtils.createTemporaryDirectory("test_readlink"), "symlink"); + File path = new File(TestIoUtils.createTemporaryDirectory("test_readlink"), "symlink"); // ext2 and ext4 have PAGE_SIZE limits on symlink targets. // If file encryption is enabled, there's extra overhead to store the @@ -1251,7 +1350,7 @@ public class OsTest extends TestCase { android.system.Os.sendfile(outFd, inFd, offset, maxBytes); assertEquals(expectedEndOffset, offset == null ? null : offset.value); } - return IoUtils.readFileAsString(out.getPath()); + return TestIoUtils.readFileAsString(out.getPath()); } finally { out.delete(); } @@ -1307,7 +1406,7 @@ public class OsTest extends TestCase { assertEquals(5, offOut.value); } - assertEquals("oobar", IoUtils.readFileAsString(out.getPath())); + assertEquals("oobar", TestIoUtils.readFileAsString(out.getPath())); Os.close(pipe[0]); Os.close(pipe[1]); @@ -1414,4 +1513,83 @@ public class OsTest extends TestCase { InetAddress inetAddress = Os.inet_pton(AF_INET, srcAddress); assertNull(inetAddress); } + + /** + * Verifies the {@link OsConstants#MAP_ANONYMOUS}. + */ + public void testMapAnonymous() throws Exception { + final long size = 4096; + final long address = Os.mmap(0, size, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, new FileDescriptor(), 0); + assertTrue(address > 0); + Os.munmap(address, size); + } + + public void testMemfdCreate() throws Exception { + FileDescriptor fd = null; + try { + fd = Os.memfd_create("test_memfd", 0); + assertNotNull(fd); + assertTrue(fd.valid()); + + StructStat stat = Os.fstat(fd); + assertEquals(0, stat.st_size); + + final byte[] expected = new byte[] {1, 2, 3, 4}; + Os.write(fd, expected, 0, expected.length); + stat = Os.fstat(fd); + assertEquals(expected.length, stat.st_size); + + byte[] actual = new byte[expected.length]; + // should be seekable + Os.lseek(fd, 0, SEEK_SET); + Os.read(fd, actual, 0, actual.length); + assertArrayEquals(expected, actual); + } finally { + if (fd != null) { + Os.close(fd); + fd = null; + } + } + } + + public void testMemfdCreateFlags() throws Exception { + FileDescriptor fd = null; + + // test that MFD_CLOEXEC is obeyed + try { + fd = Os.memfd_create("test_memfd", 0); + assertNotNull(fd); + assertTrue(fd.valid()); + int flags = Os.fcntlVoid(fd, F_GETFD); + assertTrue("Expected flags to not include " + FD_CLOEXEC + ", actual value: " + flags, + 0 == (flags & FD_CLOEXEC)); + } finally { + if (fd != null) { + Os.close(fd); + fd = null; + } + } + try { + fd = Os.memfd_create("test_memfd", MFD_CLOEXEC); + assertNotNull(fd); + assertTrue(fd.valid()); + int flags = Os.fcntlVoid(fd, F_GETFD); + assertTrue("Expected flags to include " + FD_CLOEXEC + ", actual value: " + flags, + 0 != (flags & FD_CLOEXEC)); + } finally { + if (fd != null) { + Os.close(fd); + fd = null; + } + } + } + + public void testMemfdCreateErrno() throws Exception { + expectException(() -> Os.memfd_create(null, 0), NullPointerException.class, null, + "memfd_create(null, 0)"); + + expectException(() -> Os.memfd_create("test_memfd", 0xffff), ErrnoException.class, EINVAL, + "memfd_create(\"test_memfd\", 0xffff)"); + } } diff --git a/luni/src/test/java/libcore/dalvik/system/BaseDexClassLoaderTest.java b/luni/src/test/java/libcore/dalvik/system/BaseDexClassLoaderTest.java index 84f7f71178..7d3b6f2b87 100644 --- a/luni/src/test/java/libcore/dalvik/system/BaseDexClassLoaderTest.java +++ b/luni/src/test/java/libcore/dalvik/system/BaseDexClassLoaderTest.java @@ -20,10 +20,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import dalvik.system.BaseDexClassLoader; import dalvik.system.DelegateLastClassLoader; import dalvik.system.PathClassLoader; +import java.lang.reflect.Method; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; @@ -32,6 +34,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -46,23 +49,21 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public final class BaseDexClassLoaderTest { private static class Reporter implements BaseDexClassLoader.Reporter { - public final List<ClassLoader> classLoaders = new ArrayList<>(); - public final List<String> loadedDexPaths = new ArrayList<>(); + public final Map<String, String> loadedDexMapping = new HashMap<String, String>(); @Override - public void report(List<ClassLoader> loaders, List<String> dexPaths) { - classLoaders.addAll(loaders); - loadedDexPaths.addAll(dexPaths); + public void report(Map<String, String> contextMap) { + loadedDexMapping.putAll(contextMap); } void reset() { - classLoaders.clear(); - loadedDexPaths.clear(); + loadedDexMapping.clear(); } } private ClassLoader pcl; private File jar; + private File jar2; private Reporter reporter; // For resources that we will load in this test. We're re-using parent.jar and child.jar @@ -81,7 +82,7 @@ public final class BaseDexClassLoaderTest { } @Before - public void extractTestJar() throws Exception { + public void extractTestJars() throws Exception { // Extract loading-test.jar from the resource. pcl = BaseDexClassLoaderTest.class.getClassLoader(); jar = File.createTempFile("loading-test", ".jar"); @@ -89,6 +90,11 @@ public final class BaseDexClassLoaderTest { FileOutputStream out = new FileOutputStream(jar)) { Streams.copy(in, out); } + jar2 = File.createTempFile("loading-test2", ".jar"); + try (InputStream in = pcl.getResourceAsStream("dalvik/system/loading-test2.jar"); + FileOutputStream out = new FileOutputStream(jar2)) { + Streams.copy(in, out); + } } @Before @@ -103,8 +109,9 @@ public final class BaseDexClassLoaderTest { } @After - public void deleteTestJar() throws Exception { + public void deleteTestJars() throws Exception { assertTrue(jar.delete()); + assertTrue(jar2.delete()); } @Test @@ -113,17 +120,15 @@ public final class BaseDexClassLoaderTest { BaseDexClassLoader cl1 = new PathClassLoader(jar.getPath(), ClassLoader.getSystemClassLoader()); - // Verify the reported data. - assertEquals(2, reporter.loadedDexPaths.size()); - assertEquals(2, reporter.classLoaders.size()); - - // First class loader should be the one loading the files - assertEquals(jar.getPath(), reporter.loadedDexPaths.get(0)); - assertEquals(cl1, reporter.classLoaders.get(0)); + assertEquals(1, reporter.loadedDexMapping.size()); - // Second class loader should be the system class loader. - // Don't check the actual classpath as that might vary based on system properties. - assertEquals(ClassLoader.getSystemClassLoader(), reporter.classLoaders.get(1)); + String[] contexts = reporter.loadedDexMapping.get(jar.getPath()).split(";"); + assertEquals(2, contexts.length); + // Verify the context for the loaded dex files. + assertEquals("PCL[]", contexts[0]); + // We cannot fully verify the context of the system class loader because its classpath + // may vary based on system properties and whether or not we are in a test environment. + assertTrue(contexts[1].startsWith("PCL[")); } @Test @@ -132,16 +137,10 @@ public final class BaseDexClassLoaderTest { ClassLoader unknownLoader = new ClassLoader(ClassLoader.getSystemClassLoader()) {}; BaseDexClassLoader cl1 = new PathClassLoader(jar.getPath(), unknownLoader); - assertEquals(3, reporter.loadedDexPaths.size()); - assertEquals(3, reporter.classLoaders.size()); - - assertEquals(jar.getPath(), reporter.loadedDexPaths.get(0)); - assertEquals(cl1, reporter.classLoaders.get(0)); - - assertNull(reporter.loadedDexPaths.get(1)); - assertEquals(unknownLoader, reporter.classLoaders.get(1)); - - assertEquals(ClassLoader.getSystemClassLoader(), reporter.classLoaders.get(2)); + // Verify the dex path gets reported, but with no class loader context due to the foreign + // class loader. + assertEquals(Map.of(jar.getPath(), "=UnsupportedClassLoaderContext="), + reporter.loadedDexMapping); } @Test @@ -149,8 +148,15 @@ public final class BaseDexClassLoaderTest { BaseDexClassLoader cl1 = new PathClassLoader(jar.getPath(), ClassLoader.getSystemClassLoader()); - assertEquals(2, reporter.loadedDexPaths.size()); - assertEquals(2, reporter.classLoaders.size()); + assertEquals(1, reporter.loadedDexMapping.size()); + + String[] contexts = reporter.loadedDexMapping.get(jar.getPath()).split(";"); + assertEquals(2, contexts.length); + // Verify the context for the loaded dex files. + assertEquals("PCL[]", contexts[0]); + // We cannot fully verify the context of the system class loader because its classpath + // may vary based on system properties and whether or not we are in a test environment. + assertTrue(contexts[1].startsWith("PCL[")); // Check we don't report after the reporter is unregistered. unregisterReporter(); @@ -160,8 +166,120 @@ public final class BaseDexClassLoaderTest { BaseDexClassLoader cl2 = new PathClassLoader(jar.getPath(), pcl); // Verify nothing reported - assertEquals(0, reporter.loadedDexPaths.size()); - assertEquals(0, reporter.classLoaders.size()); + assertEquals(Map.<String, String>of(), reporter.loadedDexMapping); + } + + @Test + public void testReporting_multipleJars() throws Exception { + // Load the jar file using a PathClassLoader. + BaseDexClassLoader cl1 = new PathClassLoader( + String.join(File.pathSeparator, jar.getPath(), jar2.getPath()), + ClassLoader.getSystemClassLoader()); + + assertEquals(2, reporter.loadedDexMapping.size()); + // Verify the first jar. + String[] contexts = reporter.loadedDexMapping.get(jar.getPath()).split(";"); + assertEquals(2, contexts.length); + // Verify the context for the loaded dex files. + assertEquals("PCL[]", contexts[0]); + // We cannot fully verify the context of the system class loader because its classpath + // may vary based on system properties and whether or not we are in a test environment. + assertTrue(contexts[1].startsWith("PCL[")); + + // Verify the second jar. + String[] contexts2 = reporter.loadedDexMapping.get(jar2.getPath()).split(";"); + assertEquals(2, contexts2.length); + // Verify the context for the loaded dex files. + assertEquals("PCL[" + jar.getPath() + "]", contexts2[0]); + // We cannot fully verify the context of the system class loader because its classpath + // may vary based on system properties and whether or not we are in a test environment. + assertTrue(contexts2[1].startsWith("PCL[")); + } + + + /** + * Separates the system class loader context from the rest of the context. + * Returns an array of 2 elements, where index 0 is the application class loader context + * without the system class loader and index 0 is the system class loader context. + */ + private String[] separateSystemClassLoaderContext(String context) { + int clcSeparatorIndex = context.lastIndexOf(";"); + String jarContext = context.substring(0, clcSeparatorIndex); + String systemClassLoaderContext = context.substring(clcSeparatorIndex + 1); + return new String[] {jarContext, systemClassLoaderContext}; + } + + @Test + public void testReporting_withSharedLibraries() throws Exception { + final ClassLoader parent = ClassLoader.getSystemClassLoader(); + final ClassLoader sharedLoaders[] = new ClassLoader[] { + new PathClassLoader(jar2.getPath(), /* librarySearchPath */ null, parent), + }; + // Reset so we don't get load reports from creating the shared library CL + reporter.reset(); + + BaseDexClassLoader bdcl = new PathClassLoader(jar.getPath(), null, parent, sharedLoaders); + + assertEquals(1, reporter.loadedDexMapping.size()); + + String[] contexts = separateSystemClassLoaderContext( + reporter.loadedDexMapping.get(jar.getPath())); + // We cannot fully verify the context of the system class loader because its classpath + // may vary based on system properties and whether or not we are in a test environment. + assertTrue(contexts[1].startsWith("PCL[")); + // Verify the context for the loaded dex files. The system class loader should be part + // of the shared library class loader. + assertEquals("PCL[]{PCL[" + jar2.getPath() + "];" + contexts[1] + "}", + contexts[0]); + } + + @Test + public void testReporting_multipleJars_withSharedLibraries() throws Exception { + final ClassLoader parent = ClassLoader.getSystemClassLoader(); + final String sharedJarPath = resourcesMap.get("parent.jar").getAbsolutePath(); + final ClassLoader sharedLoaders[] = new ClassLoader[] { + new PathClassLoader(sharedJarPath, /* librarySearchPath */ null, parent), + }; + // Reset so we don't get load reports from creating the shared library CL + reporter.reset(); + + BaseDexClassLoader bdcl = new PathClassLoader( + String.join(File.pathSeparator, jar.getPath(), jar2.getPath()), + null, parent, sharedLoaders); + + assertEquals(2, reporter.loadedDexMapping.size()); + + + // Verify the first jar. + String[] contexts = separateSystemClassLoaderContext( + reporter.loadedDexMapping.get(jar.getPath())); + String contextSuffix = "{PCL[" + sharedJarPath + "];" + contexts[1] + "}"; + + // We cannot fully verify the context of the system class loader because its classpath + // may vary based on system properties and whether or not we are in a test environment. + assertTrue(contexts[1].startsWith("PCL[")); + // Verify the context for the loaded dex files. + assertEquals("PCL[]" + contextSuffix, contexts[0]); + // We cannot fully verify the context of the system class loader because its classpath + // may vary based on system properties and whether or not we are in a test environment. + assertTrue(contexts[1].startsWith("PCL[")); + + // Verify the second jar. + String[] contexts2 = separateSystemClassLoaderContext( + reporter.loadedDexMapping.get(jar2.getPath())); + String contextSuffix2 = "{PCL[" + sharedJarPath + "];" + contexts2[1] + "}"; + + // Verify the context for the loaded dex files. + assertEquals("PCL[" + jar.getPath() + "]" + contextSuffix2, contexts2[0]); + // We cannot fully verify the context of the system class loader because its classpath + // may vary based on system properties and whether or not we are in a test environment. + assertTrue(contexts2[1].startsWith("PCL[")) ; + } + + @Test + public void testReporting_emptyPath() throws Exception { + BaseDexClassLoader cl1 = new PathClassLoader("", ClassLoader.getSystemClassLoader()); + assertEquals(Map.<String, String>of(), reporter.loadedDexMapping); } /* package */ static List<String> readResources(ClassLoader cl, String resourceName) @@ -337,4 +455,30 @@ public final class BaseDexClassLoaderTest { assertEquals("child", readResource(delegateLast, "resource.txt")); } + + @Test + public void testAddDexPath() throws Exception { + BaseDexClassLoader bdcl = new PathClassLoader(jar.getPath(), + ClassLoader.getSystemClassLoader()); + + Class test1Class = bdcl.loadClass("test.Test1"); + Method testMethod = test1Class.getMethod("test", (Class[]) null); + String testResult = (String) testMethod.invoke(null, (Object[]) null); + assertEquals("blort", testResult); + + // Just for completeness sake, prove that we were able to load + // the class only after addDexPath was called. + try { + bdcl.loadClass("test2.Target2"); + fail(); + } catch (ClassNotFoundException expected) { + } + + bdcl.addDexPath(jar2.getPath()); + + Class target2Class = bdcl.loadClass("test2.Target2"); + Method frotzMethod = target2Class.getMethod("frotz", (Class[]) null); + String frotzResult = (String) frotzMethod.invoke(null, (Object[]) null); + assertEquals("frotz", frotzResult); + } } diff --git a/luni/src/test/java/libcore/dalvik/system/DexClassLoaderTest.java b/luni/src/test/java/libcore/dalvik/system/DexClassLoaderTest.java index efc9c29513..0294f26bb6 100644 --- a/luni/src/test/java/libcore/dalvik/system/DexClassLoaderTest.java +++ b/luni/src/test/java/libcore/dalvik/system/DexClassLoaderTest.java @@ -348,6 +348,16 @@ public class DexClassLoaderTest extends TestCase { * Tests native modification behaviors */ + private boolean isLibraryFound(DexClassLoader loader, String libName) { + String ret = loader.findLibrary(libName); + if (ret != null && ret.startsWith("/")) { + return true; + } + // This case includes findLibrary returning null or a mapped libname + // e.g. "libfake.so" when libName was "fake". + return false; + } + /** * Checks that a adding a native library to an existing class loader makes it visible for * subsequent calls. @@ -357,12 +367,12 @@ public class DexClassLoaderTest extends TestCase { String path = nativeLib1.getParentFile().getAbsolutePath(); DexClassLoader classLoader = (DexClassLoader) createLoader(dex1); - assertNull("findLibrary should not find un-added path", - classLoader.findLibrary("fake")); + assertFalse("findLibrary should not find un-added path", + isLibraryFound(classLoader, "fake")); classLoader.addNativePath(Collections.singletonList(path)); - assertNotNull("findLibrary should find newly added path", - classLoader.findLibrary("fake")); + assertTrue("findLibrary should find newly added path", + isLibraryFound(classLoader, "fake")); } } diff --git a/luni/src/test/java/libcore/dalvik/system/EmulatedStackFrameTest.java b/luni/src/test/java/libcore/dalvik/system/EmulatedStackFrameTest.java index 6d61300443..c17fad71cf 100644 --- a/luni/src/test/java/libcore/dalvik/system/EmulatedStackFrameTest.java +++ b/luni/src/test/java/libcore/dalvik/system/EmulatedStackFrameTest.java @@ -113,6 +113,23 @@ public class EmulatedStackFrameTest extends TestCase { assertEquals("foo", reader.nextReference(String.class)); } + public void testReaderWriter_assignableTypes() { + EmulatedStackFrame stackFrame = EmulatedStackFrame.create( + MethodType.methodType(Object.class, Object.class)); + + EmulatedStackFrame.StackFrameWriter writer = new EmulatedStackFrame.StackFrameWriter(); + writer.attach(stackFrame); + writer.putNextReference(Boolean.TRUE, Object.class); + writer.makeReturnValueAccessor(); + writer.putNextReference(Boolean.FALSE, Object.class); + + EmulatedStackFrame.StackFrameReader reader = new EmulatedStackFrame.StackFrameReader(); + reader.attach(stackFrame); + assertEquals(Boolean.TRUE, reader.nextReference(Object.class)); + reader.makeReturnValueAccessor(); + assertEquals(Boolean.FALSE, reader.nextReference(Object.class)); + } + public void testReaderWriter_wrongTypes() { EmulatedStackFrame stackFrame = EmulatedStackFrame.create( MethodType.methodType(boolean.class, String.class)); diff --git a/luni/src/test/java/libcore/java/io/FileDescriptorTest.java b/luni/src/test/java/libcore/java/io/FileDescriptorTest.java index 3e82690bf3..390cfd650b 100644 --- a/luni/src/test/java/libcore/java/io/FileDescriptorTest.java +++ b/luni/src/test/java/libcore/java/io/FileDescriptorTest.java @@ -16,7 +16,10 @@ package libcore.java.io; +import android.system.Os; + import java.io.File; +import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; @@ -24,6 +27,8 @@ import java.io.RandomAccessFile; import java.net.ServerSocket; import junit.framework.TestCase; +import static org.junit.Assert.assertNotEquals; + public class FileDescriptorTest extends TestCase { public void testReadOnlyFileDescriptorSync() throws Exception { File f= File.createTempFile("FileDescriptorTest", "tmp"); @@ -40,4 +45,31 @@ public class FileDescriptorTest extends TestCase { assertTrue(s.getImpl().getFD$().isSocket$()); s.close(); } + + public void testStaticFileDescriptors() { + assertTrue(FileDescriptor.in.valid()); + assertTrue(FileDescriptor.out.valid()); + assertTrue(FileDescriptor.err.valid()); + } + + public void testFileDescriptorCloneForFork() throws Exception { + FileDescriptor [] sources = { FileDescriptor.in, FileDescriptor.out, FileDescriptor.err }; + for (FileDescriptor source : sources) { + // Create a new file descriptor and set it's native descriptor to each of the well + // known descriptors in FileDescriptor. + FileDescriptor target = new FileDescriptor(); + target.setInt$(source.getInt$()); + assertEquals(target.getInt$(), source.getInt$()); + + // Clone file descriptor, this creates a native file descriptor. + target.cloneForFork(); + assertTrue(source.valid()); + assertTrue(target.valid()); + assertNotEquals(target.getInt$(), source.getInt$()); + + // Clean-up native resource we allocated in cloneForFork. Os.close() may throw + // an ErrnoException. + Os.close(target); + } + } } diff --git a/luni/src/test/java/libcore/java/io/RandomAccessFileTest.java b/luni/src/test/java/libcore/java/io/RandomAccessFileTest.java index 3811cbcd45..eab558a963 100644 --- a/luni/src/test/java/libcore/java/io/RandomAccessFileTest.java +++ b/luni/src/test/java/libcore/java/io/RandomAccessFileTest.java @@ -41,16 +41,6 @@ public final class RandomAccessFileTest extends TestCaseWithRules { file.delete(); } - public void testSeekTooLarge() throws Exception { - try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) { - try { - raf.seek(Long.MAX_VALUE); - fail(); - } catch (IOException expected) { - } - } - } - public void testSetLengthTooLarge() throws Exception { try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) { try { diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java index c440ebe1ba..395209aa42 100644 --- a/luni/src/test/java/libcore/java/lang/StringTest.java +++ b/luni/src/test/java/libcore/java/lang/StringTest.java @@ -29,7 +29,6 @@ import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; -import java.nio.charset.ModifiedUtf8; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.ArrayList; diff --git a/luni/src/test/java/libcore/java/lang/ThreadTest.java b/luni/src/test/java/libcore/java/lang/ThreadTest.java index f1d0db6501..4e6089130c 100644 --- a/luni/src/test/java/libcore/java/lang/ThreadTest.java +++ b/luni/src/test/java/libcore/java/lang/ThreadTest.java @@ -16,7 +16,13 @@ package libcore.java.lang; +import dalvik.system.InMemoryDexClassLoader; + +import java.io.InputStream; +import java.lang.reflect.Method; import java.lang.Thread.UncaughtExceptionHandler; +import java.nio.ByteBuffer; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.LockSupport; @@ -28,6 +34,7 @@ import junit.framework.TestCase; import org.mockito.InOrder; import org.mockito.Mockito; +import libcore.io.Streams; import libcore.java.lang.ref.FinalizationTester; public final class ThreadTest extends TestCase { @@ -137,6 +144,85 @@ public final class ThreadTest extends TestCase { assertSame(Thread.currentThread().getContextClassLoader(), other.getContextClassLoader()); } + public void testSetPriority_unstarted() throws Exception { + Thread thread = new Thread(); + checkSetPriority_inBounds_succeeds(thread); + checkSetPriority_outOfBounds_fails(thread); + } + + public void testSetPriority_starting() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + Thread thread = new Thread("starting thread") { + @Override public void run() { try { latch.await(); } catch (Exception e) { } } + }; + // priority set while thread was not started should carry over to started thread + int priority = thread.getPriority() + 1; + if (priority > Thread.MAX_PRIORITY) { + priority = Thread.MIN_PRIORITY; + } + thread.setPriority(priority); + thread.start(); + assertEquals(priority, thread.getPriority()); + latch.countDown(); + thread.join(); + } + + public void testSetPriority_started() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + Thread startedThread = new Thread("started thread") { + @Override public void run() { try { latch.await(); } catch (Exception e) { } } + }; + startedThread.start(); + checkSetPriority_inBounds_succeeds(startedThread); + checkSetPriority_outOfBounds_fails(startedThread); + latch.countDown(); + startedThread.join(); + } + + public void testSetPriority_joined() throws Exception { + Thread joinedThread = new Thread(); + joinedThread.start(); + joinedThread.join(); + + int originalPriority = joinedThread.getPriority(); + for (int p = Thread.MIN_PRIORITY; p <= Thread.MAX_PRIORITY; p++) { + joinedThread.setPriority(p); + // setting the priority of a not-alive Thread should not succeed + assertEquals(originalPriority, joinedThread.getPriority()); + } + checkSetPriority_outOfBounds_fails(joinedThread); + } + + private static void checkSetPriority_inBounds_succeeds(Thread thread) { + int oldPriority = thread.getPriority(); + try { + for (int priority = Thread.MIN_PRIORITY; priority <= Thread.MAX_PRIORITY; priority++) { + thread.setPriority(priority); + assertEquals(priority, thread.getPriority()); + } + } finally { + thread.setPriority(oldPriority); + } + assertEquals(oldPriority, thread.getPriority()); + } + + private static void checkSetPriority_outOfBounds_fails(Thread thread) { + checkSetPriority_outOfBounds_fails(thread, Thread.MIN_PRIORITY - 1); + checkSetPriority_outOfBounds_fails(thread, Thread.MAX_PRIORITY + 1); + checkSetPriority_outOfBounds_fails(thread, Integer.MIN_VALUE); + checkSetPriority_outOfBounds_fails(thread, Integer.MAX_VALUE); + } + + private static void checkSetPriority_outOfBounds_fails(Thread thread, int invalidPriority) { + int oldPriority = thread.getPriority(); + try { + thread.setPriority(invalidPriority); + fail(); + } catch (IllegalArgumentException expected) { + } + assertEquals(oldPriority, thread.getPriority()); // priority shouldn't have changed + } + public void testUncaughtExceptionPreHandler_calledBeforeDefaultHandler() { UncaughtExceptionHandler initialHandler = Mockito.mock(UncaughtExceptionHandler.class); UncaughtExceptionHandler defaultHandler = Mockito.mock(UncaughtExceptionHandler.class); @@ -203,6 +289,84 @@ public final class ThreadTest extends TestCase { t1.join(); } + /** + * Checks that a stacktrace reports the expected debug metadata + * (source-filename, line number) hard-coded in a class loaded from + * pre-built test resources. + */ + public void testGetStackTrace_debugInfo() throws Exception { + StackTraceElement ste = getStackTraceElement("debugInfo"); + + // Verify that this StackTraceElement appears as we expect it to + // e.g. when an exception is printed. + assertEquals("java.lang.ThreadTestHelper.debugInfo(ThreadTestHelper.java:9)", + ste.toString()); + + // Since we emit debug information for ThreadTestHelper.debugInfo, + // the Runtime will symbolicate this frame with the correct file name. + assertEquals("ThreadTestHelper.java", ste.getFileName()); + + // We explicitly specify this in the test resource. + assertEquals(9, ste.getLineNumber()); + } + + /** + * Checks that a stacktrace reports the expected dex PC in place of + * a line number when debug info is missing for a method; the method is + * declared on a class loaded from pre-built test resources. + */ + public void testGetStackTrace_noDebugInfo() throws Exception { + StackTraceElement ste = getStackTraceElement("noDebugInfo"); + + // Verify that this StackTraceElement appears as we expect it to + // e.g. when an exception is printed. + assertEquals("java.lang.ThreadTestHelper.noDebugInfo(Unknown Source:3)", ste.toString()); + + // Since we don't have any debug info for this method, the Runtime + // doesn't symbolicate this with a file name (even though the + // enclosing class may have the file name specified). + assertEquals(null, ste.getFileName()); + + // In the test resource we emit 3 nops before generating a stack + // trace; each nop advances the dex PC by 1 because a nop is a + // single code unit wide. + assertEquals(3, ste.getLineNumber()); + } + + /** + * Calls the given static method declared on ThreadTestHelper, which + * is loaded from precompiled test resources. + * + * @param methodName either {@quote "debugInfo"} or {@quote "noDebugInfo"} + * @return the StackTraceElement corresponding to said method's frame + */ + private static StackTraceElement getStackTraceElement(String methodName) throws Exception { + final String className = "java.lang.ThreadTestHelper"; + byte[] data; + try (InputStream is = + ThreadTest.class.getClassLoader().getResourceAsStream("core-tests-smali.dex")) { + data = Streams.readFullyNoClose(is); + } + ClassLoader imcl = new InMemoryDexClassLoader(ByteBuffer.wrap(data), + ThreadTest.class.getClassLoader()); + Class<?> helper = imcl.loadClass(className); + Method m = helper.getDeclaredMethod(methodName); + StackTraceElement[] stes = (StackTraceElement[]) m.invoke(null); + + // The top of the stack trace looks like: + // - VMStack.getThreadStackTrace() + // - Thread.getStackTrace() + // - ThreadTestHelper.createStackTrace() + // - ThreadTestHelper.{debugInfo,noDebugInfo} + StackTraceElement result = stes[3]; + + // Sanity check before we return + assertEquals(result.getClassName(), className); + assertEquals(result.getMethodName(), methodName); + assertFalse(result.isNativeMethod()); + return result; + } + public void testGetAllStackTracesIncludesAllGroups() throws Exception { final AtomicInteger visibleTraces = new AtomicInteger(); ThreadGroup group = new ThreadGroup("1"); diff --git a/luni/src/test/java/libcore/java/lang/ThreadTestHelper.smali b/luni/src/test/java/libcore/java/lang/ThreadTestHelper.smali new file mode 100644 index 0000000000..d55120e184 --- /dev/null +++ b/luni/src/test/java/libcore/java/lang/ThreadTestHelper.smali @@ -0,0 +1,96 @@ +# +# 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. +# + +# Generated by running the following java through dx/baksmali: +# package java.lang; +# +# public class ThreadTestHelper { +# static StackTraceElement[] createStackTrace() { +# return Thread.currentThread().getStackTrace(); +# } +# +# static public StackTraceElement[] debugInfo() { +# return createStackTrace(); +# } +# +# static public StackTraceElement[] noDebugInfo() { +# return createStackTrace(); +# } +# } +# Additionally .line / .prologue declarations were removed from noDebugInfo +# so that no debug info is generated for that method and three nops were +# introduced so that the stack trace is a little bit more interesting. +.class public Ljava/lang/ThreadTestHelper; +.super Ljava/lang/Object; +.source "ThreadTestHelper.java" + + +# direct methods +.method public constructor <init>()V + .registers 1 + + .prologue + .line 3 + invoke-direct {p0}, Ljava/lang/Object;-><init>()V + + return-void +.end method + +.method static createStackTrace()[Ljava/lang/StackTraceElement; + .registers 1 + + .prologue + .line 5 + invoke-static {}, Ljava/lang/Thread;->currentThread()Ljava/lang/Thread; + + move-result-object v0 + + invoke-virtual {v0}, Ljava/lang/Thread;->getStackTrace()[Ljava/lang/StackTraceElement; + + move-result-object v0 + + return-object v0 +.end method + +.method public static debugInfo()[Ljava/lang/StackTraceElement; + .registers 1 + + .prologue + .line 9 + invoke-static {}, Ljava/lang/ThreadTestHelper;->createStackTrace()[Ljava/lang/StackTraceElement; + + move-result-object v0 + + return-object v0 +.end method + +.method public static noDebugInfo()[Ljava/lang/StackTraceElement; + .registers 1 + + # Removed so this method doesn't have debug info + #.prologue + #.line 13 + + # Added so the stack trace looks more interesting + nop + nop + nop + invoke-static {}, Ljava/lang/ThreadTestHelper;->createStackTrace()[Ljava/lang/StackTraceElement; + + move-result-object v0 + + return-object v0 +.end method diff --git a/luni/src/test/java/libcore/java/lang/invoke/ExplicitCastArgumentsTest.java b/luni/src/test/java/libcore/java/lang/invoke/ExplicitCastArgumentsTest.java new file mode 100644 index 0000000000..abc58257af --- /dev/null +++ b/luni/src/test/java/libcore/java/lang/invoke/ExplicitCastArgumentsTest.java @@ -0,0 +1,5724 @@ +/* + * 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 + */ + +package libcore.java.lang.invoke; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.WrongMethodTypeException; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class ExplicitCastArgumentsTest { + // + // Constants for value casts. + // + private static final Boolean[] BOOLEAN_VALUES = new Boolean[]{ Boolean.TRUE, Boolean.FALSE }; + + private static final Byte[] BYTE_VALUES = new Byte[]{ + Byte.valueOf((byte) 0), Byte.valueOf((byte) 1), Byte.valueOf((byte) 2), + Byte.valueOf((byte) -1), Byte.valueOf((byte) -2), Byte.MIN_VALUE, Byte.MAX_VALUE + }; + + private static final Character[] CHARACTER_VALUES = new Character[]{ + Character.MIN_VALUE, Character.MAX_VALUE, Character.valueOf('A'), Character.valueOf('B'), + }; + + private static final Short[] SHORT_VALUES = new Short[]{ + Short.valueOf((short) 0), Short.valueOf((short) 1), Short.valueOf((short) 130), + Short.valueOf((short) -1), Short.valueOf((short) -130), Short.MIN_VALUE, Short.MAX_VALUE + }; + + private static final Integer[] INTEGER_VALUES = new Integer[]{ + Integer.valueOf(0), Integer.valueOf(1), Integer.valueOf(130), Integer.valueOf(32768), + Integer.valueOf(-1), Integer.valueOf(-130), Integer.valueOf(-32769), + Integer.MIN_VALUE, Integer.MAX_VALUE + }; + + private static final Long[] LONG_VALUES = new Long[]{ + Long.valueOf(0L), Long.valueOf(1L), Long.valueOf(130L), Long.valueOf(32768L), + Long.valueOf(0x800000000L), Long.valueOf(0x800000001L), + Long.valueOf(-1l), Long.valueOf(-130l), Long.valueOf(-32769l), Long.valueOf(-0x800000000L), + Long.valueOf(-0x800000001L), Long.MIN_VALUE, Long.MAX_VALUE + }; + + private static final Float[] FLOAT_VALUES = new Float[]{ + Float.valueOf(0.0f), Float.valueOf(0.5f), Float.valueOf(1.0f), Float.valueOf(2.0f), + Float.valueOf(3.141f), Float.valueOf(-0.5f), Float.valueOf(-1.0f), Float.valueOf(-2.0f), + Float.valueOf(-3.141f), Float.MIN_VALUE, Float.MAX_VALUE + }; + + private static final Double[] DOUBLE_VALUES = new Double[]{ + Double.valueOf(0.0), Double.valueOf(0.5), Double.valueOf(1.0), Double.valueOf(2.0), + Double.valueOf(3.141), Double.valueOf(-0.5), Double.valueOf(-1.0), Double.valueOf(-2.0), + Double.valueOf(-3.141), Double.MIN_VALUE, Double.MAX_VALUE, + }; + + // Conversions to boolean for explicitCastArgument(). + private static boolean toBooleanValue(byte v) { return (v & 1) != 0; } + private static boolean toBooleanValue(char v) { return toBooleanValue((byte) v); } + private static boolean toBooleanValue(short v) { return toBooleanValue((byte) v); } + private static boolean toBooleanValue(int v) { return toBooleanValue((byte) v); } + private static boolean toBooleanValue(long v) { return toBooleanValue((byte) v); } + private static boolean toBooleanValue(float v) { return toBooleanValue((long) v); } + private static boolean toBooleanValue(double v) { return toBooleanValue((long) v); } + + // Conversions from boolean for explicitCastArgument(). + private static byte byteFromBooleanValue(boolean v) { return v ? (byte) 1 : (byte) 0; } + private static char charFromBooleanValue(boolean v) { return v ? (char) 1 : (char) 0; } + private static short shortFromBooleanValue(boolean v) { return v ? (short) 1 : (short) 0; } + private static int intFromBooleanValue(boolean v) { return v ? 1 : 0; } + private static long longFromBooleanValue(boolean v) { return v ? 1L : 0L; } + private static float floatFromBooleanValue(boolean v) { return v ? 1.0f : 0.0f; } + private static double doubleFromBooleanValue(boolean v) { return v ? 1.0 : 0.0; } + + // Helper constructing a MethodHandle of type (identityClass, argClass) for testing + // explicit casts applied to the argument of the MethodHandle invocation. + private static MethodHandle explicitCastArgumentToIdentity(Class identityClass, + Class argClass) { + MethodHandle identity = MethodHandles.identity(identityClass); + MethodType mt = MethodType.methodType(identityClass, argClass); + return MethodHandles.explicitCastArguments(identity, mt); + } + + // Helper constructing a MethodHandle of type (argClass, identity) for testing + // explicit casts applied to the return value from the MethodHandle invocation. + private static MethodHandle explicitCastReturnValueFromIdentity(Class identityClass, + Class retClass) { + MethodHandle identity = MethodHandles.identity(identityClass); + MethodType mt = MethodType.methodType(retClass, identityClass); + return MethodHandles.explicitCastArguments(identity, mt); + } + + // Helper for constructing a typed null constant with aan explicit cast to a primitive + // type. + private static MethodHandle nullConstantExplicitCastToPrimitive(Class constantType, + Class primitiveType) { + return MethodHandles.explicitCastArguments(MethodHandles.constant(constantType, null), + MethodType.methodType(primitiveType)); + } + + // Helper returning void. + public static void voidFunction() { + } + + // Helper for constructing an explicit cast from void to type return value. + private static MethodHandle explicitCastVoidReturnValue(Class toType) throws Throwable { + MethodHandle m = + MethodHandles.publicLookup().findStatic(ExplicitCastArgumentsTest.class, + "voidFunction", + MethodType.methodType(void.class)); + return MethodHandles.explicitCastArguments(m, MethodType.methodType(toType)); + } + + // Helper classes and interfaces for reference checks. + interface ParentInterface { + public static String name = "ParentInterface"; + } + + interface ChildInterface { + public static String name = "ChildInterface"; + } + + class Parent implements ParentInterface {} + + class Child extends Parent implements ChildInterface {} + + // Explicit casting of arguments and return values for reference types. + @Test + public void explicitCastArgumentParentToChild() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Child.class, Parent.class); + try { + Child c = (Child) mh.invokeExact(new Parent()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentNullParentToChild() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Child.class, Parent.class); + Child c = (Child) mh.invokeExact((Parent) null); + assertNull(c); + } + + @Test + public void explicitCastArgumentChildToParent() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Parent.class, Child.class); + Parent p = (Parent) mh.invokeExact(new Child()); + assertTrue(p instanceof Child); + } + + @Test + public void explicitCastArgumentNullChildToParent() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Parent.class, Child.class); + Parent p = (Parent) mh.invokeExact((Child) null); + assertNull(p); + } + + @Test + public void explicitCastReturnValueNullParentToChild() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Parent.class, Child.class); + Child c = (Child) mh.invokeExact((Parent) null); + assertNull(c); + } + + @Test + public void explicitCastReturnValueParentToChild() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Parent.class, Child.class); + try { + Child c = (Child) mh.invokeExact(new Parent()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueNullChildToParent() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Child.class, Parent.class); + Parent p = (Parent) mh.invokeExact((Child) null); + assertNull(p); + } + + @Test + public void explicitCastReturnValueChildToParent() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Child.class, Parent.class); + Parent x = (Parent) mh.invokeExact(new Child()); + assertTrue(x instanceof Child); + } + + @Test + public void explicitCastArgumentOfInterfaceType_doesNotThrow() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(ParentInterface.class, Parent.class); + ParentInterface pi = (ParentInterface) mh.invokeExact(new Parent()); + assertTrue(pi instanceof ParentInterface); + pi = (ParentInterface) mh.invokeExact((Parent) null); + assertNull(pi); + + MethodHandle mh1 = explicitCastArgumentToIdentity(ParentInterface.class, Child.class); + pi = (ParentInterface) mh1.invokeExact(new Child()); + assertTrue(pi instanceof ParentInterface); + pi = (ParentInterface) mh1.invokeExact((Child) null); + assertNull(pi); + + MethodHandle mh2 = explicitCastArgumentToIdentity(ParentInterface.class, Integer.class); + pi = (ParentInterface) mh2.invokeExact(Integer.valueOf(3)); + assertFalse(pi instanceof ParentInterface); + pi = (ParentInterface) mh2.invokeExact((Integer) null); + assertNull(pi); + } + + @Test + public void explicitCastReturnValueOfInterfaceType_doesNotThrow() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Parent.class, + ParentInterface.class); + ParentInterface pi = (ParentInterface) mh.invokeExact(new Parent()); + assertTrue(pi instanceof ParentInterface); + pi = (ParentInterface) mh.invokeExact((Parent) null); + assertNull(pi); + + MethodHandle mh1 = explicitCastReturnValueFromIdentity(Child.class, + ParentInterface.class); + pi = (ParentInterface) mh1.invokeExact(new Child()); + assertTrue(pi instanceof ParentInterface); + pi = (ParentInterface) mh1.invokeExact((Child) null); + assertNull(pi); + + MethodHandle mh2 = explicitCastReturnValueFromIdentity(Integer.class, + ParentInterface.class); + pi = (ParentInterface) mh2.invokeExact(Integer.valueOf(42)); + assertFalse(pi instanceof ParentInterface); + pi = (ParentInterface) mh2.invokeExact((Integer) null); + assertNull(pi); + } + + @Test + public void originalTypeAndNewTypeEqual() throws Throwable { + MethodHandle mh = MethodHandles.identity(Integer.class); + assertEquals(mh, MethodHandles.explicitCastArguments(mh, mh.type())); + assertEquals(mh, + MethodHandles.explicitCastArguments(mh, + MethodType.methodType(Integer.class, + Integer.class))); + } + + // + // Explicit casting of arguments between the primitive types and their + // reference type counterparts. + // + @Test + public void explicitCastArgumentZToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, boolean.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(v, (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentZToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, boolean.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(byteFromBooleanValue(v), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentZToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, boolean.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(charFromBooleanValue(v), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentZToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, boolean.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(shortFromBooleanValue(v), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentZToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, boolean.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(intFromBooleanValue(v), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentZToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, boolean.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(longFromBooleanValue(v), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentZToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, boolean.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(floatFromBooleanValue(v), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentZToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, boolean.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(doubleFromBooleanValue(v), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentZToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, boolean.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(Boolean.valueOf(v), (Boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentZToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, boolean.class); + try { + Byte o = (Byte) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentZToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, boolean.class); + try { + Character o = (Character) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentZToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, boolean.class); + try { + Short o = (Short) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentZToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, boolean.class); + try { + Integer o = (Integer) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentZToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, boolean.class); + try { + Long o = (Long) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentZToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, boolean.class); + try { + Float o = (Float) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentZToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, boolean.class); + try { + Double o = (Double) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, byte.class); + for (byte v : BYTE_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, byte.class); + for (byte v : BYTE_VALUES) { + assertEquals(v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, byte.class); + for (byte v : BYTE_VALUES) { + assertEquals((char) v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, byte.class); + for (byte v : BYTE_VALUES) { + assertEquals((short) v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, byte.class); + for (byte v : BYTE_VALUES) { + assertEquals((int) v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, byte.class); + for (byte v : BYTE_VALUES) { + assertEquals((long) v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, byte.class); + for (byte v : BYTE_VALUES) { + assertEquals((float) v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentBToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, byte.class); + for (byte v : BYTE_VALUES) { + assertEquals((double) v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentBToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, byte.class); + try { + Boolean o = (Boolean) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, byte.class); + for (byte v : BYTE_VALUES) { + assertEquals(Byte.valueOf(v), (Byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, byte.class); + try { + Character o = (Character) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, byte.class); + try { + Short o = (Short) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, byte.class); + try { + Integer o = (Integer) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, byte.class); + try { + Long o = (Long) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, byte.class); + try { + Float o = (Float) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, byte.class); + try { + Double o = (Double) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, char.class); + for (char v : CHARACTER_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, char.class); + for (char v : CHARACTER_VALUES) { + assertEquals((byte) v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, char.class); + for (char v : CHARACTER_VALUES) { + assertEquals(v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, char.class); + for (char v : CHARACTER_VALUES) { + assertEquals((short) v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, char.class); + for (char v : CHARACTER_VALUES) { + assertEquals((int) v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, char.class); + for (char v : CHARACTER_VALUES) { + assertEquals((long) v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, char.class); + for (char v : CHARACTER_VALUES) { + assertEquals((float) v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentCToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, char.class); + for (char v : CHARACTER_VALUES) { + assertEquals((double) v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentCToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, char.class); + try { + Boolean o = (Boolean) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, char.class); + try { + Byte o = (Byte) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, char.class); + for (char v : CHARACTER_VALUES) { + assertEquals(Character.valueOf(v), (Character) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, char.class); + try { + Short o = (Short) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, char.class); + try { + Integer o = (Integer) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, char.class); + try { + Long o = (Long) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, char.class); + try { + Float o = (Float) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, char.class); + try { + Double o = (Double) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentSToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, short.class); + for (short v : SHORT_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentSToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, short.class); + for (short v : SHORT_VALUES) { + assertEquals((byte) v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentSToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, short.class); + for (short v : SHORT_VALUES) { + assertEquals((char) v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentSToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, short.class); + for (short v : SHORT_VALUES) { + assertEquals(v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentSToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, short.class); + for (short v : SHORT_VALUES) { + assertEquals((int) v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentSToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, short.class); + for (short v : SHORT_VALUES) { + assertEquals((long) v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentSToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, short.class); + for (short v : SHORT_VALUES) { + assertEquals((float) v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentSToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, short.class); + for (short v : SHORT_VALUES) { + assertEquals((double) v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentSToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, short.class); + try { + Boolean o = (Boolean) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentSToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, short.class); + try { + Byte o = (Byte) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentSToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, short.class); + try { + Character o = (Character) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentSToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, short.class); + for (short v : SHORT_VALUES) { + assertEquals(Short.valueOf(v), (Short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentSToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, short.class); + try { + Integer o = (Integer) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentSToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, short.class); + try { + Long o = (Long) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentSToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, short.class); + try { + Float o = (Float) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentSToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, short.class); + try { + Double o = (Double) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, int.class); + for (int v : INTEGER_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, int.class); + for (int v : INTEGER_VALUES) { + assertEquals((byte) v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, int.class); + for (int v : INTEGER_VALUES) { + assertEquals((char) v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, int.class); + for (int v : INTEGER_VALUES) { + assertEquals((short) v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, int.class); + for (int v : INTEGER_VALUES) { + assertEquals(v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, int.class); + for (int v : INTEGER_VALUES) { + assertEquals((long) v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, int.class); + for (int v : INTEGER_VALUES) { + assertEquals((float) v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentIToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, int.class); + for (int v : INTEGER_VALUES) { + assertEquals((double) v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentIToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, int.class); + try { + Boolean o = (Boolean) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, int.class); + try { + Byte o = (Byte) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, int.class); + try { + Character o = (Character) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, int.class); + try { + Short o = (Short) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, int.class); + for (int v : INTEGER_VALUES) { + assertEquals(Integer.valueOf(v), (Integer) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, int.class); + try { + Long o = (Long) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, int.class); + try { + Float o = (Float) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, int.class); + try { + Double o = (Double) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentJToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, long.class); + for (long v : LONG_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentJToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, long.class); + for (long v : LONG_VALUES) { + assertEquals((byte) v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentJToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, long.class); + for (long v : LONG_VALUES) { + assertEquals((char) v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentJToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, long.class); + for (long v : LONG_VALUES) { + assertEquals((short) v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentJToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, long.class); + for (long v : LONG_VALUES) { + assertEquals((int) v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentJToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, long.class); + for (long v : LONG_VALUES) { + assertEquals(v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentJToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, long.class); + for (long v : LONG_VALUES) { + assertEquals((float) v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentJToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, long.class); + for (long v : LONG_VALUES) { + assertEquals((double) v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentJToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, long.class); + try { + Boolean o = (Boolean) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentJToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, long.class); + try { + Byte o = (Byte) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentJToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, long.class); + try { + Character o = (Character) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentJToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, long.class); + try { + Short o = (Short) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentJToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, long.class); + try { + Integer o = (Integer) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentJToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, long.class); + for (long v : LONG_VALUES) { + assertEquals(Long.valueOf(v), (Long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentJToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, long.class); + try { + Float o = (Float) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentJToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, long.class); + try { + Double o = (Double) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, float.class); + for (float v : FLOAT_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentFToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, float.class); + for (float v : FLOAT_VALUES) { + assertEquals((byte) v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentFToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, float.class); + for (float v : FLOAT_VALUES) { + assertEquals((char) v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentFToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, float.class); + for (float v : FLOAT_VALUES) { + assertEquals((short) v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentFToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, float.class); + for (float v : FLOAT_VALUES) { + assertEquals((int) v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentFToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, float.class); + for (float v : FLOAT_VALUES) { + assertEquals((long) v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentFToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, float.class); + for (float v : FLOAT_VALUES) { + assertEquals(v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentFToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, float.class); + for (float v : FLOAT_VALUES) { + assertEquals((double) v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentFToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, float.class); + try { + Boolean o = (Boolean) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, float.class); + try { + Byte o = (Byte) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, float.class); + try { + Character o = (Character) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, float.class); + try { + Short o = (Short) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, float.class); + try { + Integer o = (Integer) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, float.class); + try { + Long o = (Long) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, float.class); + for (float v : FLOAT_VALUES) { + assertEquals(Float.valueOf(v), (Float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentFToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, float.class); + try { + Double o = (Double) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, double.class); + for (double v : DOUBLE_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentDToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, double.class); + for (double v : DOUBLE_VALUES) { + assertEquals((byte) v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentDToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, double.class); + for (double v : DOUBLE_VALUES) { + assertEquals((char) v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentDToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, double.class); + for (double v : DOUBLE_VALUES) { + assertEquals((short) v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentDToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, double.class); + for (double v : DOUBLE_VALUES) { + assertEquals((int) v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentDToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, double.class); + for (double v : DOUBLE_VALUES) { + assertEquals((long) v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentDToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, double.class); + for (double v : DOUBLE_VALUES) { + assertEquals((float) v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentDToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, double.class); + for (double v : DOUBLE_VALUES) { + assertEquals(v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentDToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, double.class); + try { + Boolean o = (Boolean) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, double.class); + try { + Byte o = (Byte) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, double.class); + try { + Character o = (Character) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, double.class); + try { + Short o = (Short) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, double.class); + try { + Integer o = (Integer) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, double.class); + try { + Long o = (Long) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, double.class); + try { + Float o = (Float) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, double.class); + for (double v : DOUBLE_VALUES) { + assertEquals(Double.valueOf(v), (Double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentBooleanToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, Boolean.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(v.booleanValue(), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBooleanToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, Boolean.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(byteFromBooleanValue(v.booleanValue()), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBooleanToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, Boolean.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(charFromBooleanValue(v.booleanValue()), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBooleanToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, Boolean.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(shortFromBooleanValue(v.booleanValue()), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBooleanToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, Boolean.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(intFromBooleanValue(v.booleanValue()), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBooleanToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, Boolean.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(longFromBooleanValue(v.booleanValue()), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBooleanToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, Boolean.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(floatFromBooleanValue(v.booleanValue()), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentBooleanToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, Boolean.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(doubleFromBooleanValue(v.booleanValue()), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentBooleanToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, Boolean.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(v, (Boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentBooleanToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, Boolean.class); + try { + Byte o = (Byte) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBooleanToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, Boolean.class); + try { + Character o = (Character) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBooleanToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, Boolean.class); + try { + Short o = (Short) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBooleanToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, Boolean.class); + try { + Integer o = (Integer) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBooleanToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, Boolean.class); + try { + Long o = (Long) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBooleanToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, Boolean.class); + try { + Float o = (Float) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentBooleanToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, Boolean.class); + try { + Double o = (Double) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentByteToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, Byte.class); + for (Byte v : BYTE_VALUES) { + assertEquals(toBooleanValue(v.byteValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentByteToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, Byte.class); + for (Byte v : BYTE_VALUES) { + assertEquals(v.byteValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentByteToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, Byte.class); + for (Byte v : BYTE_VALUES) { + assertEquals((char) v.byteValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentByteToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, Byte.class); + for (Byte v : BYTE_VALUES) { + assertEquals((short) v.byteValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentByteToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, Byte.class); + for (Byte v : BYTE_VALUES) { + assertEquals((int) v.byteValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentByteToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, Byte.class); + for (Byte v : BYTE_VALUES) { + assertEquals((long) v.byteValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentByteToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, Byte.class); + for (Byte v : BYTE_VALUES) { + assertEquals((float) v.byteValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentByteToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, Byte.class); + for (Byte v : BYTE_VALUES) { + assertEquals((double) v.byteValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentByteToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, Byte.class); + try { + Boolean o = (Boolean) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentByteToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, Byte.class); + for (Byte v : BYTE_VALUES) { + assertEquals(v, (Byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentByteToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, Byte.class); + try { + Character o = (Character) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentByteToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, Byte.class); + try { + Short o = (Short) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentByteToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, Byte.class); + try { + Integer o = (Integer) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentByteToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, Byte.class); + try { + Long o = (Long) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentByteToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, Byte.class); + try { + Float o = (Float) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentByteToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, Byte.class); + try { + Double o = (Double) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCharacterToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, Character.class); + for (Character v : CHARACTER_VALUES) { + assertEquals(toBooleanValue(v.charValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCharacterToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, Character.class); + for (Character v : CHARACTER_VALUES) { + assertEquals((byte) v.charValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCharacterToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, Character.class); + for (Character v : CHARACTER_VALUES) { + assertEquals(v.charValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCharacterToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, Character.class); + for (Character v : CHARACTER_VALUES) { + assertEquals((short) v.charValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCharacterToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, Character.class); + for (Character v : CHARACTER_VALUES) { + assertEquals((int) v.charValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCharacterToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, Character.class); + for (Character v : CHARACTER_VALUES) { + assertEquals((long) v.charValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCharacterToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, Character.class); + for (Character v : CHARACTER_VALUES) { + assertEquals((float) v.charValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentCharacterToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, Character.class); + for (Character v : CHARACTER_VALUES) { + assertEquals((double) v.charValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentCharacterToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, Character.class); + try { + Boolean o = (Boolean) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCharacterToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, Character.class); + try { + Byte o = (Byte) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCharacterToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, Character.class); + for (Character v : CHARACTER_VALUES) { + assertEquals(v, (Character) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentCharacterToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, Character.class); + try { + Short o = (Short) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCharacterToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, Character.class); + try { + Integer o = (Integer) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCharacterToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, Character.class); + try { + Long o = (Long) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCharacterToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, Character.class); + try { + Float o = (Float) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentCharacterToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, Character.class); + try { + Double o = (Double) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentShortToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, Short.class); + for (Short v : SHORT_VALUES) { + assertEquals(toBooleanValue(v.shortValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentShortToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, Short.class); + for (Short v : SHORT_VALUES) { + assertEquals((byte) v.shortValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentShortToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, Short.class); + for (Short v : SHORT_VALUES) { + assertEquals((char) v.shortValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentShortToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, Short.class); + for (Short v : SHORT_VALUES) { + assertEquals(v.shortValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentShortToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, Short.class); + for (Short v : SHORT_VALUES) { + assertEquals((int) v.shortValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentShortToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, Short.class); + for (Short v : SHORT_VALUES) { + assertEquals((long) v.shortValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentShortToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, Short.class); + for (Short v : SHORT_VALUES) { + assertEquals((float) v.shortValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentShortToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, Short.class); + for (Short v : SHORT_VALUES) { + assertEquals((double) v.shortValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentShortToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, Short.class); + try { + Boolean o = (Boolean) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentShortToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, Short.class); + try { + Byte o = (Byte) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentShortToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, Short.class); + try { + Character o = (Character) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentShortToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, Short.class); + for (Short v : SHORT_VALUES) { + assertEquals(v, (Short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentShortToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, Short.class); + try { + Integer o = (Integer) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentShortToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, Short.class); + try { + Long o = (Long) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentShortToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, Short.class); + try { + Float o = (Float) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentShortToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, Short.class); + try { + Double o = (Double) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIntegerToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, Integer.class); + for (Integer v : INTEGER_VALUES) { + assertEquals(toBooleanValue(v.intValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIntegerToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, Integer.class); + for (Integer v : INTEGER_VALUES) { + assertEquals((byte) v.intValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIntegerToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, Integer.class); + for (Integer v : INTEGER_VALUES) { + assertEquals((char) v.intValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIntegerToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, Integer.class); + for (Integer v : INTEGER_VALUES) { + assertEquals((short) v.intValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIntegerToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, Integer.class); + for (Integer v : INTEGER_VALUES) { + assertEquals(v.intValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIntegerToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, Integer.class); + for (Integer v : INTEGER_VALUES) { + assertEquals((long) v.intValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIntegerToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, Integer.class); + for (Integer v : INTEGER_VALUES) { + assertEquals((float) v.intValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentIntegerToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, Integer.class); + for (Integer v : INTEGER_VALUES) { + assertEquals((double) v.intValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentIntegerToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, Integer.class); + try { + Boolean o = (Boolean) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIntegerToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, Integer.class); + try { + Byte o = (Byte) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIntegerToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, Integer.class); + try { + Character o = (Character) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIntegerToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, Integer.class); + try { + Short o = (Short) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIntegerToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, Integer.class); + for (Integer v : INTEGER_VALUES) { + assertEquals(v, (Integer) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentIntegerToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, Integer.class); + try { + Long o = (Long) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIntegerToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, Integer.class); + try { + Float o = (Float) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentIntegerToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, Integer.class); + try { + Double o = (Double) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentLongToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, Long.class); + for (Long v : LONG_VALUES) { + assertEquals(toBooleanValue(v.longValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentLongToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, Long.class); + for (Long v : LONG_VALUES) { + assertEquals((byte) v.longValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentLongToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, Long.class); + for (Long v : LONG_VALUES) { + assertEquals((char) v.longValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentLongToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, Long.class); + for (Long v : LONG_VALUES) { + assertEquals((short) v.longValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentLongToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, Long.class); + for (Long v : LONG_VALUES) { + assertEquals((int) v.longValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentLongToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, Long.class); + for (Long v : LONG_VALUES) { + assertEquals(v.longValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentLongToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, Long.class); + for (Long v : LONG_VALUES) { + assertEquals((float) v.longValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentLongToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, Long.class); + for (Long v : LONG_VALUES) { + assertEquals((double) v.longValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentLongToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, Long.class); + try { + Boolean o = (Boolean) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentLongToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, Long.class); + try { + Byte o = (Byte) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentLongToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, Long.class); + try { + Character o = (Character) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentLongToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, Long.class); + try { + Short o = (Short) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentLongToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, Long.class); + try { + Integer o = (Integer) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentLongToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, Long.class); + for (Long v : LONG_VALUES) { + assertEquals(v, (Long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentLongToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, Long.class); + try { + Float o = (Float) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentLongToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, Long.class); + try { + Double o = (Double) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFloatToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, Float.class); + for (Float v : FLOAT_VALUES) { + assertEquals(toBooleanValue(v.floatValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentFloatToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, Float.class); + for (Float v : FLOAT_VALUES) { + assertEquals((byte) v.floatValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentFloatToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, Float.class); + for (Float v : FLOAT_VALUES) { + assertEquals((char) v.floatValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentFloatToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, Float.class); + for (Float v : FLOAT_VALUES) { + assertEquals((short) v.floatValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentFloatToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, Float.class); + for (Float v : FLOAT_VALUES) { + assertEquals((int) v.floatValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentFloatToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, Float.class); + for (Float v : FLOAT_VALUES) { + assertEquals((long) v.floatValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentFloatToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, Float.class); + for (Float v : FLOAT_VALUES) { + assertEquals(v.floatValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentFloatToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, Float.class); + for (Float v : FLOAT_VALUES) { + assertEquals((double) v.floatValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentFloatToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, Float.class); + try { + Boolean o = (Boolean) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFloatToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, Float.class); + try { + Byte o = (Byte) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFloatToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, Float.class); + try { + Character o = (Character) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFloatToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, Float.class); + try { + Short o = (Short) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFloatToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, Float.class); + try { + Integer o = (Integer) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFloatToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, Float.class); + try { + Long o = (Long) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentFloatToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, Float.class); + for (Float v : FLOAT_VALUES) { + assertEquals(v, (Float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentFloatToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, Float.class); + try { + Double o = (Double) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDoubleToZ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(boolean.class, Double.class); + for (Double v : DOUBLE_VALUES) { + assertEquals(toBooleanValue(v.doubleValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentDoubleToB() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(byte.class, Double.class); + for (Double v : DOUBLE_VALUES) { + assertEquals((byte) v.doubleValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentDoubleToC() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(char.class, Double.class); + for (Double v : DOUBLE_VALUES) { + assertEquals((char) v.doubleValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentDoubleToS() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(short.class, Double.class); + for (Double v : DOUBLE_VALUES) { + assertEquals((short) v.doubleValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentDoubleToI() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(int.class, Double.class); + for (Double v : DOUBLE_VALUES) { + assertEquals((int) v.doubleValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentDoubleToJ() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(long.class, Double.class); + for (Double v : DOUBLE_VALUES) { + assertEquals((long) v.doubleValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastArgumentDoubleToF() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(float.class, Double.class); + for (Double v : DOUBLE_VALUES) { + assertEquals((float) v.doubleValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentDoubleToD() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(double.class, Double.class); + for (Double v : DOUBLE_VALUES) { + assertEquals(v.doubleValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastArgumentDoubleToBoolean() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Boolean.class, Double.class); + try { + Boolean o = (Boolean) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDoubleToByte() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Byte.class, Double.class); + try { + Byte o = (Byte) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDoubleToCharacter() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Character.class, Double.class); + try { + Character o = (Character) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDoubleToShort() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Short.class, Double.class); + try { + Short o = (Short) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDoubleToInteger() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Integer.class, Double.class); + try { + Integer o = (Integer) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDoubleToLong() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Long.class, Double.class); + try { + Long o = (Long) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDoubleToFloat() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Float.class, Double.class); + try { + Float o = (Float) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastArgumentDoubleToDouble() throws Throwable { + MethodHandle mh = explicitCastArgumentToIdentity(Double.class, Double.class); + for (Double v : DOUBLE_VALUES) { + assertEquals(v, (Double) mh.invokeExact(v), 0.0); + } + } + + // + // Explicit casting of return values between the primitive types and their + // reference type counterparts. + // + @Test + public void explicitCastReturnValueZToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, boolean.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(v, (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, boolean.class); + for (byte v : BYTE_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, boolean.class); + for (char v : CHARACTER_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueSToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, boolean.class); + for (short v : SHORT_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, boolean.class); + for (int v : INTEGER_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueJToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, boolean.class); + for (long v : LONG_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, boolean.class); + for (float v : FLOAT_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueDToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, boolean.class); + for (double v : DOUBLE_VALUES) { + assertEquals(toBooleanValue(v), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBooleanToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, boolean.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(v.booleanValue(), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueByteToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, boolean.class); + for (Byte v : BYTE_VALUES) { + assertEquals(toBooleanValue(v.byteValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCharacterToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, boolean.class); + for (Character v : CHARACTER_VALUES) { + assertEquals(toBooleanValue(v.charValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueShortToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, boolean.class); + for (Short v : SHORT_VALUES) { + assertEquals(toBooleanValue(v.shortValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIntegerToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, boolean.class); + for (Integer v : INTEGER_VALUES) { + assertEquals(toBooleanValue(v.intValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueLongToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, boolean.class); + for (Long v : LONG_VALUES) { + assertEquals(toBooleanValue(v.longValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFloatToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, boolean.class); + for (Float v : FLOAT_VALUES) { + assertEquals(toBooleanValue(v.floatValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueDoubleToZ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, boolean.class); + for (Double v : DOUBLE_VALUES) { + assertEquals(toBooleanValue(v.doubleValue()), (boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueZToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, byte.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(byteFromBooleanValue(v), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, byte.class); + for (byte v : BYTE_VALUES) { + assertEquals(v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, byte.class); + for (char v : CHARACTER_VALUES) { + assertEquals((byte) v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueSToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, byte.class); + for (short v : SHORT_VALUES) { + assertEquals((byte) v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, byte.class); + for (int v : INTEGER_VALUES) { + assertEquals((byte) v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueJToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, byte.class); + for (long v : LONG_VALUES) { + assertEquals((byte) v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, byte.class); + for (float v : FLOAT_VALUES) { + assertEquals((byte) v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueDToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, byte.class); + for (double v : DOUBLE_VALUES) { + assertEquals((byte) v, (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBooleanToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, byte.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(byteFromBooleanValue(v.booleanValue()), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueByteToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, byte.class); + for (Byte v : BYTE_VALUES) { + assertEquals(v.byteValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCharacterToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, byte.class); + for (Character v : CHARACTER_VALUES) { + assertEquals((byte) v.charValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueShortToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, byte.class); + for (Short v : SHORT_VALUES) { + assertEquals((byte) v.shortValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIntegerToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, byte.class); + for (Integer v : INTEGER_VALUES) { + assertEquals((byte) v.intValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueLongToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, byte.class); + for (Long v : LONG_VALUES) { + assertEquals((byte) v.longValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFloatToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, byte.class); + for (Float v : FLOAT_VALUES) { + assertEquals((byte) v.floatValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueDoubleToB() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, byte.class); + for (Double v : DOUBLE_VALUES) { + assertEquals((byte) v.doubleValue(), (byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueZToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, char.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(charFromBooleanValue(v), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, char.class); + for (byte v : BYTE_VALUES) { + assertEquals((char) v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, char.class); + for (char v : CHARACTER_VALUES) { + assertEquals(v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueSToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, char.class); + for (short v : SHORT_VALUES) { + assertEquals((char) v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, char.class); + for (int v : INTEGER_VALUES) { + assertEquals((char) v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueJToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, char.class); + for (long v : LONG_VALUES) { + assertEquals((char) v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, char.class); + for (float v : FLOAT_VALUES) { + assertEquals((char) v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueDToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, char.class); + for (double v : DOUBLE_VALUES) { + assertEquals((char) v, (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBooleanToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, char.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(charFromBooleanValue(v.booleanValue()), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueByteToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, char.class); + for (Byte v : BYTE_VALUES) { + assertEquals((char) v.byteValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCharacterToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, char.class); + for (Character v : CHARACTER_VALUES) { + assertEquals(v.charValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueShortToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, char.class); + for (Short v : SHORT_VALUES) { + assertEquals((char) v.shortValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIntegerToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, char.class); + for (Integer v : INTEGER_VALUES) { + assertEquals((char) v.intValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueLongToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, char.class); + for (Long v : LONG_VALUES) { + assertEquals((char) v.longValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFloatToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, char.class); + for (Float v : FLOAT_VALUES) { + assertEquals((char) v.floatValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueDoubleToC() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, char.class); + for (Double v : DOUBLE_VALUES) { + assertEquals((char) v.doubleValue(), (char) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueZToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, short.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(shortFromBooleanValue(v), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, short.class); + for (byte v : BYTE_VALUES) { + assertEquals((short) v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, short.class); + for (char v : CHARACTER_VALUES) { + assertEquals((short) v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueSToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, short.class); + for (short v : SHORT_VALUES) { + assertEquals(v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, short.class); + for (int v : INTEGER_VALUES) { + assertEquals((short) v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueJToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, short.class); + for (long v : LONG_VALUES) { + assertEquals((short) v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, short.class); + for (float v : FLOAT_VALUES) { + assertEquals((short) v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueDToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, short.class); + for (double v : DOUBLE_VALUES) { + assertEquals((short) v, (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBooleanToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, short.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(shortFromBooleanValue(v.booleanValue()), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueByteToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, short.class); + for (Byte v : BYTE_VALUES) { + assertEquals((short) v.byteValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCharacterToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, short.class); + for (Character v : CHARACTER_VALUES) { + assertEquals((short) v.charValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueShortToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, short.class); + for (Short v : SHORT_VALUES) { + assertEquals(v.shortValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIntegerToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, short.class); + for (Integer v : INTEGER_VALUES) { + assertEquals((short) v.intValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueLongToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, short.class); + for (Long v : LONG_VALUES) { + assertEquals((short) v.longValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFloatToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, short.class); + for (Float v : FLOAT_VALUES) { + assertEquals((short) v.floatValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueDoubleToS() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, short.class); + for (Double v : DOUBLE_VALUES) { + assertEquals((short) v.doubleValue(), (short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueZToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, int.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(intFromBooleanValue(v), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, int.class); + for (byte v : BYTE_VALUES) { + assertEquals((int) v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, int.class); + for (char v : CHARACTER_VALUES) { + assertEquals((int) v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueSToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, int.class); + for (short v : SHORT_VALUES) { + assertEquals((int) v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, int.class); + for (int v : INTEGER_VALUES) { + assertEquals(v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueJToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, int.class); + for (long v : LONG_VALUES) { + assertEquals((int) v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, int.class); + for (float v : FLOAT_VALUES) { + assertEquals((int) v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueDToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, int.class); + for (double v : DOUBLE_VALUES) { + assertEquals((int) v, (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBooleanToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, int.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(intFromBooleanValue(v.booleanValue()), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueByteToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, int.class); + for (Byte v : BYTE_VALUES) { + assertEquals((int) v.byteValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCharacterToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, int.class); + for (Character v : CHARACTER_VALUES) { + assertEquals((int) v.charValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueShortToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, int.class); + for (Short v : SHORT_VALUES) { + assertEquals((int) v.shortValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIntegerToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, int.class); + for (Integer v : INTEGER_VALUES) { + assertEquals(v.intValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueLongToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, int.class); + for (Long v : LONG_VALUES) { + assertEquals((int) v.longValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFloatToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, int.class); + for (Float v : FLOAT_VALUES) { + assertEquals((int) v.floatValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueDoubleToI() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, int.class); + for (Double v : DOUBLE_VALUES) { + assertEquals((int) v.doubleValue(), (int) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueZToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, long.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(longFromBooleanValue(v), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, long.class); + for (byte v : BYTE_VALUES) { + assertEquals((long) v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, long.class); + for (char v : CHARACTER_VALUES) { + assertEquals((long) v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueSToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, long.class); + for (short v : SHORT_VALUES) { + assertEquals((long) v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, long.class); + for (int v : INTEGER_VALUES) { + assertEquals((long) v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueJToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, long.class); + for (long v : LONG_VALUES) { + assertEquals(v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, long.class); + for (float v : FLOAT_VALUES) { + assertEquals((long) v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueDToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, long.class); + for (double v : DOUBLE_VALUES) { + assertEquals((long) v, (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBooleanToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, long.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(longFromBooleanValue(v.booleanValue()), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueByteToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, long.class); + for (Byte v : BYTE_VALUES) { + assertEquals((long) v.byteValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCharacterToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, long.class); + for (Character v : CHARACTER_VALUES) { + assertEquals((long) v.charValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueShortToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, long.class); + for (Short v : SHORT_VALUES) { + assertEquals((long) v.shortValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIntegerToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, long.class); + for (Integer v : INTEGER_VALUES) { + assertEquals((long) v.intValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueLongToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, long.class); + for (Long v : LONG_VALUES) { + assertEquals(v.longValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFloatToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, long.class); + for (Float v : FLOAT_VALUES) { + assertEquals((long) v.floatValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueDoubleToJ() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, long.class); + for (Double v : DOUBLE_VALUES) { + assertEquals((long) v.doubleValue(), (long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueZToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, float.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(floatFromBooleanValue(v), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueBToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, float.class); + for (byte v : BYTE_VALUES) { + assertEquals((float) v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueCToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, float.class); + for (char v : CHARACTER_VALUES) { + assertEquals((float) v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueSToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, float.class); + for (short v : SHORT_VALUES) { + assertEquals((float) v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueIToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, float.class); + for (int v : INTEGER_VALUES) { + assertEquals((float) v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueJToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, float.class); + for (long v : LONG_VALUES) { + assertEquals((float) v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueFToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, float.class); + for (float v : FLOAT_VALUES) { + assertEquals(v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueDToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, float.class); + for (double v : DOUBLE_VALUES) { + assertEquals((float) v, (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueBooleanToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, float.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(floatFromBooleanValue(v.booleanValue()), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueByteToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, float.class); + for (Byte v : BYTE_VALUES) { + assertEquals((float) v.byteValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueCharacterToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, float.class); + for (Character v : CHARACTER_VALUES) { + assertEquals((float) v.charValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueShortToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, float.class); + for (Short v : SHORT_VALUES) { + assertEquals((float) v.shortValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueIntegerToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, float.class); + for (Integer v : INTEGER_VALUES) { + assertEquals((float) v.intValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueLongToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, float.class); + for (Long v : LONG_VALUES) { + assertEquals((float) v.longValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueFloatToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, float.class); + for (Float v : FLOAT_VALUES) { + assertEquals(v.floatValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueDoubleToF() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, float.class); + for (Double v : DOUBLE_VALUES) { + assertEquals((float) v.doubleValue(), (float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueZToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, double.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(doubleFromBooleanValue(v), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueBToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, double.class); + for (byte v : BYTE_VALUES) { + assertEquals((double) v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueCToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, double.class); + for (char v : CHARACTER_VALUES) { + assertEquals((double) v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueSToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, double.class); + for (short v : SHORT_VALUES) { + assertEquals((double) v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueIToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, double.class); + for (int v : INTEGER_VALUES) { + assertEquals((double) v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueJToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, double.class); + for (long v : LONG_VALUES) { + assertEquals((double) v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueFToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, double.class); + for (float v : FLOAT_VALUES) { + assertEquals((double) v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueDToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, double.class); + for (double v : DOUBLE_VALUES) { + assertEquals(v, (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueBooleanToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, double.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(doubleFromBooleanValue(v.booleanValue()), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueByteToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, double.class); + for (Byte v : BYTE_VALUES) { + assertEquals((double) v.byteValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueCharacterToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, double.class); + for (Character v : CHARACTER_VALUES) { + assertEquals((double) v.charValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueShortToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, double.class); + for (Short v : SHORT_VALUES) { + assertEquals((double) v.shortValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueIntegerToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, double.class); + for (Integer v : INTEGER_VALUES) { + assertEquals((double) v.intValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueLongToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, double.class); + for (Long v : LONG_VALUES) { + assertEquals((double) v.longValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueFloatToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, double.class); + for (Float v : FLOAT_VALUES) { + assertEquals((double) v.floatValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueDoubleToD() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, double.class); + for (Double v : DOUBLE_VALUES) { + assertEquals(v.doubleValue(), (double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueZToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, Boolean.class); + for (boolean v : BOOLEAN_VALUES) { + assertEquals(Boolean.valueOf(v), (Boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueBToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueSToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueJToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBooleanToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, Boolean.class); + for (Boolean v : BOOLEAN_VALUES) { + assertEquals(v, (Boolean) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueByteToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCharacterToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueShortToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIntegerToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueLongToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFloatToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDoubleToBoolean() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, Boolean.class); + try { + Boolean o = (Boolean) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueZToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, Byte.class); + for (byte v : BYTE_VALUES) { + assertEquals(Byte.valueOf(v), (Byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueSToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueJToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBooleanToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueByteToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, Byte.class); + for (Byte v : BYTE_VALUES) { + assertEquals(v, (Byte) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueCharacterToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueShortToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIntegerToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueLongToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFloatToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDoubleToByte() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, Byte.class); + try { + Byte o = (Byte) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueZToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, Character.class); + try { + Character o = (Character) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, Character.class); + try { + Character o = (Character) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, Character.class); + for (char v : CHARACTER_VALUES) { + assertEquals(Character.valueOf(v), (Character) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueSToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, Character.class); + try { + Character o = (Character) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, Character.class); + try { + Character o = (Character) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueJToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, Character.class); + try { + Character o = (Character) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, Character.class); + try { + Character o = (Character) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, Character.class); + try { + Character o = (Character) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBooleanToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, Character.class); + try { + Character o = (Character) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueByteToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, Character.class); + try { + Character o = (Character) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCharacterToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, Character.class); + for (Character v : CHARACTER_VALUES) { + assertEquals(v, (Character) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueShortToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, Character.class); + try { + Character o = (Character) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIntegerToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, Character.class); + try { + Character o = (Character) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueLongToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, Character.class); + try { + Character o = (Character) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFloatToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, Character.class); + try { + Character o = (Character) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDoubleToCharacter() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, Character.class); + try { + Character o = (Character) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueZToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, Short.class); + try { + Short o = (Short) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, Short.class); + try { + Short o = (Short) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, Short.class); + try { + Short o = (Short) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueSToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, Short.class); + for (short v : SHORT_VALUES) { + assertEquals(Short.valueOf(v), (Short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, Short.class); + try { + Short o = (Short) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueJToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, Short.class); + try { + Short o = (Short) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, Short.class); + try { + Short o = (Short) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, Short.class); + try { + Short o = (Short) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBooleanToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, Short.class); + try { + Short o = (Short) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueByteToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, Short.class); + try { + Short o = (Short) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCharacterToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, Short.class); + try { + Short o = (Short) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueShortToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, Short.class); + for (Short v : SHORT_VALUES) { + assertEquals(v, (Short) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueIntegerToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, Short.class); + try { + Short o = (Short) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueLongToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, Short.class); + try { + Short o = (Short) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFloatToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, Short.class); + try { + Short o = (Short) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDoubleToShort() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, Short.class); + try { + Short o = (Short) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueZToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueSToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, Integer.class); + for (int v : INTEGER_VALUES) { + assertEquals(Integer.valueOf(v), (Integer) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueJToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBooleanToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueByteToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCharacterToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueShortToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIntegerToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, Integer.class); + for (Integer v : INTEGER_VALUES) { + assertEquals(v, (Integer) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueLongToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFloatToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDoubleToInteger() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, Integer.class); + try { + Integer o = (Integer) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueZToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, Long.class); + try { + Long o = (Long) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, Long.class); + try { + Long o = (Long) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, Long.class); + try { + Long o = (Long) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueSToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, Long.class); + try { + Long o = (Long) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, Long.class); + try { + Long o = (Long) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueJToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, Long.class); + for (long v : LONG_VALUES) { + assertEquals(Long.valueOf(v), (Long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, Long.class); + try { + Long o = (Long) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, Long.class); + try { + Long o = (Long) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBooleanToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, Long.class); + try { + Long o = (Long) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueByteToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, Long.class); + try { + Long o = (Long) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCharacterToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, Long.class); + try { + Long o = (Long) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueShortToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, Long.class); + try { + Long o = (Long) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIntegerToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, Long.class); + try { + Long o = (Long) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueLongToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, Long.class); + for (Long v : LONG_VALUES) { + assertEquals(v, (Long) mh.invokeExact(v)); + } + } + + @Test + public void explicitCastReturnValueFloatToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, Long.class); + try { + Long o = (Long) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDoubleToLong() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, Long.class); + try { + Long o = (Long) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueZToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, Float.class); + try { + Float o = (Float) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, Float.class); + try { + Float o = (Float) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, Float.class); + try { + Float o = (Float) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueSToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, Float.class); + try { + Float o = (Float) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, Float.class); + try { + Float o = (Float) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueJToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, Float.class); + try { + Float o = (Float) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, Float.class); + for (float v : FLOAT_VALUES) { + assertEquals(Float.valueOf(v), (Float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueDToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, Float.class); + try { + Float o = (Float) mh.invokeExact(DOUBLE_VALUES[0].doubleValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBooleanToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, Float.class); + try { + Float o = (Float) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueByteToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, Float.class); + try { + Float o = (Float) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCharacterToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, Float.class); + try { + Float o = (Float) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueShortToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, Float.class); + try { + Float o = (Float) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIntegerToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, Float.class); + try { + Float o = (Float) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueLongToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, Float.class); + try { + Float o = (Float) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFloatToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, Float.class); + for (Float v : FLOAT_VALUES) { + assertEquals(v, (Float) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueDoubleToFloat() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, Float.class); + try { + Float o = (Float) mh.invokeExact(DOUBLE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueZToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(boolean.class, Double.class); + try { + Double o = (Double) mh.invokeExact(BOOLEAN_VALUES[0].booleanValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueBToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(byte.class, Double.class); + try { + Double o = (Double) mh.invokeExact(BYTE_VALUES[0].byteValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(char.class, Double.class); + try { + Double o = (Double) mh.invokeExact(CHARACTER_VALUES[0].charValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueSToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(short.class, Double.class); + try { + Double o = (Double) mh.invokeExact(SHORT_VALUES[0].shortValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(int.class, Double.class); + try { + Double o = (Double) mh.invokeExact(INTEGER_VALUES[0].intValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueJToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(long.class, Double.class); + try { + Double o = (Double) mh.invokeExact(LONG_VALUES[0].longValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(float.class, Double.class); + try { + Double o = (Double) mh.invokeExact(FLOAT_VALUES[0].floatValue()); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(double.class, Double.class); + for (double v : DOUBLE_VALUES) { + assertEquals(Double.valueOf(v), (Double) mh.invokeExact(v), 0.0); + } + } + + @Test + public void explicitCastReturnValueBooleanToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Boolean.class, Double.class); + try { + Double o = (Double) mh.invokeExact(BOOLEAN_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueByteToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Byte.class, Double.class); + try { + Double o = (Double) mh.invokeExact(BYTE_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueCharacterToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Character.class, Double.class); + try { + Double o = (Double) mh.invokeExact(CHARACTER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueShortToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Short.class, Double.class); + try { + Double o = (Double) mh.invokeExact(SHORT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueIntegerToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Integer.class, Double.class); + try { + Double o = (Double) mh.invokeExact(INTEGER_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueLongToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Long.class, Double.class); + try { + Double o = (Double) mh.invokeExact(LONG_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueFloatToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Float.class, Double.class); + try { + Double o = (Double) mh.invokeExact(FLOAT_VALUES[0]); + fail("Expected CCE"); + } catch (ClassCastException expected) {} + } + + @Test + public void explicitCastReturnValueDoubleToDouble() throws Throwable { + MethodHandle mh = explicitCastReturnValueFromIdentity(Double.class, Double.class); + for (Double v : DOUBLE_VALUES) { + assertEquals(v, (Double) mh.invokeExact(v), 0.0); + } + } + + // + // Explicit casting of null valued arguments to primitive type values + // (zero/false). + // + @Test + public void nullBooleanArgumentToZ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(boolean.class, Boolean.class); + assertEquals(false, (boolean) m.invokeExact((Boolean) null)); + } + + @Test + public void nullBooleanArgumentToB() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(byte.class, Boolean.class); + assertEquals((byte) 0, (byte) m.invokeExact((Boolean) null)); + } + + @Test + public void nullBooleanArgumentToC() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(char.class, Boolean.class); + assertEquals((char) 0, (char) m.invokeExact((Boolean) null)); + } + + @Test + public void nullBooleanArgumentToS() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(short.class, Boolean.class); + assertEquals((short) 0, (short) m.invokeExact((Boolean) null)); + } + + @Test + public void nullBooleanArgumentToI() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(int.class, Boolean.class); + assertEquals((int) 0, (int) m.invokeExact((Boolean) null)); + } + + @Test + public void nullBooleanArgumentToJ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(long.class, Boolean.class); + assertEquals((long) 0, (long) m.invokeExact((Boolean) null)); + } + + @Test + public void nullBooleanArgumentToF() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(float.class, Boolean.class); + assertEquals((float) 0, (float) m.invokeExact((Boolean) null), 0.0); + } + + @Test + public void nullBooleanArgumentToD() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(double.class, Boolean.class); + assertEquals((double) 0, (double) m.invokeExact((Boolean) null), 0.0); + } + + @Test + public void nullByteArgumentToZ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(boolean.class, Byte.class); + assertEquals(false, (boolean) m.invokeExact((Byte) null)); + } + + @Test + public void nullByteArgumentToB() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(byte.class, Byte.class); + assertEquals((byte) 0, (byte) m.invokeExact((Byte) null)); + } + + @Test + public void nullByteArgumentToC() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(char.class, Byte.class); + assertEquals((char) 0, (char) m.invokeExact((Byte) null)); + } + + @Test + public void nullByteArgumentToS() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(short.class, Byte.class); + assertEquals((short) 0, (short) m.invokeExact((Byte) null)); + } + + @Test + public void nullByteArgumentToI() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(int.class, Byte.class); + assertEquals((int) 0, (int) m.invokeExact((Byte) null)); + } + + @Test + public void nullByteArgumentToJ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(long.class, Byte.class); + assertEquals((long) 0, (long) m.invokeExact((Byte) null)); + } + + @Test + public void nullByteArgumentToF() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(float.class, Byte.class); + assertEquals((float) 0, (float) m.invokeExact((Byte) null), 0.0); + } + + @Test + public void nullByteArgumentToD() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(double.class, Byte.class); + assertEquals((double) 0, (double) m.invokeExact((Byte) null), 0.0); + } + + @Test + public void nullCharacterArgumentToZ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(boolean.class, Character.class); + assertEquals(false, (boolean) m.invokeExact((Character) null)); + } + + @Test + public void nullCharacterArgumentToB() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(byte.class, Character.class); + assertEquals((byte) 0, (byte) m.invokeExact((Character) null)); + } + + @Test + public void nullCharacterArgumentToC() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(char.class, Character.class); + assertEquals((char) 0, (char) m.invokeExact((Character) null)); + } + + @Test + public void nullCharacterArgumentToS() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(short.class, Character.class); + assertEquals((short) 0, (short) m.invokeExact((Character) null)); + } + + @Test + public void nullCharacterArgumentToI() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(int.class, Character.class); + assertEquals((int) 0, (int) m.invokeExact((Character) null)); + } + + @Test + public void nullCharacterArgumentToJ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(long.class, Character.class); + assertEquals((long) 0, (long) m.invokeExact((Character) null)); + } + + @Test + public void nullCharacterArgumentToF() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(float.class, Character.class); + assertEquals((float) 0, (float) m.invokeExact((Character) null), 0.0); + } + + @Test + public void nullCharacterArgumentToD() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(double.class, Character.class); + assertEquals((double) 0, (double) m.invokeExact((Character) null), 0.0); + } + + @Test + public void nullShortArgumentToZ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(boolean.class, Short.class); + assertEquals(false, (boolean) m.invokeExact((Short) null)); + } + + @Test + public void nullShortArgumentToB() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(byte.class, Short.class); + assertEquals((byte) 0, (byte) m.invokeExact((Short) null)); + } + + @Test + public void nullShortArgumentToC() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(char.class, Short.class); + assertEquals((char) 0, (char) m.invokeExact((Short) null)); + } + + @Test + public void nullShortArgumentToS() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(short.class, Short.class); + assertEquals((short) 0, (short) m.invokeExact((Short) null)); + } + + @Test + public void nullShortArgumentToI() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(int.class, Short.class); + assertEquals((int) 0, (int) m.invokeExact((Short) null)); + } + + @Test + public void nullShortArgumentToJ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(long.class, Short.class); + assertEquals((long) 0, (long) m.invokeExact((Short) null)); + } + + @Test + public void nullShortArgumentToF() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(float.class, Short.class); + assertEquals((float) 0, (float) m.invokeExact((Short) null), 0.0); + } + + @Test + public void nullShortArgumentToD() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(double.class, Short.class); + assertEquals((double) 0, (double) m.invokeExact((Short) null), 0.0); + } + + @Test + public void nullIntegerArgumentToZ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(boolean.class, Integer.class); + assertEquals(false, (boolean) m.invokeExact((Integer) null)); + } + + @Test + public void nullIntegerArgumentToB() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(byte.class, Integer.class); + assertEquals((byte) 0, (byte) m.invokeExact((Integer) null)); + } + + @Test + public void nullIntegerArgumentToC() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(char.class, Integer.class); + assertEquals((char) 0, (char) m.invokeExact((Integer) null)); + } + + @Test + public void nullIntegerArgumentToS() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(short.class, Integer.class); + assertEquals((short) 0, (short) m.invokeExact((Integer) null)); + } + + @Test + public void nullIntegerArgumentToI() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(int.class, Integer.class); + assertEquals((int) 0, (int) m.invokeExact((Integer) null)); + } + + @Test + public void nullIntegerArgumentToJ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(long.class, Integer.class); + assertEquals((long) 0, (long) m.invokeExact((Integer) null)); + } + + @Test + public void nullIntegerArgumentToF() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(float.class, Integer.class); + assertEquals((float) 0, (float) m.invokeExact((Integer) null), 0.0); + } + + @Test + public void nullIntegerArgumentToD() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(double.class, Integer.class); + assertEquals((double) 0, (double) m.invokeExact((Integer) null), 0.0); + } + + @Test + public void nullLongArgumentToZ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(boolean.class, Long.class); + assertEquals(false, (boolean) m.invokeExact((Long) null)); + } + + @Test + public void nullLongArgumentToB() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(byte.class, Long.class); + assertEquals((byte) 0, (byte) m.invokeExact((Long) null)); + } + + @Test + public void nullLongArgumentToC() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(char.class, Long.class); + assertEquals((char) 0, (char) m.invokeExact((Long) null)); + } + + @Test + public void nullLongArgumentToS() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(short.class, Long.class); + assertEquals((short) 0, (short) m.invokeExact((Long) null)); + } + + @Test + public void nullLongArgumentToI() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(int.class, Long.class); + assertEquals((int) 0, (int) m.invokeExact((Long) null)); + } + + @Test + public void nullLongArgumentToJ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(long.class, Long.class); + assertEquals((long) 0, (long) m.invokeExact((Long) null)); + } + + @Test + public void nullLongArgumentToF() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(float.class, Long.class); + assertEquals((float) 0, (float) m.invokeExact((Long) null), 0.0); + } + + @Test + public void nullLongArgumentToD() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(double.class, Long.class); + assertEquals((double) 0, (double) m.invokeExact((Long) null), 0.0); + } + + @Test + public void nullFloatArgumentToZ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(boolean.class, Float.class); + assertEquals(false, (boolean) m.invokeExact((Float) null)); + } + + @Test + public void nullFloatArgumentToB() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(byte.class, Float.class); + assertEquals((byte) 0, (byte) m.invokeExact((Float) null)); + } + + @Test + public void nullFloatArgumentToC() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(char.class, Float.class); + assertEquals((char) 0, (char) m.invokeExact((Float) null)); + } + + @Test + public void nullFloatArgumentToS() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(short.class, Float.class); + assertEquals((short) 0, (short) m.invokeExact((Float) null)); + } + + @Test + public void nullFloatArgumentToI() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(int.class, Float.class); + assertEquals((int) 0, (int) m.invokeExact((Float) null)); + } + + @Test + public void nullFloatArgumentToJ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(long.class, Float.class); + assertEquals((long) 0, (long) m.invokeExact((Float) null)); + } + + @Test + public void nullFloatArgumentToF() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(float.class, Float.class); + assertEquals((float) 0, (float) m.invokeExact((Float) null), 0.0); + } + + @Test + public void nullFloatArgumentToD() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(double.class, Float.class); + assertEquals((double) 0, (double) m.invokeExact((Float) null), 0.0); + } + + @Test + public void nullDoubleArgumentToZ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(boolean.class, Double.class); + assertEquals(false, (boolean) m.invokeExact((Double) null)); + } + + @Test + public void nullDoubleArgumentToB() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(byte.class, Double.class); + assertEquals((byte) 0, (byte) m.invokeExact((Double) null)); + } + + @Test + public void nullDoubleArgumentToC() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(char.class, Double.class); + assertEquals((char) 0, (char) m.invokeExact((Double) null)); + } + + @Test + public void nullDoubleArgumentToS() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(short.class, Double.class); + assertEquals((short) 0, (short) m.invokeExact((Double) null)); + } + + @Test + public void nullDoubleArgumentToI() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(int.class, Double.class); + assertEquals((int) 0, (int) m.invokeExact((Double) null)); + } + + @Test + public void nullDoubleArgumentToJ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(long.class, Double.class); + assertEquals((long) 0, (long) m.invokeExact((Double) null)); + } + + @Test + public void nullDoubleArgumentToF() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(float.class, Double.class); + assertEquals((float) 0, (float) m.invokeExact((Double) null), 0.0); + } + + @Test + public void nullDoubleArgumentToD() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(double.class, Double.class); + assertEquals((double) 0, (double) m.invokeExact((Double) null), 0.0); + } + + @Test + public void nullObjectArgumentToZ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(boolean.class, Object.class); + assertEquals(false, (boolean) m.invokeExact((Object) null)); + } + + @Test + public void nullObjectArgumentToB() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(byte.class, Object.class); + assertEquals((byte) 0, (byte) m.invokeExact((Object) null)); + } + + @Test + public void nullObjectArgumentToC() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(char.class, Object.class); + assertEquals((char) 0, (char) m.invokeExact((Object) null)); + } + + @Test + public void nullObjectArgumentToS() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(short.class, Object.class); + assertEquals((short) 0, (short) m.invokeExact((Object) null)); + } + + @Test + public void nullObjectArgumentToI() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(int.class, Object.class); + assertEquals((int) 0, (int) m.invokeExact((Object) null)); + } + + @Test + public void nullObjectArgumentToJ() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(long.class, Object.class); + assertEquals((long) 0, (long) m.invokeExact((Object) null)); + } + + @Test + public void nullObjectArgumentToF() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(float.class, Object.class); + assertEquals((float) 0, (float) m.invokeExact((Object) null), 0.0); + } + + @Test + public void nullObjectArgumentToD() throws Throwable { + MethodHandle m = explicitCastArgumentToIdentity(double.class, Object.class); + assertEquals((double) 0, (double) m.invokeExact((Object) null), 0.0); + } + + // + // Explicit casting of null valued return values to primitive type values + // (zero/false). + // + @Test + public void returnValueNullBooleanToZ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Boolean.class, boolean.class); + assertEquals(false, (boolean) m.invokeExact()); + } + + @Test + public void returnValueNullBooleanToB() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Boolean.class, byte.class); + assertEquals((byte) 0, (byte) m.invokeExact()); + } + + @Test + public void returnValueNullBooleanToC() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Boolean.class, char.class); + assertEquals((char) 0, (char) m.invokeExact()); + } + + @Test + public void returnValueNullBooleanToS() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Boolean.class, short.class); + assertEquals((short) 0, (short) m.invokeExact()); + } + + @Test + public void returnValueNullBooleanToI() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Boolean.class, int.class); + assertEquals((int) 0, (int) m.invokeExact()); + } + + @Test + public void returnValueNullBooleanToJ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Boolean.class, long.class); + assertEquals((long) 0, (long) m.invokeExact()); + } + + @Test + public void returnValueNullBooleanToF() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Boolean.class, float.class); + assertEquals((float) 0, (float) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullBooleanToD() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Boolean.class, double.class); + assertEquals((double) 0, (double) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullByteToZ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Byte.class, boolean.class); + assertEquals(false, (boolean) m.invokeExact()); + } + + @Test + public void returnValueNullByteToB() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Byte.class, byte.class); + assertEquals((byte) 0, (byte) m.invokeExact()); + } + + @Test + public void returnValueNullByteToC() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Byte.class, char.class); + assertEquals((char) 0, (char) m.invokeExact()); + } + + @Test + public void returnValueNullByteToS() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Byte.class, short.class); + assertEquals((short) 0, (short) m.invokeExact()); + } + + @Test + public void returnValueNullByteToI() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Byte.class, int.class); + assertEquals((int) 0, (int) m.invokeExact()); + } + + @Test + public void returnValueNullByteToJ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Byte.class, long.class); + assertEquals((long) 0, (long) m.invokeExact()); + } + + @Test + public void returnValueNullByteToF() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Byte.class, float.class); + assertEquals((float) 0, (float) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullByteToD() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Byte.class, double.class); + assertEquals((double) 0, (double) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullCharacterToZ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Character.class, boolean.class); + assertEquals(false, (boolean) m.invokeExact()); + } + + @Test + public void returnValueNullCharacterToB() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Character.class, byte.class); + assertEquals((byte) 0, (byte) m.invokeExact()); + } + + @Test + public void returnValueNullCharacterToC() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Character.class, char.class); + assertEquals((char) 0, (char) m.invokeExact()); + } + + @Test + public void returnValueNullCharacterToS() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Character.class, short.class); + assertEquals((short) 0, (short) m.invokeExact()); + } + + @Test + public void returnValueNullCharacterToI() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Character.class, int.class); + assertEquals((int) 0, (int) m.invokeExact()); + } + + @Test + public void returnValueNullCharacterToJ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Character.class, long.class); + assertEquals((long) 0, (long) m.invokeExact()); + } + + @Test + public void returnValueNullCharacterToF() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Character.class, float.class); + assertEquals((float) 0, (float) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullCharacterToD() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Character.class, double.class); + assertEquals((double) 0, (double) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullShortToZ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Short.class, boolean.class); + assertEquals(false, (boolean) m.invokeExact()); + } + + @Test + public void returnValueNullShortToB() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Short.class, byte.class); + assertEquals((byte) 0, (byte) m.invokeExact()); + } + + @Test + public void returnValueNullShortToC() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Short.class, char.class); + assertEquals((char) 0, (char) m.invokeExact()); + } + + @Test + public void returnValueNullShortToS() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Short.class, short.class); + assertEquals((short) 0, (short) m.invokeExact()); + } + + @Test + public void returnValueNullShortToI() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Short.class, int.class); + assertEquals((int) 0, (int) m.invokeExact()); + } + + @Test + public void returnValueNullShortToJ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Short.class, long.class); + assertEquals((long) 0, (long) m.invokeExact()); + } + + @Test + public void returnValueNullShortToF() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Short.class, float.class); + assertEquals((float) 0, (float) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullShortToD() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Short.class, double.class); + assertEquals((double) 0, (double) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullIntegerToZ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Integer.class, boolean.class); + assertEquals(false, (boolean) m.invokeExact()); + } + + @Test + public void returnValueNullIntegerToB() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Integer.class, byte.class); + assertEquals((byte) 0, (byte) m.invokeExact()); + } + + @Test + public void returnValueNullIntegerToC() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Integer.class, char.class); + assertEquals((char) 0, (char) m.invokeExact()); + } + + @Test + public void returnValueNullIntegerToS() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Integer.class, short.class); + assertEquals((short) 0, (short) m.invokeExact()); + } + + @Test + public void returnValueNullIntegerToI() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Integer.class, int.class); + assertEquals((int) 0, (int) m.invokeExact()); + } + + @Test + public void returnValueNullIntegerToJ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Integer.class, long.class); + assertEquals((long) 0, (long) m.invokeExact()); + } + + @Test + public void returnValueNullIntegerToF() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Integer.class, float.class); + assertEquals((float) 0, (float) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullIntegerToD() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Integer.class, double.class); + assertEquals((double) 0, (double) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullLongToZ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Long.class, boolean.class); + assertEquals(false, (boolean) m.invokeExact()); + } + + @Test + public void returnValueNullLongToB() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Long.class, byte.class); + assertEquals((byte) 0, (byte) m.invokeExact()); + } + + @Test + public void returnValueNullLongToC() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Long.class, char.class); + assertEquals((char) 0, (char) m.invokeExact()); + } + + @Test + public void returnValueNullLongToS() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Long.class, short.class); + assertEquals((short) 0, (short) m.invokeExact()); + } + + @Test + public void returnValueNullLongToI() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Long.class, int.class); + assertEquals((int) 0, (int) m.invokeExact()); + } + + @Test + public void returnValueNullLongToJ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Long.class, long.class); + assertEquals((long) 0, (long) m.invokeExact()); + } + + @Test + public void returnValueNullLongToF() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Long.class, float.class); + assertEquals((float) 0, (float) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullLongToD() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Long.class, double.class); + assertEquals((double) 0, (double) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullFloatToZ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Float.class, boolean.class); + assertEquals(false, (boolean) m.invokeExact()); + } + + @Test + public void returnValueNullFloatToB() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Float.class, byte.class); + assertEquals((byte) 0, (byte) m.invokeExact()); + } + + @Test + public void returnValueNullFloatToC() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Float.class, char.class); + assertEquals((char) 0, (char) m.invokeExact()); + } + + @Test + public void returnValueNullFloatToS() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Float.class, short.class); + assertEquals((short) 0, (short) m.invokeExact()); + } + + @Test + public void returnValueNullFloatToI() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Float.class, int.class); + assertEquals((int) 0, (int) m.invokeExact()); + } + + @Test + public void returnValueNullFloatToJ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Float.class, long.class); + assertEquals((long) 0, (long) m.invokeExact()); + } + + @Test + public void returnValueNullFloatToF() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Float.class, float.class); + assertEquals((float) 0, (float) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullFloatToD() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Float.class, double.class); + assertEquals((double) 0, (double) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullDoubleToZ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Double.class, boolean.class); + assertEquals(false, (boolean) m.invokeExact()); + } + + @Test + public void returnValueNullDoubleToB() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Double.class, byte.class); + assertEquals((byte) 0, (byte) m.invokeExact()); + } + + @Test + public void returnValueNullDoubleToC() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Double.class, char.class); + assertEquals((char) 0, (char) m.invokeExact()); + } + + @Test + public void returnValueNullDoubleToS() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Double.class, short.class); + assertEquals((short) 0, (short) m.invokeExact()); + } + + @Test + public void returnValueNullDoubleToI() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Double.class, int.class); + assertEquals((int) 0, (int) m.invokeExact()); + } + + @Test + public void returnValueNullDoubleToJ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Double.class, long.class); + assertEquals((long) 0, (long) m.invokeExact()); + } + + @Test + public void returnValueNullDoubleToF() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Double.class, float.class); + assertEquals((float) 0, (float) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullDoubleToD() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Double.class, double.class); + assertEquals((double) 0, (double) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullObjectToZ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Object.class, boolean.class); + assertEquals(false, (boolean) m.invokeExact()); + } + + @Test + public void returnValueNullObjectToB() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Object.class, byte.class); + assertEquals((byte) 0, (byte) m.invokeExact()); + } + + @Test + public void returnValueNullObjectToC() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Object.class, char.class); + assertEquals((char) 0, (char) m.invokeExact()); + } + + @Test + public void returnValueNullObjectToS() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Object.class, short.class); + assertEquals((short) 0, (short) m.invokeExact()); + } + + @Test + public void returnValueNullObjectToI() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Object.class, int.class); + assertEquals((int) 0, (int) m.invokeExact()); + } + + @Test + public void returnValueNullObjectToJ() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Object.class, long.class); + assertEquals((long) 0, (long) m.invokeExact()); + } + + @Test + public void returnValueNullObjectToF() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Object.class, float.class); + assertEquals((float) 0, (float) m.invokeExact(), 0.0); + } + + @Test + public void returnValueNullObjectToD() throws Throwable + { + MethodHandle m = nullConstantExplicitCastToPrimitive(Object.class, double.class); + assertEquals((double) 0, (double) m.invokeExact(), 0.0); + } + + // + // Check asType() behaviour of void return value cast to primitives yields + // zero/false/null. + // + @Test + public void testVoidReturnToZ() throws Throwable { + assertFalse((boolean) explicitCastVoidReturnValue(boolean.class).invokeExact()); + } + + @Test + public void testVoidReturnToB() throws Throwable { + assertEquals((byte) 0, (byte) explicitCastVoidReturnValue(byte.class).invokeExact()); + } + + @Test + public void testVoidReturnToC() throws Throwable { + assertEquals((char) 0, (char) explicitCastVoidReturnValue(char.class).invokeExact()); + } + + @Test + public void testVoidReturnToS() throws Throwable { + assertEquals((short) 0, (short) explicitCastVoidReturnValue(short.class).invokeExact()); + } + + @Test + public void testVoidReturnToI() throws Throwable { + assertEquals((int) 0, (int) explicitCastVoidReturnValue(int.class).invokeExact()); + } + + @Test + public void testVoidReturnToJ() throws Throwable { + assertEquals((long) 0, (long) explicitCastVoidReturnValue(long.class).invokeExact()); + } + + @Test + public void testVoidReturnToF() throws Throwable { + assertEquals((float) 0, (float) explicitCastVoidReturnValue(float.class).invokeExact(), 0.0); + } + + @Test + public void testVoidReturnToD() throws Throwable { + assertEquals((double) 0, (double) explicitCastVoidReturnValue(double.class).invokeExact(), 0.0); + } + + @Test + public void testVoidReturnToBoolean() throws Throwable { + assertNull((Boolean) explicitCastVoidReturnValue(Boolean.class).invokeExact()); + } + + @Test + public void testVoidReturnToByte() throws Throwable { + assertNull((Byte) explicitCastVoidReturnValue(Byte.class).invokeExact()); + } + + @Test + public void testVoidReturnToCharacter() throws Throwable { + assertNull((Character) explicitCastVoidReturnValue(Character.class).invokeExact()); + } + + @Test + public void testVoidReturnToShort() throws Throwable { + assertNull((Short) explicitCastVoidReturnValue(Short.class).invokeExact()); + } + + @Test + public void testVoidReturnToInteger() throws Throwable { + assertNull((Integer) explicitCastVoidReturnValue(Integer.class).invokeExact()); + } + + @Test + public void testVoidReturnToLong() throws Throwable { + assertNull((Long) explicitCastVoidReturnValue(Long.class).invokeExact()); + } + + @Test + public void testVoidReturnToFloat() throws Throwable { + assertNull((Float) explicitCastVoidReturnValue(Float.class).invokeExact()); + } + + @Test + public void testVoidReturnToDouble() throws Throwable { + assertNull((Double) explicitCastVoidReturnValue(Double.class).invokeExact()); + } + + @Test + public void testVoidReturnToObject() throws Throwable { + assertNull((Object) explicitCastVoidReturnValue(Object.class).invokeExact()); + } + + // + // Check asType() behaviour of returning a value cast to void. + // + @Test + public void testReturnZToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(boolean.class, void.class); + m.invokeExact((boolean) BOOLEAN_VALUES[0]); + } + + @Test + public void testReturnBToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(byte.class, void.class); + m.invokeExact((byte) BYTE_VALUES[0]); + } + + @Test + public void testReturnCToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(char.class, void.class); + m.invokeExact((char) CHARACTER_VALUES[0]); + } + + @Test + public void testReturnSToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(short.class, void.class); + m.invokeExact((short) SHORT_VALUES[0]); + } + + @Test + public void testReturnIToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(int.class, void.class); + m.invokeExact((int) INTEGER_VALUES[0]); + } + + @Test + public void testReturnJToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(long.class, void.class); + m.invokeExact((long) LONG_VALUES[0]); + } + + @Test + public void testReturnFToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(float.class, void.class); + m.invokeExact((float) FLOAT_VALUES[0]); + } + + @Test + public void testReturnDToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(double.class, void.class); + m.invokeExact((double) DOUBLE_VALUES[0]); + } + + @Test + public void testReturnBooleanToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(Boolean.class, void.class); + m.invokeExact((Boolean) BOOLEAN_VALUES[0]); + } + + @Test + public void testReturnByteToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(Byte.class, void.class); + m.invokeExact((Byte) BYTE_VALUES[0]); + } + + @Test + public void testReturnCharacterToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(Character.class, void.class); + m.invokeExact((Character) CHARACTER_VALUES[0]); + } + + @Test + public void testReturnShortToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(Short.class, void.class); + m.invokeExact((Short) SHORT_VALUES[0]); + } + + @Test + public void testReturnIntegerToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(Integer.class, void.class); + m.invokeExact((Integer) INTEGER_VALUES[0]); + } + + @Test + public void testReturnLongToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(Long.class, void.class); + m.invokeExact((Long) LONG_VALUES[0]); + } + + @Test + public void testReturnFloatToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(Float.class, void.class); + m.invokeExact((Float) FLOAT_VALUES[0]); + } + + @Test + public void testReturnDoubleToVoid() throws Throwable { + MethodHandle m = explicitCastReturnValueFromIdentity(Double.class, void.class); + m.invokeExact((Double) DOUBLE_VALUES[0]); + } + +} diff --git a/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java index 5866ae4ae2..a8cfa24224 100644 --- a/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java +++ b/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java @@ -1214,7 +1214,7 @@ public class MethodHandleCombinersTest extends TestCase { Object ret = handle.invokeWithArguments(new Object[]{"a", "b", "c"}); assertEquals(42, (int) ret); - ret = handle.invokeWithArguments(new String[]{"a", "b", "c"}); + ret = handle.invokeWithArguments((Object[]) new String[]{"a", "b", "c"}); assertEquals(42, (int) ret); // Also test the versions that take a List<?> instead of an array. diff --git a/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java index fc18ab8efa..8e08a59394 100644 --- a/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java +++ b/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java @@ -29,6 +29,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.function.Consumer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -299,6 +300,18 @@ public class MethodHandlesTest extends TestCase { public static final Lookup lookup = MethodHandles.lookup(); } + public interface F { + public default void callInner(Consumer<Class<?>> c) { + c.accept(F.class); + } + } + + public class G implements F { + public void callInner(Consumer<Class<?>> c) { + c.accept(G.class); + } + } + public void testfindSpecial_invokeSuperBehaviour() throws Throwable { // This is equivalent to an invoke-super instruction where the referrer // is B.class. @@ -364,6 +377,41 @@ public class MethodHandlesTest extends TestCase { } catch (NoSuchMethodException e) {} } + public void testfindSpecial_invokeSuperInterfaceBehaviour() throws Throwable { + // Check interface invoke super on unrelated lookup (with some private access). + Class<?>[] res = new Class<?>[2]; + MethodHandle mh = MethodHandles.lookup().findSpecial(F.class /* refC */, "callInner", + MethodType.methodType(void.class, Consumer.class), G.class /* specialCaller */); + G g = new G(); + Consumer<Class<?>> oc = (Class<?> c) -> { res[0] = c; }; + mh.invokeExact(g, oc); + g.callInner((Class<?> c) -> { res[1] = c; }); + // Make sure the method-handle calls the default implementatoin + assertTrue(res[0] == F.class); + // Make sure the normal one works as we expect. + assertTrue(res[1] == G.class); + + // Check findSpecial always fails if the lookup has only public access + try { + MethodHandles.publicLookup().findSpecial(F.class /* refC */, "callInner", + MethodType.methodType(void.class, Consumer.class), G.class /* specialCaller */); + fail(); + } catch (IllegalAccessException e) {} + + // Check doing invokeSpecial on abstract interface methods gets appropriate errors. We + // expect it to throw an IllegalAccessError. + MethodHandle mh2 = + MethodHandles.lookup().findSpecial( + Foo.class /* refC */, + "foo", + MethodType.methodType(String.class), + Bar.class /* specialCaller */); + try { + mh2.invoke(new BarImpl()); + fail(); + } catch (IllegalAccessException e) {} + } + public void testfindSpecial_invokeDirectBehaviour() throws Throwable { D dInstance = new D(); diff --git a/luni/src/test/java/libcore/java/lang/invoke/MethodTypeTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodTypeTest.java index f833840126..0c4d18b564 100644 --- a/luni/src/test/java/libcore/java/lang/invoke/MethodTypeTest.java +++ b/luni/src/test/java/libcore/java/lang/invoke/MethodTypeTest.java @@ -96,7 +96,7 @@ public class MethodTypeTest extends TestCase { } try { - MethodType.methodType(int.class, String.class, null); + MethodType.methodType(int.class, String.class, (Class<?>) null); fail(); } catch (NullPointerException expected) { } @@ -334,7 +334,7 @@ public class MethodTypeTest extends TestCase { } try { - mt.insertParameterTypes(1, Arrays.asList(null)); + mt.insertParameterTypes(1, Arrays.asList((Class<?>) null)); fail(); } catch (NullPointerException expected) { } @@ -404,7 +404,7 @@ public class MethodTypeTest extends TestCase { } try { - mt.appendParameterTypes(Arrays.asList(null)); + mt.appendParameterTypes(Arrays.asList((Class<?>) null)); fail(); } catch (NullPointerException expected) { } diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotationsTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotationsTest.java index 0e40644aea..a0b706659c 100644 --- a/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotationsTest.java +++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotationsTest.java @@ -15,7 +15,6 @@ */ package libcore.java.lang.reflect.annotations; -import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; @@ -23,19 +22,12 @@ import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Annotat import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationB; import libcore.junit.junit3.TestCaseWithRules; -import libcore.junit.util.SwitchTargetSdkVersionRule; -import libcore.junit.util.SwitchTargetSdkVersionRule.TargetSdkVersion; -import org.junit.Rule; -import org.junit.rules.TestRule; /** * Tests for the behavior of Annotation instances at runtime. */ public class AnnotationsTest extends TestCaseWithRules { - @Rule - public TestRule switchTargetSdkVersionRule = SwitchTargetSdkVersionRule.getInstance(); - enum Breakfast { WAFFLES, PANCAKES } @Retention(RetentionPolicy.RUNTIME) @@ -80,39 +72,4 @@ public class AnnotationsTest extends TestCaseWithRules { private static Object defaultValue(String name) throws NoSuchMethodException { return HasDefaultsAnnotation.class.getMethod(name).getDefaultValue(); } - - @Retention(RetentionPolicy.CLASS) - public @interface ClassRetentionAnnotation {} - - @Retention(RetentionPolicy.RUNTIME) - public @interface RuntimeRetentionAnnotation {} - - @Retention(RetentionPolicy.SOURCE) - public @interface SourceRetentionAnnotation {} - - @ClassRetentionAnnotation @RuntimeRetentionAnnotation @SourceRetentionAnnotation - public static class RetentionAnnotations {} - - // b/29500035 - @TargetSdkVersion(23) - public void testRetentionPolicy_targetSdkVersion_23() { - // Test pre-N behavior - Annotation classRetentionAnnotation = - RetentionAnnotations.class.getAnnotation(ClassRetentionAnnotation.class); - assertNotNull(classRetentionAnnotation); - } - - // b/29500035 - @TargetSdkVersion(24) - public void testRetentionPolicy_targetSdkVersion_24() { - // Test N and later behavior - Annotation classRetentionAnnotation = - RetentionAnnotations.class.getAnnotation(ClassRetentionAnnotation.class); - assertNull(classRetentionAnnotation); - } - - public void testRetentionPolicy() { - assertNotNull(RetentionAnnotations.class.getAnnotation(RuntimeRetentionAnnotation.class)); - assertNull(RetentionAnnotations.class.getAnnotation(SourceRetentionAnnotation.class)); - } } diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/RetentionPolicyTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/RetentionPolicyTest.java new file mode 100644 index 0000000000..54039105ec --- /dev/null +++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/RetentionPolicyTest.java @@ -0,0 +1,124 @@ +/* + * 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. + */ +package libcore.java.lang.reflect.annotations; + +import dalvik.system.PathClassLoader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import libcore.io.Streams; +import libcore.junit.util.SwitchTargetSdkVersionRule; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +/** + * Runs tests against classes loaded from the annotations-test.jar. + * + * <p>The annotated classes are built separately in order to ensure class-retention annotations are + * kept which is no longer the default behavior of the platform dexer. + */ +@RunWith(JUnit4.class) +public class RetentionPolicyTest { + + @Rule + public TestRule switchTargetSdkVersionRule = SwitchTargetSdkVersionRule.getInstance(); + + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); + + /** + * Static reference to the classloader created for annotations-test.jar. + * + * <p>This is created statically as it is expensive to create. + */ + private static ClassLoader classLoader; + + @BeforeClass + public static void openClassLoader() throws IOException { + ClassLoader myClassLoader = RetentionPolicyTest.class.getClassLoader(); + assertNotNull(myClassLoader); + + // Load the annotated class (and annotation classes) from the annotations-test.jar. + File jarFile = new File(temporaryFolder.getRoot(), "annotations-test.jar"); + try (InputStream in = myClassLoader.getResourceAsStream("annotations-test.jar"); + OutputStream out = new FileOutputStream(jarFile)) { + Streams.copy(in, out); + } + + classLoader = new PathClassLoader(jarFile.getAbsolutePath(), myClassLoader); + } + + @AfterClass + public static void closeClassLoader() { + // Null the reference to allow it to be garbage collected if necessary. + classLoader = null; + } + + @SuppressWarnings("unchecked") + private Class<? extends Annotation> getAnnotationClass(String name) throws Exception { + return (Class<? extends Annotation>) classLoader.loadClass(name); + } + + private Class<?> getRetentionAnnotationsClass() throws Exception { + return classLoader.loadClass("libcore.tests.annotations.RetentionAnnotations"); + } + + // b/29500035 + @SwitchTargetSdkVersionRule.TargetSdkVersion(23) + @Test + public void testRetentionPolicy_targetSdkVersion_23() throws Exception { + Class<? extends Annotation> annotationClass = getAnnotationClass( + "libcore.tests.annotations.ClassRetentionAnnotation"); + // Test pre-N behavior + Annotation classRetentionAnnotation = + getRetentionAnnotationsClass().getAnnotation(annotationClass); + assertNotNull(classRetentionAnnotation); + } + + // b/29500035 + @SwitchTargetSdkVersionRule.TargetSdkVersion(24) + @Test + public void testRetentionPolicy_targetSdkVersion_24() throws Exception { + // Test N and later behavior + Class<? extends Annotation> annotationClass = getAnnotationClass( + "libcore.tests.annotations.ClassRetentionAnnotation"); + Annotation classRetentionAnnotation = + getRetentionAnnotationsClass().getAnnotation(annotationClass); + assertNull(classRetentionAnnotation); + } + + @Test + public void testRetentionPolicy() throws Exception { + Class<?> retentionAnnotationsClass = getRetentionAnnotationsClass(); + assertNotNull(retentionAnnotationsClass.getAnnotation(getAnnotationClass( + "libcore.tests.annotations.RuntimeRetentionAnnotation"))); + assertNull(retentionAnnotationsClass.getAnnotation(getAnnotationClass( + "libcore.tests.annotations.SourceRetentionAnnotation"))); + } +} diff --git a/luni/src/test/java/libcore/java/math/BigIntegerTest.java b/luni/src/test/java/libcore/java/math/BigIntegerTest.java index 80041c222f..6c1d11e684 100644 --- a/luni/src/test/java/libcore/java/math/BigIntegerTest.java +++ b/luni/src/test/java/libcore/java/math/BigIntegerTest.java @@ -195,4 +195,35 @@ public class BigIntegerTest extends junit.framework.TestCase { assertEquals("-9223372036854775808", negV.toString()); assertEquals( "9223372036854775808", posV.toString()); } + + private void try_gcd_variants(BigInteger arg1, BigInteger arg2, BigInteger result) + throws Exception { + // Test both argument orders, and all 4 combinations of negation. + assertEquals(arg1.gcd(arg2), result); + assertEquals(arg2.gcd(arg1), result); + assertEquals(arg1.negate().gcd(arg2), result); + assertEquals(arg2.gcd(arg1.negate()), result); + assertEquals(arg1.gcd(arg2.negate()), result); + assertEquals(arg2.negate().gcd(arg1), result); + assertEquals(arg1.negate().gcd(arg2.negate()), result); + assertEquals(arg2.negate().gcd(arg1.negate()), result); + } + + /** + * Test gcd(), with emphasis on arguments of very different size. + */ + public void test_gcd() throws Exception { + BigInteger two = BigInteger.valueOf(2); // BigInteger.TWO added in OpenJDK 9 + BigInteger three = BigInteger.valueOf(3); + try_gcd_variants(BigInteger.TEN, two, two); + try_gcd_variants(BigInteger.TEN, BigInteger.TEN, BigInteger.TEN); + try_gcd_variants(BigInteger.TEN, BigInteger.ZERO, BigInteger.TEN); + try_gcd_variants(BigInteger.ZERO, BigInteger.ZERO, BigInteger.ZERO); + BigInteger large = three.shiftLeft(500); + try_gcd_variants(large, three, three); + try_gcd_variants(large, large, large); + try_gcd_variants(large, two, two); + try_gcd_variants(large, BigInteger.valueOf(5), BigInteger.ONE); + try_gcd_variants(large, BigInteger.ZERO, large); + } } diff --git a/luni/src/test/java/libcore/java/net/AuditInputStream.java b/luni/src/test/java/libcore/java/net/AuditInputStream.java new file mode 100644 index 0000000000..2a76cac092 --- /dev/null +++ b/luni/src/test/java/libcore/java/net/AuditInputStream.java @@ -0,0 +1,61 @@ +/* + * 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. + */ + +package libcore.java.net; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Objects; + +/** + * An {@link InputStream} that reads from a delegate and also writes an audit log of all data + * that was read to the given {@code audit} {@link OutputStream}. + */ +class AuditInputStream extends FilterInputStream { + private final OutputStream audit; + + protected AuditInputStream(InputStream in, OutputStream audit) { + super(in); + this.audit = Objects.requireNonNull(audit); + } + + @Override + public int read() throws IOException { + int result = super.read(); + audit.write(result); + return result; + } + + @Override + public int read(byte[] b) throws IOException { + int result = super.read(b); + if (result > 0) { + audit.write(b, 0, result); + } + return result; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + int result = super.read(b, off, len); + if (result > 0) { + audit.write(b, off, result); + } + return result; + } +} diff --git a/luni/src/test/java/libcore/java/net/InetAddressTest.java b/luni/src/test/java/libcore/java/net/InetAddressTest.java index 307cd1d45c..6bbfe0187a 100644 --- a/luni/src/test/java/libcore/java/net/InetAddressTest.java +++ b/luni/src/test/java/libcore/java/net/InetAddressTest.java @@ -36,6 +36,7 @@ import java.util.Set; import junitparams.JUnitParamsRunner; import junitparams.Parameters; import libcore.libcore.util.SerializationTester; +import libcore.net.InetAddressUtils; import org.junit.Test; import org.junit.runner.RunWith; @@ -281,10 +282,17 @@ public class InetAddressTest { public void test_isReachable_by_ICMP() throws Exception { InetAddress[] inetAddresses = InetAddress.getAllByName("www.google.com"); for (InetAddress ia : inetAddresses) { - // ICMP is not reliable, allow 5 attempts before failing. - assertTrue(ia.isReachableByICMP(5 * 1000 /* ICMP timeout */)); + // ICMP is not reliable, allow 5 attempts to each IP address before failing. + // If any address is reachable then that's sufficient. + if (ia.isReachableByICMP(5 * 1000 /* ICMP timeout */)) { + return; + } } + fail(); + } + @Test + public void test_inUnreachable() throws Exception { // IPv6 discard prefix. RFC 6666. final InetAddress blackholeAddress = InetAddress.getByName("100::1"); assertFalse(blackholeAddress.isReachable(1000)); @@ -312,8 +320,12 @@ public class InetAddressTest { public void test_getByName_invalid(String invalid) throws Exception { try { InetAddress.getByName(invalid); - fail("Invalid IP address incorrectly recognized as valid: " - + invalid); + String msg = "Invalid IP address incorrectly recognized as valid: \"" + invalid + "\""; + if (InetAddressUtils.parseNumericAddressNoThrowStripOptionalBrackets(invalid) == null) { + msg += " (it was probably unexpectedly resolved by this network's DNS)"; + } + msg += "."; + fail(msg); } catch (UnknownHostException expected) { } diff --git a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java index 51c8b04afa..f0f79ade93 100644 --- a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java +++ b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java @@ -18,6 +18,7 @@ package libcore.java.net; import junit.framework.TestCase; +import android.system.StructIfaddrs; import java.io.BufferedReader; import java.io.FileDescriptor; import java.io.InputStreamReader; @@ -29,6 +30,7 @@ import java.net.InterfaceAddress; import java.net.MulticastSocket; import java.net.NetworkInterface; import java.net.SocketException; +import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.HashSet; @@ -100,7 +102,6 @@ public class NetworkInterfaceTest extends TestCase { } // Ethernet if (isEthernet(nif.getName())) { - assertEquals(6, nif.getHardwareAddress().length); for (InterfaceAddress ia : nif.getInterfaceAddresses()) { if (ia.getAddress() instanceof Inet4Address) { assertNotNull(ia.getBroadcast()); @@ -110,6 +111,13 @@ public class NetworkInterfaceTest extends TestCase { } } + public void testGetHardwareAddress_returnsNull() throws Exception { + // Hardware addresses should be unavailable to non-system apps. + for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) { + assertNull(nif.getHardwareAddress()); + } + } + public void testLoopback() throws Exception { NetworkInterface lo = NetworkInterface.getByName("lo"); assertNull(lo.getHardwareAddress()); @@ -201,31 +209,16 @@ public class NetworkInterfaceTest extends TestCase { } catch(SocketException expected) {} } - // b/29243557 - public void testGetNetworkInterfaces() throws Exception { - // Check that the interfaces we get from #getNetworkInterfaces agrees with IP-LINK(8). - - // Parse output of ip link. - String[] cmd = { "ip", "link" }; - Process proc = Runtime.getRuntime().exec(cmd); - BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream())); - Set<String> expectedNiNames = new HashSet<>(); - for (String s; (s = stdInput.readLine()) != null; ) { - String[] split = s.split(": |@"); - try { - if (split.length > 2) { - expectedNiNames.add(split[1]); - } - } catch (NumberFormatException e) { - // Skip this line. - } - } + public void testGetNetworkInterfaces_matchesIfaddrs() throws Exception { + StructIfaddrs[] ifaddrs = Libcore.os.getifaddrs(); + Set<String> ifaddrsNames = new HashSet<>(); + Arrays.asList(ifaddrs).forEach(ifa -> ifaddrsNames.add(ifa.ifa_name)); - Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces(); + List<NetworkInterface> nifs = Collections.list(NetworkInterface.getNetworkInterfaces()); Set<String> actualNiNames = new HashSet<>(); - Collections.list(nifs).forEach(ni -> actualNiNames.add(ni.getName())); + nifs.forEach(ni -> actualNiNames.add(ni.getName())); - assertEquals(expectedNiNames, actualNiNames); + assertEquals(ifaddrsNames, actualNiNames); } // Calling getSubInterfaces on interfaces with no subinterface should not throw NPE. diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java index 1574caf644..ddd447ad06 100644 --- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java +++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java @@ -16,17 +16,19 @@ package libcore.java.net; +import com.android.okhttp.AndroidShimResponseCache; +import com.android.okhttp.internal.Platform; +import com.android.okhttp.internal.tls.TrustRootIndex; import com.google.mockwebserver.Dispatcher; import com.google.mockwebserver.MockResponse; import com.google.mockwebserver.MockWebServer; +import com.google.mockwebserver.QueueDispatcher; import com.google.mockwebserver.RecordedRequest; import com.google.mockwebserver.SocketPolicy; -import com.android.okhttp.AndroidShimResponseCache; -import com.android.okhttp.internal.Platform; -import com.android.okhttp.internal.tls.TrustRootIndex; - -import junit.framework.TestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; import java.io.ByteArrayOutputStream; import java.io.File; @@ -57,6 +59,7 @@ import java.net.URL; import java.net.URLConnection; import java.net.UnknownHostException; import java.nio.channels.SocketChannel; +import java.nio.charset.StandardCharsets; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; @@ -86,8 +89,10 @@ import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; +import libcore.content.type.MimeMap; import libcore.java.security.TestKeyStore; import libcore.javax.net.ssl.TestSSLContext; +import libcore.testing.io.TestIoUtils; import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END; import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_START; @@ -95,23 +100,26 @@ import static com.google.mockwebserver.SocketPolicy.FAIL_HANDSHAKE; import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END; import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -public final class URLConnectionTest extends TestCase { +public final class URLConnectionTest { private MockWebServer server; private AndroidShimResponseCache cache; private String hostName; private List<TestSSLContext> testSSLContextsToClose; - @Override protected void setUp() throws Exception { - super.setUp(); + @Before public void setUp() throws Exception { server = new MockWebServer(); hostName = server.getHostName(); testSSLContextsToClose = new ArrayList<>(); } - @Override protected void tearDown() throws Exception { + @After public void tearDown() throws Exception { ResponseCache.setDefault(null); Authenticator.setDefault(null); System.clearProperty("proxyHost"); @@ -129,10 +137,9 @@ public final class URLConnectionTest extends TestCase { for (TestSSLContext testSSLContext : testSSLContextsToClose) { testSSLContext.close(); } - super.tearDown(); } - public void testRequestHeaderValidation() throws Exception { + @Test public void requestHeaderValidation() throws Exception { // Android became more strict after M about which characters were allowed in request header // names and values: previously almost anything was allowed if it didn't contain \0. @@ -225,7 +232,7 @@ public final class URLConnectionTest extends TestCase { return urlConnection.getRequestProperty("key"); } - public void testRequestHeaders() throws IOException, InterruptedException { + @Test public void requestHeaders() throws IOException, InterruptedException { server.enqueue(new MockResponse()); server.play(); @@ -288,7 +295,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testGetRequestPropertyReturnsLastValue() throws Exception { + @Test public void getRequestPropertyReturnsLastValue() throws Exception { server.play(); HttpURLConnection urlConnection = (HttpURLConnection) server.getUrl("/").openConnection(); urlConnection.addRequestProperty("A", "value1"); @@ -296,7 +303,7 @@ public final class URLConnectionTest extends TestCase { assertEquals("value2", urlConnection.getRequestProperty("A")); } - public void testResponseHeaders() throws IOException, InterruptedException { + @Test public void responseHeaders() throws IOException, InterruptedException { server.enqueue(new MockResponse() .setStatus("HTTP/1.0 200 Fantastic") .addHeader("A: c") @@ -331,24 +338,24 @@ public final class URLConnectionTest extends TestCase { assertEquals("e", urlConnection.getHeaderField(2)); } - public void testGetErrorStreamOnSuccessfulRequest() throws Exception { + @Test public void getErrorStreamOnSuccessfulRequest() throws Exception { server.enqueue(new MockResponse().setBody("A")); server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); assertNull(connection.getErrorStream()); } - public void testGetErrorStreamOnUnsuccessfulRequest() throws Exception { + @Test public void getErrorStreamOnUnsuccessfulRequest() throws Exception { server.enqueue(new MockResponse().setResponseCode(404).setBody("A")); server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); - assertEquals("A", readAscii(connection.getErrorStream(), Integer.MAX_VALUE)); + assertEquals("A", readAscii(connection.getErrorStream())); } // Check that if we don't read to the end of a response, the next request on the // recycled connection doesn't get the unread tail of the first request's response. // http://code.google.com/p/android/issues/detail?id=2939 - public void test_2939() throws Exception { + @Test public void bug2939() throws Exception { MockResponse response = new MockResponse().setChunkedBody("ABCDE\nFGHIJ\nKLMNO\nPQR", 8); server.enqueue(response); @@ -361,12 +368,12 @@ public final class URLConnectionTest extends TestCase { // Check that we recognize a few basic mime types by extension. // http://code.google.com/p/android/issues/detail?id=10100 - public void test_10100() throws Exception { + @Test public void bug10100() throws Exception { assertEquals("image/jpeg", URLConnection.guessContentTypeFromName("someFile.jpg")); assertEquals("application/pdf", URLConnection.guessContentTypeFromName("stuff.pdf")); } - public void testConnectionsArePooled() throws Exception { + @Test public void connectionsArePooled() throws Exception { MockResponse response = new MockResponse().setBody("ABCDEFGHIJKLMNOPQR"); server.enqueue(response); @@ -382,7 +389,7 @@ public final class URLConnectionTest extends TestCase { assertEquals(2, server.takeRequest().getSequenceNumber()); } - public void testChunkedConnectionsArePooled() throws Exception { + @Test public void chunkedConnectionsArePooled() throws Exception { MockResponse response = new MockResponse().setChunkedBody("ABCDEFGHIJKLMNOPQR", 5); server.enqueue(response); @@ -402,24 +409,24 @@ public final class URLConnectionTest extends TestCase { * Test that connections are added to the pool as soon as the response has * been consumed. */ - public void testConnectionsArePooledWithoutExplicitDisconnect() throws Exception { + @Test public void connectionsArePooledWithoutExplicitDisconnect() throws Exception { server.enqueue(new MockResponse().setBody("ABC")); server.enqueue(new MockResponse().setBody("DEF")); server.play(); URLConnection connection1 = server.getUrl("/").openConnection(); - assertEquals("ABC", readAscii(connection1.getInputStream(), Integer.MAX_VALUE)); + assertEquals("ABC", readAscii(connection1.getInputStream())); assertEquals(0, server.takeRequest().getSequenceNumber()); URLConnection connection2 = server.getUrl("/").openConnection(); - assertEquals("DEF", readAscii(connection2.getInputStream(), Integer.MAX_VALUE)); + assertEquals("DEF", readAscii(connection2.getInputStream())); assertEquals(1, server.takeRequest().getSequenceNumber()); } - public void testServerClosesSocket() throws Exception { + @Test public void serverClosesSocket() throws Exception { testServerClosesSocket(DISCONNECT_AT_END); } - public void testServerShutdownInput() throws Exception { + @Test public void serverShutdownInput() throws Exception { testServerClosesSocket(SHUTDOWN_INPUT_AT_END); } @@ -437,7 +444,7 @@ public final class URLConnectionTest extends TestCase { assertEquals(0, server.takeRequest().getSequenceNumber()); } - public void testServerShutdownOutput() throws Exception { + @Test public void serverShutdownOutput() throws Exception { // This test causes MockWebServer to log a "connection failed" stack trace // Setting the server workerThreads to 1 ensures the responses are generated in the order @@ -461,27 +468,27 @@ public final class URLConnectionTest extends TestCase { enum WriteKind { BYTE_BY_BYTE, SMALL_BUFFERS, LARGE_BUFFERS } - public void test_chunkedUpload_byteByByte() throws Exception { + @Test public void chunkedUpload_byteByByte() throws Exception { doUpload(TransferKind.CHUNKED, WriteKind.BYTE_BY_BYTE); } - public void test_chunkedUpload_smallBuffers() throws Exception { + @Test public void chunkedUpload_smallBuffers() throws Exception { doUpload(TransferKind.CHUNKED, WriteKind.SMALL_BUFFERS); } - public void test_chunkedUpload_largeBuffers() throws Exception { + @Test public void chunkedUpload_largeBuffers() throws Exception { doUpload(TransferKind.CHUNKED, WriteKind.LARGE_BUFFERS); } - public void test_fixedLengthUpload_byteByByte() throws Exception { + @Test public void fixedLengthUpload_byteByByte() throws Exception { doUpload(TransferKind.FIXED_LENGTH, WriteKind.BYTE_BY_BYTE); } - public void test_fixedLengthUpload_smallBuffers() throws Exception { + @Test public void fixedLengthUpload_smallBuffers() throws Exception { doUpload(TransferKind.FIXED_LENGTH, WriteKind.SMALL_BUFFERS); } - public void test_fixedLengthUpload_largeBuffers() throws Exception { + @Test public void fixedLengthUpload_largeBuffers() throws Exception { doUpload(TransferKind.FIXED_LENGTH, WriteKind.LARGE_BUFFERS); } @@ -522,7 +529,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testGetResponseCodeNoResponseBody() throws Exception { + @Test public void getResponseCodeNoResponseBody() throws Exception { server.enqueue(new MockResponse() .addHeader("abc: def")); server.play(); @@ -539,7 +546,11 @@ public final class URLConnectionTest extends TestCase { } } - public void testConnectViaHttps() throws IOException, InterruptedException { + @Test public void connectViaHttps() throws IOException, InterruptedException { + checkConnectViaHttps(); + } + + private void checkConnectViaHttps() throws IOException, InterruptedException { TestSSLContext testSSLContext = createDefaultTestSSLContext(); server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); @@ -556,7 +567,7 @@ public final class URLConnectionTest extends TestCase { assertEquals("TLSv1.2", request.getSslProtocol()); } - public void testConnectViaHttpsReusingConnections() throws IOException, InterruptedException { + @Test public void connectViaHttpsReusingConnections() throws IOException, InterruptedException { TestSSLContext testSSLContext = createDefaultTestSSLContext(); SSLSocketFactory clientSocketFactory = testSSLContext.clientContext.getSocketFactory(); @@ -577,7 +588,7 @@ public final class URLConnectionTest extends TestCase { assertEquals(1, server.takeRequest().getSequenceNumber()); } - public void testConnectViaHttpsReusingConnectionsDifferentFactories() + @Test public void connectViaHttpsReusingConnectionsDifferentFactories() throws IOException, InterruptedException { TestSSLContext testSSLContext = createDefaultTestSSLContext(); @@ -593,7 +604,7 @@ public final class URLConnectionTest extends TestCase { connection = (HttpsURLConnection) server.getUrl("/").openConnection(); try { - readAscii(connection.getInputStream(), Integer.MAX_VALUE); + readAscii(connection.getInputStream()); fail("without an SSL socket factory, the connection should fail"); } catch (SSLException expected) { } @@ -604,7 +615,7 @@ public final class URLConnectionTest extends TestCase { * * http://code.google.com/p/android/issues/detail?id=13178 */ - public void testConnectViaHttpsToUntrustedServer() throws IOException, InterruptedException { + @Test public void connectViaHttpsToUntrustedServer() throws IOException, InterruptedException { TestSSLContext testSSLContext = TestSSLContext.create(TestKeyStore.getClientCA2(), TestKeyStore.getServer()); testSSLContextsToClose.add(testSSLContext); @@ -624,29 +635,29 @@ public final class URLConnectionTest extends TestCase { assertEquals(0, server.getRequestCount()); } - public void testConnectViaProxy_emptyPath() throws Exception { + @Test public void connectViaProxy_emptyPath() throws Exception { // expected normalization http://android -> http://android/ per b/30107354 checkConnectViaProxy( ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY, "http://android.com", "http://android.com/", "android.com"); } - public void testConnectViaProxy_complexUrlWithNoPath() throws Exception { + @Test public void connectViaProxy_complexUrlWithNoPath() throws Exception { checkConnectViaProxy(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY, "http://android.com:8080?height=100&width=42", "http://android.com:8080/?height=100&width=42", "android.com:8080"); } - public void testConnectViaProxyUsingProxyArg() throws Exception { + @Test public void connectViaProxyUsingProxyArg() throws Exception { checkConnectViaProxy(ProxyConfig.CREATE_ARG); } - public void testConnectViaProxyUsingProxySystemProperty() throws Exception { + @Test public void connectViaProxyUsingProxySystemProperty() throws Exception { checkConnectViaProxy(ProxyConfig.PROXY_SYSTEM_PROPERTY); } - public void testConnectViaProxyUsingHttpProxySystemProperty() throws Exception { + @Test public void connectViaProxyUsingHttpProxySystemProperty() throws Exception { checkConnectViaProxy(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY); } @@ -670,7 +681,7 @@ public final class URLConnectionTest extends TestCase { assertContains(request.getHeaders(), "Host: " + expectedHost); } - public void testContentDisagreesWithContentLengthHeader() throws IOException { + @Test public void contentDisagreesWithContentLengthHeader() throws IOException { server.enqueue(new MockResponse() .setBody("abc\r\nYOU SHOULD NOT SEE THIS") .clearHeaders() @@ -680,7 +691,7 @@ public final class URLConnectionTest extends TestCase { assertContent("abc", server.getUrl("/").openConnection()); } - public void testContentDisagreesWithChunkedHeader() throws IOException { + @Test public void contentDisagreesWithChunkedHeader() throws IOException { MockResponse mockResponse = new MockResponse(); mockResponse.setChunkedBody("abc", 3); ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); @@ -696,16 +707,16 @@ public final class URLConnectionTest extends TestCase { assertContent("abc", server.getUrl("/").openConnection()); } - public void testConnectViaHttpProxyToHttpsUsingProxyArgWithNoProxy() throws Exception { - testConnectViaDirectProxyToHttps(ProxyConfig.NO_PROXY); + @Test public void connectViaHttpProxyToHttpsUsingProxyArgWithNoProxy() throws Exception { + checkConnectViaDirectProxyToHttps(ProxyConfig.NO_PROXY); } - public void testConnectViaHttpProxyToHttpsUsingHttpProxySystemProperty() throws Exception { + @Test public void connectViaHttpProxyToHttpsUsingHttpProxySystemProperty() throws Exception { // https should not use http proxy - testConnectViaDirectProxyToHttps(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY); + checkConnectViaDirectProxyToHttps(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY); } - private void testConnectViaDirectProxyToHttps(ProxyConfig proxyConfig) throws Exception { + private void checkConnectViaDirectProxyToHttps(ProxyConfig proxyConfig) throws Exception { TestSSLContext testSSLContext = createDefaultTestSSLContext(); server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); @@ -723,27 +734,27 @@ public final class URLConnectionTest extends TestCase { } - public void testConnectViaHttpProxyToHttpsUsingProxyArg() throws Exception { - testConnectViaHttpProxyToHttps(ProxyConfig.CREATE_ARG); + @Test public void connectViaHttpProxyToHttpsUsingProxyArg() throws Exception { + checkConnectViaHttpProxyToHttps(ProxyConfig.CREATE_ARG); } /** * We weren't honoring all of the appropriate proxy system properties when * connecting via HTTPS. http://b/3097518 */ - public void testConnectViaHttpProxyToHttpsUsingProxySystemProperty() throws Exception { - testConnectViaHttpProxyToHttps(ProxyConfig.PROXY_SYSTEM_PROPERTY); + @Test public void connectViaHttpProxyToHttpsUsingProxySystemProperty() throws Exception { + checkConnectViaHttpProxyToHttps(ProxyConfig.PROXY_SYSTEM_PROPERTY); } - public void testConnectViaHttpProxyToHttpsUsingHttpsProxySystemProperty() throws Exception { - testConnectViaHttpProxyToHttps(ProxyConfig.HTTPS_PROXY_SYSTEM_PROPERTY); + @Test public void connectViaHttpProxyToHttpsUsingHttpsProxySystemProperty() throws Exception { + checkConnectViaHttpProxyToHttps(ProxyConfig.HTTPS_PROXY_SYSTEM_PROPERTY); } /** * We were verifying the wrong hostname when connecting to an HTTPS site * through a proxy. http://b/3097277 */ - private void testConnectViaHttpProxyToHttps(ProxyConfig proxyConfig) throws Exception { + private void checkConnectViaHttpProxyToHttps(ProxyConfig proxyConfig) throws Exception { TestSSLContext testSSLContext = createDefaultTestSSLContext(); RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier(); @@ -776,7 +787,8 @@ public final class URLConnectionTest extends TestCase { /** * Tolerate bad https proxy response when using HttpResponseCache. http://b/6754912 */ - public void testConnectViaHttpProxyToHttpsUsingBadProxyAndHttpResponseCache() throws Exception { + @Test public void connectViaHttpProxyToHttpsUsingBadProxyAndHttpResponseCache() + throws Exception { TestSSLContext testSSLContext = createDefaultTestSSLContext(); initResponseCache(); @@ -817,7 +829,7 @@ public final class URLConnectionTest extends TestCase { * Test Etag headers are returned correctly when a client-side cache is not installed. * https://code.google.com/p/android/issues/detail?id=108949 */ - public void testEtagHeaders_uncached() throws Exception { + @Test public void etagHeaders_uncached() throws Exception { final String etagValue1 = "686897696a7c876b7e"; final String body1 = "Response with etag 1"; final String etagValue2 = "686897696a7c876b7f"; @@ -854,32 +866,100 @@ public final class URLConnectionTest extends TestCase { assertNull(request.getHeader("If-None-Match")); } + @Test public void getFileNameMap_null() { + assertThrowsNpe(() -> URLConnection.getFileNameMap().getContentTypeFor(null)); + assertThrowsNpe(() -> URLConnection.guessContentTypeFromName(null)); + } + + private static void assertThrowsNpe(Runnable runnable) { + try { + runnable.run(); + fail(); + } catch (NullPointerException expected) { + } + } + /** * Checks that paths ending in '/' (directory listings) are identified as HTML. */ - public void testGetFileNameMap_directory() { + @Test public void getFileNameMap_directory() { checkFileNameMap("text/html", "/directory/path/"); checkFileNameMap("text/html", "http://example.com/path/"); + checkFileNameMap("text/html", "http://example.com/path/#fragment"); } - public void testGetFileNameMap_simple() { + @Test public void getFileNameMap_simple() { checkFileNameMap("text/plain", "example.txt"); checkFileNameMap("text/plain", "example.com/file.txt"); } + @Test public void getFileNameMap_compositeExtension() { + checkFileNameMap("text/plain", "example.html.txt"); // html.txt isn't known, but txt is + checkFileNameMap("application/x-font-pcf", "filename.pcf.Z"); // pcf.Z is known + } + + @Test public void getFileNameMap_compositeExtension_customMimeMap() { + MimeMap testMimeMap = MimeMap.builder() + .put("text/html", "html") + .put("application/gzip", "gz") + .put("application/tar+gzip", "tar.gz") + .build(); + MimeMap defaultMimeMap = MimeMap.getDefault(); + MimeMap.setDefaultSupplier(() -> testMimeMap); + try { + checkFileNameMap("application/gzip", "filename.gz"); + checkFileNameMap("application/gzip", "filename.foobar.gz"); + checkFileNameMap("application/gzip", "filename.html.gz"); + checkFileNameMap("application/tar+gzip", "filename.tar.gz"); // tar.gz is found + } finally { + MimeMap.setDefaultSupplier(() -> defaultMimeMap); + } + } + + /** + * Checks that as long as there are no '.' or '/', a file name that matches + * a known extension is interpreted as that extension, as if it was preceded by ".". + */ + @Test public void getFileNameMap_plainExtension() { + checkFileNameMap("text/plain", "txt"); + checkFileNameMap("text/plain", "txt#fragment"); + checkFileNameMap(null, "example.com/txt"); + checkFileNameMap(null, "example.com/txt#fragment"); + checkFileNameMap(null, "example/txt"); + checkFileNameMap(null, "http://example/txt#fragment"); + } + /** - * Checks that the *last* dot is considered for determining a file extension. + * Checks cases where there's a '.' in the fragment, path or as an earlier path + * of a file name (only the last '.' that is part of the filename should count). */ - public void testGetFileNameMap_multipleDots() { + @Test public void getFileNameMap_dotsInOtherPlaces() { + // '.' in path checkFileNameMap("text/html", "example.com/foo.txt/bar.html"); checkFileNameMap("text/plain", "example.com/foo.html/bar.txt"); + checkFileNameMap(null, "/path.txt/noextensionfound"); + + // '.' earlier in filename checkFileNameMap("text/plain", "example.html.txt"); + + // '.' in fragment + checkFileNameMap(null, "/path/noextensionfound#fragment.html"); + + // multiple additional dots that shouldn't count + checkFileNameMap("text/plain", "/path.html/foo/../readme.html.txt#fragment.html"); + } + + @Test public void getFileNameMap_multipleHashCharacters() { + // Based on RFC 3986, URLs can only contain a single '#' but android.net.Uri + // considers the fragment to start after the first, rather than the last, '#'. + // We check that FileNameMap cuts off after the first '#', consistent with Uri. + checkFileNameMap(null, "/path/noextensionfound#frag.txt#ment.html"); } /** * Checks that fragments are stripped when determining file extension. */ - public void testGetFileNameMap_fragment() { + @Test public void getFileNameMap_fragment() { checkFileNameMap("text/plain", "example.txt#fragment"); checkFileNameMap("text/plain", "example.com/path/example.txt#fragment"); } @@ -889,7 +969,7 @@ public final class URLConnectionTest extends TestCase { * of file type. * This matches RI behavior, but it'd be reasonable to change behavior here. */ - public void testGetFileNameMap_queryParameter() { + @Test public void getFileNameMap_queryParameter() { checkFileNameMap(null, "example.txt?key=value"); checkFileNameMap(null, "example.txt?key=value#fragment"); } @@ -908,7 +988,7 @@ public final class URLConnectionTest extends TestCase { * data is unchanged. * https://code.google.com/p/android/issues/detail?id=108949 */ - public void testEtagHeaders_cachedWithServerHit() throws Exception { + @Test public void etagHeaders_cachedWithServerHit() throws Exception { final String etagValue = "686897696a7c876b7e"; final String body = "Response with etag"; @@ -951,7 +1031,7 @@ public final class URLConnectionTest extends TestCase { * data has changed. * https://code.google.com/p/android/issues/detail?id=108949 */ - public void testEtagHeaders_cachedWithServerMiss() throws Exception { + @Test public void etagHeaders_cachedWithServerMiss() throws Exception { final String etagValue1 = "686897696a7c876b7e"; final String body1 = "Response with etag 1"; final String etagValue2 = "686897696a7c876b7f"; @@ -998,7 +1078,7 @@ public final class URLConnectionTest extends TestCase { /** * Test which headers are sent unencrypted to the HTTP proxy. */ - public void testProxyConnectIncludesProxyHeadersOnly() + @Test public void proxyConnectIncludesProxyHeadersOnly() throws IOException, InterruptedException { Authenticator.setDefault(new SimpleAuthenticator()); RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier(); @@ -1052,7 +1132,7 @@ public final class URLConnectionTest extends TestCase { assertEquals(Arrays.asList("verify android.com"), hostnameVerifier.calls); } - public void testProxyAuthenticateOnConnect() throws Exception { + @Test public void proxyAuthenticateOnConnect() throws Exception { Authenticator.setDefault(new SimpleAuthenticator()); TestSSLContext testSSLContext = createDefaultTestSSLContext(); server.useHttps(testSSLContext.serverContext.getSocketFactory(), true); @@ -1088,7 +1168,7 @@ public final class URLConnectionTest extends TestCase { // Don't disconnect after building a tunnel with CONNECT // http://code.google.com/p/android/issues/detail?id=37221 - public void testProxyWithConnectionClose() throws IOException { + @Test public void proxyWithConnectionClose() throws IOException { TestSSLContext testSSLContext = createDefaultTestSSLContext(); server.useHttps(testSSLContext.serverContext.getSocketFactory(), true); server.enqueue(new MockResponse() @@ -1107,7 +1187,7 @@ public final class URLConnectionTest extends TestCase { assertContent("this response comes via a proxy", connection); } - public void testDisconnectedConnection() throws IOException { + @Test public void disconnectedConnection() throws IOException { server.enqueue(new MockResponse() .throttleBody(2, 100, TimeUnit.MILLISECONDS) .setBody("ABCD")); @@ -1127,23 +1207,122 @@ public final class URLConnectionTest extends TestCase { } } + @Test public void disconnectFromBackgroundThread_blockedRead_beforeHeader() + throws IOException { + QueueDispatcher dispatcher = new QueueDispatcher() { + @Override + public MockResponse dispatch(RecordedRequest request) throws InterruptedException { + Thread.sleep(6000); + return super.dispatch(request); + } + }; + server.setDispatcher(dispatcher); + server.enqueue(new MockResponse().setHeader("Key", "Value").setBody("Response body")); + checkDisconnectFromBackgroundThread_blockedRead(2000, null /* disconnectMillis */); + } + + @Test public void disconnectFromBackgroundThread_blockedRead_beforeBody() + throws IOException { + server.enqueue(new MockResponse().setHeader("Key", "Value") + .setBody("Response body").setBodyDelayTimeMs(6000)); + checkDisconnectFromBackgroundThread_blockedRead(2000, "" /* disconnectMillis */); + } + + /** + * + * @throws IOException + */ + @Test public void disconnectFromBackgroundThread_blockedRead_duringBody() + throws IOException { + server.enqueue(new MockResponse().setHeader("Key", "Value") + .setBody("Response body").throttleBody(3, 1333, TimeUnit.MILLISECONDS)); + // After 2 sec, we should have read about 6 bytes (we sleep 1333msec after every 3 bytes). + checkDisconnectFromBackgroundThread_blockedRead(2000, "Respon"); + } + + /** + * Checks that {@link HttpURLConnection#disconnect() disconnecting} a blocked read + * from a background thread unblocks the reading thread quickly and that the headers/body + * read so far are as given. + * + * The disconnect happens after approximately {@code disconnectMillis} msec (between half + * and double that is tolerated), so the server must already be set up such that reading + * the headers and the entire request takes comfortably more than that, eg. + * {@code 3 * disconnectMillis}. + * + * @param disconnectMillis number of milliseconds until the connection should be + * {@link HttpURLConnection#disconnect() disconnected} by a background thread. + * @param expectedResponseContent The part of the body that is expected to have been read by + * the time the connection is disconnected, or null if not even the headers + * are expected to have been read at the time. + * @throws IOException if one occurs unexpectedly while establishing the connection. + */ + private void checkDisconnectFromBackgroundThread_blockedRead( + long disconnectMillis, String expectedResponseContent) throws IOException { + server.play(); + HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); + + Thread disconnectThread = new Thread("Disconnect after " + disconnectMillis + "msec") { + @Override + public void run() { + try { + Thread.sleep(disconnectMillis); + } catch (InterruptedException e) { + // Even if an AssertionFailedError on this background thread doesn't + // cause the test to fail directly, we'd still prematurely disconnect() + // and that would (if significant) be detected further down by the + // assertion on the number of elapsed milliseconds observed by the + // main thread. + fail("Unexpectedly interrupted: " + e); + } + connection.disconnect(); + } + }; + + ByteArrayOutputStream auditStream = new ByteArrayOutputStream(); + AuditInputStream inputStream = null; + boolean headerRead = false; + long start = System.currentTimeMillis(); + disconnectThread.start(); + try { + inputStream = new AuditInputStream(connection.getInputStream(), auditStream); + connection.getHeaderFields(); + headerRead = true; + readAscii(inputStream); + fail("Didn't expect to successfully read all of the data"); + } catch (IOException expected) { + } finally { + TestIoUtils.closeQuietly(inputStream); + } + long elapsed = System.currentTimeMillis() - start; + + assertTrue("Expected approx. " + disconnectMillis + " msec elapsed, got " + elapsed, + disconnectMillis / 2 <= elapsed && elapsed <= 2 * disconnectMillis); + String readBody = new String(auditStream.toByteArray(), StandardCharsets.UTF_8); + + String actualResponse = headerRead ? readBody : null; + assertEquals("Headers read: " + headerRead + "; read response body: " + readBody, + expectedResponseContent, actualResponse); + } + + // http://b/33763156 - public void testDisconnectDuringConnect_getInputStream() throws IOException { + @Test public void disconnectDuringConnect_getInputStream() throws IOException { checkDisconnectDuringConnect(HttpURLConnection::getInputStream); } // http://b/33763156 - public void testDisconnectDuringConnect_getOutputStream() throws IOException { + @Test public void disconnectDuringConnect_getOutputStream() throws IOException { checkDisconnectDuringConnect(HttpURLConnection::getOutputStream); } // http://b/33763156 - public void testDisconnectDuringConnect_getResponseCode() throws IOException { + @Test public void disconnectDuringConnect_getResponseCode() throws IOException { checkDisconnectDuringConnect(HttpURLConnection::getResponseCode); } // http://b/33763156 - public void testDisconnectDuringConnect_getResponseMessage() throws IOException { + @Test public void disconnectDuringConnect_getResponseMessage() throws IOException { checkDisconnectDuringConnect(HttpURLConnection::getResponseMessage); } @@ -1188,7 +1367,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testDisconnectBeforeConnect() throws IOException { + @Test public void disconnectBeforeConnect() throws IOException { server.enqueue(new MockResponse().setBody("A")); server.play(); @@ -1199,7 +1378,7 @@ public final class URLConnectionTest extends TestCase { assertEquals(200, connection.getResponseCode()); } - public void testDisconnectAfterOnlyResponseCodeCausesNoCloseGuardWarning() throws IOException { + @Test public void disconnectAfterOnlyResponseCodeCausesNoCloseGuardWarning() throws IOException { server.enqueue(new MockResponse() .setBody(gzip("ABCABCABC".getBytes("UTF-8"))) .addHeader("Content-Encoding: gzip")); @@ -1213,7 +1392,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testDefaultRequestProperty() throws Exception { + @Test public void defaultRequestProperty() throws Exception { URLConnection.setDefaultRequestProperty("X-testSetDefaultRequestProperty", "A"); assertNull(URLConnection.getDefaultRequestProperty("X-setDefaultRequestProperty")); } @@ -1223,7 +1402,7 @@ public final class URLConnectionTest extends TestCase { * exhausted before {@code count} characters can be read, the remaining * characters are returned and the stream is closed. */ - private String readAscii(InputStream in, int count) throws IOException { + private static String readAscii(InputStream in, int count) throws IOException { StringBuilder result = new StringBuilder(); for (int i = 0; i < count; i++) { int value = in.read(); @@ -1236,15 +1415,19 @@ public final class URLConnectionTest extends TestCase { return result.toString(); } - public void testMarkAndResetWithContentLengthHeader() throws IOException { + private static String readAscii(InputStream in) throws IOException { + return readAscii(in, Integer.MAX_VALUE); + } + + @Test public void markAndResetWithContentLengthHeader() throws IOException { testMarkAndReset(TransferKind.FIXED_LENGTH); } - public void testMarkAndResetWithChunkedEncoding() throws IOException { + @Test public void markAndResetWithChunkedEncoding() throws IOException { testMarkAndReset(TransferKind.CHUNKED); } - public void testMarkAndResetWithNoLengthHeaders() throws IOException { + @Test public void markAndResetWithNoLengthHeaders() throws IOException { testMarkAndReset(TransferKind.END_OF_STREAM); } @@ -1264,7 +1447,7 @@ public final class URLConnectionTest extends TestCase { fail(); } catch (IOException expected) { } - assertEquals("FGHIJKLMNOPQRSTUVWXYZ", readAscii(in, Integer.MAX_VALUE)); + assertEquals("FGHIJKLMNOPQRSTUVWXYZ", readAscii(in)); assertContent("ABCDEFGHIJKLMNOPQRSTUVWXYZ", server.getUrl("/").openConnection()); } @@ -1273,7 +1456,7 @@ public final class URLConnectionTest extends TestCase { * code 401. This causes a new HTTP request to be issued for every call into * the URLConnection. */ - public void testUnauthorizedResponseHandling() throws IOException { + @Test public void unauthorizedResponseHandling() throws IOException { MockResponse response = new MockResponse() .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") .setResponseCode(401) // UNAUTHORIZED @@ -1292,7 +1475,7 @@ public final class URLConnectionTest extends TestCase { assertEquals(1, server.getRequestCount()); } - public void testNonHexChunkSize() throws IOException { + @Test public void nonHexChunkSize() throws IOException { server.enqueue(new MockResponse() .setBody("5\r\nABCDE\r\nG\r\nFGHIJKLMNOPQRSTU\r\n0\r\n\r\n") .clearHeaders() @@ -1301,13 +1484,13 @@ public final class URLConnectionTest extends TestCase { URLConnection connection = server.getUrl("/").openConnection(); try { - readAscii(connection.getInputStream(), Integer.MAX_VALUE); + readAscii(connection.getInputStream()); fail(); } catch (IOException e) { } } - public void testMissingChunkBody() throws IOException { + @Test public void missingChunkBody() throws IOException { server.enqueue(new MockResponse() .setBody("5") .clearHeaders() @@ -1317,7 +1500,7 @@ public final class URLConnectionTest extends TestCase { URLConnection connection = server.getUrl("/").openConnection(); try { - readAscii(connection.getInputStream(), Integer.MAX_VALUE); + readAscii(connection.getInputStream()); fail(); } catch (IOException e) { } @@ -1328,14 +1511,14 @@ public final class URLConnectionTest extends TestCase { * behavior in not required by the API, so a failure of this test does not * imply a bug in the implementation. */ - public void testGzipEncodingEnabledByDefault() throws IOException, InterruptedException { + @Test public void gzipEncodingEnabledByDefault() throws IOException, InterruptedException { server.enqueue(new MockResponse() .setBody(gzip("ABCABCABC".getBytes("UTF-8"))) .addHeader("Content-Encoding: gzip")); server.play(); URLConnection connection = server.getUrl("/").openConnection(); - assertEquals("ABCABCABC", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("ABCABCABC", readAscii(connection.getInputStream())); assertNull(connection.getContentEncoding()); assertEquals(-1, connection.getContentLength()); @@ -1343,7 +1526,7 @@ public final class URLConnectionTest extends TestCase { assertContains(request.getHeaders(), "Accept-Encoding: gzip"); } - public void testClientConfiguredGzipContentEncoding() throws Exception { + @Test public void clientConfiguredGzipContentEncoding() throws Exception { byte[] bodyBytes = gzip("ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes("UTF-8")); server.enqueue(new MockResponse() .setBody(bodyBytes) @@ -1354,7 +1537,7 @@ public final class URLConnectionTest extends TestCase { URLConnection connection = server.getUrl("/").openConnection(); connection.addRequestProperty("Accept-Encoding", "gzip"); InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream()); - assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", readAscii(gunzippedIn, Integer.MAX_VALUE)); + assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", readAscii(gunzippedIn)); assertEquals(bodyBytes.length, connection.getContentLength()); RecordedRequest request = server.takeRequest(); @@ -1362,15 +1545,15 @@ public final class URLConnectionTest extends TestCase { assertEquals("gzip", connection.getContentEncoding()); } - public void testGzipAndConnectionReuseWithFixedLength() throws Exception { + @Test public void gzipAndConnectionReuseWithFixedLength() throws Exception { testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.FIXED_LENGTH); } - public void testGzipAndConnectionReuseWithChunkedEncoding() throws Exception { + @Test public void gzipAndConnectionReuseWithChunkedEncoding() throws Exception { testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.CHUNKED); } - public void testClientConfiguredCustomContentEncoding() throws Exception { + @Test public void clientConfiguredCustomContentEncoding() throws Exception { server.enqueue(new MockResponse() .setBody("ABCDE") .addHeader("Content-Encoding: custom")); @@ -1378,7 +1561,7 @@ public final class URLConnectionTest extends TestCase { URLConnection connection = server.getUrl("/").openConnection(); connection.addRequestProperty("Accept-Encoding", "custom"); - assertEquals("ABCDE", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("ABCDE", readAscii(connection.getInputStream())); RecordedRequest request = server.takeRequest(); assertContains(request.getHeaders(), "Accept-Encoding: custom"); @@ -1403,11 +1586,11 @@ public final class URLConnectionTest extends TestCase { URLConnection connection = server.getUrl("/").openConnection(); connection.addRequestProperty("Accept-Encoding", "gzip"); InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream()); - assertEquals("one (gzipped)", readAscii(gunzippedIn, Integer.MAX_VALUE)); + assertEquals("one (gzipped)", readAscii(gunzippedIn)); assertEquals(0, server.takeRequest().getSequenceNumber()); connection = server.getUrl("/").openConnection(); - assertEquals("two (identity)", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("two (identity)", readAscii(connection.getInputStream())); assertEquals(1, server.takeRequest().getSequenceNumber()); } @@ -1415,7 +1598,7 @@ public final class URLConnectionTest extends TestCase { * Test that HEAD requests don't have a body regardless of the response * headers. http://code.google.com/p/android/issues/detail?id=24672 */ - public void testHeadAndContentLength() throws Exception { + @Test public void headAndContentLength() throws Exception { server.enqueue(new MockResponse() .clearHeaders() .addHeader("Content-Length: 100")); @@ -1428,7 +1611,7 @@ public final class URLConnectionTest extends TestCase { assertContent("", connection1); HttpURLConnection connection2 = (HttpURLConnection) server.getUrl("/").openConnection(); - assertEquals("A", readAscii(connection2.getInputStream(), Integer.MAX_VALUE)); + assertEquals("A", readAscii(connection2.getInputStream())); assertEquals(0, server.takeRequest().getSequenceNumber()); assertEquals(1, server.takeRequest().getSequenceNumber()); @@ -1441,7 +1624,7 @@ public final class URLConnectionTest extends TestCase { * the fixed chunk size. Instead, we check that chunking takes place * and we force the chunk size with flushes. */ - public void testSetChunkedStreamingMode() throws IOException, InterruptedException { + @Test public void setChunkedStreamingMode() throws IOException, InterruptedException { server.enqueue(new MockResponse()); server.play(); @@ -1468,11 +1651,11 @@ public final class URLConnectionTest extends TestCase { assertEquals(Arrays.asList(3, 3, 2), request.getChunkSizes()); } - public void testAuthenticateWithFixedLengthStreaming() throws Exception { + @Test public void authenticateWithFixedLengthStreaming() throws Exception { testAuthenticateWithStreamingPost(StreamingMode.FIXED_LENGTH); } - public void testAuthenticateWithChunkedStreaming() throws Exception { + @Test public void authenticateWithChunkedStreaming() throws Exception { testAuthenticateWithStreamingPost(StreamingMode.CHUNKED); } @@ -1508,7 +1691,7 @@ public final class URLConnectionTest extends TestCase { assertEquals(Arrays.toString(requestBody), Arrays.toString(request.getBody())); } - public void testSetValidRequestMethod() throws Exception { + @Test public void setValidRequestMethod() throws Exception { server.play(); assertValidRequestMethod("GET"); assertValidRequestMethod("DELETE"); @@ -1525,12 +1708,12 @@ public final class URLConnectionTest extends TestCase { assertEquals(requestMethod, connection.getRequestMethod()); } - public void testSetInvalidRequestMethodLowercase() throws Exception { + @Test public void setInvalidRequestMethodLowercase() throws Exception { server.play(); assertInvalidRequestMethod("get"); } - public void testSetInvalidRequestMethodConnect() throws Exception { + @Test public void setInvalidRequestMethodConnect() throws Exception { server.play(); assertInvalidRequestMethod("CONNECT"); } @@ -1544,7 +1727,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testCannotSetNegativeFixedLengthStreamingMode() throws Exception { + @Test public void cannotSetNegativeFixedLengthStreamingMode() throws Exception { server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); try { @@ -1554,17 +1737,17 @@ public final class URLConnectionTest extends TestCase { } } - public void testCanSetNegativeChunkedStreamingMode() throws Exception { + @Test public void canSetNegativeChunkedStreamingMode() throws Exception { server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); connection.setChunkedStreamingMode(-2); } - public void testCannotSetFixedLengthStreamingModeAfterConnect() throws Exception { + @Test public void cannotSetFixedLengthStreamingModeAfterConnect() throws Exception { server.enqueue(new MockResponse().setBody("A")); server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); - assertEquals("A", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("A", readAscii(connection.getInputStream())); try { connection.setFixedLengthStreamingMode(1); fail(); @@ -1572,11 +1755,11 @@ public final class URLConnectionTest extends TestCase { } } - public void testCannotSetChunkedStreamingModeAfterConnect() throws Exception { + @Test public void cannotSetChunkedStreamingModeAfterConnect() throws Exception { server.enqueue(new MockResponse().setBody("A")); server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); - assertEquals("A", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("A", readAscii(connection.getInputStream())); try { connection.setChunkedStreamingMode(1); fail(); @@ -1584,7 +1767,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testCannotSetFixedLengthStreamingModeAfterChunkedStreamingMode() throws Exception { + @Test public void cannotSetFixedLengthStreamingModeAfterChunkedStreamingMode() throws Exception { server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); connection.setChunkedStreamingMode(1); @@ -1595,7 +1778,8 @@ public final class URLConnectionTest extends TestCase { } } - public void testCannotSetChunkedStreamingModeAfterFixedLengthStreamingMode() throws Exception { + @Test public void cannotSetChunkedStreamingModeAfterFixedLengthStreamingMode() + throws Exception { server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); connection.setFixedLengthStreamingMode(1); @@ -1606,11 +1790,11 @@ public final class URLConnectionTest extends TestCase { } } - public void testSecureFixedLengthStreaming() throws Exception { + @Test public void secureFixedLengthStreaming() throws Exception { testSecureStreamingPost(StreamingMode.FIXED_LENGTH); } - public void testSecureChunkedStreaming() throws Exception { + @Test public void secureChunkedStreaming() throws Exception { testSecureStreamingPost(StreamingMode.CHUNKED); } @@ -1636,7 +1820,7 @@ public final class URLConnectionTest extends TestCase { OutputStream outputStream = connection.getOutputStream(); outputStream.write(requestBody); outputStream.close(); - assertEquals("Success!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("Success!", readAscii(connection.getInputStream())); RecordedRequest request = server.takeRequest(); assertEquals("POST / HTTP/1.1", request.getRequestLine()); @@ -1652,7 +1836,7 @@ public final class URLConnectionTest extends TestCase { FIXED_LENGTH, CHUNKED } - public void testAuthenticateWithPost() throws Exception { + @Test public void authenticateWithPost() throws Exception { MockResponse pleaseAuthenticate = new MockResponse() .setResponseCode(401) .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") @@ -1672,7 +1856,7 @@ public final class URLConnectionTest extends TestCase { OutputStream outputStream = connection.getOutputStream(); outputStream.write(requestBody); outputStream.close(); - assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("Successful auth!", readAscii(connection.getInputStream())); // no authorization header for the first request... RecordedRequest request = server.takeRequest(); @@ -1688,7 +1872,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testAuthenticateWithGet() throws Exception { + @Test public void authenticateWithGet() throws Exception { MockResponse pleaseAuthenticate = new MockResponse() .setResponseCode(401) .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") @@ -1704,7 +1888,7 @@ public final class URLConnectionTest extends TestCase { SimpleAuthenticator authenticator = new SimpleAuthenticator(); Authenticator.setDefault(authenticator); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); - assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("Successful auth!", readAscii(connection.getInputStream())); assertEquals(Authenticator.RequestorType.SERVER, authenticator.requestorType); assertEquals(server.getPort(), authenticator.requestingPort); assertEquals(InetAddress.getByName(server.getHostName()), authenticator.requestingSite); @@ -1726,7 +1910,7 @@ public final class URLConnectionTest extends TestCase { } // bug 11473660 - public void testAuthenticateWithLowerCaseHeadersAndScheme() throws Exception { + @Test public void authenticateWithLowerCaseHeadersAndScheme() throws Exception { MockResponse pleaseAuthenticate = new MockResponse() .setResponseCode(401) .addHeader("www-authenticate: basic realm=\"protected area\"") @@ -1742,7 +1926,7 @@ public final class URLConnectionTest extends TestCase { SimpleAuthenticator authenticator = new SimpleAuthenticator(); Authenticator.setDefault(authenticator); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); - assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("Successful auth!", readAscii(connection.getInputStream())); assertEquals(Authenticator.RequestorType.SERVER, authenticator.requestorType); assertEquals(server.getPort(), authenticator.requestingPort); assertEquals(InetAddress.getByName(server.getHostName()), authenticator.requestingSite); @@ -1752,7 +1936,7 @@ public final class URLConnectionTest extends TestCase { } // http://code.google.com/p/android/issues/detail?id=19081 - public void testAuthenticateWithCommaSeparatedAuthenticationMethods() throws Exception { + @Test public void authenticateWithCommaSeparatedAuthenticationMethods() throws Exception { server.enqueue(new MockResponse() .setResponseCode(401) .addHeader("WWW-Authenticate: Scheme1 realm=\"a\", Basic realm=\"b\", " @@ -1765,7 +1949,7 @@ public final class URLConnectionTest extends TestCase { authenticator.expectedPrompt = "b"; Authenticator.setDefault(authenticator); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); - assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("Successful auth!", readAscii(connection.getInputStream())); assertContainsNoneMatching(server.takeRequest().getHeaders(), "Authorization: .*"); assertContains(server.takeRequest().getHeaders(), @@ -1773,7 +1957,7 @@ public final class URLConnectionTest extends TestCase { assertEquals("Basic", authenticator.requestingScheme); } - public void testAuthenticateWithMultipleAuthenticationHeaders() throws Exception { + @Test public void authenticateWithMultipleAuthenticationHeaders() throws Exception { server.enqueue(new MockResponse() .setResponseCode(401) .addHeader("WWW-Authenticate: Scheme1 realm=\"a\"") @@ -1787,7 +1971,7 @@ public final class URLConnectionTest extends TestCase { authenticator.expectedPrompt = "b"; Authenticator.setDefault(authenticator); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); - assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("Successful auth!", readAscii(connection.getInputStream())); assertContainsNoneMatching(server.takeRequest().getHeaders(), "Authorization: .*"); assertContains(server.takeRequest().getHeaders(), @@ -1795,15 +1979,15 @@ public final class URLConnectionTest extends TestCase { assertEquals("Basic", authenticator.requestingScheme); } - public void testRedirectedWithChunkedEncoding() throws Exception { + @Test public void redirectedWithChunkedEncoding() throws Exception { testRedirected(TransferKind.CHUNKED, true); } - public void testRedirectedWithContentLengthHeader() throws Exception { + @Test public void redirectedWithContentLengthHeader() throws Exception { testRedirected(TransferKind.FIXED_LENGTH, true); } - public void testRedirectedWithNoLengthHeaders() throws Exception { + @Test public void redirectedWithNoLengthHeaders() throws Exception { testRedirected(TransferKind.END_OF_STREAM, false); } @@ -1817,8 +2001,7 @@ public final class URLConnectionTest extends TestCase { server.play(); URLConnection connection = server.getUrl("/").openConnection(); - assertEquals("This is the new location!", - readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("This is the new location!", readAscii(connection.getInputStream())); RecordedRequest first = server.takeRequest(); assertEquals("GET / HTTP/1.1", first.getRequestLine()); @@ -1829,7 +2012,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testRedirectedOnHttps() throws IOException, InterruptedException { + @Test public void redirectedOnHttps() throws IOException, InterruptedException { TestSSLContext testSSLContext = createDefaultTestSSLContext(); server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); server.enqueue(new MockResponse() @@ -1841,8 +2024,7 @@ public final class URLConnectionTest extends TestCase { HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection(); connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); - assertEquals("This is the new location!", - readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("This is the new location!", readAscii(connection.getInputStream())); RecordedRequest first = server.takeRequest(); assertEquals("GET / HTTP/1.1", first.getRequestLine()); @@ -1851,7 +2033,7 @@ public final class URLConnectionTest extends TestCase { assertEquals("Expected connection reuse", 1, retry.getSequenceNumber()); } - public void testNotRedirectedFromHttpsToHttp() throws IOException, InterruptedException { + @Test public void notRedirectedFromHttpsToHttp() throws IOException, InterruptedException { TestSSLContext testSSLContext = createDefaultTestSSLContext(); server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); server.enqueue(new MockResponse() @@ -1862,11 +2044,10 @@ public final class URLConnectionTest extends TestCase { HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection(); connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); - assertEquals("This page has moved!", - readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("This page has moved!", readAscii(connection.getInputStream())); } - public void testNotRedirectedFromHttpToHttps() throws IOException, InterruptedException { + @Test public void notRedirectedFromHttpToHttps() throws IOException, InterruptedException { server.enqueue(new MockResponse() .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) .addHeader("Location: https://anyhost/foo") @@ -1874,11 +2055,10 @@ public final class URLConnectionTest extends TestCase { server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); - assertEquals("This page has moved!", - readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("This page has moved!", readAscii(connection.getInputStream())); } - public void testRedirectToAnotherOriginServer() throws Exception { + @Test public void redirectToAnotherOriginServer() throws Exception { MockWebServer server2 = new MockWebServer(); server2.enqueue(new MockResponse().setBody("This is the 2nd server!")); server2.play(); @@ -1891,13 +2071,11 @@ public final class URLConnectionTest extends TestCase { server.play(); URLConnection connection = server.getUrl("/").openConnection(); - assertEquals("This is the 2nd server!", - readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("This is the 2nd server!", readAscii(connection.getInputStream())); assertEquals(server2.getUrl("/"), connection.getURL()); // make sure the first server was careful to recycle the connection - assertEquals("This is the first server again!", - readAscii(server.getUrl("/").openStream(), Integer.MAX_VALUE)); + assertEquals("This is the first server again!", readAscii(server.getUrl("/").openStream())); RecordedRequest first = server.takeRequest(); assertContains(first.getHeaders(), "Host: " + hostName + ":" + server.getPort()); @@ -1911,7 +2089,7 @@ public final class URLConnectionTest extends TestCase { // http://b/27590872 - assert we do not throw a runtime exception if a server responds with // a location that cannot be represented directly by URI. - public void testRedirectWithInvalidRedirectUrl() throws Exception { + @Test public void redirectWithInvalidRedirectUrl() throws Exception { // The first server hosts a redirect to a second. We need two so that the ProxySelector // installed is used for the redirect. Otherwise the second request will be handled via the // existing keep-alive connection. @@ -1963,7 +2141,7 @@ public final class URLConnectionTest extends TestCase { try { HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); - assertEquals("Target", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("Target", readAscii(connection.getInputStream())); // Inspect the redirect request to see what request was actually made. RecordedRequest actualRequest = server2.takeRequest(); @@ -1981,7 +2159,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testInstanceFollowsRedirects() throws Exception { + @Test public void instanceFollowsRedirects() throws Exception { testInstanceFollowsRedirects("http://www.google.com/"); testInstanceFollowsRedirects("https://www.google.com/"); } @@ -1995,7 +2173,7 @@ public final class URLConnectionTest extends TestCase { assertFalse(urlConnection.getInstanceFollowRedirects()); } - public void testFollowRedirects() throws Exception { + @Test public void followRedirects() throws Exception { testFollowRedirects("http://www.google.com/"); testFollowRedirects("https://www.google.com/"); } @@ -2020,20 +2198,20 @@ public final class URLConnectionTest extends TestCase { } } - public void testResponse300MultipleChoiceWithPost() throws Exception { + @Test public void response300MultipleChoiceWithPost() throws Exception { // Chrome doesn't follow the redirect, but Firefox and the RI both do testResponseRedirectedWithPost(HttpURLConnection.HTTP_MULT_CHOICE); } - public void testResponse301MovedPermanentlyWithPost() throws Exception { + @Test public void response301MovedPermanentlyWithPost() throws Exception { testResponseRedirectedWithPost(HttpURLConnection.HTTP_MOVED_PERM); } - public void testResponse302MovedTemporarilyWithPost() throws Exception { + @Test public void response302MovedTemporarilyWithPost() throws Exception { testResponseRedirectedWithPost(HttpURLConnection.HTTP_MOVED_TEMP); } - public void testResponse303SeeOtherWithPost() throws Exception { + @Test public void response303SeeOtherWithPost() throws Exception { testResponseRedirectedWithPost(HttpURLConnection.HTTP_SEE_OTHER); } @@ -2051,7 +2229,7 @@ public final class URLConnectionTest extends TestCase { OutputStream outputStream = connection.getOutputStream(); outputStream.write(requestBody); outputStream.close(); - assertEquals("Page 2", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("Page 2", readAscii(connection.getInputStream())); assertTrue(connection.getDoOutput()); RecordedRequest page1 = server.takeRequest(); @@ -2062,7 +2240,7 @@ public final class URLConnectionTest extends TestCase { assertEquals("GET /page2 HTTP/1.1", page2.getRequestLine()); } - public void testResponse305UseProxy() throws Exception { + @Test public void response305UseProxy() throws Exception { server.play(); server.enqueue(new MockResponse() .setResponseCode(HttpURLConnection.HTTP_USE_PROXY) @@ -2072,15 +2250,14 @@ public final class URLConnectionTest extends TestCase { HttpURLConnection connection = (HttpURLConnection) server.getUrl("/foo").openConnection(); // Fails on the RI, which gets "Proxy Response" - assertEquals("This page has moved!", - readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("This page has moved!", readAscii(connection.getInputStream())); RecordedRequest page1 = server.takeRequest(); assertEquals("GET /foo HTTP/1.1", page1.getRequestLine()); assertEquals(1, server.getRequestCount()); } - public void testHttpsWithCustomTrustManager() throws Exception { + @Test public void httpsWithCustomTrustManager() throws Exception { RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier(); RecordingTrustManager trustManager = new RecordingTrustManager(); SSLContext sc = SSLContext.getInstance("TLS"); @@ -2099,9 +2276,9 @@ public final class URLConnectionTest extends TestCase { server.play(); URL url = server.getUrl("/"); - assertEquals("ABC", readAscii(url.openStream(), Integer.MAX_VALUE)); - assertEquals("DEF", readAscii(url.openStream(), Integer.MAX_VALUE)); - assertEquals("GHI", readAscii(url.openStream(), Integer.MAX_VALUE)); + assertEquals("ABC", readAscii(url.openStream())); + assertEquals("DEF", readAscii(url.openStream())); + assertEquals("GHI", readAscii(url.openStream())); assertEquals(Arrays.asList("verify " + hostName), hostnameVerifier.calls); assertEquals(Arrays.asList("checkServerTrusted [" @@ -2116,7 +2293,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testSetSSLSocketFactory_null() throws Exception { + @Test public void setSSLSocketFactory_null() throws Exception { URL url = new URL("https://google.com"); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); try { @@ -2126,7 +2303,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testSetDefaultSSLSocketFactory_null() { + @Test public void setDefaultSSLSocketFactory_null() { try { HttpsURLConnection.setDefaultSSLSocketFactory(null); fail(); @@ -2139,7 +2316,7 @@ public final class URLConnectionTest extends TestCase { * connection attempt. If a hostname resolves to multiple IPs HttpURLConnection will wait the * full timeout for each. */ - public void testConnectTimeouts() throws IOException { + @Test public void connectTimeouts() throws IOException { // During CTS tests we are limited in what host names we can depend on and unfortunately // DNS lookups are not pluggable through standard APIs. During manual testing you should be // able to change this to any name that can be resolved to multiple IPs and it should still @@ -2186,7 +2363,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testReadTimeouts() throws IOException { + @Test public void readTimeouts() throws IOException { /* * This relies on the fact that MockWebServer doesn't close the * connection after a response has been sent. This causes the client to @@ -2213,7 +2390,8 @@ public final class URLConnectionTest extends TestCase { } } - public void testSetChunkedEncodingAsRequestProperty() throws IOException, InterruptedException { + @Test public void setChunkedEncodingAsRequestProperty() + throws IOException, InterruptedException { server.enqueue(new MockResponse()); server.play(); @@ -2227,7 +2405,7 @@ public final class URLConnectionTest extends TestCase { assertEquals("ABC", new String(request.getBody(), "UTF-8")); } - public void testConnectionCloseInRequest() throws IOException, InterruptedException { + @Test public void connectionCloseInRequest() throws IOException, InterruptedException { server.enqueue(new MockResponse()); // server doesn't honor the connection: close header! server.enqueue(new MockResponse()); server.play(); @@ -2244,7 +2422,7 @@ public final class URLConnectionTest extends TestCase { 0, server.takeRequest().getSequenceNumber()); } - public void testConnectionCloseInResponse() throws IOException, InterruptedException { + @Test public void connectionCloseInResponse() throws IOException, InterruptedException { server.enqueue(new MockResponse().addHeader("Connection: close")); server.enqueue(new MockResponse()); server.play(); @@ -2260,7 +2438,7 @@ public final class URLConnectionTest extends TestCase { 0, server.takeRequest().getSequenceNumber()); } - public void testConnectionCloseWithRedirect() throws IOException, InterruptedException { + @Test public void connectionCloseWithRedirect() throws IOException, InterruptedException { MockResponse response = new MockResponse() .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) .addHeader("Location: /foo") @@ -2270,26 +2448,24 @@ public final class URLConnectionTest extends TestCase { server.play(); URLConnection connection = server.getUrl("/").openConnection(); - assertEquals("This is the new location!", - readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("This is the new location!", readAscii(connection.getInputStream())); assertEquals(0, server.takeRequest().getSequenceNumber()); assertEquals("When connection: close is used, each request should get its own connection", 0, server.takeRequest().getSequenceNumber()); } - public void testResponseCodeDisagreesWithHeaders() throws IOException, InterruptedException { + @Test public void responseCodeDisagreesWithHeaders() throws IOException, InterruptedException { server.enqueue(new MockResponse() .setResponseCode(HttpURLConnection.HTTP_NO_CONTENT) .setBody("This body is not allowed!")); server.play(); URLConnection connection = server.getUrl("/").openConnection(); - assertEquals("This body is not allowed!", - readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("This body is not allowed!", readAscii(connection.getInputStream())); } - public void testSingleByteReadIsSigned() throws IOException { + @Test public void singleByteReadIsSigned() throws IOException { server.enqueue(new MockResponse().setBody(new byte[] { -2, -1 })); server.play(); @@ -2300,15 +2476,15 @@ public final class URLConnectionTest extends TestCase { assertEquals(-1, in.read()); } - public void testFlushAfterStreamTransmittedWithChunkedEncoding() throws IOException { + @Test public void flushAfterStreamTransmittedWithChunkedEncoding() throws IOException { testFlushAfterStreamTransmitted(TransferKind.CHUNKED); } - public void testFlushAfterStreamTransmittedWithFixedLength() throws IOException { + @Test public void flushAfterStreamTransmittedWithFixedLength() throws IOException { testFlushAfterStreamTransmitted(TransferKind.FIXED_LENGTH); } - public void testFlushAfterStreamTransmittedWithNoLengthHeaders() throws IOException { + @Test public void flushAfterStreamTransmittedWithNoLengthHeaders() throws IOException { testFlushAfterStreamTransmitted(TransferKind.END_OF_STREAM); } @@ -2333,7 +2509,7 @@ public final class URLConnectionTest extends TestCase { OutputStream out = connection.getOutputStream(); out.write(upload); - assertEquals("abc", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("abc", readAscii(connection.getInputStream())); out.flush(); // dubious but permitted try { @@ -2343,7 +2519,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testGetHeadersThrows() throws IOException { + @Test public void getHeadersThrows() throws IOException { server.enqueue(new MockResponse().setSocketPolicy(DISCONNECT_AT_START)); server.play(); @@ -2361,7 +2537,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testReadTimeoutsOnRecycledConnections() throws Exception { + @Test public void readTimeoutsOnRecycledConnections() throws Exception { server.enqueue(new MockResponse().setBody("ABC")); server.play(); @@ -2370,7 +2546,7 @@ public final class URLConnectionTest extends TestCase { // Read timeout of a day, sure to cause the test to timeout and fail. connection.setReadTimeout(24 * 3600 * 1000); InputStream input = connection.getInputStream(); - assertEquals("ABC", readAscii(input, Integer.MAX_VALUE)); + assertEquals("ABC", readAscii(input)); input.close(); try { connection = server.getUrl("").openConnection(); @@ -2390,7 +2566,7 @@ public final class URLConnectionTest extends TestCase { * After M, Android's HttpURLConnection started canonicalizing hostnames to lower case, IDN * encoding and being more strict about invalid characters. */ - public void testUrlCharacterMapping() throws Exception { + @Test public void urlCharacterMapping() throws Exception { server.setDispatcher(new Dispatcher() { @Override public MockResponse dispatch(RecordedRequest request) throws InterruptedException { @@ -2613,7 +2789,7 @@ public final class URLConnectionTest extends TestCase { backdoorUrlToUri(new URL("http://host.tld/file#" + asFragment + "-x")).toString()); } - public void testHostWithNul() throws Exception { + @Test public void hostWithNul() throws Exception { URL url = new URL("http://host\u0000/"); try { url.openStream(); @@ -2624,7 +2800,7 @@ public final class URLConnectionTest extends TestCase { /** * Don't explode if the cache returns a null body. http://b/3373699 */ - public void testResponseCacheReturnsNullOutputStream() throws Exception { + @Test public void responseCacheReturnsNullOutputStream() throws Exception { final AtomicBoolean aborted = new AtomicBoolean(); ResponseCache.setDefault(new ResponseCache() { @Override public CacheResponse get(URI uri, String requestMethod, @@ -2657,7 +2833,7 @@ public final class URLConnectionTest extends TestCase { /** * http://code.google.com/p/android/issues/detail?id=14562 */ - public void testReadAfterLastByte() throws Exception { + @Test public void readAfterLastByte() throws Exception { server.enqueue(new MockResponse() .setBody("ABC") .clearHeaders() @@ -2672,15 +2848,15 @@ public final class URLConnectionTest extends TestCase { assertEquals(-1, in.read()); // throws IOException in Gingerbread } - public void testGetContent() throws Exception { + @Test public void getContent() throws Exception { server.enqueue(new MockResponse().setBody("A")); server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); InputStream in = (InputStream) connection.getContent(); - assertEquals("A", readAscii(in, Integer.MAX_VALUE)); + assertEquals("A", readAscii(in)); } - public void testGetContentOfType() throws Exception { + @Test public void getContentOfType() throws Exception { server.enqueue(new MockResponse().setBody("A")); server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); @@ -2698,7 +2874,7 @@ public final class URLConnectionTest extends TestCase { connection.disconnect(); } - public void testGetOutputStreamOnGetFails() throws Exception { + @Test public void getOutputStreamOnGetFails() throws Exception { server.enqueue(new MockResponse()); server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); @@ -2709,7 +2885,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testGetOutputAfterGetInputStreamFails() throws Exception { + @Test public void getOutputAfterGetInputStreamFails() throws Exception { server.enqueue(new MockResponse()); server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); @@ -2722,7 +2898,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testSetDoOutputOrDoInputAfterConnectFails() throws Exception { + @Test public void setDoOutputOrDoInputAfterConnectFails() throws Exception { server.enqueue(new MockResponse()); server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); @@ -2740,7 +2916,7 @@ public final class URLConnectionTest extends TestCase { connection.disconnect(); } - public void testLastModified() throws Exception { + @Test public void lastModified() throws Exception { server.enqueue(new MockResponse() .addHeader("Last-Modified", "Wed, 27 Nov 2013 11:26:00 GMT") .setBody("Hello")); @@ -2753,7 +2929,7 @@ public final class URLConnectionTest extends TestCase { assertEquals(1385551560000L, connection.getHeaderFieldDate("Last-Modified", -1)); } - public void testClientSendsContentLength() throws Exception { + @Test public void clientSendsContentLength() throws Exception { server.enqueue(new MockResponse().setBody("A")); server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); @@ -2761,12 +2937,12 @@ public final class URLConnectionTest extends TestCase { OutputStream out = connection.getOutputStream(); out.write(new byte[] { 'A', 'B', 'C' }); out.close(); - assertEquals("A", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); + assertEquals("A", readAscii(connection.getInputStream())); RecordedRequest request = server.takeRequest(); assertContains(request.getHeaders(), "Content-Length: 3"); } - public void testGetContentLengthConnects() throws Exception { + @Test public void getContentLengthConnects() throws Exception { server.enqueue(new MockResponse().setBody("ABC")); server.play(); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); @@ -2774,7 +2950,7 @@ public final class URLConnectionTest extends TestCase { connection.disconnect(); } - public void testGetContentTypeConnects() throws Exception { + @Test public void getContentTypeConnects() throws Exception { server.enqueue(new MockResponse() .addHeader("Content-Type: text/plain") .setBody("ABC")); @@ -2784,7 +2960,7 @@ public final class URLConnectionTest extends TestCase { connection.disconnect(); } - public void testGetContentEncodingConnects() throws Exception { + @Test public void getContentEncodingConnects() throws Exception { server.enqueue(new MockResponse() .addHeader("Content-Encoding: identity") .setBody("ABC")); @@ -2795,29 +2971,29 @@ public final class URLConnectionTest extends TestCase { } // http://b/4361656 - public void testUrlContainsQueryButNoPath() throws Exception { + @Test public void urlContainsQueryButNoPath() throws Exception { server.enqueue(new MockResponse().setBody("A")); server.play(); URL url = new URL("http", server.getHostName(), server.getPort(), "?query"); - assertEquals("A", readAscii(url.openConnection().getInputStream(), Integer.MAX_VALUE)); + assertEquals("A", readAscii(url.openConnection().getInputStream())); RecordedRequest request = server.takeRequest(); assertEquals("GET /?query HTTP/1.1", request.getRequestLine()); } // http://code.google.com/p/android/issues/detail?id=20442 - public void testInputStreamAvailableWithChunkedEncoding() throws Exception { - testInputStreamAvailable(TransferKind.CHUNKED); + @Test public void inputStreamAvailableWithChunkedEncoding() throws Exception { + checkInputStreamAvailable(TransferKind.CHUNKED); } - public void testInputStreamAvailableWithContentLengthHeader() throws Exception { - testInputStreamAvailable(TransferKind.FIXED_LENGTH); + @Test public void inputStreamAvailableWithContentLengthHeader() throws Exception { + checkInputStreamAvailable(TransferKind.FIXED_LENGTH); } - public void testInputStreamAvailableWithNoLengthHeaders() throws Exception { - testInputStreamAvailable(TransferKind.END_OF_STREAM); + @Test public void inputStreamAvailableWithNoLengthHeaders() throws Exception { + checkInputStreamAvailable(TransferKind.END_OF_STREAM); } - private void testInputStreamAvailable(TransferKind transferKind) throws IOException { + private void checkInputStreamAvailable(TransferKind transferKind) throws IOException { String body = "ABCDEFGH"; MockResponse response = new MockResponse(); transferKind.setBody(response, body, 4); @@ -2834,7 +3010,7 @@ public final class URLConnectionTest extends TestCase { } // http://code.google.com/p/android/issues/detail?id=28095 - public void testInvalidIpv4Address() throws Exception { + @Test public void invalidIpv4Address() throws Exception { try { URI uri = new URI("http://1111.111.111.111/index.html"); uri.toURL().openConnection().connect(); @@ -2843,7 +3019,7 @@ public final class URLConnectionTest extends TestCase { } } - public void testConnectIpv6() throws Exception { + @Test public void connectIpv6() throws Exception { server.enqueue(new MockResponse().setBody("testConnectIpv6 body")); server.play(); URL url = new URL("http://[::1]:" + server.getPort() + "/"); @@ -2852,7 +3028,7 @@ public final class URLConnectionTest extends TestCase { } // http://code.google.com/p/android/issues/detail?id=16895 - public void testUrlWithSpaceInHost() throws Exception { + @Test public void urlWithSpaceInHost() throws Exception { URLConnection urlConnection = new URL("http://and roid.com/").openConnection(); try { urlConnection.getInputStream(); @@ -2862,7 +3038,7 @@ public final class URLConnectionTest extends TestCase { } // http://code.google.com/p/android/issues/detail?id=16895 - public void testUrlWithSpaceInHostViaHttpProxy() throws Exception { + @Test public void urlWithSpaceInHostViaHttpProxy() throws Exception { server.enqueue(new MockResponse()); server.play(); URLConnection urlConnection = new URL("http://and roid.com/") @@ -2903,7 +3079,7 @@ public final class URLConnectionTest extends TestCase { false /* expectedWasFallbackScsvSet */, expectedProtocols); } - public void testNoSslFallback_specifiedProtocols() throws Exception { + @Test public void noSslFallback_specifiedProtocols() throws Exception { String[] enabledProtocols = { "TLSv1.2", "TLSv1.1" }; TestSSLContext testSSLContext = createDefaultTestSSLContext(); SSLSocketFactory serverSocketFactory = @@ -2916,7 +3092,7 @@ public final class URLConnectionTest extends TestCase { enabledProtocols); } - public void testNoSslFallback_defaultProtocols() throws Exception { + @Test public void noSslFallback_defaultProtocols() throws Exception { // Will need to be updated if the enabled protocols in Android's SSLSocketFactory change String[] expectedEnabledProtocols = { "TLSv1.2", "TLSv1.1", "TLSv1" }; @@ -2936,7 +3112,7 @@ public final class URLConnectionTest extends TestCase { assertEquals(expectedWasFallbackScsvSet, socket.wasTlsFallbackScsvSet()); } - public void testInspectSslBeforeConnect() throws Exception { + @Test public void inspectSslBeforeConnect() throws Exception { TestSSLContext testSSLContext = createDefaultTestSSLContext(); server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); server.enqueue(new MockResponse()); @@ -2971,7 +3147,7 @@ public final class URLConnectionTest extends TestCase { * Test that we can inspect the SSL session after connect(). * http://code.google.com/p/android/issues/detail?id=24431 */ - public void testInspectSslAfterConnect() throws Exception { + @Test public void inspectSslAfterConnect() throws Exception { TestSSLContext testSSLContext = createDefaultTestSSLContext(); server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); server.enqueue(new MockResponse()); @@ -3008,10 +3184,10 @@ public final class URLConnectionTest extends TestCase { * the minimal implementation of these methods to get OkHttp's tests to pass, so * they should never be invoked outside of OkHttp's tests. */ - public void testTrustManagerAndTrustRootIndex_unusedForHttpsConnection() throws Exception { + @Test public void trustManagerAndTrustRootIndex_unusedForHttpsConnection() throws Exception { Platform platform = Platform.getAndSetForTest(new PlatformWithoutTrustManager()); try { - testConnectViaHttps(); + checkConnectViaHttps(); } finally { Platform.getAndSetForTest(platform); } @@ -3024,7 +3200,7 @@ public final class URLConnectionTest extends TestCase { * be going wrong in order for this test to (unexpectedly) invoke the corresponding * Platform methods. */ - public void testTrustManagerAndTrustRootIndex_unusedForHttpConnection() throws Exception { + @Test public void trustManagerAndTrustRootIndex_unusedForHttpConnection() throws Exception { Platform platform = Platform.getAndSetForTest(new PlatformWithoutTrustManager()); try { server.enqueue(new MockResponse().setBody("response").setResponseCode(200)); diff --git a/luni/src/test/java/libcore/java/nio/channels/ServerSocketChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/ServerSocketChannelTest.java index 113779dd0e..f7f4e32d16 100644 --- a/luni/src/test/java/libcore/java/nio/channels/ServerSocketChannelTest.java +++ b/luni/src/test/java/libcore/java/nio/channels/ServerSocketChannelTest.java @@ -16,6 +16,14 @@ package libcore.java.nio.channels; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -28,28 +36,33 @@ import java.nio.channels.ClosedChannelException; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.UnresolvedAddressException; -import java.nio.channels.UnsupportedAddressTypeException; import java.util.Enumeration; -import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; -public class ServerSocketChannelTest extends junit.framework.TestCase { +@RunWith(JUnit4.class) +public class ServerSocketChannelTest { // http://code.google.com/p/android/issues/detail?id=16579 + @Test public void testNonBlockingAccept() throws Exception { - ServerSocketChannel ssc = ServerSocketChannel.open(); - try { + try (ServerSocketChannel ssc = ServerSocketChannel.open()) { ssc.configureBlocking(false); ssc.socket().bind(null); // Should return immediately, since we're non-blocking. assertNull(ssc.accept()); - } finally { - ssc.close(); } } /** Checks the state of the ServerSocketChannel and associated ServerSocket after open() */ - public void test_open_initialState() throws Exception { - ServerSocketChannel ssc = ServerSocketChannel.open(); - try { + @Test + public void open_initialState() throws Exception { + try (ServerSocketChannel ssc = ServerSocketChannel.open()) { assertNull(ssc.socket().getLocalSocketAddress()); ServerSocket socket = ssc.socket(); @@ -61,12 +74,11 @@ public class ServerSocketChannelTest extends junit.framework.TestCase { assertTrue(socket.getReuseAddress()); assertSame(ssc, socket.getChannel()); - } finally { - ssc.close(); } } - public void test_bind_unresolvedAddress() throws IOException { + @Test + public void bind_unresolvedAddress() throws IOException { ServerSocketChannel ssc = ServerSocketChannel.open(); try { ssc.socket().bind(new InetSocketAddress("unresolvedname", 31415)); @@ -80,7 +92,8 @@ public class ServerSocketChannelTest extends junit.framework.TestCase { ssc.close(); } - public void test_bind_nullBindsToAll() throws Exception { + @Test + public void bind_nullBindsToAll() throws Exception { ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.socket().bind(null); InetSocketAddress boundAddress = (InetSocketAddress) ssc.socket().getLocalSocketAddress(); @@ -106,9 +119,55 @@ public class ServerSocketChannelTest extends junit.framework.TestCase { ssc.close(); } - public void test_bind_loopback() throws Exception { + /** + * Server that can be used to generate a Future containing the count of incoming connections it + * accepts. Uses a latch to block the main thread until it is ready to start counting. + */ + private static class CountingServer implements Callable<Integer> { + private final ServerSocketChannel channel; + private final CountDownLatch latch; + private Integer connectionCount = 0; + + private CountingServer(ServerSocketChannel channel, CountDownLatch latch) { + this.channel = channel; + this.latch = latch; + } + + @Override + public Integer call() throws IOException { + // Clear any pending connections. + clearAcceptQueue(); + // Release the main thread. + latch.countDown(); + // Loop accepting and counting connections until the main thread closes the socket, + // triggering an IOException. + while (true) { + try { + SocketChannel client = channel.accept(); + connectionCount++; + client.close(); + } catch (IOException e) { + break; + } + } + return connectionCount; + } + + private void clearAcceptQueue() throws IOException { + channel.configureBlocking(false); + SocketChannel client; + while ((client = channel.accept()) != null) { + client.close(); + } + channel.configureBlocking(true); + } + } + + @Test + public void bind_loopback() throws Exception { + ExecutorService executor = Executors.newSingleThreadExecutor(); ServerSocketChannel ssc = ServerSocketChannel.open(); - ssc.socket().bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + ssc.socket().bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 5); InetSocketAddress boundAddress = (InetSocketAddress) ssc.socket().getLocalSocketAddress(); assertFalse(boundAddress.getAddress().isAnyLocalAddress()); assertFalse(boundAddress.getAddress().isLinkLocalAddress()); @@ -121,9 +180,16 @@ public class ServerSocketChannelTest extends junit.framework.TestCase { new InetSocketAddress(InetAddress.getLoopbackAddress(), boundAddress.getPort()); assertTrue(canConnect(loopbackAddress)); + CountDownLatch latch = new CountDownLatch(1); + Future<Integer> countFuture = executor.submit(new CountingServer(ssc, latch)); + // Wait until the CountingServer thread starts, otherwise there is a risk of + // canConnect() connecting and closing the socket before the server is ready. + latch.await(); + // Go through all local IPs and try to connect to each in turn - all should fail except // for the loopback. Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); + assertNotNull(interfaces); while (interfaces.hasMoreElements()) { NetworkInterface nic = interfaces.nextElement(); Enumeration<InetAddress> inetAddresses = nic.getInetAddresses(); @@ -131,15 +197,19 @@ public class ServerSocketChannelTest extends junit.framework.TestCase { InetSocketAddress address = new InetSocketAddress(inetAddresses.nextElement(), boundAddress.getPort()); if (!address.equals(loopbackAddress)) { - assertFalse(canConnect(address)); + // Return value ignored in favour of using countFuture below. + canConnect(address); } } } - ssc.close(); + executor.shutdown(); + // If connectionCount is non-zero then we connected to our own server which is a failure. + assertEquals(0, (int) countFuture.get()); } - public void test_bind$SocketAddress() throws IOException { + @Test + public void bind_socketAddress() throws IOException { ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); assertEquals(InetAddress.getLoopbackAddress(), @@ -168,7 +238,8 @@ public class ServerSocketChannelTest extends junit.framework.TestCase { } } - public void test_setOption() throws Exception { + @Test + public void set_option() throws Exception { ServerSocketChannel sc = ServerSocketChannel.open(); sc.setOption(StandardSocketOptions.SO_REUSEADDR, true); diff --git a/luni/src/test/java/libcore/java/nio/charset/ModifiedUtf8Test.java b/luni/src/test/java/libcore/java/nio/charset/ModifiedUtf8Test.java deleted file mode 100644 index f7c91ba770..0000000000 --- a/luni/src/test/java/libcore/java/nio/charset/ModifiedUtf8Test.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package libcore.java.nio.charset; - -import junit.framework.TestCase; - -import java.io.UTFDataFormatException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.ModifiedUtf8; -import java.util.Arrays; - -/** - * Tests for {@code ModifiedUtf8}. - */ -public class ModifiedUtf8Test extends TestCase { - public void test_decode_singleChar() throws Exception { - assertEquals("A", ModifiedUtf8.decode(new byte[] { 'A' }, new char[1], 0, 1)); - } - - public void test_decode_checkOffsetAndLength() throws Exception { - assertEquals("BC", ModifiedUtf8.decode( - new byte[] { 'A', 'B', 'C', 'D' }, new char[2], 1, 2)); - } - - public void test_decode_unexpectedEndOfStreamAfterC2_throws() { - // We need at least one byte after 0xc2. - try { - ModifiedUtf8.decode(new byte[]{'B', (byte) 0xc2}, new char[2], 0, 2); - fail("Should throw " + UTFDataFormatException.class.getName()); - } catch(UTFDataFormatException expected) { - // Expected. - } - } - - public void test_decode_unexpectedEndOfStreamAfterE0_throws() { - // We need at least two bytes after 0xe0. - try { - ModifiedUtf8.decode( - new byte[] { 'B', (byte) 0xe0, (byte) 0xab }, new char[2], 0, 3); - fail("Should throw " + UTFDataFormatException.class.getName()); - } catch(UTFDataFormatException expected) { - // Expected. - } - } - - public void test_decode_endOfStreamAfterC2() throws Exception { - assertEquals("B\u00a0", ModifiedUtf8.decode( - new byte[] { 'B', (byte) 0xc2, (byte) 0xa0 }, - new char[2], - 0, - 3)); - } - - public void test_decode_endOfStreamAfterE0() throws Exception { - assertEquals("B\u0830", ModifiedUtf8.decode( - new byte[] { 'B', (byte) 0xe0, (byte) 0xa0, (byte) 0xb0 }, - new char[2], - 0, - 4)); - } - - public void test_decode_invalidByte_characterUnknown() throws Exception { - try { - ModifiedUtf8.decode(new byte[]{'A', (byte) 0xf0}, new char[2], 0, 2); - fail("Should throw " + UTFDataFormatException.class.getName()); - } catch (UTFDataFormatException expected) { - // Expected. - } - } - - public void test_decode_someC2Character() throws Exception { - assertEquals("A\u00a6", ModifiedUtf8.decode( - new byte[] { 'A', (byte) 0xc2, (byte) 0xa6 }, new char[2], 0, 3)); - } - - public void test_decode_lastC2Character() throws Exception { - assertEquals("A\u00bf", ModifiedUtf8.decode( - new byte[] { 'A', (byte) 0xc2, (byte) 0xbf }, new char[2], 0, 3)); - } - - public void test_decode_someTwoByteCharacter() throws Exception { - // Make sure bit masking works - assertEquals("A\u0606", ModifiedUtf8.decode( - new byte[] { 'A', (byte) 0xd8, (byte) 0x86 }, new char[3], 0, 3)); - } - - public void test_decode_lastTwoByteCharacter() throws Exception { - assertEquals("A\u07ff", ModifiedUtf8.decode( - new byte[] { 'A', (byte) 0xdf, (byte) 0xbf }, new char[2], 0, 3)); - } - - public void test_decode_firstE0Character() throws Exception { - assertEquals("A\u0800", ModifiedUtf8.decode( - new byte[] { 'A', (byte) 0xe0, (byte) 0xa0, (byte) 0x80 }, - new char[2], - 0, - 4)); - } - - public void test_decode_someThreeBytesCharacter() throws Exception { - assertEquals("A\u31c6", ModifiedUtf8.decode( - new byte[]{ 'A', (byte) 0xe3, (byte) 0x87, (byte) 0x86 }, - new char[2], - 0, - 4)); - } - - public void test_decode_lastThreeBytesCharacter() throws Exception { - assertEquals("A\uffff", ModifiedUtf8.decode( - new byte[] { 'A', (byte) 0xef, (byte) 0xbf, (byte) 0xbf }, - new char[2], - 0, - 4)); - } - - public void test_decode_twoByteCharacterAfterThreeByteCharacter() throws Exception { - assertEquals("\uffff\u0606A", ModifiedUtf8.decode( - new byte[] { (byte) 0xef, (byte) 0xbf, (byte) 0xbf, (byte) 0xd8, (byte) 0x86, 'A' }, - new char[3], - 0, - 6)); - } - - public void test_decode_c080isZero() throws Exception { - assertEquals("A\u0000A", ModifiedUtf8.decode( - new byte[] { 'A', (byte) 0xc0, (byte) 0x80, 'A' }, new char[3], 0, 4)); - } - - public void test_decode_00isZero() throws Exception { - assertEquals("A\u0000A", ModifiedUtf8.decode( - new byte[] { 'A', (byte) 0, 'A' }, new char[3], 0, 3)); - } - - public void test_decode_insufficientOutputSpace_throws() throws Exception{ - try { - ModifiedUtf8.decode(new byte[] { 'A', (byte) 0, 'A' }, new char[2], 0, 3); - fail("Should throw " + ArrayIndexOutOfBoundsException.class.getName()); - } catch(ArrayIndexOutOfBoundsException expected) { - // Expected. - } - } - - public void test_decode_checkBadSecondByteOfTwo() throws Exception { - try { - ModifiedUtf8.decode(new byte[]{(byte) 0xc0, (byte) 0xc0}, new char[2], 0, 2); - fail("Should throw " + UTFDataFormatException.class.getName()); - } catch (UTFDataFormatException expected) { - // Expected. - } - } - - public void test_decode_checkBadSecondByteOfThree() throws Exception{ - try { - ModifiedUtf8.decode(new byte[]{ - (byte) 0xe0, (byte) 0xc0, (byte) 0x80}, new char[2], 0, 2); - fail("Should throw " + UTFDataFormatException.class.getName()); - } catch (UTFDataFormatException expected) { - // Expected. - } - } - - public void test_decode_checkBadThirdByteOfThree() throws Exception{ - try { - ModifiedUtf8.decode(new byte[]{ - (byte) 0xe0, (byte) 0x80, (byte) 0xc0}, new char[2], 0, 2); - fail("Should throw " + UTFDataFormatException.class.getName()); - } catch (UTFDataFormatException expected) { - // Expected. - } - } - - public void test_decode_insufficientInput_throws() throws Exception{ - try { - ModifiedUtf8.decode(new byte[] { 'A', (byte) 0, 'A' }, new char[8], 0, 100); - fail("Should throw " + ArrayIndexOutOfBoundsException.class.getName()); - } catch(ArrayIndexOutOfBoundsException expected) { - // Expected. - } - } - - public void test_decode_extraCharsInArray_ignored() throws Exception { - assertEquals("A", ModifiedUtf8.decode(new byte[] { 'A' }, new char[] { 'B', 'Z' }, 0, 1)); - } - - public void test_countBytes_rightCount() throws Exception { - assertEquals(0, ModifiedUtf8.countBytes("", false)); - assertEquals(2, ModifiedUtf8.countBytes("\u0000", false)); - assertEquals(1, ModifiedUtf8.countBytes("A", false)); - assertEquals(1, ModifiedUtf8.countBytes("\u007f", false)); - assertEquals(2, ModifiedUtf8.countBytes("\u0080", false)); - assertEquals(2, ModifiedUtf8.countBytes("\u07ff", false)); - assertEquals(3, ModifiedUtf8.countBytes("\u0800", false)); - assertEquals(3, ModifiedUtf8.countBytes("\uffff", false)); - } - - public void test_countBytes_checkExceptionThrown() throws Exception { - // These two mustn't throw... - ModifiedUtf8.countBytes("", true); - ModifiedUtf8.countBytes("A", true); - - char[] unsignedShortSizedCharArray = new char[2 * Short.MAX_VALUE + 1]; - for (int i = 0; i < unsignedShortSizedCharArray.length; i++) { - unsignedShortSizedCharArray[i] = 'A'; - } - String unsignedShortSizedString = String.copyValueOf(unsignedShortSizedCharArray); - - char[] sizeLongerThanUnsignedShortCharArray = new char[2 * Short.MAX_VALUE + 2]; - for (int i = 0; i < sizeLongerThanUnsignedShortCharArray.length; i++) { - sizeLongerThanUnsignedShortCharArray[i] = 'A'; - } - String sizeLongerThanUnsignedShortString = String.copyValueOf( - sizeLongerThanUnsignedShortCharArray); - - // Mustn't throw. - ModifiedUtf8.countBytes(unsignedShortSizedString, true); - - try { - // Must throw. - ModifiedUtf8.countBytes(sizeLongerThanUnsignedShortString, true); - fail(); - } catch (UTFDataFormatException expected) { - // Expected. - } - - // Mustn't throw. - ModifiedUtf8.countBytes(unsignedShortSizedString, false); - ModifiedUtf8.countBytes(sizeLongerThanUnsignedShortString, false); - } - - public void test_encode() throws Exception { - assertTrue(Arrays.equals(new byte[]{0, 1, 'A'}, ModifiedUtf8.encode("A"))); - assertTrue(Arrays.equals(new byte[] { 0, 3, 'A', 'B', 'C' }, ModifiedUtf8.encode("ABC"))); - assertTrue(Arrays.equals(new byte[] { 0, 3, 'A', (byte) 0xc2, (byte) 0xa0 }, - ModifiedUtf8.encode("A\u00a0"))); - assertTrue(Arrays.equals(new byte[] { 0, 4, 'A', (byte) 0xe0, (byte) 0xa0, (byte) 0xb0 }, - ModifiedUtf8.encode("A\u0830"))); - assertTrue(Arrays.equals(new byte[] { 0, 3, 'A', (byte) 0xc2, (byte) 0xa6 }, - ModifiedUtf8.encode("A\u00a6"))); - assertTrue(Arrays.equals(new byte[] { 0, 3, 'A', (byte) 0xc2, (byte) 0xbf }, - ModifiedUtf8.encode("A\u00bf"))); - assertTrue(Arrays.equals(new byte[] { 0, 3, 'A', (byte) 0xd8, (byte) 0x86 }, - ModifiedUtf8.encode("A\u0606"))); - assertTrue(Arrays.equals(new byte[] { 0, 3, 'A', (byte) 0xdf, (byte) 0xbf }, - ModifiedUtf8.encode("A\u07ff"))); - assertTrue(Arrays.equals(new byte[] { 0, 4, 'A', (byte) 0xe0, (byte) 0xa0, (byte) 0x80 }, - ModifiedUtf8.encode("A\u0800"))); - assertTrue(Arrays.equals(new byte[] { 0, 4, 'A', (byte) 0xe3, (byte) 0x87, (byte) 0x86 }, - ModifiedUtf8.encode("A\u31c6"))); - assertTrue(Arrays.equals(new byte[] { 0, 4, 'A', (byte) 0xef, (byte) 0xbf, (byte) 0xbf }, - ModifiedUtf8.encode("A\uffff"))); - assertTrue(Arrays.equals(new byte[] { 0, 3, 'A', (byte) 0xc0, (byte) 0x80 }, - ModifiedUtf8.encode("A\u0000"))); - assertTrue( - Arrays.equals(new byte[] { 0, 8, (byte) 0xe3, (byte) 0x87, (byte) 0x86, - (byte) 0xd8, (byte) 0x86, (byte) 0xc0, (byte) 0x80, 'A' }, - ModifiedUtf8.encode("\u31c6\u0606\u0000A"))); - } - - public void test_encode_throws() throws Exception { - char[] unsignedShortSizedCharArray = new char[Short.MAX_VALUE * 2 + 1]; - for (int i = 0; i < unsignedShortSizedCharArray.length; i++) { - unsignedShortSizedCharArray[i] = 'A'; - } - String unsignedShortSizedString = String.copyValueOf(unsignedShortSizedCharArray); - - char[] sizeLongerThanUnsignedShortCharArray = new char[Short.MAX_VALUE * 2 + 2]; - for (int i = 0; i < sizeLongerThanUnsignedShortCharArray.length; i++) { - sizeLongerThanUnsignedShortCharArray[i] = 'A'; - } - String sizeLongerThanUnsignedShortString = - String.copyValueOf(sizeLongerThanUnsignedShortCharArray); - - // Mustn't throw. - ModifiedUtf8.encode(unsignedShortSizedString); - try { - // Must throw. - ModifiedUtf8.encode(sizeLongerThanUnsignedShortString); - fail("Should throw " + UTFDataFormatException.class.getName()); - } catch (UTFDataFormatException expected) { - // Expected. - } - } - - public void test_encode_lengthAtBeginning() throws Exception { - int testStringLength = 20000; - char[] charArray = new char[testStringLength]; - for (int i = 0; i < charArray.length; i++) { - charArray[i] = 'A'; - } - String testString = String.copyValueOf(charArray); - - // Mustn't throw. - byte[] result = ModifiedUtf8.encode(testString); - ByteBuffer b = ByteBuffer.wrap(result); - b.order(ByteOrder.BIG_ENDIAN); - assertEquals(testStringLength, b.getShort()); - } - -} diff --git a/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java b/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java index 2916b038f0..42d0f05c75 100644 --- a/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java +++ b/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java @@ -600,7 +600,8 @@ public class DefaultFileSystemProvider2Test { } catch (NullPointerException expected) {} try { - provider.newByteChannel(filesSetup.getTestPath(), new HashSet<>(), null); + provider.newByteChannel(filesSetup.getTestPath(), new HashSet<>(), + (FileAttribute<?>) null); fail(); } catch (NullPointerException expected) {} } diff --git a/luni/src/test/java/libcore/java/nio/file/DefaultSecureDirectoryStreamTest.java b/luni/src/test/java/libcore/java/nio/file/DefaultSecureDirectoryStreamTest.java index 2c9c2cdef2..273ff8f9c8 100644 --- a/luni/src/test/java/libcore/java/nio/file/DefaultSecureDirectoryStreamTest.java +++ b/luni/src/test/java/libcore/java/nio/file/DefaultSecureDirectoryStreamTest.java @@ -185,7 +185,7 @@ public class DefaultSecureDirectoryStreamTest { // NPE try (DirectoryStream<Path> ds_path_dir1 = ds_path_root.newDirectoryStream(path_root. - relativize(path_f1), null)) { + relativize(path_f1), (LinkOption) null)) { fail(); } catch (NullPointerException expected) {} @@ -380,7 +380,7 @@ public class DefaultSecureDirectoryStreamTest { try { ds_path_dir1.move(path_dir1, ds_path_dir1, - Paths.get(path_root.getParent().toString(), null)); + Paths.get(path_root.getParent().toString(), (String) null)); fail(); } catch (NullPointerException expected) {} @@ -498,7 +498,7 @@ public class DefaultSecureDirectoryStreamTest { try (SecureDirectoryStream<Path> ds_path_root = (SecureDirectoryStream<Path>) Files.newDirectoryStream(path_root)) { ds_path_root.getFileAttributeView(path_root.relativize(path_f1), - BasicFileAttributeView.class, null); + BasicFileAttributeView.class, (LinkOption) null); fail(); } catch (NullPointerException expected) {} } diff --git a/luni/src/test/java/libcore/java/nio/file/Files2Test.java b/luni/src/test/java/libcore/java/nio/file/Files2Test.java index 436d3e309f..a3357e341b 100644 --- a/luni/src/test/java/libcore/java/nio/file/Files2Test.java +++ b/luni/src/test/java/libcore/java/nio/file/Files2Test.java @@ -1683,7 +1683,7 @@ public class Files2Test { } catch (NullPointerException expected) {} try { - Files.createTempDirectory(filesSetup.getTestDirPath(), tmpDir, null); + Files.createTempDirectory(filesSetup.getTestDirPath(), tmpDir, (FileAttribute<?>) null); fail(); } catch (NullPointerException expected) {} } @@ -1710,7 +1710,7 @@ public class Files2Test { assertEquals(attr.value(), Files.getAttribute(tmpDirPath, attr.name())); try { - Files.createTempDirectory(tmpDir, null); + Files.createTempDirectory(tmpDir, (FileAttribute<?>) null); fail(); } catch (NullPointerException expected) {} } @@ -1757,7 +1757,7 @@ public class Files2Test { try { Files.createTempFile(filesSetup.getTestDirPath(), tmpFilePrefix, tmpFileSuffix, - null); + (FileAttribute<?>) null); fail(); } catch (NullPointerException expected) {} } @@ -1796,7 +1796,7 @@ public class Files2Test { assertEquals(attr.value(), Files.getAttribute(tmpFilePath, attr.name())); try { - Files.createTempFile(tmpFilePrefix, tmpFileSuffix, null); + Files.createTempFile(tmpFilePrefix, tmpFileSuffix, (FileAttribute<?>) null); fail(); } catch (NullPointerException expected) {} } diff --git a/luni/src/test/java/libcore/java/nio/file/LinuxPathTest.java b/luni/src/test/java/libcore/java/nio/file/LinuxPathTest.java index e95f5bc9b3..458804c5da 100644 --- a/luni/src/test/java/libcore/java/nio/file/LinuxPathTest.java +++ b/luni/src/test/java/libcore/java/nio/file/LinuxPathTest.java @@ -18,6 +18,7 @@ package libcore.java.nio.file; import com.sun.nio.file.ExtendedWatchEventModifier; +import java.nio.file.WatchEvent.Kind; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -454,7 +455,7 @@ public class LinuxPathTest { } catch (NullPointerException expected) {} try { - directory.register(watchService, null); + directory.register(watchService, (Kind<?>) null); fail(); } catch (NullPointerException expected) {} } diff --git a/luni/src/test/java/libcore/java/security/ProviderTest.java b/luni/src/test/java/libcore/java/security/ProviderTest.java index a9a5318b3f..946f602d45 100644 --- a/luni/src/test/java/libcore/java/security/ProviderTest.java +++ b/luni/src/test/java/libcore/java/security/ProviderTest.java @@ -55,29 +55,19 @@ import java.util.regex.Pattern; import javax.crypto.Cipher; import javax.crypto.EncryptedPrivateKeyInfo; import javax.crypto.NoSuchPaddingException; -import junit.framework.TestCase; import libcore.javax.crypto.MockKey; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; +import org.junit.Rule; +import org.junit.rules.TestRule; -import dalvik.system.VMRuntime; -import sun.security.jca.Providers; - -public class ProviderTest extends TestCase { +public class ProviderTest extends TestCaseWithRules { // Allow access to deprecated BC algorithms in this test, so we can ensure they // continue to work - @Override - public void setUp() throws Exception { - super.setUp(); - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - } - - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); - } + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); private static final boolean LOG_DEBUG = false; diff --git a/luni/src/test/java/libcore/java/security/SignatureTest.java b/luni/src/test/java/libcore/java/security/SignatureTest.java index 3750742c8b..9c014d2c3a 100644 --- a/luni/src/test/java/libcore/java/security/SignatureTest.java +++ b/luni/src/test/java/libcore/java/security/SignatureTest.java @@ -37,29 +37,19 @@ import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import junit.framework.TestCase; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; import libcore.util.HexEncoding; +import org.junit.Rule; +import org.junit.rules.TestRule; -import dalvik.system.VMRuntime; -import sun.security.jca.Providers; - -public class SignatureTest extends TestCase { +public class SignatureTest extends TestCaseWithRules { // Allow access to deprecated BC algorithms in this test, so we can ensure they // continue to work - @Override - public void setUp() throws Exception { - super.setUp(); - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - } - - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); - } + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); private static abstract class MockProvider extends Provider { public MockProvider(String name) { diff --git a/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java b/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java index 0f84e91827..fc09ae8312 100644 --- a/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java +++ b/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java @@ -32,8 +32,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; -import junit.framework.TestCase; import libcore.java.security.TestKeyStore; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; import org.bouncycastle.asn1.x509.CRLReason; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.cert.X509CertificateHolder; @@ -48,27 +49,16 @@ import org.bouncycastle.cert.ocsp.RevokedStatus; import org.bouncycastle.operator.DigestCalculatorProvider; import org.bouncycastle.operator.bc.BcDigestCalculatorProvider; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.junit.Rule; +import org.junit.rules.TestRule; -import dalvik.system.VMRuntime; -import sun.security.jca.Providers; - -public class CertPathValidatorTest extends TestCase { +public class CertPathValidatorTest extends TestCaseWithRules { // Allow access to deprecated BC algorithms in this test, so we can ensure they // continue to work - @Override - public void setUp() throws Exception { - super.setUp(); - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - } - - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); - } + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); private OCSPResp generateOCSPResponse(X509Certificate serverCertJca, X509Certificate caCertJca, PrivateKey caKey, CertificateStatus status) throws Exception { diff --git a/luni/src/test/java/libcore/java/security/cert/PKIXParametersTest.java b/luni/src/test/java/libcore/java/security/cert/PKIXParametersTest.java index a26c631e76..1836aac2d1 100644 --- a/luni/src/test/java/libcore/java/security/cert/PKIXParametersTest.java +++ b/luni/src/test/java/libcore/java/security/cert/PKIXParametersTest.java @@ -16,32 +16,22 @@ package libcore.java.security.cert; -import junit.framework.TestCase; import java.security.InvalidAlgorithmParameterException; import java.security.KeyStore; import java.security.cert.PKIXParameters; import libcore.java.security.TestKeyStore; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; +import org.junit.Rule; +import org.junit.rules.TestRule; -import dalvik.system.VMRuntime; -import sun.security.jca.Providers; - -public class PKIXParametersTest extends TestCase { +public class PKIXParametersTest extends TestCaseWithRules { // Allow access to deprecated BC algorithms in this test, so we can ensure they // continue to work - @Override - public void setUp() throws Exception { - super.setUp(); - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - } - - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); - } + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); public void testKeyStoreConstructor() throws Exception { TestKeyStore server = TestKeyStore.getServer(); diff --git a/luni/src/test/java/libcore/java/security/cert/PKIXRevocationCheckerTest.java b/luni/src/test/java/libcore/java/security/cert/PKIXRevocationCheckerTest.java index e2066ae72c..0e420cbd5d 100644 --- a/luni/src/test/java/libcore/java/security/cert/PKIXRevocationCheckerTest.java +++ b/luni/src/test/java/libcore/java/security/cert/PKIXRevocationCheckerTest.java @@ -14,13 +14,20 @@ import java.util.Arrays; import java.util.Collections; import java.util.Map; -import junit.framework.TestCase; import libcore.java.security.TestKeyStore; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; +import org.junit.Rule; +import org.junit.rules.TestRule; -import dalvik.system.VMRuntime; -import sun.security.jca.Providers; +public class PKIXRevocationCheckerTest extends TestCaseWithRules { + + // Allow access to deprecated BC algorithms in this test, so we can ensure they + // continue to work + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); -public class PKIXRevocationCheckerTest extends TestCase { PKIXRevocationChecker checker; PrivateKeyEntry entity; @@ -31,11 +38,6 @@ public class PKIXRevocationCheckerTest extends TestCase { protected void setUp() throws Exception { super.setUp(); - // Allow access to deprecated BC algorithms in this test, so we can ensure they - // continue to work - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX"); CertPathChecker rc = cpb.getRevocationChecker(); assertNotNull(rc); @@ -49,13 +51,6 @@ public class PKIXRevocationCheckerTest extends TestCase { issuer = intermediate.getPrivateKey("RSA", "RSA"); } - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); - } - public void test_Initializes() throws Exception { assertEquals(0, checker.getOcspResponses().size()); assertEquals(0, checker.getOcspExtensions().size()); diff --git a/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java b/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java index b11b40e44e..ca612be253 100644 --- a/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java +++ b/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java @@ -18,8 +18,10 @@ package libcore.java.security.cert; import static java.nio.charset.StandardCharsets.UTF_8; -import dalvik.system.VMRuntime; -import sun.security.jca.Providers; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; +import org.junit.Rule; +import org.junit.rules.TestRule; import sun.security.provider.X509Factory; import sun.security.x509.X509CRLImpl; import tests.support.resource.Support_Resources; @@ -49,27 +51,20 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import junit.framework.TestCase; import libcore.java.security.StandardNames; -public class X509CRLTest extends TestCase { +public class X509CRLTest extends TestCaseWithRules { + + // Allow access to deprecated BC algorithms in this test, so we can ensure they + // continue to work + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); @Override public void setUp() throws Exception { super.setUp(); mX509Providers = Security.getProviders("CertificateFactory.X509"); - - // Allow access to deprecated BC algorithms in this test, so we can ensure they - // continue to work - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - } - - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); } private Provider[] mX509Providers; diff --git a/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java b/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java index 95a95c0f4b..d6942141d7 100644 --- a/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java +++ b/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java @@ -57,32 +57,26 @@ import java.util.List; import java.util.Locale; import java.util.Set; import javax.security.auth.x500.X500Principal; -import junit.framework.TestCase; import libcore.java.security.StandardNames; - -import dalvik.system.VMRuntime; -import sun.security.jca.Providers; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; +import org.junit.Rule; +import org.junit.rules.TestRule; import tests.support.resource.Support_Resources; -public class X509CertificateTest extends TestCase { +public class X509CertificateTest extends TestCaseWithRules { + + // Allow access to deprecated BC algorithms in this test, so we can ensure they + // continue to work + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); @Override protected void setUp() throws Exception { super.setUp(); mX509Providers = Security.getProviders("CertificateFactory.X509"); - - // Allow access to deprecated BC algorithms in this test, so we can ensure they - // continue to work - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - } - - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); } private Provider[] mX509Providers; diff --git a/luni/src/test/java/libcore/java/text/CollatorTest.java b/luni/src/test/java/libcore/java/text/CollatorTest.java index 75a245e358..66ea0d2f68 100644 --- a/luni/src/test/java/libcore/java/text/CollatorTest.java +++ b/luni/src/test/java/libcore/java/text/CollatorTest.java @@ -22,7 +22,11 @@ import java.text.Collator; import java.text.ParseException; import java.text.RuleBasedCollator; import java.text.StringCharacterIterator; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.Locale; +import java.util.Set; public class CollatorTest extends junit.framework.TestCase { public void test_setStrengthI() throws Exception { @@ -164,4 +168,15 @@ public class CollatorTest extends junit.framework.TestCase { public void testGetCollationElementIteratorCharacterIterator_de_DE() throws Exception { assertGetCollationElementIteratorCharacterIterator(new Locale("de", "DE", ""), "\u00e6b", 0, 1, 1, 2); } + + public void testGetAvailableLocales_icuConsistency() { + Locale[] javaLocales = Collator.getAvailableLocales(); + Locale[] icuLocales = android.icu.text.Collator.getAvailableLocales(); + Set<Locale> javaSet = new HashSet<>(Arrays.asList(javaLocales)); + Set<Locale> icuSet = new HashSet<>(Arrays.asList(icuLocales)); + assertEquals(javaSet, icuSet); + // Assert no duplicated entries + assertEquals(javaLocales.length, javaSet.size()); + assertEquals(icuLocales.length, icuSet.size()); + } } diff --git a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java index 740e7a57db..e2be925ce4 100644 --- a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java +++ b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java @@ -16,6 +16,7 @@ package libcore.java.text; +import dalvik.system.VMRuntime; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; @@ -248,11 +249,29 @@ public class DecimalFormatTest extends junit.framework.TestCase { } catch (NullPointerException expected) { } - // These just ignore null. - df.setNegativePrefix(null); - df.setNegativeSuffix(null); - df.setPositivePrefix(null); - df.setPositiveSuffix(null); + try { + df.setNegativePrefix(null); + fail(); + } catch (NullPointerException expected) { + } + + try { + df.setNegativeSuffix(null); + fail(); + } catch (NullPointerException expected) { + } + + try { + df.setPositivePrefix(null); + fail(); + } catch (NullPointerException expected) { + } + + try { + df.setPositiveSuffix(null); + fail(); + } catch (NullPointerException expected) { + } try { df.setRoundingMode(null); @@ -582,7 +601,7 @@ public class DecimalFormatTest extends junit.framework.TestCase { // toLocalizedPattern() returns no pattern separator when input pattern has no prefix. // Add prefixes 'AAA'/'BBB' to force pattern separator in output pattern. df.applyLocalizedPattern("'AAA'+0;'BBB'-0"); - assertEquals("'AAA'+#0;'BBB'-#0", df.toLocalizedPattern()); + assertEquals("'AAA'+0;'BBB'-0", df.toLocalizedPattern()); assertEquals("BBB-123", df.format(-123)); } // Test a locale using non-ascii-semi-colon pattern separator. @@ -591,7 +610,7 @@ public class DecimalFormatTest extends junit.framework.TestCase { Locale.forLanguageTag("ar-EG")); assertEquals('\u061b', df.getDecimalFormatSymbols().getPatternSeparator()); df.applyLocalizedPattern("'AAA'+\u0660\u061b'BBB'-\u0660"); - assertEquals("'AAA'+#\u0660\u061b'BBB'-#\u0660", df.toLocalizedPattern()); + assertEquals("'AAA'+\u0660\u061b'BBB'-\u0660", df.toLocalizedPattern()); assertEquals("BBB-\u0661\u0662\u0663", df.format(-123)); } } @@ -635,8 +654,6 @@ public class DecimalFormatTest extends junit.framework.TestCase { assertParsed("0; 0", " 1 ", -1, 2); // Leading space in prefix is accepted. assertParsed(" 0", " 1 ", 1, 2); - // Extra space after prefix with space is accepted. - assertParsed(" 0", " 1 ", 1, 3); } // http://b/68143370 @@ -653,6 +670,71 @@ public class DecimalFormatTest extends junit.framework.TestCase { assertParseError("0", " 1"); // Space in prefix is expected to be present. assertParseError(" 0", "1"); + // Extra space after prefix with space is not tolerated. + assertParseError(" 0", " 1 "); + } + + // Test that Bidi control character is not tolerated + public void testParseBidi() { + assertParseError("0", "\u200e1"); + assertParsed("0", "1\u200e", 1, 1); + assertParseError("0%", "\u200e1%"); + } + + public void testParseGroupingSeparator() { + // Test that grouping separator is optional when the group separator is specified + assertParsedAndConsumedAll("#,##0", "9,999", 9999); + assertParsedAndConsumedAll("#,##0", "9999", 9999); + assertParsedAndConsumedAll("#,###0", "9,9999", 99999); + + // Test that grouping size doesn't affect parsing at all + assertParsedAndConsumedAll("#,##0", "9,9999", 99999); + assertParsedAndConsumedAll("#,###0", "99,999", 99999); + + assertParsedAndConsumedAll("###0", "9999", 9999); + assertParsedAndConsumedAll("###0", "99999", 99999); + + // Test that grouping separator must not be present when the group separator is NOT specified + // Only the 1st character in front of separator , should be consumed. + assertParsed("###0", "9,9999", 9, 1); + assertParsed("###0", "9,999", 9, 1); + } + + public void testParseScienificNotation() { + assertParsedAndConsumedAll("0.###E0", "1E-3", 0.001); + assertParsedAndConsumedAll("0.###E0", "1E0", 1); + assertParsedAndConsumedAll("0.###E0", "1E3", 1000); + assertParsedAndConsumedAll("0.###E0", "1.111E3", 1111); + assertParsedAndConsumedAll("0.###E0", "1.1E3", 1100); + + // "0.###E0" is engineering notation, i.e. the exponent should be a multiple of 3 + // for formatting. But it shouldn't affect parsing. + assertParsedAndConsumedAll("0.###E0", "1E1", 10); + + // Test that exponent is not required for parsing + assertParsedAndConsumedAll("0.###E0", "1.1", 1.1); + assertParsedAndConsumedAll("0.###E0", "1100", 1100); + + // Test that the max of fraction, integer or signficant digits don't affect parsing + // Note that the max of signficant digits is 4 = min integer digits (1) + // + max fraction digits (3) + assertParsedAndConsumedAll("0.###E0", "1111.4E3", 1111400); + assertParsedAndConsumedAll("0.###E0", "1111.9999E3", 1111999.9); + } + + /* + * ISO currency code parsing is case insensitive. http://b/112469513 + */ + public void testParseCurrencyIsoCode() { + assertParsedAndConsumedAll("¤¤0", "USD10", 10); + assertParsedAndConsumedAll("¤¤0", "usd10", 10); + assertParsedAndConsumedAll("¤¤0", "Usd10", 10); + assertParsedAndConsumedAll("¤¤0", "Usd10", 10); + + // DecimalFormat.parse is only required to parse the local currency for the Locale + // associated with the DecimalFormat. assertParseError() uses Locale.US so it is expected to + // fail to parse valid ISO codes except for USD. + assertParseError("¤¤0", "GBP10"); } // Test that getMaximumIntegerDigits should return value >= 309 by default, even though a @@ -693,6 +775,13 @@ public class DecimalFormatTest extends junit.framework.TestCase { } } + /** + * Assert the expected number and the whole input string is consumed and parsed successfully. + */ + private static void assertParsedAndConsumedAll(String pattern, String input, Number expected) { + assertParsed(pattern, input, expected, input.length()); + } + private static void assertParsed(String pattern, String input, Number expected, int expectedIndex) { ParsePosition expectedPos = new ParsePosition(expectedIndex); diff --git a/luni/src/test/java/libcore/java/text/OldDecimalFormatTestICU.java b/luni/src/test/java/libcore/java/text/OldDecimalFormatTestICU.java index 205faac699..eb3f4ca579 100644 --- a/luni/src/test/java/libcore/java/text/OldDecimalFormatTestICU.java +++ b/luni/src/test/java/libcore/java/text/OldDecimalFormatTestICU.java @@ -60,14 +60,6 @@ public class OldDecimalFormatTestICU extends TestCase { } catch (IllegalArgumentException e) { // expected } - - try { - format.applyPattern("@.###"); - fail("expected IllegalArgumentException was not thrown for " - + "pattern \"@.###\"."); - } catch (IllegalArgumentException e) { - // expected - } } // AndroidOnly: special feature of icu4c diff --git a/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java b/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java index 619f788e04..9df9e437e6 100644 --- a/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java +++ b/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java @@ -68,7 +68,10 @@ public class OldNumberFormatTest extends TestCase { assertEquals("Wrong result: case 1", "23", format.format(123)); format.setMaximumIntegerDigits(Integer.MIN_VALUE); - assertEquals("Wrong result: case 2", "0", format.format(123)); + assertEquals("Wrong result: case 2", ".0", format.format(123)); + + format.setMaximumIntegerDigits(0); + assertEquals("Wrong result: case 2", ".0", format.format(123)); } public void test_setCurrencyLjava_util_Currency() { @@ -196,7 +199,7 @@ public class OldNumberFormatTest extends TestCase { nf2.setMaximumIntegerDigits(100); assertFalse("Different NumberFormat are equal", nf1.equals(nf2)); - nf2.setMaximumIntegerDigits(nf1.getMaximumIntegerDigits()); + nf1.setMaximumIntegerDigits(100); assertTrue("Equivalent Objects are not equal", nf1.equals(nf2)); nf1 = NumberFormat.getIntegerInstance(); diff --git a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java index 2d85c1bc36..a4ebad31cb 100644 --- a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java +++ b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java @@ -16,16 +16,22 @@ package libcore.java.text; +import libcore.util.Nullable; import java.text.DateFormat; import java.text.DateFormatSymbols; import java.text.ParseException; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.GregorianCalendar; +import java.util.HashMap; import java.util.Locale; +import java.util.Map; import java.util.TimeZone; +import java.util.TreeMap; public class SimpleDateFormatTest extends junit.framework.TestCase { @@ -771,6 +777,68 @@ public class SimpleDateFormatTest extends junit.framework.TestCase { assertEquals("leden", formatDateNonGregorianCalendar("LLLLL", cs)); } + /** + * This test demonstrates that optimization with special case handling of + * {@link java.util.SortedMap} in + * {@link SimpleDateFormat#matchString(java.lang.String, int, int, java.util.Map, java.text.CalendarBuilder)} + * is buggy. It makes use of {@link NonGregorianCalendarWithTreeMapDisplayNames} + * which returns {@link TreeMap} instead of {@link HashMap}. + * + * @see NonGregorianCalendarWithTreeMapDisplayNames + * @see http://b/119913354 + */ + public void testMatchStringSortedMap_treeMap() { + Calendar cal = new NonGregorianCalendarWithTreeMapDisplayNames(null); + checkMatchStringSortedMap_formatParseCzechJuly(cal); + } + + /** + * Same as {@link SimpleDateFormatTest#testMatchStringSortedMap_treeMap()} but also using + * reverse order comparator for a {@link TreeMap} returned from + * {@link Calendar#getDisplayNames(int, int, java.util.Locale)}. + * + * Reverse order comparator demonstrates that even iterating key set in descending order may + * still behave incorrectly. + */ + public void testMatchStringSortedMap_treeMapWithReverseOrderComparator() { + Calendar cal = new NonGregorianCalendarWithTreeMapDisplayNames(Comparator.reverseOrder()); + checkMatchStringSortedMap_formatParseCzechJuly(cal); + } + + /** + * Helper method for {@link #testMatchStringSortedMap_treeMap()} and + * {@link #testMatchStringSortedMap_treeMapWithReverseOrderComparator()} + * that formats "15 July 1997" using Czech locale. June in Czech (Červen) is a + * prefix of July (Červenec) which can break the logic that relies on matching + * first rather than longest match when parsing months names. + * + * For example, imagine matching "15 července 1997" which is "15 June 1997" in Czech. + * When {@link SimpleDateFormat} parses the whole string it tries to match all field names + * with "current" text chunk (in case of month this would match againsg "července"). + * This set of field names in this case would contain month names in nominative and genitive + * cases so it contains "července" (July in genitive) and "červen" (July in nominative). + * Since the real answer is "července" but "červen" would still match, {@link SimpleDateFormat} + * picks the wrong shorter field. The next parsed field is year but parsing is attempted + * from "ce 1997" chunk, not from " 1997", so it fails. + */ + private static void checkMatchStringSortedMap_formatParseCzechJuly(Calendar calendar) { + DateFormat fmt = new SimpleDateFormat("dd MMMM yyyy", new Locale("cs", "", "")); + calendar.clear(); + calendar.setTimeZone(UTC); + fmt.setCalendar(calendar); + + final String julyStr = fmt.format(new Date(97, Calendar.JULY, 15)); + + try { + Date d = fmt.parse(julyStr); + String s = fmt.format(d); + int month = d.getMonth(); + assertEquals(Calendar.JULY, month); + } catch (ParseException e) { + fail("Exception occurred: " + e); + } + } + private void assertDayPeriodParseFailure(String pattern, String source) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern, Locale.US); ParsePosition parsePosition = new ParsePosition(0); @@ -866,4 +934,31 @@ public class SimpleDateFormatTest extends junit.framework.TestCase { } } + /** + * A GregorianCalendar whose {@code getDisplayNames(int, int, Locale)} returns a + * {@link NavigableMap} which is needed to make {@link SimpleDateFormat#useDateFormatSymbols} + * explicitly use date format symbols for {@link #testMatchStringSortedMap_treeMap()} and + * {@link #testMatchStringSortedMap_treeMapWithReverseOrderComparator()} which test for usage of + * instances of {@link java.util.SortedMap} in + * {@link SimpleDateFormat#matchString(java.lang.String, int, int, java.util.Map, java.text.CalendarBuilder)}. + * + * @see http://b/119913354 + */ + private static class NonGregorianCalendarWithTreeMapDisplayNames extends GregorianCalendar { + + private Comparator<String> mapComparator; + + NonGregorianCalendarWithTreeMapDisplayNames(@Nullable Comparator<String> comparator) { + this.mapComparator = comparator; + } + + @Override + public Map<String, Integer> getDisplayNames(int field, int style, Locale locale) { + Map<String, Integer> result = super.getDisplayNames(field, style, locale); + TreeMap<String, Integer> treeMap = new TreeMap<>(this.mapComparator); + treeMap.putAll(result); + return treeMap; + } + } + } diff --git a/luni/src/test/java/libcore/java/time/chrono/JapaneseChronologyTest.java b/luni/src/test/java/libcore/java/time/chrono/JapaneseChronologyTest.java index 3c1f0cf561..5e920b38b2 100644 --- a/luni/src/test/java/libcore/java/time/chrono/JapaneseChronologyTest.java +++ b/luni/src/test/java/libcore/java/time/chrono/JapaneseChronologyTest.java @@ -15,7 +15,9 @@ */ package libcore.java.time.chrono; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + import java.time.Instant; import java.time.LocalDate; import java.time.LocalTime; @@ -26,10 +28,11 @@ import java.time.chrono.ChronoZonedDateTime; import java.time.chrono.JapaneseChronology; import java.time.chrono.JapaneseDate; import java.time.chrono.JapaneseEra; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; import java.time.temporal.ChronoField; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; +import java.util.Locale; +import org.junit.Test; /** * Additional tests for {@link JapaneseChronology} and {@link JapaneseDate}. @@ -110,4 +113,35 @@ public class JapaneseChronologyTest { assertEquals(true, date.isSupported(ChronoField.YEAR)); assertEquals(true, date.isSupported(ChronoField.YEAR_OF_ERA)); } + + @Test + public void test_JapaneseEras_dateTimeFormatter() { + DateTimeFormatter formatter = DateTimeFormatter + .ofLocalizedDate(FormatStyle.FULL) + .withChronology(JapaneseChronology.INSTANCE); + + final LocalDate heisei = LocalDate.of(2018, 1, 1); + final Locale ja = Locale.forLanguageTag("ja-JP-u-ca-japanese"); + assertEquals("平成30年1月1日月曜日", heisei.format(formatter.withLocale(ja))); + assertEquals("Monday, January 1, 30 Heisei", + heisei.format(formatter.withLocale(Locale.ENGLISH))); + + final LocalDate reiwa = LocalDate.of(2019, 5, 1); + assertEquals("令和1年5月1日水曜日", reiwa.format(formatter.withLocale(ja))); + assertEquals("Wednesday, May 1, 1 Reiwa", + reiwa.format(formatter.withLocale(Locale.ENGLISH))); + } + + // This tests era names from calendars.properties file + @Test + public void test_JapaneseEras_calendarsDotProperties() { + final LocalDate heisei = LocalDate.of(2018, 1, 1); + final LocalDate reiwa = LocalDate.of(2019, 5, 1); + JapaneseDate heiseiDate = JapaneseChronology.INSTANCE.date(heisei); + JapaneseDate reiwaDate = JapaneseChronology.INSTANCE.date(reiwa); + + assertEquals("Heisei", heiseiDate.getEra().toString()); + assertEquals("Reiwa", reiwaDate.getEra().toString()); + } + } diff --git a/luni/src/test/java/libcore/java/util/AbstractListTest.java b/luni/src/test/java/libcore/java/util/AbstractListTest.java new file mode 100644 index 0000000000..e0c4db26d1 --- /dev/null +++ b/luni/src/test/java/libcore/java/util/AbstractListTest.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.java.util; + +import junit.framework.AssertionFailedError; + +import org.junit.Test; + +import java.util.AbstractList; +import java.util.AbstractSequentialList; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.RandomAccess; +import java.util.Spliterator; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class AbstractListTest { + @Test public void sublist_outOfBounds() { + assertSubListOutOfBounds(new RandomAccessList(/* size */ 0), 0, 1); + assertSubListOutOfBounds(new RandomAccessList(/* size */ 10), 0, 11); + assertSubListOutOfBounds(new RandomAccessList(/* size */ 10), -1, 10); + assertSubListOutOfBounds(new RandomAccessList(/* size */ 10), -1, 11); + + assertSubListOutOfBounds(new SequentialList(/* elements */), 0, 1); + assertSubListOutOfBounds(new SequentialList(/* elements */ 10, 20, 30), 0, 4); + assertSubListOutOfBounds(new SequentialList(/* elements */ 10, 20, 30), -1, 3); + + // These ones work + new RandomAccessList(/* size */ 0).subList(0, 0); + new RandomAccessList(/* size */ 10).subList(0, 10); + new RandomAccessList(/* size */ 10).subList(2, 5); + new SequentialList(/* elements */).subList(0, 0); + new SequentialList(/* elements */ 10, 20, 30).subList(0, 3); + } + + private static<T> void assertSubListOutOfBounds(List<T> list, int startIndex, int endIndex) { + try { + list.subList(startIndex, endIndex); + fail(); + } catch (IndexOutOfBoundsException expected) { + } + } + + /** Checks that list.spliterator() is late-binding. */ + @Test public void spliterator_lateBinding() { + List<Integer> list = new RandomAccessList(50); + Spliterator<Integer> spliterator = list.spliterator(); + Integer newFirstValue = list.get(0) + 3000; + list.add(0, newFirstValue); // prepend + AtomicReference<Integer> receivedValue = new AtomicReference<>(null); + // No ConcurrentModificationException because of late-binding Spliterator + boolean didAdvance = spliterator.tryAdvance(value -> receivedValue.set(value)); + // Expect the values at index 0 from after the add(), not from after the spliterator(). + assertEquals(newFirstValue, receivedValue.get()); + assertTrue(didAdvance); + } + + @Test public void spliterator_modification_failFast() { + List<Integer> list = new RandomAccessList(50); + Integer expectedValue = list.get(2); + Spliterator<Integer> spliterator = list.spliterator(); + // We need to perform at least one action on the spliterator because only then does + // it initialize its internal expectedModCount. + assertTrue(spliterator.tryAdvance(value -> {})); + assertTrue(spliterator.tryAdvance(value -> {})); + list.add(42); // concurrent modification + AtomicReference<Integer> receivedValue = new AtomicReference<>(null); + try { + spliterator.tryAdvance(value -> receivedValue.set(value)); + fail(); + } catch (ConcurrentModificationException expected) { + } + // I believe it would also be within spec for this to remain unset (null), + // but the current implementation checks for concurrent modification only after + // delivering the value. We're asserting that so that we notice if the behavior + // ever changes in future. + assertEquals(expectedValue, receivedValue.get()); + } + + @Test public void spliteratorOfRandomAccessList_usesOnlyRandomAccess() { + checkSpliteratorOfOnlyRandomAccessList_usesOnlyRandomAccess(0); + checkSpliteratorOfOnlyRandomAccessList_usesOnlyRandomAccess(1); + checkSpliteratorOfOnlyRandomAccessList_usesOnlyRandomAccess(2); + checkSpliteratorOfOnlyRandomAccessList_usesOnlyRandomAccess(100); + } + + private static void checkSpliteratorOfOnlyRandomAccessList_usesOnlyRandomAccess(int listSize) { + checkSpliteratorOfRandomAccessList(listSize, + () -> new OnlyRandomAccessList(listSize)); + int subListSize = listSize / 2; + checkSpliteratorOfRandomAccessList( + subListSize, + () -> new OnlyRandomAccessList(listSize).subList(0, subListSize)); + } + + /** + * Checks basic operations on supplied RandomAccess Lists. If the supplied Lists are + * {@link OnlyRandomAccessList} or its sublists, then that has the side-effect of + * checking that only random-access operations are attempted. + */ + // We're using a Supplier<List> to keep constructing new Lists because some of the testers + // have the side effect of sorting the List. + private static void checkSpliteratorOfRandomAccessList(int size, + Supplier<List<Integer>> listSupplier) { + assertTrue(listSupplier.get() instanceof RandomAccess); + assertEquals(size, listSupplier.get().size()); + + Supplier<Spliterator<Integer>> spliteratorSupplier = () -> listSupplier.get().spliterator(); + List<Integer> expectedList = new ArrayList<>(); + for (int index = 0; index < size; index++) { + expectedList.add(RandomAccessList.initialValue(index)); + } + + SpliteratorTester.runBasicIterationTests(spliteratorSupplier.get(), expectedList); + SpliteratorTester.runBasicSplitTests(spliteratorSupplier.get(), expectedList, + Comparator.naturalOrder()); + SpliteratorTester.testSpliteratorNPE(spliteratorSupplier.get()); + + assertTrue(spliteratorSupplier.get().hasCharacteristics( + Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED)); + + SpliteratorTester.runSizedTests(spliteratorSupplier.get(), size /* expected size */); + if (spliteratorSupplier.get().trySplit() != null) { + SpliteratorTester.runSubSizedTests(spliteratorSupplier.get(), size); + } else { + assertTrue(size <= 1); // trySplit() should work for lists sized > 1. + } + } + + static class SequentialList extends AbstractSequentialList<Integer> { + private final List<Integer> delegate; + + public SequentialList(Integer... elements) { + this.delegate = Collections.unmodifiableList(Arrays.asList(elements)); + } + + @Override public ListIterator<Integer> listIterator(int index) { + return delegate.listIterator(index); + } + + @Override public int size() { return delegate.size(); } + } + + /** + * A simple list that allows random-access {@code get()} and modifications. This + * implementation increases {@link AbstractList#modCount} during {@code add()} + * and {@code remove()} to provide fail-fast Spliterators. + */ + static class RandomAccessList extends AbstractList<Integer> implements RandomAccess { + protected final List<Integer> delegate; + + public RandomAccessList(int size) { + this.delegate = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + delegate.add(initialValue(i)); + } + } + + static Integer initialValue(int index) { return 31337 ^ index; } + + @Override public Integer get(int index) { return delegate.get(index); } + @Override public int size() { return delegate.size(); } + @Override public Integer set(int index, Integer v) { return delegate.set(index, v); } + @Override public void add(int index, Integer element) { + modCount++; + delegate.add(index, element); + } + @Override public Integer remove(int index) { + modCount++; + return delegate.remove(index); + } + } + + /** + * A {@link RandomAccessList} that throws if a caller attempts {@link #iterator() + * iterative access}. + */ + static class OnlyRandomAccessList extends RandomAccessList { + public OnlyRandomAccessList(int size) { + super(size); + } + @Override public Iterator<Integer> iterator() { + throw new AssertionFailedError(); + } + + @Override public ListIterator<Integer> listIterator(int index) { + throw new AssertionFailedError(); + } + + } + +} diff --git a/luni/src/test/java/libcore/java/util/ArraysTest.java b/luni/src/test/java/libcore/java/util/ArraysTest.java index b48e8eaf6e..5a2bfe2749 100644 --- a/luni/src/test/java/libcore/java/util/ArraysTest.java +++ b/luni/src/test/java/libcore/java/util/ArraysTest.java @@ -16,15 +16,31 @@ package libcore.java.util; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.util.Arrays; +import java.util.List; import java.util.Random; +import java.util.stream.Collectors; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ArraysTest { + private static final int[] TEST_ARRAY_SIZES = { 0, 1, 2, 10, 100, 1000 }; -public class ArraysTest extends junit.framework.TestCase { /** * java.util.Arrays#setAll(int[], java.util.function.IntUnaryOperator) */ - public void test_setAll$I() { + @Test + public void setAll$I() { int[] list = new int[3]; list[0] = 0; list[1] = 1; @@ -51,7 +67,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Arrays#parallelSetAll(int[], java.util.function.IntUnaryOperator) */ - public void test_parallelSetAll$I() { + @Test + public void parallelSetAll$I() { int[] list = new int[3]; list[0] = 0; list[1] = 1; @@ -78,7 +95,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Arrays#setAll(long[], java.util.function.IntToLongFunction) */ - public void test_setAll$L() { + @Test + public void setAll$L() { long[] list = new long[3]; list[0] = 0; list[1] = 1; @@ -105,7 +123,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Arrays#parallelSetAll(long[], java.util.function.IntToLongFunction) */ - public void test_parallelSetAll$L() { + @Test + public void parallelSetAll$L() { long[] list = new long[3]; list[0] = 0; list[1] = 1; @@ -132,16 +151,17 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Arrays#setAll(double[], java.util.function.IntToDoubleFunction) */ - public void test_setAll$D() { + @Test + public void setAll$D() { double[] list = new double[3]; list[0] = 0.0d; list[1] = 1.0d; list[2] = 2.0d; Arrays.setAll(list, x -> x + 0.5); - assertEquals(0.5d, list[0]); - assertEquals(1.5d, list[1]); - assertEquals(2.5d, list[2]); + assertEquals(0.5d, list[0], 0.0); + assertEquals(1.5d, list[1], 0.0); + assertEquals(2.5d, list[2], 0.0); try { Arrays.setAll(list, null); @@ -159,16 +179,17 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Arrays#parallelSetAll(double[], java.util.function.IntToDoubleFunction) */ - public void test_parallelSetAll$D() { + @Test + public void parallelSetAll$D() { double[] list = new double[3]; list[0] = 0.0d; list[1] = 1.0d; list[2] = 2.0d; Arrays.parallelSetAll(list, x -> x + 0.5); - assertEquals(0.5d, list[0]); - assertEquals(1.5d, list[1]); - assertEquals(2.5d, list[2]); + assertEquals(0.5d, list[0], 0.0); + assertEquals(1.5d, list[1], 0.0); + assertEquals(2.5d, list[2], 0.0); try { Arrays.parallelSetAll(list, null); @@ -186,7 +207,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Array#setAll(T[], java.util.function.IntFunction<\? extends T>) */ - public void test_setAll$T() { + @Test + public void setAll$T() { String[] strings = new String[3]; strings[0] = "a"; strings[0] = "b"; @@ -213,7 +235,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Array#parallelSetAll(T[], java.util.function.IntFunction<\? extends T>) */ - public void test_parallelSetAll$T() { + @Test + public void parallelSetAll$T() { String[] strings = new String[3]; strings[0] = "a"; strings[0] = "b"; @@ -240,7 +263,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Array#parallelPrefix(int[], java.util.function.IntBinaryOperator) */ - public void test_parallelPrefix$I() { + @Test + public void parallelPrefix$I() { // Get an arbitrary array of ints. Random rand = new Random(0); int[] list = new int[1000]; @@ -256,7 +280,7 @@ public class ArraysTest extends junit.framework.TestCase { } Arrays.parallelPrefix(list, (x, y) -> x + y); - assertTrue(Arrays.equals(seqResult, list)); + assertArrayEquals(seqResult, list); try { Arrays.parallelPrefix(list, null); @@ -274,7 +298,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Array#parallelPrefix(int[], int, int, java.util.function.IntBinaryOperator) */ - public void test_parallelPrefix$III() { + @Test + public void parallelPrefix$III() { // Get an arbitrary array of ints. Random rand = new Random(0); int[] list = new int[1000]; @@ -291,7 +316,7 @@ public class ArraysTest extends junit.framework.TestCase { } Arrays.parallelPrefix(list, begin, end, (x, y) -> x + y); - assertTrue(Arrays.equals(seqResult, list)); + assertArrayEquals(seqResult, list); try { Arrays.parallelPrefix(list, begin, end, null); @@ -315,7 +340,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Array#parallelPrefix(long[], java.util.function.LongBinaryOperator) */ - public void test_parallelPrefix$L() { + @Test + public void parallelPrefix$L() { // Get an arbitrary array of ints. Random rand = new Random(0); long[] list = new long[1000]; @@ -331,7 +357,7 @@ public class ArraysTest extends junit.framework.TestCase { } Arrays.parallelPrefix(list, (x, y) -> x + y); - assertTrue(Arrays.equals(seqResult, list)); + assertArrayEquals(seqResult, list); try { Arrays.parallelPrefix(list, null); @@ -349,7 +375,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Array#parallelPrefix(long[], int, int, java.util.function.LongBinaryOperator) */ - public void test_parallelPrefix$LII() { + @Test + public void parallelPrefix$LII() { // Get an arbitrary array of ints. Random rand = new Random(0); long[] list = new long[1000]; @@ -366,7 +393,7 @@ public class ArraysTest extends junit.framework.TestCase { } Arrays.parallelPrefix(list, begin, end, (x, y) -> x + y); - assertTrue(Arrays.equals(seqResult, list)); + assertArrayEquals(seqResult, list); try { Arrays.parallelPrefix(list, begin, end, null); @@ -390,7 +417,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Array#parallelPrefix(double[], java.util.function.DoubleBinaryOperator) */ - public void test_parallelPrefix$D() { + @Test + public void parallelPrefix$D() { // Get an arbitrary array of ints. Random rand = new Random(0); double[] list = new double[1000]; @@ -410,7 +438,7 @@ public class ArraysTest extends junit.framework.TestCase { // Parallel double arithmetic contains error, reduce to integer for comparison. int[] listInInt = Arrays.stream(list).mapToInt(x -> (int) x).toArray(); int[] seqResultInInt = Arrays.stream(seqResult).mapToInt(x -> (int) x).toArray(); - assertTrue(Arrays.equals(seqResultInInt, listInInt)); + assertArrayEquals(seqResultInInt, listInInt); try { Arrays.parallelPrefix(list, null); @@ -428,7 +456,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Array#parallelPrefix(double[], int, int, java.util.function.DoubleBinaryOperator) */ - public void test_parallelPrefix$DII() { + @Test + public void parallelPrefix$DII() { // Get an arbitrary array of ints. Random rand = new Random(0); double[] list = new double[1000]; @@ -449,7 +478,7 @@ public class ArraysTest extends junit.framework.TestCase { // Parallel double arithmetic contains error, reduce to integer for comparison. int[] listInInt = Arrays.stream(list).mapToInt(x -> (int) x).toArray(); int[] seqResultInInt = Arrays.stream(seqResult).mapToInt(x -> (int) x).toArray(); - assertTrue(Arrays.equals(seqResultInInt, listInInt)); + assertArrayEquals(seqResultInInt, listInInt); try { Arrays.parallelPrefix(list, begin, end, null); @@ -473,7 +502,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Array#parallelPrefix(T[], java.util.function.BinaryOperator<T>) */ - public void test_parallelPrefix$T() { + @Test + public void parallelPrefix$T() { String[] strings = new String[3]; strings[0] = "a"; strings[1] = "b"; @@ -500,7 +530,8 @@ public class ArraysTest extends junit.framework.TestCase { /** * java.util.Array#parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>) */ - public void test_parallelPrefix$TII() { + @Test + public void parallelPrefix$TII() { String[] strings = new String[5]; strings[0] = "a"; strings[1] = "b"; @@ -536,9 +567,389 @@ public class ArraysTest extends junit.framework.TestCase { } // http://b/74236526 - public void test_deepEquals_nestedArraysOfDifferentTypesButEqualValues() { + @Test + public void deepEquals_nestedArraysOfDifferentTypesButEqualValues() { assertTrue(Arrays.deepEquals( new Object[] { new Object[] { "Hello", "world" } }, new Object[] { new String[] { "Hello", "world" } })); } + + @Test + public void streamInt() { + for (int size : TEST_ARRAY_SIZES) { + int[] sourceArray = intTestArray(size); + + // Stream, map, accumulate + int sum = Arrays.stream(sourceArray) + .map(i -> i + i) + .sum(); + assertEquals(size * (size - 1), sum); + + // Stream, collect as array again + int[] destArray = Arrays.stream(sourceArray) + .toArray(); + assertArrayEquals(sourceArray, destArray); + assertNotSame(sourceArray, destArray); + + // Stream, box, collect as list + List<Integer> destList = Arrays.stream(sourceArray) + .boxed() + .collect(Collectors.toList()); + + assertEquals(size, destList.size()); + for (int i = 0; i < size; i++) { + assertEquals((int) destList.get(i), i); + } + } + } + + @Test + public void streamIntStartEnd() { + final int size = 10; + int[] sourceArray = intTestArray(size); + for (int start = 0; start < size - 1; start++) { + for (int end = start; end < size; end++) { + int[] destArray = Arrays.stream(sourceArray, start, end) + .toArray(); + int len = end - start; + assertEquals(len, destArray.length); + if (len > 0) { + assertEquals(start, destArray[0]); + assertEquals(end - 1, destArray[len - 1]); + } + } + } + } + + @Test + public void streamIntStartEnd_Exceptions() { + int[] sourceArray = intTestArray(10); + try { + int unused = Arrays.stream(sourceArray, -1, 9) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + int unused = Arrays.stream(sourceArray, 0, 11) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + int unused = Arrays.stream(sourceArray, 11, 11) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + int unused = Arrays.stream(sourceArray, 0, -1) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + int unused = Arrays.stream(sourceArray, 4, 3) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @Test + public void streamLong() { + for (int size : TEST_ARRAY_SIZES) { + long[] sourceArray = longTestArray(size); + + // Stream, map, accumulate + long sum = Arrays.stream(sourceArray) + .map(i -> i + i) + .sum(); + assertEquals(size * (size - 1), sum); + + // Stream, collect as array again + long[] destArray = Arrays.stream(sourceArray) + .toArray(); + assertArrayEquals(sourceArray, destArray); + assertNotSame(sourceArray, destArray); + + // Stream, box, collect as list + List<Long> destList = Arrays.stream(sourceArray) + .boxed() + .collect(Collectors.toList()); + + assertEquals(size, destList.size()); + for (int i = 0; i < size; i++) { + assertEquals((long) destList.get(i), i); + } + } + } + + @Test + public void streamLongStartEnd() { + final int size = 10; + long[] sourceArray = longTestArray(size); + for (int start = 0; start < size - 1; start++) { + for (int end = start; end < size; end++) { + long[] destArray = Arrays.stream(sourceArray, start, end) + .toArray(); + int len = end - start; + assertEquals(len, destArray.length); + if (len > 0) { + assertEquals(start, destArray[0]); + assertEquals(end - 1, destArray[len - 1]); + } + } + } + } + + @Test + public void streamLongStartEnd_Exceptions() { + long[] sourceArray = longTestArray(10); + try { + long unused = Arrays.stream(sourceArray, -1, 9) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + long unused = Arrays.stream(sourceArray, 0, 11) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + long unused = Arrays.stream(sourceArray, 11, 11) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + long unused = Arrays.stream(sourceArray, 0, -1) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + long unused = Arrays.stream(sourceArray, 4, 3) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @Test + public void streamDouble() { + for (int size : TEST_ARRAY_SIZES) { + double[] sourceArray = doubleTestArray(size); + + // Stream, map, accumulate + double sum = Arrays.stream(sourceArray) + .map(i -> i + i) + .sum(); + assertEquals(size * (size - 1), sum, 0.001); + + // Stream, collect as array again + double[] destArray = Arrays.stream(sourceArray) + .toArray(); + assertArrayEquals(sourceArray, destArray, 0.001); + assertNotSame(sourceArray, destArray); + + // Stream, box, collect as list + List<Double> destList = Arrays.stream(sourceArray) + .boxed() + .collect(Collectors.toList()); + + assertEquals(size, destList.size()); + for (int i = 0; i < size; i++) { + assertEquals(destList.get(i), i, 0.001); + } + } + } + + @Test + public void streamDoubleStartEnd() { + final int size = 10; + double[] sourceArray = doubleTestArray(size); + for (int start = 0; start < size - 1; start++) { + for (int end = start; end < size; end++) { + double[] destArray = Arrays.stream(sourceArray, start, end) + .toArray(); + int len = end - start; + assertEquals(len, destArray.length); + if (len > 0) { + assertEquals(start, destArray[0], 0.0); + assertEquals(end - 1, destArray[len - 1], 0.0); + } + } + } + } + + @Test + public void streamDoubleStartEnd_Exceptions() { + double[] sourceArray = doubleTestArray(10); + try { + double unused = Arrays.stream(sourceArray, -1, 9) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + double unused = Arrays.stream(sourceArray, 0, 11) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + double unused = Arrays.stream(sourceArray, 11, 11) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + double unused = Arrays.stream(sourceArray, 0, -1) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + double unused = Arrays.stream(sourceArray, 4, 3) + .sum(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @Test + public void streamObject() { + for (int size : TEST_ARRAY_SIZES) { + String[] sourceArray = stringTestArray(size); + + // Stream, map, accumulate + int sum = Arrays.stream(sourceArray) + .mapToInt(i -> Integer.parseInt(i) * 2) + .sum(); + assertEquals(size * (size - 1), sum); + + // Stream, collect as array again + String[] destArray = Arrays.stream(sourceArray) + .toArray(String[]::new); + assertArrayEquals(sourceArray, destArray); + assertNotSame(sourceArray, destArray); + + // Stream, collect as list + List<String> destList = Arrays.stream(sourceArray) + .collect(Collectors.toList()); + + assertEquals(size, destList.size()); + for (int i = 0; i < size; i++) { + assertSame(destList.get(i), sourceArray[i]); + } + } + } + + @Test + public void streamObjectStartEnd() { + final int size = 10; + String[] sourceArray = stringTestArray(size); + for (int start = 0; start < size - 1; start++) { + for (int end = start; end < size; end++) { + String[] destArray = Arrays.stream(sourceArray, start, end) + .toArray(String[]::new); + int len = end - start; + assertEquals(len, destArray.length); + if (len > 0) { + assertSame(sourceArray[start], destArray[0]); + assertSame(sourceArray[end - 1], destArray[len - 1]); + } + } + } + } + + @Test + public void streamObjectStartEnd_Exceptions() { + String[] sourceArray = stringTestArray(10); + try { + long unused = Arrays.stream(sourceArray, -1, 9) + .count(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + long unused = Arrays.stream(sourceArray, 0, 11) + .count(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + long unused = Arrays.stream(sourceArray, 11, 11) + .count(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + long unused = Arrays.stream(sourceArray, 0, -1) + .count(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + try { + long unused = Arrays.stream(sourceArray, 4, 3) + .count(); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + private int[] intTestArray(int size) { + int[] array = new int[size]; + for (int i = 0; i < size; i++) { + array[i] = i; + } + return array; + } + + private long[] longTestArray(int size) { + long[] array = new long[size]; + for (int i = 0; i < size; i++) { + array[i] = i; + } + return array; + } + + private double[] doubleTestArray(int size) { + double[] array = new double[size]; + for (int i = 0; i < size; i++) { + array[i] = i; + } + return array; + } + + private String[] stringTestArray(int size) { + String[] array = new String[size]; + for (int i = 0; i < size; i++) { + array[i] = String.valueOf(i); + } + return array; + } } diff --git a/luni/src/test/java/libcore/java/util/ComparatorTest.java b/luni/src/test/java/libcore/java/util/ComparatorTest.java index a636ea6b10..6516df5aff 100644 --- a/luni/src/test/java/libcore/java/util/ComparatorTest.java +++ b/luni/src/test/java/libcore/java/util/ComparatorTest.java @@ -16,6 +16,7 @@ package libcore.java.util; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; @@ -35,17 +36,22 @@ public final class ComparatorTest extends TestCase { private static final Item ONEZERO = new Item(1, 0); private static final Item ONEONE = new Item(1, 1); - private static final Item[] orderedItems = new Item[]{ZERO, ONE, TWO, THREE, FOUR}; - private static final Item[] nullsFirstItems = new Item[]{null, ZERO, ONE, TWO, THREE, FOUR}; - private static final Item[] nullsLastItems = new Item[]{ZERO, ONE, TWO, THREE, FOUR, null}; - private static final Item[] orderedItemsMatrix = new Item[]{ZEROZERO, ZEROONE, ONEZERO, ONEONE}; - - private <T> void checkComparison(Comparator<T> comparator, T[] items) { - for (int i = 0; i < items.length - 1; ++i) { - assertEquals(0, comparator.compare(items[i], items[i])); - for (int j = i + 1; j < items.length; ++j) { - assertTrue(comparator.compare(items[i], items[j]) < 0); - assertTrue(comparator.compare(items[j], items[i]) > 0); + private final List<Item> orderedItems = listOf(ZERO, ONE, TWO, THREE, FOUR); + private final List<Item> nullsFirstItems = listOf(null, ZERO, ONE, TWO, THREE, FOUR); + private final List<Item> nullsLastItems = listOf(ZERO, ONE, TWO, THREE, FOUR, null); + private final List<Item> orderedItemsMatrix = listOf(ZEROZERO, ZEROONE, ONEZERO, ONEONE); + + private static<T> List<T> listOf(T... values) { + return Collections.unmodifiableList(Arrays.asList(values)); + } + + private <T> void checkComparison(Comparator<T> comparator, List<T> items) { + for (int i = 0; i < items.size() - 1; ++i) { + T a = items.get(i); + assertEquals(0, comparator.compare(a, a)); + for (T b : items.subList(i+1, items.size())) { + assertTrue(comparator.compare(a, b) < 0); + assertTrue(comparator.compare(b, a) > 0); } } } @@ -83,10 +89,11 @@ public final class ComparatorTest extends TestCase { } public void testReverseOrder() { - List<Item> itemsList = Arrays.asList(orderedItems); + // Make a copy that we can reverse. http://b/139015474 + List<Item> itemsList = new ArrayList<>(orderedItems); Collections.reverse(itemsList); Comparator<Item> comparator = Comparator.reverseOrder(); - checkComparison(comparator, (Item[]) itemsList.toArray()); + checkComparison(comparator, itemsList); } public void testReverse() { diff --git a/luni/src/test/java/libcore/java/util/DateTest.java b/luni/src/test/java/libcore/java/util/DateTest.java index 1fd8193b26..9cd986861b 100644 --- a/luni/src/test/java/libcore/java/util/DateTest.java +++ b/luni/src/test/java/libcore/java/util/DateTest.java @@ -51,18 +51,14 @@ public class DateTest extends TestCase { c.set(Calendar.YEAR, 21); assertEquals("Wed Jan 01 00:00:00 PST 21", c.getTime().toString()); String actual21GmtString = c.getTime().toGMTString(); - // zic <= 2014b data gives -08:00:00, later ones gives -07:52:58 instead. http://b/73719425 - assertTrue("Actual: " + actual21GmtString, - "1 Jan 21 07:52:58 GMT".equals(actual21GmtString) - || "1 Jan 21 08:00:00 GMT".equals(actual21GmtString)); + // zic <= 2014b data produces -08:00:00, later ones produce -07:52:58 instead. + assertEquals("1 Jan 21 07:52:58 GMT", actual21GmtString); c.set(Calendar.YEAR, 321); assertEquals("Sun Jan 01 00:00:00 PST 321", c.getTime().toString()); String actual321GmtString = c.getTime().toGMTString(); - // zic <= 2014b data gives -08:00:00, later ones gives -07:52:58 instead. http://b/73719425 - assertTrue("Actual: " + actual321GmtString, - "1 Jan 321 07:52:58 GMT".equals(actual321GmtString) - || "1 Jan 321 08:00:00 GMT".equals(actual321GmtString)); + // zic <= 2014b data produces -08:00:00, later ones produce -07:52:58 instead. + assertEquals("1 Jan 321 07:52:58 GMT", actual321GmtString); } public void test_toGMTString_nonUs() throws Exception { @@ -74,18 +70,14 @@ public class DateTest extends TestCase { c.set(Calendar.YEAR, 21); assertEquals("Wed Jan 01 00:00:00 PST 21", c.getTime().toString()); String actual21GmtString = c.getTime().toGMTString(); - // zic <= 2014b data gives -08:00:00, later ones gives -07:52:58 instead. http://b/73719425 - assertTrue("Actual: " + actual21GmtString, - "1 Jan 21 07:52:58 GMT".equals(actual21GmtString) - || "1 Jan 21 08:00:00 GMT".equals(actual21GmtString)); + // zic <= 2014b data produces -08:00:00, later ones produce -07:52:58 instead. + assertEquals("1 Jan 21 07:52:58 GMT", actual21GmtString); c.set(Calendar.YEAR, 321); assertEquals("Sun Jan 01 00:00:00 PST 321", c.getTime().toString()); String actual321GmtString = c.getTime().toGMTString(); - // zic <= 2014b data gives -08:00:00, later ones gives -07:52:58 instead. http://b/73719425 - assertTrue("Actual: " + actual321GmtString, - "1 Jan 321 07:52:58 GMT".equals(actual321GmtString) - || "1 Jan 321 08:00:00 GMT".equals(actual321GmtString)); + // zic <= 2014b data produces -08:00:00, later ones produce -07:52:58 instead. + assertEquals("1 Jan 321 07:52:58 GMT", actual321GmtString); } public void test_parse_timezones() { diff --git a/luni/src/test/java/libcore/java/util/ListOfTest.java b/luni/src/test/java/libcore/java/util/ListOfTest.java new file mode 100644 index 0000000000..04b787ff79 --- /dev/null +++ b/luni/src/test/java/libcore/java/util/ListOfTest.java @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.java.util; + +import org.junit.Test; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; +import libcore.libcore.util.SerializationTester; +import libcore.util.NonNull; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class ListOfTest { + + @Test + public void serializationCompatibility_empty() { + String golden = "ACED00057372001F6A6176612E7574696C2E436F6C6C656374696F6E7324456D7074794C69" + + "73747AB817B43CA79EDE0200007870"; + new SerializationTester<>(List.<String>of(), golden).test(); + } + + @Test public void serializationCompatibility_oneElement() { + String golden = "ACED0005737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F646966" + + "6961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C" + + "2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F64696669" + + "61626C65436F6C6C656374696F6E19420080CB5EF71E0200014C0001637400164C6A6176612F7574" + + "696C2F436F6C6C656374696F6E3B7870737200136A6176612E7574696C2E41727261794C69737478" + + "81D21D99C7619D03000149000473697A657870000000017704000000017400036F6E657871007E00" + + "06"; + new SerializationTester<>(List.of("one"), golden).test(); + } + + @Test public void serializationCompatibility_manyElements() { + String golden = "ACED0005737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F646966" + + "6961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C" + + "2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F64696669" + + "61626C65436F6C6C656374696F6E19420080CB5EF71E0200014C0001637400164C6A6176612F7574" + + "696C2F436F6C6C656374696F6E3B7870737200136A6176612E7574696C2E41727261794C69737478" + + "81D21D99C7619D03000149000473697A6578700000000D77040000000D737200116A6176612E6C61" + + "6E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C61" + + "6E672E4E756D62657286AC951D0B94E08B02000078700000000C7371007E00070000000B7371007E" + + "00070000000A7371007E0007000000097371007E0007000000087371007E0007000000077371007E" + + "0007000000067371007E0007000000057371007E0007000000047371007E0007000000037371007E" + + "0007000000027371007E0007000000017371007E0007000000007871007E0006"; + new SerializationTester<>(List.of(12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), golden).test(); + } + + @Test public void mixedTypes() { + List<?> list = List.of("element", 42); + assertEquals(asList("element", 42), list); + + assertTrue(list.contains("element")); + assertTrue(list.contains(42)); + assertFalse(list.contains(new Object())); + assertFalse(list.contains(31)); + } + + @Test public void duplicates_allowed() { + // duplicates values are allowed for List.of(), but not for Set.of() + check_nonEmpty(asList("duplicate", "duplicate"), List.of("duplicate", "duplicate")); + } + + @Test public void empty() { + assertBehaviorCommonToAllOfInstances( + Collections.<String>emptyList(), List.<String>of(), "non-null example String"); + } + + @Test public void nonEmpty() { + check_nonEmpty(asList("one"), List.of("one")); + check_nonEmpty(asList("one", "two"), List.of("one", "two")); + check_nonEmpty(asList("one", "two", "three"), List.of("one", "two", "three")); + check_nonEmpty(asList("one", "two", "three", "four"), + List.of("one", "two", "three", "four")); + check_nonEmpty(asList("one", "two", "three", "four", "five"), + List.of("one", "two", "three", "four", "five")); + check_nonEmpty(asList("one", "two", "three", "four", "five", "six"), + List.of("one", "two", "three", "four", "five", "six")); + check_nonEmpty(asList("one", "two", "three", "four", "five", "six", "seven"), + List.of("one", "two", "three", "four", "five", "six", "seven")); + check_nonEmpty(asList(1, 2, 3, 4, 5, 6, 7, 8), List.of(1, 2, 3, 4, 5, 6, 7, 8)); + check_nonEmpty(asList(1, 2, 3, 4, 5, 6, 7, 8, 9), List.of(1, 2, 3, 4, 5, 6, 7, 8, 9)); + check_nonEmpty(asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), + List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); + check_nonEmpty(asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), + List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)); + check_nonEmpty(asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), + List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)); + check_nonEmpty(asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13), + List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)); + } + + @Test public void null_examples() { + assertThrowsNpe(() -> List.<String>of((String) null)); // one-arg version + assertThrowsNpe(() -> List.<String[]>of((String[]) null)); // null var-args array + assertThrowsNpe(() -> List.<String>of(new String[] { "one", null, "three"})); // var-args + + assertThrowsNpe(() -> List.of(null, "two")); + assertThrowsNpe(() -> List.of("one", null)); + assertThrowsNpe( + () -> List.of(null, "two", "three", "four", "five", "six", "seven")); + assertThrowsNpe( + () -> List.of("one", "two", "three", "four", "five", "six", null)); + } + + @Test public void null_comprehensive() { + List<Integer> template = asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); + for (int i = 0; i < template.size(); i++) { + Integer[] l = template.toArray(new Integer[0]); + l[i] = null; + npe(i <= 0, () -> List.of(l[0])); + npe(i <= 1, () -> List.of(l[0], l[1])); + npe(i <= 2, () -> List.of(l[0], l[1], l[2])); + npe(i <= 3, () -> List.of(l[0], l[1], l[2], l[3])); + npe(i <= 4, () -> List.of(l[0], l[1], l[2], l[3], l[4])); + npe(i <= 5, () -> List.of(l[0], l[1], l[2], l[3], l[4], l[5])); + npe(i <= 6, () -> List.of(l[0], l[1], l[2], l[3], l[4], l[5], l[6])); + npe(i <= 7, () -> List.of(l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7])); + npe(i <= 8, () -> List.of(l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8])); + npe(i <= 9, () -> List.of(l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8], l[9])); + npe(i <= 10, () -> List.of( + l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8], l[9], l[10])); + npe(i <= 11, () -> List.of( + l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8], l[9], l[10], l[11])); + npe(i <= 12, () -> List.of( + l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8], l[9], l[10], l[11], l[12]) + ); + } + } + + /** + * Asserts that {@code runnable.run()} throws {@link NullPointerException} if + * any only if {@code expectedToThrowNpe}. + */ + private static void npe(boolean expectedToThrowNpe, Runnable runnable) { + if (expectedToThrowNpe) { + assertThrowsNpe(runnable); + } else { + runnable.run(); // should not throw + } + } + + private static<T extends Comparable<T>> void check_nonEmpty(List<T> expected, List<T> actual) { + T example = actual.iterator().next(); + assertBehaviorCommonToAllOfInstances(expected, actual, example); + } + + /** Checks assertions that hold for all List.of() instances. */ + private static<T extends Comparable<T>> void assertBehaviorCommonToAllOfInstances( + List<T> expected, List<T> actual, @NonNull T example) { + assertNotNull(example); + assertEquals(expected, actual); + assertEquals(expected.size(), actual.size()); + assertEquals(expected.hashCode(), actual.hashCode()); + assertEquals(actual.isEmpty(), actual.isEmpty()); + assertEquals(actual.size() == 0, actual.isEmpty()); + SpliteratorTester.runBasicIterationTests(actual.spliterator(), expected); + if (expected.isEmpty()) { + assertEquals(expected, actual.subList(0, 0)); + } else { + assertEquals(expected.subList(1, expected.size()), actual.subList(1, actual.size())); + } + assertEquals(expected.contains(example), actual.contains(example)); + assertFalse(actual.contains("absent-element")); + assertFalse(actual.contains(new Object())); + assertThrowsNpe(() -> actual.contains(null)); + assertEquals(expected.toString(), actual.toString()); + + assertUnmodifiable(actual, example); + assertEquals(actual, reserialize((Serializable) actual)); + assertTrue(actual instanceof RandomAccess); + } + + private static<T extends Comparable<T>> void assertUnmodifiable(List<T> list, T example) { + List<T> examples = Collections.singletonList(example); + assertThrowsUoe(() -> { list.add(example); } ); + assertThrowsUoe(() -> { list.addAll(examples); } ); + assertThrowsUoe(() -> { list.addAll(0, examples); } ); + // List.of() documentation guarantees that the following operations throw + // UnsupportedOperationException, even though some other implementations don't + // do that in the case of isEmpty(). + assertThrowsUoe(() -> { list.clear(); }); + assertThrowsUoe(() -> { list.remove(example); } ); + assertThrowsUoe(() -> { list.removeAll(examples); } ); + assertThrowsUoe(() -> { list.removeIf(Predicate.isEqual(example)); } ); + assertThrowsUoe(() -> { list.replaceAll(UnaryOperator.identity()); } ); + assertThrowsUoe(() -> { list.retainAll(examples); } ); + assertThrowsUoe(() -> { list.sort(Comparator.<T>naturalOrder()); } ); + } + + private static void assertThrowsUoe(Runnable runnable) { + try { + runnable.run(); + fail(); + } catch (UnsupportedOperationException expected) { + } + } + + private static void assertThrowsNpe(Runnable runnable) { + try { + runnable.run(); + fail(); + } catch (NullPointerException expected) { + } + } + + private static <S extends Serializable> S reserialize(S value) { + try { + return (S) SerializationTester.reserialize(value); + } catch (IOException | ClassNotFoundException e) { + fail("Unexpected exception: " + e.getMessage()); + throw new AssertionError(e); // unreachable + } + } +} diff --git a/luni/src/test/java/libcore/java/util/LocaleTest.java b/luni/src/test/java/libcore/java/util/LocaleTest.java index 33e427c38c..6cb9e17944 100644 --- a/luni/src/test/java/libcore/java/util/LocaleTest.java +++ b/luni/src/test/java/libcore/java/util/LocaleTest.java @@ -22,6 +22,7 @@ import static java.util.Locale.FilteringMode.IGNORE_EXTENDED_RANGES; import static java.util.Locale.FilteringMode.MAP_EXTENDED_RANGES; import static java.util.Locale.FilteringMode.REJECT_EXTENDED_RANGES; +import android.icu.util.ULocale; import java.io.ObjectInputStream; import java.text.BreakIterator; import java.text.Collator; @@ -30,13 +31,17 @@ import java.text.DateFormatSymbols; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Collections; +import java.util.HashSet; import java.util.IllformedLocaleException; import java.util.List; import java.util.Locale; import java.util.Locale.LanguageRange; import java.util.MissingResourceException; +import java.util.Set; +import java.util.stream.Collectors; public class LocaleTest extends junit.framework.TestCase { @@ -156,12 +161,10 @@ public class LocaleTest extends junit.framework.TestCase { public void test_getDisplayCountry_8870289() throws Exception { assertEquals("Hong Kong", new Locale("", "HK").getDisplayCountry(Locale.US)); - assertEquals("Macau", new Locale("", "MO").getDisplayCountry(Locale.US)); assertEquals("Palestine", new Locale("", "PS").getDisplayCountry(Locale.US)); assertEquals("Cocos (Keeling) Islands", new Locale("", "CC").getDisplayCountry(Locale.US)); assertEquals("Falkland Islands (Islas Malvinas)", new Locale("", "FK").getDisplayCountry(Locale.US)); - assertEquals("Macedonia (FYROM)", new Locale("", "MK").getDisplayCountry(Locale.US)); assertEquals("Myanmar (Burma)", new Locale("", "MM").getDisplayCountry(Locale.US)); assertEquals("Taiwan", new Locale("", "TW").getDisplayCountry(Locale.US)); } @@ -234,6 +237,19 @@ public class LocaleTest extends junit.framework.TestCase { assertOnce(newLocale, Locale.getAvailableLocales()); } + public void testGetAvailableLocales_icuConsistency() { + Locale[] javaLocales = Locale.getAvailableLocales(); + ULocale[] icuLocales = ULocale.getAvailableLocales(); + Set<Locale> javaSet = new HashSet<>(Arrays.asList(javaLocales)); + Set<Locale> icuSet = Arrays.stream(icuLocales) + .map(uLocale -> uLocale.toLocale()) + .collect(Collectors.toSet()); + assertEquals(javaSet, icuSet); + // Assert no duplicated entries + assertEquals(javaLocales.length, javaSet.size()); + assertEquals(icuLocales.length, icuSet.size()); + } + private static void assertOnce(Locale element, Locale[] array) { int count = 0; for (Locale l : array) { diff --git a/luni/src/test/java/libcore/java/util/MapOfTest.java b/luni/src/test/java/libcore/java/util/MapOfTest.java new file mode 100644 index 0000000000..68e20a754d --- /dev/null +++ b/luni/src/test/java/libcore/java/util/MapOfTest.java @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.java.util; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import libcore.libcore.util.SerializationTester; + +import static java.util.Map.entry; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Tests {@code Map.of()} overloads and {@code Map.ofEntries(...)}. + */ +@RunWith(Parameterized.class) +public class MapOfTest { + + @Test public void serializationCompatibility_empty() { + String golden = "ACED0005737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F646966" + + "6961626C654D6170F1A5A8FE74F507420200014C00016D74000F4C6A6176612F7574696C2F4D6170" + + "3B7870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F" + + "6164466163746F724900097468726573686F6C6478703F4000000000000177080000000100000000" + + "78"; + new SerializationTester<>(create(), golden).test(); + } + + @Test public void serializationCompatibility_oneElement() { + String golden = "ACED0005737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F646966" + + "6961626C654D6170F1A5A8FE74F507420200014C00016D74000F4C6A6176612F7574696C2F4D6170" + + "3B7870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F" + + "6164466163746F724900097468726573686F6C6478703F4000000000000177080000000200000001" + + "7400036F6E65737200116A6176612E6C616E672E496E746567657212E2A0A4F78187380200014900" + + "0576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000" + + "00000178"; + new SerializationTester<>(create(entry("one", 1)), golden).test(); + } + + @Test public void serializationCompatibility_manyElements() { + String golden = "ACED0005737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F646966" + + "6961626C654D6170F1A5A8FE74F507420200014C00016D74000F4C6A6176612F7574696C2F4D6170" + + "3B7870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F" + + "6164466163746F724900097468726573686F6C6478703F4000000000000C7708000000100000000A" + + "7400046E696E65737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149" + + "000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B0200007870" + + "000000097400037369787371007E000600000006740004666F75727371007E000600000004740003" + + "6F6E657371007E000600000001740005736576656E7371007E00060000000774000374656E737100" + + "7E00060000000A74000374776F7371007E00060000000274000574687265657371007E0006000000" + + "03740004666976657371007E00060000000574000565696768747371007E00060000000878"; + new SerializationTester<>( + create(entry("one", 1), entry("two", 2), entry("three", 3), + entry("four", 4), entry("five", 5), entry("six", 6), entry("seven", 7), + entry("eight", 8), entry("nine", 9), entry("ten", 10)), golden).test(); + } + + @Test public void duplicates_sameKey() { + Map.Entry[] entries = { entry("duplicateKey", 23), entry("duplicateKey", 42) }; + assertThrowsIae(() -> creator.create(entries)); + } + + @Test public void duplicates_sameEntry() { + Map.Entry[] entries = { entry("duplicateKey", 42), entry("duplicateKey", 42) }; + assertThrowsIae(() -> creator.create(entries)); + } + + @Test public void duplicates_manyElements() { + Map.Entry[] entries = { + entry("key1", 1), + entry("duplicateKey", 23), + entry("key2", 2), + entry("duplicateKey", 42) }; + assertThrowsIae(() -> creator.create(entries)); + } + + @Test public void empty() { + assertBehaviorCommonToAllOfInstances("exampleKey", 42); + } + + @Test public void nullEntries() { + assertThrowsNpe(() -> Map.ofEntries((Map.Entry[]) null)); + assertThrowsNpe(() -> Map.ofEntries((Map.Entry) null)); + List<Map.Entry<String, Integer>> sampleEntries = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + sampleEntries.add(entry("key" + i, i)); + } + for (int size = 0; size <= sampleEntries.size(); size++) { + for (int nullIndex = 0; nullIndex < size; nullIndex++) { + Map.Entry[] entries = sampleEntries.subList(0, size).toArray( + (Map.Entry<String, Integer>[]) new Map.Entry[0]); + entries[nullIndex] = null; + assertThrowsNpe(() -> Map.ofEntries(entries)); + } + } + } + + @Test public void oneEntry() { + assertBehaviorCommonToAllOfInstances( + "exampleKey", 42, entry("key", "value")); + } + + @Test public void twoEntries() { + assertBehaviorCommonToAllOfInstances( + "exampleKey", 42, entry("key1", "value1"), entry("key2", "value2")); + } + + @Test public void manyEntries() { + List<Map.Entry<String, Integer>> sampleEntries = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + sampleEntries.add(entry("key" + i, i)); + } + for (int size = 0; size <= sampleEntries.size(); size++) { + Map.Entry[] entries = sampleEntries.subList(0, size).toArray( + (Map.Entry<String, Integer>[]) new Map.Entry[0]); + assertBehaviorCommonToAllOfInstances("key0", 42, entries); + } + } + + @Test public void entry_nullKeyOrValue() { + assertThrowsNpe(() -> entry(null, "value")); + assertThrowsNpe(() -> entry("key", null)); + assertThrowsNpe(() -> entry(null, null)); + + // This one works + entry("key", "value"); + } + + @Test public void of_nullKeyOrValue() { + assertThrowsNpe(() -> Map.of(null, "value")); + assertThrowsNpe(() -> Map.of("key", null)); + assertThrowsNpe(() -> Map.of("k1", "v1", "k2", "v2", null, "v3", "k4", "v4")); + assertThrowsNpe(() -> Map.of("k1", "v1", "k2", "v2", "k3", null, "k4", "v4")); + } + + @Test public void mixedEntryTypes() { + assertBehaviorCommonToAllOfInstances( + "onekey", "new value", entry("oneKey", 1), entry(2, "twoValue")); + } + + private static<K, V> void assertUnmodifiable(Map<K, V> map, K exampleKey, V exampleValue) { + Map<K, V> exampleEntries = Collections.singletonMap(exampleKey, exampleValue); + assertThrowsUoe(() -> map.put(exampleKey, exampleValue)); + assertThrowsUoe(() -> map.putAll(exampleEntries)); + assertThrowsUoe(() -> map.remove(exampleKey)); + assertThrowsUoe(() -> map.remove(exampleKey, exampleValue)); + assertThrowsUoe(() -> map.clear()); + assertThrowsUoe(() -> map.replace(exampleKey, exampleValue, null)); + assertThrowsUoe(() -> map.putIfAbsent(exampleKey, exampleValue)); + assertThrowsUoe(() -> map.entrySet().clear()); + assertThrowsUoe(() -> map.keySet().clear()); + assertThrowsUoe(() -> map.values().clear()); + + if (!map.isEmpty()) { + Map.Entry<K, V> firstEntry = map.entrySet().iterator().next(); + assertThrowsUoe(() -> firstEntry.setValue(exampleValue)); + } + } + + /** Checks assertions that hold for all Map.of() / Map.ofEntries() instances. */ + private <K, V> void assertBehaviorCommonToAllOfInstances(K exampleKey, V exampleValue, + Map.Entry<K, V>...entries) { + Map<K, V> expected = hashMapOf(entries); + Map<K, V> actual = creator.create(entries); + assertBehaviorCommonToAllOfInstances(expected, actual, exampleKey, exampleValue); + } + + private static<K, V> void assertBehaviorCommonToAllOfInstances(Map<K, V> expected, + Map<K, V> actual, K exampleKey, V exampleValue) { + assertDoesNotSupportNull(actual); + assertMapEquals(expected, actual); + assertUnmodifiable(actual, exampleKey, exampleValue); + } + + private static<K, V> void assertDoesNotSupportNull(Map<K, V> map) { + assertThrowsNpe(() -> map.containsKey(null)); + assertThrowsNpe(() -> map.keySet().contains(null)); + assertThrowsNpe(() -> map.values().contains(null)); + } + + private static<K, V> void assertMapEquals(Map<K, V> expected, Map<K, V> actual) { + assertEquals(expected, actual); + assertEquals(actual, expected); + assertEquals(expected.size(), actual.size()); + assertEquals(expected.entrySet(), actual.entrySet()); + + assertSetEquals(expected.entrySet(), actual.entrySet()); + assertSetEquals(expected.keySet(), actual.keySet()); + assertCollectionEquals(new HashSet<>(expected.values()), new HashSet<>(actual.values())); + } + + private static<T> void assertSetEquals(Set<T> expected, Set<T> actual) { + assertCollectionEquals(expected, actual); + } + + private static<T> void assertCollectionEquals(Collection<T> expected, Collection<T> actual) { + assertEquals(expected, actual); + assertEquals(actual, expected); + assertEquals(expected.hashCode(), actual.hashCode()); + + assertEquals(expected.size(), actual.size()); + assertTrue(expected.containsAll(actual)); + assertTrue(actual.containsAll(expected)); + } + + private final Creator creator; + + public MapOfTest(Creator creator) { + this.creator = Objects.requireNonNull(creator); + } + + private<K, V> Map<K, V> create(Map.Entry<K, V>... entries) { + return creator.create(entries); + } + + @Parameterized.Parameters(name = "{0}") + public static Iterable<Creator> getCreators() { + return Arrays.asList(Creator.OF, Creator.OF_ENTRIES); + } + + private static<K, V> Map<K, V> hashMapOf(Map.Entry<K, V>... entries) { + HashMap<K, V> result = new HashMap<>(); + for (Map.Entry<K, V> entry : entries) { + result.put(entry.getKey(), entry.getValue()); + } + return result; + } + + enum Creator { + OF { + private<K,V> K k(int index, Map.Entry<K, V>... entries) { + return entries[index].getKey(); + } + private<K,V> V v(int index, Map.Entry<K, V>... entries) { + return entries[index].getValue(); + } + + @Override + <K, V> Map<K, V> create(Map.Entry<K, V>... e) { + switch (e.length) { + case 0: return Map.of(); + case 1: return Map.of(k(0, e), v(0, e)); + case 2: return Map.of(k(0, e), v(0, e), k(1, e), v(1, e)); + case 3: return Map.of(k(0, e), v(0, e), k(1, e), v(1, e), k(2, e), v(2, e)); + case 4: return Map.of(k(0, e), v(0, e), k(1, e), v(1, e), k(2, e), v(2, e), k(3, e), v(3, e)); + case 5: return Map.of(k(0, e), v(0, e), k(1, e), v(1, e), k(2, e), v(2, e), k(3, e), v(3, e), k(4, e), v(4, e)); + case 6: return Map.of(k(0, e), v(0, e), k(1, e), v(1, e), k(2, e), v(2, e), k(3, e), v(3, e), k(4, e), v(4, e), k(5, e), v(5, e)); + case 7: return Map.of(k(0, e), v(0, e), k(1, e), v(1, e), k(2, e), v(2, e), k(3, e), v(3, e), k(4, e), v(4, e), k(5, e), v(5, e), k(6, e), v(6, e)); + case 8: return Map.of(k(0, e), v(0, e), k(1, e), v(1, e), k(2, e), v(2, e), k(3, e), v(3, e), k(4, e), v(4, e), k(5, e), v(5, e), k(6, e), v(6, e), k(7, e), v(7, e)); + case 9: return Map.of(k(0, e), v(0, e), k(1, e), v(1, e), k(2, e), v(2, e), k(3, e), v(3, e), k(4, e), v(4, e), k(5, e), v(5, e), k(6, e), v(6, e), k(7, e), v(7, e), k(8, e), v(8, e)); + case 10: return Map.of(k(0, e), v(0, e), k(1, e), v(1, e), k(2, e), v(2, e), k(3, e), v(3, e), k(4, e), v(4, e), k(5, e), v(5, e), k(6, e), v(6, e), k(7, e), v(7, e), k(8, e), v(8, e), k(9, e), v(9, e)); + default: + fail(this + " requires 0 to 10 entries"); + throw new AssertionError("unreachable"); + } + + } + }, + OF_ENTRIES { + @Override + <K, V> Map<K, V> create(Map.Entry<K, V>... entries) { + return Map.ofEntries(entries); + } + } + ; + abstract <K,V> Map<K, V> create(Map.Entry<K,V>... entries); + } + + private static void assertThrowsIae(Runnable runnable) { + try { + runnable.run(); + fail(); + } catch (IllegalArgumentException expected) { + } + } + + private static void assertThrowsUoe(Runnable runnable) { + try { + runnable.run(); + fail(); + } catch (UnsupportedOperationException expected) { + } + } + + private static void assertThrowsNpe(Runnable runnable) { + try { + runnable.run(); + fail(); + } catch (NullPointerException expected) { + } + } +} diff --git a/luni/src/test/java/libcore/java/util/ObjectsTest.java b/luni/src/test/java/libcore/java/util/ObjectsTest.java index 735f6c572f..6e118e92c0 100644 --- a/luni/src/test/java/libcore/java/util/ObjectsTest.java +++ b/luni/src/test/java/libcore/java/util/ObjectsTest.java @@ -25,6 +25,111 @@ public class ObjectsTest extends junit.framework.TestCase { public String toString() { return "hello"; } } + public void test_checkFromIndexSize_valid() { + Objects.checkFromIndexSize(/* fromIndex */ 0, /* size */ 0, /* length */ 10); + Objects.checkFromIndexSize(/* fromIndex */ 10, /* size */ 0, /* length */ 10); + Objects.checkFromIndexSize(/* fromIndex */ 5, /* size */ 1, /* length */ 10); + Objects.checkFromIndexSize(/* fromIndex */ 0, /* size */ 10, /* length */ 10); + Objects.checkFromIndexSize(/* fromIndex */ 1, /* size */ 9, /* length */ 10); + Objects.checkFromIndexSize(/* fromIndex */ 0, /* size */ 9, /* length */ 10); + } + + public void test_checkFromIndexSize_negativeSize() { + assertFromIndexSizeOutOfBounds(/* fromIndex */ -1, /* size */ 10, /* length */ 100); + assertFromIndexSizeOutOfBounds(/* fromIndex */ 5, /* size */ -1, /* length */ 100); + assertFromIndexSizeOutOfBounds(/* fromIndex */ 0, /* size */ -1, /* length */ 100); + assertFromIndexSizeOutOfBounds(/* fromIndex */ 0, /* size */ -1, /* length */ -1); + assertFromIndexSizeOutOfBounds(/* fromIndex */ 0, /* size */ 0, /* length */ -1); + } + + public void test_checkFromIndexSize_beyondEnd() { + assertFromIndexSizeOutOfBounds(/* fromIndex */ 0, /* size */ 10, /* length */ 9); + assertFromIndexSizeOutOfBounds(/* fromIndex */ 1, /* size */ 10, /* length */ 10); + + // Invalid, but fromIndex + size overflows and is < length. + assertFromIndexSizeOutOfBounds(/* fromIndex */ Integer.MAX_VALUE - 10, /* size */ 11, + /* length */ Integer.MAX_VALUE); + } + + private static void assertFromIndexSizeOutOfBounds(int fromIndex, int size, int length) { + try { + Objects.checkFromIndexSize(fromIndex, size, length); + fail(); + } catch (IndexOutOfBoundsException expected) { + } + } + + public void test_checkFromToIndex_valid() { + Objects.checkFromToIndex(/* fromIndex */ 0, /* toIndex */ 0, /* length */ 10); + Objects.checkFromToIndex(/* fromIndex */ 10, /* toIndex */ 10, /* length */ 10); + Objects.checkFromToIndex(/* fromIndex */ 5, /* toIndex */ 6, /* length */ 10); + Objects.checkFromToIndex(/* fromIndex */ 0, /* toIndex */ 10, /* length */ 10); + Objects.checkFromToIndex(/* fromIndex */ 1, /* toIndex */ 10, /* length */ 10); + Objects.checkFromToIndex(/* fromIndex */ 0, /* toIndex */ 0, /* length */ 10); + } + + public void test_checkFromToIndex_negativeSize() { + assertFromToIndexOutOfBounds(/* fromIndex */ -1, /* toIndex */ 9, /* length */ 100); + assertFromToIndexOutOfBounds(/* fromIndex */ 5, /* toIndex */ 4, /* length */ 100); + assertFromToIndexOutOfBounds(/* fromIndex */ 0, /* toIndex */ -1, /* length */ 100); + assertFromToIndexOutOfBounds(/* fromIndex */ 0, /* toIndex */ -1, /* length */ -1); + assertFromToIndexOutOfBounds(/* fromIndex */ 0, /* toIndex */ 0, /* length */ -1); + } + + public void test_checkFromToIndex_beyondEnd() { + assertFromToIndexOutOfBounds(/* fromIndex */ 0, /* toIndex */ 10, /* length */ 9); + assertFromToIndexOutOfBounds(/* fromIndex */ 1, /* toIndex */ 11, /* length */ 10); + assertFromToIndexOutOfBounds(/* fromIndex */ Integer.MAX_VALUE - 10, + /* toIndex */ Integer.MIN_VALUE, /* length */ Integer.MAX_VALUE); + } + + private static void assertFromToIndexOutOfBounds(int fromIndex, int toIndex, int length) { + try { + Objects.checkFromToIndex(fromIndex, toIndex, length); + fail(); + } catch (IndexOutOfBoundsException expected) { + } + } + + public void test_checkIndex_empty() { + assertIndexOutOfBounds(0, 0); + assertIndexOutOfBounds(1, 0); + assertIndexOutOfBounds(-1, 0); + assertIndexOutOfBounds(100, 0); + assertIndexOutOfBounds(-100, 0); + assertIndexOutOfBounds(Integer.MAX_VALUE, 0); + assertIndexOutOfBounds(Integer.MAX_VALUE, 0); + } + + public void test_checkIndex_size1() { + Objects.checkIndex(0, 1); + assertIndexOutOfBounds(1, 1); + assertIndexOutOfBounds(-1, 1); + assertIndexOutOfBounds(100, 1); + assertIndexOutOfBounds(-100, 1); + assertIndexOutOfBounds(Integer.MAX_VALUE, 1); + assertIndexOutOfBounds(Integer.MAX_VALUE, 1); + } + + public void test_checkIndex_largeSize() { + Objects.checkIndex(0, 100); + Objects.checkIndex(99, 100); + Objects.checkIndex(100, Integer.MAX_VALUE); + Objects.checkIndex(Integer.MAX_VALUE - 1, Integer.MAX_VALUE); + assertIndexOutOfBounds(-1, 100); + assertIndexOutOfBounds(100, 100); + assertIndexOutOfBounds(Integer.MAX_VALUE, Integer.MAX_VALUE); + assertIndexOutOfBounds(-1, Integer.MAX_VALUE); + } + + private static void assertIndexOutOfBounds(int index, int length) { + try { + Objects.checkIndex(index, length); + fail(); + } catch (IndexOutOfBoundsException expected) { + } + } + public void test_compare() throws Exception { assertEquals(0, Objects.compare(null, null, String.CASE_INSENSITIVE_ORDER)); assertEquals(0, Objects.compare("a", "A", String.CASE_INSENSITIVE_ORDER)); @@ -121,6 +226,10 @@ public class ObjectsTest extends junit.framework.TestCase { } catch (NullPointerException expected) { } + // This does not currently throw. The presence of this test ensures that any + // future behavior change is deliberate. + assertEquals(h, Objects.requireNonNull(h, (Supplier<String>) null)); + // The message returned by the supplier is null. try { Objects.requireNonNull(null, () -> null); @@ -130,6 +239,35 @@ public class ObjectsTest extends junit.framework.TestCase { } } + public void test_requireNonNullElse() { + assertEquals("obj", Objects.requireNonNullElse("obj", "default")); + assertEquals("default", Objects.requireNonNullElse(null, "default")); + assertEquals("obj", Objects.requireNonNullElse("obj", null)); + assertThrowsNpe(() -> Objects.requireNonNullElse(null, null)); + } + + public void test_requireNonNullElseGet_obj() { + assertEquals("obj", Objects.requireNonNullElseGet("obj", () -> "default")); + // null supplier / supplier that returns null is tolerated when obj != null. + assertEquals("obj", Objects.requireNonNullElseGet("obj", () -> null)); + assertEquals("obj", Objects.requireNonNullElseGet("obj", null)); + } + + public void test_requireNonNullElseGet_nullObj() { + assertEquals("default", Objects.requireNonNullElseGet(null, () -> "default")); + // null supplier and supplier of null both throw. + assertThrowsNpe(() -> Objects.requireNonNullElseGet(null, (Supplier<?>) () -> null)); + assertThrowsNpe(() -> Objects.requireNonNullElse(null, null)); + } + + private static void assertThrowsNpe(Runnable runnable) { + try { + runnable.run(); + fail(); + } catch (NullPointerException expected) { + } + } + public void test_toString_Object() throws Exception { assertEquals("hello", Objects.toString(new Hello())); assertEquals("null", Objects.toString(null)); diff --git a/luni/src/test/java/libcore/java/util/SetOfTest.java b/luni/src/test/java/libcore/java/util/SetOfTest.java new file mode 100644 index 0000000000..86dfc742b8 --- /dev/null +++ b/luni/src/test/java/libcore/java/util/SetOfTest.java @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.java.util; + +import org.junit.Test; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; +import libcore.libcore.util.SerializationTester; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class SetOfTest { + + @Test public void of_serializationCompatibility_empty() { + String golden = "ACED00057372001E6A6176612E7574696C2E436F6C6C656374696F6E7324456D7074795365" + + "7415F5721DB403CB280200007870"; + new SerializationTester<>(Set.<String>of(), golden).test(); + } + + @Test public void of_serializationCompatibility_oneElement() { + String golden = "ACED0005737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F646966" + + "6961626C65536574801D92D18F9B80550200007872002C6A6176612E7574696C2E436F6C6C656374" + + "696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00" + + "01637400164C6A6176612F7574696C2F436F6C6C656374696F6E3B7870737200116A6176612E7574" + + "696C2E48617368536574BA44859596B8B7340300007870770C000000023F40000000000001740003" + + "6F6E6578"; + new SerializationTester<>(Set.of("one"), golden).test(); + } + + @Test public void of_serializationCompatibility_manyElements() { + String golden = "ACED0005737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F646966" + + "6961626C65536574801D92D18F9B80550200007872002C6A6176612E7574696C2E436F6C6C656374" + + "696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00" + + "01637400164C6A6176612F7574696C2F436F6C6C656374696F6E3B7870737200116A6176612E7574" + + "696C2E48617368536574BA44859596B8B7340300007870770C000000203F4000000000000D737200" + + "116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200" + + "106A6176612E6C616E672E4E756D62657286AC951D0B94E08B0200007870000000007371007E0006" + + "000000017371007E0006000000027371007E0006000000037371007E0006000000047371007E0006" + + "000000057371007E0006000000067371007E0006000000077371007E0006000000087371007E0006" + + "000000097371007E00060000000A7371007E00060000000B7371007E00060000000C78"; + new SerializationTester<>(Set.of(12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), golden).test(); + } + + @Test public void mixedTypes() { + Set<?> list = Set.of("element", 42); + assertEquals(asSet("element", 42), list); + + assertTrue(list.contains("element")); + assertTrue(list.contains(42)); + assertFalse(list.contains(new Object())); + assertFalse(list.contains(31)); + } + + @Test public void duplicate() { + assertThrowsIae(() -> { Set.of("duplicate", "duplicate"); }); + assertThrowsIae(() -> { Set.of("duplicate", "duplicate", "duplicate"); }); + assertThrowsIae(() -> { Set.of("a", "duplicate", "duplicate"); }); + assertThrowsIae(() -> { + Set.of("a", "duplicate", "b", "c", "d", "e", "f", "g", "duplicate"); + }); + assertThrowsIae(() -> { Set.of("a", "duplicate", "b", "c", "d", "e", "f", "g", + "duplicate", "h", "i", "j", "k", "l"); }); + } + + /** + * Checks that when there is both a duplicate and null, the exception that is thrown + * depends on which occurs first. + */ + @Test public void duplicateAndNull() { + assertThrowsNpe(() -> { Set.of("duplicate", null, "duplicate"); }); // null first + assertThrowsIae(() -> { Set.of("duplicate", "duplicate", null); }); // duplicate first + } + + @Test public void empty() { + check_commonBehavior(Collections.<String>emptySet(), Set.<String>of(), "non-null example"); + } + + @Test public void nonEmpty() { + check_nonEmpty(asSet("one"), Set.of("one")); + check_nonEmpty(asSet("one", "two"), Set.of("one", "two")); + check_nonEmpty(asSet("one", "two", "three"), Set.of("one", "two", "three")); + check_nonEmpty(asSet("one", "two", "three", "four"), + Set.of("one", "two", "three", "four")); + check_nonEmpty(asSet("one", "two", "three", "four", "five"), + Set.of("one", "two", "three", "four", "five")); + check_nonEmpty(asSet("one", "two", "three", "four", "five", "six"), + Set.of("one", "two", "three", "four", "five", "six")); + check_nonEmpty(asSet("one", "two", "three", "four", "five", "six", "seven"), + Set.of("one", "two", "three", "four", "five", "six", "seven")); + check_nonEmpty(asSet(1, 2, 3, 4, 5, 6, 7, 8), Set.of(1, 2, 3, 4, 5, 6, 7, 8)); + check_nonEmpty(asSet(1, 2, 3, 4, 5, 6, 7, 8, 9), Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9)); + check_nonEmpty(asSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), + Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); + check_nonEmpty(asSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), + Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)); + check_nonEmpty(asSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), + Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)); + check_nonEmpty(asSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13), + Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)); + } + + @Test public void null_examples() { + assertThrowsNpe(() -> List.<String>of((String) null)); // one-arg version + assertThrowsNpe(() -> List.<String[]>of((String[]) null)); // null var-args array + assertThrowsNpe(() -> List.<String>of(new String[] { "one", null, "three"})); // var-args + + assertThrowsNpe(() -> Set.of(null, "two")); + assertThrowsNpe(() -> Set.of("one", null)); + assertThrowsNpe( + () -> Set.of(null, "two", "three", "four", "five", "six", "seven")); + assertThrowsNpe( + () -> Set.of("one", "two", "three", "four", "five", "six", null)); + } + + @Test public void null_comprehensive() { + Set<Integer> template = asSet(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); + for (int i = 0; i < template.size(); i++) { + Integer[] l = template.toArray(new Integer[0]); + l[i] = null; + npe(i <= 0, () -> Set.of(l[0])); + npe(i <= 1, () -> Set.of(l[0], l[1])); + npe(i <= 2, () -> Set.of(l[0], l[1], l[2])); + npe(i <= 3, () -> Set.of(l[0], l[1], l[2], l[3])); + npe(i <= 4, () -> Set.of(l[0], l[1], l[2], l[3], l[4])); + npe(i <= 5, () -> Set.of(l[0], l[1], l[2], l[3], l[4], l[5])); + npe(i <= 6, () -> Set.of(l[0], l[1], l[2], l[3], l[4], l[5], l[6])); + npe(i <= 7, () -> Set.of(l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7])); + npe(i <= 8, () -> Set.of(l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8])); + npe(i <= 9, () -> Set.of(l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8], l[9])); + npe(i <= 10, () -> Set.of( + l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8], l[9], l[10])); + npe(i <= 11, () -> Set.of( + l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8], l[9], l[10], l[11])); + npe(i <= 12, () -> Set.of( + l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8], l[9], l[10], l[11], l[12]) + ); + } + } + + /** + * Asserts that {@code runnable.run()} throws {@link NullPointerException} if + * any only if {@code expectedToThrowNpe}. + */ + private static void npe(boolean expectedToThrowNpe, Runnable runnable) { + if (expectedToThrowNpe) { + assertThrowsNpe(runnable); + } else { + runnable.run(); // should not throw + } + } + + private static<T extends Comparable<T>> void check_nonEmpty(Set<T> expected, Set<T> actual) { + T example = actual.iterator().next(); + check_commonBehavior(expected, actual, example); + } + + /** Checks assertions that hold for all Set.of() instances. */ + private static<T extends Comparable<T>> void check_commonBehavior( + Set<T> expected, Set<T> actual, T nonNullExample) { + assertNotNull(nonNullExample); + assertEquals(expected, actual); + assertEquals(expected.size(), actual.size()); + assertEquals(expected.hashCode(), actual.hashCode()); + assertEquals(actual.isEmpty(), actual.isEmpty()); + assertEquals(actual.size() == 0, actual.isEmpty()); + assertEquals(expected.contains(nonNullExample), actual.contains(nonNullExample)); + assertFalse(actual.contains("absent-element")); + assertFalse(actual.contains(new Object())); + assertThrowsNpe(() -> actual.contains(null)); + + assertUnmodifiable(actual, nonNullExample); + assertEquals(actual, reserialize((Serializable) actual)); + } + + private static<T extends Comparable<T>> void assertUnmodifiable(Set<T> set, T example) { + Set<T> examples = Collections.singleton(example); + assertTrue(throwsUoe(() -> { set.add(example); } )); + assertTrue(throwsUoe(() -> { set.addAll(examples); } )); + // List.of() documentation guarantees that the following operations throw + // UnsupportedOperationException, even though some other implementations don't + // do that in the case of isEmpty(). + assertTrue(throwsUoe(() -> { set.clear(); })); + assertTrue(throwsUoe(() -> { set.remove(example); } )); + assertTrue(throwsUoe(() -> { set.removeAll(examples); } )); + assertTrue(throwsUoe(() -> { set.removeIf(Predicate.isEqual(example)); } )); + assertTrue(throwsUoe(() -> { set.retainAll(examples); } )); + } + + private static boolean throwsUoe(Runnable runnable) { + try { + runnable.run(); + return false; + } catch (UnsupportedOperationException tolerated) { + return true; + } + } + + private static void assertThrowsIae(Runnable runnable) { + try { + runnable.run(); + fail(); + } catch (IllegalArgumentException expected) { + } + } + + private static void assertThrowsNpe(Runnable runnable) { + try { + runnable.run(); + fail(); + } catch (NullPointerException expected) { + } + } + + private static <S extends Serializable> S reserialize(S value) { + try { + return (S) SerializationTester.reserialize(value); + } catch (IOException | ClassNotFoundException e) { + fail("Unexpected exception: " + e.getMessage()); + throw new AssertionError(e); // unreachable + } + } + + private static<T> Set<T> asSet(T... values) { + return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(values))); + } + +} diff --git a/luni/src/test/java/libcore/java/util/TimeZoneTest.java b/luni/src/test/java/libcore/java/util/TimeZoneTest.java index 6297080660..da4a04fb5f 100644 --- a/luni/src/test/java/libcore/java/util/TimeZoneTest.java +++ b/luni/src/test/java/libcore/java/util/TimeZoneTest.java @@ -59,7 +59,7 @@ public class TimeZoneTest extends TestCase { // http://code.google.com/p/android/issues/detail?id=14395 public void testPreHistoricInDaylightTime() { - // A replacement for testPreHistoricInDaylightTime_old() using a zone that still lacks an + // A replacement for testPreHistoricInDaylightTime_old() using a zone that lacks an // explicit transition at Integer.MIN_VALUE with zic 2019a and 2019a data. TimeZone tz = TimeZone.getTimeZone("CET"); @@ -76,9 +76,7 @@ public class TimeZoneTest extends TestCase { public void testPreHistoricInDaylightTime_old() throws Exception { // Originally this test was intended to assert what happens when the first transition for a // time zone was a "to DST" transition. i.e. that the (implicit) offset / DST state before - // the first was treated as a non-DST state. Since zic version 2014c some zones have an - // explicit non-DST transition at time -2^31 seconds so it is no longer possible to test - // this with America/Los_Angeles. + // the first was treated as a non-DST state. With the latest data this is no longer true. // This regression test has been kept in case that changes again in future and to prove the // behavior has remained consistent. @@ -92,7 +90,7 @@ public class TimeZoneTest extends TestCase { assertFalse(tz.inDaylightTime(date)); assertEquals("Fri Oct 31 08:00:00 PST 1902", date.toString()); assertEquals("31 Oct 1902 16:00:00 GMT", date.toGMTString()); - // For zic versions <= 2014b, this would be before the first transition. + // For zic versions <= 2014b with 32-bit data, this would be before the first transition. date = sdf.parse("1902-06-01T00:00:00.000+0800"); assertEquals(-28800000, tz.getOffset(date.getTime())); assertFalse(tz.inDaylightTime(date)); @@ -109,7 +107,7 @@ public class TimeZoneTest extends TestCase { // prehistoric offsets. http://b/118835133 // "Africa/Bissau" has just a few known transitions: // Transition time : Offset : DST / non-DST - // <Integer.MIN_VALUE secs>[1] : -01:02:20 : non-DST + // <Before first transition>[1]: -01:02:20 : non-DST // 1912-01-01 01:00:00 GMT : -01:00:00 : non-DST // 1975-01-01 01:00:00 GMT : 00:00:00 : non-DST // @@ -117,7 +115,8 @@ public class TimeZoneTest extends TestCase { // generate the data. When implicit, the first non-DST type defn should be used. TimeZone tz = TimeZone.getTimeZone("Africa/Bissau"); - // Times before Integer.MIN_VALUE should assume we're using the first non-DST type. + // Integer.MIN_VALUE seconds should not be significant for TimeZone on Android since it + // switched to using 64-bit data but we try a time before to make sure that is true. assertNonDaylightOffset(-3740, parseIsoTime("1900-01-01T00:00:00.0+0000"), tz); // Time before 1912-01-01 01:00:00 but after Integer.MIN_VALUE. @@ -351,11 +350,6 @@ public class TimeZoneTest extends TestCase { * calculations. A bug (http://b/18839557) was reported when someone noticed that Android's * TimeZone didn't produce the same answers as other libraries at times just outside the range * of Integer seconds. The reason was because of int overflow / underflow which has been fixed. - * At the time of writing, Android's java.util.TimeZone implementation only supports reading - * TZif version 1 data (32-bit times) and provides one additional "before first transition" - * type. This makes Android's time zone information outside of the Integer range unreliable and - * unlikely to match libraries that use 64-bit times for transitions and/or calculate times - * outside of the range using rules (e.g. like ICU4J does). */ public void testOverflowing32BitUnixDates() { final TimeZone tz = TimeZone.getTimeZone("America/New_York"); @@ -370,14 +364,8 @@ public class TimeZoneTest extends TestCase { // This timezone didn't have any daylight savings prior to 1917 and this date is in 1900. assertFalse(tz.inDaylightTime(new Date(lowerTimeMillis))); - // http://b/118835133: - // zic <= 2014b produces data that suggests before -1633280400 seconds (Sun, 31 Mar 1918 - // 07:00:00 GMT) the offset was -18000000. - // zic > 2014b produces data that suggests before Integer.MIN_VALUE seconds the offset was - // -17762000 and between Integer.MIN_VALUE and -1633280400 it was -18000000. Once Android - // moves to zic > 2014b the -18000000 can be removed. http://b/73719425 int actualOffset = tz.getOffset(lowerTimeMillis); - assertTrue(-18000000 == actualOffset || -17762000 == actualOffset); + assertEquals(-18000000, actualOffset); // Nov 30th 2039, no daylight savings as per current rules. assertFalse(tz.inDaylightTime(new Date(upperTimeMillis))); diff --git a/luni/src/test/java/libcore/java/util/logging/OldFileHandlerTest.java b/luni/src/test/java/libcore/java/util/logging/OldFileHandlerTest.java index ead0b2e930..c9f4d31688 100644 --- a/luni/src/test/java/libcore/java/util/logging/OldFileHandlerTest.java +++ b/luni/src/test/java/libcore/java/util/logging/OldFileHandlerTest.java @@ -74,12 +74,12 @@ public class OldFileHandlerTest extends TestCase { File file = new File(TEMPPATH + SEP + "log"); file.mkdir(); manager.readConfiguration(propertiesToInputStream(props)); - handler = new FileHandler(); r = new LogRecord(Level.CONFIG, "msg"); } protected void tearDown() throws Exception { if (null != handler) { + // Close handler created in setup to ensure that its lock is released. handler.close(); } reset(TEMPPATH + SEP + "log", ""); @@ -93,6 +93,7 @@ public class OldFileHandlerTest extends TestCase { } public void testFileHandler() throws Exception { + handler = new FileHandler(); assertEquals("character encoding is non equal to actual value", "iso-8859-1", handler.getEncoding()); assertNotNull("Filter is null", handler.getFilter()); @@ -115,7 +116,6 @@ public class OldFileHandlerTest extends TestCase { } public void testFileHandler_1params() throws Exception { - handler = new FileHandler("%t/log/string"); assertEquals("character encoding is non equal to actual value", "iso-8859-1", handler.getEncoding()); @@ -466,11 +466,10 @@ public class OldFileHandlerTest extends TestCase { } public void testClose() throws Exception { - FileHandler h = new FileHandler("%t/log/stringPublish"); - h.publish(r); - h.close(); - assertFileContent(TEMPPATH + SEP + "log", "stringPublish", h - .getFormatter()); + handler = new FileHandler("%t/log/stringPublish"); + handler.publish(r); + handler.close(); + assertFileContent(TEMPPATH + SEP + "log", "stringPublish", handler.getFormatter()); } /* diff --git a/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java b/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java index 99c7116997..c2d56aeaa9 100644 --- a/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java +++ b/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java @@ -718,6 +718,29 @@ public class OldMatcherTest extends TestCase { "0123zxx".replaceAll("(?<numbers>[0-9]+)", "a${other}"); fail(); } catch(IllegalArgumentException expected) {} + + // group name is numeric + try { + "0123zxx".replaceAll("(?<numbers>[0-9]+)", "a${1}"); + fail(); + } catch(IllegalArgumentException expected) {} + + // named group has the same prefix, i.e. numbers, but with additional number. + try { + "0123zxx".replaceAll("(?<numbers>[0-9]+)", "a${numbers1}"); + fail(); + } catch(IllegalArgumentException expected) {} + } + public void testOptionalCapturingGroupReplace() { + Pattern pattern = Pattern.compile("(a)(b)?c"); + assertEquals("_a_b_", pattern.matcher("abc").replaceAll("_$1_$2_")); + assertEquals("_a__", pattern.matcher("ac").replaceAll("_$1_$2_")); + + // Test optopnal named-captureing group + pattern = Pattern.compile("(a)(?<name1>b)?c"); + assertEquals("_a_b_", pattern.matcher("abc").replaceAll("_$1_${name1}_")); + assertEquals("_a__", pattern.matcher("ac").replaceAll("_$1_${name1}_")); + } } diff --git a/luni/src/test/java/libcore/java/util/stream/StreamTest.java b/luni/src/test/java/libcore/java/util/stream/StreamTest.java new file mode 100644 index 0000000000..5f8f254364 --- /dev/null +++ b/luni/src/test/java/libcore/java/util/stream/StreamTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package libcore.java.util.stream; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; + +import java.util.stream.Stream; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Streams tests required for Mainline coverage. + * + * TODO(b/153297830): Use existing CtsLibcoreOjTestCases for coverage instead. + */ + +@RunWith(JUnit4.class) +public class StreamTest { + private static final int[] TEST_ARRAY_SIZES = { 0, 1, 2, 10, 100, 1000 }; + + /** + * Stream<T>.of() has two overloads, Stream.of(T t) and Stream.of(T... values) + * + * The first builds a Stream<T> whose functionality is tested in CtsLibcoreOjTestCases, so we + * just check the contents are as expected + * + * The second is a thin wrapper around Arrays.Stream(), which is tested in ArraysTest, + * so again we just check the contents are as expected. + * + */ + @Test + public void streamOfSingleObject() { + String object = "string"; + String[] array = Stream.of(object).toArray(String[]::new); + assertEquals(1, array.length); + assertSame(object, array[0]); + } + + @Test + public void streamOfObjects() { + for (int size : TEST_ARRAY_SIZES) { + String[] sourceArray = stringTestArray(size); + + // Stream.of(T[] t) is equivalent to Stream.of(T... t) + String[] destArray = Stream.of(sourceArray) + .toArray(String[]::new); + assertNotSame(sourceArray, destArray); + assertArrayEquals(sourceArray, destArray); + } + } + + private String[] stringTestArray(int size) { + String[] array = new String[size]; + for (int i = 0; i < size; i++) { + array[i] = String.valueOf(i); + } + return array; + } +} diff --git a/luni/src/test/java/libcore/java/util/zip/DeflateRegressionTest.java b/luni/src/test/java/libcore/java/util/zip/DeflateRegressionTest.java deleted file mode 100644 index 1a505fad0f..0000000000 --- a/luni/src/test/java/libcore/java/util/zip/DeflateRegressionTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package libcore.java.util.zip; - -import com.google.archivepatcher.shared.DefaultDeflateCompatibilityWindow; - -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -/** - * A regression test for Deflate and the underlying native libraries. If any of these tests fail - * it suggests that tools such as Google Play Store that rely on deterministic binary output from - * Deflate; those tools may behave inefficiently if the output changes. - */ -public class DeflateRegressionTest { - - /* - * If this test fails then it implies a change that could regress Android user performance. - * Please check that the platform version of Deflate is still used by affected tools and notify - * them. See also http://b/27637914. - */ - @Test - public void deterministicOutput() throws Exception { - assertTrue(new DefaultDeflateCompatibilityWindow().isCompatible()); - } -} diff --git a/luni/src/test/java/libcore/java/util/zip/ZipInputStreamTest.java b/luni/src/test/java/libcore/java/util/zip/ZipInputStreamTest.java index 8485874bb3..8a33f6f620 100644 --- a/luni/src/test/java/libcore/java/util/zip/ZipInputStreamTest.java +++ b/luni/src/test/java/libcore/java/util/zip/ZipInputStreamTest.java @@ -143,6 +143,19 @@ public final class ZipInputStreamTest extends TestCaseWithRules { zis.close(); } + private static final byte[] ZIP_WITH_DATA_DESCRIPTOR = new byte[] { +(byte) 80, 75, 3, 4, 10, 0, 8, 0, 0, 0, -51, 90, -121, 80, -20, 62, -84, -103, 2, 0, 0, 0, 2, 0, 0, 0, 8, 0, 28, 0, 116, 101, 115, 116, 46, 116, 120, 116, 85, 84, 9, 0, 3, 97, 84, -116, 94, 102, 84, -116, 94, 117, 120, 11, 0, 1, 4, -119, 66, 0, 0, 4, 83, 95, 1, 0, 72, 10, 80, 75, 7, 8, -20, 62, -84, -103, 2, 0, 0, 0, 2, 0, 0, 0, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, -51, 90, -121, 80, -20, 62, -84, -103, 2, 0, 0, 0, 2, 0, 0, 0, 8, 0, 24, 0, 0, 0, 0, 0, 1, 0, 0, 0, -92, -127, 0, 0, 0, 0, 116, 101, 115, 116, 46, 116, 120, 116, 85, 84, 5, 0, 3, 97, 84, -116, 94, 117, 120, 11, 0, 1, 4, -119, 66, 0, 0, 4, 83, 95, 1, 0, 80, 75, 5, 6, 0, 0, 0, 0, 1, 0, 1, 0, 78, 0, 0, 0, 84, 0, 0, 0, 0, 0 }; + + public void testDataDescriptorOnStoredEntry() throws Exception { + ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream( + ZIP_WITH_DATA_DESCRIPTOR)); + + ZipEntry entry = zis.getNextEntry(); + assertEquals("test.txt", entry.getName()); + + zis.close(); + } + private static byte[] zip(String[] names, byte[] bytes) throws IOException { ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); ZipOutputStream zippedOut = new ZipOutputStream(bytesOut); diff --git a/luni/src/test/java/libcore/javax/crypto/HardwareAesTest.java b/luni/src/test/java/libcore/javax/crypto/HardwareAesTest.java new file mode 100644 index 0000000000..f79bb812c9 --- /dev/null +++ b/luni/src/test/java/libcore/javax/crypto/HardwareAesTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package libcore.javax.crypto; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + +import libcore.java.security.CpuFeatures; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class HardwareAesTest { + + @Test + public void hardwareAesAvailability() { + // Test is only applicable if we know for sure that the device should support + // hardware AES. That covers the important cases (non-emulated ARM and x86_64), + // For everything else we assume BoringSSL does the right thing. + assumeTrue(CpuFeatures.isKnownToSupportHardwareAes()); + assertTrue(CpuFeatures.isAesHardwareAccelerated()); + } +} diff --git a/luni/src/test/java/libcore/javax/crypto/MacTest.java b/luni/src/test/java/libcore/javax/crypto/MacTest.java index 3e49cd694e..bd2ad39649 100644 --- a/luni/src/test/java/libcore/javax/crypto/MacTest.java +++ b/luni/src/test/java/libcore/javax/crypto/MacTest.java @@ -26,28 +26,18 @@ import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; -import junit.framework.TestCase; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; +import org.junit.Rule; +import org.junit.rules.TestRule; -import dalvik.system.VMRuntime; -import sun.security.jca.Providers; - -public class MacTest extends TestCase { +public class MacTest extends TestCaseWithRules { // Allow access to deprecated BC algorithms in this test, so we can ensure they // continue to work - @Override - public void setUp() throws Exception { - super.setUp(); - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - } - - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); - } + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); private static abstract class MockProvider extends Provider { public MockProvider(String name) { diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLParametersTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLParametersTest.java index 620c022d6c..3b3cfe41bb 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/SSLParametersTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/SSLParametersTest.java @@ -16,13 +16,21 @@ package libcore.javax.net.ssl; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.util.Arrays; import javax.net.ssl.SSLParameters; -import junit.framework.TestCase; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; -public class SSLParametersTest extends TestCase { +@RunWith(JUnit4.class) +public class SSLParametersTest { - public void test_applicationProtocols() { + @Test + public void applicationProtocols() { SSLParameters params = new SSLParameters(); try { params.setApplicationProtocols(null); @@ -61,4 +69,14 @@ public class SSLParametersTest extends TestCase { assertTrue(Arrays.equals(new String[] {"h2"}, params.getApplicationProtocols())); } + @Test + public void getSetUseCipherSuitesOrder() { + SSLParameters params = new SSLParameters(); + // Default should be false + assertFalse(params.getUseCipherSuitesOrder()); + params.setUseCipherSuitesOrder(true); + assertTrue(params.getUseCipherSuitesOrder()); + params.setUseCipherSuitesOrder(false); + assertFalse(params.getUseCipherSuitesOrder()); + } } diff --git a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java index 1aa3550b75..226952f232 100644 --- a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java +++ b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java @@ -21,30 +21,20 @@ import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Arrays; import javax.security.auth.x500.X500Principal; -import junit.framework.TestCase; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; import libcore.libcore.util.SerializationTester; +import org.junit.Rule; +import org.junit.rules.TestRule; -import dalvik.system.VMRuntime; -import sun.security.jca.Providers; - -public class X500PrincipalTest extends TestCase { +public class X500PrincipalTest extends TestCaseWithRules { // Allow access to deprecated BC algorithms in this test, so we can ensure they // continue to work - @Override - public void setUp() throws Exception { - super.setUp(); - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - } - - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); - } + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); public void testSerialization() { String expected = "aced0005737200266a617661782e73656375726974792e617574682e7" diff --git a/luni/src/test/java/libcore/libcore/content/type/MimeMapTest.java b/luni/src/test/java/libcore/libcore/content/type/MimeMapTest.java new file mode 100644 index 0000000000..764bad227c --- /dev/null +++ b/luni/src/test/java/libcore/libcore/content/type/MimeMapTest.java @@ -0,0 +1,456 @@ +/* + * 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. + */ + +package libcore.libcore.content.type; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import libcore.content.type.MimeMap; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Tests {@link MimeMap} and {@link MimeMap.Builder}. + */ +public class MimeMapTest { + + private MimeMap mimeMap; + private MimeMap emptyMap; + + @Before public void setUp() { + mimeMap = MimeMap.getDefault(); + emptyMap = MimeMap.builder().build(); + } + + @After public void tearDown() { + mimeMap = null; + } + + @Test public void lookup_invalidExtension() { + assertNull(mimeMap.guessMimeTypeFromExtension(null)); + assertNull(mimeMap.guessMimeTypeFromExtension("")); + assertFalse(mimeMap.hasExtension(null)); + assertFalse(mimeMap.hasExtension("")); + } + + @Test public void lookup_invalidMimeType() { + assertNull(mimeMap.guessExtensionFromMimeType(null)); + assertNull(mimeMap.guessExtensionFromMimeType("")); + assertFalse(mimeMap.hasMimeType(null)); + assertFalse(mimeMap.hasMimeType("")); + } + + @Test public void caseNormalization_key() { + mimeMap = MimeMap.builder() + .put("application/msWord", Arrays.asList("Doc")) + .build(); + assertEquals("application/msword", mimeMap.guessMimeTypeFromExtension("dOc")); + assertEquals("doc", mimeMap.guessExtensionFromMimeType("appliCATion/mSWOrd")); + assertTrue(mimeMap.hasMimeType("application/msword")); + assertTrue(mimeMap.hasMimeType("Application/mSWord")); + + assertTrue(mimeMap.hasExtension("doc")); + assertTrue(mimeMap.hasExtension("DOC")); + assertTrue(mimeMap.hasExtension("dOc")); + } + + @Test public void caseNormalization_value() { + // Default map + for (String extension : mimeMap.extensions()) { + assertLowerCase(mimeMap.guessMimeTypeFromExtension(extension)); + } + for (String mimeType : mimeMap.mimeTypes()) { + assertLowerCase(mimeMap.guessExtensionFromMimeType(mimeType)); + } + + // Known keys for a custom map + mimeMap = MimeMap.builder() + .put("application/msWord", Arrays.asList("Doc")) + .build(); + assertEquals("doc", mimeMap.guessExtensionFromMimeType("Application/mSWord")); + assertEquals("application/msword", mimeMap.guessMimeTypeFromExtension("DoC")); + } + + private static void assertLowerCase(String s) { + assertEquals(s.toLowerCase(Locale.ROOT), s); + } + + @Test public void unmapped() { + mimeMap = MimeMap.builder() + .put("mime/test", Arrays.asList("test", "tst")) + .build(); + assertNull(mimeMap.guessExtensionFromMimeType("mime/unknown")); + assertFalse(mimeMap.hasMimeType("mime/unknown")); + + assertNull(mimeMap.guessMimeTypeFromExtension("absent")); + assertFalse(mimeMap.hasExtension("absent")); + } + + @Test public void getDefault_returnsSameInstance() { + assertSame(MimeMap.getDefault(), MimeMap.getDefault()); + } + + @Test public void getDefault_afterSetDefaultSupplier() { + MimeMap originalDefault = MimeMap.getDefault(); + try { + // Constructs a new instance every time it is called + MimeMap.setDefaultSupplier(() -> MimeMap.builder().put("mime/sup", "sup").build()); + // Same instance is returned both times + assertSame(MimeMap.getDefault(), MimeMap.getDefault()); + // Check that the supplier is in effect + assertTrue(originalDefault != MimeMap.getDefault()); + assertEquals("mime/sup", MimeMap.getDefault().guessMimeTypeFromExtension("sup")); + } finally { + MimeMap.setDefaultSupplier(() -> originalDefault); + } + assertSame(originalDefault, MimeMap.getDefault()); + } + + @Test public void setDefaultSupplier_returningNull() { + MimeMap originalDefault = MimeMap.getDefault(); + try { + // A Supplier that returns null is invalid, but we only notice during getDefault(). + MimeMap.setDefaultSupplier(() -> null); + try { + MimeMap.getDefault(); + fail(); + } catch (NullPointerException expected) { + } + } finally { + MimeMap.setDefaultSupplier(() -> originalDefault); + } + } + + @Test public void buildUpon() { + mimeMap = MimeMap.builder() + .build(); + assertMap( + makeMap(), + makeMap(), + mimeMap); + + mimeMap = mimeMap.buildUpon() + .build(); + assertMap( + makeMap(), + makeMap(), + mimeMap); + + mimeMap = mimeMap.buildUpon() + .put("text/plain", "txt") + .build(); + assertMap( + makeMap("text/plain", "txt"), + makeMap("txt", "text/plain"), + mimeMap); + + mimeMap = mimeMap.buildUpon() + .put("audio/mpeg", Arrays.asList("mp2", "mp3")) + .build(); + assertMap( + makeMap("audio/mpeg", "mp2", + "text/plain", "txt"), + makeMap("mp2", "audio/mpeg", + "mp3", "audio/mpeg", + "txt", "text/plain"), + mimeMap); + + mimeMap = mimeMap.buildUpon() + .put("text/plain", "text") + .build(); + assertMap( + makeMap("audio/mpeg", "mp2", + "text/plain", "text"), + makeMap("mp2", "audio/mpeg", + "mp3", "audio/mpeg", + "text", "text/plain", + "txt", "text/plain"), + mimeMap); + } + + @Test public void put() { + MimeMap a = MimeMap.builder() + .put("text/plain", Arrays.asList("txt", "text")) + .put("application/msword", "doc") + .build(); + MimeMap b = MimeMap.builder() + .put("text/plain", Arrays.asList("txt", "text")) + .put("application/msword", "doc") + .build(); + assertEqualsButNotSame(a, b); + assertEqualsButNotSame(a, a.buildUpon().build()); + assertMap( + makeMap( + "text/plain", "txt", + "application/msword", "doc"), + makeMap("txt", "text/plain", + "text", "text/plain", + "doc", "application/msword"), + a); + } + + @Test public void put_noExtensions() { + checkPut_noExtensions(emptyMap); + checkPut_noExtensions(MimeMap.builder().put("text/plain", "txt").build()); + checkPut_noExtensions(mimeMap); + } + + /** + * Checks that put(String, emptyList()) doesn't change or add any mappings. + */ + private static void checkPut_noExtensions(MimeMap baseMap) { + MimeMap mimeMap = baseMap.buildUpon() + .put("mime/type", Collections.emptyList()) + .build(); + assertEquals(baseMap, mimeMap); + } + + @Test public void put_String_List_nullOrEmpty() { + // We still check mimeType for validity even if no extensions are specified + assertPutThrowsNpe(null); + assertPutThrowsIae(""); + + // null or "" are not allowed for either MIME type or extension + assertPutThrowsNpe(null, "ext"); + assertPutThrowsIae("", "ext"); + assertPutThrowsNpe("mime/type", (String) null); + assertPutThrowsIae("mime/type", ""); + + assertPutThrowsNpe("mime/type", "ext", null); + assertPutThrowsIae("mime/type", "ext", ""); + } + + @Test public void put_String_String_nullOrEmpty() { + assertThrowsNpe(() -> MimeMap.builder().put(null, "ext")); + assertThrowsIae(() -> MimeMap.builder().put("", "ext")); + + assertThrowsNpe(() -> MimeMap.builder().put("mime/type", (String) null)); + assertThrowsIae(() -> MimeMap.builder().put("mime/type", "")); + } + + /** + * Tests put() arguments that have a prefix {@code "?"} which leads to putIfAbsent semantics. + */ + @Test public void putIfAbsent() { + // Starting from an empty mapping, add a bunch more, some with and some without '?'. + mimeMap = MimeMap.builder() + .put("?text/plain", "?txt") + .put("audio/mpeg", Arrays.asList("mpga", "mpega", "?mp2", "mp3")) + .build(); + assertEquals("txt", mimeMap.guessExtensionFromMimeType("text/plain")); + assertEquals("text/plain", mimeMap.guessMimeTypeFromExtension("txt")); + assertEquals("mpga", mimeMap.guessExtensionFromMimeType("audio/mpeg")); + assertEquals("audio/mpeg", mimeMap.guessMimeTypeFromExtension("mp2")); + assertEquals("audio/mpeg", mimeMap.guessMimeTypeFromExtension("mp3")); + + // Override a ext -> MIME mapping without overriding the MIME -> ext mapping. + mimeMap = mimeMap.buildUpon() + .put("?audio/mpeg", "m4a") + .build(); + assertEquals("mpga", mimeMap.guessExtensionFromMimeType("audio/mpeg")); + assertEquals("audio/mpeg", mimeMap.guessMimeTypeFromExtension("m4a")); + + // Override a MIME -> ext mapping without overriding the ext -> MIME mapping. + mimeMap = mimeMap.buildUpon() + .put("audio/mpeg", "?txt") + .build(); + assertEquals("txt", mimeMap.guessExtensionFromMimeType("audio/mpeg")); + assertEquals("text/plain", mimeMap.guessMimeTypeFromExtension("txt")); + + + // Check final state + assertMap( + makeMap( + "text/plain", "txt", + "audio/mpeg", "txt" + ), + makeMap( + "txt", "text/plain", + "m4a", "audio/mpeg", + "mp2", "audio/mpeg", + "mp3", "audio/mpeg", + "mpega", "audio/mpeg", + "mpga", "audio/mpeg" + ), + mimeMap + ); + } + + @Test public void extensions() { + assertEquals(Collections.emptySet(), emptyMap.extensions()); + mimeMap = MimeMap.builder() + .put("text/plain", Arrays.asList("txt", "text")) + .put("audi/mpeg", "m4a") + .put("application/msword", "doc") + .put("text/plain", "tx") + .build(); + Set<String> extensions = new HashSet<>(Arrays.asList( + "txt", "text", "m4a", "doc", "tx")); + assertEquals(extensions, mimeMap.extensions()); + // Check that the extensions() view is unmodifiable + try { + mimeMap.extensions().add("ext"); + fail(); + } catch (UnsupportedOperationException expected) { + } + } + + @Test public void mimeTypes() { + assertEquals(Collections.emptySet(), emptyMap.mimeTypes()); + mimeMap = MimeMap.builder() + .put("text/plain", Arrays.asList("txt", "text")) + .put("audio/mpeg", "m4a") + .put("application/msword", "doc") + .put("text/plain", "tx") + .build(); + Set<String> mimeTypes = new HashSet<>(Arrays.asList( + "text/plain", + "audio/mpeg", + "application/msword")); + assertEquals(mimeTypes, mimeMap.mimeTypes()); + // Check that the mimeTypes() view is unmodifiable + try { + mimeMap.mimeTypes().add("foo/bar"); + fail(); + } catch (UnsupportedOperationException expected) { + } + } + + /** + * Tests invalid put() invocations that have '?' in additional/invalid places. + */ + @Test public void put_invalid_additionalQuestionMarks() { + // Potentially we could tolerate additional ? as a prefix in future, but right now we don't. + assertPutThrowsIae("??text/plain", "txt"); + assertPutThrowsIae("text/p?lain", "txt"); + assertPutThrowsIae("text/plain", "txt", "t?ext"); + assertPutThrowsIae("text/plain", "??txt"); + assertPutThrowsIae("text/plain", "t?xt"); + } + + /** Checks that MIME types must have a '/', while extensions must not. */ + @Test public void put_invalid_slash() { + assertPutThrowsIae("mime/type", "invalid/ext"); + assertPutThrowsIae("invalidmime", "ext"); + + // During lookups, wrong arguments return null rather than throwing. + mimeMap = MimeMap.builder().put("mime/type", "ext").build(); + assertNull(mimeMap.guessExtensionFromMimeType("ext")); // ext is no mime type + assertNull(mimeMap.guessMimeTypeFromExtension("mime/type")); // mime/type is no extension + } + + private static void assertPutThrowsNpe(String mime, String... exts) { + assertThrowsNpe(() -> MimeMap.builder().put(mime, Arrays.asList(exts))); + } + + private static void assertPutThrowsIae(final String mime, final String... exts) { + assertThrowsIae(() -> MimeMap.builder().put(mime, Arrays.asList(exts))); + } + + private static void assertThrowsNpe(Runnable runnable) { + try { + runnable.run(); + fail(); + } catch (NullPointerException expected) { + } + } + + private static void assertThrowsIae(Runnable runnable) { + try { + runnable.run(); + fail(); + } catch (IllegalArgumentException expected) { + } + } + + @Test public void hashCodeValue() { + assertEquals(0, emptyMap.hashCode()); + MimeMap a = MimeMap.builder().put("mime/test", "test").build(); + MimeMap b = a.buildUpon().put("foo/bar", "baz").build(); + assertTrue(0 != a.hashCode()); + assertTrue((a.hashCode() != b.hashCode())); + } + + @Test public void empty_copies() { + assertEqualsButNotSame(emptyMap, MimeMap.builder().build()); + assertEqualsButNotSame(emptyMap, emptyMap.buildUpon().build()); + } + + /** Creates a map from alternating key/value arguments, useful for test assertions. */ + private static Map<String, String> makeMap(String... keysAndValues) { + if (keysAndValues.length % 2 != 0) { + throw new IllegalArgumentException( + "Invalid length " + keysAndValues.length + ": " + keysAndValues); + } + Map<String, String> result = new HashMap<>(); + for (int i = 0; i < keysAndValues.length; i += 2) { + String key = keysAndValues[i]; + String value = keysAndValues[i + 1]; + result.put(key, value); + } + return result; + + } + + /** + * Asserts that the given {@code MimeMap} has exactly the given mime -> ext and ext -> mime + * mappings, but no others. + */ + private static<T> void assertMap( + Map<String, String> expectedMimeToExt, + Map<String, String> expectedExtToMime, + MimeMap mimeMap) + { + MimeMap.Builder expectedBuilder = MimeMap.builder(); + for (Map.Entry<String, String> entry : expectedExtToMime.entrySet()) { + String ext = entry.getKey(); + String mime = entry.getValue(); + assertEquals(ext + ": " + mimeMap, mime, mimeMap.guessMimeTypeFromExtension(ext)); + expectedBuilder.put("?" + mime, ext); + } + for (Map.Entry<String, String> entry : expectedMimeToExt.entrySet()) { + String mime = entry.getKey(); + String ext = entry.getValue(); + assertEquals(mime + ": " + mimeMap, ext, mimeMap.guessExtensionFromMimeType(mime)); + expectedBuilder.put(mime, "?" + ext); + } + // Check that there are no unexpected additional mappings. + assertEqualsButNotSame(expectedBuilder.build(), mimeMap); + } + + private static<T> void assertEqualsButNotSame(T a, T b) { + assertEquals(a, b); + assertEquals(b, a); + assertNotSame(a, b); + assertEquals(a.hashCode(), b.hashCode()); + } + +} diff --git a/luni/src/test/java/libcore/libcore/icu/ICUTest.java b/luni/src/test/java/libcore/libcore/icu/ICUTest.java index e67e9a1301..30e3081fad 100644 --- a/luni/src/test/java/libcore/libcore/icu/ICUTest.java +++ b/luni/src/test/java/libcore/libcore/icu/ICUTest.java @@ -220,38 +220,25 @@ public class ICUTest extends junit.framework.TestCase { assertTrue(c.compare("AF", "af") < 0); } - // Test for the behavior of currency symbol lookup when an unrecognized locale has been set as the - // default. - public void testIcuDefaultAffectsCurrencySymbol() { - // A locale that is not going to be recognized by ICU and should fallback to "root" for the - // currency symbol. - final Locale unrecognizedLocale = new Locale("xy", "KR"); - - // A known locale with a relatively stable representation for its currency symbol. - final Locale enUsLocale = new Locale("en", "US"); - final String usDollar = "USD"; - - String initialDefaultLocale = ICU.getDefaultLocale(); - try { - // Confirm the "$" symbol for USD in en-US. - assertEquals("$", ICU.getCurrencySymbol(enUsLocale, usDollar)); - - // Set the default so this will be used as fallback for the unrecognized locale symbol lookup. - ICU.setDefaultLocale(enUsLocale.toLanguageTag()); - - // Demonstrate the USD symbol is reported as "$" for the unrecognized locale (which is using - // the default). - assertEquals("$", ICU.getCurrencySymbol(unrecognizedLocale, usDollar)); - - // Change the default. - ICU.setDefaultLocale(unrecognizedLocale.toLanguageTag()); + public void testSetDefault() { + String current = ICU.getDefaultLocale(); + + try { + assertGetDefault("", ""); + assertGetDefault("und", ""); + assertGetDefault("en-US", "en_US"); + assertGetDefault("uz-CYRL-UZ", "uz_Cyrl_UZ"); + assertGetDefault("ca-ES-PREEURO", "ca_ES_PREEURO"); + assertGetDefault("es-ES-PREEURO-u-ca-japanese", "es_ES_PREEURO@calendar=japanese"); + assertGetDefault("es-ES-PREEURO-u-ca-Japanese", "es_ES_PREEURO@calendar=japanese"); + } finally { + ICU.setDefaultLocale(current); + } + } - String currencySymbolAfterDefaultChange = ICU.getCurrencySymbol(unrecognizedLocale, usDollar); - // "$US" is the value from root. With an unrecognized locale argument, and an unrecognized - // locale as the default, ICU has returns the value in root. - assertEquals("US$", currencySymbolAfterDefaultChange); - } finally { - ICU.setDefaultLocale(initialDefaultLocale); - } + private static void assertGetDefault(String inputLangaugeTag, String expectedLanguageTag) { + ICU.setDefaultLocale(inputLangaugeTag); + assertEquals(expectedLanguageTag, ICU.getDefaultLocale()); } + } diff --git a/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java b/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java index 607397d577..eace2333c9 100644 --- a/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java +++ b/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java @@ -16,10 +16,37 @@ package libcore.libcore.icu; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import android.icu.text.DateTimePatternGenerator; + +import java.text.DateFormatSymbols; +import java.text.DecimalFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; import java.util.Locale; +import java.util.TimeZone; + import libcore.icu.LocaleData; +import libcore.junit.util.SwitchTargetSdkVersionRule; -public class LocaleDataTest extends junit.framework.TestCase { +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class LocaleDataTest { + + @Rule + public TestRule switchTargetSdkVersionRule = SwitchTargetSdkVersionRule.getInstance(); + + @Test public void testAll() throws Exception { // Test that we can get the locale data for all known locales. for (Locale l : Locale.getAvailableLocales()) { @@ -29,6 +56,7 @@ public class LocaleDataTest extends junit.framework.TestCase { } } + @Test public void test_en_US() throws Exception { LocaleData l = LocaleData.get(Locale.US); assertEquals("AM", l.amPm[0]); @@ -57,6 +85,7 @@ public class LocaleDataTest extends junit.framework.TestCase { assertEquals("Tomorrow", l.tomorrow); } + @Test public void test_de_DE() throws Exception { LocaleData l = LocaleData.get(new Locale("de", "DE")); @@ -65,6 +94,7 @@ public class LocaleDataTest extends junit.framework.TestCase { assertEquals("Morgen", l.tomorrow); } + @Test public void test_cs_CZ() throws Exception { LocaleData l = LocaleData.get(new Locale("cs", "CZ")); @@ -77,6 +107,7 @@ public class LocaleDataTest extends junit.framework.TestCase { assertEquals("1", l.tinyStandAloneMonthNames[0]); } + @Test public void test_ko_KR() throws Exception { LocaleData l = LocaleData.get(new Locale("ko", "KR")); @@ -86,6 +117,7 @@ public class LocaleDataTest extends junit.framework.TestCase { assertEquals("내일", l.tomorrow); } + @Test public void test_ru_RU() throws Exception { LocaleData l = LocaleData.get(new Locale("ru", "RU")); @@ -100,6 +132,7 @@ public class LocaleDataTest extends junit.framework.TestCase { } // http://code.google.com/p/android/issues/detail?id=38844 + @Test public void testDecimalFormatSymbols_es() throws Exception { LocaleData es = LocaleData.get(new Locale("es")); assertEquals(',', es.decimalSeparator); @@ -123,6 +156,7 @@ public class LocaleDataTest extends junit.framework.TestCase { } // http://b/7924970 + @Test public void testTimeFormat12And24() throws Exception { LocaleData en_US = LocaleData.get(Locale.US); assertEquals("h:mm a", en_US.timeFormat_hm); @@ -134,6 +168,7 @@ public class LocaleDataTest extends junit.framework.TestCase { } // http://b/26397197 + @Test public void testPatternWithOverride() throws Exception { LocaleData haw = LocaleData.get(new Locale("haw")); assertFalse(haw.shortDateFormat.isEmpty()); @@ -143,7 +178,111 @@ public class LocaleDataTest extends junit.framework.TestCase { * Check that LocaleData.get() does not throw when the input locale is invalid. * http://b/129070579 */ + @Test public void testInvalidLocale() { LocaleData.get(new Locale("invalidLocale")); } + + // Test for b/159514442 when targetSdkVersion == current + @Test + public void test_rootLocale_icu4jConsistency() { + assertRootDataEqualsToTargetLocaleData(Locale.ROOT); + } + + // Test for b/159514442 + @Test + @SwitchTargetSdkVersionRule.TargetSdkVersion(30) + public void test_rootLocale_useRealRootLocaleData() { + assertRootDataEqualsToTargetLocaleData(Locale.ROOT); + + // Regression test as in b/159514442. + SimpleDateFormat df = new SimpleDateFormat("MMM", Locale.ROOT); + df.setTimeZone(TimeZone.getTimeZone("GMT")); + assertEquals("M07", df.format(new Date(1594255915217L))); + } + + // Test for b/159514442 + @Test + @SwitchTargetSdkVersionRule.TargetSdkVersion(29) + public void test_rootLocale_notUseRealRootLocaleData() { + Locale LOCALE_EN_US_POSIX = new Locale("en", "US", "POSIX"); + assertRootDataEqualsToTargetLocaleData(LOCALE_EN_US_POSIX); + + // Regression test as in b/159514442. + SimpleDateFormat df = new SimpleDateFormat("MMM", Locale.ROOT); + df.setTimeZone(TimeZone.getTimeZone("GMT")); + assertEquals("Jul", df.format(new Date(1594255915217L))); + } + + private static void assertRootDataEqualsToTargetLocaleData(Locale targetLocale) { + LocaleData localeData = LocaleData.get(Locale.ROOT); + Calendar calendar = Calendar.getInstance(Locale.ROOT); + android.icu.util.Calendar icuCalendar = android.icu.util.Calendar.getInstance(targetLocale); + DateFormatSymbols dateFormatSymbols = DateFormatSymbols.getInstance(Locale.ROOT); + android.icu.text.DateFormatSymbols icuDateFormatSymbols = + android.icu.text.DateFormatSymbols.getInstance(targetLocale); + DecimalFormatSymbols decimalFormatSymbols = DecimalFormatSymbols.getInstance(Locale.ROOT); + android.icu.text.DecimalFormatSymbols icuDecimalFormatSymbols = + android.icu.text.DecimalFormatSymbols.getInstance(targetLocale); + DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(Locale.ROOT); + + assertEquals(localeData.firstDayOfWeek, (Integer) icuCalendar.getFirstDayOfWeek()); + assertEquals(localeData.minimalDaysInFirstWeek, + (Integer) icuCalendar.getMinimalDaysInFirstWeek()); + + assertArrayEquals(localeData.amPm, icuDateFormatSymbols.getAmPmStrings()); + assertArrayEquals(localeData.eras, icuDateFormatSymbols.getEras()); + assertArrayEquals(localeData.longMonthNames, icuDateFormatSymbols.getMonths( + android.icu.text.DateFormatSymbols.FORMAT, android.icu.text.DateFormatSymbols.WIDE)); + assertArrayEquals(localeData.tinyMonthNames, icuDateFormatSymbols.getMonths( + android.icu.text.DateFormatSymbols.FORMAT, android.icu.text.DateFormatSymbols.NARROW)); + assertArrayEquals(localeData.shortMonthNames, icuDateFormatSymbols.getMonths( + android.icu.text.DateFormatSymbols.FORMAT, android.icu.text.DateFormatSymbols.ABBREVIATED)); + assertArrayEquals(localeData.longStandAloneMonthNames, icuDateFormatSymbols.getMonths( + android.icu.text.DateFormatSymbols.STANDALONE, android.icu.text.DateFormatSymbols.WIDE)); + assertArrayEquals(localeData.tinyStandAloneMonthNames, icuDateFormatSymbols.getMonths( + android.icu.text.DateFormatSymbols.STANDALONE, android.icu.text.DateFormatSymbols.NARROW)); + assertArrayEquals(localeData.shortStandAloneMonthNames, icuDateFormatSymbols.getMonths( + android.icu.text.DateFormatSymbols.STANDALONE, + android.icu.text.DateFormatSymbols.ABBREVIATED)); + assertArrayEquals(localeData.longWeekdayNames, icuDateFormatSymbols.getWeekdays( + android.icu.text.DateFormatSymbols.FORMAT, android.icu.text.DateFormatSymbols.WIDE)); + assertArrayEquals(localeData.tinyWeekdayNames, icuDateFormatSymbols.getWeekdays( + android.icu.text.DateFormatSymbols.FORMAT, android.icu.text.DateFormatSymbols.NARROW)); + assertArrayEquals(localeData.shortWeekdayNames, icuDateFormatSymbols.getWeekdays( + android.icu.text.DateFormatSymbols.FORMAT, android.icu.text.DateFormatSymbols.ABBREVIATED)); + assertArrayEquals(localeData.longStandAloneWeekdayNames, icuDateFormatSymbols.getWeekdays( + android.icu.text.DateFormatSymbols.STANDALONE, android.icu.text.DateFormatSymbols.WIDE)); + assertArrayEquals(localeData.tinyStandAloneWeekdayNames, icuDateFormatSymbols.getWeekdays( + android.icu.text.DateFormatSymbols.STANDALONE, android.icu.text.DateFormatSymbols.NARROW)); + assertArrayEquals(localeData.shortStandAloneWeekdayNames, icuDateFormatSymbols.getWeekdays( + android.icu.text.DateFormatSymbols.STANDALONE, + android.icu.text.DateFormatSymbols.ABBREVIATED)); + + // ICU DecimalFormatSymbols has data slightly different from LocaleData, but infinity is known + // to be the same, but caused the bug b/68318492 in old Android version. + assertEquals(localeData.infinity, icuDecimalFormatSymbols.getInfinity()); + assertEquals(decimalFormatSymbols.getInfinity(), icuDecimalFormatSymbols.getInfinity()); + + assertEquals(localeData.timeFormat_Hm, dtpg.getBestPattern("Hm")); + assertEquals(localeData.timeFormat_hm, dtpg.getBestPattern("hm")); + assertEquals(localeData.timeFormat_Hms, dtpg.getBestPattern("Hms")); + assertEquals(localeData.timeFormat_hms, dtpg.getBestPattern("hms")); + + // Explicitly test Calendar and DateFormatSymbols here because they are known to + // cache some part of LocaleData. + assertEquals(calendar.getFirstDayOfWeek(), icuCalendar.getFirstDayOfWeek()); + assertEquals(calendar.getMinimalDaysInFirstWeek(), icuCalendar.getMinimalDaysInFirstWeek()); + assertArrayEquals(dateFormatSymbols.getAmPmStrings(), icuDateFormatSymbols.getAmPmStrings()); + assertArrayEquals(dateFormatSymbols.getEras(), icuDateFormatSymbols.getEras()); + + assertArrayEquals(dateFormatSymbols.getMonths(), icuDateFormatSymbols.getMonths( + android.icu.text.DateFormatSymbols.FORMAT, android.icu.text.DateFormatSymbols.WIDE)); + assertArrayEquals(dateFormatSymbols.getShortMonths(), icuDateFormatSymbols.getMonths( + android.icu.text.DateFormatSymbols.FORMAT, android.icu.text.DateFormatSymbols.ABBREVIATED)); + assertArrayEquals(dateFormatSymbols.getWeekdays(), icuDateFormatSymbols.getWeekdays( + android.icu.text.DateFormatSymbols.FORMAT, android.icu.text.DateFormatSymbols.WIDE)); + assertArrayEquals(dateFormatSymbols.getShortWeekdays(), icuDateFormatSymbols.getWeekdays( + android.icu.text.DateFormatSymbols.FORMAT, android.icu.text.DateFormatSymbols.ABBREVIATED)); + } } diff --git a/luni/src/test/java/libcore/libcore/icu/TimeZoneIntegrationTest.java b/luni/src/test/java/libcore/libcore/icu/TimeZoneIntegrationTest.java index 32dbb1c80d..f24d8b11f0 100644 --- a/luni/src/test/java/libcore/libcore/icu/TimeZoneIntegrationTest.java +++ b/luni/src/test/java/libcore/libcore/icu/TimeZoneIntegrationTest.java @@ -22,6 +22,8 @@ import android.icu.text.TimeZoneNames; import android.icu.util.VersionInfo; import android.system.Os; +import com.android.icu.util.Icu4cMetadata; + import java.io.File; import java.util.ArrayList; import java.util.Arrays; @@ -37,11 +39,10 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.stream.Collectors; -import libcore.icu.ICU; import libcore.timezone.TimeZoneDataFiles; import libcore.timezone.TimeZoneFinder; import libcore.timezone.TzDataSetVersion; -import libcore.timezone.ZoneInfoDB; +import libcore.timezone.ZoneInfoDb; import libcore.util.CoreLibraryDebug; import libcore.util.DebugInfo; @@ -182,9 +183,9 @@ public class TimeZoneIntegrationTest { */ @Test public void testTimeZoneDataVersion() { - String icu4cTzVersion = ICU.getTZDataVersion(); + String icu4cTzVersion = Icu4cMetadata.getTzdbVersion(); - String zoneInfoTzVersion = ZoneInfoDB.getInstance().getVersion(); + String zoneInfoTzVersion = ZoneInfoDb.getInstance().getVersion(); assertEquals(icu4cTzVersion, zoneInfoTzVersion); String icu4jTzVersion = android.icu.util.TimeZone.getTZDataVersion(); @@ -226,39 +227,29 @@ public class TimeZoneIntegrationTest { */ @Test public void testTzDataSetVersions() throws Exception { - String moduleTzVersionFile = "tz/" + TzDataSetVersion.DEFAULT_FILE_NAME; - + // The time zone data module is required. String timeZoneModuleVersionFile = - TimeZoneDataFiles.getTimeZoneModuleFile(moduleTzVersionFile); - // We currently treat the time zone APEX as optional in code. Its is also not present on ART - // host environments. - if (fileExists(timeZoneModuleVersionFile)) { - assertTzDataSetVersionIsCompatible(timeZoneModuleVersionFile); - } + TimeZoneDataFiles.getTimeZoneModuleTzFile(TzDataSetVersion.DEFAULT_FILE_NAME); + assertTzDataSetVersionIsCompatible(timeZoneModuleVersionFile); - String runtimeModuleVersionFile = - TimeZoneDataFiles.getRuntimeModuleFile(moduleTzVersionFile); - assertTzDataSetVersionIsCompatible(runtimeModuleVersionFile); - - // Check getRuntimeModuleTzVersionFile() is doing the right thing. - // getRuntimeModuleTzVersionFile() should go away when its one user, RulesManagerService, + // Check getTimeZoneModuleTzVersionFile() is doing the right thing. + // getTimeZoneModuleTzVersionFile() should go away when its one user, RulesManagerService, // is removed from the platform code. http://b/123398797 - assertEquals(TimeZoneDataFiles.getRuntimeModuleTzVersionFile(), runtimeModuleVersionFile); + assertEquals(TimeZoneDataFiles.getTimeZoneModuleTzVersionFile(), timeZoneModuleVersionFile); // TODO: Remove this once the /system copy of time zone files have gone away. See also // testTimeZoneDebugInfo(). assertTzDataSetVersionIsCompatible( - TimeZoneDataFiles.getSystemTimeZoneFile(TzDataSetVersion.DEFAULT_FILE_NAME)); + TimeZoneDataFiles.getSystemTzFile(TzDataSetVersion.DEFAULT_FILE_NAME)); } private static void assertTzDataSetVersionIsCompatible(String versionFile) throws Exception { - TzDataSetVersion actualVersion = - TzDataSetVersion.readFromFile(new File(versionFile)); + TzDataSetVersion actualVersion = TzDataSetVersion.readFromFile(new File(versionFile)); assertEquals( TzDataSetVersion.currentFormatMajorVersion(), - actualVersion.formatMajorVersion); + actualVersion.getFormatMajorVersion()); int minDeviceMinorVersion = TzDataSetVersion.currentFormatMinorVersion(); - assertTrue(actualVersion.formatMinorVersion >= minDeviceMinorVersion); + assertTrue(actualVersion.getFormatMinorVersion() >= minDeviceMinorVersion); } /** @@ -278,8 +269,8 @@ public class TimeZoneIntegrationTest { "core_library.timezone.source.tzdata_module_status"); String apexRootDir = TimeZoneDataFiles.getTimeZoneModuleFile(""); List<String> dataModuleFiles = - createModuleTzFileNames(TimeZoneDataFiles::getTimeZoneModuleFile); - String icuOverlayFile = TimeZoneDataFiles.getTimeZoneModuleFile("icu/icu_tzdata.dat"); + createModuleTzFiles(TimeZoneDataFiles::getTimeZoneModuleTzFile); + String icuOverlayFile = TimeZoneDataFiles.getTimeZoneModuleIcuFile("icu_tzdata.dat"); if (fileExists(apexRootDir)) { assertEquals("OK", tzModuleStatus); dataModuleFiles.forEach(TimeZoneIntegrationTest::assertFileExists); @@ -290,46 +281,36 @@ public class TimeZoneIntegrationTest { assertFileDoesNotExist(icuOverlayFile); } - // Every device should have a runtime module copy of time zone data since we expect every - // device to have a runtime module. This is the base copy of time zone data that can be - // updated when we update the runtime module. Host ART should match device. - assertEquals("OK", getDebugStringValue(debugInfo, - "core_library.timezone.source.runtime_module_status")); - assertFileExists(TimeZoneDataFiles.getRuntimeModuleFile("")); - List<String> runtimeModuleFiles = - createModuleTzFileNames(TimeZoneDataFiles::getRuntimeModuleFile); - runtimeModuleFiles.forEach(TimeZoneIntegrationTest::assertFileExists); - String icuDatFileName = "icudt" + VersionInfo.ICU_VERSION.getMajor() + "l.dat"; - String runtimeModuleIcuData = - TimeZoneDataFiles.getRuntimeModuleFile("icu/" + icuDatFileName); - assertFileExists(runtimeModuleIcuData); + String i18nModuleIcuData = TimeZoneDataFiles.getI18nModuleIcuFile(icuDatFileName); + assertFileExists(i18nModuleIcuData); // Devices currently have a subset of the time zone files in /system. These are going away // but we test them while they exist. Host ART should match device. assertEquals("OK", getDebugStringValue(debugInfo, "core_library.timezone.source.system_status")); assertFileExists( - TimeZoneDataFiles.getSystemTimeZoneFile(TzDataSetVersion.DEFAULT_FILE_NAME)); - assertFileExists(TimeZoneDataFiles.getSystemTimeZoneFile("tzdata")); + TimeZoneDataFiles.getSystemTzFile(TzDataSetVersion.DEFAULT_FILE_NAME)); + assertFileExists(TimeZoneDataFiles.getSystemTzFile(ZoneInfoDb.TZDATA_FILE_NAME)); // The following files once existed in /system but have been removed as part of APEX work. - assertFileDoesNotExist(TimeZoneDataFiles.getSystemTimeZoneFile("tzlookup.xml")); + assertFileDoesNotExist( + TimeZoneDataFiles.getSystemTzFile(TimeZoneFinder.TZLOOKUP_FILE_NAME)); // It's hard to assert much about this file as there is a symlink in /system on device for // app compatibility (b/122985829) but it doesn't exist in host environments. If the file // exists we can say it should resolve (realpath) to the same file as the runtime module. String systemIcuData = TimeZoneDataFiles.getSystemIcuFile(icuDatFileName); if (new File(systemIcuData).exists()) { - assertEquals(Os.realpath(runtimeModuleIcuData), Os.realpath(systemIcuData)); + assertEquals(Os.realpath(i18nModuleIcuData), Os.realpath(systemIcuData)); } } - private static List<String> createModuleTzFileNames( + private static List<String> createModuleTzFiles( Function<String, String> pathCreationFunction) { List<String> relativePaths = Arrays.asList( - "tz/" + TzDataSetVersion.DEFAULT_FILE_NAME, - "tz/tzdata", - "tz/tzlookup.xml"); + TzDataSetVersion.DEFAULT_FILE_NAME, + ZoneInfoDb.TZDATA_FILE_NAME, + TimeZoneFinder.TZLOOKUP_FILE_NAME); return relativePaths.stream().map(pathCreationFunction).collect(Collectors.toList()); } @@ -355,7 +336,7 @@ public class TimeZoneIntegrationTest { */ @Test public void testTimeZoneIdLookup() { - String[] zoneInfoDbAvailableIds = ZoneInfoDB.getInstance().getAvailableIDs(); + String[] zoneInfoDbAvailableIds = ZoneInfoDb.getInstance().getAvailableIDs(); // ICU has a known set of IDs. We want ANY because we don't want to filter to ICU's // canonical IDs only. diff --git a/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java b/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java index 0e2c6b588b..218678ee56 100644 --- a/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java +++ b/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java @@ -189,7 +189,6 @@ public class BlockGuardOsTest { "dup(java.io.FileDescriptor)", "dup2(java.io.FileDescriptor,int)", "environ()", - "fcntlFlock(java.io.FileDescriptor,int,android.system.StructFlock)", "fcntlInt(java.io.FileDescriptor,int,int)", "fcntlVoid(java.io.FileDescriptor,int)", "gai_strerror(int)", @@ -227,6 +226,7 @@ public class BlockGuardOsTest { "kill(int,int)", "listen(java.io.FileDescriptor,int)", "listxattr(java.lang.String)", + "memfd_create(java.lang.String,int)", "mincore(long,long,byte[])", "mlock(long,long)", "mmap(long,long,int,int,java.io.FileDescriptor,long)", diff --git a/luni/src/test/java/libcore/libcore/net/MimeUtilsTest.java b/luni/src/test/java/libcore/libcore/net/MimeUtilsTest.java deleted file mode 100644 index 7d7617b51e..0000000000 --- a/luni/src/test/java/libcore/libcore/net/MimeUtilsTest.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package libcore.libcore.net; - -import libcore.net.MimeUtils; - -import junit.framework.TestCase; - -import java.util.Locale; -import java.util.Objects; - -public class MimeUtilsTest extends TestCase { - public void test_15715370() { - assertEquals("audio/flac", MimeUtils.guessMimeTypeFromExtension("flac")); - assertEquals("flac", MimeUtils.guessExtensionFromMimeType("audio/flac")); - assertEquals("flac", MimeUtils.guessExtensionFromMimeType("application/x-flac")); - } - - // https://code.google.com/p/android/issues/detail?id=78909 - public void test_78909() { - assertEquals("mka", MimeUtils.guessExtensionFromMimeType("audio/x-matroska")); - assertEquals("mkv", MimeUtils.guessExtensionFromMimeType("video/x-matroska")); - } - - public void test_16978217() { - assertEquals("image/x-ms-bmp", MimeUtils.guessMimeTypeFromExtension("bmp")); - assertEquals("image/x-icon", MimeUtils.guessMimeTypeFromExtension("ico")); - assertEquals("video/mp2ts", MimeUtils.guessMimeTypeFromExtension("ts")); - } - - public void testCommon() { - assertEquals("audio/mpeg", MimeUtils.guessMimeTypeFromExtension("mp3")); - assertEquals("image/png", MimeUtils.guessMimeTypeFromExtension("png")); - assertEquals("application/zip", MimeUtils.guessMimeTypeFromExtension("zip")); - - assertEquals("mp3", MimeUtils.guessExtensionFromMimeType("audio/mpeg")); - assertEquals("png", MimeUtils.guessExtensionFromMimeType("image/png")); - assertEquals("zip", MimeUtils.guessExtensionFromMimeType("application/zip")); - } - - public void test_18390752() { - assertEquals("jpg", MimeUtils.guessExtensionFromMimeType("image/jpeg")); - } - - public void test_30207891() { - assertTrue(MimeUtils.hasMimeType("IMAGE/PNG")); - assertTrue(MimeUtils.hasMimeType("IMAGE/png")); - assertFalse(MimeUtils.hasMimeType("")); - assertEquals("png", MimeUtils.guessExtensionFromMimeType("IMAGE/PNG")); - assertEquals("png", MimeUtils.guessExtensionFromMimeType("IMAGE/png")); - assertNull(MimeUtils.guessMimeTypeFromExtension("")); - assertNull(MimeUtils.guessMimeTypeFromExtension("doesnotexist")); - assertTrue(MimeUtils.hasExtension("PNG")); - assertTrue(MimeUtils.hasExtension("PnG")); - assertFalse(MimeUtils.hasExtension("")); - assertFalse(MimeUtils.hasExtension(".png")); - assertEquals("image/png", MimeUtils.guessMimeTypeFromExtension("PNG")); - assertEquals("image/png", MimeUtils.guessMimeTypeFromExtension("PnG")); - assertNull(MimeUtils.guessMimeTypeFromExtension(".png")); - assertNull(MimeUtils.guessMimeTypeFromExtension("")); - assertNull(MimeUtils.guessExtensionFromMimeType("doesnotexist")); - } - - public void test_30793548() { - assertEquals("video/3gpp", MimeUtils.guessMimeTypeFromExtension("3gpp")); - assertEquals("video/3gpp", MimeUtils.guessMimeTypeFromExtension("3gp")); - assertEquals("video/3gpp2", MimeUtils.guessMimeTypeFromExtension("3gpp2")); - assertEquals("video/3gpp2", MimeUtils.guessMimeTypeFromExtension("3g2")); - } - - public void test_37167977() { - // https://tools.ietf.org/html/rfc5334#section-10.1 - assertEquals("audio/ogg", MimeUtils.guessMimeTypeFromExtension("ogg")); - assertEquals("audio/ogg", MimeUtils.guessMimeTypeFromExtension("oga")); - assertEquals("audio/ogg", MimeUtils.guessMimeTypeFromExtension("spx")); - assertEquals("video/ogg", MimeUtils.guessMimeTypeFromExtension("ogv")); - } - - public void test_70851634_mimeTypeFromExtension() { - assertEquals("video/vnd.youtube.yt", MimeUtils.guessMimeTypeFromExtension("yt")); - } - - public void test_70851634_extensionFromMimeType() { - assertEquals("yt", MimeUtils.guessExtensionFromMimeType("video/vnd.youtube.yt")); - assertEquals("yt", MimeUtils.guessExtensionFromMimeType("application/vnd.youtube.yt")); - } - - public void test_112162449_audio() { - // According to https://en.wikipedia.org/wiki/M3U#Internet_media_types - // this is a giant mess, so we pick "audio/x-mpegurl" because a similar - // playlist format uses "audio/x-scpls". - assertMimeTypeFromExtension("audio/x-mpegurl", "m3u"); - assertMimeTypeFromExtension("audio/x-mpegurl", "m3u8"); - assertExtensionFromMimeType("m3u", "audio/x-mpegurl"); - - assertExtensionFromMimeType("m4a", "audio/mp4"); - assertMimeTypeFromExtension("audio/mpeg", "m4a"); - - assertBidirectional("audio/aac", "aac"); - } - - public void test_112162449_video() { - assertBidirectional("video/x-flv", "flv"); - assertBidirectional("video/quicktime", "mov"); - assertBidirectional("video/mpeg", "mpeg"); - } - - public void test_112162449_image() { - assertBidirectional("image/heif", "heif"); - assertBidirectional("image/heif-sequence", "heifs"); - assertBidirectional("image/heic", "heic"); - assertBidirectional("image/heic-sequence", "heics"); - assertMimeTypeFromExtension("image/heif", "hif"); - - assertBidirectional("image/x-adobe-dng", "dng"); - assertBidirectional("image/x-photoshop", "psd"); - - assertBidirectional("image/jp2", "jp2"); - assertMimeTypeFromExtension("image/jp2", "jpg2"); - } - - public void test_120135571_audio() { - assertMimeTypeFromExtension("audio/mpeg", "m4r"); - } - - public void testWifiConfig_xml() { - assertExtensionFromMimeType("xml", "application/x-wifi-config"); - assertMimeTypeFromExtension("text/xml", "xml"); - } - - // http://b/122734564 - public void testNonLowercaseMimeType() { - // A mixed-case mimeType that appears in mime.types; we expect guessMimeTypeFromExtension() - // to return it in lowercase because MimeUtils considers lowercase to be the canonical form. - String mimeType = "application/vnd.ms-word.document.macroEnabled.12".toLowerCase(Locale.US); - assertBidirectional(mimeType, "docm"); - } - - // Check that the keys given for lookups in either direction are not case sensitive - public void testCaseInsensitiveKeys() { - String mimeType = MimeUtils.guessMimeTypeFromExtension("apk"); - assertNotNull(mimeType); - - assertEquals(mimeType, MimeUtils.guessMimeTypeFromExtension("APK")); - assertEquals(mimeType, MimeUtils.guessMimeTypeFromExtension("aPk")); - - assertEquals("apk", MimeUtils.guessExtensionFromMimeType(mimeType)); - assertEquals("apk", MimeUtils.guessExtensionFromMimeType(mimeType.toUpperCase(Locale.US))); - assertEquals("apk", MimeUtils.guessExtensionFromMimeType(mimeType.toLowerCase(Locale.US))); - } - - public void test_invalid_empty() { - checkInvalidExtension(""); - checkInvalidMimeType(""); - } - - public void test_invalid_null() { - checkInvalidExtension(null); - checkInvalidMimeType(null); - } - - public void test_invalid() { - checkInvalidMimeType("invalid mime type"); - checkInvalidExtension("invalid extension"); - } - - private static void checkInvalidExtension(String s) { - assertFalse(MimeUtils.hasExtension(s)); - assertNull(MimeUtils.guessMimeTypeFromExtension(s)); - } - - private static void checkInvalidMimeType(String s) { - assertFalse(MimeUtils.hasMimeType(s)); - assertNull(MimeUtils.guessExtensionFromMimeType(s)); - } - - private static void assertMimeTypeFromExtension(String mimeType, String extension) { - final String actual = MimeUtils.guessMimeTypeFromExtension(extension); - if (!Objects.equals(mimeType, actual)) { - fail("Expected " + mimeType + " but was " + actual + " for extension " + extension); - } - } - - private static void assertExtensionFromMimeType(String extension, String mimeType) { - final String actual = MimeUtils.guessExtensionFromMimeType(mimeType); - if (!Objects.equals(extension, actual)) { - fail("Expected " + extension + " but was " + actual + " for type " + mimeType); - } - } - - private static void assertBidirectional(String mimeType, String extension) { - assertMimeTypeFromExtension(mimeType, extension); - assertExtensionFromMimeType(extension, mimeType); - } -} diff --git a/luni/src/test/java/libcore/libcore/net/http/ResponseUtilsTest.java b/luni/src/test/java/libcore/libcore/net/http/ResponseUtilsTest.java deleted file mode 100644 index fed9e9bbfd..0000000000 --- a/luni/src/test/java/libcore/libcore/net/http/ResponseUtilsTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package libcore.libcore.net.http; - -import java.nio.charset.StandardCharsets; -import java.nio.charset.UnsupportedCharsetException; -import junit.framework.TestCase; -import static libcore.net.http.ResponseUtils.responseCharset; - -public class ResponseUtilsTest extends TestCase { - public void test_responseCharset_missing() { - assertEquals(StandardCharsets.UTF_8, responseCharset(null)); - assertEquals(StandardCharsets.UTF_8, responseCharset("text/plain")); - assertEquals(StandardCharsets.UTF_8, responseCharset("text/plain;foo=bar;baz=bal")); - assertEquals(StandardCharsets.UTF_8, responseCharset("text/plain;charset=")); - } - - public void test_responseCharset_valid() { - assertEquals(StandardCharsets.ISO_8859_1, - responseCharset("text/plain;charset=ISO-8859-1")); - assertEquals(StandardCharsets.ISO_8859_1, - responseCharset("text/plain;CHARSET=ISO-8859-1")); - assertEquals(StandardCharsets.ISO_8859_1, - responseCharset("text/plain; charset = ISO-8859-1")); - assertEquals(StandardCharsets.ISO_8859_1, - responseCharset("text/plain; foo=bar;baz=bag;charset=ISO-8859-1")); - assertEquals(StandardCharsets.ISO_8859_1, - responseCharset("text/plain;charset=ISO-8859-1;;==,==")); - } - - public void test_responseCharset_invalid() { - try { - responseCharset("text/plain;charset=unsupportedCharset"); - fail(); - } catch (UnsupportedCharsetException expected) { - } - } -} diff --git a/luni/src/test/java/libcore/libcore/reflect/ParameterizedTypeRegressionTest.java b/luni/src/test/java/libcore/libcore/reflect/ParameterizedTypeRegressionTest.java new file mode 100644 index 0000000000..7da11617b7 --- /dev/null +++ b/luni/src/test/java/libcore/libcore/reflect/ParameterizedTypeRegressionTest.java @@ -0,0 +1,277 @@ +/* + * 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. + */ + +package libcore.libcore.reflect; + +import com.google.common.base.Joiner; + +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + + +/** + * Regression tests for http://b/124315589 + */ +public class ParameterizedTypeRegressionTest { + + // A set of nested classes used by some of the tests in this class. + class A<X> { + class B<Y> { + class C1<Z> { + // Leaf not generic. + class D1 { + } + } + // Non-leaf not generic. + class C2 { + class D2<Z> { + } + } + } + } + + @Test + public void testNoGeneric() { + Type actual = new ParameterizedClass<List>() { + // Anonymous class declaration. + }.getArgumentType(); + Class<List> expected = List.class; + Assert.assertEquals(expected, actual); + Assert.assertEquals("interface java.util.List", actual.toString()); + } + + @Test + public void testGeneric() { + Type actual = new ParameterizedClass<List<Integer>>() { + // Anonymous class declaration. + }.getArgumentType(); + ParameterizedTypeImpl expected = new ParameterizedTypeImpl( + null, + List.class, + Integer.class + ); + Assert.assertEquals(expected, actual); + Assert.assertEquals("java.util.List<java.lang.Integer>", actual.toString()); + } + + @Test + public void testGenericOfGeneric() { + Type actual = new ParameterizedClass<List<Map<String, Float>>>() { + // Anonymous class declaration. + }.getArgumentType(); + ParameterizedTypeImpl expected = new ParameterizedTypeImpl( + null, + List.class, + new ParameterizedTypeImpl( + null, + Map.class, + String.class, + Float.class) + ); + Assert.assertEquals(expected, actual); + Assert.assertEquals( + "java.util.List<java.util.Map<java.lang.String, java.lang.Float>>", + actual.toString()); + } + + @Test + public void testNested1() { + Type actual = new ParameterizedClass<A<Integer>>() { + // Anonymous class declaration. + }.getArgumentType(); + ParameterizedTypeImpl expected = new ParameterizedTypeImpl( + ParameterizedTypeRegressionTest.class, + A.class, + Integer.class + ); + Assert.assertEquals(expected, actual); + Assert.assertEquals( + "libcore.libcore.reflect.ParameterizedTypeRegressionTest$A<java.lang.Integer>", + actual.toString()); + } + + @Test + public void testNested2() { + Type actual = new ParameterizedClass<A<Integer>.B<Float>>() { + // Anonymous class declaration. + }.getArgumentType(); + ParameterizedTypeImpl expected = new ParameterizedTypeImpl( + new ParameterizedTypeImpl( + ParameterizedTypeRegressionTest.class, + A.class, + Integer.class), + A.B.class, + Float.class + ); + Assert.assertEquals(expected, actual); + Assert.assertEquals( + "libcore.libcore.reflect.ParameterizedTypeRegressionTest$A<java.lang.Integer>" + + "$B<java.lang.Float>", + actual.toString()); + } + + @Test + public void testNested3() { + Type actual = new ParameterizedClass<A<Integer>.B<Float>.C1<String>>() { + // Anonymous class declaration. + }.getArgumentType(); + ParameterizedTypeImpl expected = new ParameterizedTypeImpl( + new ParameterizedTypeImpl( + new ParameterizedTypeImpl( + ParameterizedTypeRegressionTest.class, + A.class, + Integer.class), + A.B.class, + Float.class), + A.B.C1.class, + String.class); + Assert.assertEquals(expected, actual); + Assert.assertEquals( + "libcore.libcore.reflect.ParameterizedTypeRegressionTest$A<java.lang.Integer>" + + "$B<java.lang.Float>" + + "$C1<java.lang.String>", + actual.toString()); + } + + @Test + public void testNested4_nonGenericLeaf() { + // This anonymous class has a non-generic leaf class (D). + Type actual = new ParameterizedClass<A<Integer>.B<Float>.C1<String>.D1>() { + // Anonymous class declaration. + }.getArgumentType(); + ParameterizedTypeImpl expected = new ParameterizedTypeImpl( + new ParameterizedTypeImpl( + new ParameterizedTypeImpl( + new ParameterizedTypeImpl( + ParameterizedTypeRegressionTest.class, + A.class, + Integer.class), + A.B.class, + Float.class), + A.B.C1.class, + String.class), + A.B.C1.D1.class + ); + Assert.assertEquals(expected, actual); + Assert.assertEquals( + "libcore.libcore.reflect.ParameterizedTypeRegressionTest$A<java.lang.Integer>" + + "$B<java.lang.Float>$C1<java.lang.String>$D1", + actual.toString()); + } + + @Test + public void testNested4_nonGenericNonLeaf() { + // This anonymous class has a non-generic class (C2). + Type actual = new ParameterizedClass<A<Integer>.B<Float>.C2.D2<String>>() { + // Anonymous class declaration. + }.getArgumentType(); + ParameterizedTypeImpl expected = new ParameterizedTypeImpl( + new ParameterizedTypeImpl( + new ParameterizedTypeImpl( + new ParameterizedTypeImpl( + ParameterizedTypeRegressionTest.class, + A.class, + Integer.class), + A.B.class, + Float.class), + A.B.C2.class), + A.B.C2.D2.class, + String.class + ); + Assert.assertEquals(expected, actual); + Assert.assertEquals( + "libcore.libcore.reflect.ParameterizedTypeRegressionTest$A<java.lang.Integer>" + + "$B<java.lang.Float>$C2$D2<java.lang.String>", + actual.toString()); + } + + private static class ParameterizedClass<T> { + public Type getArgumentType() { + Class<?> parameterizedClass = getClass(); + return ((ParameterizedType) parameterizedClass.getGenericSuperclass()) + .getActualTypeArguments()[0]; + } + } + + /** + * A straightforward implementation of ParameterizedType that implements equals() and can be + * used when comparing against the platform behavior. + */ + private static class ParameterizedTypeImpl implements ParameterizedType { + private final Type ownerType; + private final Class<?> rawType; + private final Type[] typeArguments; + + ParameterizedTypeImpl(Type ownerType, Class<?> rawType, Type... typeArguments) { + this.ownerType = ownerType; + this.rawType = rawType; + this.typeArguments = typeArguments; + } + + @Override + public Class getRawType() { + return rawType; + } + + @Override + public Type[] getActualTypeArguments() { + return typeArguments; + } + + @Override + public Type getOwnerType() { + return ownerType; + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + if (ownerType != null) { + stringBuilder.append(ownerType.getTypeName()); + stringBuilder.append('$'); + stringBuilder.append(rawType.getSimpleName()); + } else { + stringBuilder.append(rawType.getName()); + } + stringBuilder.append('<'); + List<String> typeArgumentNames = Arrays.stream(typeArguments) + .map(Type::getTypeName) + .collect(Collectors.toList()); + stringBuilder.append(Joiner.on(", ").join(typeArgumentNames)); + stringBuilder.append('>'); + return stringBuilder.toString(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ParameterizedType)) { + return false; + } + ParameterizedType other = (ParameterizedType) obj; + return getRawType().equals(other.getRawType()) && + Arrays.equals(getActualTypeArguments(), other.getActualTypeArguments()) && + Objects.equals(getOwnerType(), other.getOwnerType()); + } + } +} diff --git a/luni/src/test/java/libcore/libcore/timezone/CountryTimeZonesTest.java b/luni/src/test/java/libcore/libcore/timezone/CountryTimeZonesTest.java index 2a5f6e214d..cf3289650c 100644 --- a/luni/src/test/java/libcore/libcore/timezone/CountryTimeZonesTest.java +++ b/luni/src/test/java/libcore/libcore/timezone/CountryTimeZonesTest.java @@ -20,8 +20,11 @@ import org.junit.Test; import android.icu.util.TimeZone; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; +import java.util.function.Function; import java.util.stream.Collectors; import libcore.timezone.CountryTimeZones; import libcore.timezone.CountryTimeZones.OffsetResult; @@ -39,13 +42,13 @@ public class CountryTimeZonesTest { private static final String INVALID_TZ_ID = "Moon/Tranquility_Base"; - // Zones used in the tests. NEW_YORK_TZ and LONDON_TZ chosen because they never overlap but both - // have DST. - private static final TimeZone NEW_YORK_TZ = TimeZone.getTimeZone("America/New_York"); - private static final TimeZone LONDON_TZ = TimeZone.getTimeZone("Europe/London"); - // A zone that matches LONDON_TZ for WHEN_NO_DST. It does not have DST so differs for WHEN_DST. - private static final TimeZone REYKJAVIK_TZ = TimeZone.getTimeZone("Atlantic/Reykjavik"); - // Another zone that matches LONDON_TZ for WHEN_NO_DST. It does not have DST so differs for + // Zones used in the tests. NY_TZ and LON_TZ chosen because they never overlap but both have + // DST. + private static final TimeZone NY_TZ = TimeZone.getTimeZone("America/New_York"); + private static final TimeZone LON_TZ = TimeZone.getTimeZone("Europe/London"); + // A zone that matches LON_TZ for WHEN_NO_DST. It does not have DST so differs for WHEN_DST. + private static final TimeZone REYK_TZ = TimeZone.getTimeZone("Atlantic/Reykjavik"); + // Another zone that matches LON_TZ for WHEN_NO_DST. It does not have DST so differs for // WHEN_DST. private static final TimeZone UTC_TZ = TimeZone.getTimeZone("Etc/UTC"); @@ -58,57 +61,63 @@ public class CountryTimeZonesTest { // The offset applied to most zones during DST. private static final int NORMAL_DST_ADJUSTMENT = HOUR_MILLIS; - private static final int LONDON_NO_DST_OFFSET_MILLIS = 0; - private static final int LONDON_DST_OFFSET_MILLIS = LONDON_NO_DST_OFFSET_MILLIS + private static final int LON_NO_DST_TOTAL_OFFSET = 0; + private static final int LON_DST_TOTAL_OFFSET = LON_NO_DST_TOTAL_OFFSET + NORMAL_DST_ADJUSTMENT; - private static final int NEW_YORK_NO_DST_OFFSET_MILLIS = -5 * HOUR_MILLIS; - private static final int NEW_YORK_DST_OFFSET_MILLIS = NEW_YORK_NO_DST_OFFSET_MILLIS + private static final int NY_NO_DST_TOTAL_OFFSET = -5 * HOUR_MILLIS; + private static final int NY_DST_TOTAL_OFFSET = NY_NO_DST_TOTAL_OFFSET + NORMAL_DST_ADJUSTMENT; @Test public void createValidated() throws Exception { CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* everUsesUtc */, timeZoneMappings("Europe/London"), - "test"); + "gb", "Europe/London", false /* defaultTimeZoneBoost */, + true /* everUsesUtc */, timeZoneMappings("Europe/London"), "test"); assertTrue(countryTimeZones.isForCountryCode("gb")); assertEquals("Europe/London", countryTimeZones.getDefaultTimeZoneId()); assertZoneEquals(zone("Europe/London"), countryTimeZones.getDefaultTimeZone()); assertEquals(timeZoneMappings("Europe/London"), countryTimeZones.getTimeZoneMappings()); - assertZonesEqual(zones("Europe/London"), countryTimeZones.getIcuTimeZones()); + assertEquals(timeZoneMappings("Europe/London"), + countryTimeZones.getEffectiveTimeZoneMappingsAt(0 /* whenMillis */)); } @Test public void createValidated_nullDefault() throws Exception { CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "gb", null, true /* everUsesUtc */, timeZoneMappings("Europe/London"), "test"); + "gb", null, false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings("Europe/London"), "test"); assertNull(countryTimeZones.getDefaultTimeZoneId()); + assertNull(countryTimeZones.getDefaultTimeZone()); } @Test public void createValidated_invalidDefault() throws Exception { CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "gb", INVALID_TZ_ID, true /* everUsesUtc */, + "gb", INVALID_TZ_ID, false /* defaultTimeZoneBoost */, true /* everUsesUtc */, timeZoneMappings("Europe/London", INVALID_TZ_ID), "test"); assertNull(countryTimeZones.getDefaultTimeZoneId()); + assertNull(countryTimeZones.getDefaultTimeZone()); assertEquals(timeZoneMappings("Europe/London"), countryTimeZones.getTimeZoneMappings()); - assertZonesEqual(zones("Europe/London"), countryTimeZones.getIcuTimeZones()); + assertEquals(timeZoneMappings("Europe/London"), + countryTimeZones.getEffectiveTimeZoneMappingsAt(0 /* whenMillis */)); } @Test public void createValidated_unknownTimeZoneIdIgnored() throws Exception { CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* everUsesUtc */, + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, timeZoneMappings("Unknown_Id", "Europe/London"), "test"); assertEquals(timeZoneMappings("Europe/London"), countryTimeZones.getTimeZoneMappings()); - assertZonesEqual(zones("Europe/London"), countryTimeZones.getIcuTimeZones()); + assertEquals(timeZoneMappings("Europe/London"), + countryTimeZones.getEffectiveTimeZoneMappingsAt(0 /* whenMillis */)); } @Test public void isForCountryCode() throws Exception { CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* everUsesUtc */, timeZoneMappings("Europe/London"), - "test"); + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings("Europe/London"), "test"); assertTrue(countryTimeZones.isForCountryCode("GB")); assertTrue(countryTimeZones.isForCountryCode("Gb")); assertTrue(countryTimeZones.isForCountryCode("gB")); @@ -117,375 +126,134 @@ public class CountryTimeZonesTest { @Test public void structuresAreImmutable() throws Exception { CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* everUsesUtc */, timeZoneMappings("Europe/London"), - "test"); + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings("Europe/London"), "test"); assertImmutableTimeZone(countryTimeZones.getDefaultTimeZone()); - List<TimeZone> tzList = countryTimeZones.getIcuTimeZones(); - assertEquals(1, tzList.size()); - assertImmutableList(tzList); - assertImmutableTimeZone(tzList.get(0)); - List<TimeZoneMapping> timeZoneMappings = countryTimeZones.getTimeZoneMappings(); assertEquals(1, timeZoneMappings.size()); assertImmutableList(timeZoneMappings); - } - @Test - public void lookupByOffsetWithBiasDeprecated_oneCandidate() throws Exception { - CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* everUsesUtc */, timeZoneMappings("Europe/London"), "test"); - - OffsetResult expectedResult = new OffsetResult(LONDON_TZ, true /* oneMatch */); - - // The three parameters match the configured zone: offset, isDst and time. - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_DST, null /* bias */)); - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_NO_DST_OFFSET_MILLIS, - false /* isDst */, WHEN_NO_DST, null /* bias */)); - - // Some lookup failure cases where the offset, isDst and time do not match the configured - // zone. - OffsetResult noDstMatch1 = countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, true /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch1); - - OffsetResult noDstMatch2 = countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, false /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch2); - - OffsetResult noDstMatch3 = countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch3); - - OffsetResult noDstMatch4 = countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, true /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch4); - - OffsetResult noDstMatch5 = countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, false /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch5); - - OffsetResult noDstMatch6 = countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, false /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch6); - - // Some bias cases below. - - // The bias is irrelevant here: it matches what would be returned anyway. - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_DST, LONDON_TZ /* bias */)); - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_NO_DST_OFFSET_MILLIS, - false /* isDst */, WHEN_NO_DST, LONDON_TZ /* bias */)); - // A sample of a non-matching case with bias. - assertNull(countryTimeZones.lookupByOffsetWithBias(LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_NO_DST, LONDON_TZ /* bias */)); - - // The bias should be ignored: it doesn't match any of the country's zones. - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_DST, NEW_YORK_TZ /* bias */)); - - // The bias should still be ignored even though it matches the offset information given: - // it doesn't match any of the country's configured zones. - assertNull(countryTimeZones.lookupByOffsetWithBias(NEW_YORK_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_DST, NEW_YORK_TZ /* bias */)); - } - - @Test - public void lookupByOffsetWithBiasDeprecated_multipleNonOverlappingCandidates() - throws Exception { - CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", "Europe/London", true /* everUsesUtc */, - timeZoneMappings("America/New_York", "Europe/London"), "test"); - - OffsetResult expectedLondonResult = new OffsetResult(LONDON_TZ, true /* oneMatch */); - OffsetResult expectedNewYorkResult = new OffsetResult(NEW_YORK_TZ, true /* oneMatch */); - - // The three parameters match the configured zone: offset, isDst and time. - assertOffsetResultEquals(expectedLondonResult, countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, null /* bias */)); - assertOffsetResultEquals(expectedLondonResult, countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, false /* isDst */, WHEN_NO_DST, null /* bias */)); - assertOffsetResultEquals(expectedNewYorkResult, countryTimeZones.lookupByOffsetWithBias( - NEW_YORK_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, null /* bias */)); - assertOffsetResultEquals(expectedNewYorkResult, countryTimeZones.lookupByOffsetWithBias( - NEW_YORK_NO_DST_OFFSET_MILLIS, false /* isDst */, WHEN_NO_DST, null /* bias */)); - - // Some lookup failure cases where the offset, isDst and time do not match the configured - // zone. This is a sample, not complete. - OffsetResult noDstMatch1 = countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, true /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch1); - - OffsetResult noDstMatch2 = countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, false /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch2); - - OffsetResult noDstMatch3 = countryTimeZones.lookupByOffsetWithBias( - NEW_YORK_NO_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch3); - - OffsetResult noDstMatch4 = countryTimeZones.lookupByOffsetWithBias( - NEW_YORK_NO_DST_OFFSET_MILLIS, true /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch4); - - OffsetResult noDstMatch5 = countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, false /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch5); - - OffsetResult noDstMatch6 = countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, false /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch6); - - // Some bias cases below. - - // The bias is irrelevant here: it matches what would be returned anyway. - assertOffsetResultEquals(expectedLondonResult, countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, LONDON_TZ /* bias */)); - assertOffsetResultEquals(expectedLondonResult, countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, false /* isDst */, WHEN_NO_DST, LONDON_TZ /* bias */)); - // A sample of a non-matching case with bias. - assertNull(countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, true /* isDst */, WHEN_NO_DST, LONDON_TZ /* bias */)); - - // The bias should be ignored: it matches a configured zone, but the offset is wrong so - // should not be considered a match. - assertOffsetResultEquals(expectedLondonResult, countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, NEW_YORK_TZ /* bias */)); - } - - // This is an artificial case very similar to America/Denver and America/Phoenix in the US: both - // have the same offset for 6 months of the year but diverge. Australia/Lord_Howe too. - @Test - public void lookupByOffsetWithBiasDeprecated_multipleOverlappingCandidates() throws Exception { - // Three zones that have the same offset for some of the year. Europe/London changes - // offset WHEN_DST, the others do not. - CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", "Europe/London", true /* everUsesUtc */, - timeZoneMappings("Atlantic/Reykjavik", "Europe/London", "Etc/UTC"), "test"); - - // This is the no-DST offset for LONDON_TZ, REYKJAVIK_TZ. UTC_TZ. - final int noDstOffset = LONDON_NO_DST_OFFSET_MILLIS; - // This is the DST offset for LONDON_TZ. - final int dstOffset = LONDON_DST_OFFSET_MILLIS; - - OffsetResult expectedLondonOnlyMatch = new OffsetResult(LONDON_TZ, true /* oneMatch */); - OffsetResult expectedReykjavikBestMatch = - new OffsetResult(REYKJAVIK_TZ, false /* oneMatch */); - - // The three parameters match the configured zone: offset, isDst and when. - assertOffsetResultEquals(expectedLondonOnlyMatch, - countryTimeZones.lookupByOffsetWithBias(dstOffset, true /* isDst */, WHEN_DST, - null /* bias */)); - assertOffsetResultEquals(expectedReykjavikBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, false /* isDst */, WHEN_NO_DST, - null /* bias */)); - assertOffsetResultEquals(expectedLondonOnlyMatch, - countryTimeZones.lookupByOffsetWithBias(dstOffset, true /* isDst */, WHEN_DST, - null /* bias */)); - assertOffsetResultEquals(expectedReykjavikBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, false /* isDst */, WHEN_NO_DST, - null /* bias */)); - assertOffsetResultEquals(expectedReykjavikBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, false /* isDst */, WHEN_DST, - null /* bias */)); - - // Some lookup failure cases where the offset, isDst and time do not match the configured - // zones. - OffsetResult noDstMatch1 = countryTimeZones.lookupByOffsetWithBias(dstOffset, - true /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch1); - - OffsetResult noDstMatch2 = countryTimeZones.lookupByOffsetWithBias(noDstOffset, - true /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch2); - - OffsetResult noDstMatch3 = countryTimeZones.lookupByOffsetWithBias(noDstOffset, - true /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch3); - - OffsetResult noDstMatch4 = countryTimeZones.lookupByOffsetWithBias(dstOffset, - false /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch4); - - - // Some bias cases below. - - // Multiple zones match but Reykjavik is the bias. - assertOffsetResultEquals(expectedReykjavikBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, false /* isDst */, WHEN_NO_DST, - REYKJAVIK_TZ /* bias */)); - - // Multiple zones match but London is the bias. - OffsetResult expectedLondonBestMatch = new OffsetResult(LONDON_TZ, false /* oneMatch */); - assertOffsetResultEquals(expectedLondonBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, false /* isDst */, WHEN_NO_DST, - LONDON_TZ /* bias */)); - - // Multiple zones match but UTC is the bias. - OffsetResult expectedUtcResult = new OffsetResult(UTC_TZ, false /* oneMatch */); - assertOffsetResultEquals(expectedUtcResult, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, false /* isDst */, WHEN_NO_DST, - UTC_TZ /* bias */)); - - // The bias should be ignored: it matches a configured zone, but the offset is wrong so - // should not be considered a match. - assertOffsetResultEquals(expectedLondonOnlyMatch, - countryTimeZones.lookupByOffsetWithBias(LONDON_DST_OFFSET_MILLIS, true /* isDst */, - WHEN_DST, REYKJAVIK_TZ /* bias */)); + List<TimeZoneMapping> effectiveTimeZoneMappings = + countryTimeZones.getEffectiveTimeZoneMappingsAt(0 /* whenMillis */); + assertEquals(1, effectiveTimeZoneMappings.size()); + assertImmutableList(effectiveTimeZoneMappings); } @Test public void lookupByOffsetWithBias_oneCandidate() throws Exception { CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* uses UTC */, timeZoneMappings("Europe/London"), - "test"); - - OffsetResult expectedResult = new OffsetResult(LONDON_TZ, true /* oneMatch */); - - // The three parameters match the configured zone: offset, isDst and time. - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_DST_OFFSET_MILLIS, - NORMAL_DST_ADJUSTMENT, WHEN_DST, null /* bias */)); - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_NO_DST_OFFSET_MILLIS, - 0 /* no DST */, WHEN_NO_DST, null /* bias */)); - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_DST_OFFSET_MILLIS, - null /* unknown DST */, WHEN_DST, null /* bias */)); - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_NO_DST_OFFSET_MILLIS, - null /* unknown DST */, WHEN_NO_DST, null /* bias */)); - - // Some lookup failure cases where the offset, DST offset and time do not match the - // configured zone. - OffsetResult noDstMatch1 = countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, NORMAL_DST_ADJUSTMENT, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch1); - - OffsetResult noDstMatch2 = countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, 0 /* no DST */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch2); - - OffsetResult noDstMatch3 = countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, NORMAL_DST_ADJUSTMENT, WHEN_DST, null /* bias */); - assertNull(noDstMatch3); - - OffsetResult noDstMatch4 = countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, NORMAL_DST_ADJUSTMENT, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch4); - - OffsetResult noDstMatch5 = countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, 0 /* no DST */, WHEN_DST, null /* bias */); - assertNull(noDstMatch5); - - OffsetResult noDstMatch6 = countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, 0 /* no DST */, WHEN_DST, null /* bias */); - assertNull(noDstMatch6); - - // Some bias cases below. - - // The bias is irrelevant here: it matches what would be returned anyway. - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_DST_OFFSET_MILLIS, - NORMAL_DST_ADJUSTMENT, WHEN_DST, LONDON_TZ /* bias */)); - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_NO_DST_OFFSET_MILLIS, - 0 /* no DST */, WHEN_NO_DST, LONDON_TZ /* bias */)); - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_NO_DST_OFFSET_MILLIS, - null /* unknown DST */, WHEN_NO_DST, LONDON_TZ /* bias */)); - // A sample of a non-matching case with bias. - assertNull(countryTimeZones.lookupByOffsetWithBias(LONDON_DST_OFFSET_MILLIS, - NORMAL_DST_ADJUSTMENT, WHEN_NO_DST, LONDON_TZ /* bias */)); - - // The bias should be ignored: it doesn't match any of the country's zones. - assertOffsetResultEquals(expectedResult, - countryTimeZones.lookupByOffsetWithBias(LONDON_DST_OFFSET_MILLIS, - NORMAL_DST_ADJUSTMENT, WHEN_DST, NEW_YORK_TZ /* bias */)); - - // The bias should still be ignored even though it matches the offset information given: - // it doesn't match any of the country's configured zones. - assertNull(countryTimeZones.lookupByOffsetWithBias(NEW_YORK_DST_OFFSET_MILLIS, - NORMAL_DST_ADJUSTMENT, WHEN_DST, NEW_YORK_TZ /* bias */)); + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings("Europe/London"), "test"); + + OffsetResult lonMatch = new OffsetResult(LON_TZ, true /* oneMatch */); + + // Placeholder constants to improve test case readability. + final Boolean isDst = true; + final Boolean notDst = false; + final Boolean unkIsDst = null; + final TimeZone noBias = null; + final OffsetResult noMatch = null; + + Object[][] testCases = new Object[][] { + // totalOffsetMillis, isDst, whenMillis, bias, expectedMatch + + // The parameters match the zone: total offset and time. + { LON_DST_TOTAL_OFFSET, unkIsDst, WHEN_DST, noBias, lonMatch }, + { LON_NO_DST_TOTAL_OFFSET, unkIsDst, WHEN_NO_DST, noBias, lonMatch }, + + // The parameters match the zone: total offset, isDst and time. + { LON_DST_TOTAL_OFFSET, isDst, WHEN_DST, noBias, lonMatch }, + { LON_NO_DST_TOTAL_OFFSET, notDst, WHEN_NO_DST, noBias, lonMatch }, + + // Some lookup failure cases where the total offset, isDst and time do not match the + // zone. + { LON_DST_TOTAL_OFFSET, isDst, WHEN_NO_DST, noBias, noMatch }, + { LON_DST_TOTAL_OFFSET, notDst, WHEN_NO_DST, noBias, noMatch }, + { LON_NO_DST_TOTAL_OFFSET, isDst, WHEN_DST, noBias, noMatch }, + { LON_NO_DST_TOTAL_OFFSET, isDst, WHEN_NO_DST, noBias, noMatch }, + { LON_DST_TOTAL_OFFSET, notDst, WHEN_DST, noBias, noMatch }, + { LON_NO_DST_TOTAL_OFFSET, notDst, WHEN_DST, noBias, noMatch }, + + // Some bias cases below. + + // The bias is irrelevant here: it matches what would be returned anyway. + { LON_DST_TOTAL_OFFSET, isDst, WHEN_DST, LON_TZ, lonMatch }, + { LON_NO_DST_TOTAL_OFFSET, notDst, WHEN_NO_DST, LON_TZ, lonMatch }, + + // A sample of a non-matching case with bias. + { LON_DST_TOTAL_OFFSET, isDst, WHEN_NO_DST, LON_TZ, noMatch }, + + // The bias should be ignored: it doesn't match any of the country's zones. + { LON_DST_TOTAL_OFFSET, isDst, WHEN_DST, NY_TZ, lonMatch }, + + // The bias should still be ignored even though it matches the offset information + // given it doesn't match any of the country's zones. + { NY_DST_TOTAL_OFFSET, isDst, WHEN_DST, NY_TZ, noMatch }, + }; + executeLookupByOffsetWithBiasTestCases(countryTimeZones, testCases); } @Test - public void lookupByOffsetWithBias_multipleNonOverlappingCandidates() - throws Exception { + public void lookupByOffsetWithBias_multipleNonOverlappingCandidates() throws Exception { CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", "Europe/London", true /* uses UTC */, + "xx", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, timeZoneMappings("America/New_York", "Europe/London"), "test"); - OffsetResult expectedLondonResult = new OffsetResult(LONDON_TZ, true /* oneMatch */); - OffsetResult expectedNewYorkResult = new OffsetResult(NEW_YORK_TZ, true /* oneMatch */); - - // The three parameters match the configured zone: offset, DST offset and time. - assertOffsetResultEquals(expectedLondonResult, countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, NORMAL_DST_ADJUSTMENT, WHEN_DST, null /* bias */)); - assertOffsetResultEquals(expectedLondonResult, countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, 0 /* no DST */, WHEN_NO_DST, null /* bias */)); - assertOffsetResultEquals(expectedLondonResult, countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, null /* unknown DST */, WHEN_NO_DST, null /* bias */)); - assertOffsetResultEquals(expectedNewYorkResult, countryTimeZones.lookupByOffsetWithBias( - NEW_YORK_DST_OFFSET_MILLIS, NORMAL_DST_ADJUSTMENT, WHEN_DST, null /* bias */)); - assertOffsetResultEquals(expectedNewYorkResult, countryTimeZones.lookupByOffsetWithBias( - NEW_YORK_NO_DST_OFFSET_MILLIS, 0 /* no DST */, WHEN_NO_DST, null /* bias */)); - assertOffsetResultEquals(expectedNewYorkResult, countryTimeZones.lookupByOffsetWithBias( - NEW_YORK_NO_DST_OFFSET_MILLIS, null /* unknown DST */, WHEN_NO_DST, - null /* bias */)); - - // Some lookup failure cases where the offset, DST offset and time do not match the - // configured zone. This is a sample, not complete. - OffsetResult noDstMatch1 = countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, NORMAL_DST_ADJUSTMENT, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch1); - - OffsetResult noDstMatch2 = countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, 0 /* no DST */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch2); - - OffsetResult noDstMatch3 = countryTimeZones.lookupByOffsetWithBias( - NEW_YORK_NO_DST_OFFSET_MILLIS, NORMAL_DST_ADJUSTMENT, WHEN_DST, null /* bias */); - assertNull(noDstMatch3); - - OffsetResult noDstMatch4 = countryTimeZones.lookupByOffsetWithBias( - NEW_YORK_NO_DST_OFFSET_MILLIS, NORMAL_DST_ADJUSTMENT, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch4); - - OffsetResult noDstMatch5 = countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, 0 /* no DST */, WHEN_DST, null /* bias */); - assertNull(noDstMatch5); - - OffsetResult noDstMatch6 = countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, 0 /* no DST */, WHEN_DST, null /* bias */); - assertNull(noDstMatch6); - - // Some bias cases below. - - // The bias is irrelevant here: it matches what would be returned anyway. - assertOffsetResultEquals(expectedLondonResult, countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, NORMAL_DST_ADJUSTMENT, WHEN_DST, LONDON_TZ /* bias */)); - assertOffsetResultEquals(expectedLondonResult, countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, 0 /* no DST */, WHEN_NO_DST, LONDON_TZ /* bias */)); - assertOffsetResultEquals(expectedLondonResult, countryTimeZones.lookupByOffsetWithBias( - LONDON_NO_DST_OFFSET_MILLIS, null /* unknown DST */, WHEN_NO_DST, - LONDON_TZ /* bias */)); - - // A sample of a non-matching case with bias. - assertNull(countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, NORMAL_DST_ADJUSTMENT, WHEN_NO_DST, LONDON_TZ /* bias */)); - - // The bias should be ignored: it matches a configured zone, but the offset is wrong so - // should not be considered a match. - assertOffsetResultEquals(expectedLondonResult, countryTimeZones.lookupByOffsetWithBias( - LONDON_DST_OFFSET_MILLIS, NORMAL_DST_ADJUSTMENT, WHEN_DST, NEW_YORK_TZ /* bias */)); + OffsetResult lonMatch = new OffsetResult(LON_TZ, true /* oneMatch */); + OffsetResult nyMatch = new OffsetResult(NY_TZ, true /* oneMatch */); + + // Placeholder constants to improve test case readability. + final Boolean isDst = true; + final Boolean notDst = false; + final Boolean unkIsDst = null; + final TimeZone noBias = null; + final OffsetResult noMatch = null; + + Object[][] testCases = new Object[][] { + // totalOffsetMillis, isDst, dstOffsetMillis, whenMillis, bias, expectedMatch + + // The parameters match the zone: total offset and time. + { LON_DST_TOTAL_OFFSET, unkIsDst, WHEN_DST, noBias, lonMatch }, + { LON_NO_DST_TOTAL_OFFSET, unkIsDst, WHEN_NO_DST, noBias, lonMatch }, + { NY_NO_DST_TOTAL_OFFSET, unkIsDst, WHEN_NO_DST, noBias, nyMatch }, + { NY_DST_TOTAL_OFFSET, unkIsDst, WHEN_DST, noBias, nyMatch }, + + // The parameters match the zone: total offset, isDst and time. + { LON_DST_TOTAL_OFFSET, isDst, WHEN_DST, noBias, lonMatch }, + { LON_NO_DST_TOTAL_OFFSET, notDst, WHEN_NO_DST, noBias, lonMatch }, + { NY_DST_TOTAL_OFFSET, isDst, WHEN_DST, noBias, nyMatch }, + { NY_NO_DST_TOTAL_OFFSET, notDst, WHEN_NO_DST, noBias, nyMatch }, + + // Some lookup failure cases where the total offset, isDst and time do not match the + // zone. This is a sample, not complete. + { LON_DST_TOTAL_OFFSET, isDst, WHEN_NO_DST, noBias, noMatch }, + { LON_DST_TOTAL_OFFSET, unkIsDst, WHEN_NO_DST, noBias, noMatch }, + { LON_DST_TOTAL_OFFSET, notDst, WHEN_DST, noBias, noMatch }, + { LON_NO_DST_TOTAL_OFFSET, isDst, WHEN_DST, noBias, noMatch }, + { LON_NO_DST_TOTAL_OFFSET, isDst, WHEN_NO_DST, noBias, noMatch }, + { LON_NO_DST_TOTAL_OFFSET, unkIsDst, WHEN_DST, noBias, noMatch }, + { LON_NO_DST_TOTAL_OFFSET, notDst, WHEN_DST, noBias, noMatch }, + + // Some bias cases below. + + // The bias is irrelevant here: it matches what would be returned anyway. + { LON_DST_TOTAL_OFFSET, isDst, WHEN_DST, LON_TZ, lonMatch }, + { LON_DST_TOTAL_OFFSET, unkIsDst, WHEN_DST, LON_TZ, lonMatch }, + { LON_NO_DST_TOTAL_OFFSET, unkIsDst, WHEN_NO_DST, LON_TZ, lonMatch }, + + // A sample of non-matching cases with bias. + { LON_NO_DST_TOTAL_OFFSET, isDst, WHEN_NO_DST, LON_TZ, noMatch }, + { LON_DST_TOTAL_OFFSET, isDst, WHEN_NO_DST, LON_TZ, noMatch }, + { LON_DST_TOTAL_OFFSET, unkIsDst, WHEN_NO_DST, LON_TZ, noMatch }, + + // The bias should be ignored: it matches a zone, but the offset is wrong so + // should not be considered a match. + { LON_DST_TOTAL_OFFSET, isDst, WHEN_DST, NY_TZ, lonMatch }, + { LON_DST_TOTAL_OFFSET, unkIsDst, WHEN_DST, NY_TZ, lonMatch }, + }; + executeLookupByOffsetWithBiasTestCases(countryTimeZones, testCases); } // This is an artificial case very similar to America/Denver and America/Phoenix in the US: both @@ -495,146 +263,171 @@ public class CountryTimeZonesTest { // Three zones that have the same offset for some of the year. Europe/London changes // offset WHEN_DST, the others do not. CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", "Europe/London", true /* uses UTC */, + "xx", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, timeZoneMappings("Atlantic/Reykjavik", "Europe/London", "Etc/UTC"), "test"); - // This is the no-DST offset for LONDON_TZ, REYKJAVIK_TZ. UTC_TZ. - final int noDstOffset = LONDON_NO_DST_OFFSET_MILLIS; - // This is the DST offset for LONDON_TZ. - final int dstOffset = LONDON_DST_OFFSET_MILLIS; - - OffsetResult expectedLondonOnlyMatch = new OffsetResult(LONDON_TZ, true /* oneMatch */); - OffsetResult expectedReykjavikBestMatch = - new OffsetResult(REYKJAVIK_TZ, false /* oneMatch */); - - // The three parameters match the configured zone: offset, DST offset and time. - assertOffsetResultEquals(expectedLondonOnlyMatch, - countryTimeZones.lookupByOffsetWithBias(dstOffset, NORMAL_DST_ADJUSTMENT, WHEN_DST, - null /* bias */)); - assertOffsetResultEquals(expectedReykjavikBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, 0 /* no DST */, WHEN_NO_DST, - null /* bias */)); - assertOffsetResultEquals(expectedLondonOnlyMatch, - countryTimeZones.lookupByOffsetWithBias(dstOffset, NORMAL_DST_ADJUSTMENT, WHEN_DST, - null /* bias */)); - assertOffsetResultEquals(expectedReykjavikBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, 0 /* no DST */, WHEN_NO_DST, - null /* bias */)); - assertOffsetResultEquals(expectedReykjavikBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, 0 /* no DST */, WHEN_DST, - null /* bias */)); - - // Unknown DST cases - assertOffsetResultEquals(expectedReykjavikBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, null, WHEN_NO_DST, - null /* bias */)); - assertOffsetResultEquals(expectedReykjavikBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, null, WHEN_DST, - null /* bias */)); - assertNull(countryTimeZones.lookupByOffsetWithBias(dstOffset, null, WHEN_NO_DST, - null /* bias */)); - assertOffsetResultEquals(expectedLondonOnlyMatch, - countryTimeZones.lookupByOffsetWithBias(dstOffset, null, WHEN_DST, - null /* bias */)); - - // Some lookup failure cases where the offset, DST offset and time do not match the - // configured zones. - OffsetResult noDstMatch1 = countryTimeZones.lookupByOffsetWithBias(dstOffset, - NORMAL_DST_ADJUSTMENT, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch1); - - OffsetResult noDstMatch2 = countryTimeZones.lookupByOffsetWithBias(noDstOffset, - NORMAL_DST_ADJUSTMENT, WHEN_DST, null /* bias */); - assertNull(noDstMatch2); - - OffsetResult noDstMatch3 = countryTimeZones.lookupByOffsetWithBias(noDstOffset, - NORMAL_DST_ADJUSTMENT, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch3); - - OffsetResult noDstMatch4 = countryTimeZones.lookupByOffsetWithBias(dstOffset, - 0 /* no DST */, WHEN_DST, null /* bias */); - assertNull(noDstMatch4); - - - // Some bias cases below. - - // Multiple zones match but Reykjavik is the bias. - assertOffsetResultEquals(expectedReykjavikBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, 0 /* no DST */, WHEN_NO_DST, - REYKJAVIK_TZ /* bias */)); - assertOffsetResultEquals(expectedReykjavikBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, null /* unknown DST */, - WHEN_NO_DST, REYKJAVIK_TZ /* bias */)); - - // Multiple zones match but London is the bias. - OffsetResult expectedLondonBestMatch = new OffsetResult(LONDON_TZ, false /* oneMatch */); - assertOffsetResultEquals(expectedLondonBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, 0 /* no DST */, WHEN_NO_DST, - LONDON_TZ /* bias */)); - assertOffsetResultEquals(expectedLondonBestMatch, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, null /* unknown DST */, - WHEN_NO_DST, LONDON_TZ /* bias */)); - - // Multiple zones match but UTC is the bias. - OffsetResult expectedUtcResult = new OffsetResult(UTC_TZ, false /* oneMatch */); - assertOffsetResultEquals(expectedUtcResult, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, 0 /* no DST */, WHEN_NO_DST, - UTC_TZ /* bias */)); - assertOffsetResultEquals(expectedUtcResult, - countryTimeZones.lookupByOffsetWithBias(noDstOffset, null /* unknown DST */, - WHEN_NO_DST, UTC_TZ /* bias */)); - - // The bias should be ignored: it matches a configured zone, but the offset is wrong so - // should not be considered a match. - assertOffsetResultEquals(expectedLondonOnlyMatch, - countryTimeZones.lookupByOffsetWithBias(LONDON_DST_OFFSET_MILLIS, - NORMAL_DST_ADJUSTMENT, WHEN_DST, REYKJAVIK_TZ /* bias */)); + // Placeholder constants to improve test case readability. + final Boolean isDst = true; + final Boolean notDst = false; + final Boolean unkIsDst = null; + final TimeZone noBias = null; + final OffsetResult noMatch = null; + + // This is the no-DST offset for LON_TZ, REYK_TZ. UTC_TZ. + final int noDstTotalOffset = LON_NO_DST_TOTAL_OFFSET; + // This is the DST offset for LON_TZ. + final int dstTotalOffset = LON_DST_TOTAL_OFFSET; + + OffsetResult lonOnlyMatch = new OffsetResult(LON_TZ, true /* oneMatch */); + OffsetResult lonBestMatch = new OffsetResult(LON_TZ, false /* oneMatch */); + OffsetResult reykBestMatch = new OffsetResult(REYK_TZ, false /* oneMatch */); + OffsetResult utcBestMatch = new OffsetResult(UTC_TZ, false /* oneMatch */); + + Object[][] testCases = new Object[][] { + // totalOffsetMillis, isDst, dstOffsetMillis, whenMillis, bias, expectedMatch + + // The parameters match one zone: total offset and time. + { dstTotalOffset, unkIsDst, WHEN_DST, noBias, lonOnlyMatch }, + { dstTotalOffset, unkIsDst, WHEN_DST, noBias, lonOnlyMatch }, + + // The parameters match several zones: total offset and time. + { noDstTotalOffset, unkIsDst, WHEN_NO_DST, noBias, reykBestMatch }, + { noDstTotalOffset, unkIsDst, WHEN_DST, noBias, reykBestMatch }, + + // The parameters match one zone: total offset, isDst and time. + { dstTotalOffset, isDst, WHEN_DST, noBias, lonOnlyMatch }, + { dstTotalOffset, isDst, WHEN_DST, noBias, lonOnlyMatch }, + + { noDstTotalOffset, notDst, WHEN_NO_DST, noBias, reykBestMatch }, + { noDstTotalOffset, notDst, WHEN_DST, noBias, reykBestMatch }, + + // Some lookup failure cases where the total offset, isDst and time do not match any + // zone. + { dstTotalOffset, isDst, WHEN_NO_DST, noBias, noMatch }, + { dstTotalOffset, unkIsDst, WHEN_NO_DST, noBias, noMatch }, + { noDstTotalOffset, isDst, WHEN_NO_DST, noBias, noMatch }, + { noDstTotalOffset, isDst, WHEN_DST, noBias, noMatch }, + + // Some bias cases below. + + // Multiple zones match but Reykjavik is the bias. + { noDstTotalOffset, notDst, WHEN_NO_DST, REYK_TZ, reykBestMatch }, + + // Multiple zones match but London is the bias. + { noDstTotalOffset, notDst, WHEN_NO_DST, LON_TZ, lonBestMatch }, + + // Multiple zones match but UTC is the bias. + { noDstTotalOffset, notDst, WHEN_NO_DST, UTC_TZ, utcBestMatch }, + + // The bias should be ignored: it matches a zone, but the offset is wrong so + // should not be considered a match. + { LON_DST_TOTAL_OFFSET, isDst, WHEN_DST, REYK_TZ, lonOnlyMatch }, + { LON_DST_TOTAL_OFFSET, unkIsDst, WHEN_DST, REYK_TZ, lonOnlyMatch }, + }; + executeLookupByOffsetWithBiasTestCases(countryTimeZones, testCases); } - @Test - public void isDefaultOkForCountryTimeZoneDetection_noZones() { - CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", "Europe/London", true /* everUsesUtc */, timeZoneMappings(), "test"); - assertFalse(countryTimeZones.isDefaultOkForCountryTimeZoneDetection(WHEN_DST)); - assertFalse(countryTimeZones.isDefaultOkForCountryTimeZoneDetection(WHEN_NO_DST)); + private static void executeLookupByOffsetWithBiasTestCases( + CountryTimeZones countryTimeZones, Object[][] testCases) { + + List<String> failures = new ArrayList<>(); + for (int i = 0; i < testCases.length; i++) { + Object[] testCase = testCases[i]; + int totalOffsetMillis = (int) testCase[0]; + Boolean isDst = (Boolean) testCase[1]; + long whenMillis = (Long) testCase[2]; + TimeZone bias = (TimeZone) testCase[3]; + OffsetResult expectedMatch = (OffsetResult) testCase[4]; + + OffsetResult actualMatch; + if (isDst == null) { + actualMatch = countryTimeZones.lookupByOffsetWithBias( + whenMillis, bias, totalOffsetMillis); + } else { + actualMatch = countryTimeZones.lookupByOffsetWithBias( + whenMillis, bias, totalOffsetMillis, isDst); + } + + if (!offsetResultEquals(expectedMatch, actualMatch)) { + Function<TimeZone, String> timeZoneFormatter = + x -> x == null ? "null" : x.getID(); + Function<OffsetResult, String> offsetResultFormatter = + x -> x == null ? "null" + : "{" + x.getTimeZone().getID() + ", " + x.isOnlyMatch() + "}"; + failures.add("Fail: case=" + i + + ", totalOffsetMillis=" + totalOffsetMillis + + ", isDst=" + isDst + + ", whenMillis=" + whenMillis + + ", bias=" + timeZoneFormatter.apply(bias) + + ", expectedMatch=" + offsetResultFormatter.apply(expectedMatch) + + ", actualMatch=" + offsetResultFormatter.apply(actualMatch) + + "\n"); + } + } + if (!failures.isEmpty()) { + fail("Failed:\n" + failures); + } } @Test - public void isDefaultOkForCountryTimeZoneDetection_oneZone() { + public void getEffectiveTimeZonesAt_noZones() { CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", "Europe/London", true /* everUsesUtc */, timeZoneMappings("Europe/London"), - "test"); - assertTrue(countryTimeZones.isDefaultOkForCountryTimeZoneDetection(WHEN_DST)); - assertTrue(countryTimeZones.isDefaultOkForCountryTimeZoneDetection(WHEN_NO_DST)); + "xx", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings(), "test"); + assertEquals(timeZoneMappings(), + countryTimeZones.getEffectiveTimeZoneMappingsAt(0 /* whenMillis */)); + assertEquals(timeZoneMappings(), + countryTimeZones.getEffectiveTimeZoneMappingsAt(Long.MIN_VALUE)); + assertEquals(timeZoneMappings(), + countryTimeZones.getEffectiveTimeZoneMappingsAt(Long.MAX_VALUE)); } @Test - public void isDefaultOkForCountryTimeZoneDetection_twoZones_overlap() { + public void getEffectiveTimeZonesAt_oneZone() { CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", "Europe/London", true /* everUsesUtc */, - timeZoneMappings("Europe/London", "Etc/UTC"), "test"); - // Europe/London is the same as UTC in the Winter, so all the zones have the same offset - // in Winter, but not in Summer. - assertFalse(countryTimeZones.isDefaultOkForCountryTimeZoneDetection(WHEN_DST)); - assertTrue(countryTimeZones.isDefaultOkForCountryTimeZoneDetection(WHEN_NO_DST)); + "xx", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings("Europe/London"), "test"); + assertEquals(timeZoneMappings("Europe/London"), + countryTimeZones.getEffectiveTimeZoneMappingsAt(0)); + assertEquals(timeZoneMappings("Europe/London"), + countryTimeZones.getEffectiveTimeZoneMappingsAt(Long.MIN_VALUE)); + assertEquals(timeZoneMappings("Europe/London"), + countryTimeZones.getEffectiveTimeZoneMappingsAt(Long.MAX_VALUE)); } @Test - public void isDefaultOkForCountryTimeZoneDetection_twoZones_noOverlap() { + public void getEffectiveTimeZonesAt_filtering() { + TimeZoneMapping alwaysUsed = timeZoneMapping("Europe/London", null /* notUsedAfter */); + + long mappingNotUsedAfterMillis = 0L; + TimeZoneMapping notAlwaysUsed = timeZoneMapping("Europe/Paris", + mappingNotUsedAfterMillis /* notUsedAfter */); + + List<TimeZoneMapping> timeZoneMappings = list(alwaysUsed, notAlwaysUsed); CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", "Europe/London", true /* everUsesUtc */, - timeZoneMappings("Europe/London", "America/New_York"), "test"); - // The zones have different offsets all year, so it would never be ok to use the default - // zone for the country of "xx". - assertFalse(countryTimeZones.isDefaultOkForCountryTimeZoneDetection(WHEN_DST)); - assertFalse(countryTimeZones.isDefaultOkForCountryTimeZoneDetection(WHEN_NO_DST)); + "xx", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings, "test"); + + // Before and at mappingNotUsedAfterMillis, both mappings are "effective". + assertEquals(list(alwaysUsed, notAlwaysUsed), + countryTimeZones.getEffectiveTimeZoneMappingsAt(Long.MIN_VALUE)); + assertEquals(list(alwaysUsed, notAlwaysUsed), + countryTimeZones.getEffectiveTimeZoneMappingsAt(mappingNotUsedAfterMillis)); + + // The following should filter the second mapping because it's not "effective" after + // mappingNotUsedAfterMillis. + assertEquals(list(alwaysUsed), + countryTimeZones.getEffectiveTimeZoneMappingsAt(mappingNotUsedAfterMillis + 1)); + assertEquals(list(alwaysUsed), + countryTimeZones.getEffectiveTimeZoneMappingsAt(Long.MAX_VALUE)); } @Test public void hasUtcZone_everUseUtcHintOverridesZoneInformation() { // The country has a single zone. Europe/London uses UTC in Winter. CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", "Etc/UTC", false /* everUsesUtc */, timeZoneMappings("Etc/UTC"), "test"); + "xx", "Etc/UTC", false /* defaultTimeZoneBoost */, false /* everUsesUtc */, + timeZoneMappings("Etc/UTC"), "test"); assertFalse(countryTimeZones.hasUtcZone(WHEN_DST)); assertFalse(countryTimeZones.hasUtcZone(WHEN_NO_DST)); } @@ -643,8 +436,8 @@ public class CountryTimeZonesTest { public void hasUtcZone_singleZone() { // The country has a single zone. Europe/London uses UTC in Winter. CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", "Europe/London", true /* everUsesUtc */, timeZoneMappings("Europe/London"), - "test"); + "xx", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings("Europe/London"), "test"); assertFalse(countryTimeZones.hasUtcZone(WHEN_DST)); assertTrue(countryTimeZones.hasUtcZone(WHEN_NO_DST)); } @@ -653,7 +446,8 @@ public class CountryTimeZonesTest { public void hasUtcZone_multipleZonesWithUtc() { // The country has multiple zones. Europe/London uses UTC in Winter. CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", "America/Los_Angeles", true /* everUsesUtc */, + "xx", "America/Los_Angeles", false /* defaultTimeZoneBoost */, + true /* everUsesUtc */, timeZoneMappings("America/Los_Angeles", "America/New_York", "Europe/London"), "test"); assertFalse(countryTimeZones.hasUtcZone(WHEN_DST)); @@ -664,7 +458,7 @@ public class CountryTimeZonesTest { public void hasUtcZone_multipleZonesWithoutUtc() { // The country has multiple zones, none of which use UTC. CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", "Europe/Paris", false /* everUsesUtc */, + "xx", "Europe/Paris", false /* defaultTimeZoneBoost */, false /* everUsesUtc */, timeZoneMappings("America/Los_Angeles", "America/New_York", "Europe/Paris"), "test"); assertFalse(countryTimeZones.hasUtcZone(WHEN_DST)); @@ -675,13 +469,33 @@ public class CountryTimeZonesTest { public void hasUtcZone_emptyZones() { // The country has no valid zones. CountryTimeZones countryTimeZones = CountryTimeZones.createValidated( - "xx", INVALID_TZ_ID, false /* everUsesUtc */, timeZoneMappings(INVALID_TZ_ID), - "test"); + "xx", INVALID_TZ_ID, false /* defaultTimeZoneBoost */, false /* everUsesUtc */, + timeZoneMappings(INVALID_TZ_ID), "test"); assertTrue(countryTimeZones.getTimeZoneMappings().isEmpty()); assertFalse(countryTimeZones.hasUtcZone(WHEN_DST)); assertFalse(countryTimeZones.hasUtcZone(WHEN_NO_DST)); } + @Test + public void timeZoneMapping_getTimeZone_badZoneId() { + TimeZoneMapping timeZoneMapping = + TimeZoneMapping.createForTests("DOES_NOT_EXIST", true, 1234L); + try { + timeZoneMapping.getTimeZone(); + fail(); + } catch (RuntimeException expected) { + } + } + + @Test + public void timeZoneMapping_getTimeZone_validZoneId() { + TimeZoneMapping timeZoneMapping = + TimeZoneMapping.createForTests("Europe/London", true, 1234L); + TimeZone timeZone = timeZoneMapping.getTimeZone(); + assertTrue(timeZone.isFrozen()); + assertEquals("Europe/London", timeZone.getID()); + } + private void assertImmutableTimeZone(TimeZone timeZone) { try { timeZone.setRawOffset(1000); @@ -703,18 +517,19 @@ public class CountryTimeZonesTest { assertEquals(expected, actual); } - private static void assertOffsetResultEquals(OffsetResult expected, OffsetResult actual) { - assertEquals(expected.mTimeZone.getID(), actual.mTimeZone.getID()); - assertEquals(expected.mOneMatch, actual.mOneMatch); + private static boolean offsetResultEquals(OffsetResult expected, OffsetResult actual) { + return expected == actual + || (expected != null && actual != null + && Objects.equals(expected.getTimeZone().getID(), actual.getTimeZone().getID()) + && expected.isOnlyMatch() == actual.isOnlyMatch()); } - private static void assertZonesEqual(List<TimeZone> expected, List<TimeZone> actual) { - // TimeZone.equals() only checks the ID, but that's ok for these tests. - assertEquals(expected, actual); - } - - private static TimeZone zone(String id) { - return TimeZone.getTimeZone(id); + /** + * Creates a list of default {@link TimeZoneMapping} objects with the specified time zone IDs. + */ + private static TimeZoneMapping timeZoneMapping(String timeZoneId, Long notUsedAfterMillis) { + return TimeZoneMapping.createForTests( + timeZoneId, true /* picker */, notUsedAfterMillis); } /** @@ -727,7 +542,11 @@ public class CountryTimeZonesTest { .collect(Collectors.toList()); } - private static List<TimeZone> zones(String... ids) { - return Arrays.stream(ids).map(TimeZone::getTimeZone).collect(Collectors.toList()); + private static TimeZone zone(String id) { + return TimeZone.getFrozenTimeZone(id); + } + + private static <X> List<X> list(X... xes) { + return Arrays.asList(xes); } } diff --git a/luni/src/test/java/libcore/libcore/timezone/CountryZonesFinderTest.java b/luni/src/test/java/libcore/libcore/timezone/CountryZonesFinderTest.java index 7fc2abf7d9..ecd52013e8 100644 --- a/luni/src/test/java/libcore/libcore/timezone/CountryZonesFinderTest.java +++ b/luni/src/test/java/libcore/libcore/timezone/CountryZonesFinderTest.java @@ -33,16 +33,19 @@ import static org.junit.Assert.fail; public class CountryZonesFinderTest { private static final CountryTimeZones GB_ZONES = CountryTimeZones.createValidated( - "gb", "Europe/London", true, timeZoneMappings("Europe/London"), "test"); + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true, + timeZoneMappings("Europe/London"), "test"); private static final CountryTimeZones IM_ZONES = CountryTimeZones.createValidated( - "im", "Europe/London", true, timeZoneMappings("Europe/London"), "test"); + "im", "Europe/London", false /* defaultTimeZoneBoost */, true, + timeZoneMappings("Europe/London"), "test"); private static final CountryTimeZones FR_ZONES = CountryTimeZones.createValidated( - "fr", "Europe/Paris", true, timeZoneMappings("Europe/Paris"), "test"); + "fr", "Europe/Paris", false /* defaultTimeZoneBoost */, true, + timeZoneMappings("Europe/Paris"), "test"); private static final CountryTimeZones US_ZONES = CountryTimeZones.createValidated( - "us", "America/New_York", true, + "us", "America/New_York", false /* defaultTimeZoneBoost */, true, timeZoneMappings("America/New_York", "America/Los_Angeles"), "test"); @Test diff --git a/luni/src/test/java/libcore/libcore/timezone/TelephonyLookupTest.java b/luni/src/test/java/libcore/libcore/timezone/TelephonyLookupTest.java new file mode 100644 index 0000000000..8b4d8677ac --- /dev/null +++ b/luni/src/test/java/libcore/libcore/timezone/TelephonyLookupTest.java @@ -0,0 +1,367 @@ +/* + * 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. + */ + +package libcore.libcore.timezone; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import libcore.timezone.TelephonyLookup; +import libcore.timezone.TelephonyNetwork; +import libcore.timezone.TelephonyNetworkFinder; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +public class TelephonyLookupTest { + + private Path testDir; + + @Before + public void setUp() throws Exception { + testDir = Files.createTempDirectory("TelephonyLookupTest"); + } + + @After + public void tearDown() throws Exception { + // Delete the testDir and all contents. + Files.walkFileTree(testDir, new SimpleFileVisitor<Path>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) + throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } + + @Test + public void createInstanceWithFallback() throws Exception { + String validXml1 = "<telephony_lookup>\n" + + " <networks>\n" + + " <network mcc=\"123\" mnc=\"456\" country=\"gb\"/>\n" + + " </networks>\n" + + "</telephony_lookup>\n"; + TelephonyNetwork expectedTelephonyNetwork1 = + TelephonyNetwork.create("123", "456", "gb"); + + String validXml2 = "<telephony_lookup>\n" + + " <networks>\n" + + " <network mcc=\"234\" mnc=\"567\" country=\"fr\"/>\n" + + " </networks>\n" + + "</telephony_lookup>\n"; + TelephonyNetwork expectedTelephonyNetwork2 = + TelephonyNetwork.create("234", "567", "fr"); + + String invalidXml = "<foo></foo>\n"; + checkValidateThrowsParserException(invalidXml); + + String validFile1 = createFile(validXml1); + String validFile2 = createFile(validXml2); + String invalidFile = createFile(invalidXml); + String missingFile = createMissingFile(); + + TelephonyLookup file1ThenFile2 = + TelephonyLookup.createInstanceWithFallback(validFile1, validFile2); + assertEquals(list(expectedTelephonyNetwork1), + file1ThenFile2.getTelephonyNetworkFinder().getAll()); + + TelephonyLookup missingFileThenFile1 = + TelephonyLookup.createInstanceWithFallback(missingFile, validFile1); + assertEquals(list(expectedTelephonyNetwork1), + missingFileThenFile1.getTelephonyNetworkFinder().getAll()); + + TelephonyLookup file2ThenFile1 = + TelephonyLookup.createInstanceWithFallback(validFile2, validFile1); + assertEquals(list(expectedTelephonyNetwork2), + file2ThenFile1.getTelephonyNetworkFinder().getAll()); + + // We assume the file has been validated so an invalid file is not checked ahead of time. + // We will find out when we look something up. + TelephonyLookup invalidThenValid = + TelephonyLookup.createInstanceWithFallback(invalidFile, validFile1); + assertNull(invalidThenValid.getTelephonyNetworkFinder()); + + // This is not a normal case: It would imply a device shipped without a file anywhere! + TelephonyLookup missingFiles = + TelephonyLookup.createInstanceWithFallback(missingFile, missingFile); + assertEmpty(missingFiles.getTelephonyNetworkFinder().getAll()); + } + + @Test + public void xmlParsing_emptyFile() throws Exception { + checkValidateThrowsParserException(""); + } + + @Test + public void xmlParsing_unexpectedRootElement() throws Exception { + checkValidateThrowsParserException("<foo></foo>\n"); + } + + @Test + public void xmlParsing_missingNetworks() throws Exception { + checkValidateThrowsParserException("<telephony_lookup></telephony_lookup>\n"); + } + + @Test + public void xmlParsing_emptyNetworksOk() throws Exception { + { + TelephonyLookup telephonyLookup = + validate("<telephony_lookup>\n" + + " <networks>\n" + + " </networks>\n" + + "</telephony_lookup>\n"); + TelephonyNetworkFinder telephonyNetworkFinder = telephonyLookup + .getTelephonyNetworkFinder(); + assertEquals(list(), telephonyNetworkFinder.getAll()); + } + { + TelephonyLookup telephonyLookup = + validate("<telephony_lookup>\n" + + " <networks/>\n" + + "</telephony_lookup>\n"); + TelephonyNetworkFinder telephonyNetworkFinder = telephonyLookup + .getTelephonyNetworkFinder(); + assertEquals(list(), telephonyNetworkFinder.getAll()); + } + } + + @Test + public void xmlParsing_unexpectedComments() throws Exception { + TelephonyNetwork expectedTelephonyNetwork = + TelephonyNetwork.create("123", "456", "gb"); + + TelephonyLookup telephonyLookup = validate("<telephony_lookup>\n" + + " <networks>\n" + + " <!-- This is a comment -->" + + " <network mcc=\"123\" mnc=\"456\" country=\"gb\"/>\n" + + " </networks>\n" + + "</telephony_lookup>\n"); + assertEquals(list(expectedTelephonyNetwork), telephonyLookup.getTelephonyNetworkFinder().getAll()); + } + + @Test + public void xmlParsing_unexpectedElementsIgnored() throws Exception { + TelephonyNetwork expectedTelephonyNetwork = + TelephonyNetwork.create("123", "456", "gb"); + List<TelephonyNetwork> expectedNetworks = list(expectedTelephonyNetwork); + + String unexpectedElement = "<unexpected-element>\n<a /></unexpected-element>\n"; + + // These tests are important because they ensure we can extend the format in future with + // more information but could continue using the same file on older devices. + TelephonyLookup telephonyLookup = validate("<telephony_lookup>\n" + + " " + unexpectedElement + + " <networks>\n" + + " " + unexpectedElement + + " <network mcc=\"123\" mnc=\"456\" country=\"gb\"/>\n" + + " " + unexpectedElement + + " </networks>\n" + + " " + unexpectedElement + + "</telephony_lookup>\n"); + assertEquals(expectedNetworks, telephonyLookup.getTelephonyNetworkFinder().getAll()); + + telephonyLookup = validate("<telephony_lookup>\n" + + " <networks>\n" + + " <network mcc=\"123\" mnc=\"456\" country=\"gb\">\n" + + " " + unexpectedElement + + " </network>\n" + + " </networks>\n" + + "</telephony_lookup>\n"); + assertEquals(expectedNetworks, telephonyLookup.getTelephonyNetworkFinder().getAll()); + + expectedNetworks = list(expectedTelephonyNetwork, + TelephonyNetwork.create("234", "567", "fr")); + telephonyLookup = validate("<telephony_lookup>\n" + + " <networks>\n" + + " <network mcc=\"123\" mnc=\"456\" country=\"gb\"/>\n" + + " " + unexpectedElement + + " <network mcc=\"234\" mnc=\"567\" country=\"fr\"/>\n" + + " </networks>\n" + + "</telephony_lookup>\n"); + assertEquals(expectedNetworks, telephonyLookup.getTelephonyNetworkFinder().getAll()); + } + + @Test + public void xmlParsing_unexpectedTextIgnored() throws Exception { + TelephonyNetwork expectedTelephonyNetwork = + TelephonyNetwork.create("123", "456", "gb"); + List<TelephonyNetwork> expectedNetworks = list(expectedTelephonyNetwork); + + String unexpectedText = "unexpected-text"; + TelephonyLookup telephonyLookup = validate("<telephony_lookup>\n" + + " " + unexpectedText + + " <networks>\n" + + " " + unexpectedText + + " <network mcc=\"123\" mnc=\"456\" country=\"gb\"/>\n" + + " " + unexpectedText + + " </networks>\n" + + " " + unexpectedText + + "</telephony_lookup>\n"); + assertEquals(expectedNetworks, telephonyLookup.getTelephonyNetworkFinder().getAll()); + + telephonyLookup = validate("<telephony_lookup>\n" + + " <networks>\n" + + " <network mcc=\"123\" mnc=\"456\" country=\"gb\">\n" + + " " + unexpectedText + + " </network>\n" + + " </networks>\n" + + "</telephony_lookup>\n"); + assertEquals(expectedNetworks, telephonyLookup.getTelephonyNetworkFinder().getAll()); + } + + @Test + public void xmlParsing_truncatedInput() throws Exception { + checkValidateThrowsParserException("<telephony_lookup>\n"); + + checkValidateThrowsParserException("<telephony_lookup>\n" + + " <networks>\n"); + + checkValidateThrowsParserException("<telephony_lookup>\n" + + " <networks>\n" + + " <network mcc=\"123\" mnc=\"456\" country=\"gb\"/>\n"); + + checkValidateThrowsParserException("<telephony_lookup>\n" + + " <networks>\n" + + " <network mcc=\"123\" mnc=\"456\" country=\"gb\"/>\n" + + " </networks>\n"); + } + + @Test + public void validateDuplicateMccMnc() { + checkValidateThrowsParserException("<telephony_lookup>\n" + + " <networks>\n" + + " <network mcc=\"123\" mnc=\"456\" countryCode=\"gb\"/>\n" + + " <network mcc=\"123\" mnc=\"456\" countryCode=\"fr\"/>\n" + + " </networks>\n" + + "</telephony_lookup>\n"); + } + + @Test + public void validateCountryCodeLowerCase() { + checkValidateThrowsParserException("<telephony_lookup>\n" + + " <networks>\n" + + " <network mcc=\"123\" mnc=\"456\" countryCode=\"GB\"/>\n" + + " </networks>\n" + + "</telephony_lookup>\n"); + } + + + @Test + public void getTelephonyNetworkFinder() throws Exception { + TelephonyLookup telephonyLookup = TelephonyLookup.createInstanceForTests( + "<telephony_lookup>\n" + + " <networks>\n" + + " <network mcc=\"123\" mnc=\"456\" country=\"gb\"/>\n" + + " <network mcc=\"234\" mnc=\"567\" country=\"fr\"/>\n" + + " </networks>\n" + + "</telephony_lookup>\n"); + + TelephonyNetworkFinder telephonyNetworkFinder = telephonyLookup.getTelephonyNetworkFinder(); + TelephonyNetwork expectedNetwork1 = TelephonyNetwork.create("123", "456", "gb"); + TelephonyNetwork expectedNetwork2 = TelephonyNetwork.create("234", "567", "fr"); + assertEquals(list(expectedNetwork1, expectedNetwork2), telephonyNetworkFinder.getAll()); + assertEquals(expectedNetwork1, telephonyNetworkFinder.findNetworkByMccMnc("123", "456")); + assertEquals(expectedNetwork2, telephonyNetworkFinder.findNetworkByMccMnc("234", "567")); + assertNull(telephonyNetworkFinder.findNetworkByMccMnc("999", "999")); + } + + @Test + public void xmlParsing_missingMccAttribute() throws Exception { + checkValidateThrowsParserException("<telephony_lookup>\n" + + " <networks>\n" + + " <network mnc=\"456\" country=\"gb\"/>\n" + + " </networks>\n" + + "</telephony_lookup>\n"); + } + + @Test + public void xmlParsing_missingMncAttribute() throws Exception { + TelephonyLookup telephonyLookup = TelephonyLookup.createInstanceForTests( + "<telephony_lookup>\n" + + " <networks>\n" + + " <network mcc=\"123\" country=\"gb\"/>\n" + + " </networks>\n" + + "</telephony_lookup>\n"); + assertNull(telephonyLookup.getTelephonyNetworkFinder()); + } + + @Test + public void xmlParsing_missingCountryCodeAttribute() throws Exception { + TelephonyLookup telephonyLookup = TelephonyLookup.createInstanceForTests( + "<telephony_lookup>\n" + + " <networks>\n" + + " <network mcc=\"123\" mnc=\"456\"/>\n" + + " </networks>\n" + + "</telephony_lookup>\n"); + assertNull(telephonyLookup.getTelephonyNetworkFinder()); + } + + private static void checkValidateThrowsParserException(String xml) { + try { + validate(xml); + fail(); + } catch (IOException expected) { + } + } + + private static TelephonyLookup validate(String xml) throws IOException { + TelephonyLookup telephonyLookup = TelephonyLookup.createInstanceForTests(xml); + telephonyLookup.validate(); + return telephonyLookup; + } + + private static void assertEmpty(Collection<?> collection) { + assertTrue("Expected empty:" + collection, collection.isEmpty()); + } + + private static <X> List<X> list(X... values) { + return Arrays.asList(values); + } + + private String createFile(String fileContent) throws IOException { + Path filePath = Files.createTempFile(testDir, null, null); + Files.write(filePath, fileContent.getBytes(StandardCharsets.UTF_8)); + return filePath.toString(); + } + + private String createMissingFile() throws IOException { + Path filePath = Files.createTempFile(testDir, null, null); + Files.delete(filePath); + return filePath.toString(); + } +} diff --git a/luni/src/test/java/libcore/libcore/timezone/TelephonyNetworkFinderTest.java b/luni/src/test/java/libcore/libcore/timezone/TelephonyNetworkFinderTest.java new file mode 100644 index 0000000000..44dfc8178c --- /dev/null +++ b/luni/src/test/java/libcore/libcore/timezone/TelephonyNetworkFinderTest.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package libcore.libcore.timezone; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import libcore.timezone.TelephonyNetwork; +import libcore.timezone.TelephonyNetworkFinder; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +public class TelephonyNetworkFinderTest { + + @Test + public void testCreateAndLookups() { + TelephonyNetwork network = TelephonyNetwork.create("123", "456", "gb"); + List<TelephonyNetwork> networkList = list(network); + TelephonyNetworkFinder finder = TelephonyNetworkFinder.create(networkList); + assertEquals(network, finder.findNetworkByMccMnc("123", "456")); + assertNull(finder.findNetworkByMccMnc("XXX", "XXX")); + assertNull(finder.findNetworkByMccMnc("123", "XXX")); + assertNull(finder.findNetworkByMccMnc("456", "123")); + assertNull(finder.findNetworkByMccMnc("111", "222")); + assertEquals(networkList, finder.getAll()); + } + + private static <X> List<X> list(X... values) { + return Arrays.asList(values); + } +} diff --git a/luni/src/test/java/libcore/libcore/timezone/TimeZoneDataFilesTest.java b/luni/src/test/java/libcore/libcore/timezone/TimeZoneDataFilesTest.java index e94b96e5f4..a74ba3047f 100644 --- a/luni/src/test/java/libcore/libcore/timezone/TimeZoneDataFilesTest.java +++ b/luni/src/test/java/libcore/libcore/timezone/TimeZoneDataFilesTest.java @@ -27,31 +27,28 @@ import static org.junit.Assert.assertTrue; public class TimeZoneDataFilesTest { private static final String ANDROID_TZDATA_ROOT_ENV = "ANDROID_TZDATA_ROOT"; - private static final String ANDROID_RUNTIME_ROOT_ENV = "ANDROID_RUNTIME_ROOT"; + private static final String ANDROID_I18N_ROOT_ENV = "ANDROID_I18N_ROOT"; + private static final String ANDROID_DATA_ENV = "ANDROID_DATA"; @Test public void expectedEnvironmentVariables() { // These environment variables are required to locate data files used by libcore / ICU. + assertNotNull(System.getenv(ANDROID_DATA_ENV)); assertNotNull(System.getenv(ANDROID_TZDATA_ROOT_ENV)); - assertNotNull(System.getenv(ANDROID_RUNTIME_ROOT_ENV)); + assertNotNull(System.getenv(ANDROID_I18N_ROOT_ENV)); } @Test public void getTimeZoneFilePaths() { String[] paths = TimeZoneDataFiles.getTimeZoneFilePaths("foo"); - assertEquals(4, paths.length); + assertEquals(2, paths.length); + assertTrue(paths[0].startsWith(System.getenv(ANDROID_DATA_ENV))); assertTrue(paths[0].contains("/misc/zoneinfo/current/")); assertTrue(paths[0].endsWith("/foo")); assertTrue(paths[1].startsWith(System.getenv(ANDROID_TZDATA_ROOT_ENV))); assertTrue(paths[1].endsWith("/foo")); - - assertTrue(paths[2].startsWith(System.getenv(ANDROID_RUNTIME_ROOT_ENV))); - assertTrue(paths[2].endsWith("/foo")); - - assertTrue(paths[3].contains("/usr/share/zoneinfo/")); - assertTrue(paths[3].endsWith("/foo")); } // http://b/34867424 @@ -64,6 +61,7 @@ public class TimeZoneDataFilesTest { assertEquals(3, paths.length); String dataDirPath = paths[0]; + assertTrue(dataDirPath.startsWith(System.getenv(ANDROID_DATA_ENV))); assertTrue(dataDirPath + " invalid", dataDirPath.contains("/misc/zoneinfo/current/icu")); String tzdataModulePath = paths[1]; @@ -72,7 +70,7 @@ public class TimeZoneDataFilesTest { String runtimeModulePath = paths[2]; assertTrue(runtimeModulePath + " invalid", - runtimeModulePath.startsWith(System.getenv(ANDROID_RUNTIME_ROOT_ENV))); + runtimeModulePath.startsWith(System.getenv(ANDROID_I18N_ROOT_ENV))); assertTrue(runtimeModulePath + " invalid", runtimeModulePath.contains("/etc/icu")); } } diff --git a/luni/src/test/java/libcore/libcore/timezone/TimeZoneFinderTest.java b/luni/src/test/java/libcore/libcore/timezone/TimeZoneFinderTest.java index 8bfacd81eb..ef0737142e 100644 --- a/luni/src/test/java/libcore/libcore/timezone/TimeZoneFinderTest.java +++ b/luni/src/test/java/libcore/libcore/timezone/TimeZoneFinderTest.java @@ -20,8 +20,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import android.icu.util.TimeZone; - import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.FileVisitResult; @@ -30,7 +28,6 @@ import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; -import java.util.Collection; import java.util.List; import java.util.stream.Collectors; import libcore.timezone.CountryTimeZones; @@ -39,35 +36,13 @@ import libcore.timezone.CountryZonesFinder; import libcore.timezone.TimeZoneFinder; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class TimeZoneFinderTest { - private static final int HOUR_MILLIS = 60 * 60 * 1000; - - // Zones used in the tests. NEW_YORK_TZ and LONDON_TZ chosen because they never overlap but both - // have DST. - private static final TimeZone NEW_YORK_TZ = TimeZone.getTimeZone("America/New_York"); - private static final TimeZone LONDON_TZ = TimeZone.getTimeZone("Europe/London"); - // A zone that matches LONDON_TZ for WHEN_NO_DST. It does not have DST so differs for WHEN_DST. - private static final TimeZone REYKJAVIK_TZ = TimeZone.getTimeZone("Atlantic/Reykjavik"); - // Another zone that matches LONDON_TZ for WHEN_NO_DST. It does not have DST so differs for - // WHEN_DST. - private static final TimeZone UTC_TZ = TimeZone.getTimeZone("Etc/UTC"); - - // 22nd July 2017, 13:14:15 UTC (DST time in all the timezones used in these tests that observe - // DST). - private static final long WHEN_DST = 1500729255000L; - // 22nd January 2018, 13:14:15 UTC (non-DST time in all timezones used in these tests). - private static final long WHEN_NO_DST = 1516626855000L; - - private static final int LONDON_DST_OFFSET_MILLIS = HOUR_MILLIS; - private static final int LONDON_NO_DST_OFFSET_MILLIS = 0; - - private static final int NEW_YORK_DST_OFFSET_MILLIS = -4 * HOUR_MILLIS; - private static final int NEW_YORK_NO_DST_OFFSET_MILLIS = -5 * HOUR_MILLIS; - private Path testDir; @Before @@ -105,8 +80,8 @@ public class TimeZoneFinderTest { + " </countryzones>\n" + "</timezones>\n"; CountryTimeZones expectedCountryTimeZones1 = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* everUsesUtc */, timeZoneMappings("Europe/London"), - "test"); + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings("Europe/London"), "test"); String validXml2 = "<timezones ianaversion=\"2017b\">\n" + " <countryzones>\n" @@ -116,8 +91,8 @@ public class TimeZoneFinderTest { + " </countryzones>\n" + "</timezones>\n"; CountryTimeZones expectedCountryTimeZones2 = CountryTimeZones.createValidated( - "gb", "Europe/Paris", false /* everUsesUtc */, timeZoneMappings("Europe/Paris"), - "test"); + "gb", "Europe/Paris", false /* defaultTimeZoneBoost */, false /* everUsesUtc */, + timeZoneMappings("Europe/Paris"), "test"); String invalidXml = "<foo></foo>\n"; checkValidateThrowsParserException(invalidXml); @@ -149,7 +124,7 @@ public class TimeZoneFinderTest { assertNull(invalidThenValid.getIanaVersion()); assertNull(invalidThenValid.lookupCountryTimeZones("gb")); - // This is not a normal case: It would imply a define shipped without a file in /system! + // This is not a normal case: It would imply a device shipped without a file anywhere! TimeZoneFinder missingFiles = TimeZoneFinder.createInstanceWithFallback(missingFile, missingFile); assertNull(missingFiles.getIanaVersion()); @@ -182,8 +157,8 @@ public class TimeZoneFinderTest { @Test public void xmlParsing_unexpectedComments() throws Exception { CountryTimeZones expectedCountryTimeZones = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* everUsesUtc */, timeZoneMappings("Europe/London"), - "test"); + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings("Europe/London"), "test"); TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" + " <countryzones>\n" @@ -210,8 +185,8 @@ public class TimeZoneFinderTest { @Test public void xmlParsing_unexpectedElementsIgnored() throws Exception { CountryTimeZones expectedCountryTimeZones = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* everUsesUtc */, timeZoneMappings("Europe/London"), - "test"); + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings("Europe/London"), "test"); String unexpectedElement = "<unexpected-element>\n<a /></unexpected-element>\n"; TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" @@ -267,7 +242,7 @@ public class TimeZoneFinderTest { assertEquals(expectedCountryTimeZones, finder.lookupCountryTimeZones("gb")); expectedCountryTimeZones = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* everUsesUtc */, + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, timeZoneMappings("Europe/London", "Europe/Paris"), "test"); finder = validate("<timezones ianaversion=\"2017b\">\n" + " <countryzones>\n" @@ -284,8 +259,8 @@ public class TimeZoneFinderTest { @Test public void xmlParsing_unexpectedTextIgnored() throws Exception { CountryTimeZones expectedCountryTimeZones = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* everUsesUtc */, timeZoneMappings("Europe/London"), - "test"); + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings("Europe/London"), "test"); String unexpectedText = "unexpected-text"; TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" @@ -319,7 +294,7 @@ public class TimeZoneFinderTest { assertEquals(expectedCountryTimeZones, finder.lookupCountryTimeZones("gb")); expectedCountryTimeZones = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* everUsesUtc */, + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, timeZoneMappings("Europe/London", "Europe/Paris"), "test"); finder = validate("<timezones ianaversion=\"2017b\">\n" + " <countryzones>\n" @@ -377,8 +352,8 @@ public class TimeZoneFinderTest { @Test public void xmlParsing_unknownTimeZoneIdIgnored() throws Exception { CountryTimeZones expectedCountryTimeZones = CountryTimeZones.createValidated( - "gb", "Europe/London", true /* everUsesUtc */, timeZoneMappings("Europe/London"), - "test"); + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings("Europe/London"), "test"); TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" + " <countryzones>\n" + " <country code=\"gb\" default=\"Europe/London\" everutc=\"y\">\n" @@ -435,6 +410,32 @@ public class TimeZoneFinderTest { } @Test + public void xmlParsing_badCountryDefaultBoost() throws Exception { + checkValidateThrowsParserException("<timezones ianaversion=\"2017b\">\n" + + " <countryzones>\n" + + " <country code=\"gb\" default=\"Europe/London\" defaultBoost=\"nope\"" + + "everutc=\"y\">\n" + + " <id>Europe/London</id>\n" + + " </country>\n" + + " </countryzones>\n" + + "</timezones>\n"); + } + + @Test + public void xmlParsing_countryDefaultBoost() throws Exception { + TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" + + " <countryzones>\n" + + " <country code=\"gb\" default=\"Europe/London\" defaultBoost=\"y\"" + + "everutc=\"y\">\n" + + " <id>Europe/London</id>\n" + + " </country>\n" + + " </countryzones>\n" + + "</timezones>\n"); + CountryTimeZones countryTimeZones = finder.lookupCountryTimeZones("gb"); + assertTrue(countryTimeZones.isDefaultTimeZoneBoosted()); + } + + @Test public void xmlParsing_badTimeZoneMappingPicker() throws Exception { checkValidateThrowsParserException("<timezones ianaversion=\"2017b\">\n" + " <countryzones>\n" @@ -509,16 +510,6 @@ public class TimeZoneFinderTest { } @Test - public void xmlParsing_unknownCountryReturnsNull() throws Exception { - TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" - + " <countryzones>\n" - + " </countryzones>\n" - + "</timezones>\n"); - assertNull(finder.lookupTimeZoneIdsByCountry("gb")); - assertNull(finder.lookupTimeZonesByCountry("gb")); - } - - @Test public void getCountryZonesFinder() throws Exception { TimeZoneFinder timeZoneFinder = TimeZoneFinder.createInstanceForTests( "<timezones ianaversion=\"2017b\">\n" @@ -531,10 +522,10 @@ public class TimeZoneFinderTest { + " </country>\n" + " </countryzones>\n" + "</timezones>\n"); - CountryTimeZones expectedGb = CountryTimeZones.createValidated("gb", "Europe/London", true, - timeZoneMappings("Europe/London"), "test"); - CountryTimeZones expectedFr = CountryTimeZones.createValidated("fr", "Europe/Paris", true, - timeZoneMappings("Europe/Paris"), "test"); + CountryTimeZones expectedGb = CountryTimeZones.createValidated("gb", "Europe/London", + false /* defaultTimeZoneBoost */, true, timeZoneMappings("Europe/London"), "test"); + CountryTimeZones expectedFr = CountryTimeZones.createValidated("fr", "Europe/Paris", + false /* defaultTimeZoneBoost */, true, timeZoneMappings("Europe/Paris"), "test"); CountryZonesFinder countryZonesFinder = timeZoneFinder.getCountryZonesFinder(); assertEquals(list("gb", "fr"), countryZonesFinder.lookupAllCountryIsoCodes()); assertEquals(expectedGb, countryZonesFinder.lookupCountryTimeZones("gb")); @@ -571,7 +562,7 @@ public class TimeZoneFinderTest { } @Test - public void lookupTimeZonesByCountry_structuresAreImmutable() throws Exception { + public void lookupCountryTimeZones_caseInsensitive() throws Exception { TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" + " <countryzones>\n" + " <country code=\"gb\" default=\"Europe/London\" everutc=\"y\">\n" @@ -579,323 +570,22 @@ public class TimeZoneFinderTest { + " </country>\n" + " </countryzones>\n" + "</timezones>\n"); + CountryTimeZones expectedCountryTimeZones = CountryTimeZones.createValidated( + "gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */, + timeZoneMappings("Europe/London"), "test"); - List<TimeZone> gbList = finder.lookupTimeZonesByCountry("gb"); - assertEquals(1, gbList.size()); - assertImmutableList(gbList); - assertImmutableTimeZone(gbList.get(0)); - - // Check country code normalization works too. - assertEquals(1, finder.lookupTimeZonesByCountry("GB").size()); - - assertNull(finder.lookupTimeZonesByCountry("unknown")); - } - - @Test - public void lookupTimeZoneIdsByCountry_structuresAreImmutable() throws Exception { - TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" - + " <countryzones>\n" - + " <country code=\"gb\" default=\"Europe/London\" everutc=\"y\">\n" - + " <id>Europe/London</id>\n" - + " </country>\n" - + " </countryzones>\n" - + "</timezones>\n"); - - List<String> gbList = finder.lookupTimeZoneIdsByCountry("gb"); - assertEquals(1, gbList.size()); - assertImmutableList(gbList); - - // Check country code normalization works too. - assertEquals(1, finder.lookupTimeZoneIdsByCountry("GB").size()); - - assertNull(finder.lookupTimeZoneIdsByCountry("unknown")); - } - - @Test - public void lookupDefaultTimeZoneIdByCountry() throws Exception { - TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" - + " <countryzones>\n" - + " <country code=\"gb\" default=\"Europe/London\" everutc=\"y\">\n" - + " <id>Europe/London</id>\n" - + " </country>\n" - + " </countryzones>\n" - + "</timezones>\n"); - - assertEquals("Europe/London", finder.lookupDefaultTimeZoneIdByCountry("gb")); - - // Check country code normalization works too. - assertEquals("Europe/London", finder.lookupDefaultTimeZoneIdByCountry("GB")); - } - - /** - * At runtime we don't validate too much since there's nothing we can do if the data is - * incorrect. - */ - @Test - public void lookupDefaultTimeZoneIdByCountry_notCountryTimeZoneButValid() throws Exception { - String xml = "<timezones ianaversion=\"2017b\">\n" - + " <countryzones>\n" - + " <country code=\"gb\" default=\"America/New_York\" everutc=\"y\">\n" - + " <id>Europe/London</id>\n" - + " </country>\n" - + " </countryzones>\n" - + "</timezones>\n"; - // validate() should fail because America/New_York is not one of the "gb" zones listed. - checkValidateThrowsParserException(xml); - - // But it should still work at runtime. - TimeZoneFinder finder = TimeZoneFinder.createInstanceForTests(xml); - assertEquals("America/New_York", finder.lookupDefaultTimeZoneIdByCountry("gb")); - } - - @Test - public void lookupDefaultTimeZoneIdByCountry_invalidDefault() throws Exception { - String xml = "<timezones ianaversion=\"2017b\">\n" - + " <countryzones>\n" - + " <country code=\"gb\" default=\"Moon/Tranquility_Base\" everutc=\"y\">\n" - + " <id>Europe/London</id>\n" - + " <id>Moon/Tranquility_Base</id>\n" - + " </country>\n" - + " </countryzones>\n" - + "</timezones>\n"; - // validate() should pass because the IDs all match. - TimeZoneFinder finder = validate(xml); - - // But "Moon/Tranquility_Base" is not a valid time zone ID so should not be used. - assertNull(finder.lookupDefaultTimeZoneIdByCountry("gb")); - } - - @Test - public void lookupTimeZoneByCountryAndOffset_unknownCountry() throws Exception { - TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" - + " <countryzones>\n" - + " <country code=\"xx\" default=\"Europe/London\" everutc=\"y\">\n" - + " <id>Europe/London</id>\n" - + " </country>\n" - + " </countryzones>\n" - + "</timezones>\n"); - - // Demonstrate the arguments work for a known country. - assertZoneEquals(LONDON_TZ, - finder.lookupTimeZoneByCountryAndOffset("xx", LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_DST, null /* bias */)); - - // Check country code normalization works too. - assertZoneEquals(LONDON_TZ, - finder.lookupTimeZoneByCountryAndOffset("XX", LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_DST, null /* bias */)); - - // Test with an unknown country. - String unknownCountryCode = "yy"; - assertNull(finder.lookupTimeZoneByCountryAndOffset(unknownCountryCode, - LONDON_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, null /* bias */)); - - assertNull(finder.lookupTimeZoneByCountryAndOffset(unknownCountryCode, - LONDON_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, LONDON_TZ /* bias */)); - } - - @Test - public void lookupTimeZoneByCountryAndOffset_oneCandidate() throws Exception { - TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" - + " <countryzones>\n" - + " <country code=\"xx\" default=\"Europe/London\" everutc=\"y\">\n" - + " <id>Europe/London</id>\n" - + " </country>\n" - + " </countryzones>\n" - + "</timezones>\n"); - - // The three parameters match the configured zone: offset, isDst and when. - assertZoneEquals(LONDON_TZ, - finder.lookupTimeZoneByCountryAndOffset("xx", LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_DST, null /* bias */)); - assertZoneEquals(LONDON_TZ, - finder.lookupTimeZoneByCountryAndOffset("xx", LONDON_NO_DST_OFFSET_MILLIS, - false /* isDst */, WHEN_NO_DST, null /* bias */)); - - // Some lookup failure cases where the offset, isDst and when do not match the configured - // zone. - TimeZone noDstMatch1 = finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_DST_OFFSET_MILLIS, true /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch1); - - TimeZone noDstMatch2 = finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_DST_OFFSET_MILLIS, false /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch2); - - TimeZone noDstMatch3 = finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_NO_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch3); - - TimeZone noDstMatch4 = finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_NO_DST_OFFSET_MILLIS, true /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch4); - - TimeZone noDstMatch5 = finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_DST_OFFSET_MILLIS, false /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch5); - - TimeZone noDstMatch6 = finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_NO_DST_OFFSET_MILLIS, false /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch6); - - // Some bias cases below. - - // The bias is irrelevant here: it matches what would be returned anyway. - assertZoneEquals(LONDON_TZ, - finder.lookupTimeZoneByCountryAndOffset("xx", LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_DST, LONDON_TZ /* bias */)); - assertZoneEquals(LONDON_TZ, - finder.lookupTimeZoneByCountryAndOffset("xx", LONDON_NO_DST_OFFSET_MILLIS, - false /* isDst */, WHEN_NO_DST, LONDON_TZ /* bias */)); - // A sample of a non-matching case with bias. - assertNull(finder.lookupTimeZoneByCountryAndOffset("xx", LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_NO_DST, LONDON_TZ /* bias */)); - - // The bias should be ignored: it doesn't match any of the country's zones. - assertZoneEquals(LONDON_TZ, - finder.lookupTimeZoneByCountryAndOffset("xx", LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_DST, NEW_YORK_TZ /* bias */)); - - // The bias should still be ignored even though it matches the offset information given: - // it doesn't match any of the country's configured zones. - assertNull(finder.lookupTimeZoneByCountryAndOffset("xx", NEW_YORK_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_DST, NEW_YORK_TZ /* bias */)); - } - - @Test - public void lookupTimeZoneByCountryAndOffset_multipleNonOverlappingCandidates() - throws Exception { - TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" - + " <countryzones>\n" - + " <country code=\"xx\" default=\"Europe/London\" everutc=\"y\">\n" - + " <id>America/New_York</id>\n" - + " <id>Europe/London</id>\n" - + " </country>\n" - + " </countryzones>\n" - + "</timezones>\n"); - - // The three parameters match the configured zone: offset, isDst and when. - assertZoneEquals(LONDON_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, null /* bias */)); - assertZoneEquals(LONDON_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_NO_DST_OFFSET_MILLIS, false /* isDst */, WHEN_NO_DST, null /* bias */)); - assertZoneEquals(NEW_YORK_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", - NEW_YORK_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, null /* bias */)); - assertZoneEquals(NEW_YORK_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", - NEW_YORK_NO_DST_OFFSET_MILLIS, false /* isDst */, WHEN_NO_DST, null /* bias */)); - - // Some lookup failure cases where the offset, isDst and when do not match the configured - // zone. This is a sample, not complete. - TimeZone noDstMatch1 = finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_DST_OFFSET_MILLIS, true /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch1); - - TimeZone noDstMatch2 = finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_DST_OFFSET_MILLIS, false /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch2); - - TimeZone noDstMatch3 = finder.lookupTimeZoneByCountryAndOffset("xx", - NEW_YORK_NO_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch3); - - TimeZone noDstMatch4 = finder.lookupTimeZoneByCountryAndOffset("xx", - NEW_YORK_NO_DST_OFFSET_MILLIS, true /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch4); - - TimeZone noDstMatch5 = finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_DST_OFFSET_MILLIS, false /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch5); - - TimeZone noDstMatch6 = finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_NO_DST_OFFSET_MILLIS, false /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch6); - - // Some bias cases below. - - // The bias is irrelevant here: it matches what would be returned anyway. - assertZoneEquals(LONDON_TZ, - finder.lookupTimeZoneByCountryAndOffset("xx", LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_DST, LONDON_TZ /* bias */)); - assertZoneEquals(LONDON_TZ, - finder.lookupTimeZoneByCountryAndOffset("xx", LONDON_NO_DST_OFFSET_MILLIS, - false /* isDst */, WHEN_NO_DST, LONDON_TZ /* bias */)); - // A sample of a non-matching case with bias. - assertNull(finder.lookupTimeZoneByCountryAndOffset("xx", LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_NO_DST, LONDON_TZ /* bias */)); - - // The bias should be ignored: it matches a configured zone, but the offset is wrong so - // should not be considered a match. - assertZoneEquals(LONDON_TZ, - finder.lookupTimeZoneByCountryAndOffset("xx", LONDON_DST_OFFSET_MILLIS, - true /* isDst */, WHEN_DST, NEW_YORK_TZ /* bias */)); + assertEquals(expectedCountryTimeZones, finder.lookupCountryTimeZones("gb")); + assertEquals(expectedCountryTimeZones, finder.lookupCountryTimeZones("GB")); + assertEquals(expectedCountryTimeZones, finder.lookupCountryTimeZones("Gb")); } - // This is an artificial case very similar to America/Denver and America/Phoenix in the US: both - // have the same offset for 6 months of the year but diverge. Australia/Lord_Howe too. @Test - public void lookupTimeZoneByCountryAndOffset_multipleOverlappingCandidates() throws Exception { - // Three zones that have the same offset for some of the year. Europe/London changes - // offset WHEN_DST, the others do not. + public void lookupCountryTimeZones_unknownCountryReturnsNull() throws Exception { TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n" + " <countryzones>\n" - + " <country code=\"xx\" default=\"Europe/London\" everutc=\"y\">\n" - + " <id>Atlantic/Reykjavik</id>\n" - + " <id>Europe/London</id>\n" - + " <id>Etc/UTC</id>\n" - + " </country>\n" + " </countryzones>\n" + "</timezones>\n"); - - // This is the no-DST offset for LONDON_TZ, REYKJAVIK_TZ. UTC_TZ. - final int noDstOffset = LONDON_NO_DST_OFFSET_MILLIS; - // This is the DST offset for LONDON_TZ. - final int dstOffset = LONDON_DST_OFFSET_MILLIS; - - // The three parameters match the configured zone: offset, isDst and when. - assertZoneEquals(LONDON_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", dstOffset, - true /* isDst */, WHEN_DST, null /* bias */)); - assertZoneEquals(REYKJAVIK_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", noDstOffset, - false /* isDst */, WHEN_NO_DST, null /* bias */)); - assertZoneEquals(LONDON_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", dstOffset, - true /* isDst */, WHEN_DST, null /* bias */)); - assertZoneEquals(REYKJAVIK_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", noDstOffset, - false /* isDst */, WHEN_NO_DST, null /* bias */)); - assertZoneEquals(REYKJAVIK_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", noDstOffset, - false /* isDst */, WHEN_DST, null /* bias */)); - - // Some lookup failure cases where the offset, isDst and when do not match the configured - // zones. - TimeZone noDstMatch1 = finder.lookupTimeZoneByCountryAndOffset("xx", dstOffset, - true /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch1); - - TimeZone noDstMatch2 = finder.lookupTimeZoneByCountryAndOffset("xx", noDstOffset, - true /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch2); - - TimeZone noDstMatch3 = finder.lookupTimeZoneByCountryAndOffset("xx", noDstOffset, - true /* isDst */, WHEN_NO_DST, null /* bias */); - assertNull(noDstMatch3); - - TimeZone noDstMatch4 = finder.lookupTimeZoneByCountryAndOffset("xx", dstOffset, - false /* isDst */, WHEN_DST, null /* bias */); - assertNull(noDstMatch4); - - - // Some bias cases below. - - // The bias is relevant here: it overrides what would be returned naturally. - assertZoneEquals(REYKJAVIK_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", noDstOffset, - false /* isDst */, WHEN_NO_DST, null /* bias */)); - assertZoneEquals(LONDON_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", noDstOffset, - false /* isDst */, WHEN_NO_DST, LONDON_TZ /* bias */)); - assertZoneEquals(UTC_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", noDstOffset, - false /* isDst */, WHEN_NO_DST, UTC_TZ /* bias */)); - - // The bias should be ignored: it matches a configured zone, but the offset is wrong so - // should not be considered a match. - assertZoneEquals(LONDON_TZ, finder.lookupTimeZoneByCountryAndOffset("xx", - LONDON_DST_OFFSET_MILLIS, true /* isDst */, WHEN_DST, REYKJAVIK_TZ /* bias */)); + assertNull(finder.lookupCountryTimeZones("gb")); } @Test @@ -909,9 +599,9 @@ public class TimeZoneFinderTest { + " </country>\n" + " </countryzones>\n" + "</timezones>\n"); - assertEquals(list("Europe/London"), finder.lookupTimeZoneIdsByCountry("gb")); - assertNull(finder.getIanaVersion()); + + assertNotNull(finder.lookupCountryTimeZones("gb")); } @Test @@ -925,27 +615,6 @@ public class TimeZoneFinderTest { assertEquals(expectedIanaVersion, finder.getIanaVersion()); } - private static void assertImmutableTimeZone(TimeZone timeZone) { - try { - timeZone.setRawOffset(1000); - fail(); - } catch (UnsupportedOperationException expected) { - } - } - - private static <X> void assertImmutableList(List<X> list) { - try { - list.add(null); - fail(); - } catch (UnsupportedOperationException expected) { - } - } - - private static void assertZoneEquals(TimeZone expected, TimeZone actual) { - // TimeZone.equals() only checks the ID, but that's ok for these tests. - assertEquals(expected, actual); - } - private static void checkValidateThrowsParserException(String xml) { try { validate(xml); @@ -974,11 +643,6 @@ public class TimeZoneFinderTest { return Arrays.asList(values); } - private static <X> List<X> sort(Collection<X> value) { - return value.stream().sorted() - .collect(Collectors.toList()); - } - private String createFile(String fileContent) throws IOException { Path filePath = Files.createTempFile(testDir, null, null); Files.write(filePath, fileContent.getBytes(StandardCharsets.UTF_8)); diff --git a/luni/src/test/java/libcore/libcore/timezone/TzDataSetVersionTest.java b/luni/src/test/java/libcore/libcore/timezone/TzDataSetVersionTest.java index 75e079bdb4..a653301d73 100644 --- a/luni/src/test/java/libcore/libcore/timezone/TzDataSetVersionTest.java +++ b/luni/src/test/java/libcore/libcore/timezone/TzDataSetVersionTest.java @@ -55,10 +55,10 @@ public class TzDataSetVersionTest extends TestCase { public void testConstructor() throws Exception { TzDataSetVersion distroVersion = new TzDataSetVersion(1, 2, VALID_RULES_VERSION, 3); - assertEquals(1, distroVersion.formatMajorVersion); - assertEquals(2, distroVersion.formatMinorVersion); - assertEquals(VALID_RULES_VERSION, distroVersion.rulesVersion); - assertEquals(3, distroVersion.revision); + assertEquals(1, distroVersion.getFormatMajorVersion()); + assertEquals(2, distroVersion.getFormatMinorVersion()); + assertEquals(VALID_RULES_VERSION, distroVersion.getRulesVersion()); + assertEquals(3, distroVersion.getRevision()); } public void testToFromBytesRoundTrip() throws Exception { diff --git a/luni/src/test/java/libcore/libcore/timezone/ZoneInfoDBTest.java b/luni/src/test/java/libcore/libcore/timezone/ZoneInfoDbTest.java index 3f4791cc3c..48eb28654e 100644 --- a/luni/src/test/java/libcore/libcore/timezone/ZoneInfoDBTest.java +++ b/luni/src/test/java/libcore/libcore/timezone/ZoneInfoDbTest.java @@ -18,28 +18,27 @@ package libcore.libcore.timezone; import java.io.File; import java.io.FileOutputStream; -import java.io.IOException; import java.io.RandomAccessFile; import libcore.timezone.TimeZoneDataFiles; import libcore.timezone.testing.ZoneInfoTestHelper; import libcore.util.ZoneInfo; -import libcore.timezone.ZoneInfoDB; +import libcore.timezone.ZoneInfoDb; -import static libcore.timezone.ZoneInfoDB.TzData.SIZEOF_INDEX_ENTRY; +import static libcore.timezone.ZoneInfoDb.SIZEOF_INDEX_ENTRY; -public class ZoneInfoDBTest extends junit.framework.TestCase { +public class ZoneInfoDbTest extends junit.framework.TestCase { // The base tzdata file, always present on a device. - private static final String SYSTEM_TZDATA_FILE = - TimeZoneDataFiles.getSystemTimeZoneFile(ZoneInfoDB.TZDATA_FILE); + private static final String TZDATA_FILE = + TimeZoneDataFiles.getTimeZoneModuleTzFile(ZoneInfoDb.TZDATA_FILE_NAME); // An empty override file should fall back to the default file. public void testLoadTzDataWithFallback_emptyOverrideFile() throws Exception { String emptyFilePath = makeEmptyFile().getPath(); - try (ZoneInfoDB.TzData data = ZoneInfoDB.TzData.loadTzData(SYSTEM_TZDATA_FILE); - ZoneInfoDB.TzData dataWithEmptyOverride = - ZoneInfoDB.TzData.loadTzDataWithFallback(emptyFilePath, SYSTEM_TZDATA_FILE)) { + try (ZoneInfoDb data = ZoneInfoDb.loadTzData(TZDATA_FILE); + ZoneInfoDb dataWithEmptyOverride = + ZoneInfoDb.loadTzDataWithFallback(emptyFilePath, TZDATA_FILE)) { assertEquals(data.getVersion(), dataWithEmptyOverride.getVersion()); assertEquals(data.getAvailableIDs().length, dataWithEmptyOverride.getAvailableIDs().length); } @@ -48,9 +47,9 @@ public class ZoneInfoDBTest extends junit.framework.TestCase { // A corrupt override file should fall back to the default file. public void testLoadTzDataWithFallback_corruptOverrideFile() throws Exception { String corruptFilePath = makeCorruptFile().getPath(); - try (ZoneInfoDB.TzData data = ZoneInfoDB.TzData.loadTzData(SYSTEM_TZDATA_FILE); - ZoneInfoDB.TzData dataWithCorruptOverride = - ZoneInfoDB.TzData.loadTzDataWithFallback(corruptFilePath, SYSTEM_TZDATA_FILE)) { + try (ZoneInfoDb data = ZoneInfoDb.loadTzData(TZDATA_FILE); + ZoneInfoDb dataWithCorruptOverride = + ZoneInfoDb.loadTzDataWithFallback(corruptFilePath, TZDATA_FILE)) { assertEquals(data.getVersion(), dataWithCorruptOverride.getVersion()); assertEquals(data.getAvailableIDs().length, dataWithCorruptOverride.getAvailableIDs().length); } @@ -59,7 +58,7 @@ public class ZoneInfoDBTest extends junit.framework.TestCase { // Given no tzdata files we can use, we should fall back to built-in "GMT". public void testLoadTzDataWithFallback_noGoodFile() throws Exception { String emptyFilePath = makeEmptyFile().getPath(); - try (ZoneInfoDB.TzData data = ZoneInfoDB.TzData.loadTzDataWithFallback(emptyFilePath)) { + try (ZoneInfoDb data = ZoneInfoDb.loadTzDataWithFallback(emptyFilePath)) { assertEquals("missing", data.getVersion()); assertEquals(1, data.getAvailableIDs().length); assertEquals("GMT", data.getAvailableIDs()[0]); @@ -68,7 +67,7 @@ public class ZoneInfoDBTest extends junit.framework.TestCase { // Given a valid override file, we should find ourselves using that. public void testLoadTzDataWithFallback_goodOverrideFile() throws Exception { - RandomAccessFile in = new RandomAccessFile(SYSTEM_TZDATA_FILE, "r"); + RandomAccessFile in = new RandomAccessFile(TZDATA_FILE, "r"); byte[] content = new byte[(int) in.length()]; in.readFully(content); in.close(); @@ -81,9 +80,9 @@ public class ZoneInfoDBTest extends junit.framework.TestCase { content[10] = 'z'; File goodFile = makeTemporaryFile(content); - try (ZoneInfoDB.TzData dataWithOverride = - ZoneInfoDB.TzData.loadTzDataWithFallback(goodFile.getPath(), SYSTEM_TZDATA_FILE); - ZoneInfoDB.TzData data = ZoneInfoDB.TzData.loadTzData(SYSTEM_TZDATA_FILE)) { + try (ZoneInfoDb dataWithOverride = + ZoneInfoDb.loadTzDataWithFallback(goodFile.getPath(), TZDATA_FILE); + ZoneInfoDb data = ZoneInfoDb.loadTzData(TZDATA_FILE)) { assertEquals("9999z", dataWithOverride.getVersion()); assertEquals(data.getAvailableIDs().length, dataWithOverride.getAvailableIDs().length); @@ -93,7 +92,7 @@ public class ZoneInfoDBTest extends junit.framework.TestCase { } public void testLoadTzData_badHeader() throws Exception { - RandomAccessFile in = new RandomAccessFile(SYSTEM_TZDATA_FILE, "r"); + RandomAccessFile in = new RandomAccessFile(TZDATA_FILE, "r"); byte[] content = new byte[(int) in.length()]; in.readFully(content); in.close(); @@ -107,7 +106,7 @@ public class ZoneInfoDBTest extends junit.framework.TestCase { byte[] data = new ZoneInfoTestHelper.TzDataBuilder().initializeToValid().build(); File testFile = makeTemporaryFile(data); try { - assertNotNull(ZoneInfoDB.TzData.loadTzData(testFile.getPath())); + assertNotNull(ZoneInfoDb.loadTzData(testFile.getPath())); } finally { testFile.delete(); } @@ -150,7 +149,7 @@ public class ZoneInfoDBTest extends junit.framework.TestCase { // Sections must be in the correct order: section sizing is calculated using them. int indexOffset = 10; builder.setIndexOffsetOverride(indexOffset); - int dataOffset = indexOffset + ZoneInfoDB.TzData.SIZEOF_INDEX_ENTRY - 1; + int dataOffset = indexOffset + ZoneInfoDb.SIZEOF_INDEX_ENTRY - 1; builder.setDataOffsetOverride(dataOffset); builder.setZoneTabOffsetOverride(dataOffset + 40); @@ -208,7 +207,7 @@ public class ZoneInfoDBTest extends junit.framework.TestCase { private static void checkInvalidDataDetected(byte[] data) throws Exception { File testFile = makeTemporaryFile(data); try { - assertNull(ZoneInfoDB.TzData.loadTzData(testFile.getPath())); + assertNull(ZoneInfoDb.loadTzData(testFile.getPath())); } finally { testFile.delete(); } @@ -216,7 +215,7 @@ public class ZoneInfoDBTest extends junit.framework.TestCase { // Confirms any caching that exists correctly handles TimeZone mutability. public void testMakeTimeZone_timeZoneMutability() throws Exception { - try (ZoneInfoDB.TzData data = ZoneInfoDB.TzData.loadTzData(SYSTEM_TZDATA_FILE)) { + try (ZoneInfoDb data = ZoneInfoDb.loadTzData(TZDATA_FILE)) { String tzId = "Europe/London"; ZoneInfo first = data.makeTimeZone(tzId); ZoneInfo second = data.makeTimeZone(tzId); @@ -234,14 +233,14 @@ public class ZoneInfoDBTest extends junit.framework.TestCase { } public void testMakeTimeZone_notFound() throws Exception { - try (ZoneInfoDB.TzData data = ZoneInfoDB.TzData.loadTzData(SYSTEM_TZDATA_FILE)) { + try (ZoneInfoDb data = ZoneInfoDb.loadTzData(TZDATA_FILE)) { assertNull(data.makeTimeZone("THIS_TZ_DOES_NOT_EXIST")); assertFalse(data.hasTimeZone("THIS_TZ_DOES_NOT_EXIST")); } } public void testMakeTimeZone_found() throws Exception { - try (ZoneInfoDB.TzData data = ZoneInfoDB.TzData.loadTzData(SYSTEM_TZDATA_FILE)) { + try (ZoneInfoDb data = ZoneInfoDb.loadTzData(TZDATA_FILE)) { assertNotNull(data.makeTimeZone("Europe/London")); assertTrue(data.hasTimeZone("Europe/London")); } diff --git a/luni/src/test/java/libcore/libcore/util/FP16Test.java b/luni/src/test/java/libcore/libcore/util/FP16Test.java new file mode 100644 index 0000000000..916df92e13 --- /dev/null +++ b/luni/src/test/java/libcore/libcore/util/FP16Test.java @@ -0,0 +1,400 @@ +/* + * 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. + */ + +package libcore.libcore.util; + +import static libcore.util.FP16.*; +import libcore.util.FP16; + +import junit.framework.TestCase; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class FP16Test extends TestCase { + + public void testSingleToHalf() { + // Zeroes, NaN and infinities + assertEquals(POSITIVE_ZERO, toHalf(0.0f)); + assertEquals(NEGATIVE_ZERO, toHalf(-0.0f)); + assertEquals(NaN, toHalf(Float.NaN)); + assertEquals(POSITIVE_INFINITY, toHalf(Float.POSITIVE_INFINITY)); + assertEquals(NEGATIVE_INFINITY, toHalf(Float.NEGATIVE_INFINITY)); + // Known values + assertEquals((short) 0x3c01, toHalf(1.0009765625f)); + assertEquals((short) 0xc000, toHalf(-2.0f)); + assertEquals((short) 0x0400, toHalf(6.10352e-5f)); + assertEquals((short) 0x7bff, toHalf(65504.0f)); + assertEquals((short) 0x3555, toHalf(1.0f / 3.0f)); + // Subnormals + assertEquals((short) 0x03ff, toHalf(6.09756e-5f)); + assertEquals(MIN_VALUE, toHalf(5.96046e-8f)); + assertEquals((short) 0x83ff, toHalf(-6.09756e-5f)); + assertEquals((short) 0x8001, toHalf(-5.96046e-8f)); + // Subnormals (flushed to +/-0) + assertEquals(POSITIVE_ZERO, toHalf(5.96046e-9f)); + assertEquals(NEGATIVE_ZERO, toHalf(-5.96046e-9f)); + // Test for values that overflow the mantissa bits into exp bits + assertEquals((short) 0x1000, toHalf(Float.intBitsToFloat(0x39fff000))); + assertEquals((short) 0x0400, toHalf(Float.intBitsToFloat(0x387fe000))); + // Floats with absolute value above +/-65519 are rounded to +/-inf + // when using round-to-even + assertEquals((short) 0x7bff, toHalf(65519.0f)); + assertEquals((short) 0x7bff, toHalf(65519.9f)); + assertEquals(POSITIVE_INFINITY, toHalf(65520.0f)); + assertEquals(NEGATIVE_INFINITY, toHalf(-65520.0f)); + // Check if numbers are rounded to nearest even when they + // cannot be accurately represented by Half + assertEquals((short) 0x6800, toHalf(2049.0f)); + assertEquals((short) 0x6c00, toHalf(4098.0f)); + assertEquals((short) 0x7000, toHalf(8196.0f)); + assertEquals((short) 0x7400, toHalf(16392.0f)); + assertEquals((short) 0x7800, toHalf(32784.0f)); + } + + public void testHalfToSingle() { + // Zeroes, NaN and infinities + assertEquals(0.0f, toFloat(toHalf(0.0f)), 0.0f); + assertEquals(-0.0f, toFloat(toHalf(-0.0f)), 0.0f); + assertEquals(Float.NaN, toFloat(toHalf(Float.NaN)), 0.0f); + assertEquals(Float.POSITIVE_INFINITY, toFloat(toHalf(Float.POSITIVE_INFINITY)), 0.0f); + assertEquals(Float.NEGATIVE_INFINITY, toFloat(toHalf(Float.NEGATIVE_INFINITY)), 0.0f); + // Known values + assertEquals(1.0009765625f, toFloat(toHalf(1.0009765625f)), 0.0f); + assertEquals(-2.0f, toFloat(toHalf(-2.0f)), 0.0f); + assertEquals(6.1035156e-5f, toFloat(toHalf(6.10352e-5f)), 0.0f); // Inexact + assertEquals(65504.0f, toFloat(toHalf(65504.0f)), 0.0f); + assertEquals(0.33325195f, toFloat(toHalf(1.0f / 3.0f)), 0.0f); // Inexact + // Denormals (flushed to +/-0) + assertEquals(6.097555e-5f, toFloat(toHalf(6.09756e-5f)), 0.0f); + assertEquals(5.9604645e-8f, toFloat(toHalf(5.96046e-8f)), 0.0f); + assertEquals(-6.097555e-5f, toFloat(toHalf(-6.09756e-5f)), 0.0f); + assertEquals(-5.9604645e-8f, toFloat(toHalf(-5.96046e-8f)), 0.0f); + } + + public void testHexString() { + assertEquals("NaN", toHexString(NaN)); + assertEquals("Infinity", toHexString(POSITIVE_INFINITY)); + assertEquals("-Infinity", toHexString(NEGATIVE_INFINITY)); + assertEquals("0x0.0p0", toHexString(POSITIVE_ZERO)); + assertEquals("-0x0.0p0", toHexString(NEGATIVE_ZERO)); + assertEquals("0x1.0p0", toHexString(toHalf(1.0f))); + assertEquals("-0x1.0p0", toHexString(toHalf(-1.0f))); + assertEquals("0x1.0p1", toHexString(toHalf(2.0f))); + assertEquals("0x1.0p8", toHexString(toHalf(256.0f))); + assertEquals("0x1.0p-1", toHexString(toHalf(0.5f))); + assertEquals("0x1.0p-2", toHexString(toHalf(0.25f))); + assertEquals("0x1.3ffp15", toHexString(MAX_VALUE)); + assertEquals("0x0.1p-14", toHexString(MIN_VALUE)); + assertEquals("0x1.0p-14", toHexString(MIN_NORMAL)); + assertEquals("-0x1.3ffp15", toHexString(LOWEST_VALUE)); + } + + public void testIsInfinite() { + assertTrue(FP16.isInfinite(POSITIVE_INFINITY)); + assertTrue(FP16.isInfinite(NEGATIVE_INFINITY)); + assertFalse(FP16.isInfinite(POSITIVE_ZERO)); + assertFalse(FP16.isInfinite(NEGATIVE_ZERO)); + assertFalse(FP16.isInfinite(NaN)); + assertFalse(FP16.isInfinite(MAX_VALUE)); + assertFalse(FP16.isInfinite(LOWEST_VALUE)); + assertFalse(FP16.isInfinite(toHalf(-128.3f))); + assertFalse(FP16.isInfinite(toHalf(128.3f))); + } + + public void testIsNaN() { + assertFalse(FP16.isNaN(POSITIVE_INFINITY)); + assertFalse(FP16.isNaN(NEGATIVE_INFINITY)); + assertFalse(FP16.isNaN(POSITIVE_ZERO)); + assertFalse(FP16.isNaN(NEGATIVE_ZERO)); + assertTrue(FP16.isNaN(NaN)); + assertTrue(FP16.isNaN((short) 0x7c01)); + assertTrue(FP16.isNaN((short) 0x7c18)); + assertTrue(FP16.isNaN((short) 0xfc01)); + assertTrue(FP16.isNaN((short) 0xfc98)); + assertFalse(FP16.isNaN(MAX_VALUE)); + assertFalse(FP16.isNaN(LOWEST_VALUE)); + assertFalse(FP16.isNaN(toHalf(-128.3f))); + assertFalse(FP16.isNaN(toHalf(128.3f))); + } + + public void testIsNormalized() { + assertFalse(FP16.isNormalized(POSITIVE_INFINITY)); + assertFalse(FP16.isNormalized(NEGATIVE_INFINITY)); + assertFalse(FP16.isNormalized(POSITIVE_ZERO)); + assertFalse(FP16.isNormalized(NEGATIVE_ZERO)); + assertFalse(FP16.isNormalized(NaN)); + assertTrue(FP16.isNormalized(MAX_VALUE)); + assertTrue(FP16.isNormalized(MIN_NORMAL)); + assertTrue(FP16.isNormalized(LOWEST_VALUE)); + assertTrue(FP16.isNormalized(toHalf(-128.3f))); + assertTrue(FP16.isNormalized(toHalf(128.3f))); + assertTrue(FP16.isNormalized(toHalf(0.3456f))); + assertFalse(FP16.isNormalized(MIN_VALUE)); + assertFalse(FP16.isNormalized((short) 0x3ff)); + assertFalse(FP16.isNormalized((short) 0x200)); + assertFalse(FP16.isNormalized((short) 0x100)); + } + + public void testCeil() { + assertEquals(POSITIVE_INFINITY, FP16.ceil(POSITIVE_INFINITY)); + assertEquals(NEGATIVE_INFINITY, FP16.ceil(NEGATIVE_INFINITY)); + assertEquals(POSITIVE_ZERO, FP16.ceil(POSITIVE_ZERO)); + assertEquals(NEGATIVE_ZERO, FP16.ceil(NEGATIVE_ZERO)); + assertEquals(NaN, FP16.ceil(NaN)); + assertEquals(LOWEST_VALUE, FP16.ceil(LOWEST_VALUE)); + assertEquals(1.0f, toFloat(FP16.ceil(MIN_NORMAL)), 0.0f); + assertEquals(1.0f, toFloat(FP16.ceil((short) 0x3ff)), 0.0f); + assertEquals(1.0f, toFloat(FP16.ceil(toHalf(0.2f))), 0.0f); + assertEquals(NEGATIVE_ZERO, FP16.ceil(toHalf(-0.2f))); + assertEquals(1.0f, toFloat(FP16.ceil(toHalf(0.7f))), 0.0f); + assertEquals(NEGATIVE_ZERO, FP16.ceil(toHalf(-0.7f))); + assertEquals(125.0f, toFloat(FP16.ceil(toHalf(124.7f))), 0.0f); + assertEquals(-124.0f, toFloat(FP16.ceil(toHalf(-124.7f))), 0.0f); + assertEquals(125.0f, toFloat(FP16.ceil(toHalf(124.2f))), 0.0f); + assertEquals(-124.0f, toFloat(FP16.ceil(toHalf(-124.2f))), 0.0f); + // ceil for NaN values + // These tests check whether the current ceil implementation achieves + // bit level compatibility with the hardware implementation (ARM64) + assertEquals((short) 0x7e01, FP16.ceil((short) 0x7c01)); + assertEquals((short) 0x7f00, FP16.ceil((short) 0x7d00)); + assertEquals((short) 0xfe01, FP16.ceil((short) 0xfc01)); + assertEquals((short) 0xff00, FP16.ceil((short) 0xfd00)); + } + + public void testEquals() { + assertTrue(FP16.equals(POSITIVE_INFINITY, POSITIVE_INFINITY)); + assertTrue(FP16.equals(NEGATIVE_INFINITY, NEGATIVE_INFINITY)); + assertTrue(FP16.equals(POSITIVE_ZERO, POSITIVE_ZERO)); + assertTrue(FP16.equals(NEGATIVE_ZERO, NEGATIVE_ZERO)); + assertTrue(FP16.equals(POSITIVE_ZERO, NEGATIVE_ZERO)); + assertFalse(FP16.equals(NaN, toHalf(12.4f))); + assertFalse(FP16.equals(toHalf(12.4f), NaN)); + assertFalse(FP16.equals(NaN, NaN)); + assertTrue(FP16.equals(toHalf(12.4f), toHalf(12.4f))); + assertTrue(FP16.equals(toHalf(-12.4f), toHalf(-12.4f))); + assertFalse(FP16.equals(toHalf(12.4f), toHalf(0.7f))); + } + + public void testFloor() { + assertEquals(POSITIVE_INFINITY, FP16.floor(POSITIVE_INFINITY)); + assertEquals(NEGATIVE_INFINITY, FP16.floor(NEGATIVE_INFINITY)); + assertEquals(POSITIVE_ZERO, FP16.floor(POSITIVE_ZERO)); + assertEquals(NEGATIVE_ZERO, FP16.floor(NEGATIVE_ZERO)); + assertEquals(NaN, FP16.floor(NaN)); + assertEquals(LOWEST_VALUE, FP16.floor(LOWEST_VALUE)); + assertEquals(POSITIVE_ZERO, FP16.floor(MIN_NORMAL)); + assertEquals(POSITIVE_ZERO, FP16.floor((short) 0x3ff)); + assertEquals(POSITIVE_ZERO, FP16.floor(toHalf(0.2f))); + assertEquals(-1.0f, toFloat(FP16.floor(toHalf(-0.2f))), 0.0f); + assertEquals(-1.0f, toFloat(FP16.floor(toHalf(-0.7f))), 0.0f); + assertEquals(POSITIVE_ZERO, FP16.floor(toHalf(0.7f))); + assertEquals(124.0f, toFloat(FP16.floor(toHalf(124.7f))), 0.0f); + assertEquals(-125.0f, toFloat(FP16.floor(toHalf(-124.7f))), 0.0f); + assertEquals(124.0f, toFloat(FP16.floor(toHalf(124.2f))), 0.0f); + assertEquals(-125.0f, toFloat(FP16.floor(toHalf(-124.2f))), 0.0f); + // floor for NaN values + assertEquals((short) 0x7e01, FP16.floor((short) 0x7c01)); + assertEquals((short) 0x7f00, FP16.floor((short) 0x7d00)); + assertEquals((short) 0xfe01, FP16.floor((short) 0xfc01)); + assertEquals((short) 0xff00, FP16.floor((short) 0xfd00)); + } + + public void testRint() { + assertEquals(POSITIVE_INFINITY, FP16.rint(POSITIVE_INFINITY)); + assertEquals(NEGATIVE_INFINITY, FP16.rint(NEGATIVE_INFINITY)); + assertEquals(POSITIVE_ZERO, FP16.rint(POSITIVE_ZERO)); + assertEquals(NEGATIVE_ZERO, FP16.rint(NEGATIVE_ZERO)); + assertEquals(NaN, FP16.rint(NaN)); + assertEquals(LOWEST_VALUE, FP16.rint(LOWEST_VALUE)); + assertEquals(POSITIVE_ZERO, FP16.rint(MIN_VALUE)); + assertEquals(POSITIVE_ZERO, FP16.rint((short) 0x200)); + assertEquals(POSITIVE_ZERO, FP16.rint((short) 0x3ff)); + assertEquals(POSITIVE_ZERO, FP16.rint(toHalf(0.2f))); + assertEquals(NEGATIVE_ZERO, FP16.rint(toHalf(-0.2f))); + assertEquals(1.0f, toFloat(FP16.rint(toHalf(0.7f))), 0.0f); + assertEquals(-1.0f, toFloat(FP16.rint(toHalf(-0.7f))), 0.0f); + assertEquals(0.0f, toFloat(FP16.rint(toHalf(0.5f))), 0.0f); + assertEquals(-0.0f, toFloat(FP16.rint(toHalf(-0.5f))), 0.0f); + assertEquals(2.0f, toFloat(FP16.rint(toHalf(1.5f))), 0.0f); + assertEquals(-2.0f, toFloat(FP16.rint(toHalf(-1.5f))), 0.0f); + assertEquals(1022.0f, toFloat(FP16.rint(toHalf(1022.5f))), 0.0f); + assertEquals(-1022.0f, toFloat(FP16.rint(toHalf(-1022.5f))), 0.0f); + assertEquals(125.0f, toFloat(FP16.rint(toHalf(124.7f))), 0.0f); + assertEquals(-125.0f, toFloat(FP16.rint(toHalf(-124.7f))), 0.0f); + assertEquals(124.0f, toFloat(FP16.rint(toHalf(124.2f))), 0.0f); + assertEquals(-124.0f, toFloat(FP16.rint(toHalf(-124.2f))), 0.0f); + // round for NaN values + // These tests check whether the current rint implementation achieves + // bit level compatibility with the hardware implementation (ARM64) + assertEquals((short) 0x7e01, FP16.rint((short) 0x7c01)); + assertEquals((short) 0x7f00, FP16.rint((short) 0x7d00)); + assertEquals((short) 0xfe01, FP16.rint((short) 0xfc01)); + assertEquals((short) 0xff00, FP16.rint((short) 0xfd00)); + } + + public void testTrunc() { + assertEquals(POSITIVE_INFINITY, FP16.trunc(POSITIVE_INFINITY)); + assertEquals(NEGATIVE_INFINITY, FP16.trunc(NEGATIVE_INFINITY)); + assertEquals(POSITIVE_ZERO, FP16.trunc(POSITIVE_ZERO)); + assertEquals(NEGATIVE_ZERO, FP16.trunc(NEGATIVE_ZERO)); + assertEquals(NaN, FP16.trunc(NaN)); + assertEquals(LOWEST_VALUE, FP16.trunc(LOWEST_VALUE)); + assertEquals(POSITIVE_ZERO, FP16.trunc(toHalf(0.2f))); + assertEquals(NEGATIVE_ZERO, FP16.trunc(toHalf(-0.2f))); + assertEquals(0.0f, toFloat(FP16.trunc(toHalf(0.7f))), 0.0f); + assertEquals(-0.0f, toFloat(FP16.trunc(toHalf(-0.7f))), 0.0f); + assertEquals(124.0f, toFloat(FP16.trunc(toHalf(124.7f))), 0.0f); + assertEquals(-124.0f, toFloat(FP16.trunc(toHalf(-124.7f))), 0.0f); + assertEquals(124.0f, toFloat(FP16.trunc(toHalf(124.2f))), 0.0f); + assertEquals(-124.0f, toFloat(FP16.trunc(toHalf(-124.2f))), 0.0f); + } + + public void testLess() { + assertTrue(FP16.less(NEGATIVE_INFINITY, POSITIVE_INFINITY)); + assertTrue(FP16.less(MAX_VALUE, POSITIVE_INFINITY)); + assertFalse(FP16.less(POSITIVE_INFINITY, MAX_VALUE)); + assertFalse(FP16.less(LOWEST_VALUE, NEGATIVE_INFINITY)); + assertTrue(FP16.less(NEGATIVE_INFINITY, LOWEST_VALUE)); + assertFalse(FP16.less(POSITIVE_ZERO, NEGATIVE_ZERO)); + assertFalse(FP16.less(NEGATIVE_ZERO, POSITIVE_ZERO)); + assertFalse(FP16.less(NaN, toHalf(12.3f))); + assertFalse(FP16.less(toHalf(12.3f), NaN)); + assertTrue(FP16.less(MIN_VALUE, MIN_NORMAL)); + assertFalse(FP16.less(MIN_NORMAL, MIN_VALUE)); + assertTrue(FP16.less(toHalf(12.3f), toHalf(12.4f))); + assertFalse(FP16.less(toHalf(12.4f), toHalf(12.3f))); + assertFalse(FP16.less(toHalf(-12.3f), toHalf(-12.4f))); + assertTrue(FP16.less(toHalf(-12.4f), toHalf(-12.3f))); + assertTrue(FP16.less(MIN_VALUE, (short) 0x3ff)); + } + + public void testLessEquals() { + assertTrue(FP16.lessEquals(NEGATIVE_INFINITY, POSITIVE_INFINITY)); + assertTrue(FP16.lessEquals(MAX_VALUE, POSITIVE_INFINITY)); + assertFalse(FP16.lessEquals(POSITIVE_INFINITY, MAX_VALUE)); + assertFalse(FP16.lessEquals(LOWEST_VALUE, NEGATIVE_INFINITY)); + assertTrue(FP16.lessEquals(NEGATIVE_INFINITY, LOWEST_VALUE)); + assertTrue(FP16.lessEquals(POSITIVE_ZERO, NEGATIVE_ZERO)); + assertTrue(FP16.lessEquals(NEGATIVE_ZERO, POSITIVE_ZERO)); + assertFalse(FP16.lessEquals(NaN, toHalf(12.3f))); + assertFalse(FP16.lessEquals(toHalf(12.3f), NaN)); + assertTrue(FP16.lessEquals(MIN_VALUE, MIN_NORMAL)); + assertFalse(FP16.lessEquals(MIN_NORMAL, MIN_VALUE)); + assertTrue(FP16.lessEquals(toHalf(12.3f), toHalf(12.4f))); + assertFalse(FP16.lessEquals(toHalf(12.4f), toHalf(12.3f))); + assertFalse(FP16.lessEquals(toHalf(-12.3f), toHalf(-12.4f))); + assertTrue(FP16.lessEquals(toHalf(-12.4f), toHalf(-12.3f))); + assertTrue(FP16.lessEquals(MIN_VALUE, (short) 0x3ff)); + assertTrue(FP16.lessEquals(NEGATIVE_INFINITY, NEGATIVE_INFINITY)); + assertTrue(FP16.lessEquals(POSITIVE_INFINITY, POSITIVE_INFINITY)); + assertTrue(FP16.lessEquals(toHalf(12.12356f), toHalf(12.12356f))); + assertTrue(FP16.lessEquals(toHalf(-12.12356f), toHalf(-12.12356f))); + } + + public void testGreater() { + assertTrue(FP16.greater(POSITIVE_INFINITY, NEGATIVE_INFINITY)); + assertTrue(FP16.greater(POSITIVE_INFINITY, MAX_VALUE)); + assertFalse(FP16.greater(MAX_VALUE, POSITIVE_INFINITY)); + assertFalse(FP16.greater(NEGATIVE_INFINITY, LOWEST_VALUE)); + assertTrue(FP16.greater(LOWEST_VALUE, NEGATIVE_INFINITY)); + assertFalse(FP16.greater(NEGATIVE_ZERO, POSITIVE_ZERO)); + assertFalse(FP16.greater(POSITIVE_ZERO, NEGATIVE_ZERO)); + assertFalse(FP16.greater(toHalf(12.3f), NaN)); + assertFalse(FP16.greater(NaN, toHalf(12.3f))); + assertTrue(FP16.greater(MIN_NORMAL, MIN_VALUE)); + assertFalse(FP16.greater(MIN_VALUE, MIN_NORMAL)); + assertTrue(FP16.greater(toHalf(12.4f), toHalf(12.3f))); + assertFalse(FP16.greater(toHalf(12.3f), toHalf(12.4f))); + assertFalse(FP16.greater(toHalf(-12.4f), toHalf(-12.3f))); + assertTrue(FP16.greater(toHalf(-12.3f), toHalf(-12.4f))); + assertTrue(FP16.greater((short) 0x3ff, MIN_VALUE)); + } + + public void testGreaterEquals() { + assertTrue(FP16.greaterEquals(POSITIVE_INFINITY, NEGATIVE_INFINITY)); + assertTrue(FP16.greaterEquals(POSITIVE_INFINITY, MAX_VALUE)); + assertFalse(FP16.greaterEquals(MAX_VALUE, POSITIVE_INFINITY)); + assertFalse(FP16.greaterEquals(NEGATIVE_INFINITY, LOWEST_VALUE)); + assertTrue(FP16.greaterEquals(LOWEST_VALUE, NEGATIVE_INFINITY)); + assertTrue(FP16.greaterEquals(NEGATIVE_ZERO, POSITIVE_ZERO)); + assertTrue(FP16.greaterEquals(POSITIVE_ZERO, NEGATIVE_ZERO)); + assertFalse(FP16.greaterEquals(toHalf(12.3f), NaN)); + assertFalse(FP16.greaterEquals(NaN, toHalf(12.3f))); + assertTrue(FP16.greaterEquals(MIN_NORMAL, MIN_VALUE)); + assertFalse(FP16.greaterEquals(MIN_VALUE, MIN_NORMAL)); + assertTrue(FP16.greaterEquals(toHalf(12.4f), toHalf(12.3f))); + assertFalse(FP16.greaterEquals(toHalf(12.3f), toHalf(12.4f))); + assertFalse(FP16.greaterEquals(toHalf(-12.4f), toHalf(-12.3f))); + assertTrue(FP16.greaterEquals(toHalf(-12.3f), toHalf(-12.4f))); + assertTrue(FP16.greaterEquals((short) 0x3ff, MIN_VALUE)); + assertTrue(FP16.greaterEquals(NEGATIVE_INFINITY, NEGATIVE_INFINITY)); + assertTrue(FP16.greaterEquals(POSITIVE_INFINITY, POSITIVE_INFINITY)); + assertTrue(FP16.greaterEquals(toHalf(12.12356f), toHalf(12.12356f))); + assertTrue(FP16.greaterEquals(toHalf(-12.12356f), toHalf(-12.12356f))); + } + + public void testMin() { + assertEquals(NEGATIVE_INFINITY, FP16.min(POSITIVE_INFINITY, NEGATIVE_INFINITY)); + assertEquals(NEGATIVE_ZERO, FP16.min(POSITIVE_ZERO, NEGATIVE_ZERO)); + assertEquals(NaN, FP16.min(NaN, LOWEST_VALUE)); + assertEquals(NaN, FP16.min(LOWEST_VALUE, NaN)); + assertEquals(NEGATIVE_INFINITY, FP16.min(NEGATIVE_INFINITY, LOWEST_VALUE)); + assertEquals(MAX_VALUE, FP16.min(POSITIVE_INFINITY, MAX_VALUE)); + assertEquals(MIN_VALUE, FP16.min(MIN_VALUE, MIN_NORMAL)); + assertEquals(POSITIVE_ZERO, FP16.min(MIN_VALUE, POSITIVE_ZERO)); + assertEquals(POSITIVE_ZERO, FP16.min(MIN_NORMAL, POSITIVE_ZERO)); + assertEquals(toHalf(-3.456f), FP16.min(toHalf(-3.456f), toHalf(-3.453f))); + assertEquals(toHalf(3.453f), FP16.min(toHalf(3.456f), toHalf(3.453f))); + } + + public void testMax() { + assertEquals(POSITIVE_INFINITY, FP16.max(POSITIVE_INFINITY, NEGATIVE_INFINITY)); + assertEquals(POSITIVE_ZERO, FP16.max(POSITIVE_ZERO, NEGATIVE_ZERO)); + assertEquals(NaN, FP16.max(NaN, MAX_VALUE)); + assertEquals(NaN, FP16.max(MAX_VALUE, NaN)); + assertEquals(LOWEST_VALUE, FP16.max(NEGATIVE_INFINITY, LOWEST_VALUE)); + assertEquals(POSITIVE_INFINITY, FP16.max(POSITIVE_INFINITY, MAX_VALUE)); + assertEquals(MIN_NORMAL, FP16.max(MIN_VALUE, MIN_NORMAL)); + assertEquals(MIN_VALUE, FP16.max(MIN_VALUE, POSITIVE_ZERO)); + assertEquals(MIN_NORMAL, FP16.max(MIN_NORMAL, POSITIVE_ZERO)); + assertEquals(toHalf(-3.453f), FP16.max(toHalf(-3.456f), toHalf(-3.453f))); + assertEquals(toHalf(3.456f), FP16.max(toHalf(3.456f), toHalf(3.453f))); + } + + public void testCompare() { + assertEquals(0, FP16.compare(NaN, NaN)); + assertEquals(0, FP16.compare(NaN, (short) 0xfc98)); + assertEquals(1, FP16.compare(NaN, POSITIVE_INFINITY)); + assertEquals(-1, FP16.compare(POSITIVE_INFINITY, NaN)); + + assertEquals(0, FP16.compare(POSITIVE_INFINITY, POSITIVE_INFINITY)); + assertEquals(0, FP16.compare(NEGATIVE_INFINITY, NEGATIVE_INFINITY)); + assertEquals(1, FP16.compare(POSITIVE_INFINITY, NEGATIVE_INFINITY)); + assertEquals(-1, FP16.compare(NEGATIVE_INFINITY, POSITIVE_INFINITY)); + + assertEquals(0, FP16.compare(POSITIVE_ZERO, POSITIVE_ZERO)); + assertEquals(0, FP16.compare(NEGATIVE_ZERO, NEGATIVE_ZERO)); + assertEquals(1, FP16.compare(POSITIVE_ZERO, NEGATIVE_ZERO)); + assertEquals(-1, FP16.compare(NEGATIVE_ZERO, POSITIVE_ZERO)); + + assertEquals(0, FP16.compare(toHalf(12.462f), toHalf(12.462f))); + assertEquals(0, FP16.compare(toHalf(-12.462f), toHalf(-12.462f))); + assertEquals(1, FP16.compare(toHalf(12.462f), toHalf(-12.462f))); + assertEquals(-1, FP16.compare(toHalf(-12.462f), toHalf(12.462f))); + } +} diff --git a/luni/src/test/java/libcore/libcore/util/HexEncodingTest.java b/luni/src/test/java/libcore/libcore/util/HexEncodingTest.java index 4de1a01df7..800928faf4 100644 --- a/luni/src/test/java/libcore/libcore/util/HexEncodingTest.java +++ b/luni/src/test/java/libcore/libcore/util/HexEncodingTest.java @@ -18,28 +18,69 @@ package libcore.libcore.util; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.Locale; + import junit.framework.TestCase; import static libcore.util.HexEncoding.decode; import static libcore.util.HexEncoding.encode; +import static libcore.util.HexEncoding.encodeToString; public class HexEncodingTest extends TestCase { - public void testEncode() { - final byte[] avocados = "avocados".getBytes(StandardCharsets.UTF_8); - assertArraysEqual("61766F6361646F73".toCharArray(), encode(avocados)); - assertArraysEqual(avocados, decode(encode(avocados), false)); - // Make sure we can handle lower case hex encodings as well. - assertArraysEqual(avocados, decode("61766f6361646f73".toCharArray(), false)); + public void testEncodeByte() { + Object[][] testCases = new Object[][] { + { 0x01, "01" }, + { 0x09, "09" }, + { 0x0A, "0A" }, + { 0x0F, "0F" }, + { 0x10, "10" }, + { 0x1F, "1F" }, + { 0x20, "20" }, + { 0x7F, "7F" }, + { 0x80, "80" }, + { 0xFF, "FF" }, + }; + for (Object[] testCase : testCases) { + Number toEncode = (Number) testCase[0]; + String expected = (String) testCase[1]; + + String actualUpper = encodeToString(toEncode.byteValue(), true /* upperCase */); + assertEquals(upper(expected), actualUpper); + + String actualLower = encodeToString(toEncode.byteValue(), false /* upperCase */); + assertEquals(lower(expected), actualLower); + } + } + + public void testEncodeBytes() { + Object[][] testCases = new Object[][] { + { "avocados".getBytes(StandardCharsets.UTF_8), "61766F6361646F73" }, + }; + + for (Object[] testCase : testCases) { + byte[] bytes = (byte[]) testCase[0]; + String encodedLower = lower((String) testCase[1]); + String encodedUpper = upper((String) testCase[1]); + + assertArraysEqual(encodedUpper.toCharArray(), encode(bytes)); + assertArraysEqual(encodedUpper.toCharArray(), encode(bytes, true /* upperCase */)); + assertArraysEqual(encodedLower.toCharArray(), encode(bytes, false /* upperCase */)); + + assertArraysEqual(bytes, decode(encode(bytes), false /* allowSingleChar */)); + + // Make sure we can handle lower case hex encodings as well. + assertArraysEqual(bytes, decode(encodedLower.toCharArray(), false /* allowSingleChar */)); + } } public void testDecode_allow4Bit() { assertArraysEqual(new byte[] { 6 }, decode("6".toCharArray(), true)); - assertArraysEqual(new byte[] { 6, 'v' }, decode("676".toCharArray(), true)); + assertArraysEqual(new byte[] { 6, 0x76 }, decode("676".toCharArray(), true)); } public void testDecode_disallow4Bit() { try { - decode("676".toCharArray(), false); + decode("676".toCharArray(), false /* allowSingleChar */); fail(); } catch (IllegalArgumentException expected) { } @@ -47,7 +88,7 @@ public class HexEncodingTest extends TestCase { public void testDecode_invalid() { try { - decode("DEADBARD".toCharArray(), false); + decode("DEADBARD".toCharArray(), false /* allowSingleChar */); fail(); } catch (IllegalArgumentException expected) { } @@ -56,13 +97,13 @@ public class HexEncodingTest extends TestCase { // commons uses Character.isDigit and would successfully decode a string with // arabic and devanagari characters. try { - decode("६१٧٥٥F6361646F73".toCharArray(), false); + decode("६१٧٥٥F6361646F73".toCharArray(), false /* allowSingleChar */); fail(); } catch (IllegalArgumentException expected) { } try { - decode("#%6361646F73".toCharArray(), false); + decode("#%6361646F73".toCharArray(), false /* allowSingleChar */); fail(); } catch (IllegalArgumentException expected) { } @@ -75,4 +116,12 @@ public class HexEncodingTest extends TestCase { private static void assertArraysEqual(byte[] lhs, byte[] rhs) { assertEquals(Arrays.toString(lhs), Arrays.toString(rhs)); } + + private static String lower(String string) { + return string.toLowerCase(Locale.ROOT); + } + + private static String upper(String string) { + return string.toUpperCase(Locale.ROOT); + } } diff --git a/luni/src/test/java/libcore/libcore/util/NativeAllocationRegistryTest.java b/luni/src/test/java/libcore/libcore/util/NativeAllocationRegistryTest.java index 64128da431..54c88766ec 100644 --- a/luni/src/test/java/libcore/libcore/util/NativeAllocationRegistryTest.java +++ b/luni/src/test/java/libcore/libcore/util/NativeAllocationRegistryTest.java @@ -56,15 +56,18 @@ public class NativeAllocationRegistryTest extends TestCase { return; } Runtime.getRuntime().gc(); + System.runFinalization(); + long nativeBytes = getNumNativeBytesAllocated(); + assertEquals("Native bytes already allocated", 0, nativeBytes); long max = Runtime.getRuntime().maxMemory(); long total = Runtime.getRuntime().totalMemory(); int size = 1024*1024; - int expectedMaxNumAllocations = (int)(max-total)/size; + final int nativeSize = size/2; + int javaSize = size/2; + int expectedMaxNumAllocations = (int)(max-total)/javaSize; int numSavedAllocations = expectedMaxNumAllocations/2; Allocation[] saved = new Allocation[numSavedAllocations]; - final int nativeSize = size/2; - int javaSize = size/2; NativeAllocationRegistry registry = null; int numAllocationsToSimulate = 10 * expectedMaxNumAllocations; @@ -93,10 +96,23 @@ public class NativeAllocationRegistryTest extends TestCase { // Verify most of the allocations have been freed. // Since we use fairly large Java objects, this doesn't test the GC triggering // effect; we do that elsewhere. - long nativeBytes = getNumNativeBytesAllocated(); - long nativeReachableBytes = numSavedAllocations * nativeSize; + // Since native and java objects have the same size, and we can only have max + // Java bytes in use, there should be no more than max native bytes in use, + // once all enqueued deallocations have been processed. First make sure + // that the ReferenceQueueDaemon has processed all pending requests, and then + // check. + System.runFinalization(); + nativeBytes = getNumNativeBytesAllocated(); assertTrue("Excessive native bytes still allocated (" + nativeBytes + ")" - + " given max memory of (" + max + ")", nativeBytes < 2 * max); + + " given max memory of (" + max + ")", nativeBytes <= max); + // Check that the array is fully populated, and sufficiently many native bytes + // are live. + long nativeReachableBytes = numSavedAllocations * nativeSize; + for (int i = 0; i < numSavedAllocations; i++) { + assertNotNull(saved[i]); + assertNotNull(saved[i].javaAllocation); + assertTrue(saved[i].nativeAllocation != 0); + } assertTrue("Too few native bytes still allocated (" + nativeBytes + "); " + nativeReachableBytes + " bytes are reachable", nativeBytes >= nativeReachableBytes); diff --git a/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java b/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java index cddf41ba0a..8b9715f01d 100644 --- a/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java +++ b/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java @@ -26,7 +26,7 @@ import java.time.Instant; import java.util.Arrays; import java.util.Date; import libcore.io.BufferIterator; -import libcore.timezone.ZoneInfoDB; +import libcore.timezone.ZoneInfoDb; import libcore.timezone.testing.ZoneInfoTestHelper; import libcore.util.ZoneInfo; @@ -39,7 +39,7 @@ public class ZoneInfoTest extends TestCase { * Checks that a {@link ZoneInfo} cannot be created without any types. */ public void testMakeTimeZone_NoTypes() throws Exception { - int[][] transitions = {}; + long[][] transitions = {}; int[][] types = {}; try { createZoneInfo(transitions, types); @@ -52,7 +52,7 @@ public class ZoneInfoTest extends TestCase { * Checks that a {@link ZoneInfo} can be created with one type and no transitions. */ public void testMakeTimeZone_OneType_NoTransitions() throws Exception { - int[][] transitions = {}; + long[][] transitions = {}; int[][] types = { { 4800, 0 } }; @@ -78,7 +78,7 @@ public class ZoneInfoTest extends TestCase { * Checks that a {@link ZoneInfo} can be created with one non-DST transition. */ public void testReadTimeZone_OneNonDstTransition() throws Exception { - int[][] transitions = { + long[][] transitions = { { 0, 0 } }; int[][] types = { @@ -102,7 +102,7 @@ public class ZoneInfoTest extends TestCase { * Checks that a {@link ZoneInfo} cannot be created with one DST but no non-DSTs transitions. */ public void testReadTimeZone_OneDstTransition() throws Exception { - int[][] transitions = { + long[][] transitions = { { 0, 0 } }; int[][] types = { @@ -120,7 +120,7 @@ public class ZoneInfoTest extends TestCase { * around the boundary of negative transitions. */ public void testReadTimeZone_NegativeTransition() throws Exception { - int[][] transitions = { + long[][] transitions = { { -2000, 0 }, { -5, 1 }, { 0, 2 }, @@ -157,7 +157,7 @@ public class ZoneInfoTest extends TestCase { * around the boundary of positive transitions. */ public void testReadTimeZone_PositiveTransition() throws Exception { - int[][] transitions = { + long[][] transitions = { { 0, 0 }, { 5, 1 }, { 2000, 2 }, @@ -195,7 +195,7 @@ public class ZoneInfoTest extends TestCase { * transitions where the transition times are negative is not affected by rounding issues. */ public void testReadTimeZone_HasFutureDST_NoPastDST_NegativeTransitions() throws Exception { - int[][] transitions = { + long[][] transitions = { { -2000, 0 }, { -500, 1 }, { -100, 2 }, @@ -228,7 +228,7 @@ public class ZoneInfoTest extends TestCase { * transitions where the transition times are positive is not affected by rounding issues. */ public void testReadTimeZone_HasFutureDST_NoPastDST_PositiveTransitions() throws Exception { - int[][] transitions = { + long[][] transitions = { { 4000, 0 }, { 5500, 1 }, { 6000, 2 }, @@ -261,7 +261,7 @@ public class ZoneInfoTest extends TestCase { * transitions where the transition times are negative is not affected by rounding issues. */ public void testReadTimeZone_HasPastDST_NoFutureDST_NegativeTransitions() throws Exception { - int[][] transitions = { + long[][] transitions = { { -5000, 0 }, { -2000, 1 }, { -500, 0 }, @@ -290,7 +290,7 @@ public class ZoneInfoTest extends TestCase { * transitions where the transition times are positive is not affected by rounding issues. */ public void testReadTimeZone_HasPastDST_NoFutureDST_PositiveTransitions() throws Exception { - int[][] transitions = { + long[][] transitions = { { 1000, 0 }, { 4000, 1 }, { 5500, 0 }, @@ -315,24 +315,17 @@ public class ZoneInfoTest extends TestCase { } /** - * TimeZone APIs use long times in millis. Android uses TZif version 1 format data which - * uses 32-bit time values for transitions so it only gives accurate results for times in that - * range. + * TimeZone APIs use Java long times in millis. * - * <p>Newer versions of zic after 2014b introduce an explicit transition at the earliest - * representable time, which is Integer.MIN_VALUE for TZif version 1 files. Previously the type - * used was left implicit and readers were expected to use the first non-DST type in the file. - * This extra transition mostly went away again with zic 2018f. - * - * <p>Testing newer zic versions demonstrated that Android had been mishandling the lookup of - * offset for times before the first transition. The logic has been corrected. This test would - * fail on versions of Android <= P. + * <p>Android has historically mishandled the lookup of offset for times before Integer.MIN_VALUE + * seconds for various reasons. The logic has been corrected. This test would fail on versions of + * Android <= P. */ public void testReadTimeZone_Bug118835133_extraFirstTransition() throws Exception { - // A time before the first representable time in a TZif version 1 file. + // A time before the first representable time in seconds with a java int. Instant before32BitTime = timeFromSeconds(Integer.MIN_VALUE).minusMillis(1); - // Times between the start of the 32-bit time range and the first "official" transition. + // Times around the 32-bit seconds minimum. Instant[] earlyTimes = { timeFromSeconds(Integer.MIN_VALUE), timeFromSeconds(Integer.MIN_VALUE).plusMillis(1), @@ -358,10 +351,9 @@ public class ZoneInfoTest extends TestCase { { offsetToSeconds(type2Offset), 0 }, }; - // Creates a simulation of zic version <= 2014b or zic version >= 2018f where there is often - // no explicit transition at Integer.MIN_VALUE seconds in TZif version 1 data. + // Simulates a zone with a single transition. { - int[][] transitions = { + long[][] transitions = { { timeToSeconds(firstRealTransitionTime), 2 /* type 2 */ }, }; ZoneInfo oldZoneInfo = createZoneInfo(transitions, types, currentTime); @@ -375,11 +367,11 @@ public class ZoneInfoTest extends TestCase { assertOffsetAt(oldZoneInfo, type2Offset, afterFirstRealTransitionTimes); } - // Creates a simulation of zic version > 2014b and zic version < 2018f where there is usually an - // explicit transition at Integer.MIN_VALUE seconds for TZif version 1 data. + // Simulation a zone where there is an explicit transition at Integer.MIN_VALUE seconds. This + // used to be common when Android used 32-bit data from the TZif file. { - int[][] transitions = { - { Integer.MIN_VALUE, 1 /* type 1 */ }, // The extra transition added by zic. + long[][] transitions = { + { Integer.MIN_VALUE, 1 /* type 1 */ }, { timeToSeconds(firstRealTransitionTime), 2 /* type 2 */ }, }; ZoneInfo newZoneInfo = createZoneInfo(transitions, types, currentTime); @@ -398,7 +390,7 @@ public class ZoneInfoTest extends TestCase { /** * Newer versions of zic after 2014b sometime introduce an explicit transition at - * Integer.MAX_VALUE. + * Integer.MAX_VALUE seconds. */ public void testReadTimeZone_Bug118835133_extraLastTransition() throws Exception { // An arbitrary time to use as currentTime. Not important for this test. @@ -419,10 +411,10 @@ public class ZoneInfoTest extends TestCase { }; Duration expectedLateOffset = offsetFromSeconds(latestOffsetSeconds); - // Create a simulation of zic version <= 2014b where there is usually no explicit transition at - // Integer.MAX_VALUE seconds. + // Create a simulation of a zone where there is no explicit transition at Integer.MAX_VALUE + // seconds. { - int[][] transitions = { + long[][] transitions = { { 1000, 0 }, { 2000, 1 }, }; @@ -430,10 +422,10 @@ public class ZoneInfoTest extends TestCase { assertOffsetAt(oldZoneInfo, expectedLateOffset, timesToCheck); } - // Create a simulation of zic version > 2014b where there is sometimes an explicit transition at - // Integer.MAX_VALUE seconds. + // Create a simulation of a zone where there is an explicit transition at Integer.MAX_VALUE + // seconds. { - int[][] transitions = { + long[][] transitions = { { 1000, 0 }, { 2000, 1 }, { Integer.MAX_VALUE, 1}, // The extra transition. @@ -444,12 +436,14 @@ public class ZoneInfoTest extends TestCase { } /** - * Checks to make sure that it can handle up to 256 types. + * Checks to make sure that ZoneInfo can handle up to 256 types. */ - public void testReadTimeZone_LotsOfTypes() throws Exception { - int[][] transitions = { + public void testReadTimeZone_MaxTypeCount() throws Exception { + long[][] transitions = { { -2000, 255 }, }; + // Create 256 types, each with zero offset and without DST except the last, which is offset by + // one hour but also without DST. int[][] types = new int[256][]; Arrays.fill(types, new int[2]); types[255] = new int[] { 3600, 0 }; @@ -476,7 +470,7 @@ public class ZoneInfoTest extends TestCase { * creates the {@link ZoneInfo} instances does not prevent any of the time zones being loaded. */ public void testReadTimeZone_All() throws Exception { - ZoneInfoDB.TzData instance = ZoneInfoDB.getInstance(); + ZoneInfoDb instance = ZoneInfoDb.getInstance(); String[] availableIDs = instance.getAvailableIDs(); Arrays.sort(availableIDs); for (String id : availableIDs) { @@ -491,14 +485,14 @@ public class ZoneInfoTest extends TestCase { } } - public void testReadTimeZone_valid() throws Exception { + public void testReadTimeZone_Valid() throws Exception { ZoneInfoTestHelper.ZicDataBuilder builder = new ZoneInfoTestHelper.ZicDataBuilder() .initializeToValid(); assertNotNull(createZoneInfo(getName(), Instant.now(), builder.build())); } - public void testReadTimeZone_badMagic() throws Exception { + public void testReadTimeZone_BadMagic() { ZoneInfoTestHelper.ZicDataBuilder builder = new ZoneInfoTestHelper.ZicDataBuilder() .initializeToValid() @@ -512,11 +506,15 @@ public class ZoneInfoTest extends TestCase { /** * Checks to make sure that ZoneInfo rejects more than 256 types. */ - public void testReadTimeZone_TooManyTypes() throws Exception { + public void testReadTimeZone_TooManyTypes() { + int typeCount = 257; // Max types allowed is 256 + int transitionCount = 5; + long[][] transitions = createTransitions(transitionCount, typeCount); + int[][] types = createTypes(typeCount); ZoneInfoTestHelper.ZicDataBuilder builder = new ZoneInfoTestHelper.ZicDataBuilder() .initializeToValid() - .setTypeCountOverride(257); + .setTransitionsAndTypes(transitions, types); byte[] bytes = builder.build(); try { createZoneInfo(getName(), Instant.now(), bytes); @@ -528,11 +526,15 @@ public class ZoneInfoTest extends TestCase { /** * Checks to make sure that ZoneInfo rejects more than 2000 transitions. */ - public void testReadTimeZone_TooManyTransitions() throws Exception { + public void testReadTimeZone_TooManyTransitions() { + int typeCount = 5; + int transitionCount = 2001; // Max transitions allowed is 2000. + long[][] transitions = createTransitions(transitionCount, typeCount); + int[][] types = createTypes(typeCount); ZoneInfoTestHelper.ZicDataBuilder builder = new ZoneInfoTestHelper.ZicDataBuilder() .initializeToValid() - .setTransitionCountOverride(2001); + .setTransitionsAndTypes(transitions, types); byte[] bytes = builder.build(); try { createZoneInfo(getName(), Instant.now(), bytes); @@ -541,40 +543,8 @@ public class ZoneInfoTest extends TestCase { } } - /** - * Checks to make sure that ZoneInfo rejects a negative type count. - */ - public void testReadTimeZone_NegativeTypes() throws Exception { - ZoneInfoTestHelper.ZicDataBuilder builder = - new ZoneInfoTestHelper.ZicDataBuilder() - .initializeToValid() - .setTypeCountOverride(-1); - byte[] bytes = builder.build(); - try { - createZoneInfo(getName(), Instant.now(), bytes); - fail(); - } catch (IOException expected) { - } - } - - /** - * Checks to make sure that ZoneInfo rejects a negative transition count. - */ - public void testReadTimeZone_NegativeTransitions() throws Exception { - ZoneInfoTestHelper.ZicDataBuilder builder = - new ZoneInfoTestHelper.ZicDataBuilder() - .initializeToValid() - .setTransitionCountOverride(-1); - byte[] bytes = builder.build(); - try { - createZoneInfo(getName(), Instant.now(), bytes); - fail(); - } catch (IOException expected) { - } - } - - public void testReadTimeZone_TransitionsNotSorted() throws Exception { - int[][] transitions = { + public void testReadTimeZone_TransitionsNotSorted() { + long[][] transitions = { { 1000, 0 }, { 3000, 1 }, // Out of transition order. { 2000, 0 }, @@ -597,8 +567,8 @@ public class ZoneInfoTest extends TestCase { } } - public void testReadTimeZone_InvalidTypeIndex() throws Exception { - int[][] transitions = { + public void testReadTimeZone_InvalidTypeIndex() { + long[][] transitions = { { 1000, 0 }, { 2000, 2 }, // Invalid type index - only 0 and 1 defined below. { 3000, 0 }, @@ -621,8 +591,8 @@ public class ZoneInfoTest extends TestCase { } } - public void testReadTimeZone_InvalidIsDst() throws Exception { - int[][] transitions = { + public void testReadTimeZone_InvalidIsDst() { + long[][] transitions = { { 1000, 0 }, { 2000, 1 }, { 3000, 0 }, @@ -664,7 +634,7 @@ public class ZoneInfoTest extends TestCase { zoneInfoRead = (ZoneInfo) object; } - int[][] transitions = { + long[][] transitions = { { -5000, 0 }, { -2000, 1 }, { -500, 0 }, @@ -705,16 +675,12 @@ public class ZoneInfoTest extends TestCase { } } - private static Instant timeFromSeconds(int timeInSeconds) { + private static Instant timeFromSeconds(long timeInSeconds) { return Instant.ofEpochSecond(timeInSeconds); } - private static int timeToSeconds(Instant time) { - long seconds = time.getEpochSecond(); - if (seconds < Integer.MIN_VALUE || seconds > Integer.MAX_VALUE) { - fail("Time out of seconds range: " + time); - } - return (int) seconds; + private static long timeToSeconds(Instant time) { + return time.getEpochSecond(); } private static Duration offsetFromSeconds(int offsetSeconds) { @@ -729,17 +695,17 @@ public class ZoneInfoTest extends TestCase { return (int) seconds; } - private ZoneInfo createZoneInfo(int[][] transitions, int[][] types) + private ZoneInfo createZoneInfo(long[][] transitions, int[][] types) throws Exception { return createZoneInfo(getName(), transitions, types, Instant.now()); } - private ZoneInfo createZoneInfo(int[][] transitions, int[][] types, Instant currentTime) + private ZoneInfo createZoneInfo(long[][] transitions, int[][] types, Instant currentTime) throws Exception { return createZoneInfo(getName(), transitions, types, currentTime); } - private ZoneInfo createZoneInfo(String name, int[][] transitions, int[][] types, + private ZoneInfo createZoneInfo(String name, long[][] transitions, int[][] types, Instant currentTime) throws Exception { ZoneInfoTestHelper.ZicDataBuilder builder = @@ -748,7 +714,7 @@ public class ZoneInfoTest extends TestCase { return createZoneInfo(name, currentTime, builder.build()); } - private ZoneInfo createZoneInfo(String name, Instant currentTime, byte[] bytes) + private static ZoneInfo createZoneInfo(String name, Instant currentTime, byte[] bytes) throws IOException { ByteBufferIterator bufferIterator = new ByteBufferIterator(ByteBuffer.wrap(bytes)); return ZoneInfo.readTimeZone( @@ -756,6 +722,38 @@ public class ZoneInfoTest extends TestCase { } /** + * Creates {@code typeCount} "types" for use with + * {@link ZoneInfoTestHelper.ZicDataBuilder#setTypes(int[][])} and related methods. Each type is + * given an arbitrary offset and "isDst" value. + */ + private static int[][] createTypes(int typeCount) { + int[][] types = new int[typeCount][2]; + for (int i = 0; i < typeCount; i++) { + // [0] holds the offset from UTC in seconds. + types[i][0] = typeCount; + // [1] holds isDst: 0 == STD, 1 == DST + types[i][1] = typeCount % 2; + } + return types; + } + + /** + * Creates {@code transitionCount} "transition pairs" for use with + * {@link ZoneInfoTestHelper.ZicDataBuilder#setTransitions(long[][])} and related methods. Each + * transition is given an arbitrary (but increasing) time referencing an arbitrary type. + */ + private static long[][] createTransitions(int transitionCount, int typeCount) { + long[][] transitions = new long[transitionCount][2]; + for (int i = 0; i < transitionCount; i++) { + // [0] holds the transition time. + transitions[i][0] = (i * 3600) + 100; + // [1] holds the type index to use. Must be > 0 and < typeCount to be valid. + transitions[i][1] = i % typeCount; + } + return transitions; + } + + /** * A {@link BufferIterator} that wraps a {@link ByteBuffer}. */ private static class ByteBufferIterator extends BufferIterator { @@ -782,8 +780,8 @@ public class ZoneInfoTest extends TestCase { } @Override - public void readByteArray(byte[] dst, int dstOffset, int byteCount) { - buffer.get(dst, dstOffset, byteCount); + public void readByteArray(byte[] bytes, int arrayOffset, int byteCount) { + buffer.get(bytes, arrayOffset, byteCount); } @Override @@ -796,16 +794,24 @@ public class ZoneInfoTest extends TestCase { int value = buffer.asIntBuffer().get(); // Using a separate view does not update the position of this buffer so do it // explicitly. - skip(4); + skip(Integer.BYTES); return value; } @Override - public void readIntArray(int[] dst, int dstOffset, int intCount) { - buffer.asIntBuffer().get(dst, dstOffset, intCount); + public void readIntArray(int[] ints, int arrayOffset, int intCount) { + buffer.asIntBuffer().get(ints, arrayOffset, intCount); + // Using a separate view does not update the position of this buffer so do it + // explicitly. + skip(Integer.BYTES * intCount); + } + + @Override + public void readLongArray(long[] longs, int arrayOffset, int longCount) { + buffer.asLongBuffer().get(longs, arrayOffset, longCount); // Using a separate view does not update the position of this buffer so do it // explicitly. - skip(4 * intCount); + skip(Long.BYTES * longCount); } @Override @@ -813,7 +819,7 @@ public class ZoneInfoTest extends TestCase { short value = buffer.asShortBuffer().get(); // Using a separate view does not update the position of this buffer so do it // explicitly. - skip(2); + skip(Short.BYTES); return value; } } diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java index 7d8aff0e11..751a99e6dc 100644 --- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java +++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java @@ -39,39 +39,29 @@ import javax.crypto.SecretKey; import javax.crypto.ShortBufferException; import javax.crypto.spec.DHGenParameterSpec; import javax.crypto.spec.SecretKeySpec; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; import org.apache.harmony.crypto.tests.support.MyMacSpi; import org.apache.harmony.security.tests.support.SpiEngUtils; -import junit.framework.TestCase; import junit.framework.Test; import junit.framework.TestSuite; import libcore.java.security.StandardNames; import libcore.javax.crypto.MockKey; import libcore.javax.crypto.MockKey2; - -import dalvik.system.VMRuntime; -import sun.security.jca.Providers; +import org.junit.Rule; +import org.junit.rules.TestRule; /** * Tests for Mac class constructors and methods * */ -public class MacTest extends TestCase { +public class MacTest extends TestCaseWithRules { // Allow access to deprecated BC algorithms in this test, so we can ensure they // continue to work - @Override - public void setUp() throws Exception { - super.setUp(); - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - } - - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); - } + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); public static final String srvMac = "Mac"; diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/KeyAgreementThread.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/KeyAgreementThread.java index 480ea7ff64..33e9c2130a 100644 --- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/KeyAgreementThread.java +++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/KeyAgreementThread.java @@ -15,7 +15,6 @@ */ package org.apache.harmony.crypto.tests.javax.crypto.func; -import com.android.org.bouncycastle.util.Arrays; import java.security.AlgorithmParameterGenerator; import java.security.AlgorithmParameters; import java.security.KeyFactory; @@ -25,6 +24,7 @@ import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.spec.X509EncodedKeySpec; +import java.util.Arrays; import javax.crypto.KeyAgreement; import javax.crypto.spec.DHParameterSpec; @@ -80,7 +80,7 @@ public class KeyAgreementThread extends TestThread { byte[] sk1 = kag1.getSecretKey(algName, bArray2); byte[] sk2 = kag2.getSecretKey(algName, bArray1); - if (Arrays.areEqual(sk1, sk2) == false) { + if (!Arrays.equals(sk1, sk2)) { throw new Exception ("Generated keys are not the same"); } } diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java index 689efa51c4..5367dcd911 100644 --- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java +++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java @@ -33,9 +33,19 @@ import java.util.Map; import java.util.Map.Entry; import dalvik.system.VMRuntime; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; +import org.junit.Rule; +import org.junit.rules.TestRule; import sun.security.jca.Providers; -public class MessageDigest2Test extends junit.framework.TestCase { +public class MessageDigest2Test extends TestCaseWithRules { + + // Allow access to deprecated BC algorithms in this test, so we can ensure they + // continue to work + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); private static final String MESSAGEDIGEST_ID = "MessageDigest."; @@ -434,18 +444,6 @@ public class MessageDigest2Test extends junit.framework.TestCase { for (Provider provider : providers) { digestAlgs.put(provider, getDigestAlgorithms(provider)); } - - // Allow access to deprecated BC algorithms in this test, so we can ensure they - // continue to work - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - } - - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); } /* diff --git a/luni/src/test/java/tests/security/cert/CertPathBuilder1Test.java b/luni/src/test/java/tests/security/cert/CertPathBuilder1Test.java index aae021b830..20597db2c9 100644 --- a/luni/src/test/java/tests/security/cert/CertPathBuilder1Test.java +++ b/luni/src/test/java/tests/security/cert/CertPathBuilder1Test.java @@ -22,8 +22,6 @@ package tests.security.cert; -import dalvik.annotation.KnownFailure; - import org.apache.harmony.security.tests.support.SpiEngUtils; import org.apache.harmony.security.tests.support.cert.MyCertPathBuilderSpi; import org.apache.harmony.security.tests.support.cert.TestUtils; @@ -316,8 +314,6 @@ public class CertPathBuilder1Test extends TestCase { } } - // Test passed on RI - @KnownFailure(value="expired certificate bug 2322662") public void testBuild() throws Exception { TestUtils.initCertPathSSCertChain(); CertPathParameters params = TestUtils.getCertPathParameters(); diff --git a/luni/src/test/java/tests/security/cert/CertificateFactory4Test.java b/luni/src/test/java/tests/security/cert/CertificateFactory4Test.java index 18fe0c4e6f..1b3f00c35d 100644 --- a/luni/src/test/java/tests/security/cert/CertificateFactory4Test.java +++ b/luni/src/test/java/tests/security/cert/CertificateFactory4Test.java @@ -17,10 +17,10 @@ package tests.security.cert; -import junit.framework.TestCase; - -import dalvik.system.VMRuntime; -import sun.security.jca.Providers; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; +import org.junit.Rule; +import org.junit.rules.TestRule; import tests.support.resource.Support_Resources; import tests.support.Support_GetResource; @@ -40,23 +40,13 @@ import java.security.cert.CertificateFactory; import java.util.Collection; import java.util.List; -public class CertificateFactory4Test extends TestCase { +public class CertificateFactory4Test extends TestCaseWithRules { // Allow access to deprecated BC algorithms in this test, so we can ensure they // continue to work - @Override - public void setUp() throws Exception { - super.setUp(); - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - } - - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); - } + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); private static final String BASE_URL = Support_GetResource .getResourceURL("/../internalres/"); diff --git a/luni/src/test/java/tests/targets/security/cert/CertificateTest.java b/luni/src/test/java/tests/targets/security/cert/CertificateTest.java index 80b34c017d..4a8e5ef7a4 100644 --- a/luni/src/test/java/tests/targets/security/cert/CertificateTest.java +++ b/luni/src/test/java/tests/targets/security/cert/CertificateTest.java @@ -32,29 +32,19 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Calendar; import java.util.List; -import junit.framework.TestCase; import libcore.java.security.StandardNames; +import libcore.junit.junit3.TestCaseWithRules; +import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule; +import org.junit.Rule; +import org.junit.rules.TestRule; -import dalvik.system.VMRuntime; -import sun.security.jca.Providers; - -public class CertificateTest extends TestCase { +public class CertificateTest extends TestCaseWithRules { // Allow access to deprecated BC algorithms in this test, so we can ensure they // continue to work - @Override - public void setUp() throws Exception { - super.setUp(); - Providers.setMaximumAllowableApiLevelForBcDeprecation( - VMRuntime.getRuntime().getTargetSdkVersion()); - } - - @Override - public void tearDown() throws Exception { - Providers.setMaximumAllowableApiLevelForBcDeprecation( - Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); - super.tearDown(); - } + @Rule + public TestRule enableDeprecatedBCAlgorithmsRule = + EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); /* * Following certificate chain was taken from https://www.verisign.com and diff --git a/luni/src/test/java9language/Android.bp b/luni/src/test/java9language/Android.bp new file mode 100644 index 0000000000..dddc18492f --- /dev/null +++ b/luni/src/test/java9language/Android.bp @@ -0,0 +1,74 @@ +// 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. + +// Android tests related to Java 9 language features. + +// Use jarjar to repackage Java9LanguageFeatures, to be used in tests below. +java_library { + name: "core-java-9-language-features-repackaged-for-test", + hostdex: true, + + srcs: [":core-java-9-language-features-source"], + jarjar_rules: "jarjar_rules_java9_language_features.txt", + java_version: "1.9", + + sdk_version: "none", + system_modules: "core-all-system-modules", + patch_module: "java.base", + + visibility: ["//visibility:private"], +} + +// Generate a clone of Java9LanguageFeaturesTest which uses a version of +// Java9LanguageFeatures repackaged by jarjar. This ensures that jarjar is able +// to handle a class file which must be at least v53 and includes bytecode +// compiled from Java 9 language features. +filegroup { + name: "core-rewrite-test-for-jarjar-sed-script", + srcs: ["rewrite-test-for-jarjar.sed"], + visibility: ["//visibility:private"], +} + +filegroup { + name: "core-java-9-language-features-test-src", + srcs: ["java/libcore/libcore/internal/Java9LanguageFeaturesTest.java"], + visibility: ["//visibility:private"], +} + +genrule { + name: "core-gen-test-repackaged-java-9-language-features", + srcs: [ + ":core-rewrite-test-for-jarjar-sed-script", + ":core-java-9-language-features-test-src", + ], + out: ["libcore/libcore/internal/Java9LanguageFeaturesJarjarTest.java"], + cmd: "sed -r -f $(location :core-rewrite-test-for-jarjar-sed-script) $(location :core-java-9-language-features-test-src) > $(out)", + visibility: ["//visibility:private"], +} + +java_library { + name: "core-java-9-language-tests", + hostdex: true, + srcs: [ + "java/**/*.java", + ":core-gen-test-repackaged-java-9-language-features", + ], + sdk_version: "none", + system_modules: "core-all-system-modules", + static_libs: [ + "core-java-9-language-features-repackaged-for-test", + "junit", + ], + visibility: ["//libcore"], +} diff --git a/luni/src/test/java9language/jarjar_rules_java9_language_features.txt b/luni/src/test/java9language/jarjar_rules_java9_language_features.txt new file mode 100644 index 0000000000..dee72bc8dc --- /dev/null +++ b/luni/src/test/java9language/jarjar_rules_java9_language_features.txt @@ -0,0 +1 @@ +rule libcore.internal.** libcore.internal.repackaged.@1 diff --git a/luni/src/test/java/libcore/libcore/internal/Java9LanguageFeaturesTest.java b/luni/src/test/java9language/java/libcore/libcore/internal/Java9LanguageFeaturesTest.java index cc48ec07a0..cc48ec07a0 100644 --- a/luni/src/test/java/libcore/libcore/internal/Java9LanguageFeaturesTest.java +++ b/luni/src/test/java9language/java/libcore/libcore/internal/Java9LanguageFeaturesTest.java diff --git a/ojluni/Android.mk b/luni/src/test/java9language/rewrite-test-for-jarjar.sed index 8eef8b5330..525a14ab76 100644 --- a/ojluni/Android.mk +++ b/luni/src/test/java9language/rewrite-test-for-jarjar.sed @@ -1,5 +1,4 @@ -# -*- mode: makefile -*- -# Copyright (C) 2016 The Android Open Source Project +# 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. @@ -13,9 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -LOCAL_PATH := $(call my-dir) +# This is a sed script that modifies Java source code in two ways. -include $(CLEAR_VARS) -LOCAL_MODULE := ojluni-phony -include $(BUILD_PHONY_PACKAGE) +# Replace libcore.internal with libcore.internal.repackaged in imports: +s/import libcore.internal/import libcore.internal.repackaged/ +# Replace Test with JarjarTest in class declarations. +s/class ([A-Za-z0-9_]+)Test/class \1JarjarTest/ diff --git a/luni/src/test/native/libcore_java_lang_ThreadTest.cpp b/luni/src/test/native/libcore_java_lang_ThreadTest.cpp index f9426072d1..a20ff483e2 100644 --- a/luni/src/test/native/libcore_java_lang_ThreadTest.cpp +++ b/luni/src/test/native/libcore_java_lang_ThreadTest.cpp @@ -71,7 +71,9 @@ static void* TestThreadNaming(void* arg) { if (javaVm->DetachCurrentThread() != JNI_OK) { - exception_message = new std::string("Detach failed"); + if (exception_message == nullptr) { + exception_message = new std::string("Detach failed"); + } } return exception_message; diff --git a/luni/src/test/native/libcore_libcore_util_NativeAllocationRegistryTest.cpp b/luni/src/test/native/libcore_libcore_util_NativeAllocationRegistryTest.cpp index 62982f4dda..b9011897f9 100644 --- a/luni/src/test/native/libcore_libcore_util_NativeAllocationRegistryTest.cpp +++ b/luni/src/test/native/libcore_libcore_util_NativeAllocationRegistryTest.cpp @@ -18,6 +18,7 @@ #include <stdio.h> #include <string.h> +#include <atomic> #include <string> #include <jni.h> @@ -69,7 +70,7 @@ jboolean Java_libcore_libcore_util_NativeAllocationRegistryTest_isNativeBridgedA return static_cast<jboolean>(is_native_bridged_abi); } -uint64_t gNumNativeBytesAllocated = 0; +std::atomic<uint64_t> gNumNativeBytesAllocated = 0; static void finalize(uint64_t* ptr) { gNumNativeBytesAllocated -= *ptr; diff --git a/luni/src/test/parameter_metadata/Android.bp b/luni/src/test/parameter_metadata/Android.bp new file mode 100644 index 0000000000..0eec841d8e --- /dev/null +++ b/luni/src/test/parameter_metadata/Android.bp @@ -0,0 +1,34 @@ +// 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. + +// Contains classes for testing access to parameter information via reflection. +// +// This is a separate library so it can use the -parameters javac flag (to add parameter information +// to the class files) without affecting other tests. +// +// Included as a resource by //libcore:core-tests and loaded into its own +// class loader by libcore.java.lang.reflect.ParameterTest. +java_library { + name: "parameter-metadata-test", + visibility: [ + "//libcore", + ], + compile_dex: true, + srcs: ["src/**/*.java"], + sdk_version: "core_platform", + javacflags: ["-parameters"], + errorprone: { + javacflags: ["-Xep:MissingOverride:OFF"], + }, +} diff --git a/metrictests/memory/README b/metrictests/memory/README index 77574efba4..e0b083b4f0 100644 --- a/metrictests/memory/README +++ b/metrictests/memory/README @@ -27,7 +27,7 @@ This instrumentation dumps a heap, performs some configurable action (see the co then dumps another heap. You can run it manually as follows: make LibcoreHeapDumper - adb install -g -r ${ANDROID_PRODUCT_OUT}/data/app/LibcoreHeapDumper/LibcoreHeapDumper.apk + adb install -g -r ${ANDROID_PRODUCT_OUT}/testcases/LibcoreHeapDumper/arm64/LibcoreHeapDumper.apk DEVICE_EXTERNAL_STORAGE=$(adb shell 'echo -n ${EXTERNAL_STORAGE}') # Pick a suitable name here: diff --git a/metrictests/memory/apps/AndroidManifest.xml b/metrictests/memory/apps/AndroidManifest.xml index a8856aa4be..aca7177759 100644 --- a/metrictests/memory/apps/AndroidManifest.xml +++ b/metrictests/memory/apps/AndroidManifest.xml @@ -18,7 +18,9 @@ package="libcore.heapdumper"> <uses-sdk android:minSdkVersion="19" /> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" /> <instrumentation android:name="libcore.heapdumper.HeapDumpInstrumentation" @@ -30,6 +32,7 @@ <application android:allowBackup="false" + android:requestLegacyExternalStorage="true" android:label="@string/libcore_heap_dumper_title"> </application> </manifest> diff --git a/metrictests/memory/apps/src/libcore/heapdumper/Actions.java b/metrictests/memory/apps/src/libcore/heapdumper/Actions.java index e8b56f1894..e5ef4bab75 100644 --- a/metrictests/memory/apps/src/libcore/heapdumper/Actions.java +++ b/metrictests/memory/apps/src/libcore/heapdumper/Actions.java @@ -19,6 +19,8 @@ package libcore.heapdumper; import java.text.Collator; import java.util.Arrays; import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * An enumeration of actions for which we'd like to measure the effect on the post-GC heap. @@ -65,6 +67,33 @@ enum Actions implements Runnable { } }, + REGEX { + @Override + public void run() { + final String sequence = "foo 123 bar baz"; + Pattern p = Pattern.compile("foo (\\d+) bar (\\w+)"); + Matcher m = p.matcher(sequence); + + boolean found = m.find(); + boolean matches = m.matches(); + int groups = m.groupCount(); + String first = m.group(1); + String second = m.group(2); + boolean hitEnd = m.hitEnd(); + + // Set region to prefix of the original sequence + m.region(0, "foo 123".length()); + boolean matchesPrefix = m.lookingAt(); + boolean requireEnd = m.requireEnd(); + + m.useTransparentBounds(true); + boolean matchesPrefixTransparentBounds = m.lookingAt(); + + m.useAnchoringBounds(true); + boolean matchesPrefixAnchoringBounds = m.lookingAt(); + } + } + ; private static void useCollatorForLocale(Locale locale) { diff --git a/metrictests/memory/host/Android.bp b/metrictests/memory/host/Android.bp index a70afc6f95..beed9e13db 100644 --- a/metrictests/memory/host/Android.bp +++ b/metrictests/memory/host/Android.bp @@ -15,7 +15,7 @@ java_test_host { name: "libcore-memory-metrics-tests", srcs: ["src/**/*.java"], - libs: [ + static_libs: [ "tradefed", "ahat", ], diff --git a/metrictests/memory/host/src/libcore/heapmetrics/LibcoreHeapMetricsTest.java b/metrictests/memory/host/src/libcore/heapmetrics/LibcoreHeapMetricsTest.java index 5340d9050d..22316145b2 100644 --- a/metrictests/memory/host/src/libcore/heapmetrics/LibcoreHeapMetricsTest.java +++ b/metrictests/memory/host/src/libcore/heapmetrics/LibcoreHeapMetricsTest.java @@ -103,6 +103,12 @@ public class LibcoreHeapMetricsTest implements IDeviceTest { recordBeforeAndAfterAppHeapMetrics(result.getBeforeDump(), result.getAfterDump()); } + @Test + public void measureRegexes() throws Exception { + MetricsRunner.Result result = metricsRunner.runAllInstrumentations("REGEX"); + recordBeforeAndAfterAppHeapMetrics(result.getBeforeDump(), result.getAfterDump()); + } + private void recordHeapMetrics(AhatSnapshot dump, String metricPrefix, String heapName) { AhatHeap heap = dump.getHeap(heapName); recordSizeMetric(metricPrefix, heap.getSize()); diff --git a/metrictests/memory/host/src/libcore/heapmetrics/MetricsRunner.java b/metrictests/memory/host/src/libcore/heapmetrics/MetricsRunner.java index c3f9e0df38..e96bc72c6e 100644 --- a/metrictests/memory/host/src/libcore/heapmetrics/MetricsRunner.java +++ b/metrictests/memory/host/src/libcore/heapmetrics/MetricsRunner.java @@ -30,8 +30,7 @@ import com.android.tradefed.util.FileUtil; import java.io.File; import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.time.Instant; /** * Helper class that runs the metric instrumentations on a test device. @@ -243,10 +242,14 @@ class MetricsRunner { } } + /** + * Returns the ISO 8601 form of the current time in UTC, for use as a timestamp in filenames. + * (Note that using UTC avoids an issue where the timezone indicator includes a + sign for the + * offset, which triggers an issue with URL encoding in tradefed, which causes the calls to + * {@code testDevice.pullFile()} to fail. See b/149018916.) + */ private static String getCurrentTimeIso8601() { - SimpleDateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); - Date now = new Date(); - return iso8601Format.format(now); + return Instant.now().toString(); } /** diff --git a/mmodules/core_platform_api/Android.bp b/mmodules/core_platform_api/Android.bp index 42105977dc..f2a042b4cf 100644 --- a/mmodules/core_platform_api/Android.bp +++ b/mmodules/core_platform_api/Android.bp @@ -12,21 +12,31 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Build rules for the APIs that various core libraries provide to other parts -// of the Android software stack: these include the public SDK APIs plus some -// "core platform APIs" that only the Android software stack can use. - -// Generates stub source files for the {public SDK + core platform} API of the -// core jars. +// Generates stub source files for the core platform API of the ART module. +// i.e. every class/member that is either in the public API or annotated with +// @CorePlatformApi. +// +// The API specification .txt files managed by this only contain the additional +// classes/members that are in the intra-core API but which are not in the public +// API. droidstubs { - name: "core-platform-api-stubs", - srcs: [":core_api_files"], - no_standard_libs: true, + name: "art-module-platform-api-stubs-source", + srcs: [ + ":art_module_api_files", + ], + sdk_version: "none", + system_modules: "none", + libs: [ + // Needed to break the cycle in the platform api caused by + // b/141747409. + "i18n.module.intra.core.api.stubs", + ], installable: false, - args: "--hide-annotation libcore.api.Hide " - + "--show-single-annotation libcore.api.CorePlatformApi " - + "--skip-annotation-instance-methods=false ", + args: "--hide HiddenSuperclass " + + "--hide-annotation libcore.api.Hide " + + "--show-single-annotation libcore.api.CorePlatformApi " + + "--skip-annotation-instance-methods=false ", merge_inclusion_annotations_dirs: ["ojluni-annotated-mmodule-stubs"], api_filename: "api.txt", @@ -45,7 +55,52 @@ droidstubs { }, } -// A library containing the {public SDK + core platform} API stubs for the core jars. +// A special set of system modules that is needed to break the cycle in the +// platform api caused by b/141747409. +java_system_modules { + name: "break-cycle-in-core-platform-system-modules", + libs: [ + "art.module.intra.core.api.stubs", + "i18n.module.intra.core.api.stubs", + ], +} + +// A library containing the core platform API stubs of the ART module. +// +// Core platform APIs are only intended for use of other parts of the platform, not the +// core library modules. +java_library { + name: "art.module.platform.api.stubs", + srcs: [ + ":art-module-platform-api-stubs-source", + ], + hostdex: true, + + sdk_version: "none", + system_modules: "break-cycle-in-core-platform-system-modules", + patch_module: "java.base", +} + +// Used when compiling higher-level code against core.platform.api.stubs. +java_system_modules { + name: "art-module-platform-api-stubs-system-modules", + visibility: [ + "//art/build/sdk", + "//external/conscrypt", + "//external/icu/android_icu4j", + "//external/wycheproof", + ], + libs: [ + "art.module.platform.api.stubs", + ], +} + +// Ideally this should be a restricted whitelist but there are hundreds of modules that depend on +// this. +// TODO(http://b/134561230) - limit the number of dependents on this. +core_platform_visibility = ["//visibility:public"] + +// A library containing the core platform API stubs for the core libraries. // // Although this stubs library is primarily used by the Java compiler / build to indicate // the core platform API surface area, compile_dex: true is used so that the Core Platform @@ -53,23 +108,33 @@ droidstubs { // accessibility. b/119068555 java_library { name: "core.platform.api.stubs", - srcs: [":core-platform-api-stubs"], + visibility: core_platform_visibility, hostdex: true, compile_dex: true, - no_standard_libs: true, + sdk_version: "none", system_modules: "none", + static_libs: [ + "art.module.platform.api.stubs", + "conscrypt.module.platform.api.stubs", + "i18n.module.platform.api.stubs", + ], patch_module: "java.base", } // Used when compiling higher-level code against core.platform.api.stubs. java_system_modules { name: "core-platform-api-stubs-system-modules", + visibility: core_platform_visibility, libs: [ "core.platform.api.stubs", // This one is not on device but it's needed when javac compiles code // containing lambdas. "core-lambda-stubs-for-system-modules", + // This one is not on device but it's needed when javac compiles code + // containing @Generated annotations produced by some code generation + // tools. + // See http://b/123891440. + "core-generated-annotation-stubs", ], } - diff --git a/mmodules/core_platform_api/api/platform/current-api.txt b/mmodules/core_platform_api/api/platform/current-api.txt index b2b81df415..15a0a48d8c 100644 --- a/mmodules/core_platform_api/api/platform/current-api.txt +++ b/mmodules/core_platform_api/api/platform/current-api.txt @@ -1,88 +1,42 @@ // Signature format: 2.0 -package android.icu.impl { +package android.compat { - public class CalendarAstronomer { - ctor public CalendarAstronomer(double, double); - method public long getSunRiseSet(boolean); - method public void setTime(long); + public final class Compatibility { + method public static void clearOverrides(); + method public static boolean isChangeEnabled(long); + method public static void reportChange(long); + method public static void setCallbacks(android.compat.Compatibility.Callbacks); + method public static void setOverrides(android.compat.Compatibility.ChangeConfig); } - public class TimeZoneAdapter extends java.util.TimeZone { - method public static java.util.TimeZone wrap(android.icu.util.TimeZone); + public static class Compatibility.Callbacks { + ctor protected Compatibility.Callbacks(); + method protected boolean isChangeEnabled(long); + method protected void reportChange(long); } -} - -package android.icu.text { - - public final class StringPrep { - method public static android.icu.text.StringPrep getInstance(int); - method public String prepare(String, int) throws android.icu.text.StringPrepParseException; - field public static final int DEFAULT = 0; // 0x0 - field public static final int RFC3920_RESOURCEPREP = 8; // 0x8 - } - - public class StringPrepParseException extends java.text.ParseException { - ctor public StringPrepParseException(String, int); - ctor public StringPrepParseException(String, int, String, int); - ctor public StringPrepParseException(String, int, String, int, int); - method public int getError(); - field public static final int ACE_PREFIX_ERROR = 6; // 0x6 - field public static final int BUFFER_OVERFLOW_ERROR = 9; // 0x9 - field public static final int CHECK_BIDI_ERROR = 4; // 0x4 - field public static final int DOMAIN_NAME_TOO_LONG_ERROR = 11; // 0xb - field public static final int ILLEGAL_CHAR_FOUND = 1; // 0x1 - field public static final int INVALID_CHAR_FOUND = 0; // 0x0 - field public static final int LABEL_TOO_LONG_ERROR = 8; // 0x8 - field public static final int PROHIBITED_ERROR = 2; // 0x2 - field public static final int STD3_ASCII_RULES_ERROR = 5; // 0x5 - field public static final int UNASSIGNED_ERROR = 3; // 0x3 - field public static final int VERIFICATION_ERROR = 7; // 0x7 - field public static final int ZERO_LENGTH_LABEL = 10; // 0xa - } - -} - -package android.icu.util { - - public abstract class BasicTimeZone extends android.icu.util.TimeZone { - method public abstract android.icu.util.TimeZoneTransition getNextTransition(long, boolean); - } - - public class Region implements java.lang.Comparable<android.icu.util.Region> { - method public static java.util.Set<android.icu.util.Region> getAvailable(android.icu.util.Region.RegionType); - } - - public enum Region.RegionType { - enum_constant public static final android.icu.util.Region.RegionType TERRITORY; - } - - public abstract class TimeZoneRule implements java.io.Serializable { - method public int getDSTSavings(); - } - - public class TimeZoneTransition { - method public android.icu.util.TimeZoneRule getFrom(); - method public long getTime(); - method public android.icu.util.TimeZoneRule getTo(); + public static final class Compatibility.ChangeConfig { + ctor public Compatibility.ChangeConfig(java.util.Set<java.lang.Long>, java.util.Set<java.lang.Long>); + method public long[] forceDisabledChangesArray(); + method public java.util.Set<java.lang.Long> forceDisabledSet(); + method public long[] forceEnabledChangesArray(); + method public java.util.Set<java.lang.Long> forceEnabledSet(); + method public boolean isEmpty(); + method public boolean isForceDisabled(long); + method public boolean isForceEnabled(long); } } package android.system { - public final class ErrnoException extends java.lang.Exception { - method public java.io.IOException rethrowAsIOException() throws java.io.IOException; - method public java.net.SocketException rethrowAsSocketException() throws java.net.SocketException; - } - public class Int32Ref { ctor public Int32Ref(int); - field @dalvik.annotation.compat.UnsupportedAppUsage public int value; + field public int value; } public final class NetlinkSocketAddress extends java.net.SocketAddress { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public NetlinkSocketAddress(int, int); + ctor public NetlinkSocketAddress(int, int); method public int getGroupsMask(); method public int getPortId(); } @@ -90,7 +44,6 @@ package android.system { public final class Os { method public static android.system.StructCapUserData[] capget(android.system.StructCapUserHeader) throws android.system.ErrnoException; method public static void capset(android.system.StructCapUserHeader, android.system.StructCapUserData[]) throws android.system.ErrnoException; - method public static int fcntlInt(java.io.FileDescriptor, int, int) throws android.system.ErrnoException; method public static int getpgid(int) throws android.system.ErrnoException; method public static android.system.StructRlimit getrlimit(int) throws android.system.ErrnoException; method public static int getsockoptInt(java.io.FileDescriptor, int, int) throws android.system.ErrnoException; @@ -101,36 +54,35 @@ package android.system { method public static void setpgid(int, int) throws android.system.ErrnoException; method public static void setregid(int, int) throws android.system.ErrnoException; method public static void setreuid(int, int) throws android.system.ErrnoException; - method @dalvik.annotation.compat.UnsupportedAppUsage public static void setsockoptIfreq(java.io.FileDescriptor, int, int, String) throws android.system.ErrnoException; + method public static void setsockoptIfreq(java.io.FileDescriptor, int, int, String) throws android.system.ErrnoException; method public static void setsockoptLinger(java.io.FileDescriptor, int, int, android.system.StructLinger) throws android.system.ErrnoException; method public static long splice(java.io.FileDescriptor, android.system.Int64Ref, java.io.FileDescriptor, android.system.Int64Ref, long, int) throws android.system.ErrnoException; method public static void unlink(String) throws android.system.ErrnoException; } public final class OsConstants { - method @dalvik.annotation.compat.UnsupportedAppUsage public static int CAP_TO_INDEX(int); - method @dalvik.annotation.compat.UnsupportedAppUsage public static int CAP_TO_MASK(int); - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int ENONET; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int EUSERS; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int MAP_POPULATE; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int NETLINK_NETFILTER; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int O_DIRECT; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int PR_CAP_AMBIENT; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int PR_CAP_AMBIENT_RAISE; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int RLIMIT_NOFILE; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int RTMGRP_IPV4_IFADDR; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int SPLICE_F_MORE; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int SPLICE_F_MOVE; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int TIOCOUTQ; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int UDP_ENCAP; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int UDP_ENCAP_ESPINUDP; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int XATTR_CREATE; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int _LINUX_CAPABILITY_VERSION_3; + method public static int CAP_TO_INDEX(int); + method public static int CAP_TO_MASK(int); + field public static final int ARPHRD_LOOPBACK; + field public static final int ENONET; + field public static final int EUSERS; + field public static final int MAP_POPULATE; + field public static final int O_DIRECT; + field public static final int PR_CAP_AMBIENT; + field public static final int PR_CAP_AMBIENT_RAISE; + field public static final int RLIMIT_NOFILE; + field public static final int RTMGRP_IPV4_IFADDR; + field public static final int SPLICE_F_MORE; + field public static final int SPLICE_F_MOVE; + field public static final int TIOCOUTQ; + field public static final int UDP_ENCAP; + field public static final int UDP_ENCAP_ESPINUDP; + field public static final int XATTR_CREATE; + field public static final int _LINUX_CAPABILITY_VERSION_3; } public final class PacketSocketAddress extends java.net.SocketAddress { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public PacketSocketAddress(short, int); - ctor @dalvik.annotation.compat.UnsupportedAppUsage public PacketSocketAddress(int, byte[]); + ctor public PacketSocketAddress(int, int, byte[]); } public final class StructCapUserData { @@ -208,18 +160,18 @@ package com.android.org.bouncycastle.asn1 { } public class ASN1EncodableVector { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public ASN1EncodableVector(); - method @dalvik.annotation.compat.UnsupportedAppUsage public void add(com.android.org.bouncycastle.asn1.ASN1Encodable); + ctor public ASN1EncodableVector(); + method public void add(com.android.org.bouncycastle.asn1.ASN1Encodable); } public class ASN1InputStream extends java.io.FilterInputStream { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public ASN1InputStream(java.io.InputStream); - ctor @dalvik.annotation.compat.UnsupportedAppUsage public ASN1InputStream(byte[]); - method @dalvik.annotation.compat.UnsupportedAppUsage public com.android.org.bouncycastle.asn1.ASN1Primitive readObject() throws java.io.IOException; + ctor public ASN1InputStream(java.io.InputStream); + ctor public ASN1InputStream(byte[]); + method public com.android.org.bouncycastle.asn1.ASN1Primitive readObject() throws java.io.IOException; } public class ASN1Integer extends com.android.org.bouncycastle.asn1.ASN1Primitive { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public ASN1Integer(java.math.BigInteger); + ctor public ASN1Integer(java.math.BigInteger); } public abstract class ASN1Null extends com.android.org.bouncycastle.asn1.ASN1Primitive { @@ -256,24 +208,24 @@ package com.android.org.bouncycastle.asn1 { } public class DERBitString extends com.android.org.bouncycastle.asn1.ASN1BitString { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public DERBitString(byte[]); + ctor public DERBitString(byte[]); } @Deprecated public class DERInteger extends com.android.org.bouncycastle.asn1.ASN1Integer { - ctor @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public DERInteger(long); + ctor @Deprecated public DERInteger(long); } public class DERNull extends com.android.org.bouncycastle.asn1.ASN1Null { - field @dalvik.annotation.compat.UnsupportedAppUsage public static final com.android.org.bouncycastle.asn1.DERNull INSTANCE; + field public static final com.android.org.bouncycastle.asn1.DERNull INSTANCE; } public class DEROctetString extends com.android.org.bouncycastle.asn1.ASN1OctetString { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public DEROctetString(byte[]); + ctor public DEROctetString(byte[]); } public class DERSequence extends com.android.org.bouncycastle.asn1.ASN1Sequence { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public DERSequence(); - ctor @dalvik.annotation.compat.UnsupportedAppUsage public DERSequence(com.android.org.bouncycastle.asn1.ASN1EncodableVector); + ctor public DERSequence(); + ctor public DERSequence(com.android.org.bouncycastle.asn1.ASN1EncodableVector); } public class DERTaggedObject extends com.android.org.bouncycastle.asn1.ASN1TaggedObject { @@ -290,7 +242,7 @@ package com.android.org.bouncycastle.asn1 { package com.android.org.bouncycastle.asn1.pkcs { public interface PKCSObjectIdentifiers { - field @dalvik.annotation.compat.UnsupportedAppUsage public static final com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier sha256WithRSAEncryption; + field public static final com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier sha256WithRSAEncryption; field public static final com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier sha512WithRSAEncryption; } @@ -321,8 +273,8 @@ package com.android.org.bouncycastle.asn1.x500.style { package com.android.org.bouncycastle.asn1.x509 { public class AlgorithmIdentifier extends com.android.org.bouncycastle.asn1.ASN1Object { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public AlgorithmIdentifier(com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier); - ctor @dalvik.annotation.compat.UnsupportedAppUsage public AlgorithmIdentifier(com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier, com.android.org.bouncycastle.asn1.ASN1Encodable); + ctor public AlgorithmIdentifier(com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier); + ctor public AlgorithmIdentifier(com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier, com.android.org.bouncycastle.asn1.ASN1Encodable); method public com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier getAlgorithm(); } @@ -332,7 +284,7 @@ package com.android.org.bouncycastle.asn1.x509 { } public class Certificate extends com.android.org.bouncycastle.asn1.ASN1Object { - method @dalvik.annotation.compat.UnsupportedAppUsage public static com.android.org.bouncycastle.asn1.x509.Certificate getInstance(Object); + method public static com.android.org.bouncycastle.asn1.x509.Certificate getInstance(Object); } public class GeneralName extends com.android.org.bouncycastle.asn1.ASN1Object { @@ -345,35 +297,35 @@ package com.android.org.bouncycastle.asn1.x509 { } public class SubjectPublicKeyInfo extends com.android.org.bouncycastle.asn1.ASN1Object { - method @dalvik.annotation.compat.UnsupportedAppUsage public static com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo getInstance(Object); + method public static com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo getInstance(Object); } public class TBSCertificate extends com.android.org.bouncycastle.asn1.ASN1Object { } public class Time extends com.android.org.bouncycastle.asn1.ASN1Object { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public Time(java.util.Date); + ctor public Time(java.util.Date); } public class V3TBSCertificateGenerator { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public V3TBSCertificateGenerator(); - method @dalvik.annotation.compat.UnsupportedAppUsage public com.android.org.bouncycastle.asn1.x509.TBSCertificate generateTBSCertificate(); - method @dalvik.annotation.compat.UnsupportedAppUsage public void setEndDate(com.android.org.bouncycastle.asn1.x509.Time); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public void setIssuer(com.android.org.bouncycastle.asn1.x509.X509Name); - method @dalvik.annotation.compat.UnsupportedAppUsage public void setSerialNumber(com.android.org.bouncycastle.asn1.ASN1Integer); - method @dalvik.annotation.compat.UnsupportedAppUsage public void setSignature(com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier); - method @dalvik.annotation.compat.UnsupportedAppUsage public void setStartDate(com.android.org.bouncycastle.asn1.x509.Time); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public void setSubject(com.android.org.bouncycastle.asn1.x509.X509Name); - method @dalvik.annotation.compat.UnsupportedAppUsage public void setSubjectPublicKeyInfo(com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo); + ctor public V3TBSCertificateGenerator(); + method public com.android.org.bouncycastle.asn1.x509.TBSCertificate generateTBSCertificate(); + method public void setEndDate(com.android.org.bouncycastle.asn1.x509.Time); + method @Deprecated public void setIssuer(com.android.org.bouncycastle.asn1.x509.X509Name); + method public void setSerialNumber(com.android.org.bouncycastle.asn1.ASN1Integer); + method public void setSignature(com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier); + method public void setStartDate(com.android.org.bouncycastle.asn1.x509.Time); + method @Deprecated public void setSubject(com.android.org.bouncycastle.asn1.x509.X509Name); + method public void setSubjectPublicKeyInfo(com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo); } @Deprecated public class X509Name extends com.android.org.bouncycastle.asn1.ASN1Object { - ctor @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public X509Name(String); + ctor @Deprecated public X509Name(String); method @Deprecated public static com.android.org.bouncycastle.asn1.x509.X509Name getInstance(Object); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public java.util.Vector getOIDs(); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public java.util.Vector getValues(); + method @Deprecated public java.util.Vector getOIDs(); + method @Deprecated public java.util.Vector getValues(); method @Deprecated public String toString(boolean, java.util.Hashtable); - field @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public static final com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier CN; + field @Deprecated public static final com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier CN; field @Deprecated public static final java.util.Hashtable DefaultSymbols; field @Deprecated public static final com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier O; field @Deprecated public static final com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier OU; @@ -384,7 +336,7 @@ package com.android.org.bouncycastle.asn1.x509 { package com.android.org.bouncycastle.asn1.x9 { public interface X9ObjectIdentifiers { - field @dalvik.annotation.compat.UnsupportedAppUsage public static final com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier ecdsa_with_SHA256; + field public static final com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier ecdsa_with_SHA256; } } @@ -401,6 +353,28 @@ package com.android.org.bouncycastle.crypto { } +package com.android.org.bouncycastle.crypto.digests { + + public abstract class GeneralDigest { + method public void finish(); + method protected abstract void processBlock(); + method public void update(byte[], int, int); + } + + public class MD4Digest extends com.android.org.bouncycastle.crypto.digests.GeneralDigest { + ctor public MD4Digest(); + method public int doFinal(byte[], int); + method protected void processBlock(); + } + + public class SHA1Digest extends com.android.org.bouncycastle.crypto.digests.GeneralDigest { + ctor public SHA1Digest(); + method public int doFinal(byte[], int); + method protected void processBlock(); + } + +} + package com.android.org.bouncycastle.crypto.generators { public class OpenSSLPBEParametersGenerator extends com.android.org.bouncycastle.crypto.PBEParametersGenerator { @@ -430,7 +404,7 @@ package com.android.org.bouncycastle.jcajce.util { package com.android.org.bouncycastle.jce { @Deprecated public class X509Principal extends com.android.org.bouncycastle.asn1.x509.X509Name implements java.security.Principal { - ctor @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public X509Principal(byte[]) throws java.io.IOException; + ctor @Deprecated public X509Principal(byte[]) throws java.io.IOException; ctor @Deprecated public X509Principal(java.util.Vector, java.util.Hashtable); method public byte[] getEncoded(); } @@ -440,11 +414,11 @@ package com.android.org.bouncycastle.jce { package com.android.org.bouncycastle.jce.provider { public final class BouncyCastleProvider extends java.security.Provider { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public BouncyCastleProvider(); + ctor public BouncyCastleProvider(); } @Deprecated public class X509CertificateObject extends java.security.cert.X509Certificate { - ctor @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public X509CertificateObject(com.android.org.bouncycastle.asn1.x509.Certificate) throws java.security.cert.CertificateParsingException; + ctor @Deprecated public X509CertificateObject(com.android.org.bouncycastle.asn1.x509.Certificate) throws java.security.cert.CertificateParsingException; } } @@ -499,129 +473,38 @@ package com.android.org.bouncycastle.x509 { } @Deprecated public class X509V3CertificateGenerator { - ctor @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public X509V3CertificateGenerator(); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public java.security.cert.X509Certificate generate(java.security.PrivateKey) throws java.security.cert.CertificateEncodingException, java.lang.IllegalStateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.SignatureException; - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public void setIssuerDN(javax.security.auth.x500.X500Principal); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public void setNotAfter(java.util.Date); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public void setNotBefore(java.util.Date); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public void setPublicKey(java.security.PublicKey) throws java.lang.IllegalArgumentException; - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public void setSerialNumber(java.math.BigInteger); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public void setSignatureAlgorithm(String); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public void setSubjectDN(javax.security.auth.x500.X500Principal); + ctor @Deprecated public X509V3CertificateGenerator(); + method @Deprecated public java.security.cert.X509Certificate generate(java.security.PrivateKey) throws java.security.cert.CertificateEncodingException, java.lang.IllegalStateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.SignatureException; + method @Deprecated public void setIssuerDN(javax.security.auth.x500.X500Principal); + method @Deprecated public void setNotAfter(java.util.Date); + method @Deprecated public void setNotBefore(java.util.Date); + method @Deprecated public void setPublicKey(java.security.PublicKey) throws java.lang.IllegalArgumentException; + method @Deprecated public void setSerialNumber(java.math.BigInteger); + method @Deprecated public void setSignatureAlgorithm(String); + method @Deprecated public void setSubjectDN(javax.security.auth.x500.X500Principal); } } -package com.android.org.conscrypt { - - public interface CertPinManager { - } - - public final class ClientSessionContext implements javax.net.ssl.SSLSessionContext { - method public final java.util.Enumeration<byte[]> getIds(); - method public final javax.net.ssl.SSLSession getSession(byte[]); - method public final int getSessionCacheSize(); - method public final int getSessionTimeout(); - method @dalvik.annotation.compat.UnsupportedAppUsage public void setPersistentCache(com.android.org.conscrypt.SSLClientSessionCache); - method public final void setSessionCacheSize(int) throws java.lang.IllegalArgumentException; - method public final void setSessionTimeout(int) throws java.lang.IllegalArgumentException; - } - - public final class Conscrypt { - method public static javax.net.ssl.X509TrustManager getDefaultX509TrustManager() throws java.security.KeyManagementException; - } - - public interface ConscryptCertStore { - } - - public final class FileClientSessionCache { - method @dalvik.annotation.compat.UnsupportedAppUsage public static com.android.org.conscrypt.SSLClientSessionCache usingDirectory(java.io.File) throws java.io.IOException; - } - - public final class OpenSSLProvider extends java.security.Provider { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public OpenSSLProvider(); - } - - public abstract class OpenSSLSocketImpl extends javax.net.ssl.SSLSocket { - method public void addHandshakeCompletedListener(javax.net.ssl.HandshakeCompletedListener); - method public final void connect(java.net.SocketAddress) throws java.io.IOException; - method public final void connect(java.net.SocketAddress, int) throws java.io.IOException; - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public final byte[] getAlpnSelectedProtocol(); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public final byte[] getNpnSelectedProtocol(); - method public final int getPort(); - method public final int getSoTimeout() throws java.net.SocketException; - method public void removeHandshakeCompletedListener(javax.net.ssl.HandshakeCompletedListener); - method public final void sendUrgentData(int) throws java.io.IOException; - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public final void setAlpnProtocols(byte[]); - method @dalvik.annotation.compat.UnsupportedAppUsage public abstract void setChannelIdPrivateKey(java.security.PrivateKey); - method @dalvik.annotation.compat.UnsupportedAppUsage public void setHandshakeTimeout(int) throws java.net.SocketException; - method @dalvik.annotation.compat.UnsupportedAppUsage public void setHostname(String); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public final void setNpnProtocols(byte[]); - method public final void setOOBInline(boolean) throws java.net.SocketException; - method public final void setSoTimeout(int) throws java.net.SocketException; - method @dalvik.annotation.compat.UnsupportedAppUsage public void setSoWriteTimeout(int) throws java.net.SocketException; - method @dalvik.annotation.compat.UnsupportedAppUsage public abstract void setUseSessionTickets(boolean); - } +package dalvik.annotation.codegen { - public interface SSLClientSessionCache { + @java.lang.annotation.Repeatable(CovariantReturnType.CovariantReturnTypes.class) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) public @interface CovariantReturnType { + method public abstract int presentAfter(); + method public abstract Class<?> returnType(); } - public final class TrustManagerImpl extends javax.net.ssl.X509ExtendedTrustManager { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public TrustManagerImpl(java.security.KeyStore); - ctor public TrustManagerImpl(java.security.KeyStore, com.android.org.conscrypt.CertPinManager, com.android.org.conscrypt.ConscryptCertStore); - method public void checkClientTrusted(java.security.cert.X509Certificate[], String) throws java.security.cert.CertificateException; - method public void checkClientTrusted(java.security.cert.X509Certificate[], String, java.net.Socket) throws java.security.cert.CertificateException; - method public void checkClientTrusted(java.security.cert.X509Certificate[], String, javax.net.ssl.SSLEngine) throws java.security.cert.CertificateException; - method @dalvik.annotation.compat.UnsupportedAppUsage public java.util.List<java.security.cert.X509Certificate> checkServerTrusted(java.security.cert.X509Certificate[], String, String) throws java.security.cert.CertificateException; - method public java.util.List<java.security.cert.X509Certificate> getTrustedChainForServer(java.security.cert.X509Certificate[], String, java.net.Socket) throws java.security.cert.CertificateException; - method public java.util.List<java.security.cert.X509Certificate> getTrustedChainForServer(java.security.cert.X509Certificate[], String, javax.net.ssl.SSLEngine) throws java.security.cert.CertificateException; - method public void handleTrustStorageUpdate(); - } - - public final class TrustedCertificateIndex { - ctor public TrustedCertificateIndex(); - method public java.util.Set<java.security.cert.TrustAnchor> findAllByIssuerAndSignature(java.security.cert.X509Certificate); - method public java.security.cert.TrustAnchor findByIssuerAndSignature(java.security.cert.X509Certificate); - method public java.security.cert.TrustAnchor findBySubjectAndPublicKey(java.security.cert.X509Certificate); - method public java.security.cert.TrustAnchor index(java.security.cert.X509Certificate); - } - - public class TrustedCertificateStore implements com.android.org.conscrypt.ConscryptCertStore { - ctor @dalvik.annotation.compat.UnsupportedAppUsage public TrustedCertificateStore(); - method public java.util.Set<java.lang.String> aliases(); - method public java.util.Set<java.lang.String> allSystemAliases(); - method public boolean containsAlias(String); - method public void deleteCertificateEntry(String) throws java.security.cert.CertificateException, java.io.IOException; - method public java.util.Set<java.security.cert.X509Certificate> findAllIssuers(java.security.cert.X509Certificate); - method public java.security.cert.X509Certificate findIssuer(java.security.cert.X509Certificate); - method public java.security.cert.Certificate getCertificate(String); - method public java.security.cert.Certificate getCertificate(String, boolean); - method public String getCertificateAlias(java.security.cert.Certificate); - method public String getCertificateAlias(java.security.cert.Certificate, boolean); - method @dalvik.annotation.compat.UnsupportedAppUsage public java.util.List<java.security.cert.X509Certificate> getCertificateChain(java.security.cert.X509Certificate) throws java.security.cert.CertificateException; - method public java.io.File getCertificateFile(java.io.File, java.security.cert.X509Certificate); - method public java.util.Date getCreationDate(String); - method public java.security.cert.X509Certificate getTrustAnchor(java.security.cert.X509Certificate); - method public void installCertificate(java.security.cert.X509Certificate) throws java.security.cert.CertificateException, java.io.IOException; - method public static final boolean isUser(String); - method public boolean isUserAddedCertificate(java.security.cert.X509Certificate); - method public static void setDefaultUserDirectory(java.io.File); - method public java.util.Set<java.lang.String> userAliases(); + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) public static @interface CovariantReturnType.CovariantReturnTypes { + method public abstract dalvik.annotation.codegen.CovariantReturnType[] value(); } } package dalvik.annotation.compat { - @java.lang.annotation.Repeatable(UnsupportedAppUsage.Container.class) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.TYPE}) public @interface UnsupportedAppUsage { - method public abstract String expectedSignature() default ""; - method public abstract String implicitMember() default ""; - method public abstract int maxTargetSdk() default java.lang.Integer.MAX_VALUE; - method public abstract long trackingBug() default 0; - } - - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) public static @interface UnsupportedAppUsage.Container { - method public abstract dalvik.annotation.compat.UnsupportedAppUsage[] value(); + public class VersionCodes { + field public static final int O = 26; // 0x1a + field public static final int P = 28; // 0x1c + field public static final int Q = 29; // 0x1d } } @@ -645,28 +528,29 @@ package dalvik.system { } public class BaseDexClassLoader extends java.lang.ClassLoader { - method @dalvik.annotation.compat.UnsupportedAppUsage public void addDexPath(String); + method public void addDexPath(String); method public void addNativePath(java.util.Collection<java.lang.String>); - method @dalvik.annotation.compat.UnsupportedAppUsage public String getLdLibraryPath(); + method public String getLdLibraryPath(); + method public void reportClassLoaderChain(); method public static void setReporter(dalvik.system.BaseDexClassLoader.Reporter); } public static interface BaseDexClassLoader.Reporter { - method public void report(java.util.List<java.lang.ClassLoader>, java.util.List<java.lang.String>); + method public void report(java.util.Map<java.lang.String,java.lang.String>); } public final class BlockGuard { - method @NonNull @dalvik.annotation.compat.UnsupportedAppUsage public static dalvik.system.BlockGuard.Policy getThreadPolicy(); + method @NonNull public static dalvik.system.BlockGuard.Policy getThreadPolicy(); method @NonNull public static dalvik.system.BlockGuard.VmPolicy getVmPolicy(); - method @dalvik.annotation.compat.UnsupportedAppUsage public static void setThreadPolicy(@NonNull dalvik.system.BlockGuard.Policy); + method public static void setThreadPolicy(@NonNull dalvik.system.BlockGuard.Policy); method public static void setVmPolicy(@NonNull dalvik.system.BlockGuard.VmPolicy); - field @dalvik.annotation.compat.UnsupportedAppUsage public static final dalvik.system.BlockGuard.Policy LAX_POLICY; + field public static final dalvik.system.BlockGuard.Policy LAX_POLICY; field public static final dalvik.system.BlockGuard.VmPolicy LAX_VM_POLICY; } public static interface BlockGuard.Policy { method public int getPolicyMask(); - method @dalvik.annotation.compat.UnsupportedAppUsage public void onReadFromDisk(); + method public void onReadFromDisk(); method public void onUnbufferedIO(); method public void onWriteToDisk(); } @@ -676,17 +560,19 @@ package dalvik.system { } public final class CloseGuard { - method @dalvik.annotation.compat.UnsupportedAppUsage public void close(); - method @dalvik.annotation.compat.UnsupportedAppUsage public static dalvik.system.CloseGuard get(); + method public void close(); + method public static dalvik.system.CloseGuard get(); method public static dalvik.system.CloseGuard.Reporter getReporter(); - method @dalvik.annotation.compat.UnsupportedAppUsage public void open(String); - method @dalvik.annotation.compat.UnsupportedAppUsage public static void setEnabled(boolean); - method @dalvik.annotation.compat.UnsupportedAppUsage public static void setReporter(dalvik.system.CloseGuard.Reporter); - method @dalvik.annotation.compat.UnsupportedAppUsage public void warnIfOpen(); + method public void open(String); + method public void openWithCallSite(String, String); + method public static void setEnabled(boolean); + method public static void setReporter(dalvik.system.CloseGuard.Reporter); + method public void warnIfOpen(); } public static interface CloseGuard.Reporter { - method @dalvik.annotation.compat.UnsupportedAppUsage public void report(String, Throwable); + method public void report(String, Throwable); + method public default void report(String); } public interface DalvikLogHandler { @@ -730,22 +616,28 @@ package dalvik.system { } public final class RuntimeHooks { + method @Nullable public static dalvik.system.ThreadPrioritySetter getThreadPrioritySetter(); + method public static void setThreadPrioritySetter(@NonNull dalvik.system.ThreadPrioritySetter); method public static void setTimeZoneIdSupplier(java.util.function.Supplier<java.lang.String>); method public static void setUncaughtExceptionPreHandler(java.lang.Thread.UncaughtExceptionHandler); } public abstract class SocketTagger { ctor public SocketTagger(); - method @dalvik.annotation.compat.UnsupportedAppUsage public static dalvik.system.SocketTagger get(); + method public static dalvik.system.SocketTagger get(); method public static void set(dalvik.system.SocketTagger); method public abstract void tag(java.io.FileDescriptor) throws java.net.SocketException; - method @dalvik.annotation.compat.UnsupportedAppUsage public final void tag(java.net.Socket) throws java.net.SocketException; + method public final void tag(java.net.Socket) throws java.net.SocketException; method public final void tag(java.net.DatagramSocket) throws java.net.SocketException; method public abstract void untag(java.io.FileDescriptor) throws java.net.SocketException; - method @dalvik.annotation.compat.UnsupportedAppUsage public final void untag(java.net.Socket) throws java.net.SocketException; + method public final void untag(java.net.Socket) throws java.net.SocketException; method public final void untag(java.net.DatagramSocket) throws java.net.SocketException; } + @java.lang.FunctionalInterface public interface ThreadPrioritySetter { + method public void setPriority(int, int); + } + public final class VMDebug { method public static void attachAgent(String, ClassLoader) throws java.io.IOException; method public static boolean cacheRegisterMap(String); @@ -754,14 +646,14 @@ package dalvik.system { method public static void dumpHprofData(String) throws java.io.IOException; method public static void dumpHprofData(String, java.io.FileDescriptor) throws java.io.IOException; method public static void dumpHprofDataDdms(); - method @dalvik.annotation.compat.UnsupportedAppUsage public static void dumpReferenceTables(); + method public static void dumpReferenceTables(); method public static int getAllocCount(int); method @dalvik.annotation.optimization.FastNative public static int getLoadedClassCount(); method public static int getMethodTracingMode(); method public static String getRuntimeStat(String); method public static java.util.Map<java.lang.String,java.lang.String> getRuntimeStats(); method public static String[] getVmFeatureList(); - method @dalvik.annotation.compat.UnsupportedAppUsage @dalvik.annotation.optimization.FastNative public static boolean isDebuggerConnected(); + method @dalvik.annotation.optimization.FastNative public static boolean isDebuggerConnected(); method @dalvik.annotation.optimization.FastNative public static boolean isDebuggingEnabled(); method @dalvik.annotation.optimization.FastNative public static long lastDebuggerActivity(); method @dalvik.annotation.optimization.FastNative public static void printLoadedClasses(int); @@ -791,47 +683,51 @@ package dalvik.system { } public final class VMRuntime { - method @dalvik.annotation.compat.UnsupportedAppUsage @dalvik.annotation.optimization.FastNative public long addressOf(Object); + method @dalvik.annotation.optimization.FastNative public long addressOf(Object); + method public static void bootCompleted(); method public void clampGrowthLimit(); - method @dalvik.annotation.compat.UnsupportedAppUsage public void clearGrowthLimit(); + method public void clearGrowthLimit(); method public static boolean didPruneDalvikCache(); method public void disableJitCompilation(); - method @dalvik.annotation.compat.UnsupportedAppUsage public static String getCurrentInstructionSet(); - method @dalvik.annotation.compat.UnsupportedAppUsage public static String getInstructionSet(String); - method @dalvik.annotation.compat.UnsupportedAppUsage public static dalvik.system.VMRuntime getRuntime(); + method public static String getCurrentInstructionSet(); + method public static String getInstructionSet(String); + method public static dalvik.system.VMRuntime getRuntime(); method public float getTargetHeapUtilization(); method public int getTargetSdkVersion(); method @dalvik.annotation.optimization.FastNative public static boolean hasBootImageSpaces(); - method @dalvik.annotation.compat.UnsupportedAppUsage @dalvik.annotation.optimization.FastNative public boolean is64Bit(); - method @dalvik.annotation.compat.UnsupportedAppUsage public static boolean is64BitAbi(String); + method @dalvik.annotation.optimization.FastNative public boolean is64Bit(); + method public static boolean is64BitAbi(String); method public static boolean is64BitInstructionSet(String); method public static boolean isBootClassPathOnDisk(String); method @dalvik.annotation.optimization.FastNative public boolean isCheckJniEnabled(); method @dalvik.annotation.optimization.FastNative public boolean isNativeDebuggable(); - method @dalvik.annotation.compat.UnsupportedAppUsage @dalvik.annotation.optimization.FastNative public Object newNonMovableArray(Class<?>, int); + method public static boolean isValidClassLoaderContext(String); + method @dalvik.annotation.optimization.FastNative public Object newNonMovableArray(Class<?>, int); method @dalvik.annotation.optimization.FastNative public Object newUnpaddedArray(Class<?>, int); method public void notifyStartupCompleted(); method public void preloadDexCaches(); method public static void registerAppInfo(String, String[]); - method @dalvik.annotation.compat.UnsupportedAppUsage public void registerNativeAllocation(long); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public void registerNativeAllocation(int); - method @dalvik.annotation.compat.UnsupportedAppUsage public void registerNativeFree(long); - method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public void registerNativeFree(int); + method public void registerNativeAllocation(long); + method @Deprecated public void registerNativeAllocation(int); + method public void registerNativeFree(long); + method @Deprecated public void registerNativeFree(int); method public static void registerSensitiveThread(); method public void requestConcurrentGC(); + method public static void resetJitCounters(); method public static void setDedupeHiddenApiWarnings(boolean); + method public void setDisabledCompatChanges(long[]); method public void setHiddenApiAccessLogSamplingRate(int); method public void setHiddenApiExemptions(String[]); method public static void setHiddenApiUsageLogger(dalvik.system.VMRuntime.HiddenApiUsageLogger); method public static void setNonSdkApiUsageConsumer(java.util.function.Consumer<java.lang.String>); method public static void setProcessDataDirectory(String); method public static void setProcessPackageName(String); - method @dalvik.annotation.compat.UnsupportedAppUsage public float setTargetHeapUtilization(float); + method public float setTargetHeapUtilization(float); method public void setTargetSdkVersion(int); method public void startJitCompilation(); method public void updateProcessState(int); - method @dalvik.annotation.compat.UnsupportedAppUsage public String vmInstructionSet(); - method @dalvik.annotation.compat.UnsupportedAppUsage public String vmLibrary(); + method public String vmInstructionSet(); + method public String vmLibrary(); field public static final int SDK_VERSION_CUR_DEVELOPMENT = 10000; // 0x2710 } @@ -847,18 +743,13 @@ package dalvik.system { method @dalvik.annotation.optimization.FastNative public static dalvik.system.AnnotatedStackTraceElement[] getAnnotatedThreadStackTrace(Thread); } - public class VersionCodes { - field public static final int O = 26; // 0x1a - field public static final int P = 28; // 0x1c - } - public final class ZygoteHooks { method public static void gcAndFinalize(); method public static void onBeginPreload(); method public static void onEndPreload(); method public static void postForkChild(int, boolean, boolean, String); method public static void postForkCommon(); - method public static void postForkSystemServer(); + method public static void postForkSystemServer(int); method public static void preFork(); method public static void startZygoteNoThreadCreation(); method public static void stopZygoteNoThreadCreation(); @@ -881,10 +772,6 @@ package java.io { package java.lang { - public final class Byte extends java.lang.Number implements java.lang.Comparable<java.lang.Byte> { - method public static String toHexString(byte, boolean); - } - public final class Class<T> implements java.lang.reflect.AnnotatedElement java.lang.reflect.GenericDeclaration java.io.Serializable java.lang.reflect.Type { method @dalvik.annotation.optimization.FastNative public java.lang.reflect.Field[] getDeclaredFieldsUnchecked(boolean); method @dalvik.annotation.optimization.FastNative public java.lang.reflect.Method[] getDeclaredMethodsUnchecked(boolean); @@ -966,10 +853,15 @@ package java.nio { method public final void setAccessible(boolean); } + public final class NIOAccess { + method public static Object getBaseArray(java.nio.Buffer); + method public static int getBaseArrayOffset(java.nio.Buffer); + } + public final class NioUtils { - method @dalvik.annotation.compat.UnsupportedAppUsage public static void freeDirectBuffer(java.nio.ByteBuffer); - method @dalvik.annotation.compat.UnsupportedAppUsage public static byte[] unsafeArray(java.nio.ByteBuffer); - method @dalvik.annotation.compat.UnsupportedAppUsage public static int unsafeArrayOffset(java.nio.ByteBuffer); + method public static void freeDirectBuffer(java.nio.ByteBuffer); + method public static byte[] unsafeArray(java.nio.ByteBuffer); + method public static int unsafeArrayOffset(java.nio.ByteBuffer); } } @@ -1035,45 +927,73 @@ package javax.crypto { } +package javax.net.ssl { + + public abstract class HttpsURLConnection extends java.net.HttpURLConnection { + method public static javax.net.ssl.HostnameVerifier getStrictHostnameVerifier(); + } + +} + +package libcore.content.type { + + public final class MimeMap { + method public libcore.content.type.MimeMap.Builder buildUpon(); + method public static libcore.content.type.MimeMap.Builder builder(); + method @NonNull public java.util.Set<java.lang.String> extensions(); + method @NonNull public static libcore.content.type.MimeMap getDefault(); + method @Nullable public String guessExtensionFromMimeType(@Nullable String); + method @Nullable public String guessMimeTypeFromExtension(@Nullable String); + method public boolean hasExtension(@Nullable String); + method public boolean hasMimeType(@Nullable String); + method @NonNull public java.util.Set<java.lang.String> mimeTypes(); + method public static void setDefaultSupplier(@NonNull java.util.function.Supplier<libcore.content.type.MimeMap>); + } + + public static final class MimeMap.Builder { + method public libcore.content.type.MimeMap build(); + method public libcore.content.type.MimeMap.Builder put(@NonNull String, @NonNull java.util.List<java.lang.String>); + } + +} + package libcore.icu { public final class DateIntervalFormat { - method @dalvik.annotation.compat.UnsupportedAppUsage public static String formatDateRange(long, long, int, String); + method public static String formatDateRange(long, long, int, String); } public final class ICU { - method @dalvik.annotation.compat.UnsupportedAppUsage public static java.util.Locale addLikelySubtags(java.util.Locale); - method @dalvik.annotation.compat.UnsupportedAppUsage public static String getBestDateTimePattern(String, java.util.Locale); - method @dalvik.annotation.compat.UnsupportedAppUsage public static char[] getDateFormatOrder(String); - method public static String getTZDataVersion(); + method public static String getBestDateTimePattern(String, java.util.Locale); + method public static char[] getDateFormatOrder(String); } public final class LocaleData { - method @dalvik.annotation.compat.UnsupportedAppUsage public static libcore.icu.LocaleData get(java.util.Locale); + method public static libcore.icu.LocaleData get(java.util.Locale); method public String getDateFormat(int); field public String[] amPm; - field @dalvik.annotation.compat.UnsupportedAppUsage public Integer firstDayOfWeek; + field public Integer firstDayOfWeek; field public String[] longMonthNames; field public String[] longStandAloneMonthNames; - field @dalvik.annotation.compat.UnsupportedAppUsage public String[] longStandAloneWeekdayNames; + field public String[] longStandAloneWeekdayNames; field public String[] longWeekdayNames; field public String narrowAm; field public String narrowPm; - field @dalvik.annotation.compat.UnsupportedAppUsage public String[] shortMonthNames; - field @dalvik.annotation.compat.UnsupportedAppUsage public String[] shortStandAloneMonthNames; - field @dalvik.annotation.compat.UnsupportedAppUsage public String[] shortStandAloneWeekdayNames; + field public String[] shortMonthNames; + field public String[] shortStandAloneMonthNames; + field public String[] shortStandAloneWeekdayNames; field public String[] shortWeekdayNames; - field @dalvik.annotation.compat.UnsupportedAppUsage public String timeFormat_Hm; + field public String timeFormat_Hm; field public String timeFormat_Hms; - field @dalvik.annotation.compat.UnsupportedAppUsage public String timeFormat_hm; + field public String timeFormat_hm; field public String timeFormat_hms; field public String[] tinyMonthNames; field public String[] tinyStandAloneMonthNames; field public String[] tinyStandAloneWeekdayNames; field public String[] tinyWeekdayNames; - field @dalvik.annotation.compat.UnsupportedAppUsage public String today; + field public String today; field public String yesterday; - field @dalvik.annotation.compat.UnsupportedAppUsage public char zeroDigit; + field public char zeroDigit; } public final class RelativeDateTimeFormatter { @@ -1095,13 +1015,13 @@ package libcore.internal { package libcore.io { public class ForwardingOs implements libcore.io.Os { - ctor @dalvik.annotation.compat.UnsupportedAppUsage protected ForwardingOs(libcore.io.Os); - method @dalvik.annotation.compat.UnsupportedAppUsage public boolean access(String, int) throws android.system.ErrnoException; - method @dalvik.annotation.compat.UnsupportedAppUsage public java.io.FileDescriptor open(String, int, int) throws android.system.ErrnoException; - method @dalvik.annotation.compat.UnsupportedAppUsage public void remove(String) throws android.system.ErrnoException; - method @dalvik.annotation.compat.UnsupportedAppUsage public void rename(String, String) throws android.system.ErrnoException; - method @dalvik.annotation.compat.UnsupportedAppUsage public android.system.StructStat stat(String) throws android.system.ErrnoException; - method @dalvik.annotation.compat.UnsupportedAppUsage public void unlink(String) throws android.system.ErrnoException; + ctor protected ForwardingOs(libcore.io.Os); + method public boolean access(String, int) throws android.system.ErrnoException; + method public java.io.FileDescriptor open(String, int, int) throws android.system.ErrnoException; + method public void remove(String) throws android.system.ErrnoException; + method public void rename(String, String) throws android.system.ErrnoException; + method public android.system.StructStat stat(String) throws android.system.ErrnoException; + method public void unlink(String) throws android.system.ErrnoException; } public final class IoBridge { @@ -1118,14 +1038,13 @@ package libcore.io { public final class IoUtils { method public static int acquireRawFd(@NonNull java.io.FileDescriptor); method public static void close(java.io.FileDescriptor) throws java.io.IOException; - method @dalvik.annotation.compat.UnsupportedAppUsage public static void closeQuietly(AutoCloseable); - method @dalvik.annotation.compat.UnsupportedAppUsage public static void closeQuietly(java.io.FileDescriptor); - method @dalvik.annotation.compat.UnsupportedAppUsage public static void closeQuietly(java.net.Socket); - method @Deprecated public static java.io.File createTemporaryDirectory(String); + method public static void closeQuietly(AutoCloseable); + method public static void closeQuietly(java.io.FileDescriptor); + method public static void closeQuietly(java.net.Socket); method @Deprecated public static void deleteContents(java.io.File) throws java.io.IOException; - method @dalvik.annotation.compat.UnsupportedAppUsage public static byte[] readFileAsByteArray(String) throws java.io.IOException; - method @dalvik.annotation.compat.UnsupportedAppUsage public static String readFileAsString(String) throws java.io.IOException; - method @dalvik.annotation.compat.UnsupportedAppUsage public static void setBlocking(java.io.FileDescriptor, boolean) throws java.io.IOException; + method public static byte[] readFileAsByteArray(String) throws java.io.IOException; + method public static String readFileAsString(String) throws java.io.IOException; + method public static void setBlocking(java.io.FileDescriptor, boolean) throws java.io.IOException; method public static void setFdOwner(@NonNull java.io.FileDescriptor, @NonNull Object); } @@ -1144,14 +1063,14 @@ package libcore.io { } public final class Streams { - method @dalvik.annotation.compat.UnsupportedAppUsage public static int copy(java.io.InputStream, java.io.OutputStream) throws java.io.IOException; - method @dalvik.annotation.compat.UnsupportedAppUsage public static void readFully(java.io.InputStream, byte[]) throws java.io.IOException; - method @dalvik.annotation.compat.UnsupportedAppUsage public static byte[] readFully(java.io.InputStream) throws java.io.IOException; + method public static int copy(java.io.InputStream, java.io.OutputStream) throws java.io.IOException; + method public static void readFully(java.io.InputStream, byte[]) throws java.io.IOException; + method public static byte[] readFully(java.io.InputStream) throws java.io.IOException; method public static String readFully(java.io.Reader) throws java.io.IOException; method public static byte[] readFullyNoClose(java.io.InputStream) throws java.io.IOException; - method @dalvik.annotation.compat.UnsupportedAppUsage public static int readSingleByte(java.io.InputStream) throws java.io.IOException; + method public static int readSingleByte(java.io.InputStream) throws java.io.IOException; method public static long skipByReading(java.io.InputStream, long) throws java.io.IOException; - method @dalvik.annotation.compat.UnsupportedAppUsage public static void writeSingleByte(java.io.OutputStream, int) throws java.io.IOException; + method public static void writeSingleByte(java.io.OutputStream, int) throws java.io.IOException; } } @@ -1163,18 +1082,11 @@ package libcore.net { method public static java.net.InetAddress parseNumericAddress(String); } - public final class MimeUtils { - method @dalvik.annotation.compat.UnsupportedAppUsage public static String guessExtensionFromMimeType(String); - method @dalvik.annotation.compat.UnsupportedAppUsage public static String guessMimeTypeFromExtension(String); - method public static boolean hasExtension(String); - method public static boolean hasMimeType(String); - } - public abstract class NetworkSecurityPolicy { ctor public NetworkSecurityPolicy(); method public static libcore.net.NetworkSecurityPolicy getInstance(); method public abstract boolean isCertificateTransparencyVerificationRequired(String); - method @dalvik.annotation.compat.UnsupportedAppUsage public abstract boolean isCleartextTrafficPermitted(); + method public abstract boolean isCleartextTrafficPermitted(); method public abstract boolean isCleartextTrafficPermitted(String); method public static void setInstance(libcore.net.NetworkSecurityPolicy); } @@ -1184,7 +1096,7 @@ package libcore.net { package libcore.net.event { public class NetworkEventDispatcher { - method @dalvik.annotation.compat.UnsupportedAppUsage public static libcore.net.event.NetworkEventDispatcher getInstance(); + method public static libcore.net.event.NetworkEventDispatcher getInstance(); method public void onNetworkConfigurationChanged(); } @@ -1194,24 +1106,28 @@ package libcore.timezone { public final class CountryTimeZones { method public String getCountryIso(); + method public android.icu.util.TimeZone getDefaultTimeZone(); method public String getDefaultTimeZoneId(); + method public java.util.List<libcore.timezone.CountryTimeZones.TimeZoneMapping> getEffectiveTimeZoneMappingsAt(long); method public java.util.List<libcore.timezone.CountryTimeZones.TimeZoneMapping> getTimeZoneMappings(); method public boolean hasUtcZone(long); - method public boolean isDefaultOkForCountryTimeZoneDetection(long); + method public boolean isDefaultTimeZoneBoosted(); method public boolean isForCountryCode(String); - method @Deprecated public libcore.timezone.CountryTimeZones.OffsetResult lookupByOffsetWithBias(int, boolean, long, android.icu.util.TimeZone); + method public libcore.timezone.CountryTimeZones.OffsetResult lookupByOffsetWithBias(long, android.icu.util.TimeZone, int, boolean); + method public libcore.timezone.CountryTimeZones.OffsetResult lookupByOffsetWithBias(long, android.icu.util.TimeZone, int); } public static final class CountryTimeZones.OffsetResult { - field public final boolean mOneMatch; - field public final android.icu.util.TimeZone mTimeZone; + method public android.icu.util.TimeZone getTimeZone(); + method public boolean isOnlyMatch(); } public static final class CountryTimeZones.TimeZoneMapping { method public static libcore.timezone.CountryTimeZones.TimeZoneMapping createForTests(String, boolean, Long); - field public final Long notUsedAfter; - field public final boolean showInPicker; - field public final String timeZoneId; + method public Long getNotUsedAfter(); + method public android.icu.util.TimeZone getTimeZone(); + method public String getTimeZoneId(); + method public boolean isShownInPicker(); } public final class CountryZonesFinder { @@ -1220,10 +1136,27 @@ package libcore.timezone { method public java.util.List<libcore.timezone.CountryTimeZones> lookupCountryTimeZonesForZoneId(String); } + public final class TelephonyLookup { + method public static libcore.timezone.TelephonyLookup createInstance(String) throws java.io.IOException; + method public static libcore.timezone.TelephonyLookup getInstance(); + method public libcore.timezone.TelephonyNetworkFinder getTelephonyNetworkFinder(); + method public void validate() throws java.io.IOException; + } + + public final class TelephonyNetwork { + method public String getCountryIsoCode(); + method public String getMcc(); + method public String getMnc(); + } + + public final class TelephonyNetworkFinder { + method public libcore.timezone.TelephonyNetwork findNetworkByMccMnc(String, String); + } + public final class TimeZoneDataFiles { method public static String getDataTimeZoneFile(String); method public static String getDataTimeZoneRootDir(); - method public static String getRuntimeModuleTzVersionFile(); + method public static String getTimeZoneModuleTzVersionFile(); } public final class TimeZoneFinder { @@ -1232,22 +1165,22 @@ package libcore.timezone { method public String getIanaVersion(); method public static libcore.timezone.TimeZoneFinder getInstance(); method public libcore.timezone.CountryTimeZones lookupCountryTimeZones(String); - method public String lookupDefaultTimeZoneIdByCountry(String); - method public android.icu.util.TimeZone lookupTimeZoneByCountryAndOffset(String, int, boolean, long, android.icu.util.TimeZone); - method public java.util.List<java.lang.String> lookupTimeZoneIdsByCountry(String); - method public java.util.List<android.icu.util.TimeZone> lookupTimeZonesByCountry(String); method public void validate() throws java.io.IOException; } - public class TzDataSetVersion { + public final class TzDataSetVersion { ctor public TzDataSetVersion(int, int, String, int) throws libcore.timezone.TzDataSetVersion.TzDataSetException; method public static int currentFormatMajorVersion(); method public static int currentFormatMinorVersion(); + method public int getFormatMajorVersion(); + method public int getFormatMinorVersion(); + method public int getRevision(); + method public String getRulesVersion(); method public static boolean isCompatibleWithThisDevice(libcore.timezone.TzDataSetVersion); method public static libcore.timezone.TzDataSetVersion readFromFile(java.io.File) throws java.io.IOException, libcore.timezone.TzDataSetVersion.TzDataSetException; + method public static libcore.timezone.TzDataSetVersion readTimeZoneModuleVersion() throws java.io.IOException, libcore.timezone.TzDataSetVersion.TzDataSetException; method public byte[] toBytes(); field public static final String DEFAULT_FILE_NAME = "tz_version"; - field public final String rulesVersion; } public static class TzDataSetVersion.TzDataSetException extends java.lang.Exception { @@ -1255,14 +1188,11 @@ package libcore.timezone { ctor public TzDataSetVersion.TzDataSetException(String, Throwable); } - public final class ZoneInfoDB { - method public static libcore.timezone.ZoneInfoDB.TzData getInstance(); - } - - public static class ZoneInfoDB.TzData implements java.lang.AutoCloseable { + public final class ZoneInfoDb implements java.lang.AutoCloseable { + method public static libcore.timezone.ZoneInfoDb getInstance(); method public String getVersion(); method public boolean hasTimeZone(String) throws java.io.IOException; - method public static libcore.timezone.ZoneInfoDB.TzData loadTzData(String); + method public static libcore.timezone.ZoneInfoDb loadTzData(String); method public libcore.util.ZoneInfo makeTimeZone(String) throws java.io.IOException; method public void validate() throws java.io.IOException; } @@ -1294,21 +1224,66 @@ package libcore.util { public final class EmptyArray { field public static final boolean[] BOOLEAN; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final byte[] BYTE; + field public static final byte[] BYTE; field public static final float[] FLOAT; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final int[] INT; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final long[] LONG; - field @dalvik.annotation.compat.UnsupportedAppUsage public static final Object[] OBJECT; + field public static final int[] INT; + field public static final long[] LONG; + field public static final Object[] OBJECT; field public static final String[] STRING; } + public class FP16 { + method public static short ceil(short); + method public static int compare(short, short); + method public static boolean equals(short, short); + method public static short floor(short); + method public static boolean greater(short, short); + method public static boolean greaterEquals(short, short); + method public static boolean isInfinite(short); + method public static boolean isNaN(short); + method public static boolean isNormalized(short); + method public static boolean less(short, short); + method public static boolean lessEquals(short, short); + method public static short max(short, short); + method public static short min(short, short); + method public static short rint(short); + method public static float toFloat(short); + method public static short toHalf(float); + method public static String toHexString(short); + method public static short trunc(short); + field public static final short EPSILON = 5120; // 0x1400 + field public static final int EXPONENT_BIAS = 15; // 0xf + field public static final int EXPONENT_SHIFT = 10; // 0xa + field public static final int EXPONENT_SIGNIFICAND_MASK = 32767; // 0x7fff + field public static final short LOWEST_VALUE = -1025; // 0xfffffbff + field public static final int MAX_EXPONENT = 15; // 0xf + field public static final short MAX_VALUE = 31743; // 0x7bff + field public static final int MIN_EXPONENT = -14; // 0xfffffff2 + field public static final short MIN_NORMAL = 1024; // 0x400 + field public static final short MIN_VALUE = 1; // 0x1 + field public static final short NEGATIVE_INFINITY = -1024; // 0xfffffc00 + field public static final short NEGATIVE_ZERO = -32768; // 0xffff8000 + field public static final short NaN = 32256; // 0x7e00 + field public static final short POSITIVE_INFINITY = 31744; // 0x7c00 + field public static final short POSITIVE_ZERO = 0; // 0x0 + field public static final int SHIFTED_EXPONENT_MASK = 31; // 0x1f + field public static final int SIGNIFICAND_MASK = 1023; // 0x3ff + field public static final int SIGN_MASK = 32768; // 0x8000 + field public static final int SIGN_SHIFT = 15; // 0xf + field public static final int SIZE = 16; // 0x10 + } + public class HexEncoding { method public static byte[] decode(String) throws java.lang.IllegalArgumentException; + method public static byte[] decode(String, boolean) throws java.lang.IllegalArgumentException; method public static byte[] decode(char[]) throws java.lang.IllegalArgumentException; method public static byte[] decode(char[], boolean) throws java.lang.IllegalArgumentException; method public static char[] encode(byte[]); + method public static char[] encode(byte[], boolean); method public static char[] encode(byte[], int, int); + method public static String encodeToString(byte, boolean); method public static String encodeToString(byte[]); + method public static String encodeToString(byte[], boolean); } public class NativeAllocationRegistry { @@ -1391,7 +1366,7 @@ package org.apache.harmony.dalvik.ddmc { public class Chunk { ctor public Chunk(int, byte[], int, int); - ctor @dalvik.annotation.compat.UnsupportedAppUsage public Chunk(int, java.nio.ByteBuffer); + ctor public Chunk(int, java.nio.ByteBuffer); field public int type; } @@ -1406,21 +1381,21 @@ package org.apache.harmony.dalvik.ddmc { method public static void putString(java.nio.ByteBuffer, String); method public static int type(String); method public static java.nio.ByteBuffer wrapChunk(org.apache.harmony.dalvik.ddmc.Chunk); - field @dalvik.annotation.compat.UnsupportedAppUsage public static final java.nio.ByteOrder CHUNK_ORDER; + field public static final java.nio.ByteOrder CHUNK_ORDER; } public class DdmServer { method public static void registerHandler(int, org.apache.harmony.dalvik.ddmc.ChunkHandler); method public static void registrationComplete(); - method @dalvik.annotation.compat.UnsupportedAppUsage public static void sendChunk(org.apache.harmony.dalvik.ddmc.Chunk); + method public static void sendChunk(org.apache.harmony.dalvik.ddmc.Chunk); } public class DdmVmInternal { method public static void enableRecentAllocations(boolean); method @dalvik.annotation.optimization.FastNative public static boolean getRecentAllocationStatus(); method @dalvik.annotation.optimization.FastNative public static byte[] getRecentAllocations(); - method @dalvik.annotation.compat.UnsupportedAppUsage public static StackTraceElement[] getStackTraceById(int); - method @dalvik.annotation.compat.UnsupportedAppUsage public static byte[] getThreadStats(); + method public static StackTraceElement[] getStackTraceById(int); + method public static byte[] getThreadStats(); method @dalvik.annotation.optimization.FastNative public static boolean heapInfoNotify(int); method public static boolean heapSegmentNotify(int, int, boolean); method public static void threadNotify(boolean); @@ -1431,7 +1406,7 @@ package org.apache.harmony.dalvik.ddmc { package org.json { public class JSONObject { - method @dalvik.annotation.compat.UnsupportedAppUsage public java.util.Set<java.lang.String> keySet(); + method public java.util.Set<java.lang.String> keySet(); } } @@ -1445,14 +1420,30 @@ package sun.misc { public final class Unsafe { method public int arrayBaseOffset(Class); + method public int arrayIndexScale(Class); + method @dalvik.annotation.optimization.FastNative public void copyMemory(long, long, long); + method @dalvik.annotation.optimization.FastNative public boolean getBoolean(Object, long); method @dalvik.annotation.optimization.FastNative public byte getByte(Object, long); method @dalvik.annotation.optimization.FastNative public byte getByte(long); + method @dalvik.annotation.optimization.FastNative public double getDouble(Object, long); + method @dalvik.annotation.optimization.FastNative public float getFloat(Object, long); + method @dalvik.annotation.optimization.FastNative public int getInt(Object, long); + method @dalvik.annotation.optimization.FastNative public int getInt(long); method @dalvik.annotation.optimization.FastNative public long getLong(Object, long); method @dalvik.annotation.optimization.FastNative public long getLong(long); + method @dalvik.annotation.optimization.FastNative public Object getObject(Object, long); method public static sun.misc.Unsafe getUnsafe(); method public long objectFieldOffset(java.lang.reflect.Field); + method @dalvik.annotation.optimization.FastNative public void putBoolean(Object, long, boolean); method @dalvik.annotation.optimization.FastNative public void putByte(Object, long, byte); method @dalvik.annotation.optimization.FastNative public void putByte(long, byte); + method @dalvik.annotation.optimization.FastNative public void putDouble(Object, long, double); + method @dalvik.annotation.optimization.FastNative public void putFloat(Object, long, float); + method @dalvik.annotation.optimization.FastNative public void putInt(Object, long, int); + method @dalvik.annotation.optimization.FastNative public void putInt(long, int); + method @dalvik.annotation.optimization.FastNative public void putLong(Object, long, long); + method @dalvik.annotation.optimization.FastNative public void putLong(long, long); + method @dalvik.annotation.optimization.FastNative public void putObject(Object, long, Object); } } diff --git a/mmodules/intracoreapi/Android.bp b/mmodules/intracoreapi/Android.bp index a07f540354..c2a3de357e 100644 --- a/mmodules/intracoreapi/Android.bp +++ b/mmodules/intracoreapi/Android.bp @@ -12,22 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Build rules for the APIs that the various core libraries can depend on from -// each other: public SDK APIs and "intra-core" APIs. Intra-core APIs are not -// for use by other parts of the Android software stack. - -// Generates stub source files for the {public SDK + intra-core} API -// of the core jars. +// Generates stub source files for the intra-core API of the ART module. +// i.e. every class/member that is either in the public API or annotated with +// @IntraCoreApi. +// +// The API specification .txt files managed by this only contain the additional +// classes/members that are in the intra-core API but which are not in the public +// API. droidstubs { - name: "core-intra-stubs", - srcs: [":core_api_files"], - no_standard_libs: true, - libs: ["core-all"], + name: "art-module-intra-core-api-stubs-source", + srcs: [ + ":art_module_api_files", + ], + sdk_version: "none", + system_modules: "none", installable: false, - args: "--hide-annotation libcore.api.Hide " - + "--show-single-annotation libcore.api.IntraCoreApi " - + "--skip-annotation-instance-methods=false ", + args: "--hide-annotation libcore.api.Hide " + + "--show-single-annotation libcore.api.IntraCoreApi " + + "--skip-annotation-instance-methods=false ", merge_inclusion_annotations_dirs: ["ojluni-annotated-mmodule-stubs"], api_filename: "api.txt", @@ -45,51 +48,33 @@ droidstubs { }, } -// A library containing the {public SDK + intra-core} API stubs for the -// core jars. +// A library containing the intra-core API stubs of the ART module. +// +// Intra-core APIs are only intended for the use of other core library modules. java_library { - name: "core.intra.stubs", - srcs: [":core-intra-stubs"], + name: "art.module.intra.core.api.stubs", + visibility: [ + "//libcore/mmodules/core_platform_api", + ], + srcs: [ + ":art-module-intra-core-api-stubs-source", + ":openjdk_lambda_stub_files", + ":openjdk_generated_annotation_stub_files", + ], - no_standard_libs: true, - libs: ["core-all"], - system_modules: "core-all-system-modules", - openjdk9: { - javacflags: ["--patch-module=java.base=."], - }, + sdk_version: "none", + system_modules: "none", + patch_module: "java.base", } -// Used when compiling against core.intra.stubs. +// Used when compiling against art.module.intra.core.api.stubs. java_system_modules { - name: "core-intra-stubs-system-modules", - libs: ["core.intra.stubs"], -} - -// A rule that checks we can build core-libart and core-oj using only the source -// for core-libart and core-oj and the APIs in core-intra-stubs. This proves we -// don't actually depend on things from (for example) conscrypt we haven't added -// to the intra-core API. -java_library { - name: "core-libart-oj.depscheck", - srcs: [ - ":core_libart_java_files", - ":core_oj_java_files", + name: "art-module-intra-core-api-stubs-system-modules", + visibility: [ + "//art/build/sdk", + "//external/bouncycastle", + "//external/conscrypt", + "//external/icu/android_icu4j", ], - errorprone: { - javacflags: [ - "-Xep:MissingOverride:OFF", // Ignore missing @Override. - "-Xep:ConstantOverflow:WARN", // Known constant overflow in SplittableRandom - ], - }, - - installable: false, - - no_standard_libs: true, - libs: ["core.intra.stubs"], - system_modules: "core-intra-stubs-system-modules", - java_version: "1.9", - openjdk9: { - javacflags: ["--patch-module=java.base=."], - }, + libs: ["art.module.intra.core.api.stubs"], } - diff --git a/mmodules/intracoreapi/api/intra/current-api.txt b/mmodules/intracoreapi/api/intra/current-api.txt index a7a2fdc504..5137a10913 100644 --- a/mmodules/intracoreapi/api/intra/current-api.txt +++ b/mmodules/intracoreapi/api/intra/current-api.txt @@ -1,415 +1,37 @@ // Signature format: 2.0 -package android.system { +package android.compat { - public final class ErrnoException extends java.lang.Exception { - method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public java.net.SocketException rethrowAsSocketException() throws java.net.SocketException; + @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public final class Compatibility { + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static boolean isChangeEnabled(long); + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static void reportChange(long); } -} - -package com.android.org.conscrypt { - - @libcore.api.IntraCoreApi public class DESEDESecretKeyFactory extends javax.crypto.SecretKeyFactorySpi { - ctor @libcore.api.IntraCoreApi public DESEDESecretKeyFactory(); - } - - @libcore.api.IntraCoreApi public final class DefaultSSLContextImpl extends com.android.org.conscrypt.OpenSSLContextImpl { - ctor @libcore.api.IntraCoreApi public DefaultSSLContextImpl() throws java.security.GeneralSecurityException, java.io.IOException; - } - - @libcore.api.IntraCoreApi public class ECParameters extends java.security.AlgorithmParametersSpi { - ctor @libcore.api.IntraCoreApi public ECParameters(); - } - - @libcore.api.IntraCoreApi public final class GCMParameters extends java.security.AlgorithmParametersSpi { - ctor @libcore.api.IntraCoreApi public GCMParameters(); - } - - @libcore.api.IntraCoreApi public class IvParameters extends java.security.AlgorithmParametersSpi { - ctor @libcore.api.IntraCoreApi public IvParameters(); - } - - @libcore.api.IntraCoreApi public static class IvParameters.AES extends com.android.org.conscrypt.IvParameters { - ctor @libcore.api.IntraCoreApi public IvParameters.AES(); - } - - @libcore.api.IntraCoreApi public static class IvParameters.ChaCha20 extends com.android.org.conscrypt.IvParameters { - ctor @libcore.api.IntraCoreApi public IvParameters.ChaCha20(); - } - - @libcore.api.IntraCoreApi public static class IvParameters.DESEDE extends com.android.org.conscrypt.IvParameters { - ctor @libcore.api.IntraCoreApi public IvParameters.DESEDE(); - } - - @libcore.api.IntraCoreApi public abstract class KeyGeneratorImpl extends javax.crypto.KeyGeneratorSpi { - } - - @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.AES extends com.android.org.conscrypt.KeyGeneratorImpl { - ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.AES(); - } - - @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.ARC4 extends com.android.org.conscrypt.KeyGeneratorImpl { - ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.ARC4(); - } - - @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.ChaCha20 extends com.android.org.conscrypt.KeyGeneratorImpl { - ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.ChaCha20(); - } - - @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.DESEDE extends com.android.org.conscrypt.KeyGeneratorImpl { - ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.DESEDE(); - } - - @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.HmacMD5 extends com.android.org.conscrypt.KeyGeneratorImpl { - ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.HmacMD5(); - } - - @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.HmacSHA1 extends com.android.org.conscrypt.KeyGeneratorImpl { - ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.HmacSHA1(); - } - - @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.HmacSHA224 extends com.android.org.conscrypt.KeyGeneratorImpl { - ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.HmacSHA224(); - } - - @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.HmacSHA256 extends com.android.org.conscrypt.KeyGeneratorImpl { - ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.HmacSHA256(); - } - - @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.HmacSHA384 extends com.android.org.conscrypt.KeyGeneratorImpl { - ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.HmacSHA384(); - } - - @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.HmacSHA512 extends com.android.org.conscrypt.KeyGeneratorImpl { - ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.HmacSHA512(); - } - - @libcore.api.IntraCoreApi public class OAEPParameters extends java.security.AlgorithmParametersSpi { - ctor @libcore.api.IntraCoreApi public OAEPParameters(); - } - - @libcore.api.IntraCoreApi public abstract class OpenSSLCipher extends javax.crypto.CipherSpi { - } - - @libcore.api.IntraCoreApi public abstract static class OpenSSLCipher.EVP_AEAD extends com.android.org.conscrypt.OpenSSLCipher { - } - - @libcore.api.IntraCoreApi public abstract static class OpenSSLCipher.EVP_AEAD.AES extends com.android.org.conscrypt.OpenSSLCipher.EVP_AEAD { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_AEAD.AES.GCM extends com.android.org.conscrypt.OpenSSLCipher.EVP_AEAD.AES { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_AEAD.AES.GCM(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_AEAD.AES.GCM.AES_128 extends com.android.org.conscrypt.OpenSSLCipher.EVP_AEAD.AES.GCM { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_AEAD.AES.GCM.AES_128(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_AEAD.AES.GCM.AES_256 extends com.android.org.conscrypt.OpenSSLCipher.EVP_AEAD.AES.GCM { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_AEAD.AES.GCM.AES_256(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_AEAD.ChaCha20 extends com.android.org.conscrypt.OpenSSLCipher.EVP_AEAD { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_AEAD.ChaCha20(); - } - - @libcore.api.IntraCoreApi public abstract static class OpenSSLCipher.EVP_CIPHER extends com.android.org.conscrypt.OpenSSLCipher { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES.CBC extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES.CBC.NoPadding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES.CBC { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES.CBC.NoPadding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES.CBC.PKCS5Padding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES.CBC { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES.CBC.PKCS5Padding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES.CTR extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES.CTR(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES.ECB extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES.ECB.NoPadding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES.ECB { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES.ECB.NoPadding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES.ECB.PKCS5Padding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES.ECB { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES.ECB.PKCS5Padding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_128 extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_128.CBC extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES_128 { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_128.CBC.NoPadding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES_128.CBC { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES_128.CBC.NoPadding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_128.CBC.PKCS5Padding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES_128.CBC { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES_128.CBC.PKCS5Padding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_128.ECB extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES_128 { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_128.ECB.NoPadding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES_128.ECB { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES_128.ECB.NoPadding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_128.ECB.PKCS5Padding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES_128.ECB { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES_128.ECB.PKCS5Padding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_256 extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_256.CBC extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES_256 { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_256.CBC.NoPadding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES_256.CBC { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES_256.CBC.NoPadding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_256.CBC.PKCS5Padding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES_256.CBC { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES_256.CBC.PKCS5Padding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_256.ECB extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES_256 { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_256.ECB.NoPadding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES_256.ECB { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES_256.ECB.NoPadding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.AES_256.ECB.PKCS5Padding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.AES_256.ECB { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.AES_256.ECB.PKCS5Padding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.ARC4 extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.ARC4(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.DESEDE extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.DESEDE.CBC extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.DESEDE { - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.DESEDE.CBC.NoPadding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.DESEDE.CBC { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.DESEDE.CBC.NoPadding(); - } - - @libcore.api.IntraCoreApi public static class OpenSSLCipher.EVP_CIPHER.DESEDE.CBC.PKCS5Padding extends com.android.org.conscrypt.OpenSSLCipher.EVP_CIPHER.DESEDE.CBC { - ctor @libcore.api.IntraCoreApi public OpenSSLCipher.EVP_CIPHER.DESEDE.CBC.PKCS5Padding(); - } - - @libcore.api.IntraCoreApi public class OpenSSLCipherChaCha20 extends com.android.org.conscrypt.OpenSSLCipher { - ctor @libcore.api.IntraCoreApi public OpenSSLCipherChaCha20(); - } - - @libcore.api.IntraCoreApi public abstract class OpenSSLContextImpl extends javax.net.ssl.SSLContextSpi { + @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static final class Compatibility.ChangeConfig { + ctor public Compatibility.ChangeConfig(java.util.Set<java.lang.Long>, java.util.Set<java.lang.Long>); + method public long[] forceDisabledChangesArray(); + method public java.util.Set<java.lang.Long> forceDisabledSet(); + method public long[] forceEnabledChangesArray(); + method public java.util.Set<java.lang.Long> forceEnabledSet(); + method public boolean isEmpty(); + method public boolean isForceDisabled(long); + method public boolean isForceEnabled(long); } - @libcore.api.IntraCoreApi public static final class OpenSSLContextImpl.TLSv1 extends com.android.org.conscrypt.OpenSSLContextImpl { - ctor @libcore.api.IntraCoreApi public OpenSSLContextImpl.TLSv1(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLContextImpl.TLSv11 extends com.android.org.conscrypt.OpenSSLContextImpl { - ctor @libcore.api.IntraCoreApi public OpenSSLContextImpl.TLSv11(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLContextImpl.TLSv12 extends com.android.org.conscrypt.OpenSSLContextImpl { - ctor @dalvik.annotation.compat.UnsupportedAppUsage @libcore.api.IntraCoreApi public OpenSSLContextImpl.TLSv12(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLContextImpl.TLSv13 extends com.android.org.conscrypt.OpenSSLContextImpl { - ctor @libcore.api.IntraCoreApi public OpenSSLContextImpl.TLSv13(); - } - - @libcore.api.IntraCoreApi public final class OpenSSLECDHKeyAgreement extends javax.crypto.KeyAgreementSpi { - ctor @libcore.api.IntraCoreApi public OpenSSLECDHKeyAgreement(); - } - - @libcore.api.IntraCoreApi public final class OpenSSLECKeyFactory extends java.security.KeyFactorySpi { - ctor @libcore.api.IntraCoreApi public OpenSSLECKeyFactory(); - } - - @libcore.api.IntraCoreApi public final class OpenSSLECKeyPairGenerator extends java.security.KeyPairGenerator { - ctor @libcore.api.IntraCoreApi public OpenSSLECKeyPairGenerator(); - } - - @libcore.api.IntraCoreApi public abstract class OpenSSLMac extends javax.crypto.MacSpi { - } - - @libcore.api.IntraCoreApi public static final class OpenSSLMac.HmacMD5 extends com.android.org.conscrypt.OpenSSLMac { - ctor @libcore.api.IntraCoreApi public OpenSSLMac.HmacMD5(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLMac.HmacSHA1 extends com.android.org.conscrypt.OpenSSLMac { - ctor @libcore.api.IntraCoreApi public OpenSSLMac.HmacSHA1(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLMac.HmacSHA224 extends com.android.org.conscrypt.OpenSSLMac { - ctor @libcore.api.IntraCoreApi public OpenSSLMac.HmacSHA224() throws java.security.NoSuchAlgorithmException; - } - - @libcore.api.IntraCoreApi public static final class OpenSSLMac.HmacSHA256 extends com.android.org.conscrypt.OpenSSLMac { - ctor @libcore.api.IntraCoreApi public OpenSSLMac.HmacSHA256() throws java.security.NoSuchAlgorithmException; - } - - @libcore.api.IntraCoreApi public static final class OpenSSLMac.HmacSHA384 extends com.android.org.conscrypt.OpenSSLMac { - ctor @libcore.api.IntraCoreApi public OpenSSLMac.HmacSHA384() throws java.security.NoSuchAlgorithmException; - } - - @libcore.api.IntraCoreApi public static final class OpenSSLMac.HmacSHA512 extends com.android.org.conscrypt.OpenSSLMac { - ctor @libcore.api.IntraCoreApi public OpenSSLMac.HmacSHA512(); - } - - @libcore.api.IntraCoreApi public class OpenSSLMessageDigestJDK extends java.security.MessageDigestSpi implements java.lang.Cloneable { - } - - @libcore.api.IntraCoreApi public static final class OpenSSLMessageDigestJDK.MD5 extends com.android.org.conscrypt.OpenSSLMessageDigestJDK { - ctor @libcore.api.IntraCoreApi public OpenSSLMessageDigestJDK.MD5() throws java.security.NoSuchAlgorithmException; - } - - @libcore.api.IntraCoreApi public static final class OpenSSLMessageDigestJDK.SHA1 extends com.android.org.conscrypt.OpenSSLMessageDigestJDK { - ctor @libcore.api.IntraCoreApi public OpenSSLMessageDigestJDK.SHA1() throws java.security.NoSuchAlgorithmException; - } - - @libcore.api.IntraCoreApi public static final class OpenSSLMessageDigestJDK.SHA224 extends com.android.org.conscrypt.OpenSSLMessageDigestJDK { - ctor @libcore.api.IntraCoreApi public OpenSSLMessageDigestJDK.SHA224() throws java.security.NoSuchAlgorithmException; - } - - @libcore.api.IntraCoreApi public static final class OpenSSLMessageDigestJDK.SHA256 extends com.android.org.conscrypt.OpenSSLMessageDigestJDK { - ctor @libcore.api.IntraCoreApi public OpenSSLMessageDigestJDK.SHA256() throws java.security.NoSuchAlgorithmException; - } - - @libcore.api.IntraCoreApi public static final class OpenSSLMessageDigestJDK.SHA384 extends com.android.org.conscrypt.OpenSSLMessageDigestJDK { - ctor @libcore.api.IntraCoreApi public OpenSSLMessageDigestJDK.SHA384() throws java.security.NoSuchAlgorithmException; - } - - @libcore.api.IntraCoreApi public static final class OpenSSLMessageDigestJDK.SHA512 extends com.android.org.conscrypt.OpenSSLMessageDigestJDK { - ctor @libcore.api.IntraCoreApi public OpenSSLMessageDigestJDK.SHA512() throws java.security.NoSuchAlgorithmException; - } - - @libcore.api.IntraCoreApi public final class OpenSSLRSAKeyFactory extends java.security.KeyFactorySpi { - ctor @libcore.api.IntraCoreApi public OpenSSLRSAKeyFactory(); - } - - @libcore.api.IntraCoreApi public final class OpenSSLRSAKeyPairGenerator extends java.security.KeyPairGeneratorSpi { - ctor @libcore.api.IntraCoreApi public OpenSSLRSAKeyPairGenerator(); - } - - @libcore.api.IntraCoreApi public final class OpenSSLRandom extends java.security.SecureRandomSpi implements java.io.Serializable { - ctor @dalvik.annotation.compat.UnsupportedAppUsage @libcore.api.IntraCoreApi public OpenSSLRandom(); - } - - @libcore.api.IntraCoreApi public class OpenSSLSignature extends java.security.SignatureSpi { - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.MD5RSA extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.MD5RSA(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA1ECDSA extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA1ECDSA(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA1RSA extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA1RSA(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA1RSAPSS extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA1RSAPSS(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA224ECDSA extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA224ECDSA(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA224RSA extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA224RSA(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA224RSAPSS extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA224RSAPSS(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA256ECDSA extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA256ECDSA(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA256RSA extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA256RSA(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA256RSAPSS extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA256RSAPSS(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA384ECDSA extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA384ECDSA(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA384RSA extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA384RSA(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA384RSAPSS extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA384RSAPSS(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA512ECDSA extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA512ECDSA(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA512RSA extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA512RSA(); - } - - @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA512RSAPSS extends com.android.org.conscrypt.OpenSSLSignature { - ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA512RSAPSS(); - } - - @libcore.api.IntraCoreApi public class OpenSSLSignatureRawECDSA extends java.security.SignatureSpi { - ctor @libcore.api.IntraCoreApi public OpenSSLSignatureRawECDSA(); - } - - @libcore.api.IntraCoreApi public final class OpenSSLSignatureRawRSA extends java.security.SignatureSpi { - ctor @libcore.api.IntraCoreApi public OpenSSLSignatureRawRSA(); - } +} - @libcore.api.IntraCoreApi public class OpenSSLX509CertificateFactory extends java.security.cert.CertificateFactorySpi { - ctor @libcore.api.IntraCoreApi public OpenSSLX509CertificateFactory(); - } +package dalvik.annotation.compat { - @libcore.api.IntraCoreApi public class PSSParameters extends java.security.AlgorithmParametersSpi { - ctor @libcore.api.IntraCoreApi public PSSParameters(); + @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public class VersionCodes { + field @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static final int O = 26; // 0x1a + field @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static final int P = 28; // 0x1c + field @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static final int Q = 29; // 0x1d } } -package dalvik.annotation.compat { - - @java.lang.annotation.Repeatable(UnsupportedAppUsage.Container.class) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.TYPE}) @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public @interface UnsupportedAppUsage { - method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public abstract String expectedSignature() default ""; - method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public abstract String implicitMember() default ""; - method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public abstract int maxTargetSdk() default java.lang.Integer.MAX_VALUE; - method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public abstract long trackingBug() default 0; - } +package dalvik.annotation.optimization { - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static @interface UnsupportedAppUsage.Container { - method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public abstract dalvik.annotation.compat.UnsupportedAppUsage[] value(); + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) @libcore.api.IntraCoreApi public @interface ReachabilitySensitive { } } @@ -417,23 +39,18 @@ package dalvik.annotation.compat { package dalvik.system { @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public final class BlockGuard { - method @NonNull @dalvik.annotation.compat.UnsupportedAppUsage @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static dalvik.system.BlockGuard.Policy getThreadPolicy(); + method @NonNull @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static dalvik.system.BlockGuard.Policy getThreadPolicy(); } @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static interface BlockGuard.Policy { - method @dalvik.annotation.compat.UnsupportedAppUsage @libcore.api.IntraCoreApi public void onNetwork(); + method @libcore.api.IntraCoreApi public void onNetwork(); } @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public final class CloseGuard { - method @dalvik.annotation.compat.UnsupportedAppUsage @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public void close(); - method @dalvik.annotation.compat.UnsupportedAppUsage @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static dalvik.system.CloseGuard get(); - method @dalvik.annotation.compat.UnsupportedAppUsage @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public void open(String); - method @dalvik.annotation.compat.UnsupportedAppUsage @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public void warnIfOpen(); - } - - @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public class VersionCodes { - field @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static final int O = 26; // 0x1a - field @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static final int P = 28; // 0x1c + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public void close(); + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static dalvik.system.CloseGuard get(); + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public void open(String); + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public void warnIfOpen(); } } @@ -446,6 +63,22 @@ package java.net { } +package java.nio.charset { + + public abstract class Charset implements java.lang.Comparable<java.nio.charset.Charset> { + ctor @libcore.api.IntraCoreApi protected Charset(String, String[]); + } + + public abstract class CharsetDecoder { + ctor protected CharsetDecoder(java.nio.charset.Charset, float, float); + } + + public abstract class CharsetEncoder { + ctor protected CharsetEncoder(java.nio.charset.Charset, float, float, byte[], boolean); + } + +} + package java.security.spec { public class ECParameterSpec implements java.security.spec.AlgorithmParameterSpec { @@ -465,6 +98,14 @@ package libcore.api { } +package libcore.io { + + @libcore.api.IntraCoreApi public final class AsynchronousCloseMonitor { + method @libcore.api.IntraCoreApi public static void signalBlockedThreads(java.io.FileDescriptor); + } + +} + package libcore.net { @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public abstract class NetworkSecurityPolicy { @@ -477,10 +118,15 @@ package libcore.net { package libcore.util { - @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE_USE}) @libcore.api.IntraCoreApi public @interface NonNull { + @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public class NativeAllocationRegistry { + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static libcore.util.NativeAllocationRegistry createMalloced(ClassLoader, long); + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public Runnable registerNativeAllocation(Object, long); + } + + @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.TYPE_USE}) @libcore.api.IntraCoreApi public @interface NonNull { } - @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE_USE}) @libcore.api.IntraCoreApi public @interface Nullable { + @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.TYPE_USE}) @libcore.api.IntraCoreApi public @interface Nullable { } } diff --git a/mmodules/intracoreapi/api/intra/last-api.txt b/mmodules/intracoreapi/api/intra/last-api.txt index e69de29bb2..a62bfb60ac 100644 --- a/mmodules/intracoreapi/api/intra/last-api.txt +++ b/mmodules/intracoreapi/api/intra/last-api.txt @@ -0,0 +1,88 @@ +// Signature format: 2.0 +package dalvik.annotation.compat { + + @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public class VersionCodes { + field @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static final int Q = 29; // 0x1d + } + +} + +package dalvik.system { + + @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public final class BlockGuard { + method @NonNull @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static dalvik.system.BlockGuard.Policy getThreadPolicy(); + } + + @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static interface BlockGuard.Policy { + method @libcore.api.IntraCoreApi public void onNetwork(); + } + + @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public final class CloseGuard { + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public void close(); + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static dalvik.system.CloseGuard get(); + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public void open(String); + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public void warnIfOpen(); + } + +} + +package java.net { + + public class Socket implements java.io.Closeable { + method public java.io.FileDescriptor getFileDescriptor$(); + } + +} + +package java.security.spec { + + public class ECParameterSpec implements java.security.spec.AlgorithmParameterSpec { + method public String getCurveName(); + method public void setCurveName(String); + } + +} + +package libcore.api { + + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.ANNOTATION_TYPE}) @libcore.api.IntraCoreApi public @interface CorePlatformApi { + } + + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.ANNOTATION_TYPE}) @libcore.api.IntraCoreApi public @interface IntraCoreApi { + } + +} + +package libcore.io { + + @libcore.api.IntraCoreApi public final class AsynchronousCloseMonitor { + method @libcore.api.IntraCoreApi public static void signalBlockedThreads(java.io.FileDescriptor); + } + +} + +package libcore.net { + + @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public abstract class NetworkSecurityPolicy { + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static libcore.net.NetworkSecurityPolicy getInstance(); + method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public abstract boolean isCertificateTransparencyVerificationRequired(String); + } + +} + +package libcore.util { + + @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.TYPE_USE}) @libcore.api.IntraCoreApi public @interface NonNull { + } + +} + +package sun.security.x509 { + + public class AlgorithmId implements java.io.Serializable { + method public static sun.security.x509.AlgorithmId get(String) throws java.security.NoSuchAlgorithmException; + method public String getName(); + } + +} + diff --git a/non_openjdk_java_files.bp b/non_openjdk_java_files.bp index 3e4083fdef..e3c8c16c9e 100644 --- a/non_openjdk_java_files.bp +++ b/non_openjdk_java_files.bp @@ -1,32 +1,18 @@ filegroup { name: "non_openjdk_javadoc_files", srcs: [ - "luni/src/main/java/android/system/ErrnoException.java", - "luni/src/main/java/android/system/GaiException.java", - "luni/src/main/java/android/system/Int32Ref.java", - "luni/src/main/java/android/system/Int64Ref.java", - "luni/src/main/java/android/system/NetlinkSocketAddress.java", - "luni/src/main/java/android/system/Os.java", - "luni/src/main/java/android/system/OsConstants.java", - "luni/src/main/java/android/system/PacketSocketAddress.java", - "luni/src/main/java/android/system/StructAddrinfo.java", - "luni/src/main/java/android/system/StructCapUserData.java", - "luni/src/main/java/android/system/StructCapUserHeader.java", - "luni/src/main/java/android/system/StructFlock.java", - "luni/src/main/java/android/system/StructGroupReq.java", - "luni/src/main/java/android/system/StructIcmpHdr.java", - "luni/src/main/java/android/system/StructIfaddrs.java", - "luni/src/main/java/android/system/StructLinger.java", - "luni/src/main/java/android/system/StructPasswd.java", - "luni/src/main/java/android/system/StructPollfd.java", - "luni/src/main/java/android/system/StructRlimit.java", - "luni/src/main/java/android/system/StructStat.java", - "luni/src/main/java/android/system/StructStatVfs.java", - "luni/src/main/java/android/system/StructTimeval.java", - "luni/src/main/java/android/system/StructTimespec.java", - "luni/src/main/java/android/system/StructUcred.java", - "luni/src/main/java/android/system/StructUtsname.java", - "luni/src/main/java/android/system/UnixSocketAddress.java", + ":non_openjdk_javadoc_dalvik_files", + ":non_openjdk_javadoc_json_files", + ":non_openjdk_javadoc_libart_files", + ":non_openjdk_javadoc_luni_files", + ":non_openjdk_javadoc_xml_files", + ], + visibility: ["//visibility:private"], +} + +filegroup { + name: "non_openjdk_javadoc_dalvik_files", + srcs: [ "dalvik/src/main/java/dalvik/annotation/AnnotationDefault.java", "dalvik/src/main/java/dalvik/annotation/EnclosingClass.java", "dalvik/src/main/java/dalvik/annotation/EnclosingMethod.java", @@ -39,7 +25,6 @@ filegroup { "dalvik/src/main/java/dalvik/annotation/TestTargetClass.java", "dalvik/src/main/java/dalvik/annotation/Throws.java", "dalvik/src/main/java/dalvik/annotation/codegen/CovariantReturnType.java", - "dalvik/src/main/java/dalvik/annotation/compat/UnsupportedAppUsage.java", "dalvik/src/main/java/dalvik/annotation/optimization/CriticalNative.java", "dalvik/src/main/java/dalvik/annotation/optimization/DeadReferenceSafe.java", "dalvik/src/main/java/dalvik/annotation/optimization/FastNative.java", @@ -47,10 +32,8 @@ filegroup { "dalvik/src/main/java/dalvik/bytecode/OpcodeInfo.java", "dalvik/src/main/java/dalvik/bytecode/Opcodes.java", "dalvik/src/main/java/dalvik/system/AllocationLimitError.java", - "libart/src/main/java/dalvik/system/AnnotatedStackTraceElement.java", "dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java", "dalvik/src/main/java/dalvik/system/BlockGuard.java", - "libart/src/main/java/dalvik/system/ClassExt.java", "dalvik/src/main/java/dalvik/system/CloseGuard.java", "dalvik/src/main/java/dalvik/system/DalvikLogHandler.java", "dalvik/src/main/java/dalvik/system/DalvikLogging.java", @@ -66,21 +49,114 @@ filegroup { "dalvik/src/main/java/dalvik/system/RuntimeHooks.java", "dalvik/src/main/java/dalvik/system/SocketTagger.java", "dalvik/src/main/java/dalvik/system/TemporaryDirectory.java", - "libart/src/main/java/dalvik/system/TransactionAbortError.java", - "dalvik/src/main/java/dalvik/system/VersionCodes.java", + "dalvik/src/main/java/dalvik/system/ThreadPrioritySetter.java", "dalvik/src/main/java/dalvik/system/VMDebug.java", + "dalvik/src/main/java/dalvik/system/ZygoteHooks.java", + "dalvik/src/main/java/org/apache/harmony/dalvik/NativeTestTarget.java", + "dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/Chunk.java", + "dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/ChunkHandler.java", + "dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmServer.java", + "dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmVmInternal.java", + ":hidden_api_surface_annotation_files", + ], + path: "dalvik/src/main", + visibility: ["//visibility:private"], +} + +filegroup { + name: "non_openjdk_javadoc_json_files", + srcs: [ + "json/src/main/java/org/json/JSON.java", + "json/src/main/java/org/json/JSONArray.java", + "json/src/main/java/org/json/JSONException.java", + "json/src/main/java/org/json/JSONObject.java", + "json/src/main/java/org/json/JSONStringer.java", + "json/src/main/java/org/json/JSONTokener.java", + ], + path: "json/src/main", + visibility: ["//visibility:private"], +} + +filegroup { + name: "non_openjdk_javadoc_libart_files", + srcs: [ + "libart/src/main/java/dalvik/system/AnnotatedStackTraceElement.java", + "libart/src/main/java/dalvik/system/ClassExt.java", + "libart/src/main/java/dalvik/system/TransactionAbortError.java", "libart/src/main/java/dalvik/system/VMRuntime.java", "libart/src/main/java/dalvik/system/VMStack.java", - "dalvik/src/main/java/dalvik/system/ZygoteHooks.java", "libart/src/main/java/java/lang/AndroidHardcodedSystemProperties.java", "libart/src/main/java/java/lang/Daemons.java", "libart/src/main/java/java/lang/DexCache.java", - "luni/src/main/java/java/lang/FindBugsSuppressWarnings.java", "libart/src/main/java/java/lang/VMClassLoader.java", "libart/src/main/java/java/lang/invoke/ArrayElementVarHandle.java", "libart/src/main/java/java/lang/invoke/ByteArrayViewVarHandle.java", "libart/src/main/java/java/lang/invoke/ByteBufferViewVarHandle.java", "libart/src/main/java/java/lang/invoke/FieldVarHandle.java", + ], + path: "libart/src/main", + visibility: ["//visibility:private"], +} + +// The set of annotations used for defining visible (i.e. not hidden) API +// surfaces. +filegroup { + name: "visible_api_surface_annotation_files", + srcs: [ + "luni/src/main/java/libcore/api/CorePlatformApi.java", + "luni/src/main/java/libcore/api/Hide.java", + "luni/src/main/java/libcore/api/IntraCoreApi.java", + ], +} + +// The set of annotations used for defining the hidden API surface. +filegroup { + name: "hidden_api_surface_annotation_files", + srcs: [ + "dalvik/src/main/java/dalvik/annotation/compat/VersionCodes.java", + ], +} + +// The set of annotations used for defining all API surfaces, including hidden +// APIs. +filegroup { + name: "api_surface_annotation_files", + srcs: [ + ":hidden_api_surface_annotation_files", + ":visible_api_surface_annotation_files", + ], +} + +filegroup { + name: "non_openjdk_javadoc_luni_files", + srcs: [ + "luni/src/main/java/android/compat/Compatibility.java", + "luni/src/main/java/android/system/ErrnoException.java", + "luni/src/main/java/android/system/GaiException.java", + "luni/src/main/java/android/system/IcmpHeaders.java", + "luni/src/main/java/android/system/Int32Ref.java", + "luni/src/main/java/android/system/Int64Ref.java", + "luni/src/main/java/android/system/NetlinkSocketAddress.java", + "luni/src/main/java/android/system/Os.java", + "luni/src/main/java/android/system/OsConstants.java", + "luni/src/main/java/android/system/PacketSocketAddress.java", + "luni/src/main/java/android/system/StructAddrinfo.java", + "luni/src/main/java/android/system/StructCapUserData.java", + "luni/src/main/java/android/system/StructCapUserHeader.java", + "luni/src/main/java/android/system/StructGroupReq.java", + "luni/src/main/java/android/system/StructIfaddrs.java", + "luni/src/main/java/android/system/StructLinger.java", + "luni/src/main/java/android/system/StructPasswd.java", + "luni/src/main/java/android/system/StructPollfd.java", + "luni/src/main/java/android/system/StructRlimit.java", + "luni/src/main/java/android/system/StructStat.java", + "luni/src/main/java/android/system/StructStatVfs.java", + "luni/src/main/java/android/system/StructTimespec.java", + "luni/src/main/java/android/system/StructTimeval.java", + "luni/src/main/java/android/system/StructUcred.java", + "luni/src/main/java/android/system/StructUtsname.java", + "luni/src/main/java/android/system/UnixSocketAddress.java", + "luni/src/main/java/java/lang/FindBugsSuppressWarnings.java", "luni/src/main/java/java/lang/ref/FinalizerReference.java", "luni/src/main/java/java/math/BigDecimal.java", "luni/src/main/java/java/math/BigInt.java", @@ -97,10 +173,6 @@ filegroup { "luni/src/main/java/java/net/DefaultFileNameMap.java", "luni/src/main/java/java/nio/NIOAccess.java", "luni/src/main/java/java/nio/NioUtils.java", - "luni/src/main/java/java/nio/charset/CharsetDecoderICU.java", - "luni/src/main/java/java/nio/charset/CharsetEncoderICU.java", - "luni/src/main/java/java/nio/charset/CharsetICU.java", - "luni/src/main/java/java/nio/charset/ModifiedUtf8.java", "luni/src/main/java/javax/xml/XMLConstants.java", "luni/src/main/java/javax/xml/datatype/DatatypeConfigurationException.java", "luni/src/main/java/javax/xml/datatype/DatatypeConstants.java", @@ -159,15 +231,14 @@ filegroup { "luni/src/main/java/javax/xml/xpath/XPathFunctionException.java", "luni/src/main/java/javax/xml/xpath/XPathFunctionResolver.java", "luni/src/main/java/javax/xml/xpath/XPathVariableResolver.java", - "luni/src/main/java/libcore/api/CorePlatformApi.java", + "luni/src/main/java/libcore/content/type/MimeMap.java", "luni/src/main/java/libcore/icu/DateIntervalFormat.java", - "luni/src/main/java/libcore/api/Hide.java", - "luni/src/main/java/libcore/api/IntraCoreApi.java", "luni/src/main/java/libcore/icu/ICU.java", "luni/src/main/java/libcore/icu/LocaleData.java", "luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java", "luni/src/main/java/libcore/icu/TimeZoneNames.java", "luni/src/main/java/libcore/internal/StringPool.java", + "luni/src/main/java/libcore/io/AsynchronousCloseMonitor.java", "luni/src/main/java/libcore/io/ForwardingOs.java", "luni/src/main/java/libcore/io/IoBridge.java", "luni/src/main/java/libcore/io/IoUtils.java", @@ -176,20 +247,24 @@ filegroup { "luni/src/main/java/libcore/io/Os.java", "luni/src/main/java/libcore/io/Streams.java", "luni/src/main/java/libcore/net/InetAddressUtils.java", - "luni/src/main/java/libcore/net/MimeUtils.java", "luni/src/main/java/libcore/net/NetworkSecurityPolicy.java", "luni/src/main/java/libcore/net/event/NetworkEventDispatcher.java", "luni/src/main/java/libcore/timezone/CountryTimeZones.java", "luni/src/main/java/libcore/timezone/CountryZonesFinder.java", + "luni/src/main/java/libcore/timezone/TelephonyLookup.java", + "luni/src/main/java/libcore/timezone/TelephonyNetwork.java", + "luni/src/main/java/libcore/timezone/TelephonyNetworkFinder.java", "luni/src/main/java/libcore/timezone/TimeZoneDataFiles.java", "luni/src/main/java/libcore/timezone/TimeZoneFinder.java", "luni/src/main/java/libcore/timezone/TzDataSetVersion.java", - "luni/src/main/java/libcore/timezone/ZoneInfoDB.java", + "luni/src/main/java/libcore/timezone/XmlUtils.java", + "luni/src/main/java/libcore/timezone/ZoneInfoDb.java", "luni/src/main/java/libcore/util/ArrayUtils.java", "luni/src/main/java/libcore/util/BasicLruCache.java", "luni/src/main/java/libcore/util/CoreLibraryDebug.java", "luni/src/main/java/libcore/util/DebugInfo.java", "luni/src/main/java/libcore/util/EmptyArray.java", + "luni/src/main/java/libcore/util/FP16.java", "luni/src/main/java/libcore/util/HexEncoding.java", "luni/src/main/java/libcore/util/NativeAllocationRegistry.java", "luni/src/main/java/libcore/util/NonNull.java", @@ -197,17 +272,6 @@ filegroup { "luni/src/main/java/libcore/util/SneakyThrow.java", "luni/src/main/java/libcore/util/XmlObjectFactory.java", "luni/src/main/java/libcore/util/ZoneInfo.java", - "dalvik/src/main/java/org/apache/harmony/dalvik/NativeTestTarget.java", - "dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/Chunk.java", - "dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/ChunkHandler.java", - "dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmServer.java", - "dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmVmInternal.java", - "json/src/main/java/org/json/JSON.java", - "json/src/main/java/org/json/JSONArray.java", - "json/src/main/java/org/json/JSONException.java", - "json/src/main/java/org/json/JSONObject.java", - "json/src/main/java/org/json/JSONStringer.java", - "json/src/main/java/org/json/JSONTokener.java", "luni/src/main/java/org/w3c/dom/Attr.java", "luni/src/main/java/org/w3c/dom/CDATASection.java", "luni/src/main/java/org/w3c/dom/CharacterData.java", @@ -283,24 +347,36 @@ filegroup { "luni/src/main/java/org/xml/sax/helpers/XMLFilterImpl.java", "luni/src/main/java/org/xml/sax/helpers/XMLReaderAdapter.java", "luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java", + ":visible_api_surface_annotation_files", + ], + path: "luni/src/main", + visibility: ["//visibility:private"], +} + +filegroup { + name: "non_openjdk_javadoc_xml_files", + srcs: [ "xml/src/main/java/org/xmlpull/v1/XmlPullParser.java", "xml/src/main/java/org/xmlpull/v1/XmlPullParserException.java", "xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java", "xml/src/main/java/org/xmlpull/v1/XmlSerializer.java", "xml/src/main/java/org/xmlpull/v1/sax2/Driver.java", ], + path: "xml/src/main", + visibility: ["//visibility:private"], } filegroup { name: "non_openjdk_java_files", + visibility: [ + "//frameworks/base", + ], srcs: [ "luni/src/main/java/java/net/AddressCache.java", "luni/src/main/java/libcore/icu/CollationKeyICU.java", "luni/src/main/java/libcore/icu/DateTimeFormat.java", "luni/src/main/java/libcore/icu/DateUtilsBridge.java", - "luni/src/main/java/libcore/icu/NativeConverter.java", "luni/src/main/java/libcore/internal/Java9LanguageFeatures.java", - "luni/src/main/java/libcore/io/AsynchronousCloseMonitor.java", "luni/src/main/java/libcore/io/ClassPathURLStreamHandler.java", "luni/src/main/java/libcore/io/BlockGuardOs.java", "luni/src/main/java/libcore/io/BufferIterator.java", @@ -311,7 +387,6 @@ filegroup { "luni/src/main/java/libcore/math/MathUtils.java", "luni/src/main/java/libcore/net/event/NetworkEventListener.java", "luni/src/main/java/libcore/net/http/HttpDate.java", - "luni/src/main/java/libcore/net/http/ResponseUtils.java", "luni/src/main/java/libcore/reflect/AnnotatedElements.java", "luni/src/main/java/libcore/reflect/AnnotationFactory.java", "luni/src/main/java/libcore/reflect/AnnotationMember.java", @@ -326,8 +401,6 @@ filegroup { "luni/src/main/java/libcore/reflect/WildcardTypeImpl.java", "luni/src/main/java/libcore/util/CharsetUtils.java", "luni/src/main/java/libcore/util/CollectionUtils.java", - "luni/src/main/java/libcore/util/NonNull.java", - "luni/src/main/java/libcore/util/Nullable.java", "luni/src/main/java/libcore/util/NullFromTypeParam.java", "luni/src/main/java/libcore/util/Objects.java", "luni/src/main/java/org/apache/harmony/xml/ExpatAttributes.java", @@ -373,6 +446,7 @@ filegroup { srcs: [ "luni/src/main/java/libcore/api/CorePlatformApi.java", "luni/src/main/java/libcore/api/IntraCoreApi.java", + "luni/src/main/java/libcore/timezone/TimeZoneDataFiles.java", "luni/src/main/java/libcore/timezone/TzDataSetVersion.java", ], } diff --git a/ojluni/Android.bp b/ojluni/Android.bp new file mode 100644 index 0000000000..20a5a5a1a6 --- /dev/null +++ b/ojluni/Android.bp @@ -0,0 +1,26 @@ +// 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. + +// Phony target that causes the build to check the license file in this +// directory, detect that it is a GPL license and then copy all the files +// from this directory and its subdirectories in to the +// ${OUT}/obj/PACKAGING/gpl_source_intermediates/gpl_source.tgz file. +phony { + name: "ojluni-phony", + + // A phony module must have at least one dependency. + required: [ + "core-oj", + ], +} diff --git a/ojluni/annotations/hiddenapi/com/sun/nio/file/ExtendedWatchEventModifier.java b/ojluni/annotations/hiddenapi/com/sun/nio/file/ExtendedWatchEventModifier.java index d3d1fd7a4c..9abd97c8d8 100644 --- a/ojluni/annotations/hiddenapi/com/sun/nio/file/ExtendedWatchEventModifier.java +++ b/ojluni/annotations/hiddenapi/com/sun/nio/file/ExtendedWatchEventModifier.java @@ -27,7 +27,7 @@ package com.sun.nio.file; @SuppressWarnings({"unchecked", "deprecation", "all"}) public enum ExtendedWatchEventModifier implements java.nio.file.WatchEvent.Modifier { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage FILE_TREE; private ExtendedWatchEventModifier() { diff --git a/ojluni/annotations/hiddenapi/java/io/Console.java b/ojluni/annotations/hiddenapi/java/io/Console.java index 9a93310b78..24039a1e1b 100644 --- a/ojluni/annotations/hiddenapi/java/io/Console.java +++ b/ojluni/annotations/hiddenapi/java/io/Console.java @@ -26,7 +26,7 @@ package java.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Console implements java.io.Flushable { diff --git a/ojluni/annotations/hiddenapi/java/io/File.java b/ojluni/annotations/hiddenapi/java/io/File.java index 7b93218cad..bdcce885bd 100644 --- a/ojluni/annotations/hiddenapi/java/io/File.java +++ b/ojluni/annotations/hiddenapi/java/io/File.java @@ -26,7 +26,7 @@ package java.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class File implements java.io.Serializable, java.lang.Comparable<java.io.File> { diff --git a/ojluni/annotations/hiddenapi/java/io/FileDescriptor.java b/ojluni/annotations/hiddenapi/java/io/FileDescriptor.java index 7872403862..6e9e74d4c4 100644 --- a/ojluni/annotations/hiddenapi/java/io/FileDescriptor.java +++ b/ojluni/annotations/hiddenapi/java/io/FileDescriptor.java @@ -25,7 +25,7 @@ package java.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class FileDescriptor { diff --git a/ojluni/annotations/hiddenapi/java/io/FileInputStream.java b/ojluni/annotations/hiddenapi/java/io/FileInputStream.java index 3de1617018..1999d13128 100644 --- a/ojluni/annotations/hiddenapi/java/io/FileInputStream.java +++ b/ojluni/annotations/hiddenapi/java/io/FileInputStream.java @@ -26,7 +26,7 @@ package java.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class FileInputStream extends java.io.InputStream { diff --git a/ojluni/annotations/hiddenapi/java/io/FileOutputStream.java b/ojluni/annotations/hiddenapi/java/io/FileOutputStream.java index b918f6ac3a..5e35fc09ed 100644 --- a/ojluni/annotations/hiddenapi/java/io/FileOutputStream.java +++ b/ojluni/annotations/hiddenapi/java/io/FileOutputStream.java @@ -26,7 +26,7 @@ package java.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class FileOutputStream extends java.io.OutputStream { diff --git a/ojluni/annotations/hiddenapi/java/io/FileSystem.java b/ojluni/annotations/hiddenapi/java/io/FileSystem.java index 4999b3c64b..e522846cd3 100644 --- a/ojluni/annotations/hiddenapi/java/io/FileSystem.java +++ b/ojluni/annotations/hiddenapi/java/io/FileSystem.java @@ -26,7 +26,7 @@ package java.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) abstract class FileSystem { diff --git a/ojluni/annotations/hiddenapi/java/io/ObjectInputStream.java b/ojluni/annotations/hiddenapi/java/io/ObjectInputStream.java index 90dcfea0cb..562d846f23 100644 --- a/ojluni/annotations/hiddenapi/java/io/ObjectInputStream.java +++ b/ojluni/annotations/hiddenapi/java/io/ObjectInputStream.java @@ -26,7 +26,7 @@ package java.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ObjectInputStream extends java.io.InputStream diff --git a/ojluni/annotations/hiddenapi/java/io/ObjectOutputStream.java b/ojluni/annotations/hiddenapi/java/io/ObjectOutputStream.java index f3e462d671..1e429a43e4 100644 --- a/ojluni/annotations/hiddenapi/java/io/ObjectOutputStream.java +++ b/ojluni/annotations/hiddenapi/java/io/ObjectOutputStream.java @@ -26,7 +26,7 @@ package java.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ObjectOutputStream extends java.io.OutputStream diff --git a/ojluni/annotations/hiddenapi/java/io/ObjectStreamClass.java b/ojluni/annotations/hiddenapi/java/io/ObjectStreamClass.java index d617d32934..658d60178f 100644 --- a/ojluni/annotations/hiddenapi/java/io/ObjectStreamClass.java +++ b/ojluni/annotations/hiddenapi/java/io/ObjectStreamClass.java @@ -25,7 +25,7 @@ package java.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ObjectStreamClass implements java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/io/ObjectStreamField.java b/ojluni/annotations/hiddenapi/java/io/ObjectStreamField.java index b3b7c34691..36ba79917e 100644 --- a/ojluni/annotations/hiddenapi/java/io/ObjectStreamField.java +++ b/ojluni/annotations/hiddenapi/java/io/ObjectStreamField.java @@ -25,7 +25,7 @@ package java.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ObjectStreamField implements java.lang.Comparable<java.lang.Object> { diff --git a/ojluni/annotations/hiddenapi/java/io/RandomAccessFile.java b/ojluni/annotations/hiddenapi/java/io/RandomAccessFile.java index 32d36ab1ca..5bc7d69e2b 100644 --- a/ojluni/annotations/hiddenapi/java/io/RandomAccessFile.java +++ b/ojluni/annotations/hiddenapi/java/io/RandomAccessFile.java @@ -26,7 +26,7 @@ package java.io; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class RandomAccessFile implements java.io.DataOutput, java.io.DataInput, java.io.Closeable { diff --git a/ojluni/annotations/hiddenapi/java/lang/AbstractStringBuilder.java b/ojluni/annotations/hiddenapi/java/lang/AbstractStringBuilder.java index 42a5b552f9..4ec2383068 100644 --- a/ojluni/annotations/hiddenapi/java/lang/AbstractStringBuilder.java +++ b/ojluni/annotations/hiddenapi/java/lang/AbstractStringBuilder.java @@ -25,7 +25,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) abstract class AbstractStringBuilder implements java.lang.Appendable, java.lang.CharSequence { diff --git a/ojluni/annotations/hiddenapi/java/lang/Boolean.java b/ojluni/annotations/hiddenapi/java/lang/Boolean.java index 14f02551b5..5f82352e3e 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Boolean.java +++ b/ojluni/annotations/hiddenapi/java/lang/Boolean.java @@ -25,8 +25,8 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VersionCodes; +import android.compat.annotation.UnsupportedAppUsage; +import dalvik.annotation.compat.VersionCodes; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Boolean diff --git a/ojluni/annotations/hiddenapi/java/lang/Byte.java b/ojluni/annotations/hiddenapi/java/lang/Byte.java index 6938eb7ce5..612108b2d0 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Byte.java +++ b/ojluni/annotations/hiddenapi/java/lang/Byte.java @@ -25,8 +25,8 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VersionCodes; +import android.compat.annotation.UnsupportedAppUsage; +import dalvik.annotation.compat.VersionCodes; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Byte extends java.lang.Number implements java.lang.Comparable<java.lang.Byte> { diff --git a/ojluni/annotations/hiddenapi/java/lang/Character.java b/ojluni/annotations/hiddenapi/java/lang/Character.java index 6ac842dd9c..207008e611 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Character.java +++ b/ojluni/annotations/hiddenapi/java/lang/Character.java @@ -25,8 +25,8 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VersionCodes; +import android.compat.annotation.UnsupportedAppUsage; +import dalvik.annotation.compat.VersionCodes; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Character diff --git a/ojluni/annotations/hiddenapi/java/lang/Class.java b/ojluni/annotations/hiddenapi/java/lang/Class.java index 12a69d7eb8..a9c15152b3 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Class.java +++ b/ojluni/annotations/hiddenapi/java/lang/Class.java @@ -26,7 +26,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Class<T> diff --git a/ojluni/annotations/hiddenapi/java/lang/ClassLoader.java b/ojluni/annotations/hiddenapi/java/lang/ClassLoader.java index 6af0cb8223..b9c371ea7e 100644 --- a/ojluni/annotations/hiddenapi/java/lang/ClassLoader.java +++ b/ojluni/annotations/hiddenapi/java/lang/ClassLoader.java @@ -26,7 +26,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class ClassLoader { diff --git a/ojluni/annotations/hiddenapi/java/lang/Double.java b/ojluni/annotations/hiddenapi/java/lang/Double.java index 187b7b4887..1daeeb97ea 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Double.java +++ b/ojluni/annotations/hiddenapi/java/lang/Double.java @@ -25,8 +25,8 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VersionCodes; +import android.compat.annotation.UnsupportedAppUsage; +import dalvik.annotation.compat.VersionCodes; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Double extends java.lang.Number diff --git a/ojluni/annotations/hiddenapi/java/lang/Enum.java b/ojluni/annotations/hiddenapi/java/lang/Enum.java index 369e58e037..8cd1b6dc5b 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Enum.java +++ b/ojluni/annotations/hiddenapi/java/lang/Enum.java @@ -26,7 +26,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class Enum<E extends java.lang.Enum<E>> diff --git a/ojluni/annotations/hiddenapi/java/lang/Float.java b/ojluni/annotations/hiddenapi/java/lang/Float.java index 1081764c46..98f0b093ea 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Float.java +++ b/ojluni/annotations/hiddenapi/java/lang/Float.java @@ -25,8 +25,8 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VersionCodes; +import android.compat.annotation.UnsupportedAppUsage; +import dalvik.annotation.compat.VersionCodes; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Float extends java.lang.Number implements java.lang.Comparable<java.lang.Float> { diff --git a/ojluni/annotations/hiddenapi/java/lang/Integer.java b/ojluni/annotations/hiddenapi/java/lang/Integer.java index adb8c9c19a..388878e18e 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Integer.java +++ b/ojluni/annotations/hiddenapi/java/lang/Integer.java @@ -26,8 +26,8 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VersionCodes; +import android.compat.annotation.UnsupportedAppUsage; +import dalvik.annotation.compat.VersionCodes; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Integer extends java.lang.Number diff --git a/ojluni/annotations/hiddenapi/java/lang/Long.java b/ojluni/annotations/hiddenapi/java/lang/Long.java index 2f32b27385..e3041cc6ce 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Long.java +++ b/ojluni/annotations/hiddenapi/java/lang/Long.java @@ -26,8 +26,8 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VersionCodes; +import android.compat.annotation.UnsupportedAppUsage; +import dalvik.annotation.compat.VersionCodes; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Long extends java.lang.Number implements java.lang.Comparable<java.lang.Long> { diff --git a/ojluni/annotations/hiddenapi/java/lang/Object.java b/ojluni/annotations/hiddenapi/java/lang/Object.java index 5289874686..7b26bf5e66 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Object.java +++ b/ojluni/annotations/hiddenapi/java/lang/Object.java @@ -26,7 +26,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Object { diff --git a/ojluni/annotations/hiddenapi/java/lang/Runtime.java b/ojluni/annotations/hiddenapi/java/lang/Runtime.java index ca8c56c34d..798967fc73 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Runtime.java +++ b/ojluni/annotations/hiddenapi/java/lang/Runtime.java @@ -26,7 +26,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Runtime { diff --git a/ojluni/annotations/hiddenapi/java/lang/Short.java b/ojluni/annotations/hiddenapi/java/lang/Short.java index f1f06418bc..05f18cece5 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Short.java +++ b/ojluni/annotations/hiddenapi/java/lang/Short.java @@ -25,8 +25,8 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VersionCodes; +import android.compat.annotation.UnsupportedAppUsage; +import dalvik.annotation.compat.VersionCodes; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Short extends java.lang.Number implements java.lang.Comparable<java.lang.Short> { diff --git a/ojluni/annotations/hiddenapi/java/lang/StackTraceElement.java b/ojluni/annotations/hiddenapi/java/lang/StackTraceElement.java index a396013ddf..010d949dae 100644 --- a/ojluni/annotations/hiddenapi/java/lang/StackTraceElement.java +++ b/ojluni/annotations/hiddenapi/java/lang/StackTraceElement.java @@ -25,7 +25,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class StackTraceElement implements java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/lang/String.java b/ojluni/annotations/hiddenapi/java/lang/String.java index 51fdfb7add..a7b137a519 100644 --- a/ojluni/annotations/hiddenapi/java/lang/String.java +++ b/ojluni/annotations/hiddenapi/java/lang/String.java @@ -26,7 +26,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class String diff --git a/ojluni/annotations/hiddenapi/java/lang/System.java b/ojluni/annotations/hiddenapi/java/lang/System.java index a401efdbca..407473b1d2 100644 --- a/ojluni/annotations/hiddenapi/java/lang/System.java +++ b/ojluni/annotations/hiddenapi/java/lang/System.java @@ -26,7 +26,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class System { diff --git a/ojluni/annotations/hiddenapi/java/lang/Thread.java b/ojluni/annotations/hiddenapi/java/lang/Thread.java index 2e8557b276..36ca327997 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Thread.java +++ b/ojluni/annotations/hiddenapi/java/lang/Thread.java @@ -26,7 +26,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Thread implements java.lang.Runnable { @@ -429,7 +429,9 @@ public class Thread implements java.lang.Runnable { long threadLocalRandomSeed; - @UnsupportedAppUsage + @UnsupportedAppUsage(publicAlternatives = "Please update to a current version of the " + + "{@code Streamsupport} library; older versions of {@code Streamsupport} do not " + + "support current versions of Android.") java.lang.ThreadLocal.ThreadLocalMap threadLocals; private java.lang.Thread threadQ; diff --git a/ojluni/annotations/hiddenapi/java/lang/ThreadGroup.java b/ojluni/annotations/hiddenapi/java/lang/ThreadGroup.java index ee9feb0e58..bc6903318d 100644 --- a/ojluni/annotations/hiddenapi/java/lang/ThreadGroup.java +++ b/ojluni/annotations/hiddenapi/java/lang/ThreadGroup.java @@ -26,7 +26,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ThreadGroup implements java.lang.Thread.UncaughtExceptionHandler { diff --git a/ojluni/annotations/hiddenapi/java/lang/ThreadLocal.java b/ojluni/annotations/hiddenapi/java/lang/ThreadLocal.java index 5772a6d5ac..ca5927b706 100644 --- a/ojluni/annotations/hiddenapi/java/lang/ThreadLocal.java +++ b/ojluni/annotations/hiddenapi/java/lang/ThreadLocal.java @@ -25,7 +25,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ThreadLocal<T> { diff --git a/ojluni/annotations/hiddenapi/java/lang/Throwable.java b/ojluni/annotations/hiddenapi/java/lang/Throwable.java index 0bc7d12cf1..00a3b2c168 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Throwable.java +++ b/ojluni/annotations/hiddenapi/java/lang/Throwable.java @@ -26,7 +26,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Throwable implements java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/lang/UNIXProcess.java b/ojluni/annotations/hiddenapi/java/lang/UNIXProcess.java index 75c3aa88e8..974ca3ebfa 100644 --- a/ojluni/annotations/hiddenapi/java/lang/UNIXProcess.java +++ b/ojluni/annotations/hiddenapi/java/lang/UNIXProcess.java @@ -104,7 +104,7 @@ final class UNIXProcess extends java.lang.Process { private boolean hasExited; - @dalvik.annotation.compat.UnsupportedAppUsage private final int pid; + @android.compat.annotation.UnsupportedAppUsage private final int pid; { pid = 0; diff --git a/ojluni/annotations/hiddenapi/java/lang/Void.java b/ojluni/annotations/hiddenapi/java/lang/Void.java index e082300ffe..35118c44b4 100644 --- a/ojluni/annotations/hiddenapi/java/lang/Void.java +++ b/ojluni/annotations/hiddenapi/java/lang/Void.java @@ -25,7 +25,7 @@ package java.lang; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Void { diff --git a/ojluni/annotations/hiddenapi/java/lang/invoke/MethodHandles.java b/ojluni/annotations/hiddenapi/java/lang/invoke/MethodHandles.java index dcb5f1154b..d89c2a1443 100644 --- a/ojluni/annotations/hiddenapi/java/lang/invoke/MethodHandles.java +++ b/ojluni/annotations/hiddenapi/java/lang/invoke/MethodHandles.java @@ -25,7 +25,7 @@ package java.lang.invoke; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class MethodHandles { diff --git a/ojluni/annotations/hiddenapi/java/lang/invoke/SerializedLambda.java b/ojluni/annotations/hiddenapi/java/lang/invoke/SerializedLambda.java index b63d0def63..fd92ce4279 100644 --- a/ojluni/annotations/hiddenapi/java/lang/invoke/SerializedLambda.java +++ b/ojluni/annotations/hiddenapi/java/lang/invoke/SerializedLambda.java @@ -24,7 +24,7 @@ */ package java.lang.invoke; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.io.Serializable; public final class SerializedLambda implements Serializable { diff --git a/ojluni/annotations/hiddenapi/java/lang/ref/Reference.java b/ojluni/annotations/hiddenapi/java/lang/ref/Reference.java index f2239ea5a8..74359c1555 100644 --- a/ojluni/annotations/hiddenapi/java/lang/ref/Reference.java +++ b/ojluni/annotations/hiddenapi/java/lang/ref/Reference.java @@ -26,7 +26,7 @@ package java.lang.ref; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class Reference<T> { diff --git a/ojluni/annotations/hiddenapi/java/lang/ref/ReferenceQueue.java b/ojluni/annotations/hiddenapi/java/lang/ref/ReferenceQueue.java index 423b8307ad..e123068758 100644 --- a/ojluni/annotations/hiddenapi/java/lang/ref/ReferenceQueue.java +++ b/ojluni/annotations/hiddenapi/java/lang/ref/ReferenceQueue.java @@ -26,7 +26,7 @@ package java.lang.ref; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ReferenceQueue<T> { diff --git a/ojluni/annotations/hiddenapi/java/lang/reflect/AccessibleObject.java b/ojluni/annotations/hiddenapi/java/lang/reflect/AccessibleObject.java index b105a24b90..0a7060852b 100644 --- a/ojluni/annotations/hiddenapi/java/lang/reflect/AccessibleObject.java +++ b/ojluni/annotations/hiddenapi/java/lang/reflect/AccessibleObject.java @@ -26,7 +26,7 @@ package java.lang.reflect; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class AccessibleObject implements java.lang.reflect.AnnotatedElement { diff --git a/ojluni/annotations/hiddenapi/java/lang/reflect/Constructor.java b/ojluni/annotations/hiddenapi/java/lang/reflect/Constructor.java index 79d24e3ce8..5accc6a366 100644 --- a/ojluni/annotations/hiddenapi/java/lang/reflect/Constructor.java +++ b/ojluni/annotations/hiddenapi/java/lang/reflect/Constructor.java @@ -26,7 +26,7 @@ package java.lang.reflect; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Constructor<T> extends java.lang.reflect.Executable { diff --git a/ojluni/annotations/hiddenapi/java/lang/reflect/Executable.java b/ojluni/annotations/hiddenapi/java/lang/reflect/Executable.java index e40b1b1a9a..198e79f276 100644 --- a/ojluni/annotations/hiddenapi/java/lang/reflect/Executable.java +++ b/ojluni/annotations/hiddenapi/java/lang/reflect/Executable.java @@ -25,7 +25,7 @@ package java.lang.reflect; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class Executable extends java.lang.reflect.AccessibleObject diff --git a/ojluni/annotations/hiddenapi/java/lang/reflect/Field.java b/ojluni/annotations/hiddenapi/java/lang/reflect/Field.java index 2048f74d03..c11a65b9d9 100644 --- a/ojluni/annotations/hiddenapi/java/lang/reflect/Field.java +++ b/ojluni/annotations/hiddenapi/java/lang/reflect/Field.java @@ -26,7 +26,7 @@ package java.lang.reflect; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Field extends java.lang.reflect.AccessibleObject @@ -165,10 +165,6 @@ public final class Field extends java.lang.reflect.AccessibleObject public native java.lang.annotation.Annotation[] getDeclaredAnnotations(); - public int getDexFieldIndex() { - throw new RuntimeException("Stub!"); - } - @UnsupportedAppUsage public int getOffset() { throw new RuntimeException("Stub!"); @@ -181,7 +177,7 @@ public final class Field extends java.lang.reflect.AccessibleObject private java.lang.Class<?> declaringClass; - private int dexFieldIndex; + private int artFieldIndex; private int offset; diff --git a/ojluni/annotations/hiddenapi/java/lang/reflect/Parameter.java b/ojluni/annotations/hiddenapi/java/lang/reflect/Parameter.java index 40ccf9e066..9982658775 100644 --- a/ojluni/annotations/hiddenapi/java/lang/reflect/Parameter.java +++ b/ojluni/annotations/hiddenapi/java/lang/reflect/Parameter.java @@ -25,7 +25,7 @@ package java.lang.reflect; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Parameter implements java.lang.reflect.AnnotatedElement { diff --git a/ojluni/annotations/hiddenapi/java/lang/reflect/Proxy.java b/ojluni/annotations/hiddenapi/java/lang/reflect/Proxy.java index e65bf19f19..593de12cb0 100644 --- a/ojluni/annotations/hiddenapi/java/lang/reflect/Proxy.java +++ b/ojluni/annotations/hiddenapi/java/lang/reflect/Proxy.java @@ -26,7 +26,7 @@ package java.lang.reflect; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Proxy implements java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/net/Authenticator.java b/ojluni/annotations/hiddenapi/java/net/Authenticator.java index 2765044ed7..3ac00897a8 100644 --- a/ojluni/annotations/hiddenapi/java/net/Authenticator.java +++ b/ojluni/annotations/hiddenapi/java/net/Authenticator.java @@ -25,7 +25,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class Authenticator { diff --git a/ojluni/annotations/hiddenapi/java/net/DatagramSocket.java b/ojluni/annotations/hiddenapi/java/net/DatagramSocket.java index fd804c78bb..db3446a05f 100644 --- a/ojluni/annotations/hiddenapi/java/net/DatagramSocket.java +++ b/ojluni/annotations/hiddenapi/java/net/DatagramSocket.java @@ -26,7 +26,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class DatagramSocket implements java.io.Closeable { diff --git a/ojluni/annotations/hiddenapi/java/net/HttpCookie.java b/ojluni/annotations/hiddenapi/java/net/HttpCookie.java index 113e804ef3..97189e49c3 100644 --- a/ojluni/annotations/hiddenapi/java/net/HttpCookie.java +++ b/ojluni/annotations/hiddenapi/java/net/HttpCookie.java @@ -26,7 +26,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class HttpCookie implements java.lang.Cloneable { @@ -256,7 +256,8 @@ public final class HttpCookie implements java.lang.Cloneable { header = null; } - @UnsupportedAppUsage + @UnsupportedAppUsage( + publicAlternatives = "Use {@link #setHttpOnly()}/{@link #isHttpOnly()} instead.") private boolean httpOnly; @UnsupportedAppUsage diff --git a/ojluni/annotations/hiddenapi/java/net/Inet4Address.java b/ojluni/annotations/hiddenapi/java/net/Inet4Address.java index 16395eae7c..b8f60cbf09 100644 --- a/ojluni/annotations/hiddenapi/java/net/Inet4Address.java +++ b/ojluni/annotations/hiddenapi/java/net/Inet4Address.java @@ -26,7 +26,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Inet4Address extends java.net.InetAddress { diff --git a/ojluni/annotations/hiddenapi/java/net/Inet6Address.java b/ojluni/annotations/hiddenapi/java/net/Inet6Address.java index f46fa58533..fc48ebc3fd 100644 --- a/ojluni/annotations/hiddenapi/java/net/Inet6Address.java +++ b/ojluni/annotations/hiddenapi/java/net/Inet6Address.java @@ -26,7 +26,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Inet6Address extends java.net.InetAddress { diff --git a/ojluni/annotations/hiddenapi/java/net/Inet6AddressImpl.java b/ojluni/annotations/hiddenapi/java/net/Inet6AddressImpl.java index 964bdda062..dd25edf872 100644 --- a/ojluni/annotations/hiddenapi/java/net/Inet6AddressImpl.java +++ b/ojluni/annotations/hiddenapi/java/net/Inet6AddressImpl.java @@ -81,7 +81,7 @@ class Inet6AddressImpl implements java.net.InetAddressImpl { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private static final java.net.AddressCache addressCache; static { diff --git a/ojluni/annotations/hiddenapi/java/net/InetAddress.java b/ojluni/annotations/hiddenapi/java/net/InetAddress.java index 0f128ddc96..2be05b798f 100644 --- a/ojluni/annotations/hiddenapi/java/net/InetAddress.java +++ b/ojluni/annotations/hiddenapi/java/net/InetAddress.java @@ -26,8 +26,8 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VersionCodes; +import android.compat.annotation.UnsupportedAppUsage; +import dalvik.annotation.compat.VersionCodes; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class InetAddress implements java.io.Serializable { @@ -181,7 +181,10 @@ public class InetAddress implements java.io.Serializable { throw new RuntimeException("Stub!"); } - @UnsupportedAppUsage(maxTargetSdk = VersionCodes.P, trackingBug = 78686891) + @UnsupportedAppUsage(maxTargetSdk = VersionCodes.P, trackingBug = 78686891, + publicAlternatives = "Use {@link android.net.InetAddresses#isNumericAddress} " + + "instead. There is a behavioural difference between the original method and its " + + "replacement.") public static boolean isNumeric(java.lang.String address) { throw new RuntimeException("Stub!"); } @@ -198,7 +201,10 @@ public class InetAddress implements java.io.Serializable { /** * @deprecated Use {@code android.net.InetAddresses.parseNumericAddress(String)} instead. */ - @UnsupportedAppUsage(maxTargetSdk = VersionCodes.P, trackingBug = 78686891) + @UnsupportedAppUsage(maxTargetSdk = VersionCodes.P, trackingBug = 78686891, + publicAlternatives = "Use {@link android.net.InetAddresses#parseNumericAddress} " + + "instead. There is a behavioural difference between the original method and its " + + "replacement.") public static java.net.InetAddress parseNumericAddress(java.lang.String numericAddress) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/java/net/InetSocketAddress.java b/ojluni/annotations/hiddenapi/java/net/InetSocketAddress.java index 0a54f95eec..7522e0ee61 100644 --- a/ojluni/annotations/hiddenapi/java/net/InetSocketAddress.java +++ b/ojluni/annotations/hiddenapi/java/net/InetSocketAddress.java @@ -26,7 +26,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class InetSocketAddress extends java.net.SocketAddress { diff --git a/ojluni/annotations/hiddenapi/java/net/InterfaceAddress.java b/ojluni/annotations/hiddenapi/java/net/InterfaceAddress.java index 728784767a..84d3537b64 100644 --- a/ojluni/annotations/hiddenapi/java/net/InterfaceAddress.java +++ b/ojluni/annotations/hiddenapi/java/net/InterfaceAddress.java @@ -25,7 +25,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class InterfaceAddress { diff --git a/ojluni/annotations/hiddenapi/java/net/PlainSocketImpl.java b/ojluni/annotations/hiddenapi/java/net/PlainSocketImpl.java index 806a428262..4d7b6be552 100644 --- a/ojluni/annotations/hiddenapi/java/net/PlainSocketImpl.java +++ b/ojluni/annotations/hiddenapi/java/net/PlainSocketImpl.java @@ -29,7 +29,7 @@ package java.net; @SuppressWarnings({"unchecked", "deprecation", "all"}) class PlainSocketImpl extends java.net.AbstractPlainSocketImpl { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage PlainSocketImpl() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/java/net/Proxy.java b/ojluni/annotations/hiddenapi/java/net/Proxy.java index 4df3fa48c2..ff91f355ac 100644 --- a/ojluni/annotations/hiddenapi/java/net/Proxy.java +++ b/ojluni/annotations/hiddenapi/java/net/Proxy.java @@ -25,7 +25,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Proxy { diff --git a/ojluni/annotations/hiddenapi/java/net/ServerSocket.java b/ojluni/annotations/hiddenapi/java/net/ServerSocket.java index eabb24772f..ad0788ab8c 100644 --- a/ojluni/annotations/hiddenapi/java/net/ServerSocket.java +++ b/ojluni/annotations/hiddenapi/java/net/ServerSocket.java @@ -25,7 +25,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ServerSocket implements java.io.Closeable { diff --git a/ojluni/annotations/hiddenapi/java/net/Socket.java b/ojluni/annotations/hiddenapi/java/net/Socket.java index 2ad18ff46f..495d134cf4 100644 --- a/ojluni/annotations/hiddenapi/java/net/Socket.java +++ b/ojluni/annotations/hiddenapi/java/net/Socket.java @@ -26,7 +26,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Socket implements java.io.Closeable { diff --git a/ojluni/annotations/hiddenapi/java/net/SocketException.java b/ojluni/annotations/hiddenapi/java/net/SocketException.java index 03e48e9ea3..3775798bcd 100644 --- a/ojluni/annotations/hiddenapi/java/net/SocketException.java +++ b/ojluni/annotations/hiddenapi/java/net/SocketException.java @@ -26,7 +26,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class SocketException extends java.io.IOException { diff --git a/ojluni/annotations/hiddenapi/java/net/SocketImpl.java b/ojluni/annotations/hiddenapi/java/net/SocketImpl.java index be5c4f8b1c..9b9461adad 100644 --- a/ojluni/annotations/hiddenapi/java/net/SocketImpl.java +++ b/ojluni/annotations/hiddenapi/java/net/SocketImpl.java @@ -26,7 +26,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class SocketImpl implements java.net.SocketOptions { diff --git a/ojluni/annotations/hiddenapi/java/net/SocksSocketImpl.java b/ojluni/annotations/hiddenapi/java/net/SocksSocketImpl.java index 6e0f66cbd7..001d4414f1 100644 --- a/ojluni/annotations/hiddenapi/java/net/SocksSocketImpl.java +++ b/ojluni/annotations/hiddenapi/java/net/SocksSocketImpl.java @@ -25,7 +25,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) class SocksSocketImpl extends java.net.PlainSocketImpl implements java.net.SocksConsts { diff --git a/ojluni/annotations/hiddenapi/java/net/URI.java b/ojluni/annotations/hiddenapi/java/net/URI.java index 2287ab8da6..ec7e242dc0 100644 --- a/ojluni/annotations/hiddenapi/java/net/URI.java +++ b/ojluni/annotations/hiddenapi/java/net/URI.java @@ -26,7 +26,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class URI implements java.lang.Comparable<java.net.URI>, java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/net/URL.java b/ojluni/annotations/hiddenapi/java/net/URL.java index 905413ca69..9ba63581fd 100644 --- a/ojluni/annotations/hiddenapi/java/net/URL.java +++ b/ojluni/annotations/hiddenapi/java/net/URL.java @@ -26,7 +26,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class URL implements java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/net/URLClassLoader.java b/ojluni/annotations/hiddenapi/java/net/URLClassLoader.java index 105b0c7f0a..c9a040db67 100644 --- a/ojluni/annotations/hiddenapi/java/net/URLClassLoader.java +++ b/ojluni/annotations/hiddenapi/java/net/URLClassLoader.java @@ -25,7 +25,7 @@ package java.net; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class URLClassLoader extends java.security.SecureClassLoader implements java.io.Closeable { diff --git a/ojluni/annotations/hiddenapi/java/nio/Buffer.java b/ojluni/annotations/hiddenapi/java/nio/Buffer.java index cbcd8c1850..fa8b31b868 100644 --- a/ojluni/annotations/hiddenapi/java/nio/Buffer.java +++ b/ojluni/annotations/hiddenapi/java/nio/Buffer.java @@ -26,7 +26,7 @@ package java.nio; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class Buffer { diff --git a/ojluni/annotations/hiddenapi/java/nio/ByteBuffer.java b/ojluni/annotations/hiddenapi/java/nio/ByteBuffer.java index 65b6d58e4e..32f53a4789 100644 --- a/ojluni/annotations/hiddenapi/java/nio/ByteBuffer.java +++ b/ojluni/annotations/hiddenapi/java/nio/ByteBuffer.java @@ -28,7 +28,7 @@ package java.nio; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class ByteBuffer extends java.nio.Buffer diff --git a/ojluni/annotations/hiddenapi/java/nio/CharBuffer.java b/ojluni/annotations/hiddenapi/java/nio/CharBuffer.java index 891e8c309c..b447bb698e 100644 --- a/ojluni/annotations/hiddenapi/java/nio/CharBuffer.java +++ b/ojluni/annotations/hiddenapi/java/nio/CharBuffer.java @@ -28,7 +28,7 @@ package java.nio; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class CharBuffer extends java.nio.Buffer diff --git a/ojluni/annotations/hiddenapi/java/nio/DirectByteBuffer.java b/ojluni/annotations/hiddenapi/java/nio/DirectByteBuffer.java index 1d5e04f9b5..b6ca5fb8ff 100644 --- a/ojluni/annotations/hiddenapi/java/nio/DirectByteBuffer.java +++ b/ojluni/annotations/hiddenapi/java/nio/DirectByteBuffer.java @@ -26,7 +26,7 @@ package java.nio; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class DirectByteBuffer extends java.nio.MappedByteBuffer implements sun.nio.ch.DirectBuffer { diff --git a/ojluni/annotations/hiddenapi/java/nio/charset/Charset.java b/ojluni/annotations/hiddenapi/java/nio/charset/Charset.java index daaa265533..fb86662bbd 100644 --- a/ojluni/annotations/hiddenapi/java/nio/charset/Charset.java +++ b/ojluni/annotations/hiddenapi/java/nio/charset/Charset.java @@ -26,7 +26,7 @@ package java.nio.charset; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class Charset implements java.lang.Comparable<java.nio.charset.Charset> { diff --git a/ojluni/annotations/hiddenapi/java/nio/charset/CharsetEncoder.java b/ojluni/annotations/hiddenapi/java/nio/charset/CharsetEncoder.java index f053caed99..0e0fd2da71 100644 --- a/ojluni/annotations/hiddenapi/java/nio/charset/CharsetEncoder.java +++ b/ojluni/annotations/hiddenapi/java/nio/charset/CharsetEncoder.java @@ -28,7 +28,7 @@ package java.nio.charset; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class CharsetEncoder { diff --git a/ojluni/annotations/hiddenapi/java/nio/file/FileTreeWalker.java b/ojluni/annotations/hiddenapi/java/nio/file/FileTreeWalker.java index d3e6a425a3..0f9ae1e99c 100644 --- a/ojluni/annotations/hiddenapi/java/nio/file/FileTreeWalker.java +++ b/ojluni/annotations/hiddenapi/java/nio/file/FileTreeWalker.java @@ -72,20 +72,20 @@ class FileTreeWalker implements java.io.Closeable { private boolean closed; - @dalvik.annotation.compat.UnsupportedAppUsage private final boolean followLinks; + @android.compat.annotation.UnsupportedAppUsage private final boolean followLinks; { followLinks = false; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private final java.nio.file.LinkOption[] linkOptions; { linkOptions = new java.nio.file.LinkOption[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage private final int maxDepth; + @android.compat.annotation.UnsupportedAppUsage private final int maxDepth; { maxDepth = 0; diff --git a/ojluni/annotations/hiddenapi/java/security/KeyPairGenerator.java b/ojluni/annotations/hiddenapi/java/security/KeyPairGenerator.java index 2dba7cd62f..e5ceb2a87b 100644 --- a/ojluni/annotations/hiddenapi/java/security/KeyPairGenerator.java +++ b/ojluni/annotations/hiddenapi/java/security/KeyPairGenerator.java @@ -25,7 +25,7 @@ package java.security; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class KeyPairGenerator extends java.security.KeyPairGeneratorSpi { diff --git a/ojluni/annotations/hiddenapi/java/security/KeyStore.java b/ojluni/annotations/hiddenapi/java/security/KeyStore.java index ae64169905..6bf29a17ca 100644 --- a/ojluni/annotations/hiddenapi/java/security/KeyStore.java +++ b/ojluni/annotations/hiddenapi/java/security/KeyStore.java @@ -25,7 +25,7 @@ package java.security; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class KeyStore { diff --git a/ojluni/annotations/hiddenapi/java/security/Signature.java b/ojluni/annotations/hiddenapi/java/security/Signature.java index a249f65913..f9d4ab7cae 100644 --- a/ojluni/annotations/hiddenapi/java/security/Signature.java +++ b/ojluni/annotations/hiddenapi/java/security/Signature.java @@ -26,7 +26,7 @@ package java.security; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class Signature extends java.security.SignatureSpi { diff --git a/ojluni/annotations/hiddenapi/java/security/spec/ECParameterSpec.java b/ojluni/annotations/hiddenapi/java/security/spec/ECParameterSpec.java index db13a4b8fa..316678767a 100644 --- a/ojluni/annotations/hiddenapi/java/security/spec/ECParameterSpec.java +++ b/ojluni/annotations/hiddenapi/java/security/spec/ECParameterSpec.java @@ -26,7 +26,7 @@ package java.security.spec; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ECParameterSpec implements java.security.spec.AlgorithmParameterSpec { diff --git a/ojluni/annotations/hiddenapi/java/text/Collator.java b/ojluni/annotations/hiddenapi/java/text/Collator.java index 82aa868d70..befb9b9591 100644 --- a/ojluni/annotations/hiddenapi/java/text/Collator.java +++ b/ojluni/annotations/hiddenapi/java/text/Collator.java @@ -39,7 +39,7 @@ package java.text; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class Collator diff --git a/ojluni/annotations/hiddenapi/java/text/DateFormat.java b/ojluni/annotations/hiddenapi/java/text/DateFormat.java index 7a1973feeb..2b8ed78bb4 100644 --- a/ojluni/annotations/hiddenapi/java/text/DateFormat.java +++ b/ojluni/annotations/hiddenapi/java/text/DateFormat.java @@ -39,7 +39,7 @@ package java.text; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class DateFormat extends java.text.Format { diff --git a/ojluni/annotations/hiddenapi/java/text/DecimalFormatSymbols.java b/ojluni/annotations/hiddenapi/java/text/DecimalFormatSymbols.java index 52395a9ba1..1b0a68cae8 100644 --- a/ojluni/annotations/hiddenapi/java/text/DecimalFormatSymbols.java +++ b/ojluni/annotations/hiddenapi/java/text/DecimalFormatSymbols.java @@ -39,7 +39,7 @@ package java.text; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class DecimalFormatSymbols implements java.lang.Cloneable, java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/text/NumberFormat.java b/ojluni/annotations/hiddenapi/java/text/NumberFormat.java index a570716c59..232c94ff60 100644 --- a/ojluni/annotations/hiddenapi/java/text/NumberFormat.java +++ b/ojluni/annotations/hiddenapi/java/text/NumberFormat.java @@ -39,7 +39,7 @@ package java.text; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class NumberFormat extends java.text.Format { diff --git a/ojluni/annotations/hiddenapi/java/time/Duration.java b/ojluni/annotations/hiddenapi/java/time/Duration.java index 3090adb09c..ca9983261a 100644 --- a/ojluni/annotations/hiddenapi/java/time/Duration.java +++ b/ojluni/annotations/hiddenapi/java/time/Duration.java @@ -62,7 +62,7 @@ package java.time; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Duration diff --git a/ojluni/annotations/hiddenapi/java/time/OffsetDateTime.java b/ojluni/annotations/hiddenapi/java/time/OffsetDateTime.java index f95f12f50c..d4822c47bf 100644 --- a/ojluni/annotations/hiddenapi/java/time/OffsetDateTime.java +++ b/ojluni/annotations/hiddenapi/java/time/OffsetDateTime.java @@ -62,7 +62,7 @@ package java.time; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class OffsetDateTime diff --git a/ojluni/annotations/hiddenapi/java/time/ZoneId.java b/ojluni/annotations/hiddenapi/java/time/ZoneId.java index f3ae76a318..ef4a7aa72c 100644 --- a/ojluni/annotations/hiddenapi/java/time/ZoneId.java +++ b/ojluni/annotations/hiddenapi/java/time/ZoneId.java @@ -62,7 +62,7 @@ package java.time; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class ZoneId implements java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/util/ArrayDeque.java b/ojluni/annotations/hiddenapi/java/util/ArrayDeque.java index 59315d81ee..65c684ae8d 100644 --- a/ojluni/annotations/hiddenapi/java/util/ArrayDeque.java +++ b/ojluni/annotations/hiddenapi/java/util/ArrayDeque.java @@ -34,7 +34,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ArrayDeque<E> extends java.util.AbstractCollection<E> diff --git a/ojluni/annotations/hiddenapi/java/util/ArrayList.java b/ojluni/annotations/hiddenapi/java/util/ArrayList.java index 7457f1e7c5..3d90fa5cfb 100644 --- a/ojluni/annotations/hiddenapi/java/util/ArrayList.java +++ b/ojluni/annotations/hiddenapi/java/util/ArrayList.java @@ -26,7 +26,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ArrayList<E> extends java.util.AbstractList<E> @@ -425,7 +425,9 @@ public class ArrayList<E> extends java.util.AbstractList<E> parentOffset = 0; } - @UnsupportedAppUsage + @UnsupportedAppUsage(publicAlternatives = "Please update to a current version of the " + + "{@code Streamsupport} library; older versions of {@code Streamsupport} do not " + + "support current versions of Android.") int size; } } diff --git a/ojluni/annotations/hiddenapi/java/util/Arrays.java b/ojluni/annotations/hiddenapi/java/util/Arrays.java index c763a2d538..040c8b0b3a 100644 --- a/ojluni/annotations/hiddenapi/java/util/Arrays.java +++ b/ojluni/annotations/hiddenapi/java/util/Arrays.java @@ -26,7 +26,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Arrays { diff --git a/ojluni/annotations/hiddenapi/java/util/Calendar.java b/ojluni/annotations/hiddenapi/java/util/Calendar.java index 99a76f7df8..274f801937 100644 --- a/ojluni/annotations/hiddenapi/java/util/Calendar.java +++ b/ojluni/annotations/hiddenapi/java/util/Calendar.java @@ -39,7 +39,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class Calendar diff --git a/ojluni/annotations/hiddenapi/java/util/Collections.java b/ojluni/annotations/hiddenapi/java/util/Collections.java index 010ba3df61..d7445f0276 100644 --- a/ojluni/annotations/hiddenapi/java/util/Collections.java +++ b/ojluni/annotations/hiddenapi/java/util/Collections.java @@ -26,7 +26,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Collections { diff --git a/ojluni/annotations/hiddenapi/java/util/EnumMap.java b/ojluni/annotations/hiddenapi/java/util/EnumMap.java index 81cd885805..5b0c31f353 100644 --- a/ojluni/annotations/hiddenapi/java/util/EnumMap.java +++ b/ojluni/annotations/hiddenapi/java/util/EnumMap.java @@ -26,7 +26,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class EnumMap<K extends java.lang.Enum<K>, V> extends java.util.AbstractMap<K, V> diff --git a/ojluni/annotations/hiddenapi/java/util/EnumSet.java b/ojluni/annotations/hiddenapi/java/util/EnumSet.java index f8edb19843..6c920b02ca 100644 --- a/ojluni/annotations/hiddenapi/java/util/EnumSet.java +++ b/ojluni/annotations/hiddenapi/java/util/EnumSet.java @@ -26,7 +26,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class EnumSet<E extends java.lang.Enum<E>> extends java.util.AbstractSet<E> diff --git a/ojluni/annotations/hiddenapi/java/util/HashMap.java b/ojluni/annotations/hiddenapi/java/util/HashMap.java index af1c3425ce..b13c25c75e 100644 --- a/ojluni/annotations/hiddenapi/java/util/HashMap.java +++ b/ojluni/annotations/hiddenapi/java/util/HashMap.java @@ -25,7 +25,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class HashMap<K, V> extends java.util.AbstractMap<K, V> diff --git a/ojluni/annotations/hiddenapi/java/util/HashSet.java b/ojluni/annotations/hiddenapi/java/util/HashSet.java index a006121932..896c1aa81d 100644 --- a/ojluni/annotations/hiddenapi/java/util/HashSet.java +++ b/ojluni/annotations/hiddenapi/java/util/HashSet.java @@ -25,7 +25,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class HashSet<E> extends java.util.AbstractSet<E> diff --git a/ojluni/annotations/hiddenapi/java/util/LinkedHashMap.java b/ojluni/annotations/hiddenapi/java/util/LinkedHashMap.java index 8294334eb0..99d649ba68 100644 --- a/ojluni/annotations/hiddenapi/java/util/LinkedHashMap.java +++ b/ojluni/annotations/hiddenapi/java/util/LinkedHashMap.java @@ -25,7 +25,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class LinkedHashMap<K, V> extends java.util.HashMap<K, V> implements java.util.Map<K, V> { diff --git a/ojluni/annotations/hiddenapi/java/util/LinkedList.java b/ojluni/annotations/hiddenapi/java/util/LinkedList.java index c7eb0488d0..58cbb5f455 100644 --- a/ojluni/annotations/hiddenapi/java/util/LinkedList.java +++ b/ojluni/annotations/hiddenapi/java/util/LinkedList.java @@ -25,7 +25,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class LinkedList<E> extends java.util.AbstractSequentialList<E> diff --git a/ojluni/annotations/hiddenapi/java/util/Locale.java b/ojluni/annotations/hiddenapi/java/util/Locale.java index 3f6a54fea1..73d2dfa98d 100644 --- a/ojluni/annotations/hiddenapi/java/util/Locale.java +++ b/ojluni/annotations/hiddenapi/java/util/Locale.java @@ -41,7 +41,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Locale implements java.lang.Cloneable, java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/util/PriorityQueue.java b/ojluni/annotations/hiddenapi/java/util/PriorityQueue.java index b8d2a1818f..09c9d86f2e 100644 --- a/ojluni/annotations/hiddenapi/java/util/PriorityQueue.java +++ b/ojluni/annotations/hiddenapi/java/util/PriorityQueue.java @@ -25,7 +25,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class PriorityQueue<E> extends java.util.AbstractQueue<E> implements java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/util/Properties.java b/ojluni/annotations/hiddenapi/java/util/Properties.java index 3aee2d179e..397fa753ca 100644 --- a/ojluni/annotations/hiddenapi/java/util/Properties.java +++ b/ojluni/annotations/hiddenapi/java/util/Properties.java @@ -26,7 +26,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Properties extends java.util.Hashtable<java.lang.Object, java.lang.Object> { diff --git a/ojluni/annotations/hiddenapi/java/util/Random.java b/ojluni/annotations/hiddenapi/java/util/Random.java index ce80aa13f4..930688a6c1 100644 --- a/ojluni/annotations/hiddenapi/java/util/Random.java +++ b/ojluni/annotations/hiddenapi/java/util/Random.java @@ -25,7 +25,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Random implements java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/util/TimerTask.java b/ojluni/annotations/hiddenapi/java/util/TimerTask.java index 8a5c6d5aa4..65c845c03a 100644 --- a/ojluni/annotations/hiddenapi/java/util/TimerTask.java +++ b/ojluni/annotations/hiddenapi/java/util/TimerTask.java @@ -25,7 +25,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class TimerTask implements java.lang.Runnable { diff --git a/ojluni/annotations/hiddenapi/java/util/UUID.java b/ojluni/annotations/hiddenapi/java/util/UUID.java index 0585e5dea4..353f2b6135 100644 --- a/ojluni/annotations/hiddenapi/java/util/UUID.java +++ b/ojluni/annotations/hiddenapi/java/util/UUID.java @@ -25,7 +25,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class UUID implements java.io.Serializable, java.lang.Comparable<java.util.UUID> { diff --git a/ojluni/annotations/hiddenapi/java/util/Vector.java b/ojluni/annotations/hiddenapi/java/util/Vector.java index 394a097859..91a6aa70b0 100644 --- a/ojluni/annotations/hiddenapi/java/util/Vector.java +++ b/ojluni/annotations/hiddenapi/java/util/Vector.java @@ -25,7 +25,7 @@ package java.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Vector<E> extends java.util.AbstractList<E> diff --git a/ojluni/annotations/hiddenapi/java/util/concurrent/CopyOnWriteArrayList.java b/ojluni/annotations/hiddenapi/java/util/concurrent/CopyOnWriteArrayList.java index 7d526a723a..5a19180997 100644 --- a/ojluni/annotations/hiddenapi/java/util/concurrent/CopyOnWriteArrayList.java +++ b/ojluni/annotations/hiddenapi/java/util/concurrent/CopyOnWriteArrayList.java @@ -34,7 +34,7 @@ package java.util.concurrent; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class CopyOnWriteArrayList<E> diff --git a/ojluni/annotations/hiddenapi/java/util/concurrent/CopyOnWriteArraySet.java b/ojluni/annotations/hiddenapi/java/util/concurrent/CopyOnWriteArraySet.java index 98c53b0db7..2450ff4d99 100644 --- a/ojluni/annotations/hiddenapi/java/util/concurrent/CopyOnWriteArraySet.java +++ b/ojluni/annotations/hiddenapi/java/util/concurrent/CopyOnWriteArraySet.java @@ -35,7 +35,7 @@ package java.util.concurrent; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class CopyOnWriteArraySet<E> extends java.util.AbstractSet<E> diff --git a/ojluni/annotations/hiddenapi/java/util/concurrent/Executors.java b/ojluni/annotations/hiddenapi/java/util/concurrent/Executors.java index 1fbd62cebf..cd64ac80a3 100644 --- a/ojluni/annotations/hiddenapi/java/util/concurrent/Executors.java +++ b/ojluni/annotations/hiddenapi/java/util/concurrent/Executors.java @@ -35,7 +35,7 @@ package java.util.concurrent; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Executors { diff --git a/ojluni/annotations/hiddenapi/java/util/concurrent/FutureTask.java b/ojluni/annotations/hiddenapi/java/util/concurrent/FutureTask.java index 22746114f2..24746d4f13 100644 --- a/ojluni/annotations/hiddenapi/java/util/concurrent/FutureTask.java +++ b/ojluni/annotations/hiddenapi/java/util/concurrent/FutureTask.java @@ -35,7 +35,7 @@ package java.util.concurrent; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class FutureTask<V> implements java.util.concurrent.RunnableFuture<V> { diff --git a/ojluni/annotations/hiddenapi/java/util/concurrent/LinkedBlockingDeque.java b/ojluni/annotations/hiddenapi/java/util/concurrent/LinkedBlockingDeque.java index de84037a6a..391ba63113 100644 --- a/ojluni/annotations/hiddenapi/java/util/concurrent/LinkedBlockingDeque.java +++ b/ojluni/annotations/hiddenapi/java/util/concurrent/LinkedBlockingDeque.java @@ -35,7 +35,7 @@ package java.util.concurrent; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class LinkedBlockingDeque<E> extends java.util.AbstractQueue<E> diff --git a/ojluni/annotations/hiddenapi/java/util/concurrent/LinkedBlockingQueue.java b/ojluni/annotations/hiddenapi/java/util/concurrent/LinkedBlockingQueue.java index f7aec5c622..683a8f1bfd 100644 --- a/ojluni/annotations/hiddenapi/java/util/concurrent/LinkedBlockingQueue.java +++ b/ojluni/annotations/hiddenapi/java/util/concurrent/LinkedBlockingQueue.java @@ -35,7 +35,7 @@ package java.util.concurrent; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class LinkedBlockingQueue<E> extends java.util.AbstractQueue<E> diff --git a/ojluni/annotations/hiddenapi/java/util/concurrent/PriorityBlockingQueue.java b/ojluni/annotations/hiddenapi/java/util/concurrent/PriorityBlockingQueue.java index 0577e8c41e..35bc3c06fe 100644 --- a/ojluni/annotations/hiddenapi/java/util/concurrent/PriorityBlockingQueue.java +++ b/ojluni/annotations/hiddenapi/java/util/concurrent/PriorityBlockingQueue.java @@ -35,7 +35,7 @@ package java.util.concurrent; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class PriorityBlockingQueue<E> extends java.util.AbstractQueue<E> diff --git a/ojluni/annotations/hiddenapi/java/util/concurrent/ThreadPoolExecutor.java b/ojluni/annotations/hiddenapi/java/util/concurrent/ThreadPoolExecutor.java index e89f678bbd..0d2771151c 100644 --- a/ojluni/annotations/hiddenapi/java/util/concurrent/ThreadPoolExecutor.java +++ b/ojluni/annotations/hiddenapi/java/util/concurrent/ThreadPoolExecutor.java @@ -35,7 +35,7 @@ package java.util.concurrent; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ThreadPoolExecutor extends java.util.concurrent.AbstractExecutorService { diff --git a/ojluni/annotations/hiddenapi/java/util/concurrent/atomic/AtomicInteger.java b/ojluni/annotations/hiddenapi/java/util/concurrent/atomic/AtomicInteger.java index a5718ac13e..ed7ef76cea 100644 --- a/ojluni/annotations/hiddenapi/java/util/concurrent/atomic/AtomicInteger.java +++ b/ojluni/annotations/hiddenapi/java/util/concurrent/atomic/AtomicInteger.java @@ -35,7 +35,7 @@ package java.util.concurrent.atomic; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class AtomicInteger extends java.lang.Number implements java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/util/concurrent/locks/ReentrantLock.java b/ojluni/annotations/hiddenapi/java/util/concurrent/locks/ReentrantLock.java index 1ad6e8d617..892120809a 100644 --- a/ojluni/annotations/hiddenapi/java/util/concurrent/locks/ReentrantLock.java +++ b/ojluni/annotations/hiddenapi/java/util/concurrent/locks/ReentrantLock.java @@ -35,7 +35,7 @@ package java.util.concurrent.locks; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ReentrantLock implements java.util.concurrent.locks.Lock, java.io.Serializable { diff --git a/ojluni/annotations/hiddenapi/java/util/jar/JarFile.java b/ojluni/annotations/hiddenapi/java/util/jar/JarFile.java index 1c97964cd3..3c7d7bb30f 100644 --- a/ojluni/annotations/hiddenapi/java/util/jar/JarFile.java +++ b/ojluni/annotations/hiddenapi/java/util/jar/JarFile.java @@ -26,7 +26,7 @@ package java.util.jar; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class JarFile extends java.util.zip.ZipFile { diff --git a/ojluni/annotations/hiddenapi/java/util/logging/Handler.java b/ojluni/annotations/hiddenapi/java/util/logging/Handler.java index 2d04f15fdb..7243f48b6b 100644 --- a/ojluni/annotations/hiddenapi/java/util/logging/Handler.java +++ b/ojluni/annotations/hiddenapi/java/util/logging/Handler.java @@ -25,7 +25,7 @@ package java.util.logging; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class Handler { diff --git a/ojluni/annotations/hiddenapi/java/util/logging/LogManager.java b/ojluni/annotations/hiddenapi/java/util/logging/LogManager.java index a140100388..8900a5a898 100644 --- a/ojluni/annotations/hiddenapi/java/util/logging/LogManager.java +++ b/ojluni/annotations/hiddenapi/java/util/logging/LogManager.java @@ -26,7 +26,7 @@ package java.util.logging; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class LogManager { diff --git a/ojluni/annotations/hiddenapi/java/util/logging/Logger.java b/ojluni/annotations/hiddenapi/java/util/logging/Logger.java index f504c96017..1c14d54b59 100644 --- a/ojluni/annotations/hiddenapi/java/util/logging/Logger.java +++ b/ojluni/annotations/hiddenapi/java/util/logging/Logger.java @@ -25,7 +25,7 @@ package java.util.logging; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Logger { diff --git a/ojluni/annotations/hiddenapi/java/util/regex/Matcher.java b/ojluni/annotations/hiddenapi/java/util/regex/Matcher.java index 18d6d95812..686f1bdb53 100644 --- a/ojluni/annotations/hiddenapi/java/util/regex/Matcher.java +++ b/ojluni/annotations/hiddenapi/java/util/regex/Matcher.java @@ -26,7 +26,7 @@ package java.util.regex; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Matcher implements java.util.regex.MatchResult { diff --git a/ojluni/annotations/hiddenapi/java/util/zip/Adler32.java b/ojluni/annotations/hiddenapi/java/util/zip/Adler32.java index f78844fa16..e22aec40b8 100644 --- a/ojluni/annotations/hiddenapi/java/util/zip/Adler32.java +++ b/ojluni/annotations/hiddenapi/java/util/zip/Adler32.java @@ -25,7 +25,7 @@ package java.util.zip; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Adler32 implements java.util.zip.Checksum { diff --git a/ojluni/annotations/hiddenapi/java/util/zip/CRC32.java b/ojluni/annotations/hiddenapi/java/util/zip/CRC32.java index 0e25349eda..6766fa18a4 100644 --- a/ojluni/annotations/hiddenapi/java/util/zip/CRC32.java +++ b/ojluni/annotations/hiddenapi/java/util/zip/CRC32.java @@ -25,7 +25,7 @@ package java.util.zip; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class CRC32 implements java.util.zip.Checksum { diff --git a/ojluni/annotations/hiddenapi/java/util/zip/Deflater.java b/ojluni/annotations/hiddenapi/java/util/zip/Deflater.java index f8f419d3b2..0dbe2a5f2f 100644 --- a/ojluni/annotations/hiddenapi/java/util/zip/Deflater.java +++ b/ojluni/annotations/hiddenapi/java/util/zip/Deflater.java @@ -25,7 +25,7 @@ package java.util.zip; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Deflater { diff --git a/ojluni/annotations/hiddenapi/java/util/zip/Inflater.java b/ojluni/annotations/hiddenapi/java/util/zip/Inflater.java index c4194d2f64..e5a5dccfeb 100644 --- a/ojluni/annotations/hiddenapi/java/util/zip/Inflater.java +++ b/ojluni/annotations/hiddenapi/java/util/zip/Inflater.java @@ -26,7 +26,7 @@ package java.util.zip; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Inflater { diff --git a/ojluni/annotations/hiddenapi/java/util/zip/ZipEntry.java b/ojluni/annotations/hiddenapi/java/util/zip/ZipEntry.java index 87ca0f58fe..91440c2813 100644 --- a/ojluni/annotations/hiddenapi/java/util/zip/ZipEntry.java +++ b/ojluni/annotations/hiddenapi/java/util/zip/ZipEntry.java @@ -26,7 +26,7 @@ package java.util.zip; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ZipEntry implements java.util.zip.ZipConstants, java.lang.Cloneable { diff --git a/ojluni/annotations/hiddenapi/java/util/zip/ZipFile.java b/ojluni/annotations/hiddenapi/java/util/zip/ZipFile.java index 371659ae56..b2c72a79a9 100644 --- a/ojluni/annotations/hiddenapi/java/util/zip/ZipFile.java +++ b/ojluni/annotations/hiddenapi/java/util/zip/ZipFile.java @@ -26,7 +26,7 @@ package java.util.zip; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ZipFile implements java.util.zip.ZipConstants, java.io.Closeable { diff --git a/ojluni/annotations/hiddenapi/java/util/zip/ZipInputStream.java b/ojluni/annotations/hiddenapi/java/util/zip/ZipInputStream.java index 90947b77cc..18c1b2e2cd 100644 --- a/ojluni/annotations/hiddenapi/java/util/zip/ZipInputStream.java +++ b/ojluni/annotations/hiddenapi/java/util/zip/ZipInputStream.java @@ -26,7 +26,7 @@ package java.util.zip; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ZipInputStream extends java.util.zip.InflaterInputStream diff --git a/ojluni/annotations/hiddenapi/java/util/zip/ZipOutputStream.java b/ojluni/annotations/hiddenapi/java/util/zip/ZipOutputStream.java index 943fefa93c..fd4276a47d 100644 --- a/ojluni/annotations/hiddenapi/java/util/zip/ZipOutputStream.java +++ b/ojluni/annotations/hiddenapi/java/util/zip/ZipOutputStream.java @@ -26,7 +26,7 @@ package java.util.zip; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ZipOutputStream extends java.util.zip.DeflaterOutputStream diff --git a/ojluni/annotations/hiddenapi/javax/net/ssl/SSLServerSocketFactory.java b/ojluni/annotations/hiddenapi/javax/net/ssl/SSLServerSocketFactory.java index 26989a89c5..e947a88e94 100644 --- a/ojluni/annotations/hiddenapi/javax/net/ssl/SSLServerSocketFactory.java +++ b/ojluni/annotations/hiddenapi/javax/net/ssl/SSLServerSocketFactory.java @@ -26,8 +26,8 @@ package javax.net.ssl; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VersionCodes; +import android.compat.annotation.UnsupportedAppUsage; +import dalvik.annotation.compat.VersionCodes; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class SSLServerSocketFactory extends javax.net.ServerSocketFactory { @@ -55,7 +55,11 @@ public abstract class SSLServerSocketFactory extends javax.net.ServerSocketFacto * changes. */ @UnsupportedAppUsage(maxTargetSdk = VersionCodes.P, - trackingBug = 118741276) + trackingBug = 118741276, + publicAlternatives = "Use {@link #getDefault()} to read the current default; from Android " + + "API level 21 onwards, apps should have no need to ever write this value because it is " + + "automatically recomputed when the set of {@link java.security.Provider} security " + + "providers changes.") private static javax.net.ssl.SSLServerSocketFactory defaultServerSocketFactory; private static int lastVersion = -1; // 0xffffffff diff --git a/ojluni/annotations/hiddenapi/javax/net/ssl/SSLSocketFactory.java b/ojluni/annotations/hiddenapi/javax/net/ssl/SSLSocketFactory.java index 6ce4b5e9f4..b945122a90 100644 --- a/ojluni/annotations/hiddenapi/javax/net/ssl/SSLSocketFactory.java +++ b/ojluni/annotations/hiddenapi/javax/net/ssl/SSLSocketFactory.java @@ -26,8 +26,8 @@ package javax.net.ssl; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VersionCodes; +import android.compat.annotation.UnsupportedAppUsage; +import dalvik.annotation.compat.VersionCodes; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class SSLSocketFactory extends javax.net.SocketFactory { @@ -76,7 +76,11 @@ public abstract class SSLSocketFactory extends javax.net.SocketFactory { * changes. */ @UnsupportedAppUsage(maxTargetSdk = VersionCodes.P, - trackingBug = 118741276) + trackingBug = 118741276, + publicAlternatives = "Use {@link #getDefault()} to read the current default; from " + + "Android API level 21 onwards, apps should have no need to ever write this value " + + "because it is automatically recomputed when the set of " + + "{@link java.security.Provider} security providers changes.") private static javax.net.ssl.SSLSocketFactory defaultSocketFactory; private static int lastVersion = -1; // 0xffffffff diff --git a/ojluni/annotations/hiddenapi/sun/misc/ASCIICaseInsensitiveComparator.java b/ojluni/annotations/hiddenapi/sun/misc/ASCIICaseInsensitiveComparator.java index b632c1e197..2df53e2a88 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/ASCIICaseInsensitiveComparator.java +++ b/ojluni/annotations/hiddenapi/sun/misc/ASCIICaseInsensitiveComparator.java @@ -36,7 +36,7 @@ public class ASCIICaseInsensitiveComparator implements java.util.Comparator<java throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static int lowerCaseHashCode(java.lang.String s) { throw new RuntimeException("Stub!"); } @@ -57,7 +57,7 @@ public class ASCIICaseInsensitiveComparator implements java.util.Comparator<java throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final java.util.Comparator<java.lang.String> CASE_INSENSITIVE_ORDER; static { diff --git a/ojluni/annotations/hiddenapi/sun/misc/BASE64Decoder.java b/ojluni/annotations/hiddenapi/sun/misc/BASE64Decoder.java index 2ce6dc81af..65b468282a 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/BASE64Decoder.java +++ b/ojluni/annotations/hiddenapi/sun/misc/BASE64Decoder.java @@ -28,7 +28,7 @@ package sun.misc; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class BASE64Decoder extends sun.misc.CharacterDecoder { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public BASE64Decoder() { throw new RuntimeException("Stub!"); } @@ -55,7 +55,7 @@ public class BASE64Decoder extends sun.misc.CharacterDecoder { pem_array = new char[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage private static final byte[] pem_convert_array; + @android.compat.annotation.UnsupportedAppUsage private static final byte[] pem_convert_array; static { pem_convert_array = new byte[0]; diff --git a/ojluni/annotations/hiddenapi/sun/misc/BASE64Encoder.java b/ojluni/annotations/hiddenapi/sun/misc/BASE64Encoder.java index 8a9ef70301..146b54350f 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/BASE64Encoder.java +++ b/ojluni/annotations/hiddenapi/sun/misc/BASE64Encoder.java @@ -28,7 +28,7 @@ package sun.misc; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class BASE64Encoder extends sun.misc.CharacterEncoder { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public BASE64Encoder() { throw new RuntimeException("Stub!"); } @@ -46,7 +46,7 @@ public class BASE64Encoder extends sun.misc.CharacterEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage private static final char[] pem_array; + @android.compat.annotation.UnsupportedAppUsage private static final char[] pem_array; static { pem_array = new char[0]; diff --git a/ojluni/annotations/hiddenapi/sun/misc/CEFormatException.java b/ojluni/annotations/hiddenapi/sun/misc/CEFormatException.java index d351479cb6..d52e699f34 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/CEFormatException.java +++ b/ojluni/annotations/hiddenapi/sun/misc/CEFormatException.java @@ -28,7 +28,7 @@ package sun.misc; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class CEFormatException extends java.io.IOException { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CEFormatException(java.lang.String s) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/misc/CEStreamExhausted.java b/ojluni/annotations/hiddenapi/sun/misc/CEStreamExhausted.java index e696c671a2..e78d20ea8d 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/CEStreamExhausted.java +++ b/ojluni/annotations/hiddenapi/sun/misc/CEStreamExhausted.java @@ -28,7 +28,7 @@ package sun.misc; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class CEStreamExhausted extends java.io.IOException { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CEStreamExhausted() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/misc/CharacterDecoder.java b/ojluni/annotations/hiddenapi/sun/misc/CharacterDecoder.java index de6f9421fd..1b769fac94 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/CharacterDecoder.java +++ b/ojluni/annotations/hiddenapi/sun/misc/CharacterDecoder.java @@ -29,7 +29,7 @@ package sun.misc; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class CharacterDecoder { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CharacterDecoder() { throw new RuntimeException("Stub!"); } @@ -78,7 +78,7 @@ public abstract class CharacterDecoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] decodeBuffer(java.lang.String inputString) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/misc/CharacterEncoder.java b/ojluni/annotations/hiddenapi/sun/misc/CharacterEncoder.java index bbbf3f72b7..b254846bf1 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/CharacterEncoder.java +++ b/ojluni/annotations/hiddenapi/sun/misc/CharacterEncoder.java @@ -29,7 +29,7 @@ package sun.misc; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class CharacterEncoder { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CharacterEncoder() { throw new RuntimeException("Stub!"); } @@ -38,7 +38,7 @@ public abstract class CharacterEncoder { protected abstract int bytesPerLine(); - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage protected void encodeBufferPrefix(java.io.OutputStream aStream) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -73,7 +73,7 @@ public abstract class CharacterEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.String encode(byte[] aBuffer) { throw new RuntimeException("Stub!"); } @@ -101,7 +101,7 @@ public abstract class CharacterEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.String encodeBuffer(byte[] aBuffer) { throw new RuntimeException("Stub!"); } @@ -115,6 +115,6 @@ public abstract class CharacterEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage protected java.io.PrintStream pStream; } diff --git a/ojluni/annotations/hiddenapi/sun/misc/Cleaner.java b/ojluni/annotations/hiddenapi/sun/misc/Cleaner.java index eb21393821..cdbc65882f 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/Cleaner.java +++ b/ojluni/annotations/hiddenapi/sun/misc/Cleaner.java @@ -25,7 +25,7 @@ package sun.misc; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class Cleaner extends java.lang.ref.PhantomReference<java.lang.Object> { diff --git a/ojluni/annotations/hiddenapi/sun/misc/FloatingDecimal.java b/ojluni/annotations/hiddenapi/sun/misc/FloatingDecimal.java index 0c210ace97..fd8c6680fd 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/FloatingDecimal.java +++ b/ojluni/annotations/hiddenapi/sun/misc/FloatingDecimal.java @@ -86,17 +86,17 @@ public class FloatingDecimal { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage static java.lang.String stripLeadingZeros(java.lang.String s) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage static int getHexDigit(java.lang.String s, int position) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage private static boolean $assertionsDisabled; + @android.compat.annotation.UnsupportedAppUsage private static boolean $assertionsDisabled; static final sun.misc.FloatingDecimal.ASCIIToBinaryConverter A2BC_NEGATIVE_INFINITY; diff --git a/ojluni/annotations/hiddenapi/sun/misc/FormattedFloatingDecimal.java b/ojluni/annotations/hiddenapi/sun/misc/FormattedFloatingDecimal.java index b6766cfdc3..a7529316fe 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/FormattedFloatingDecimal.java +++ b/ojluni/annotations/hiddenapi/sun/misc/FormattedFloatingDecimal.java @@ -79,7 +79,7 @@ public class FormattedFloatingDecimal { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage private static boolean $assertionsDisabled; + @android.compat.annotation.UnsupportedAppUsage private static boolean $assertionsDisabled; private int decExponentRounded; @@ -95,11 +95,11 @@ public class FormattedFloatingDecimal { @SuppressWarnings({"unchecked", "deprecation", "all"}) public static enum Form { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage SCIENTIFIC, - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage COMPATIBLE, - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage DECIMAL_FLOAT, GENERAL; diff --git a/ojluni/annotations/hiddenapi/sun/misc/FpUtils.java b/ojluni/annotations/hiddenapi/sun/misc/FpUtils.java index 38347bd426..16bb5b0880 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/FpUtils.java +++ b/ojluni/annotations/hiddenapi/sun/misc/FpUtils.java @@ -43,7 +43,7 @@ public class FpUtils { } @Deprecated - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static double rawCopySign(double magnitude, double sign) { throw new RuntimeException("Stub!"); } @@ -165,5 +165,5 @@ public class FpUtils { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage private static boolean $assertionsDisabled; + @android.compat.annotation.UnsupportedAppUsage private static boolean $assertionsDisabled; } diff --git a/ojluni/annotations/hiddenapi/sun/misc/HexDumpEncoder.java b/ojluni/annotations/hiddenapi/sun/misc/HexDumpEncoder.java index f278c74a9d..c92af9ae54 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/HexDumpEncoder.java +++ b/ojluni/annotations/hiddenapi/sun/misc/HexDumpEncoder.java @@ -28,7 +28,7 @@ package sun.misc; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class HexDumpEncoder extends sun.misc.CharacterEncoder { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public HexDumpEncoder() { throw new RuntimeException("Stub!"); } @@ -62,11 +62,11 @@ public class HexDumpEncoder extends sun.misc.CharacterEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage private int currentByte; + @android.compat.annotation.UnsupportedAppUsage private int currentByte; - @dalvik.annotation.compat.UnsupportedAppUsage private int offset; + @android.compat.annotation.UnsupportedAppUsage private int offset; - @dalvik.annotation.compat.UnsupportedAppUsage private byte[] thisLine; + @android.compat.annotation.UnsupportedAppUsage private byte[] thisLine; - @dalvik.annotation.compat.UnsupportedAppUsage private int thisLineLength; + @android.compat.annotation.UnsupportedAppUsage private int thisLineLength; } diff --git a/ojluni/annotations/hiddenapi/sun/misc/IOUtils.java b/ojluni/annotations/hiddenapi/sun/misc/IOUtils.java index 90f7909572..251261bb4e 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/IOUtils.java +++ b/ojluni/annotations/hiddenapi/sun/misc/IOUtils.java @@ -34,7 +34,7 @@ public class IOUtils { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static byte[] readFully(java.io.InputStream is, int length, boolean readAll) throws java.io.IOException { throw new RuntimeException("Stub!"); diff --git a/ojluni/annotations/hiddenapi/sun/misc/JarIndex.java b/ojluni/annotations/hiddenapi/sun/misc/JarIndex.java index 06187e143f..a93d1de628 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/JarIndex.java +++ b/ojluni/annotations/hiddenapi/sun/misc/JarIndex.java @@ -41,7 +41,7 @@ public class JarIndex { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public JarIndex(java.lang.String[] files) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -83,7 +83,7 @@ public class JarIndex { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void write(java.io.OutputStream out) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/misc/MessageUtils.java b/ojluni/annotations/hiddenapi/sun/misc/MessageUtils.java index bd61419922..9fe08e4417 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/MessageUtils.java +++ b/ojluni/annotations/hiddenapi/sun/misc/MessageUtils.java @@ -29,7 +29,7 @@ package sun.misc; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class MessageUtils { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public MessageUtils() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/misc/MetaIndex.java b/ojluni/annotations/hiddenapi/sun/misc/MetaIndex.java index b3ae0cce04..4c38d4138d 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/MetaIndex.java +++ b/ojluni/annotations/hiddenapi/sun/misc/MetaIndex.java @@ -33,12 +33,12 @@ public class MetaIndex { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static sun.misc.MetaIndex forJar(java.io.File jar) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static synchronized void registerDirectory(java.io.File dir) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/misc/URLClassPath.java b/ojluni/annotations/hiddenapi/sun/misc/URLClassPath.java index 7ca8bd92b7..561a21c01f 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/URLClassPath.java +++ b/ojluni/annotations/hiddenapi/sun/misc/URLClassPath.java @@ -26,7 +26,7 @@ package sun.misc; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class URLClassPath { diff --git a/ojluni/annotations/hiddenapi/sun/misc/Unsafe.java b/ojluni/annotations/hiddenapi/sun/misc/Unsafe.java index 54308e4a69..c6dad00190 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/Unsafe.java +++ b/ojluni/annotations/hiddenapi/sun/misc/Unsafe.java @@ -25,8 +25,9 @@ package sun.misc; -import dalvik.annotation.compat.UnsupportedAppUsage; -import dalvik.system.VersionCodes; +import android.compat.annotation.UnsupportedAppUsage; + +import dalvik.annotation.compat.VersionCodes; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Unsafe { diff --git a/ojluni/annotations/hiddenapi/sun/misc/VM.java b/ojluni/annotations/hiddenapi/sun/misc/VM.java index 979818cb0a..a043c573bf 100644 --- a/ojluni/annotations/hiddenapi/sun/misc/VM.java +++ b/ojluni/annotations/hiddenapi/sun/misc/VM.java @@ -83,7 +83,7 @@ public class VM { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static long maxDirectMemory() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/net/ftp/FtpClient.java b/ojluni/annotations/hiddenapi/sun/net/ftp/FtpClient.java index c60accd409..0a54520153 100644 --- a/ojluni/annotations/hiddenapi/sun/net/ftp/FtpClient.java +++ b/ojluni/annotations/hiddenapi/sun/net/ftp/FtpClient.java @@ -31,7 +31,7 @@ import java.net.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class FtpClient implements java.io.Closeable { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage protected FtpClient() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/net/util/IPAddressUtil.java b/ojluni/annotations/hiddenapi/sun/net/util/IPAddressUtil.java index 710e3a895e..0134b09b6b 100644 --- a/ojluni/annotations/hiddenapi/sun/net/util/IPAddressUtil.java +++ b/ojluni/annotations/hiddenapi/sun/net/util/IPAddressUtil.java @@ -40,12 +40,12 @@ public class IPAddressUtil { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static boolean isIPv4LiteralAddress(java.lang.String src) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static boolean isIPv6LiteralAddress(java.lang.String src) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/net/www/MessageHeader.java b/ojluni/annotations/hiddenapi/sun/net/www/MessageHeader.java index c63d115128..4afd1348a5 100644 --- a/ojluni/annotations/hiddenapi/sun/net/www/MessageHeader.java +++ b/ojluni/annotations/hiddenapi/sun/net/www/MessageHeader.java @@ -35,12 +35,12 @@ import java.util.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class MessageHeader { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public MessageHeader() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public MessageHeader(java.io.InputStream is) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -53,7 +53,7 @@ public class MessageHeader { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public synchronized java.lang.String findValue(java.lang.String k) { throw new RuntimeException("Stub!"); } @@ -99,17 +99,17 @@ public class MessageHeader { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public synchronized void print(java.io.PrintStream p) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public synchronized void add(java.lang.String k, java.lang.String v) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public synchronized void prepend(java.lang.String k, java.lang.String v) { throw new RuntimeException("Stub!"); } @@ -126,7 +126,7 @@ public class MessageHeader { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public synchronized void set(java.lang.String k, java.lang.String v) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/net/www/ParseUtil.java b/ojluni/annotations/hiddenapi/sun/net/www/ParseUtil.java index d439a1fde1..3acc9eed6b 100644 --- a/ojluni/annotations/hiddenapi/sun/net/www/ParseUtil.java +++ b/ojluni/annotations/hiddenapi/sun/net/www/ParseUtil.java @@ -37,7 +37,7 @@ public class ParseUtil { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static java.lang.String encodePath(java.lang.String path, boolean flag) { throw new RuntimeException("Stub!"); } @@ -50,7 +50,7 @@ public class ParseUtil { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static java.lang.String decode(java.lang.String s) { throw new RuntimeException("Stub!"); } @@ -59,7 +59,7 @@ public class ParseUtil { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static java.net.URL fileToEncodedURL(java.io.File file) throws java.net.MalformedURLException { throw new RuntimeException("Stub!"); diff --git a/ojluni/annotations/hiddenapi/sun/net/www/URLConnection.java b/ojluni/annotations/hiddenapi/sun/net/www/URLConnection.java index 76692725e0..12b1d722c8 100644 --- a/ojluni/annotations/hiddenapi/sun/net/www/URLConnection.java +++ b/ojluni/annotations/hiddenapi/sun/net/www/URLConnection.java @@ -25,12 +25,10 @@ package sun.net.www; -import java.util.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class URLConnection extends java.net.URLConnection { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public URLConnection(java.net.URL u) { super(null); throw new RuntimeException("Stub!"); @@ -40,7 +38,7 @@ public abstract class URLConnection extends java.net.URLConnection { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void setProperties(sun.net.www.MessageHeader properties) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/nio/ch/DirectBuffer.java b/ojluni/annotations/hiddenapi/sun/nio/ch/DirectBuffer.java index e755c28142..87a24478ff 100644 --- a/ojluni/annotations/hiddenapi/sun/nio/ch/DirectBuffer.java +++ b/ojluni/annotations/hiddenapi/sun/nio/ch/DirectBuffer.java @@ -25,7 +25,7 @@ package sun.nio.ch; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public interface DirectBuffer { diff --git a/ojluni/annotations/hiddenapi/sun/nio/ch/FileChannelImpl.java b/ojluni/annotations/hiddenapi/sun/nio/ch/FileChannelImpl.java index ca3f145a22..7ab1dc25c9 100644 --- a/ojluni/annotations/hiddenapi/sun/nio/ch/FileChannelImpl.java +++ b/ojluni/annotations/hiddenapi/sun/nio/ch/FileChannelImpl.java @@ -207,7 +207,7 @@ public class FileChannelImpl extends java.nio.channels.FileChannel { private native long map0(int prot, long position, long length) throws java.io.IOException; - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private static native int unmap0(long address, long length); private native long transferTo0( diff --git a/ojluni/annotations/hiddenapi/sun/nio/ch/SelectorImpl.java b/ojluni/annotations/hiddenapi/sun/nio/ch/SelectorImpl.java index 294cdee0a5..41c9dd3207 100644 --- a/ojluni/annotations/hiddenapi/sun/nio/ch/SelectorImpl.java +++ b/ojluni/annotations/hiddenapi/sun/nio/ch/SelectorImpl.java @@ -94,9 +94,9 @@ public abstract class SelectorImpl extends java.nio.channels.spi.AbstractSelecto private java.util.Set<java.nio.channels.SelectionKey> publicKeys; - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private java.util.Set<java.nio.channels.SelectionKey> publicSelectedKeys; - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage protected java.util.Set<java.nio.channels.SelectionKey> selectedKeys; } diff --git a/ojluni/annotations/hiddenapi/sun/nio/cs/HistoricallyNamedCharset.java b/ojluni/annotations/hiddenapi/sun/nio/cs/HistoricallyNamedCharset.java index ed066b49e5..b0c71f4045 100644 --- a/ojluni/annotations/hiddenapi/sun/nio/cs/HistoricallyNamedCharset.java +++ b/ojluni/annotations/hiddenapi/sun/nio/cs/HistoricallyNamedCharset.java @@ -28,6 +28,6 @@ package sun.nio.cs; @SuppressWarnings({"unchecked", "deprecation", "all"}) public interface HistoricallyNamedCharset { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.String historicalName(); } diff --git a/ojluni/annotations/hiddenapi/sun/nio/cs/ThreadLocalCoders.java b/ojluni/annotations/hiddenapi/sun/nio/cs/ThreadLocalCoders.java index ef036318c9..3357f41694 100644 --- a/ojluni/annotations/hiddenapi/sun/nio/cs/ThreadLocalCoders.java +++ b/ojluni/annotations/hiddenapi/sun/nio/cs/ThreadLocalCoders.java @@ -25,8 +25,6 @@ package sun.nio.cs; -import java.nio.charset.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ThreadLocalCoders { @@ -34,7 +32,7 @@ public class ThreadLocalCoders { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static java.nio.charset.CharsetDecoder decoderFor(java.lang.Object name) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/nio/fs/BasicFileAttributesHolder.java b/ojluni/annotations/hiddenapi/sun/nio/fs/BasicFileAttributesHolder.java index 78cf143fce..3d6c0e8376 100644 --- a/ojluni/annotations/hiddenapi/sun/nio/fs/BasicFileAttributesHolder.java +++ b/ojluni/annotations/hiddenapi/sun/nio/fs/BasicFileAttributesHolder.java @@ -28,7 +28,7 @@ package sun.nio.fs; @SuppressWarnings({"unchecked", "deprecation", "all"}) public interface BasicFileAttributesHolder { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.nio.file.attribute.BasicFileAttributes get(); public void invalidate(); diff --git a/ojluni/annotations/hiddenapi/sun/reflect/Reflection.java b/ojluni/annotations/hiddenapi/sun/reflect/Reflection.java index ab0fb2a418..120ecb18ed 100644 --- a/ojluni/annotations/hiddenapi/sun/reflect/Reflection.java +++ b/ojluni/annotations/hiddenapi/sun/reflect/Reflection.java @@ -38,7 +38,7 @@ public class Reflection { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static void ensureMemberAccess( java.lang.Class<?> currentClass, java.lang.Class<?> memberClass, @@ -68,7 +68,7 @@ public class Reflection { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage static boolean isSubclassOf(java.lang.Class<?> queryClass, java.lang.Class<?> ofClass) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/reflect/misc/ReflectUtil.java b/ojluni/annotations/hiddenapi/sun/reflect/misc/ReflectUtil.java index 3200def80c..014d61300b 100644 --- a/ojluni/annotations/hiddenapi/sun/reflect/misc/ReflectUtil.java +++ b/ojluni/annotations/hiddenapi/sun/reflect/misc/ReflectUtil.java @@ -53,22 +53,22 @@ public final class ReflectUtil { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private static boolean isSubclassOf(java.lang.Class<?> queryClass, java.lang.Class<?> ofClass) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static void checkPackageAccess(java.lang.Class<?> clazz) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static void checkPackageAccess(java.lang.String name) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static boolean isPackageAccessible(java.lang.Class<?> clazz) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/action/GetBooleanAction.java b/ojluni/annotations/hiddenapi/sun/security/action/GetBooleanAction.java index 36355d7291..a9e37e463a 100644 --- a/ojluni/annotations/hiddenapi/sun/security/action/GetBooleanAction.java +++ b/ojluni/annotations/hiddenapi/sun/security/action/GetBooleanAction.java @@ -28,7 +28,7 @@ package sun.security.action; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class GetBooleanAction implements java.security.PrivilegedAction<java.lang.Boolean> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public GetBooleanAction(java.lang.String theProp) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/action/GetIntegerAction.java b/ojluni/annotations/hiddenapi/sun/security/action/GetIntegerAction.java index a0bc736832..223563cfc3 100644 --- a/ojluni/annotations/hiddenapi/sun/security/action/GetIntegerAction.java +++ b/ojluni/annotations/hiddenapi/sun/security/action/GetIntegerAction.java @@ -32,7 +32,7 @@ public class GetIntegerAction implements java.security.PrivilegedAction<java.lan throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public GetIntegerAction(java.lang.String theProp, int defaultVal) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/action/GetPropertyAction.java b/ojluni/annotations/hiddenapi/sun/security/action/GetPropertyAction.java index b83e1cdfea..ee83f58f86 100644 --- a/ojluni/annotations/hiddenapi/sun/security/action/GetPropertyAction.java +++ b/ojluni/annotations/hiddenapi/sun/security/action/GetPropertyAction.java @@ -28,12 +28,12 @@ package sun.security.action; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class GetPropertyAction implements java.security.PrivilegedAction<java.lang.String> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public GetPropertyAction(java.lang.String theProp) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public GetPropertyAction(java.lang.String theProp, java.lang.String defaultVal) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/jca/GetInstance.java b/ojluni/annotations/hiddenapi/sun/security/jca/GetInstance.java index e046dae3fc..92756f94c7 100644 --- a/ojluni/annotations/hiddenapi/sun/security/jca/GetInstance.java +++ b/ojluni/annotations/hiddenapi/sun/security/jca/GetInstance.java @@ -75,7 +75,7 @@ public class GetInstance { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static sun.security.jca.GetInstance.Instance getInstance( java.lang.String type, java.lang.Class<?> clazz, @@ -94,7 +94,7 @@ public class GetInstance { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static sun.security.jca.GetInstance.Instance getInstance( java.lang.String type, java.lang.Class<?> clazz, @@ -114,7 +114,7 @@ public class GetInstance { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static sun.security.jca.GetInstance.Instance getInstance( java.lang.String type, java.lang.Class<?> clazz, @@ -156,13 +156,13 @@ public class GetInstance { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage public final java.lang.Object impl; + @android.compat.annotation.UnsupportedAppUsage public final java.lang.Object impl; { impl = null; } - @dalvik.annotation.compat.UnsupportedAppUsage public final java.security.Provider provider; + @android.compat.annotation.UnsupportedAppUsage public final java.security.Provider provider; { provider = null; diff --git a/ojluni/annotations/hiddenapi/sun/security/jca/JCAUtil.java b/ojluni/annotations/hiddenapi/sun/security/jca/JCAUtil.java index 26d767f316..ca703f284c 100644 --- a/ojluni/annotations/hiddenapi/sun/security/jca/JCAUtil.java +++ b/ojluni/annotations/hiddenapi/sun/security/jca/JCAUtil.java @@ -39,7 +39,7 @@ public final class JCAUtil { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static java.security.SecureRandom getSecureRandom() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/jca/ProviderConfig.java b/ojluni/annotations/hiddenapi/sun/security/jca/ProviderConfig.java index 60ed61eeb7..f6abd8bbaf 100644 --- a/ojluni/annotations/hiddenapi/sun/security/jca/ProviderConfig.java +++ b/ojluni/annotations/hiddenapi/sun/security/jca/ProviderConfig.java @@ -47,7 +47,7 @@ final class ProviderConfig { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private boolean hasArgument() { throw new RuntimeException("Stub!"); } @@ -56,7 +56,7 @@ final class ProviderConfig { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private void disableLoad() { throw new RuntimeException("Stub!"); } @@ -94,7 +94,7 @@ final class ProviderConfig { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage private static final java.lang.Class[] CL_STRING; + @android.compat.annotation.UnsupportedAppUsage private static final java.lang.Class[] CL_STRING; static { CL_STRING = new java.lang.Class[0]; @@ -107,7 +107,7 @@ final class ProviderConfig { private static final java.lang.String P11_SOL_NAME = "sun.security.pkcs11.SunPKCS11"; - @dalvik.annotation.compat.UnsupportedAppUsage private final java.lang.String argument; + @android.compat.annotation.UnsupportedAppUsage private final java.lang.String argument; { argument = null; diff --git a/ojluni/annotations/hiddenapi/sun/security/jca/ProviderList.java b/ojluni/annotations/hiddenapi/sun/security/jca/ProviderList.java index 7cd3d4e9e8..e823f31706 100644 --- a/ojluni/annotations/hiddenapi/sun/security/jca/ProviderList.java +++ b/ojluni/annotations/hiddenapi/sun/security/jca/ProviderList.java @@ -106,7 +106,7 @@ public final class ProviderList { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.security.Provider.Service getService(java.lang.String type, java.lang.String name) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/jca/Providers.java b/ojluni/annotations/hiddenapi/sun/security/jca/Providers.java index da37d94dd5..4e116fc88f 100644 --- a/ojluni/annotations/hiddenapi/sun/security/jca/Providers.java +++ b/ojluni/annotations/hiddenapi/sun/security/jca/Providers.java @@ -38,17 +38,17 @@ public class Providers { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static java.lang.Object startJarVerification() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static void stopJarVerification(java.lang.Object obj) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static sun.security.jca.ProviderList getProviderList() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/pkcs/ContentInfo.java b/ojluni/annotations/hiddenapi/sun/security/pkcs/ContentInfo.java index 98a0a8506e..4340ab510e 100644 --- a/ojluni/annotations/hiddenapi/sun/security/pkcs/ContentInfo.java +++ b/ojluni/annotations/hiddenapi/sun/security/pkcs/ContentInfo.java @@ -31,13 +31,13 @@ import sun.security.util.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ContentInfo { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public ContentInfo( sun.security.util.ObjectIdentifier contentType, sun.security.util.DerValue content) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public ContentInfo(byte[] bytes) { throw new RuntimeException("Stub!"); } @@ -60,12 +60,12 @@ public class ContentInfo { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] getData() throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void encode(sun.security.util.DerOutputStream out) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -78,7 +78,7 @@ public class ContentInfo { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static sun.security.util.ObjectIdentifier DATA_OID; public static sun.security.util.ObjectIdentifier DIGESTED_DATA_OID; diff --git a/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS7.java b/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS7.java index 029282789c..48a4c3ce44 100644 --- a/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS7.java +++ b/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS7.java @@ -44,12 +44,12 @@ public class PKCS7 { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public PKCS7(byte[] bytes) throws sun.security.pkcs.ParsingException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public PKCS7( sun.security.x509.AlgorithmId[] digestAlgorithmIds, sun.security.pkcs.ContentInfo contentInfo, @@ -59,7 +59,7 @@ public class PKCS7 { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public PKCS7( sun.security.x509.AlgorithmId[] digestAlgorithmIds, sun.security.pkcs.ContentInfo contentInfo, @@ -93,7 +93,7 @@ public class PKCS7 { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void encodeSignedData(java.io.OutputStream out) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -102,7 +102,7 @@ public class PKCS7 { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.pkcs.SignerInfo verify(sun.security.pkcs.SignerInfo info, byte[] bytes) throws java.security.NoSuchAlgorithmException, java.security.SignatureException { throw new RuntimeException("Stub!"); @@ -115,7 +115,7 @@ public class PKCS7 { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.pkcs.SignerInfo[] verify(byte[] bytes) throws java.security.NoSuchAlgorithmException, java.security.SignatureException { throw new RuntimeException("Stub!"); @@ -134,12 +134,12 @@ public class PKCS7 { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.pkcs.ContentInfo getContentInfo() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.security.cert.X509Certificate[] getCertificates() { throw new RuntimeException("Stub!"); } @@ -148,7 +148,7 @@ public class PKCS7 { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.pkcs.SignerInfo[] getSignerInfos() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS8Key.java b/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS8Key.java index fa84ed9454..e8bb5a11c4 100644 --- a/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS8Key.java +++ b/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS8Key.java @@ -32,7 +32,7 @@ import sun.security.x509.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class PKCS8Key implements java.security.PrivateKey { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public PKCS8Key() { throw new RuntimeException("Stub!"); } @@ -115,11 +115,11 @@ public class PKCS8Key implements java.security.PrivateKey { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage protected sun.security.x509.AlgorithmId algid; + @android.compat.annotation.UnsupportedAppUsage protected sun.security.x509.AlgorithmId algid; - @dalvik.annotation.compat.UnsupportedAppUsage protected byte[] encodedKey; + @android.compat.annotation.UnsupportedAppUsage protected byte[] encodedKey; - @dalvik.annotation.compat.UnsupportedAppUsage protected byte[] key; + @android.compat.annotation.UnsupportedAppUsage protected byte[] key; private static final long serialVersionUID = -3836890099307167124L; // 0xcac0a0c88c95426cL diff --git a/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS9Attribute.java b/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS9Attribute.java index 40718c2f18..4413f4e192 100644 --- a/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS9Attribute.java +++ b/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS9Attribute.java @@ -29,19 +29,19 @@ package sun.security.pkcs; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class PKCS9Attribute implements sun.security.util.DerEncoder { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public PKCS9Attribute(sun.security.util.ObjectIdentifier oid, java.lang.Object value) throws java.lang.IllegalArgumentException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public PKCS9Attribute(java.lang.String name, java.lang.Object value) throws java.lang.IllegalArgumentException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public PKCS9Attribute(sun.security.util.DerValue derVal) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -51,7 +51,7 @@ public class PKCS9Attribute implements sun.security.util.DerEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void derEncode(java.io.OutputStream out) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -60,7 +60,7 @@ public class PKCS9Attribute implements sun.security.util.DerEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.Object getValue() { throw new RuntimeException("Stub!"); } @@ -69,7 +69,7 @@ public class PKCS9Attribute implements sun.security.util.DerEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.ObjectIdentifier getOID() { throw new RuntimeException("Stub!"); } @@ -116,7 +116,7 @@ public class PKCS9Attribute implements sun.security.util.DerEncoder { public static final java.lang.String CHALLENGE_PASSWORD_STR = "ChallengePassword"; - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier CONTENT_TYPE_OID; static { @@ -133,7 +133,7 @@ public class PKCS9Attribute implements sun.security.util.DerEncoder { public static final java.lang.String COUNTERSIGNATURE_STR = "Countersignature"; - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier EMAIL_ADDRESS_OID; static { @@ -167,7 +167,7 @@ public class PKCS9Attribute implements sun.security.util.DerEncoder { public static final java.lang.String ISSUER_SERIALNUMBER_STR = "IssuerAndSerialNumber"; - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier MESSAGE_DIGEST_OID; static { @@ -220,7 +220,7 @@ public class PKCS9Attribute implements sun.security.util.DerEncoder { public static final java.lang.String SIGNING_CERTIFICATE_STR = "SigningCertificate"; - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier SIGNING_TIME_OID; static { diff --git a/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS9Attributes.java b/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS9Attributes.java index ac9fabaed3..a5e9019936 100644 --- a/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS9Attributes.java +++ b/ojluni/annotations/hiddenapi/sun/security/pkcs/PKCS9Attributes.java @@ -36,18 +36,18 @@ public class PKCS9Attributes { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public PKCS9Attributes(sun.security.util.DerInputStream in) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public PKCS9Attributes(sun.security.util.DerInputStream in, boolean ignoreUnsupportedAttributes) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public PKCS9Attributes(sun.security.pkcs.PKCS9Attribute[] attribs) throws java.io.IOException, java.lang.IllegalArgumentException { throw new RuntimeException("Stub!"); @@ -57,7 +57,7 @@ public class PKCS9Attributes { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void encode(byte tag, java.io.OutputStream out) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -66,7 +66,7 @@ public class PKCS9Attributes { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] getDerEncoding() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -75,7 +75,7 @@ public class PKCS9Attributes { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.pkcs.PKCS9Attribute getAttribute(java.lang.String name) { throw new RuntimeException("Stub!"); } @@ -84,7 +84,7 @@ public class PKCS9Attributes { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.Object getAttributeValue(sun.security.util.ObjectIdentifier oid) throws java.io.IOException { throw new RuntimeException("Stub!"); diff --git a/ojluni/annotations/hiddenapi/sun/security/pkcs/ParsingException.java b/ojluni/annotations/hiddenapi/sun/security/pkcs/ParsingException.java index 7b101157c1..1f012cb930 100644 --- a/ojluni/annotations/hiddenapi/sun/security/pkcs/ParsingException.java +++ b/ojluni/annotations/hiddenapi/sun/security/pkcs/ParsingException.java @@ -37,7 +37,7 @@ public class ParsingException extends java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public ParsingException(java.lang.String s) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/pkcs/SignerInfo.java b/ojluni/annotations/hiddenapi/sun/security/pkcs/SignerInfo.java index 03ebf6fc7e..162b4209ea 100644 --- a/ojluni/annotations/hiddenapi/sun/security/pkcs/SignerInfo.java +++ b/ojluni/annotations/hiddenapi/sun/security/pkcs/SignerInfo.java @@ -34,7 +34,7 @@ public class SignerInfo implements sun.security.util.DerEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public SignerInfo( sun.security.x509.X500Name issuerName, java.math.BigInteger serial, @@ -44,7 +44,7 @@ public class SignerInfo implements sun.security.util.DerEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public SignerInfo( sun.security.x509.X500Name issuerName, java.math.BigInteger serial, @@ -74,13 +74,13 @@ public class SignerInfo implements sun.security.util.DerEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.security.cert.X509Certificate getCertificate(sun.security.pkcs.PKCS7 block) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.util.ArrayList<java.security.cert.X509Certificate> getCertificateChain( sun.security.pkcs.PKCS7 block) throws java.io.IOException { throw new RuntimeException("Stub!"); @@ -115,7 +115,7 @@ public class SignerInfo implements sun.security.util.DerEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.x509.AlgorithmId getDigestAlgorithmId() { throw new RuntimeException("Stub!"); } @@ -124,12 +124,12 @@ public class SignerInfo implements sun.security.util.DerEncoder { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.x509.AlgorithmId getDigestEncryptionAlgorithmId() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] getEncryptedDigest() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/provider/X509Factory.java b/ojluni/annotations/hiddenapi/sun/security/provider/X509Factory.java index 499dddc810..5f2376510a 100644 --- a/ojluni/annotations/hiddenapi/sun/security/provider/X509Factory.java +++ b/ojluni/annotations/hiddenapi/sun/security/provider/X509Factory.java @@ -25,8 +25,6 @@ package sun.security.provider; -import java.security.cert.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public class X509Factory { @@ -34,25 +32,25 @@ public class X509Factory { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static synchronized sun.security.x509.X509CertImpl intern( java.security.cert.X509Certificate c) throws java.security.cert.CertificateException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static synchronized sun.security.x509.X509CRLImpl intern(java.security.cert.X509CRL c) throws java.security.cert.CRLException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private static synchronized <K, V> V getFromCache( sun.security.util.Cache<K, V> cache, byte[] encoding) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private static synchronized <V> void addToCache( sun.security.util.Cache<java.lang.Object, V> cache, byte[] encoding, V value) { throw new RuntimeException("Stub!"); @@ -60,7 +58,7 @@ public class X509Factory { private static final int ENC_MAX_LENGTH = 4194304; // 0x400000 - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private static final sun.security.util.Cache<java.lang.Object, sun.security.x509.X509CertImpl> certCache; @@ -68,7 +66,7 @@ public class X509Factory { certCache = null; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private static final sun.security.util.Cache<java.lang.Object, sun.security.x509.X509CRLImpl> crlCache; diff --git a/ojluni/annotations/hiddenapi/sun/security/provider/certpath/X509CertPath.java b/ojluni/annotations/hiddenapi/sun/security/provider/certpath/X509CertPath.java index f3d432a644..71cc57f1c2 100644 --- a/ojluni/annotations/hiddenapi/sun/security/provider/certpath/X509CertPath.java +++ b/ojluni/annotations/hiddenapi/sun/security/provider/certpath/X509CertPath.java @@ -25,25 +25,23 @@ package sun.security.provider.certpath; -import java.util.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public class X509CertPath extends java.security.cert.CertPath { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X509CertPath(java.util.List<? extends java.security.cert.Certificate> certs) throws java.security.cert.CertificateException { super(null); throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X509CertPath(java.io.InputStream is) throws java.security.cert.CertificateException { super(null); throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X509CertPath(java.io.InputStream is, java.lang.String encoding) throws java.security.cert.CertificateException { super(null); @@ -81,7 +79,7 @@ public class X509CertPath extends java.security.cert.CertPath { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static java.util.Iterator<java.lang.String> getEncodingsStatic() { throw new RuntimeException("Stub!"); } @@ -100,7 +98,7 @@ public class X509CertPath extends java.security.cert.CertPath { private static final java.lang.String PKIPATH_ENCODING = "PkiPath"; - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private java.util.List<java.security.cert.X509Certificate> certs; private static final java.util.Collection<java.lang.String> encodingList; diff --git a/ojluni/annotations/hiddenapi/sun/security/provider/certpath/X509CertificatePair.java b/ojluni/annotations/hiddenapi/sun/security/provider/certpath/X509CertificatePair.java index 3d5b41064a..fa9fb60410 100644 --- a/ojluni/annotations/hiddenapi/sun/security/provider/certpath/X509CertificatePair.java +++ b/ojluni/annotations/hiddenapi/sun/security/provider/certpath/X509CertificatePair.java @@ -43,7 +43,7 @@ public class X509CertificatePair { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static synchronized void clearCache() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/timestamp/TimestampToken.java b/ojluni/annotations/hiddenapi/sun/security/timestamp/TimestampToken.java index 241935ef65..1c2d11595b 100644 --- a/ojluni/annotations/hiddenapi/sun/security/timestamp/TimestampToken.java +++ b/ojluni/annotations/hiddenapi/sun/security/timestamp/TimestampToken.java @@ -28,27 +28,27 @@ package sun.security.timestamp; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class TimestampToken { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public TimestampToken(byte[] timestampTokenInfo) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.util.Date getDate() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.x509.AlgorithmId getHashAlgorithm() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] getHashedMessage() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.math.BigInteger getNonce() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/util/BitArray.java b/ojluni/annotations/hiddenapi/sun/security/util/BitArray.java index 2eb98fe5ab..a27ab6540a 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/BitArray.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/BitArray.java @@ -32,7 +32,7 @@ public class BitArray { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public BitArray(int length, byte[] a) throws java.lang.IllegalArgumentException { throw new RuntimeException("Stub!"); } @@ -65,7 +65,7 @@ public class BitArray { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] toByteArray() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/util/Cache.java b/ojluni/annotations/hiddenapi/sun/security/util/Cache.java index f5077e1f1b..1520e12cc1 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/Cache.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/Cache.java @@ -31,20 +31,20 @@ import java.util.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public abstract class Cache<K, V> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage protected Cache() { throw new RuntimeException("Stub!"); } public abstract int size(); - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public abstract void clear(); - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public abstract void put(K key, V value); - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public abstract V get(java.lang.Object key); public abstract void remove(java.lang.Object key); @@ -63,7 +63,7 @@ public abstract class Cache<K, V> { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static <K, V> sun.security.util.Cache<K, V> newHardMemoryCache(int size) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/util/Debug.java b/ojluni/annotations/hiddenapi/sun/security/util/Debug.java index e511d0d589..5421d20a51 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/Debug.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/Debug.java @@ -33,7 +33,7 @@ public class Debug { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static sun.security.util.Debug getInstance(java.lang.String option) { throw new RuntimeException("Stub!"); } @@ -47,17 +47,17 @@ public class Debug { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void println(java.lang.String message) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void println() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static java.lang.String toHexString(java.math.BigInteger b) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/util/DerIndefLenConverter.java b/ojluni/annotations/hiddenapi/sun/security/util/DerIndefLenConverter.java index af6e282901..6ac25a92fc 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/DerIndefLenConverter.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/DerIndefLenConverter.java @@ -29,7 +29,7 @@ package sun.security.util; @SuppressWarnings({"unchecked", "deprecation", "all"}) class DerIndefLenConverter { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage DerIndefLenConverter() { throw new RuntimeException("Stub!"); } @@ -42,27 +42,27 @@ class DerIndefLenConverter { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage static boolean isIndefinite(int lengthByte) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private void parseTag() throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private void writeTag() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private int parseLength() throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private void writeLengthAndValue() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -79,7 +79,7 @@ class DerIndefLenConverter { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private void parseValue(int curLen) { throw new RuntimeException("Stub!"); } @@ -88,7 +88,7 @@ class DerIndefLenConverter { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage byte[] convert(byte[] indefData) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -105,21 +105,21 @@ class DerIndefLenConverter { private static final int TAG_MASK = 31; // 0x1f - @dalvik.annotation.compat.UnsupportedAppUsage private byte[] data; + @android.compat.annotation.UnsupportedAppUsage private byte[] data; - @dalvik.annotation.compat.UnsupportedAppUsage private int dataPos; + @android.compat.annotation.UnsupportedAppUsage private int dataPos; - @dalvik.annotation.compat.UnsupportedAppUsage private int dataSize; + @android.compat.annotation.UnsupportedAppUsage private int dataSize; private int index; private java.util.ArrayList<java.lang.Object> ndefsList; - @dalvik.annotation.compat.UnsupportedAppUsage private byte[] newData; + @android.compat.annotation.UnsupportedAppUsage private byte[] newData; private int newDataPos; - @dalvik.annotation.compat.UnsupportedAppUsage private int numOfTotalLenBytes = 0; // 0x0 + @android.compat.annotation.UnsupportedAppUsage private int numOfTotalLenBytes = 0; // 0x0 private int unresolved = 0; // 0x0 } diff --git a/ojluni/annotations/hiddenapi/sun/security/util/DerInputStream.java b/ojluni/annotations/hiddenapi/sun/security/util/DerInputStream.java index a8348e32f1..fefcd08451 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/DerInputStream.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/DerInputStream.java @@ -29,7 +29,7 @@ package sun.security.util; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class DerInputStream { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public DerInputStream(byte[] data) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -52,7 +52,7 @@ public class DerInputStream { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.DerInputStream subStream(int len, boolean do_skip) throws java.io.IOException { throw new RuntimeException("Stub!"); @@ -62,12 +62,12 @@ public class DerInputStream { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public int getInteger() throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.math.BigInteger getBigInteger() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -80,7 +80,7 @@ public class DerInputStream { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] getBitString() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -89,7 +89,7 @@ public class DerInputStream { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] getOctetString() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -102,7 +102,7 @@ public class DerInputStream { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.ObjectIdentifier getOID() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -112,17 +112,17 @@ public class DerInputStream { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.DerValue[] getSequence(int startLen) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.DerValue[] getSet(int startLen) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.DerValue[] getSet(int startLen, boolean implicit) throws java.io.IOException { throw new RuntimeException("Stub!"); @@ -143,12 +143,12 @@ public class DerInputStream { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.DerValue getDerValue() throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.String getUTF8String() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -179,7 +179,7 @@ public class DerInputStream { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.util.Date getUTCTime() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -192,7 +192,7 @@ public class DerInputStream { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public int peekByte() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -209,22 +209,22 @@ public class DerInputStream { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void mark(int value) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void reset() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public int available() { throw new RuntimeException("Stub!"); } sun.security.util.DerInputBuffer buffer; - @dalvik.annotation.compat.UnsupportedAppUsage public byte tag; + @android.compat.annotation.UnsupportedAppUsage public byte tag; } diff --git a/ojluni/annotations/hiddenapi/sun/security/util/DerOutputStream.java b/ojluni/annotations/hiddenapi/sun/security/util/DerOutputStream.java index 77e5e05c78..772018d09c 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/DerOutputStream.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/DerOutputStream.java @@ -30,22 +30,22 @@ package sun.security.util; public class DerOutputStream extends java.io.ByteArrayOutputStream implements sun.security.util.DerEncoder { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public DerOutputStream(int size) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public DerOutputStream() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void write(byte tag, byte[] buf) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void write(byte tag, sun.security.util.DerOutputStream out) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -55,12 +55,12 @@ public class DerOutputStream extends java.io.ByteArrayOutputStream throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putDerValue(sun.security.util.DerValue val) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putBoolean(boolean val) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -69,7 +69,7 @@ public class DerOutputStream extends java.io.ByteArrayOutputStream throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putInteger(java.math.BigInteger i) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -78,7 +78,7 @@ public class DerOutputStream extends java.io.ByteArrayOutputStream throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putInteger(int i) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -87,7 +87,7 @@ public class DerOutputStream extends java.io.ByteArrayOutputStream throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putBitString(byte[] bits) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -101,22 +101,22 @@ public class DerOutputStream extends java.io.ByteArrayOutputStream throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putOctetString(byte[] octets) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putNull() throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putOID(sun.security.util.ObjectIdentifier oid) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putSequence(sun.security.util.DerValue[] seq) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -125,7 +125,7 @@ public class DerOutputStream extends java.io.ByteArrayOutputStream throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putOrderedSetOf(byte tag, sun.security.util.DerEncoder[] set) throws java.io.IOException { throw new RuntimeException("Stub!"); @@ -142,12 +142,12 @@ public class DerOutputStream extends java.io.ByteArrayOutputStream throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putUTF8String(java.lang.String s) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putPrintableString(java.lang.String s) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -156,7 +156,7 @@ public class DerOutputStream extends java.io.ByteArrayOutputStream throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putIA5String(java.lang.String s) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -174,7 +174,7 @@ public class DerOutputStream extends java.io.ByteArrayOutputStream throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void putUTCTime(java.util.Date d) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/util/DerValue.java b/ojluni/annotations/hiddenapi/sun/security/util/DerValue.java index d034f44a90..42825d3ed3 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/DerValue.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/DerValue.java @@ -30,7 +30,7 @@ import java.io.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class DerValue { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public DerValue(java.lang.String value) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -39,7 +39,7 @@ public class DerValue { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public DerValue(byte tag, byte[] data) { throw new RuntimeException("Stub!"); } @@ -49,17 +49,17 @@ public class DerValue { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public DerValue(byte[] buf) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public DerValue(byte[] buf, int offset, int len) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public DerValue(java.io.InputStream in) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -72,12 +72,12 @@ public class DerValue { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public boolean isContextSpecific() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public boolean isContextSpecific(byte cntxtTag) { throw new RuntimeException("Stub!"); } @@ -86,7 +86,7 @@ public class DerValue { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public boolean isConstructed() { throw new RuntimeException("Stub!"); } @@ -105,12 +105,12 @@ public class DerValue { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void encode(sun.security.util.DerOutputStream out) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public final sun.security.util.DerInputStream getData() { throw new RuntimeException("Stub!"); } @@ -123,7 +123,7 @@ public class DerValue { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.ObjectIdentifier getOID() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -132,7 +132,7 @@ public class DerValue { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] getOctetString() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -141,12 +141,12 @@ public class DerValue { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.math.BigInteger getBigInteger() throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.math.BigInteger getPositiveBigInteger() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -155,17 +155,17 @@ public class DerValue { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] getBitString() throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.BitArray getUnalignedBitString() throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.String getAsString() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -179,7 +179,7 @@ public class DerValue { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] getDataBytes() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -236,12 +236,12 @@ public class DerValue { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] toByteArray() throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.DerInputStream toDerInputStream() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -250,17 +250,17 @@ public class DerValue { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static boolean isPrintableStringChar(char ch) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static byte createTag(byte tagClass, boolean form, byte val) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void resetTag(byte tag) { throw new RuntimeException("Stub!"); } @@ -277,9 +277,9 @@ public class DerValue { public static final byte TAG_UNIVERSAL = 0; // 0x0 - @dalvik.annotation.compat.UnsupportedAppUsage protected sun.security.util.DerInputBuffer buffer; + @android.compat.annotation.UnsupportedAppUsage protected sun.security.util.DerInputBuffer buffer; - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public final sun.security.util.DerInputStream data; { @@ -290,7 +290,7 @@ public class DerValue { private byte[] originalEncodedForm; - @dalvik.annotation.compat.UnsupportedAppUsage public byte tag; + @android.compat.annotation.UnsupportedAppUsage public byte tag; public static final byte tag_BMPString = 30; // 0x1e diff --git a/ojluni/annotations/hiddenapi/sun/security/util/ManifestDigester.java b/ojluni/annotations/hiddenapi/sun/security/util/ManifestDigester.java index ff473fb141..b8d89f8bd7 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/ManifestDigester.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/ManifestDigester.java @@ -30,7 +30,7 @@ import java.security.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class ManifestDigester { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public ManifestDigester(byte[] bytes) { throw new RuntimeException("Stub!"); } @@ -43,12 +43,12 @@ public class ManifestDigester { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.ManifestDigester.Entry get(java.lang.String name, boolean oldStyle) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] manifestDigest(java.security.MessageDigest md) { throw new RuntimeException("Stub!"); } @@ -66,7 +66,7 @@ public class ManifestDigester { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] digest(java.security.MessageDigest md) { throw new RuntimeException("Stub!"); } @@ -76,7 +76,7 @@ public class ManifestDigester { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] digestWorkaround(java.security.MessageDigest md) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/util/MemoryCache.java b/ojluni/annotations/hiddenapi/sun/security/util/MemoryCache.java index 0bea0a2017..5a7d646e15 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/MemoryCache.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/MemoryCache.java @@ -16,7 +16,7 @@ package sun.security.util; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) class MemoryCache<K, V> extends sun.security.util.Cache<K, V> { diff --git a/ojluni/annotations/hiddenapi/sun/security/util/ObjectIdentifier.java b/ojluni/annotations/hiddenapi/sun/security/util/ObjectIdentifier.java index 1c17bed56e..7b536f470f 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/ObjectIdentifier.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/ObjectIdentifier.java @@ -30,12 +30,12 @@ import java.io.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class ObjectIdentifier implements java.io.Serializable { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public ObjectIdentifier(java.lang.String oid) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public ObjectIdentifier(int[] values) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -61,7 +61,7 @@ public final class ObjectIdentifier implements java.io.Serializable { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static sun.security.util.ObjectIdentifier newInternal(int[] values) { throw new RuntimeException("Stub!"); } @@ -71,7 +71,7 @@ public final class ObjectIdentifier implements java.io.Serializable { } @Deprecated - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public boolean equals(sun.security.util.ObjectIdentifier other) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/util/PropertyExpander.java b/ojluni/annotations/hiddenapi/sun/security/util/PropertyExpander.java index f763de7d0b..9a86630c92 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/PropertyExpander.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/PropertyExpander.java @@ -33,7 +33,7 @@ public class PropertyExpander { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static java.lang.String expand(java.lang.String value) throws sun.security.util.PropertyExpander.ExpandException { throw new RuntimeException("Stub!"); diff --git a/ojluni/annotations/hiddenapi/sun/security/util/ResourcesMgr.java b/ojluni/annotations/hiddenapi/sun/security/util/ResourcesMgr.java index eef01dc330..0a66caebc2 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/ResourcesMgr.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/ResourcesMgr.java @@ -32,7 +32,7 @@ public class ResourcesMgr { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static java.lang.String getString(java.lang.String s) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/util/SecurityConstants.java b/ojluni/annotations/hiddenapi/sun/security/util/SecurityConstants.java index 33d67c63b0..4a89da6384 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/SecurityConstants.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/SecurityConstants.java @@ -51,7 +51,7 @@ public final class SecurityConstants { CREATE_ACC_PERMISSION = null; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final java.lang.RuntimePermission CREATE_CLASSLOADER_PERMISSION; static { @@ -68,7 +68,7 @@ public final class SecurityConstants { public static final java.lang.String FILE_WRITE_ACTION = "write"; - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final java.lang.RuntimePermission GET_CLASSLOADER_PERMISSION; static { @@ -123,14 +123,14 @@ public final class SecurityConstants { LOCAL_LISTEN_PERMISSION = null; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final java.lang.RuntimePermission MODIFY_THREADGROUP_PERMISSION; static { MODIFY_THREADGROUP_PERMISSION = null; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final java.lang.RuntimePermission MODIFY_THREAD_PERMISSION; static { diff --git a/ojluni/annotations/hiddenapi/sun/security/util/SignatureFileVerifier.java b/ojluni/annotations/hiddenapi/sun/security/util/SignatureFileVerifier.java index bce34ad2b9..0d9c77092a 100644 --- a/ojluni/annotations/hiddenapi/sun/security/util/SignatureFileVerifier.java +++ b/ojluni/annotations/hiddenapi/sun/security/util/SignatureFileVerifier.java @@ -50,7 +50,7 @@ public class SignatureFileVerifier { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static boolean isBlockOrSF(java.lang.String s) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/AVA.java b/ojluni/annotations/hiddenapi/sun/security/x509/AVA.java index e2e18ca09e..d4018bfae3 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/AVA.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/AVA.java @@ -26,7 +26,7 @@ package sun.security.x509; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class AVA implements sun.security.util.DerEncoder { diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/AVAComparator.java b/ojluni/annotations/hiddenapi/sun/security/x509/AVAComparator.java index 21494c3199..3643d60bd0 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/AVAComparator.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/AVAComparator.java @@ -16,7 +16,7 @@ package sun.security.x509; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) class AVAComparator implements java.util.Comparator<sun.security.x509.AVA> { diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/AVAKeyword.java b/ojluni/annotations/hiddenapi/sun/security/x509/AVAKeyword.java index 78d379f9e8..adadd59138 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/AVAKeyword.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/AVAKeyword.java @@ -17,7 +17,7 @@ package sun.security.x509; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) class AVAKeyword { diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/AccessDescription.java b/ojluni/annotations/hiddenapi/sun/security/x509/AccessDescription.java index 5f3d77fe04..d6f5e1d4b9 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/AccessDescription.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/AccessDescription.java @@ -36,17 +36,17 @@ public final class AccessDescription { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public AccessDescription(sun.security.util.DerValue derValue) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.ObjectIdentifier getAccessMethod() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.x509.GeneralName getAccessLocation() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/AlgorithmId.java b/ojluni/annotations/hiddenapi/sun/security/x509/AlgorithmId.java index 3f9214b274..7948de8bb6 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/AlgorithmId.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/AlgorithmId.java @@ -26,7 +26,7 @@ package sun.security.x509; -import dalvik.annotation.compat.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class AlgorithmId implements java.io.Serializable, sun.security.util.DerEncoder { diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/AttributeNameEnumeration.java b/ojluni/annotations/hiddenapi/sun/security/x509/AttributeNameEnumeration.java index c3728d7a1f..6bda58ed6d 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/AttributeNameEnumeration.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/AttributeNameEnumeration.java @@ -29,7 +29,7 @@ package sun.security.x509; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class AttributeNameEnumeration extends java.util.Vector<java.lang.String> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public AttributeNameEnumeration() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/CRLDistributionPointsExtension.java b/ojluni/annotations/hiddenapi/sun/security/x509/CRLDistributionPointsExtension.java index 84063ed77e..2e8439f88a 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/CRLDistributionPointsExtension.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/CRLDistributionPointsExtension.java @@ -100,7 +100,7 @@ public class CRLDistributionPointsExtension extends sun.security.x509.Extension throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private void encodeThis() throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/CRLNumberExtension.java b/ojluni/annotations/hiddenapi/sun/security/x509/CRLNumberExtension.java index 00d0ee00fc..40eb1b8afd 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/CRLNumberExtension.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/CRLNumberExtension.java @@ -49,7 +49,7 @@ public class CRLNumberExtension extends sun.security.x509.Extension throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CRLNumberExtension(java.lang.Boolean critical, java.lang.Object value) throws java.io.IOException { throw new RuntimeException("Stub!"); @@ -65,7 +65,7 @@ public class CRLNumberExtension extends sun.security.x509.Extension throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private void encodeThis() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -74,7 +74,7 @@ public class CRLNumberExtension extends sun.security.x509.Extension throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.math.BigInteger get(java.lang.String name) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateAlgorithmId.java b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateAlgorithmId.java index 5a3bc38d07..4a8f963d33 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateAlgorithmId.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateAlgorithmId.java @@ -30,7 +30,7 @@ import sun.security.util.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class CertificateAlgorithmId implements sun.security.x509.CertAttrSet<java.lang.String> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CertificateAlgorithmId(sun.security.x509.AlgorithmId algId) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateExtensions.java b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateExtensions.java index cad6f74ab4..da41fbded9 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateExtensions.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateExtensions.java @@ -32,12 +32,12 @@ import sun.security.util.*; public class CertificateExtensions implements sun.security.x509.CertAttrSet<sun.security.x509.Extension> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CertificateExtensions() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CertificateExtensions(sun.security.util.DerInputStream in) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -55,18 +55,18 @@ public class CertificateExtensions throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void encode(java.io.OutputStream out, boolean isCertReq) throws java.security.cert.CertificateException, java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void set(java.lang.String name, java.lang.Object obj) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.x509.Extension get(java.lang.String name) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateIssuerName.java b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateIssuerName.java index 22380db47c..c6736ff76c 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateIssuerName.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateIssuerName.java @@ -30,7 +30,7 @@ import sun.security.util.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class CertificateIssuerName implements sun.security.x509.CertAttrSet<java.lang.String> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CertificateIssuerName(sun.security.x509.X500Name name) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateSerialNumber.java b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateSerialNumber.java index 131b445576..1a0cb8109b 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateSerialNumber.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateSerialNumber.java @@ -30,12 +30,12 @@ import sun.security.util.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class CertificateSerialNumber implements sun.security.x509.CertAttrSet<java.lang.String> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CertificateSerialNumber(java.math.BigInteger num) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CertificateSerialNumber(int num) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateSubjectName.java b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateSubjectName.java index f5ff91086c..87842cae19 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateSubjectName.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateSubjectName.java @@ -30,7 +30,7 @@ import sun.security.util.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class CertificateSubjectName implements sun.security.x509.CertAttrSet<java.lang.String> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CertificateSubjectName(sun.security.x509.X500Name name) { throw new RuntimeException("Stub!"); } @@ -55,7 +55,7 @@ public class CertificateSubjectName implements sun.security.x509.CertAttrSet<jav throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.Object get(java.lang.String name) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateValidity.java b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateValidity.java index bb5d59980d..db96a7af73 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateValidity.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateValidity.java @@ -35,7 +35,7 @@ public class CertificateValidity implements sun.security.x509.CertAttrSet<java.l throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CertificateValidity(java.util.Date notBefore, java.util.Date notAfter) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateVersion.java b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateVersion.java index 85ad759697..3b3c1808af 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateVersion.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateVersion.java @@ -34,7 +34,7 @@ public class CertificateVersion implements sun.security.x509.CertAttrSet<java.la throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CertificateVersion(int version) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateX509Key.java b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateX509Key.java index 6f4505731f..ff5cc1d0d9 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/CertificateX509Key.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/CertificateX509Key.java @@ -30,7 +30,7 @@ import sun.security.util.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class CertificateX509Key implements sun.security.x509.CertAttrSet<java.lang.String> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public CertificateX509Key(java.security.PublicKey key) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/Extension.java b/ojluni/annotations/hiddenapi/sun/security/x509/Extension.java index f4acc6c4f5..60cd779617 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/Extension.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/Extension.java @@ -44,7 +44,7 @@ public class Extension implements java.security.cert.Extension { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public Extension(sun.security.x509.Extension ext) { throw new RuntimeException("Stub!"); } @@ -61,7 +61,7 @@ public class Extension implements java.security.cert.Extension { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void encode(sun.security.util.DerOutputStream out) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -70,7 +70,7 @@ public class Extension implements java.security.cert.Extension { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.util.ObjectIdentifier getExtensionId() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/GeneralName.java b/ojluni/annotations/hiddenapi/sun/security/x509/GeneralName.java index c7eb02e419..9fa401c18b 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/GeneralName.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/GeneralName.java @@ -30,7 +30,7 @@ import sun.security.util.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class GeneralName { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public GeneralName(sun.security.x509.GeneralNameInterface name) { throw new RuntimeException("Stub!"); } @@ -44,12 +44,12 @@ public class GeneralName { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public int getType() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.x509.GeneralNameInterface getName() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/GeneralNames.java b/ojluni/annotations/hiddenapi/sun/security/x509/GeneralNames.java index fdac69f2c8..df5f5eecd5 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/GeneralNames.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/GeneralNames.java @@ -31,17 +31,17 @@ import sun.security.util.*; @SuppressWarnings({"unchecked", "deprecation", "all"}) public class GeneralNames { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public GeneralNames(sun.security.util.DerValue derVal) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public GeneralNames() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.x509.GeneralNames add(sun.security.x509.GeneralName name) { throw new RuntimeException("Stub!"); } @@ -50,7 +50,7 @@ public class GeneralNames { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public boolean isEmpty() { throw new RuntimeException("Stub!"); } @@ -67,7 +67,7 @@ public class GeneralNames { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void encode(sun.security.util.DerOutputStream out) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/KeyIdentifier.java b/ojluni/annotations/hiddenapi/sun/security/x509/KeyIdentifier.java index 8faa83a363..427b1334d1 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/KeyIdentifier.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/KeyIdentifier.java @@ -38,12 +38,12 @@ public class KeyIdentifier { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public KeyIdentifier(java.security.PublicKey pubKey) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] getIdentifier() { throw new RuntimeException("Stub!"); } @@ -64,5 +64,5 @@ public class KeyIdentifier { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage private byte[] octetString; + @android.compat.annotation.UnsupportedAppUsage private byte[] octetString; } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/KeyUsageExtension.java b/ojluni/annotations/hiddenapi/sun/security/x509/KeyUsageExtension.java index e9addc9e03..cd2ff3ecf6 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/KeyUsageExtension.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/KeyUsageExtension.java @@ -35,7 +35,7 @@ public class KeyUsageExtension extends sun.security.x509.Extension throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public KeyUsageExtension(boolean[] bitString) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -69,7 +69,7 @@ public class KeyUsageExtension extends sun.security.x509.Extension throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.Boolean get(java.lang.String name) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/NetscapeCertTypeExtension.java b/ojluni/annotations/hiddenapi/sun/security/x509/NetscapeCertTypeExtension.java index 88e4f118a7..2db2b558a5 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/NetscapeCertTypeExtension.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/NetscapeCertTypeExtension.java @@ -32,7 +32,7 @@ import sun.security.util.*; public class NetscapeCertTypeExtension extends sun.security.x509.Extension implements sun.security.x509.CertAttrSet<java.lang.String> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public NetscapeCertTypeExtension(byte[] bitString) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -70,7 +70,7 @@ public class NetscapeCertTypeExtension extends sun.security.x509.Extension throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.Boolean get(java.lang.String name) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/OIDMap.java b/ojluni/annotations/hiddenapi/sun/security/x509/OIDMap.java index 8186c239e5..12be25abc1 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/OIDMap.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/OIDMap.java @@ -60,7 +60,7 @@ public class OIDMap { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static java.lang.Class<?> getClass(sun.security.util.ObjectIdentifier oid) throws java.security.cert.CertificateException { throw new RuntimeException("Stub!"); @@ -136,14 +136,14 @@ public class OIDMap { private static final java.lang.String SUB_KEY_IDENTIFIER = "x509.info.extensions.SubjectKeyIdentifier"; - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private static final java.util.Map<java.lang.String, sun.security.x509.OIDMap.OIDInfo> nameMap; static { nameMap = null; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private static final java.util.Map< sun.security.util.ObjectIdentifier, sun.security.x509.OIDMap.OIDInfo> oidMap; @@ -166,7 +166,7 @@ public class OIDMap { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage private volatile java.lang.Class<?> clazz; + @android.compat.annotation.UnsupportedAppUsage private volatile java.lang.Class<?> clazz; final java.lang.String name; diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/PKIXExtensions.java b/ojluni/annotations/hiddenapi/sun/security/x509/PKIXExtensions.java index de3027a1c9..105172c9c7 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/PKIXExtensions.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/PKIXExtensions.java @@ -95,7 +95,7 @@ public class PKIXExtensions { CRLNumber_data = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier CertificateIssuer_Id; static { diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/SerialNumber.java b/ojluni/annotations/hiddenapi/sun/security/x509/SerialNumber.java index 1c14ef3f9b..f6b1663e92 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/SerialNumber.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/SerialNumber.java @@ -42,7 +42,7 @@ public class SerialNumber { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public SerialNumber(sun.security.util.DerValue val) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/SubjectAlternativeNameExtension.java b/ojluni/annotations/hiddenapi/sun/security/x509/SubjectAlternativeNameExtension.java index 44aa6ab2f5..9b1ed0b080 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/SubjectAlternativeNameExtension.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/SubjectAlternativeNameExtension.java @@ -67,7 +67,7 @@ public class SubjectAlternativeNameExtension extends sun.security.x509.Extension throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.x509.GeneralNames get(java.lang.String name) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/SubjectKeyIdentifierExtension.java b/ojluni/annotations/hiddenapi/sun/security/x509/SubjectKeyIdentifierExtension.java index 2a85bd5f4d..a9c323d940 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/SubjectKeyIdentifierExtension.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/SubjectKeyIdentifierExtension.java @@ -25,13 +25,11 @@ package sun.security.x509; -import sun.security.util.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public class SubjectKeyIdentifierExtension extends sun.security.x509.Extension implements sun.security.x509.CertAttrSet<java.lang.String> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public SubjectKeyIdentifierExtension(byte[] octetString) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/URIName.java b/ojluni/annotations/hiddenapi/sun/security/x509/URIName.java index 5030158ede..5b8ee8f820 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/URIName.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/URIName.java @@ -25,8 +25,6 @@ package sun.security.x509; -import sun.security.util.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public class URIName implements sun.security.x509.GeneralNameInterface { @@ -67,12 +65,12 @@ public class URIName implements sun.security.x509.GeneralNameInterface { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.String getName() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.String getScheme() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/UniqueIdentity.java b/ojluni/annotations/hiddenapi/sun/security/x509/UniqueIdentity.java index b43e762889..c5b0995d5c 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/UniqueIdentity.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/UniqueIdentity.java @@ -25,8 +25,6 @@ package sun.security.x509; -import sun.security.util.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public class UniqueIdentity { @@ -38,12 +36,12 @@ public class UniqueIdentity { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public UniqueIdentity(sun.security.util.DerInputStream in) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public UniqueIdentity(sun.security.util.DerValue derVal) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -52,7 +50,7 @@ public class UniqueIdentity { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void encode(sun.security.util.DerOutputStream out, byte tag) throws java.io.IOException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/X500Name.java b/ojluni/annotations/hiddenapi/sun/security/x509/X500Name.java index 4c697abeec..fd8e9b6a03 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/X500Name.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/X500Name.java @@ -26,14 +26,10 @@ package sun.security.x509; -import java.lang.reflect.*; -import java.util.*; -import sun.security.util.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public class X500Name implements sun.security.x509.GeneralNameInterface, java.security.Principal { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X500Name(java.lang.String dname) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -44,12 +40,12 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X500Name(java.lang.String dname, java.lang.String format) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X500Name( java.lang.String commonName, java.lang.String organizationUnit, @@ -59,7 +55,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X500Name( java.lang.String commonName, java.lang.String organizationUnit, @@ -75,17 +71,17 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X500Name(sun.security.util.DerValue value) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X500Name(sun.security.util.DerInputStream in) throws java.io.IOException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X500Name(byte[] name) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -98,7 +94,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.util.List<sun.security.x509.AVA> allAvas() { throw new RuntimeException("Stub!"); } @@ -107,7 +103,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public boolean isEmpty() { throw new RuntimeException("Stub!"); } @@ -141,7 +137,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.String getCommonName() throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -235,7 +231,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void encode(sun.security.util.DerOutputStream out) throws java.io.IOException { throw new RuntimeException("Stub!"); } @@ -300,12 +296,12 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public javax.security.auth.x500.X500Principal asX500Principal() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static sun.security.x509.X500Name asX500Name(javax.security.auth.x500.X500Principal p) { throw new RuntimeException("Stub!"); } @@ -316,7 +312,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se DNQUALIFIER_DATA = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier DNQUALIFIER_OID; static { @@ -329,7 +325,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se DOMAIN_COMPONENT_DATA = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier DOMAIN_COMPONENT_OID; static { @@ -342,7 +338,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se GENERATIONQUALIFIER_DATA = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier GENERATIONQUALIFIER_OID; static { @@ -355,7 +351,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se GIVENNAME_DATA = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier GIVENNAME_OID; static { @@ -368,7 +364,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se INITIALS_DATA = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier INITIALS_OID; static { @@ -381,7 +377,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se SERIALNUMBER_DATA = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier SERIALNUMBER_OID; static { @@ -394,7 +390,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se SURNAME_DATA = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier SURNAME_OID; static { @@ -411,7 +407,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se commonName_data = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier commonName_oid; static { @@ -424,7 +420,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se countryName_data = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier countryName_oid; static { @@ -449,7 +445,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se ipAddress_data = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier ipAddress_oid; static { @@ -462,7 +458,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se localityName_data = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier localityName_oid; static { @@ -477,7 +473,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se orgName_data = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier orgName_oid; static { @@ -490,7 +486,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se orgUnitName_data = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier orgUnitName_oid; static { @@ -522,7 +518,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se stateName_data = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier stateName_oid; static { @@ -535,7 +531,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se streetAddress_data = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier streetAddress_oid; static { @@ -548,7 +544,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se title_data = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier title_oid; static { @@ -561,7 +557,7 @@ public class X500Name implements sun.security.x509.GeneralNameInterface, java.se userid_data = new int[0]; } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final sun.security.util.ObjectIdentifier userid_oid; static { diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/X509CRLEntryImpl.java b/ojluni/annotations/hiddenapi/sun/security/x509/X509CRLEntryImpl.java index 066a4adc8f..5684afae03 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/X509CRLEntryImpl.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/X509CRLEntryImpl.java @@ -25,9 +25,6 @@ package sun.security.x509; -import java.util.*; -import sun.security.util.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public class X509CRLEntryImpl extends java.security.cert.X509CRLEntry implements java.lang.Comparable<sun.security.x509.X509CRLEntryImpl> { @@ -120,7 +117,7 @@ public class X509CRLEntryImpl extends java.security.cert.X509CRLEntry throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.security.x509.Extension getExtension(sun.security.util.ObjectIdentifier oid) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/X509CRLImpl.java b/ojluni/annotations/hiddenapi/sun/security/x509/X509CRLImpl.java index 7f353dec58..64cf8db913 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/X509CRLImpl.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/X509CRLImpl.java @@ -25,9 +25,6 @@ package sun.security.x509; -import java.util.*; -import sun.security.util.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public class X509CRLImpl extends java.security.cert.X509CRL implements sun.security.util.DerEncoder { @@ -36,17 +33,17 @@ public class X509CRLImpl extends java.security.cert.X509CRL throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X509CRLImpl(byte[] crlData) throws java.security.cert.CRLException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X509CRLImpl(sun.security.util.DerValue val) throws java.security.cert.CRLException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X509CRLImpl(java.io.InputStream inStrm) throws java.security.cert.CRLException { throw new RuntimeException("Stub!"); } @@ -75,7 +72,7 @@ public class X509CRLImpl extends java.security.cert.X509CRL throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] getEncodedInternal() throws java.security.cert.CRLException { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/X509CertImpl.java b/ojluni/annotations/hiddenapi/sun/security/x509/X509CertImpl.java index 9333689381..5188e10e33 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/X509CertImpl.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/X509CertImpl.java @@ -25,11 +25,6 @@ package sun.security.x509; -import java.security.*; -import java.security.cert.*; -import java.util.*; -import sun.security.util.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public class X509CertImpl extends java.security.cert.X509Certificate implements sun.security.util.DerEncoder { @@ -38,17 +33,17 @@ public class X509CertImpl extends java.security.cert.X509Certificate throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X509CertImpl(byte[] certData) throws java.security.cert.CertificateException { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X509CertImpl(sun.security.x509.X509CertInfo certInfo) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X509CertImpl(sun.security.util.DerValue derVal) throws java.security.cert.CertificateException { throw new RuntimeException("Stub!"); @@ -72,7 +67,7 @@ public class X509CertImpl extends java.security.cert.X509Certificate throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public byte[] getEncodedInternal() throws java.security.cert.CertificateEncodingException { throw new RuntimeException("Stub!"); } @@ -106,7 +101,7 @@ public class X509CertImpl extends java.security.cert.X509Certificate throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void sign(java.security.PrivateKey key, java.lang.String algorithm) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, @@ -134,7 +129,7 @@ public class X509CertImpl extends java.security.cert.X509Certificate throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.Object get(java.lang.String name) throws java.security.cert.CertificateParsingException { throw new RuntimeException("Stub!"); @@ -366,7 +361,7 @@ public class X509CertImpl extends java.security.cert.X509Certificate throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private void parse(sun.security.util.DerValue val) throws java.security.cert.CertificateException, java.io.IOException { throw new RuntimeException("Stub!"); @@ -460,7 +455,7 @@ public class X509CertImpl extends java.security.cert.X509Certificate public static final java.lang.String VERSION = "x509.info.version.number"; - @dalvik.annotation.compat.UnsupportedAppUsage protected sun.security.x509.AlgorithmId algId; + @android.compat.annotation.UnsupportedAppUsage protected sun.security.x509.AlgorithmId algId; private java.util.Set<sun.security.x509.AccessDescription> authInfoAccess; @@ -472,13 +467,13 @@ public class X509CertImpl extends java.security.cert.X509Certificate private java.util.Collection<java.util.List<?>> issuerAlternativeNames; - @dalvik.annotation.compat.UnsupportedAppUsage private boolean readOnly = false; + @android.compat.annotation.UnsupportedAppUsage private boolean readOnly = false; private static final long serialVersionUID = -3457612960190864406L; // 0xd0041754f90963eaL - @dalvik.annotation.compat.UnsupportedAppUsage protected byte[] signature; + @android.compat.annotation.UnsupportedAppUsage protected byte[] signature; - @dalvik.annotation.compat.UnsupportedAppUsage private byte[] signedCert; + @android.compat.annotation.UnsupportedAppUsage private byte[] signedCert; private java.util.Collection<java.util.List<?>> subjectAlternativeNames; diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/X509CertInfo.java b/ojluni/annotations/hiddenapi/sun/security/x509/X509CertInfo.java index 21b4d6195f..2309a50c0c 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/X509CertInfo.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/X509CertInfo.java @@ -25,19 +25,15 @@ package sun.security.x509; -import java.security.cert.*; -import java.util.*; -import sun.security.util.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public class X509CertInfo implements sun.security.x509.CertAttrSet<java.lang.String> { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X509CertInfo() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X509CertInfo(byte[] cert) throws java.security.cert.CertificateParsingException { throw new RuntimeException("Stub!"); } @@ -80,7 +76,7 @@ public class X509CertInfo implements sun.security.x509.CertAttrSet<java.lang.Str throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void set(java.lang.String name, java.lang.Object val) throws java.security.cert.CertificateException, java.io.IOException { throw new RuntimeException("Stub!"); @@ -91,7 +87,7 @@ public class X509CertInfo implements sun.security.x509.CertAttrSet<java.lang.Str throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.Object get(java.lang.String name) throws java.security.cert.CertificateException, java.io.IOException { throw new RuntimeException("Stub!"); diff --git a/ojluni/annotations/hiddenapi/sun/security/x509/X509Key.java b/ojluni/annotations/hiddenapi/sun/security/x509/X509Key.java index 2a830d7285..8c4924feaf 100644 --- a/ojluni/annotations/hiddenapi/sun/security/x509/X509Key.java +++ b/ojluni/annotations/hiddenapi/sun/security/x509/X509Key.java @@ -25,13 +25,10 @@ package sun.security.x509; -import java.io.*; -import sun.security.util.*; - @SuppressWarnings({"unchecked", "deprecation", "all"}) public class X509Key implements java.security.PublicKey { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public X509Key() { throw new RuntimeException("Stub!"); } @@ -49,7 +46,7 @@ public class X509Key implements java.security.PublicKey { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static java.security.PublicKey parse(sun.security.util.DerValue in) throws java.io.IOException { throw new RuntimeException("Stub!"); @@ -129,15 +126,15 @@ public class X509Key implements java.security.PublicKey { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage protected sun.security.x509.AlgorithmId algid; + @android.compat.annotation.UnsupportedAppUsage protected sun.security.x509.AlgorithmId algid; private sun.security.util.BitArray bitStringKey; - @dalvik.annotation.compat.UnsupportedAppUsage protected byte[] encodedKey; + @android.compat.annotation.UnsupportedAppUsage protected byte[] encodedKey; - @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage protected byte[] key; + @Deprecated @android.compat.annotation.UnsupportedAppUsage protected byte[] key; private static final long serialVersionUID = -5359250853002055002L; // 0xb5a01dbe649a72a6L - @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage private int unusedBits = 0; // 0x0 + @Deprecated @android.compat.annotation.UnsupportedAppUsage private int unusedBits = 0; // 0x0 } diff --git a/ojluni/annotations/hiddenapi/sun/util/calendar/AbstractCalendar.java b/ojluni/annotations/hiddenapi/sun/util/calendar/AbstractCalendar.java index dd8fd2bf43..3e1be5eaa3 100644 --- a/ojluni/annotations/hiddenapi/sun/util/calendar/AbstractCalendar.java +++ b/ojluni/annotations/hiddenapi/sun/util/calendar/AbstractCalendar.java @@ -37,7 +37,7 @@ public abstract class AbstractCalendar extends sun.util.calendar.CalendarSystem throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.util.calendar.Era[] getEras() { throw new RuntimeException("Stub!"); } @@ -75,7 +75,7 @@ public abstract class AbstractCalendar extends sun.util.calendar.CalendarSystem throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public long getTimeOfDayValue(sun.util.calendar.CalendarDate date) { throw new RuntimeException("Stub!"); } @@ -104,7 +104,7 @@ public abstract class AbstractCalendar extends sun.util.calendar.CalendarSystem throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static long getDayOfWeekDateOnOrBefore(long fixedDate, int dayOfWeek) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/util/calendar/BaseCalendar.java b/ojluni/annotations/hiddenapi/sun/util/calendar/BaseCalendar.java index 8c8f122598..660ba87686 100644 --- a/ojluni/annotations/hiddenapi/sun/util/calendar/BaseCalendar.java +++ b/ojluni/annotations/hiddenapi/sun/util/calendar/BaseCalendar.java @@ -185,10 +185,10 @@ public abstract class BaseCalendar extends sun.util.calendar.AbstractCalendar { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public abstract int getNormalizedYear(); - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public abstract void setNormalizedYear(int normalizedYear); protected final boolean hit(int year) { diff --git a/ojluni/annotations/hiddenapi/sun/util/calendar/CalendarDate.java b/ojluni/annotations/hiddenapi/sun/util/calendar/CalendarDate.java index f63c574701..165920c7c1 100644 --- a/ojluni/annotations/hiddenapi/sun/util/calendar/CalendarDate.java +++ b/ojluni/annotations/hiddenapi/sun/util/calendar/CalendarDate.java @@ -45,7 +45,7 @@ public abstract class CalendarDate implements java.lang.Cloneable { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public int getYear() { throw new RuntimeException("Stub!"); } @@ -66,7 +66,7 @@ public abstract class CalendarDate implements java.lang.Cloneable { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public int getMonth() { throw new RuntimeException("Stub!"); } @@ -79,12 +79,12 @@ public abstract class CalendarDate implements java.lang.Cloneable { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public int getDayOfMonth() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.util.calendar.CalendarDate setDayOfMonth(int date) { throw new RuntimeException("Stub!"); } @@ -101,7 +101,7 @@ public abstract class CalendarDate implements java.lang.Cloneable { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.util.calendar.CalendarDate setHours(int hours) { throw new RuntimeException("Stub!"); } @@ -114,7 +114,7 @@ public abstract class CalendarDate implements java.lang.Cloneable { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.util.calendar.CalendarDate setMinutes(int minutes) { throw new RuntimeException("Stub!"); } @@ -127,7 +127,7 @@ public abstract class CalendarDate implements java.lang.Cloneable { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.util.calendar.CalendarDate setSeconds(int seconds) { throw new RuntimeException("Stub!"); } @@ -140,7 +140,7 @@ public abstract class CalendarDate implements java.lang.Cloneable { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.util.calendar.CalendarDate setMillis(int millis) { throw new RuntimeException("Stub!"); } @@ -149,12 +149,12 @@ public abstract class CalendarDate implements java.lang.Cloneable { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public long getTimeOfDay() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.util.calendar.CalendarDate setDate(int year, int month, int dayOfMonth) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/util/calendar/CalendarSystem.java b/ojluni/annotations/hiddenapi/sun/util/calendar/CalendarSystem.java index bddd682e4c..c84764100c 100644 --- a/ojluni/annotations/hiddenapi/sun/util/calendar/CalendarSystem.java +++ b/ojluni/annotations/hiddenapi/sun/util/calendar/CalendarSystem.java @@ -34,12 +34,12 @@ public abstract class CalendarSystem { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static sun.util.calendar.Gregorian getGregorianCalendar() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static sun.util.calendar.CalendarSystem forName(java.lang.String calendarName) { throw new RuntimeException("Stub!"); } @@ -62,10 +62,10 @@ public abstract class CalendarSystem { public abstract sun.util.calendar.CalendarDate newCalendarDate(); - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public abstract sun.util.calendar.CalendarDate newCalendarDate(java.util.TimeZone zone); - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public abstract long getTime(sun.util.calendar.CalendarDate date); public abstract int getYearLength(sun.util.calendar.CalendarDate date); @@ -88,7 +88,7 @@ public abstract class CalendarSystem { public abstract sun.util.calendar.CalendarDate setTimeOfDay( sun.util.calendar.CalendarDate date, int timeOfDay); - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public abstract boolean validate(sun.util.calendar.CalendarDate date); public abstract boolean normalize(sun.util.calendar.CalendarDate date); diff --git a/ojluni/annotations/hiddenapi/sun/util/calendar/CalendarUtils.java b/ojluni/annotations/hiddenapi/sun/util/calendar/CalendarUtils.java index 9ecd8dc60a..2a05603a14 100644 --- a/ojluni/annotations/hiddenapi/sun/util/calendar/CalendarUtils.java +++ b/ojluni/annotations/hiddenapi/sun/util/calendar/CalendarUtils.java @@ -40,12 +40,12 @@ public class CalendarUtils { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final long floorDivide(long n, long d) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final int floorDivide(int n, int d) { throw new RuntimeException("Stub!"); } @@ -58,12 +58,12 @@ public class CalendarUtils { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final long mod(long x, long y) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public static final int mod(int x, int y) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/util/calendar/Era.java b/ojluni/annotations/hiddenapi/sun/util/calendar/Era.java index 28e50951a5..49aa034d7b 100644 --- a/ojluni/annotations/hiddenapi/sun/util/calendar/Era.java +++ b/ojluni/annotations/hiddenapi/sun/util/calendar/Era.java @@ -28,12 +28,12 @@ package sun.util.calendar; @SuppressWarnings({"unchecked", "deprecation", "all"}) public final class Era { - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public Era(java.lang.String name, java.lang.String abbr, long since, boolean localTime) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.String getName() { throw new RuntimeException("Stub!"); } @@ -42,7 +42,7 @@ public final class Era { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public java.lang.String getAbbreviation() { throw new RuntimeException("Stub!"); } @@ -55,7 +55,7 @@ public final class Era { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.util.calendar.CalendarDate getSinceDate() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/util/calendar/ImmutableGregorianDate.java b/ojluni/annotations/hiddenapi/sun/util/calendar/ImmutableGregorianDate.java index 825e9d6a12..aa92656962 100644 --- a/ojluni/annotations/hiddenapi/sun/util/calendar/ImmutableGregorianDate.java +++ b/ojluni/annotations/hiddenapi/sun/util/calendar/ImmutableGregorianDate.java @@ -242,7 +242,7 @@ class ImmutableGregorianDate extends sun.util.calendar.BaseCalendar.Date { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage private void unsupported() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/hiddenapi/sun/util/calendar/LocalGregorianCalendar.java b/ojluni/annotations/hiddenapi/sun/util/calendar/LocalGregorianCalendar.java index 95267d05d5..b1320c5f2f 100644 --- a/ojluni/annotations/hiddenapi/sun/util/calendar/LocalGregorianCalendar.java +++ b/ojluni/annotations/hiddenapi/sun/util/calendar/LocalGregorianCalendar.java @@ -68,12 +68,12 @@ public class LocalGregorianCalendar extends sun.util.calendar.BaseCalendar { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.util.calendar.LocalGregorianCalendar.Date newCalendarDate(java.util.TimeZone zone) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public boolean validate(sun.util.calendar.CalendarDate date) { throw new RuntimeException("Stub!"); } @@ -82,7 +82,7 @@ public class LocalGregorianCalendar extends sun.util.calendar.BaseCalendar { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public boolean normalize(sun.util.calendar.CalendarDate date) { throw new RuntimeException("Stub!"); } @@ -122,7 +122,7 @@ public class LocalGregorianCalendar extends sun.util.calendar.BaseCalendar { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.util.calendar.LocalGregorianCalendar.Date setEra(sun.util.calendar.Era era) { throw new RuntimeException("Stub!"); } @@ -131,17 +131,17 @@ public class LocalGregorianCalendar extends sun.util.calendar.BaseCalendar { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public sun.util.calendar.LocalGregorianCalendar.Date setYear(int localYear) { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public int getNormalizedYear() { throw new RuntimeException("Stub!"); } - @dalvik.annotation.compat.UnsupportedAppUsage + @android.compat.annotation.UnsupportedAppUsage public void setNormalizedYear(int normalizedYear) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/mmodule/java/lang/Byte.annotated.java b/ojluni/annotations/mmodule/java/lang/Byte.annotated.java deleted file mode 100644 index 2d61598e20..0000000000 --- a/ojluni/annotations/mmodule/java/lang/Byte.annotated.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -package java.lang; - - -@SuppressWarnings({"unchecked", "deprecation", "all"}) -public final class Byte extends java.lang.Number implements java.lang.Comparable<java.lang.Byte> { - -public Byte(byte value) { throw new RuntimeException("Stub!"); } - -public Byte(java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); } - -public static java.lang.String toString(byte b) { throw new RuntimeException("Stub!"); } - -public static java.lang.Byte valueOf(byte b) { throw new RuntimeException("Stub!"); } - -public static byte parseByte(java.lang.String s, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); } - -public static byte parseByte(java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); } - -public static java.lang.Byte valueOf(java.lang.String s, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); } - -public static java.lang.Byte valueOf(java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); } - -public static java.lang.Byte decode(java.lang.String nm) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); } - -public byte byteValue() { throw new RuntimeException("Stub!"); } - -public short shortValue() { throw new RuntimeException("Stub!"); } - -public int intValue() { throw new RuntimeException("Stub!"); } - -public long longValue() { throw new RuntimeException("Stub!"); } - -public float floatValue() { throw new RuntimeException("Stub!"); } - -public double doubleValue() { throw new RuntimeException("Stub!"); } - -public java.lang.String toString() { throw new RuntimeException("Stub!"); } - -public int hashCode() { throw new RuntimeException("Stub!"); } - -public static int hashCode(byte value) { throw new RuntimeException("Stub!"); } - -public boolean equals(java.lang.Object obj) { throw new RuntimeException("Stub!"); } - -public int compareTo(java.lang.Byte anotherByte) { throw new RuntimeException("Stub!"); } - -public static int compare(byte x, byte y) { throw new RuntimeException("Stub!"); } - -public static int toUnsignedInt(byte x) { throw new RuntimeException("Stub!"); } - -public static long toUnsignedLong(byte x) { throw new RuntimeException("Stub!"); } - -@libcore.api.CorePlatformApi -public static java.lang.String toHexString(byte b, boolean upperCase) { throw new RuntimeException("Stub!"); } - -public static final int BYTES = 1; // 0x1 - -public static final byte MAX_VALUE = 127; // 0x7f - -public static final byte MIN_VALUE = -128; // 0xffffff80 - -public static final int SIZE = 8; // 0x8 - -public static final java.lang.Class<java.lang.Byte> TYPE; -static { TYPE = null; } -} - diff --git a/ojluni/annotations/mmodule/java/net/SocketImpl.annotated.java b/ojluni/annotations/mmodule/java/net/SocketImpl.annotated.java index ab1f94e3aa..2146d2f750 100644 --- a/ojluni/annotations/mmodule/java/net/SocketImpl.annotated.java +++ b/ojluni/annotations/mmodule/java/net/SocketImpl.annotated.java @@ -63,7 +63,7 @@ protected void shutdownOutput() throws java.io.IOException { throw new RuntimeEx protected java.io.FileDescriptor getFileDescriptor() { throw new RuntimeException("Stub!"); } @libcore.api.CorePlatformApi -public FileDescriptor getFD$() { throw new RuntimeException("Stub!"); } +public java.io.FileDescriptor getFD$() { throw new RuntimeException("Stub!"); } protected java.net.InetAddress getInetAddress() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/mmodule/java/nio/charset/CharsetDecoder.annotated.java b/ojluni/annotations/mmodule/java/nio/charset/CharsetDecoder.annotated.java new file mode 100644 index 0000000000..ed0f37840f --- /dev/null +++ b/ojluni/annotations/mmodule/java/nio/charset/CharsetDecoder.annotated.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// -- This file was mechanically generated: Do not edit! -- // + + +package java.nio.charset; + +import java.nio.CharBuffer; +import java.nio.ByteBuffer; +import java.nio.Buffer; +import java.nio.charset.CoderMalfunctionError; + +@SuppressWarnings({"unchecked", "deprecation", "all"}) +public abstract class CharsetDecoder { + +@libcore.api.IntraCoreApi +protected CharsetDecoder(java.nio.charset.Charset cs, float averageCharsPerByte, float maxCharsPerByte) { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.Charset charset() { throw new RuntimeException("Stub!"); } + +public final java.lang.String replacement() { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.CharsetDecoder replaceWith(java.lang.String newReplacement) { throw new RuntimeException("Stub!"); } + +protected void implReplaceWith(java.lang.String newReplacement) { throw new RuntimeException("Stub!"); } + +public java.nio.charset.CodingErrorAction malformedInputAction() { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.CharsetDecoder onMalformedInput(java.nio.charset.CodingErrorAction newAction) { throw new RuntimeException("Stub!"); } + +protected void implOnMalformedInput(java.nio.charset.CodingErrorAction newAction) { throw new RuntimeException("Stub!"); } + +public java.nio.charset.CodingErrorAction unmappableCharacterAction() { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.CharsetDecoder onUnmappableCharacter(java.nio.charset.CodingErrorAction newAction) { throw new RuntimeException("Stub!"); } + +protected void implOnUnmappableCharacter(java.nio.charset.CodingErrorAction newAction) { throw new RuntimeException("Stub!"); } + +public final float averageCharsPerByte() { throw new RuntimeException("Stub!"); } + +public final float maxCharsPerByte() { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.CoderResult decode(java.nio.ByteBuffer in, java.nio.CharBuffer out, boolean endOfInput) { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.CoderResult flush(java.nio.CharBuffer out) { throw new RuntimeException("Stub!"); } + +protected java.nio.charset.CoderResult implFlush(java.nio.CharBuffer out) { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.CharsetDecoder reset() { throw new RuntimeException("Stub!"); } + +protected void implReset() { throw new RuntimeException("Stub!"); } + +protected abstract java.nio.charset.CoderResult decodeLoop(java.nio.ByteBuffer in, java.nio.CharBuffer out); + +public final java.nio.CharBuffer decode(java.nio.ByteBuffer in) throws java.nio.charset.CharacterCodingException { throw new RuntimeException("Stub!"); } + +public boolean isAutoDetecting() { throw new RuntimeException("Stub!"); } + +public boolean isCharsetDetected() { throw new RuntimeException("Stub!"); } + +public java.nio.charset.Charset detectedCharset() { throw new RuntimeException("Stub!"); } +} + diff --git a/ojluni/annotations/mmodule/java/nio/charset/CharsetEncoder.annotated.java b/ojluni/annotations/mmodule/java/nio/charset/CharsetEncoder.annotated.java new file mode 100644 index 0000000000..ceb323e207 --- /dev/null +++ b/ojluni/annotations/mmodule/java/nio/charset/CharsetEncoder.annotated.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// -- This file was mechanically generated: Do not edit! -- // + + +package java.nio.charset; + +import java.nio.CharBuffer; +import java.nio.ByteBuffer; +import java.nio.Buffer; +import java.nio.charset.CoderMalfunctionError; + +@SuppressWarnings({"unchecked", "deprecation", "all"}) +public abstract class CharsetEncoder { + +protected CharsetEncoder(java.nio.charset.Charset cs, float averageBytesPerChar, float maxBytesPerChar, byte[] replacement) { throw new RuntimeException("Stub!"); } + +@libcore.api.IntraCoreApi +protected CharsetEncoder(java.nio.charset.Charset cs, float averageBytesPerChar, float maxBytesPerChar, byte[] replacement, boolean trusted) { throw new RuntimeException("Stub!"); } + +protected CharsetEncoder(java.nio.charset.Charset cs, float averageBytesPerChar, float maxBytesPerChar) { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.Charset charset() { throw new RuntimeException("Stub!"); } + +public final byte[] replacement() { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.CharsetEncoder replaceWith(byte[] newReplacement) { throw new RuntimeException("Stub!"); } + +protected void implReplaceWith(byte[] newReplacement) { throw new RuntimeException("Stub!"); } + +public boolean isLegalReplacement(byte[] repl) { throw new RuntimeException("Stub!"); } + +public java.nio.charset.CodingErrorAction malformedInputAction() { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.CharsetEncoder onMalformedInput(java.nio.charset.CodingErrorAction newAction) { throw new RuntimeException("Stub!"); } + +protected void implOnMalformedInput(java.nio.charset.CodingErrorAction newAction) { throw new RuntimeException("Stub!"); } + +public java.nio.charset.CodingErrorAction unmappableCharacterAction() { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.CharsetEncoder onUnmappableCharacter(java.nio.charset.CodingErrorAction newAction) { throw new RuntimeException("Stub!"); } + +protected void implOnUnmappableCharacter(java.nio.charset.CodingErrorAction newAction) { throw new RuntimeException("Stub!"); } + +public final float averageBytesPerChar() { throw new RuntimeException("Stub!"); } + +public final float maxBytesPerChar() { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.CoderResult encode(java.nio.CharBuffer in, java.nio.ByteBuffer out, boolean endOfInput) { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.CoderResult flush(java.nio.ByteBuffer out) { throw new RuntimeException("Stub!"); } + +protected java.nio.charset.CoderResult implFlush(java.nio.ByteBuffer out) { throw new RuntimeException("Stub!"); } + +public final java.nio.charset.CharsetEncoder reset() { throw new RuntimeException("Stub!"); } + +protected void implReset() { throw new RuntimeException("Stub!"); } + +protected abstract java.nio.charset.CoderResult encodeLoop(java.nio.CharBuffer in, java.nio.ByteBuffer out); + +public final java.nio.ByteBuffer encode(java.nio.CharBuffer in) throws java.nio.charset.CharacterCodingException { throw new RuntimeException("Stub!"); } + +public boolean canEncode(char c) { throw new RuntimeException("Stub!"); } + +public boolean canEncode(java.lang.CharSequence cs) { throw new RuntimeException("Stub!"); } +} + diff --git a/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java b/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java index f272a9ab90..a6711e010e 100644 --- a/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java +++ b/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java @@ -25,6 +25,8 @@ package sun.misc; +// sun.misc.Unsafe is part of the Core Platform API as platform uses protobuf and protobuf uses +// this API for fast structure updates from native code (b/144502743). @libcore.api.CorePlatformApi @libcore.api.Hide @SuppressWarnings({"unchecked", "deprecation", "all"}) @@ -40,30 +42,80 @@ public final class Unsafe { } @libcore.api.CorePlatformApi - public long objectFieldOffset(java.lang.reflect.Field field) { + public int arrayBaseOffset(Class clazz) { throw new RuntimeException("Stub!"); } @libcore.api.CorePlatformApi - public int arrayBaseOffset(java.lang.Class clazz) { + public int arrayIndexScale(Class clazz) { throw new RuntimeException("Stub!"); } @libcore.api.CorePlatformApi - public native byte getByte(java.lang.Object obj, long offset); + public native void copyMemory(long srcAddr, long destAddr, long bytes); + + @libcore.api.CorePlatformApi + public native boolean getBoolean(Object obj, long offset); @libcore.api.CorePlatformApi public native byte getByte(long address); @libcore.api.CorePlatformApi - public native long getLong(java.lang.Object obj, long offset); + public native byte getByte(Object obj, long offset); + + @libcore.api.CorePlatformApi + public native double getDouble(Object obj, long offset); + + @libcore.api.CorePlatformApi + public native float getFloat(Object obj, long offset); + + @libcore.api.CorePlatformApi + public native int getInt(long address); + + @libcore.api.CorePlatformApi + public native int getInt(Object obj, long offset); @libcore.api.CorePlatformApi public native long getLong(long address); @libcore.api.CorePlatformApi - public native void putByte(java.lang.Object obj, long offset, byte newValue); + public native long getLong(Object obj, long offset); + + @libcore.api.CorePlatformApi + public native Object getObject(Object obj, long offset); + + @libcore.api.CorePlatformApi + public long objectFieldOffset(java.lang.reflect.Field field) { + throw new RuntimeException("Stub!"); + } + + @libcore.api.CorePlatformApi + public native void putBoolean(Object obj, long offset, boolean newValue); + + @libcore.api.CorePlatformApi + public native void putByte(long address, byte newValue); + + @libcore.api.CorePlatformApi + public native void putByte(Object obj, long offset, byte newValue); + + @libcore.api.CorePlatformApi + public native void putDouble(Object obj, long offset, double newValue); + + @libcore.api.CorePlatformApi + public native void putFloat(Object obj, long offset, float newValue); + + @libcore.api.CorePlatformApi + public native void putInt(long address, int newValue); + + @libcore.api.CorePlatformApi + public native void putInt(Object obj, long offset, int newValue); + + @libcore.api.CorePlatformApi + public native void putLong(long address, long newValue); + + @libcore.api.CorePlatformApi + public native void putLong(Object obj, long offset, long newValue); @libcore.api.CorePlatformApi - public native void putByte(long address, byte x); + public native void putObject(Object obj, long offset, Object newValue); } diff --git a/ojluni/annotations/sdk/nullability/java/lang/Class.annotated.java b/ojluni/annotations/sdk/nullability/java/lang/Class.annotated.java index 5cbfa4987c..cb99f54132 100644 --- a/ojluni/annotations/sdk/nullability/java/lang/Class.annotated.java +++ b/ojluni/annotations/sdk/nullability/java/lang/Class.annotated.java @@ -141,9 +141,9 @@ public java.lang.reflect.@libcore.util.NonNull Constructor<?> @libcore.util.NonN @libcore.util.Nullable public java.io.InputStream getResourceAsStream(@libcore.util.NonNull java.lang.String name) { throw new RuntimeException("Stub!"); } -public java.net.URL getResource(@libcore.util.NonNull java.lang.String name) { throw new RuntimeException("Stub!"); } +@libcore.util.Nullable public java.net.URL getResource(@libcore.util.NonNull java.lang.String name) { throw new RuntimeException("Stub!"); } -public java.security.ProtectionDomain getProtectionDomain() { throw new RuntimeException("Stub!"); } +@libcore.util.Nullable public java.security.ProtectionDomain getProtectionDomain() { throw new RuntimeException("Stub!"); } public boolean desiredAssertionStatus() { throw new RuntimeException("Stub!"); } @@ -156,7 +156,7 @@ public T @libcore.util.Nullable [] getEnumConstants() { throw new RuntimeExcepti @libcore.util.NonNull public <U> java.lang.Class<? extends U> asSubclass(@libcore.util.NonNull java.lang.Class<U> clazz) { throw new RuntimeException("Stub!"); } -public <A extends java.lang.annotation.Annotation> A getAnnotation(@libcore.util.NonNull java.lang.Class<A> annotationClass) { throw new RuntimeException("Stub!"); } +@libcore.util.Nullable public <A extends java.lang.annotation.Annotation> A getAnnotation(@libcore.util.NonNull java.lang.Class<A> annotationClass) { throw new RuntimeException("Stub!"); } public boolean isAnnotationPresent(@libcore.util.NonNull java.lang.Class<? extends java.lang.annotation.Annotation> annotationClass) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/sdk/nullability/java/lang/StringBuilder.annotated.java b/ojluni/annotations/sdk/nullability/java/lang/StringBuilder.annotated.java index 9ec4039dd7..6fdde8afef 100644 --- a/ojluni/annotations/sdk/nullability/java/lang/StringBuilder.annotated.java +++ b/ojluni/annotations/sdk/nullability/java/lang/StringBuilder.annotated.java @@ -119,11 +119,11 @@ public int length() { throw new RuntimeException("Stub!"); } public void setCharAt(int index, char ch) { throw new RuntimeException("Stub!"); } -public java.lang.CharSequence subSequence(int start, int end) { throw new RuntimeException("Stub!"); } +@libcore.util.NonNull public java.lang.CharSequence subSequence(int start, int end) { throw new RuntimeException("Stub!"); } -public java.lang.String substring(int start) { throw new RuntimeException("Stub!"); } +@libcore.util.NonNull public java.lang.String substring(int start) { throw new RuntimeException("Stub!"); } -public java.lang.String substring(int start, int end) { throw new RuntimeException("Stub!"); } +@libcore.util.NonNull public java.lang.String substring(int start, int end) { throw new RuntimeException("Stub!"); } public int capacity() { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/sdk/nullability/java/lang/System.annotated.java b/ojluni/annotations/sdk/nullability/java/lang/System.annotated.java index b39f09a20f..4cd1c31f5d 100644 --- a/ojluni/annotations/sdk/nullability/java/lang/System.annotated.java +++ b/ojluni/annotations/sdk/nullability/java/lang/System.annotated.java @@ -76,7 +76,7 @@ public static void setProperties(@libcore.util.Nullable java.util.Properties pro @libcore.util.Nullable public static java.lang.String getenv(@libcore.util.NonNull java.lang.String name) { throw new RuntimeException("Stub!"); } -public static java.util.Map<java.lang.String,java.lang.String> getenv() { throw new RuntimeException("Stub!"); } +@libcore.util.NonNull public static java.util.Map<java.lang.String,java.lang.String> getenv() { throw new RuntimeException("Stub!"); } public static void exit(int status) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/sdk/nullability/java/lang/ThreadLocal.annotated.java b/ojluni/annotations/sdk/nullability/java/lang/ThreadLocal.annotated.java index 3b7e93a430..b8cf5276b6 100644 --- a/ojluni/annotations/sdk/nullability/java/lang/ThreadLocal.annotated.java +++ b/ojluni/annotations/sdk/nullability/java/lang/ThreadLocal.annotated.java @@ -37,7 +37,7 @@ public ThreadLocal() { throw new RuntimeException("Stub!"); } @libcore.util.Nullable protected T initialValue() { throw new RuntimeException("Stub!"); } -public static <S> java.lang.ThreadLocal<S> withInitial(@libcore.util.NonNull java.util.function.Supplier<? extends S> supplier) { throw new RuntimeException("Stub!"); } +@libcore.util.NonNull public static <S> java.lang.ThreadLocal<S> withInitial(@libcore.util.NonNull java.util.function.Supplier<? extends S> supplier) { throw new RuntimeException("Stub!"); } @libcore.util.Nullable public T get() { throw new RuntimeException("Stub!"); } @@ -45,4 +45,3 @@ public void set(@libcore.util.NullFromTypeParam T value) { throw new RuntimeExce public void remove() { throw new RuntimeException("Stub!"); } } - diff --git a/ojluni/annotations/sdk/nullability/java/lang/reflect/Executable.annotated.java b/ojluni/annotations/sdk/nullability/java/lang/reflect/Executable.annotated.java index 4b5b841fa9..d964aadabb 100644 --- a/ojluni/annotations/sdk/nullability/java/lang/reflect/Executable.annotated.java +++ b/ojluni/annotations/sdk/nullability/java/lang/reflect/Executable.annotated.java @@ -61,7 +61,7 @@ public boolean isSynthetic() { throw new RuntimeException("Stub!"); } public abstract java.lang.annotation.@libcore.util.NonNull Annotation @libcore.util.NonNull [] @libcore.util.NonNull [] getParameterAnnotations(); -@libcore.util.Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@libcore.util.NonNull getjava.lang.Class<T> annotationClass) { throw new RuntimeException("Stub!"); } +@libcore.util.Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@libcore.util.NonNull java.lang.Class<T> annotationClass) { throw new RuntimeException("Stub!"); } public <T extends java.lang.annotation.Annotation> T[] getAnnotationsByType(@libcore.util.NonNull java.lang.Class<T> annotationClass) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/sdk/nullability/java/util/HashMap.annotated.java b/ojluni/annotations/sdk/nullability/java/util/HashMap.annotated.java index 567354ac64..3bcc489b8c 100644 --- a/ojluni/annotations/sdk/nullability/java/util/HashMap.annotated.java +++ b/ojluni/annotations/sdk/nullability/java/util/HashMap.annotated.java @@ -74,11 +74,11 @@ public boolean replace(@libcore.util.NullFromTypeParam K key, @libcore.util.Null @libcore.util.Nullable public V computeIfAbsent(@libcore.util.NullFromTypeParam K key, @libcore.util.NonNull java.util.function.Function<? super @libcore.util.NullFromTypeParam K,? extends @libcore.util.Nullable V> mappingFunction) { throw new RuntimeException("Stub!"); } -@libcore.util.Nullable public V computeIfPresent(@libcore.util.NullFromTypeParam K key, @libcore.util.NonNull java.util.function.BiFunction<? super @libcore.util.NullFromTypeParam K,? super @libcore.util.NonNull V,? extends Nu V> remappingFunction) { throw new RuntimeException("Stub!"); } +@libcore.util.Nullable public V computeIfPresent(@libcore.util.NullFromTypeParam K key, @libcore.util.NonNull java.util.function.BiFunction<? super @libcore.util.NullFromTypeParam K,? super @libcore.util.NonNull V,? extends @libcore.util.Nullable V> remappingFunction) { throw new RuntimeException("Stub!"); } @libcore.util.Nullable public V compute(@libcore.util.NullFromTypeParam K key, @libcore.util.NonNull java.util.function.BiFunction<? super @libcore.util.NullFromTypeParam K,? super @libcore.util.Nullable V,? extends @libcore.util.Nullable V> remappingFunction) { throw new RuntimeException("Stub!"); } -@libcore.util.Nullable public V merge(@libcore.util.NullFromTypeParam K key, @libcore.util.NonNull V value, @libcore.util.NonNull java.util.function.BiFunction<? super Nn V,? super @libcore.util.NonNull V,? extends @libcore.util.Nullable V> remappingFunction) { throw new RuntimeException("Stub!"); } +@libcore.util.Nullable public V merge(@libcore.util.NullFromTypeParam K key, @libcore.util.NonNull V value, @libcore.util.NonNull java.util.function.BiFunction<? super @libcore.util.NonNull V,? super @libcore.util.NonNull V,? extends @libcore.util.Nullable V> remappingFunction) { throw new RuntimeException("Stub!"); } public void forEach(@libcore.util.NonNull java.util.function.BiConsumer<? super @libcore.util.NullFromTypeParam K,? super @libcore.util.NullFromTypeParam V> action) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/annotations/sdk/nullability/java/util/List.annotated.java b/ojluni/annotations/sdk/nullability/java/util/List.annotated.java index 958b33531c..2ef4a6f066 100644 --- a/ojluni/annotations/sdk/nullability/java/util/List.annotated.java +++ b/ojluni/annotations/sdk/nullability/java/util/List.annotated.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,4 +86,29 @@ public int lastIndexOf(@libcore.util.Nullable java.lang.Object o); @libcore.util.NonNull public java.util.List<@libcore.util.NullFromTypeParam E> subList(int fromIndex, int toIndex); @libcore.util.NonNull public default java.util.Spliterator<@libcore.util.NullFromTypeParam E> spliterator() { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.List<@libcore.util.NonNull E> of() { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.List<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.List<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.List<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.List<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.List<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4, @libcore.util.NonNull E e5) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.List<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4, @libcore.util.NonNull E e5, @libcore.util.NonNull E e6) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.List<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4, @libcore.util.NonNull E e5, @libcore.util.NonNull E e6, @libcore.util.NonNull E e7) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.List<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4, @libcore.util.NonNull E e5, @libcore.util.NonNull E e6, @libcore.util.NonNull E e7, @libcore.util.NonNull E e8) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.List<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4, @libcore.util.NonNull E e5, @libcore.util.NonNull E e6, @libcore.util.NonNull E e7, @libcore.util.NonNull E e8, @libcore.util.NonNull E e9) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.List<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4, @libcore.util.NonNull E e5, @libcore.util.NonNull E e6, @libcore.util.NonNull E e7, @libcore.util.NonNull E e8, @libcore.util.NonNull E e9, @libcore.util.NonNull E e10) { throw new RuntimeException("Stub!"); } + +@java.lang.SafeVarargs +@libcore.util.NonNull public static <E> java.util.List<@libcore.util.NonNull E> of(E @libcore.util.NonNull ... elements) { throw new RuntimeException("Stub!"); } } diff --git a/ojluni/annotations/sdk/nullability/java/util/Map.annotated.java b/ojluni/annotations/sdk/nullability/java/util/Map.annotated.java index 400899603c..c19add2f1b 100644 --- a/ojluni/annotations/sdk/nullability/java/util/Map.annotated.java +++ b/ojluni/annotations/sdk/nullability/java/util/Map.annotated.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,6 +80,33 @@ public default boolean replace(@libcore.util.NullFromTypeParam K key, @libcore.u @libcore.util.Nullable public default V compute(@libcore.util.NullFromTypeParam K key, @libcore.util.NonNull java.util.function.BiFunction<? super @libcore.util.NullFromTypeParam K,? super @libcore.util.Nullable V,? extends @libcore.util.Nullable V> remappingFunction) { throw new RuntimeException("Stub!"); } @libcore.util.Nullable public default V merge(@libcore.util.NullFromTypeParam K key, @libcore.util.NonNull V value, @libcore.util.NonNull java.util.function.BiFunction<? super @libcore.util.NonNull V,? super @libcore.util.NonNull V,? extends @libcore.util.Nullable V> remappingFunction) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <K, V> java.util.Map<@libcore.util.NonNull K, @libcore.util.NonNull V> of() { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <K, V> java.util.Map<@libcore.util.NonNull K, @libcore.util.NonNull V> of(@libcore.util.NonNull K k1, @libcore.util.NonNull V v1) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <K, V> java.util.Map<@libcore.util.NonNull K, @libcore.util.NonNull V> of(@libcore.util.NonNull K k1, @libcore.util.NonNull V v1, @libcore.util.NonNull K k2, @libcore.util.NonNull V v2) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <K, V> java.util.Map<@libcore.util.NonNull K, @libcore.util.NonNull V> of(@libcore.util.NonNull K k1, @libcore.util.NonNull V v1, @libcore.util.NonNull K k2, @libcore.util.NonNull V v2, @libcore.util.NonNull K k3, @libcore.util.NonNull V v3) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <K, V> java.util.Map<@libcore.util.NonNull K, @libcore.util.NonNull V> of(@libcore.util.NonNull K k1, @libcore.util.NonNull V v1, @libcore.util.NonNull K k2, @libcore.util.NonNull V v2, @libcore.util.NonNull K k3, @libcore.util.NonNull V v3, @libcore.util.NonNull K k4, @libcore.util.NonNull V v4) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <K, V> java.util.Map<@libcore.util.NonNull K, @libcore.util.NonNull V> of(@libcore.util.NonNull K k1, @libcore.util.NonNull V v1, @libcore.util.NonNull K k2, @libcore.util.NonNull V v2, @libcore.util.NonNull K k3, @libcore.util.NonNull V v3, @libcore.util.NonNull K k4, @libcore.util.NonNull V v4, @libcore.util.NonNull K k5, @libcore.util.NonNull V v5) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <K, V> java.util.Map<@libcore.util.NonNull K, @libcore.util.NonNull V> of(@libcore.util.NonNull K k1, @libcore.util.NonNull V v1, @libcore.util.NonNull K k2, @libcore.util.NonNull V v2, @libcore.util.NonNull K k3, @libcore.util.NonNull V v3, @libcore.util.NonNull K k4, @libcore.util.NonNull V v4, @libcore.util.NonNull K k5, @libcore.util.NonNull V v5, @libcore.util.NonNull K k6, @libcore.util.NonNull V v6) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <K, V> java.util.Map<@libcore.util.NonNull K, @libcore.util.NonNull V> of(@libcore.util.NonNull K k1, @libcore.util.NonNull V v1, @libcore.util.NonNull K k2, @libcore.util.NonNull V v2, @libcore.util.NonNull K k3, @libcore.util.NonNull V v3, @libcore.util.NonNull K k4, @libcore.util.NonNull V v4, @libcore.util.NonNull K k5, @libcore.util.NonNull V v5, @libcore.util.NonNull K k6, @libcore.util.NonNull V v6, @libcore.util.NonNull K k7, @libcore.util.NonNull V v7) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <K, V> java.util.Map<@libcore.util.NonNull K, @libcore.util.NonNull V> of(@libcore.util.NonNull K k1, @libcore.util.NonNull V v1, @libcore.util.NonNull K k2, @libcore.util.NonNull V v2, @libcore.util.NonNull K k3, @libcore.util.NonNull V v3, @libcore.util.NonNull K k4, @libcore.util.NonNull V v4, @libcore.util.NonNull K k5, @libcore.util.NonNull V v5, @libcore.util.NonNull K k6, @libcore.util.NonNull V v6, @libcore.util.NonNull K k7, @libcore.util.NonNull V v7, @libcore.util.NonNull K k8, @libcore.util.NonNull V v8) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <K, V> java.util.Map<@libcore.util.NonNull K, @libcore.util.NonNull V> of(@libcore.util.NonNull K k1, @libcore.util.NonNull V v1, @libcore.util.NonNull K k2, @libcore.util.NonNull V v2, @libcore.util.NonNull K k3, @libcore.util.NonNull V v3, @libcore.util.NonNull K k4, @libcore.util.NonNull V v4, @libcore.util.NonNull K k5, @libcore.util.NonNull V v5, @libcore.util.NonNull K k6, @libcore.util.NonNull V v6, @libcore.util.NonNull K k7, @libcore.util.NonNull V v7, @libcore.util.NonNull K k8, @libcore.util.NonNull V v8, @libcore.util.NonNull K k9, @libcore.util.NonNull V v9) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <K, V> java.util.Map<@libcore.util.NonNull K, @libcore.util.NonNull V> of(@libcore.util.NonNull K k1, @libcore.util.NonNull V v1, @libcore.util.NonNull K k2, @libcore.util.NonNull V v2, @libcore.util.NonNull K k3, @libcore.util.NonNull V v3, @libcore.util.NonNull K k4, @libcore.util.NonNull V v4, @libcore.util.NonNull K k5, @libcore.util.NonNull V v5, @libcore.util.NonNull K k6, @libcore.util.NonNull V v6, @libcore.util.NonNull K k7, @libcore.util.NonNull V v7, @libcore.util.NonNull K k8, @libcore.util.NonNull V v8, @libcore.util.NonNull K k9, @libcore.util.NonNull V v9, @libcore.util.NonNull K k10, @libcore.util.NonNull V v10) { throw new RuntimeException("Stub!"); } + +@java.lang.SafeVarargs +@libcore.util.NonNull public static <K, V> java.util.Map<@libcore.util.NonNull K, @libcore.util.NonNull V> ofEntries(@libcore.util.NonNull java.util.Map.Entry<? extends @libcore.util.NonNull K,? extends @libcore.util.NonNull V>... entries) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <K, V> java.util.Map.Entry<@libcore.util.NonNull K, @libcore.util.NonNull V> entry(@libcore.util.NonNull K k, @libcore.util.NonNull V v) { throw new RuntimeException("Stub!"); } @SuppressWarnings({"unchecked", "deprecation", "all"}) public static interface Entry<K, V> { diff --git a/ojluni/annotations/sdk/nullability/java/util/Objects.annotated.java b/ojluni/annotations/sdk/nullability/java/util/Objects.annotated.java index 591a022fab..ee1b692b58 100644 --- a/ojluni/annotations/sdk/nullability/java/util/Objects.annotated.java +++ b/ojluni/annotations/sdk/nullability/java/util/Objects.annotated.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,5 +55,9 @@ public static boolean isNull(@libcore.util.Nullable java.lang.Object obj) { thro public static boolean nonNull(@libcore.util.Nullable java.lang.Object obj) { throw new RuntimeException("Stub!"); } +@libcore.util.NonNull public static <T> T requireNonNullElse(@libcore.util.Nullable T obj, @libcore.util.NonNull T defaultObj) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <T> T requireNonNullElseGet(@libcore.util.Nullable T obj, @libcore.util.NonNull java.util.function.Supplier<? extends @libcore.util.NonNull T> supplier) { throw new RuntimeException("Stub!"); } + @libcore.util.NonNull public static <T> T requireNonNull(@libcore.util.Nullable T obj, @libcore.util.NonNull java.util.function.Supplier<@libcore.util.NonNull java.lang.String> messageSupplier) { throw new RuntimeException("Stub!"); } } diff --git a/ojluni/annotations/sdk/nullability/java/util/Set.annotated.java b/ojluni/annotations/sdk/nullability/java/util/Set.annotated.java index 1257b5c4c0..bae8bdd743 100644 --- a/ojluni/annotations/sdk/nullability/java/util/Set.annotated.java +++ b/ojluni/annotations/sdk/nullability/java/util/Set.annotated.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,4 +62,29 @@ public boolean equals(@libcore.util.Nullable java.lang.Object o); public int hashCode(); @libcore.util.NonNull public default java.util.Spliterator<@libcore.util.NullFromTypeParam E> spliterator() { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.Set<@libcore.util.NonNull E> of() { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.Set<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.Set<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.Set<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.Set<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.Set<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4, @libcore.util.NonNull E e5) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.Set<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4, @libcore.util.NonNull E e5, @libcore.util.NonNull E e6) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.Set<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4, @libcore.util.NonNull E e5, @libcore.util.NonNull E e6, @libcore.util.NonNull E e7) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.Set<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4, @libcore.util.NonNull E e5, @libcore.util.NonNull E e6, @libcore.util.NonNull E e7, @libcore.util.NonNull E e8) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.Set<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4, @libcore.util.NonNull E e5, @libcore.util.NonNull E e6, @libcore.util.NonNull E e7, @libcore.util.NonNull E e8, @libcore.util.NonNull E e9) { throw new RuntimeException("Stub!"); } + +@libcore.util.NonNull public static <E> java.util.Set<@libcore.util.NonNull E> of(@libcore.util.NonNull E e1, @libcore.util.NonNull E e2, @libcore.util.NonNull E e3, @libcore.util.NonNull E e4, @libcore.util.NonNull E e5, @libcore.util.NonNull E e6, @libcore.util.NonNull E e7, @libcore.util.NonNull E e8, @libcore.util.NonNull E e9, @libcore.util.NonNull E e10) { throw new RuntimeException("Stub!"); } + +@java.lang.SafeVarargs +@libcore.util.NonNull public static <E> java.util.Set<@libcore.util.NonNull E> of(E @libcore.util.NonNull ... elements) { throw new RuntimeException("Stub!"); } } diff --git a/ojluni/annotations/sdk/nullability/java/util/logging/Logger.annotated.java b/ojluni/annotations/sdk/nullability/java/util/logging/Logger.annotated.java index 2ad4bfbbf7..f3a25cbf47 100644 --- a/ojluni/annotations/sdk/nullability/java/util/logging/Logger.annotated.java +++ b/ojluni/annotations/sdk/nullability/java/util/logging/Logger.annotated.java @@ -75,7 +75,7 @@ public void logp(@libcore.util.NonNull java.util.logging.Level level, @libcore.u public void logp(@libcore.util.NonNull java.util.logging.Level level, @libcore.util.Nullable java.lang.String sourceClass, @libcore.util.Nullable java.lang.String sourceMethod, @libcore.util.Nullable java.lang.String msg, @libcore.util.Nullable java.lang.Object param1) { throw new RuntimeException("Stub!"); } -public void logp(@libcore.util.NonNull java.util.logging.Level level, @libcore.util.Nullable java.lang.String sourceClass, @libcore.util.Nullable java.lang.String sourceMethod, @libcore.util.Nullable java.lang.String msg, java.lang.@libcore.util.Nullable Object @Nu [] params) { throw new RuntimeException("Stub!"); } +public void logp(@libcore.util.NonNull java.util.logging.Level level, @libcore.util.Nullable java.lang.String sourceClass, @libcore.util.Nullable java.lang.String sourceMethod, @libcore.util.Nullable java.lang.String msg, java.lang.@libcore.util.Nullable Object @libcore.util.Nullable [] params) { throw new RuntimeException("Stub!"); } public void logp(@libcore.util.NonNull java.util.logging.Level level, @libcore.util.Nullable java.lang.String sourceClass, @libcore.util.Nullable java.lang.String sourceMethod, @libcore.util.Nullable java.lang.String msg, @libcore.util.Nullable java.lang.Throwable thrown) { throw new RuntimeException("Stub!"); } diff --git a/ojluni/src/generated-annotation/java/javax/annotation/processing/Generated.java b/ojluni/src/generated-annotation/java/javax/annotation/processing/Generated.java new file mode 100644 index 0000000000..cd3e666f6d --- /dev/null +++ b/ojluni/src/generated-annotation/java/javax/annotation/processing/Generated.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package javax.annotation.processing; + +import java.lang.annotation.*; +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +// Android-changed: Javadoc removed (this is just a stub). + +@Documented +@Retention(SOURCE) +@Target({PACKAGE, TYPE, METHOD, CONSTRUCTOR, FIELD, + LOCAL_VARIABLE, PARAMETER}) +public @interface Generated { + + String[] value(); + + String date() default ""; + + String comments() default ""; +} diff --git a/ojluni/src/lambda/java/java/lang/invoke/TEST_MAPPING b/ojluni/src/lambda/java/java/lang/invoke/TEST_MAPPING new file mode 100644 index 0000000000..e321f0bc55 --- /dev/null +++ b/ojluni/src/lambda/java/java/lang/invoke/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "imports": [ + { + "path": "libcore/libart/src/main/java/java/lang/invoke" + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/awt/font/TEST_MAPPING b/ojluni/src/main/java/java/awt/font/TEST_MAPPING new file mode 100644 index 0000000000..a23d298cc8 --- /dev/null +++ b/ojluni/src/main/java/java/awt/font/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.awt.font" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/beans/TEST_MAPPING b/ojluni/src/main/java/java/beans/TEST_MAPPING new file mode 100644 index 0000000000..0e669a8e6d --- /dev/null +++ b/ojluni/src/main/java/java/beans/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.beans.tests.java.beans" + }, + { + "include-filter": "libcore.java.util.beans" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/io/FileDescriptor.java b/ojluni/src/main/java/java/io/FileDescriptor.java index a2c833dc22..98db443816 100644 --- a/ojluni/src/main/java/java/io/FileDescriptor.java +++ b/ojluni/src/main/java/java/io/FileDescriptor.java @@ -46,9 +46,9 @@ import java.util.concurrent.atomic.AtomicInteger; * @see java.io.FileOutputStream * @since JDK1.0 */ -// Android-changed: Removed parent reference counting. Creator is responsible for closing -// the file descriptor. public final class FileDescriptor { + // Android-changed: Removed parent reference counting. Creator is responsible for closing + // the file descriptor. // Android-changed: Renamed fd to descriptor to avoid issues with JNI/reflection // fetching the descriptor value. @@ -82,8 +82,7 @@ public final class FileDescriptor { * * @see java.lang.System#in */ - // Android-changed: Duplicates of FDs needed for RuntimeInit#redirectLogStreams - public static final FileDescriptor in = dupFd(0); + public static final FileDescriptor in = new FileDescriptor(0); /** * A handle to the standard output stream. Usually, this file @@ -91,8 +90,7 @@ public final class FileDescriptor { * known as <code>System.out</code>. * @see java.lang.System#out */ - // Android-changed: Duplicates of FDs needed for RuntimeInit#redirectLogStreams - public static final FileDescriptor out = dupFd(1); + public static final FileDescriptor out = new FileDescriptor(1); /** * A handle to the standard error stream. Usually, this file @@ -101,8 +99,7 @@ public final class FileDescriptor { * * @see java.lang.System#err */ - // Android-changed: Duplicates of FDs needed for RuntimeInit#redirectLogStreams - public static final FileDescriptor err = dupFd(2); + public static final FileDescriptor err = new FileDescriptor(2); /** * Tests if this file descriptor object is valid. @@ -169,6 +166,26 @@ public final class FileDescriptor { this.descriptor = fd; } + // BEGIN Android-added: Method to clone standard file descriptors. + // Required as a consequence of RuntimeInit#redirectLogStreams. Cloning is used in + // ZygoteHooks.onEndPreload(). + /** + * Clones the current native file descriptor and uses this for this FileDescriptor instance. + * + * This method does not close the current native file descriptor. + * + * @hide internal use only + */ + public void cloneForFork() { + try { + int newDescriptor = Os.fcntlInt(this, F_DUPFD_CLOEXEC, 0); + this.descriptor = newDescriptor; + } catch (ErrnoException e) { + throw new RuntimeException(e); + } + } + // END Android-added: Method to clone standard file descriptors. + // BEGIN Android-added: Methods to enable ownership enforcement of Unix file descriptors. /** * Returns the owner ID of this FileDescriptor. It's highly unlikely you should be calling this. @@ -206,23 +223,14 @@ public final class FileDescriptor { } // END Android-added: Methods to enable ownership enforcement of Unix file descriptors. + // Android-added: Needed for framework to test if it's a socket /** * @hide internal use only */ - // Android-added: Needed for framework to test if it's a socket public boolean isSocket$() { return isSocket(descriptor); } - // Android-added: Needed for RuntimeInit#redirectLogStreams. - private static FileDescriptor dupFd(int fd) { - try { - return new FileDescriptor(Os.fcntlInt(new FileDescriptor(fd), F_DUPFD_CLOEXEC, 0)); - } catch (ErrnoException e) { - throw new RuntimeException(e); - } - } - private static native boolean isSocket(int descriptor); // Set up JavaIOFileDescriptorAccess in SharedSecrets static { diff --git a/ojluni/src/main/java/java/io/FileInputStream.java b/ojluni/src/main/java/java/io/FileInputStream.java index 74ee3aabb7..38230bbc90 100755 --- a/ojluni/src/main/java/java/io/FileInputStream.java +++ b/ojluni/src/main/java/java/io/FileInputStream.java @@ -154,9 +154,11 @@ class FileInputStream extends InputStream if (file.isInvalid()) { throw new FileNotFoundException("Invalid file path"); } - // Android-changed: Open files through common bridge code. + // BEGIN Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic. + // http://b/112107427 // fd = new FileDescriptor(); fd = IoBridge.open(name, O_RDONLY); + // END Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic. // Android-changed: Tracking mechanism for FileDescriptor sharing. // fd.attach(this); @@ -164,7 +166,7 @@ class FileInputStream extends InputStream path = name; - // Android-removed: Open files through common bridge code. + // Android-removed: Open files using IoBridge to share BlockGuard & StrictMode logic. // open(name); // Android-added: File descriptor ownership tracking. @@ -222,20 +224,25 @@ class FileInputStream extends InputStream this.isFdOwner = isFdOwner; } + // BEGIN Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic. + // http://b/112107427 + /* /** * Opens the specified file for reading. * @param name the name of the file - */ + * private native void open0(String name) throws FileNotFoundException; // wrap native call to allow instrumentation /** * Opens the specified file for reading. * @param name the name of the file - */ + * private void open(String name) throws FileNotFoundException { open0(name); } + */ + // END Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic. /** * Reads a byte of data from this input stream. This method blocks diff --git a/ojluni/src/main/java/java/io/FileOutputStream.java b/ojluni/src/main/java/java/io/FileOutputStream.java index 95ad1be138..d0d0d403cd 100755 --- a/ojluni/src/main/java/java/io/FileOutputStream.java +++ b/ojluni/src/main/java/java/io/FileOutputStream.java @@ -229,11 +229,12 @@ class FileOutputStream extends OutputStream if (file.isInvalid()) { throw new FileNotFoundException("Invalid file path"); } - // BEGIN Android-changed: Open files through common bridge code. + // BEGIN Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic. + // http://b/111268862 // this.fd = new FileDescriptor(); int flags = O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC); this.fd = IoBridge.open(name, flags); - // END Android-changed: Open files through common bridge code. + // END Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic. // Android-changed: Tracking mechanism for FileDescriptor sharing. // fd.attach(this); @@ -242,7 +243,7 @@ class FileOutputStream extends OutputStream this.append = append; this.path = name; - // Android-removed: Open files through common bridge code. + // Android-removed: Open files using IoBridge to share BlockGuard & StrictMode logic. // open(name, append); // Android-added: File descriptor ownership tracking. @@ -300,11 +301,14 @@ class FileOutputStream extends OutputStream this.isFdOwner = isFdOwner; } + // BEGIN Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic. + // http://b/112107427 + /* /** * Opens a file, with the specified name, for overwriting or appending. * @param name name of file to be opened * @param append whether the file is to be opened in append mode - */ + * private native void open0(String name, boolean append) throws FileNotFoundException; @@ -313,11 +317,13 @@ class FileOutputStream extends OutputStream * Opens a file, with the specified name, for overwriting or appending. * @param name name of file to be opened * @param append whether the file is to be opened in append mode - */ + * private void open(String name, boolean append) throws FileNotFoundException { open0(name, append); } + */ + // END Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic. // Android-removed: write(int, boolean), use IoBridge instead. /* diff --git a/ojluni/src/main/java/java/io/FilterOutputStream.java b/ojluni/src/main/java/java/io/FilterOutputStream.java index 209e63b77c..89f5ef529b 100644 --- a/ojluni/src/main/java/java/io/FilterOutputStream.java +++ b/ojluni/src/main/java/java/io/FilterOutputStream.java @@ -48,6 +48,12 @@ class FilterOutputStream extends OutputStream { */ protected OutputStream out; + // Android-added: Integrate OpenJDK 9 fix for double-close. http://b/122733269. + /** + * Whether the stream is closed; implicitly initialized to false. + */ + private boolean closed; + /** * Creates an output stream filter built on top of the specified * underlying output stream. @@ -144,18 +150,58 @@ class FilterOutputStream extends OutputStream { * Closes this output stream and releases any system resources * associated with the stream. * <p> - * The <code>close</code> method of <code>FilterOutputStream</code> - * calls its <code>flush</code> method, and then calls the - * <code>close</code> method of its underlying output stream. + * When not already closed, the {@code close} method of {@code + * FilterOutputStream} calls its {@code flush} method, and then + * calls the {@code close} method of its underlying output stream. * * @exception IOException if an I/O error occurs. * @see java.io.FilterOutputStream#flush() * @see java.io.FilterOutputStream#out */ + // BEGIN Android-changed: Integrate OpenJDK 9 fix for double-close. http://b/122733269. + /* @SuppressWarnings("try") public void close() throws IOException { try (OutputStream ostream = out) { flush(); } } + */ + @Override + public void close() throws IOException { + if (closed) { + return; + } + closed = true; + + Throwable flushException = null; + try { + flush(); + } catch (Throwable e) { + flushException = e; + throw e; + } finally { + if (flushException == null) { + out.close(); + } else { + try { + out.close(); + } catch (Throwable closeException) { + // evaluate possible precedence of flushException over closeException + if ((flushException instanceof ThreadDeath) && + !(closeException instanceof ThreadDeath)) { + flushException.addSuppressed(closeException); + throw (ThreadDeath) flushException; + } + + if (flushException != closeException) { + closeException.addSuppressed(flushException); + } + + throw closeException; + } + } + } + } + // END Android-changed: Integrate OpenJDK 9 fix for double-close. http://b/122733269. } diff --git a/ojluni/src/main/java/java/io/InterruptedIOException.java b/ojluni/src/main/java/java/io/InterruptedIOException.java index 25569dd8b0..29b7c29ab2 100644 --- a/ojluni/src/main/java/java/io/InterruptedIOException.java +++ b/ojluni/src/main/java/java/io/InterruptedIOException.java @@ -73,18 +73,18 @@ class InterruptedIOException extends IOException { */ public int bytesTransferred = 0; - /** @hide */ // Android-added: Additional constructor for internal use. + /** @hide */ public InterruptedIOException(Throwable cause) { super(cause); } + // Android-added: Additional constructor for internal use. /** * Constructs a new instance with given detail message and cause. * * @hide internal use only */ - // Android-added: Additional constructor for internal use. public InterruptedIOException(String detailMessage, Throwable cause) { super(detailMessage, cause); } diff --git a/ojluni/src/main/java/java/io/ObjectInputStream.java b/ojluni/src/main/java/java/io/ObjectInputStream.java index 56b5abe3f8..8369a59da7 100644 --- a/ojluni/src/main/java/java/io/ObjectInputStream.java +++ b/ojluni/src/main/java/java/io/ObjectInputStream.java @@ -202,7 +202,7 @@ import dalvik.system.VMStack; * @see java.io.DataInput * @see java.io.ObjectOutputStream * @see java.io.Serializable - * @see <a href="https://docs.oracle.com/javase/8/docs/platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a> + * @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a> * @since JDK1.1 */ public class ObjectInputStream diff --git a/ojluni/src/main/java/java/io/ObjectOutputStream.java b/ojluni/src/main/java/java/io/ObjectOutputStream.java index fa8a65831f..ccec944eb1 100644 --- a/ojluni/src/main/java/java/io/ObjectOutputStream.java +++ b/ojluni/src/main/java/java/io/ObjectOutputStream.java @@ -157,7 +157,7 @@ import sun.reflect.misc.ReflectUtil; * @see java.io.ObjectInputStream * @see java.io.Serializable * @see java.io.Externalizable - * @see <a href="https://docs.oracle.com/javase/8/docs/platform/serialization/spec/output.html">Object Serialization Specification, Section 2, Object Output Classes</a> + * @see <a href="../../../platform/serialization/spec/output.html">Object Serialization Specification, Section 2, Object Output Classes</a> * @since JDK1.1 */ public class ObjectOutputStream diff --git a/ojluni/src/main/java/java/io/ObjectStreamClass.java b/ojluni/src/main/java/java/io/ObjectStreamClass.java index 7d2efd2af2..a88ad63bed 100644 --- a/ojluni/src/main/java/java/io/ObjectStreamClass.java +++ b/ojluni/src/main/java/java/io/ObjectStreamClass.java @@ -60,13 +60,13 @@ import dalvik.system.VMRuntime; * loaded in this Java VM can be found/created using the lookup method. * * <p>The algorithm to compute the SerialVersionUID is described in - * <a href="https://docs.oracle.com/javase/8/docs/platform/serialization/spec/class.html#4100">Object + * <a href="../../../platform/serialization/spec/class.html#4100">Object * Serialization Specification, Section 4.6, Stream Unique Identifiers</a>. * * @author Mike Warres * @author Roger Riggs * @see ObjectStreamField - * @see <a href="https://docs.oracle.com/javase/8/docs/platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a> + * @see <a href="../../../platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a> * @since JDK1.1 */ public class ObjectStreamClass implements Serializable { diff --git a/ojluni/src/main/java/java/io/TEST_MAPPING b/ojluni/src/main/java/java/io/TEST_MAPPING new file mode 100644 index 0000000000..6eb3bd74de --- /dev/null +++ b/ojluni/src/main/java/java/io/TEST_MAPPING @@ -0,0 +1,18 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.io" + }, + { + "include-filter": "org.apache.harmony.luni.tests.java.io" + }, + { + "include-filter": "org.apache.harmony.tests.java.io" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/io/package.html b/ojluni/src/main/java/java/io/package.html index db1c8a5db8..1b909adac7 100644 --- a/ojluni/src/main/java/java/io/package.html +++ b/ojluni/src/main/java/java/io/package.html @@ -36,7 +36,7 @@ or method in any class or interface in this package will cause a <h2>Package Specification</h2> <ul> - <li><a href="https://docs.oracle.com/javase/8/docs/platform/serialization/spec/serialTOC.html"> Java Object Serialization Specification </a> + <li><a href="../../../platform/serialization/spec/serialTOC.html"> Java Object Serialization Specification </a> </ul> <h2>Related Documentation</h2> @@ -44,7 +44,7 @@ or method in any class or interface in this package will cause a For overviews, tutorials, examples, guides, and tool documentation, please see: <ul> - <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/serialization">Serialization Enhancements</a> + <li><a href="../../../technotes/guides/serialization">Serialization Enhancements</a> </ul> @since JDK1.0 diff --git a/ojluni/src/main/java/java/lang/Byte.java b/ojluni/src/main/java/java/lang/Byte.java index e53899cdec..deb4ecb403 100644 --- a/ojluni/src/main/java/java/lang/Byte.java +++ b/ojluni/src/main/java/java/lang/Byte.java @@ -25,6 +25,8 @@ package java.lang; +import libcore.util.HexEncoding; + /** * * The {@code Byte} class wraps a value of primitive type {@code byte} @@ -523,24 +525,8 @@ public final class Byte extends Number implements Comparable<Byte> { * @hide */ public static String toHexString(byte b, boolean upperCase) { - char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS; - char[] buf = new char[2]; // We always want two digits. - buf[0] = digits[(b >> 4) & 0xf]; - buf[1] = digits[b & 0xf]; - return new String(0, 2, buf); + // This method currently retained because it is marked @UnsupportedAppUsage. + return HexEncoding.encodeToString(b, upperCase); } - private static final char[] DIGITS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', - 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', - 'u', 'v', 'w', 'x', 'y', 'z' - }; - - private static final char[] UPPER_CASE_DIGITS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z' - }; // END Android-added: toHexString() for internal use. } diff --git a/ojluni/src/main/java/java/lang/Comparable.java b/ojluni/src/main/java/java/lang/Comparable.java index f0e4b38730..a88cf167fb 100644 --- a/ojluni/src/main/java/java/lang/Comparable.java +++ b/ojluni/src/main/java/java/lang/Comparable.java @@ -84,7 +84,7 @@ import java.util.*; * {(x, y) such that x.equals(y)}. </pre><p> * * This interface is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <T> the type of objects that this object may be compared to diff --git a/ojluni/src/main/java/java/lang/Iterable.java b/ojluni/src/main/java/java/lang/Iterable.java index db0e7673fd..eed39388a8 100644 --- a/ojluni/src/main/java/java/lang/Iterable.java +++ b/ojluni/src/main/java/java/lang/Iterable.java @@ -30,12 +30,11 @@ import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; -// Android-changed: href changed in javadoc for redirection. /** * Implementing this interface allows an object to be the target of * the "for-each loop" statement. See * <strong> - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/language/foreach.html">For-each Loop</a> + * <a href="{@docRoot}/../technotes/guides/language/foreach.html">For-each Loop</a> * </strong> * * @param <T> the type of elements returned by the iterator diff --git a/ojluni/src/main/java/java/lang/Math.java b/ojluni/src/main/java/java/lang/Math.java index bb84b81ae9..17cbf6d3c9 100644 --- a/ojluni/src/main/java/java/lang/Math.java +++ b/ojluni/src/main/java/java/lang/Math.java @@ -31,6 +31,10 @@ import java.util.Random; import sun.misc.FloatConsts; import sun.misc.DoubleConsts; +// Android-note: Document that the results from Math are based on libm's behavior. +// For performance, Android implements many of the methods in this class in terms of the underlying +// OS's libm functions. libm has well-defined behavior for special cases. Where known these are +// marked with the tag above and the documentation has been modified as needed. /** * The class {@code Math} contains methods for performing basic * numeric operations such as the elementary exponential, logarithm, @@ -502,6 +506,11 @@ public final class Math { @CriticalNative public static native double atan2(double y, double x); + // Android-changed: Document that the results from Math are based on libm's behavior. + // The cases known to differ with libm's pow(): + // If the first argument is 1.0 then result is always 1.0 (not NaN). + // If the first argument is -1.0 and the second argument is infinite, the result is 1.0 (not + // NaN). /** * Returns the value of the first argument raised to the power of the * second argument. Special cases: @@ -510,7 +519,9 @@ public final class Math { * result is 1.0. * <li>If the second argument is 1.0, then the result is the same as the * first argument. - * <li>If the second argument is NaN, then the result is NaN. + * <li>If the first argument is 1.0, then the result is 1.0. + * <li>If the second argument is NaN, then the result is NaN except where the first argument is + * 1.0. * <li>If the first argument is NaN and the second argument is nonzero, * then the result is NaN. * @@ -534,7 +545,7 @@ public final class Math { * then the result is positive zero. * * <li>If the absolute value of the first argument equals 1 and the - * second argument is infinite, then the result is NaN. + * second argument is infinite, then the result is 1.0. * * <li>If * <ul> diff --git a/ojluni/src/main/java/java/lang/Runtime.java b/ojluni/src/main/java/java/lang/Runtime.java index bb0bcb4d1d..f5c52e7b9d 100644 --- a/ojluni/src/main/java/java/lang/Runtime.java +++ b/ojluni/src/main/java/java/lang/Runtime.java @@ -35,7 +35,8 @@ import sun.reflect.CallerSensitive; import java.lang.ref.FinalizerReference; import java.util.ArrayList; import java.util.List; -import dalvik.system.BaseDexClassLoader; +import dalvik.system.DelegateLastClassLoader; +import dalvik.system.PathClassLoader; import dalvik.system.VMDebug; import dalvik.system.VMRuntime; import sun.reflect.Reflection; @@ -1058,6 +1059,21 @@ public class Runtime { // have returned null; therefore we treat BootClassLoader the same as null here. if (loader != null && !(loader instanceof BootClassLoader)) { String filename = loader.findLibrary(libraryName); + if (filename == null && + (loader.getClass() == PathClassLoader.class || + loader.getClass() == DelegateLastClassLoader.class)) { + // Don't give up even if we failed to find the library in the native lib paths. + // The underlying dynamic linker might be able to find the lib in one of the linker + // namespaces associated with the current linker namespace. In order to give the + // dynamic linker a chance, proceed to load the library with its soname, which + // is the fileName. + // Note that we do this only for PathClassLoader and DelegateLastClassLoader to + // minimize the scope of this behavioral change as much as possible, which might + // cause problem like b/143649498. These two class loaders are the only + // platform-provided class loaders that can load apps. See the classLoader attribute + // of the application tag in app manifest. + filename = System.mapLibraryName(libraryName); + } if (filename == null) { // It's not necessarily true that the ClassLoader used // System.mapLibraryName, but the default setup does, and it's diff --git a/ojluni/src/main/java/java/lang/String.java b/ojluni/src/main/java/java/lang/String.java index 58207eb111..2ba7b1f805 100644 --- a/ojluni/src/main/java/java/lang/String.java +++ b/ojluni/src/main/java/java/lang/String.java @@ -144,7 +144,7 @@ public final class String * Class String is special cased within the Serialization Stream Protocol. * * A String instance is written into an ObjectOutputStream according to - * <a href="https://docs.oracle.com/javase/8/docs/platform/serialization/spec/output.html"> + * <a href="{@docRoot}/../platform/serialization/spec/output.html"> * Object Serialization Specification, Section 6.2, "Stream Elements"</a> */ private static final ObjectStreamField[] serialPersistentFields = diff --git a/ojluni/src/main/java/java/lang/System.java b/ojluni/src/main/java/java/lang/System.java index 8235bf754b..352d9eca00 100644 --- a/ojluni/src/main/java/java/lang/System.java +++ b/ojluni/src/main/java/java/lang/System.java @@ -25,20 +25,19 @@ */ package java.lang; +import com.android.icu.util.Icu4cMetadata; +import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; import android.system.ErrnoException; import android.system.StructPasswd; import android.system.StructUtsname; import dalvik.system.VMRuntime; import java.io.*; -import java.lang.annotation.Annotation; import java.nio.channels.Channel; import java.nio.channels.spi.SelectorProvider; import java.util.Locale; -import java.util.Map; import java.util.Properties; import java.util.PropertyPermission; -import libcore.icu.ICU; import libcore.io.Libcore; import libcore.timezone.TimeZoneDataFiles; @@ -296,6 +295,7 @@ public final class System { * the current time and midnight, January 1, 1970 UTC. * @see java.util.Date */ + @CriticalNative public static native long currentTimeMillis(); /** @@ -342,6 +342,7 @@ public final class System { * high-resolution time source, in nanoseconds * @since 1.5 */ + @CriticalNative public static native long nanoTime(); /** @@ -509,13 +510,9 @@ public final class System { * The byte[] specialized version of arraycopy(). * Note: This method is required for runtime ART compiler optimizations. * Do not remove or change the signature. - * Note: Unlike the others, this variant is public due to a dependency we - * are working on removing. b/74103559 - * - * @hide */ @SuppressWarnings("unused") - public static void arraycopy(byte[] src, int srcPos, byte[] dst, int dstPos, int length) { + private static void arraycopy(byte[] src, int srcPos, byte[] dst, int dstPos, int length) { if (src == null) { throw new NullPointerException("src == null"); } @@ -1000,9 +997,9 @@ public final class System { p.put("os.version", info.release); // Android-added: Undocumented properties that exist only on Android. - p.put("android.icu.library.version", ICU.getIcuVersion()); - p.put("android.icu.unicode.version", ICU.getUnicodeVersion()); - p.put("android.icu.cldr.version", ICU.getCldrVersion()); + p.put("android.icu.library.version", Icu4cMetadata.getIcuVersion()); + p.put("android.icu.unicode.version", Icu4cMetadata.getUnicodeVersion()); + p.put("android.icu.cldr.version", Icu4cMetadata.getCldrVersion()); // Property override for ICU4J : this is the location of the ICU4C data. This // is prioritized over the properties in ICUConfig.properties. The issue with using diff --git a/ojluni/src/main/java/java/lang/TEST_MAPPING b/ojluni/src/main/java/java/lang/TEST_MAPPING new file mode 100644 index 0000000000..9374f92dae --- /dev/null +++ b/ojluni/src/main/java/java/lang/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "imports": [ + { + "path": "libcore/libart/src/main/java/java/lang" + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/lang/Thread.java b/ojluni/src/main/java/java/lang/Thread.java index 54fd49aba2..699a1ac539 100644 --- a/ojluni/src/main/java/java/lang/Thread.java +++ b/ojluni/src/main/java/java/lang/Thread.java @@ -40,6 +40,8 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.LockSupport; import sun.nio.ch.Interruptible; import sun.reflect.CallerSensitive; +import dalvik.system.RuntimeHooks; +import dalvik.system.ThreadPrioritySetter; import dalvik.system.VMStack; import libcore.util.EmptyArray; @@ -282,11 +284,11 @@ class Thread implements Runnable { private volatile Interruptible blocker; private final Object blockerLock = new Object(); - /** Set the blocker field - * @hide - */ // Android-changed: Make blockedOn() @hide public, for internal use. - // Used by java.nio.channels.spi.AbstractInterruptibleChannel. + // Changed comment to reflect usage on Android + /* Set the blocker field; used by java.nio.channels.spi.AbstractInterruptibleChannel + */ + /** @hide */ public void blockedOn(Interruptible b) { synchronized (blockerLock) { blocker = b; @@ -662,8 +664,8 @@ class Thread implements Runnable { init(group, null, name, 0); } + // BEGIN Android-added: Private constructor - used by the runtime. /** @hide */ - // Android-added: Private constructor - used by the runtime. Thread(ThreadGroup group, String name, int priority, boolean daemon) { this.group = group; this.group.addUnstarted(); @@ -692,6 +694,8 @@ class Thread implements Runnable { parent.inheritableThreadLocals); } } + // END Android-added: Private constructor - used by the runtime. + /** * Allocates a new {@code Thread} object. This constructor has the same @@ -961,7 +965,7 @@ class Thread implements Runnable { * for example), the <code>interrupt</code> method should be used to * interrupt the wait. * For more information, see - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why + * <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. */ @Deprecated @@ -997,7 +1001,7 @@ class Thread implements Runnable { * could be used to generate exceptions that the target thread was * not prepared to handle. * For more information, see - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why + * <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. */ @Deprecated @@ -1122,7 +1126,7 @@ class Thread implements Runnable { private native boolean isInterrupted(boolean ClearInterrupted); */ - // Android-changed: Throw UnsupportedOperationException instead of NoSuchMethodError. + // BEGIN Android-changed: Throw UnsupportedOperationException instead of NoSuchMethodError. /** * Throws {@link UnsupportedOperationException}. * @@ -1136,7 +1140,7 @@ class Thread implements Runnable { * If another thread ever attempted to lock this resource, deadlock * would result. Such deadlocks typically manifest themselves as * "frozen" processes. For more information, see - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html"> + * <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html"> * Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. * @throws UnsupportedOperationException always */ @@ -1144,6 +1148,7 @@ class Thread implements Runnable { public void destroy() { throw new UnsupportedOperationException(); } + // END Android-changed: Throw UnsupportedOperationException instead of NoSuchMethodError. /** * Tests if this thread is alive. A thread is alive if it has @@ -1169,7 +1174,7 @@ class Thread implements Runnable { * monitor prior to calling <code>resume</code>, deadlock results. Such * deadlocks typically manifest themselves as "frozen" processes. * For more information, see - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why + * <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. * @throws UnsupportedOperationException always */ @@ -1189,7 +1194,7 @@ class Thread implements Runnable { * @deprecated This method exists solely for use with {@link #suspend}, * which has been deprecated because it is deadlock-prone. * For more information, see - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why + * <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. * @throws UnsupportedOperationException always */ @@ -1241,7 +1246,18 @@ class Thread implements Runnable { synchronized(this) { this.priority = newPriority; if (isAlive()) { - setPriority0(newPriority); + // BEGIN Android-added: Customize behavior of Thread.setPriority(). + // http://b/139521784 + // setPriority0(newPriority); + ThreadPrioritySetter threadPrioritySetter = + RuntimeHooks.getThreadPrioritySetter(); + int nativeTid = this.getNativeTid(); + if (threadPrioritySetter != null && nativeTid != 0) { + threadPrioritySetter.setPriority(nativeTid, newPriority); + } else { + setPriority0(newPriority); + } + // END Android-added: Customize behavior of Thread.setPriority(). } } } @@ -2106,7 +2122,7 @@ class Thread implements Runnable { return defaultUncaughtExceptionHandler; } - // BEGIN Android-added: uncaughtExceptionPreHandler for use by platform. + // BEGIN Android-added: The concept of an uncaughtExceptionPreHandler for use by platform. // See http://b/29624607 for background information. // null unless explicitly set private static volatile UncaughtExceptionHandler uncaughtExceptionPreHandler; @@ -2129,7 +2145,7 @@ class Thread implements Runnable { public static UncaughtExceptionHandler getUncaughtExceptionPreHandler() { return uncaughtExceptionPreHandler; } - // END Android-added: uncaughtExceptionPreHandler for use by platform. + // END Android-added: The concept of an uncaughtExceptionPreHandler for use by platform. /** * Returns the handler invoked when this thread abruptly terminates @@ -2324,4 +2340,14 @@ class Thread implements Runnable { // Android-added: Android specific nativeGetStatus() method. private native int nativeGetStatus(boolean hasBeenStarted); + + // BEGIN Android-added: Customize behavior of Thread.setPriority(). http://b/139521784 + /** + * Returns the thread ID of the underlying native thread -- which is different from + * the {@link #getId() managed thread ID} -- or 0 if the native thread is not + * started or has stopped. + */ + @FastNative + private native int getNativeTid(); + // END Android-added: Customize behavior of Thread.setPriority(). http://b/139521784 } diff --git a/ojluni/src/main/java/java/lang/UnsupportedOperationException.java b/ojluni/src/main/java/java/lang/UnsupportedOperationException.java index 1de2508aa3..fcb355c036 100644 --- a/ojluni/src/main/java/java/lang/UnsupportedOperationException.java +++ b/ojluni/src/main/java/java/lang/UnsupportedOperationException.java @@ -29,7 +29,7 @@ package java.lang; * Thrown to indicate that the requested operation is not supported.<p> * * This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch diff --git a/ojluni/src/main/java/java/lang/annotation/TEST_MAPPING b/ojluni/src/main/java/java/lang/annotation/TEST_MAPPING new file mode 100644 index 0000000000..f5f636500f --- /dev/null +++ b/ojluni/src/main/java/java/lang/annotation/TEST_MAPPING @@ -0,0 +1,18 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.lang.reflect.annotations" + }, + { + "include-filter": "libcore.java.lang.annotation" + }, + { + "include-filter": "org.apache.harmony.annotation.tests.java.lang.annotation" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java index 17c5f57d1d..1188ac60e4 100644 --- a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java +++ b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java @@ -1129,7 +1129,8 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method // Make sure that the special caller is identical to the lookup class or that we have // private access. - checkSpecialCaller(specialCaller); + // Android-changed: Also allow access to any interface methods. + checkSpecialCaller(specialCaller, refc); // Even though constructors are invoked using a "special" invoke, handles to them can't // be created using findSpecial. Callers must use findConstructor instead. Similarly, @@ -1655,7 +1656,9 @@ return mh1; } if (!m.isAccessible()) { - checkSpecialCaller(specialCaller); + // Android-changed: Match Java language 9 behavior where unreflectSpecial continues + // to require exact caller lookupClass match. + checkSpecialCaller(specialCaller, null); } final MethodType methodType = MethodType.methodType(m.getReturnType(), @@ -1937,13 +1940,19 @@ return mh1; // // private static final boolean ALLOW_NESTMATE_ACCESS = false; - private void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException { + // Android-changed: Match java language 9 behavior allowing special access if the reflected + // class (called 'refc', the class from which the method is being accessed) is an interface + // and is implemented by the caller. + private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException { // Android-changed: No support for TRUSTED lookups. Also construct the // IllegalAccessException by hand because the upstream code implicitly assumes // that the lookupClass == specialCaller. // // if (allowedModes == TRUSTED) return; - if (!hasPrivateAccess() || (specialCaller != lookupClass())) { + boolean isInterfaceLookup = (refc != null && + refc.isInterface() && + refc.isAssignableFrom(specialCaller)); + if (!hasPrivateAccess() || (specialCaller != lookupClass() && !isInterfaceLookup)) { throw new IllegalAccessException("no private access for invokespecial : " + specialCaller + ", from" + this); } @@ -2588,15 +2597,24 @@ return invoker; MethodType oldType = target.type(); if (oldType == newType) return target; if (oldType.explicitCastEquivalentToAsType(newType)) { - return target.asFixedArity().asType(newType); + if (Transformers.Transformer.class.isAssignableFrom(target.getClass())) { + // The StackFrameReader and StackFrameWriter used to perform transforms on + // EmulatedStackFrames (in Transformers.java) do not how to perform asType() + // conversions, but we know here that an explicit cast transform is the same as + // having called asType() on the method handle. + return new Transformers.ExplicitCastArguments(target.asFixedArity(), newType); + } else { + // Runtime will perform asType() conversion during invocation. + return target.asFixedArity().asType(newType); + } } - return new Transformers.ExplicitCastArguments(target, newType); } private static void explicitCastArgumentsChecks(MethodHandle target, MethodType newType) { if (target.type().parameterCount() != newType.parameterCount()) { - throw new WrongMethodTypeException("cannot explicitly cast " + target + " to " + newType); + throw new WrongMethodTypeException("cannot explicitly cast " + target + + " to " + newType); } } diff --git a/ojluni/src/main/java/java/lang/invoke/MethodType.java b/ojluni/src/main/java/java/lang/invoke/MethodType.java index b2ff6e73e1..4652c9348c 100644 --- a/ojluni/src/main/java/java/lang/invoke/MethodType.java +++ b/ojluni/src/main/java/java/lang/invoke/MethodType.java @@ -894,9 +894,6 @@ class MethodType implements java.io.Serializable { return true; } - // Android-changed: Temporary workaround for bug in MethodHandle.asType(MethodType). - // See http://b/113855305 for more details - // Update documentation to describe new behavior. /** Reports true if the src can be converted to the dst, by both asType and MHs.eCE, * and with the same effect. * MHs.eCA has the following "upgrades" to MH.asType: @@ -914,9 +911,7 @@ class MethodType implements java.io.Serializable { */ private static boolean explicitCastEquivalentToAsType(Class<?> src, Class<?> dst) { if (src == dst || dst == Object.class || dst == void.class) return true; - // Android-changed: Temporary workaround for bug in MethodHandle.asType(MethodType). - // if (src.isPrimitive()) { - if (src.isPrimitive() && src != void.class) { + if (src.isPrimitive()) { // Could be a prim/prim conversion, where casting is a strict superset. // Or a boxing conversion, which is always to an exact wrapper class. return canConvert(src, dst); diff --git a/ojluni/src/main/java/java/lang/invoke/TEST_MAPPING b/ojluni/src/main/java/java/lang/invoke/TEST_MAPPING new file mode 100644 index 0000000000..e321f0bc55 --- /dev/null +++ b/ojluni/src/main/java/java/lang/invoke/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "imports": [ + { + "path": "libcore/libart/src/main/java/java/lang/invoke" + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/lang/invoke/Transformers.java b/ojluni/src/main/java/java/lang/invoke/Transformers.java index fc8727a41e..15546a8333 100644 --- a/ojluni/src/main/java/java/lang/invoke/Transformers.java +++ b/ojluni/src/main/java/java/lang/invoke/Transformers.java @@ -417,7 +417,7 @@ public class Transformers { @Override public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable { - final Class<?> receiverType = type().rtype(); + final Class<?> receiverType = constructorHandle.type().parameterType(0); checkInstantiable(receiverType); // Allocate memory for receiver. @@ -1827,27 +1827,9 @@ public class Transformers { throw new InternalError("Unexpected type: " + unexpectedType); } - private static void explicitCastFromBoolean(boolean fromValue, - final StackFrameWriter writer, - final Class<?> to) { - int value = fromValue ? 1 : 0; - if (to == byte.class) { - writer.putNextByte((byte) value); - } else if (to == char.class) { - writer.putNextChar((char) value); - } else if (to == short.class) { - writer.putNextShort((short) value); - } else if (to == int.class) { - writer.putNextInt(value); - } else if (to == long.class) { - writer.putNextLong(value); - } else if (to == float.class) { - writer.putNextFloat(value); - } else if (to == double.class) { - writer.putNextDouble(value); - } else { - throwUnexpectedType(to); - } + @SuppressWarnings("unchecked") + private static void badCast(final Class<?> from, final Class<?> to) { + throw new ClassCastException("Cannot cast " + from.getName() + " to " + to.getName()); } /** @@ -1874,6 +1856,8 @@ public class Transformers { return (byte) reader.nextFloat(); } else if (from == double.class) { return (byte) reader.nextDouble(); + } else if (from == boolean.class) { + return reader.nextBoolean() ? (byte) 1 : (byte) 0; } else { throwUnexpectedType(from); return 0; @@ -1896,6 +1880,8 @@ public class Transformers { return (char) reader.nextFloat(); } else if (from == double.class) { return (char) reader.nextDouble(); + } else if (from == boolean.class) { + return reader.nextBoolean() ? (char) 1 : (char) 0; } else { throwUnexpectedType(from); return 0; @@ -1918,6 +1904,8 @@ public class Transformers { return (short) reader.nextFloat(); } else if (from == double.class) { return (short) reader.nextDouble(); + } else if (from == boolean.class) { + return reader.nextBoolean() ? (short) 1 : (short) 0; } else { throwUnexpectedType(from); return 0; @@ -1940,6 +1928,8 @@ public class Transformers { return (int) reader.nextFloat(); } else if (from == double.class) { return (int) reader.nextDouble(); + } else if (from == boolean.class) { + return reader.nextBoolean() ? 1 : 0; } else { throwUnexpectedType(from); return 0; @@ -1962,6 +1952,8 @@ public class Transformers { return (long) reader.nextFloat(); } else if (from == double.class) { return (long) reader.nextDouble(); + } else if (from == boolean.class) { + return reader.nextBoolean() ? 1L : 0L; } else { throwUnexpectedType(from); return 0; @@ -1984,6 +1976,8 @@ public class Transformers { return (float) reader.nextFloat(); } else if (from == double.class) { return (float) reader.nextDouble(); + } else if (from == boolean.class) { + return reader.nextBoolean() ? 1.0f : 0.0f; } else { throwUnexpectedType(from); return 0; @@ -2006,19 +2000,14 @@ public class Transformers { return (double) reader.nextFloat(); } else if (from == double.class) { return (double) reader.nextDouble(); + } else if (from == boolean.class) { + return reader.nextBoolean() ? 1.0 : 0.0; } else { throwUnexpectedType(from); return 0; } } - private static void explicitCastToBoolean(final StackFrameReader reader, - final Class<?> from, - final StackFrameWriter writer) { - byte byteValue = readPrimitiveAsByte(reader, from); - writer.putNextBoolean(toBoolean(byteValue)); - } - private static void explicitCastPrimitives(final StackFrameReader reader, final Class<?> from, final StackFrameWriter writer, @@ -2044,6 +2033,9 @@ public class Transformers { } else if (to == double.class) { double value = readPrimitiveAsDouble(reader, from); writer.putNextDouble(value); + } else if (to == boolean.class) { + byte byteValue = readPrimitiveAsByte(reader, from); + writer.putNextBoolean(toBoolean(byteValue)); } else { throwUnexpectedType(to); } @@ -2073,32 +2065,176 @@ public class Transformers { private static void unboxNonNull(final Object ref, final Class<?> from, final StackFrameWriter writer, final Class<?> to) { - if (to == boolean.class) { - if (from == Boolean.class) { - writer.putNextBoolean((boolean) ref); - } else if (from == Float.class || from == Double.class) { - byte b = (byte) ((double) ref); - writer.putNextBoolean(toBoolean(b)); + if (from == Boolean.class) { + boolean z = (boolean) ref; + if (to == boolean.class) { + writer.putNextBoolean(z); + } else if (to == byte.class) { + writer.putNextByte(z ? (byte) 1 : (byte) 0); + } else if (to == short.class) { + writer.putNextShort(z ? (short) 1 : (short) 0); + } else if (to == char.class) { + writer.putNextChar(z ? (char) 1 : (char) 0); + } else if (to == int.class) { + writer.putNextInt(z ? 1 : 0); + } else if (to == long.class) { + writer.putNextLong(z ? 1l : 0l); + } else if (to == float.class) { + writer.putNextFloat(z ? 1.0f : 0.0f); + } else if (to == double.class) { + writer.putNextDouble(z ? 1.0 : 0.0); } else { - byte b = (byte) ((long) ref); + badCast(from, to); + } + } else if (from == Byte.class) { + byte b = (byte) ref; + if (to == byte.class) { + writer.putNextByte(b); + } else if (to == boolean.class) { writer.putNextBoolean(toBoolean(b)); + } else if (to == short.class) { + writer.putNextShort((short) b); + } else if (to == char.class) { + writer.putNextChar((char) b); + } else if (to == int.class) { + writer.putNextInt((int) b); + } else if (to == long.class) { + writer.putNextLong((long) b); + } else if (to == float.class) { + writer.putNextFloat((float) b); + } else if (to == double.class) { + writer.putNextDouble((double) b); + } else { + badCast(from, to); + } + } else if (from == Short.class) { + short s = (short) ref; + if (to == boolean.class) { + writer.putNextBoolean((s & 1) == 1); + } else if (to == byte.class) { + writer.putNextByte((byte) s); + } else if (to == short.class) { + writer.putNextShort(s); + } else if (to == char.class) { + writer.putNextChar((char) s); + } else if (to == int.class) { + writer.putNextInt((int) s); + } else if (to == long.class) { + writer.putNextLong((long) s); + } else if (to == float.class) { + writer.putNextFloat((float) s); + } else if (to == double.class) { + writer.putNextDouble((double) s); + } else { + badCast(from, to); + } + } else if (from == Character.class) { + char c = (char) ref; + if (to == boolean.class) { + writer.putNextBoolean((c & (char) 1) == (char) 1); + } else if (to == byte.class) { + writer.putNextByte((byte) c); + } else if (to == short.class) { + writer.putNextShort((short) c); + } else if (to == char.class) { + writer.putNextChar(c); + } else if (to == int.class) { + writer.putNextInt((int) c); + } else if (to == long.class) { + writer.putNextLong((long) c); + } else if (to == float.class) { + writer.putNextFloat((float) c); + } else if (to == double.class) { + writer.putNextDouble((double) c); + } else { + badCast(from, to); + } + } else if (from == Integer.class) { + int i = (int) ref; + if (to == boolean.class) { + writer.putNextBoolean((i & 1) == 1); + } else if (to == byte.class) { + writer.putNextByte((byte) i); + } else if (to == short.class) { + writer.putNextShort((short) i); + } else if (to == char.class) { + writer.putNextChar((char) i); + } else if (to == int.class) { + writer.putNextInt(i); + } else if (to == long.class) { + writer.putNextLong((long) i); + } else if (to == float.class) { + writer.putNextFloat((float) i); + } else if (to == double.class) { + writer.putNextDouble((double) i); + } else { + badCast(from, to); + } + } else if (from == Long.class) { + long j = (long) ref; + if (to == boolean.class) { + writer.putNextBoolean((j & 1l) == 1l); + } else if (to == byte.class) { + writer.putNextByte((byte) j); + } else if (to == short.class) { + writer.putNextShort((short) j); + } else if (to == char.class) { + writer.putNextChar((char) j); + } else if (to == int.class) { + writer.putNextInt((int) j); + } else if (to == long.class) { + writer.putNextLong(j); + } else if (to == float.class) { + writer.putNextFloat((float) j); + } else if (to == double.class) { + writer.putNextDouble((double) j); + } else { + badCast(from, to); + } + } else if (from == Float.class) { + float f = (float) ref; + if (to == boolean.class) { + writer.putNextBoolean(((byte) f & 1) != 0); + } else if (to == byte.class) { + writer.putNextByte((byte) f); + } else if (to == short.class) { + writer.putNextShort((short) f); + } else if (to == char.class) { + writer.putNextChar((char) f); + } else if (to == int.class) { + writer.putNextInt((int) f); + } else if (to == long.class) { + writer.putNextLong((long) f); + } else if (to == float.class) { + writer.putNextFloat(f); + } else if (to == double.class) { + writer.putNextDouble((double) f); + } else { + badCast(from, to); + } + } else if (from == Double.class) { + double d = (double) ref; + if (to == boolean.class) { + writer.putNextBoolean(((byte) d & 1) != 0); + } else if (to == byte.class) { + writer.putNextByte((byte) d); + } else if (to == short.class) { + writer.putNextShort((short) d); + } else if (to == char.class) { + writer.putNextChar((char) d); + } else if (to == int.class) { + writer.putNextInt((int) d); + } else if (to == long.class) { + writer.putNextLong((long) d); + } else if (to == float.class) { + writer.putNextFloat((float) d); + } else if (to == double.class) { + writer.putNextDouble(d); + } else { + badCast(from, to); } - } else if (to == byte.class) { - writer.putNextByte((byte) ref); - } else if (to == char.class) { - writer.putNextChar((char) ref); - } else if (to == short.class) { - writer.putNextShort((short) ref); - } else if (to == int.class) { - writer.putNextInt((int) ref); - } else if (to == long.class) { - writer.putNextLong((long) ref); - } else if (to == float.class) { - writer.putNextFloat((float) ref); - } else if (to == double.class) { - writer.putNextDouble((double) ref); } else { - throwUnexpectedType(to); + badCast(from, to); } } @@ -2140,31 +2276,31 @@ public class Transformers { final StackFrameWriter writer, final Class<?> to) { if (from.equals(to)) { StackFrameAccessor.copyNext(reader, writer, from); - } else if (!from.isPrimitive()) { + return; + } + + if (from.isPrimitive()) { + if (to.isPrimitive()) { + // |from| and |to| are primitive types. + explicitCastPrimitives(reader, from, writer, to); + } else { + // |from| is a primitive type, |to| is a reference type. + box(reader, from, writer, to); + } + } else { + // |from| is a reference type. Object ref = reader.nextReference(from); - if (to.isInterface()) { + if (to.isPrimitive()) { + // |from| is a reference type, |to| is a primitive type, + unbox(ref, from, writer, to); + } else if (to.isInterface()) { // Pass from without a cast according to description for // {@link java.lang.invoke.MethodHandles#explicitCastArguments()}. writer.putNextReference(ref, to); - } else if (!to.isPrimitive()) { - // |to| is a reference type, perform class cast check. - writer.putNextReference(to.cast(ref), to); - } else { - // |from| is a reference type, |to| is a primitive type, - unbox(ref, from, writer, to); - } - } else if (to.isPrimitive()) { - // |from| and |to| are primitive types. - if (from == boolean.class) { - explicitCastFromBoolean(reader.nextBoolean(), writer, to); - } else if (to == boolean.class) { - explicitCastToBoolean(reader, from, writer); } else { - explicitCastPrimitives(reader, from, writer, to); + // |to| and from |from| are reference types, perform class cast check. + writer.putNextReference(to.cast(ref), to); } - } else { - // |from| is a primitive type, |to| is a reference type. - box(reader, from, writer, to); } } } diff --git a/ojluni/src/main/java/java/lang/ref/Reference.java b/ojluni/src/main/java/java/lang/ref/Reference.java index cf8c8b5d7f..e5126b533e 100644 --- a/ojluni/src/main/java/java/lang/ref/Reference.java +++ b/ojluni/src/main/java/java/lang/ref/Reference.java @@ -38,10 +38,11 @@ import dalvik.annotation.optimization.FastNative; * @author Mark Reinhold * @since 1.2 */ -// BEGIN Android-changed: Reimplemented to accommodate a different GC and compiler. -// ClassLinker knows about the fields of this class. public abstract class Reference<T> { + // BEGIN Android-changed: Reimplemented to accommodate a different GC and compiler. + // ClassLinker knows about the fields of this class. + /** * Forces JNI path. * If GC is not in progress (ie: not going through slow path), the referent diff --git a/ojluni/src/main/java/java/lang/ref/TEST_MAPPING b/ojluni/src/main/java/java/lang/ref/TEST_MAPPING new file mode 100644 index 0000000000..c90a051bb3 --- /dev/null +++ b/ojluni/src/main/java/java/lang/ref/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "imports": [ + { + "path": "libcore/luni/src/main/java/java/lang/ref" + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/lang/reflect/Field.java b/ojluni/src/main/java/java/lang/reflect/Field.java index 2bcf9e9297..ca5857a3e6 100644 --- a/ojluni/src/main/java/java/lang/reflect/Field.java +++ b/ojluni/src/main/java/java/lang/reflect/Field.java @@ -61,7 +61,7 @@ class Field extends AccessibleObject implements Member { private int accessFlags; private Class<?> declaringClass; - private int dexFieldIndex; + private int artFieldIndex; private int offset; private Class<?> type; @@ -82,12 +82,17 @@ class Field extends AccessibleObject implements Member { */ public String getName() { // Android-changed: getName() implemented differently. - if (dexFieldIndex == -1) { + if (declaringClass.isProxy()) { // Proxy classes have 1 synthesized static field with no valid dex index. - if (!declaringClass.isProxy()) { - throw new AssertionError(); + if ((getModifiers() & Modifier.STATIC) == 0) { + throw new AssertionError("Invalid modifiers for proxy field: " + getModifiers()); + } + // Only 2 fields are present on proxy classes. + switch (artFieldIndex) { + case 0: return "interfaces"; + case 1: return "throws"; + default: throw new AssertionError("Invalid index for proxy: " + artFieldIndex); } - return "throws"; } return getNameInternal(); @@ -928,15 +933,6 @@ class Field extends AccessibleObject implements Member { // BEGIN Android-added: Methods for use by Android-specific code. /** - * Returns the index of this field's ID in its dex file. - * - * @hide - */ - public int getDexFieldIndex() { - return dexFieldIndex; - } - - /** * Returns the offset of the field within an instance, or for static fields, the class. * * @hide diff --git a/ojluni/src/main/java/java/lang/reflect/TEST_MAPPING b/ojluni/src/main/java/java/lang/reflect/TEST_MAPPING new file mode 100644 index 0000000000..2d13e0a2ee --- /dev/null +++ b/ojluni/src/main/java/java/lang/reflect/TEST_MAPPING @@ -0,0 +1,18 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.lang.reflect" + }, + { + "include-filter": "libcore.java.lang.reflect.annotations" + }, + { + "include-filter": "org.apache.harmony.tests.java.lang.reflect" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/net/Inet6AddressImpl.java b/ojluni/src/main/java/java/net/Inet6AddressImpl.java index bb722f3df2..84bcf17eda 100644 --- a/ojluni/src/main/java/java/net/Inet6AddressImpl.java +++ b/ojluni/src/main/java/java/net/Inet6AddressImpl.java @@ -27,7 +27,7 @@ package java.net; import android.system.ErrnoException; import android.system.GaiException; import android.system.StructAddrinfo; -import android.system.StructIcmpHdr; +import android.system.IcmpHeaders; import dalvik.system.BlockGuard; @@ -258,12 +258,12 @@ class Inet6AddressImpl implements InetAddressImpl { byte[] packet; // ICMP is unreliable, try sending requests every second until timeout. - for (int to = timeout, seq = 0; to > 0; ++seq) { + for (int to = timeout, seq = 1; to > 0; ++seq) { int sockTo = to >= 1000 ? 1000 : to; IoBridge.setSocketOption(fd, SocketOptions.SO_TIMEOUT, sockTo); - packet = StructIcmpHdr.IcmpEchoHdr(isIPv4, seq).getBytes(); + packet = IcmpHeaders.createIcmpEchoHdr(isIPv4, seq); IoBridge.sendto(fd, packet, 0, packet.length, 0, addr, 0); final int icmpId = IoBridge.getLocalInetSocketAddress(fd).getPort(); @@ -277,11 +277,11 @@ class Inet6AddressImpl implements InetAddressImpl { if (receivedPacket.getAddress().equals(addr) && received[0] == expectedType && received[4] == (byte) (icmpId >> 8) - && received[5] == (byte) icmpId - && received[6] == (byte) (seq >> 8) - && received[7] == (byte) seq) { - // This is the packet we're expecting. - return true; + && received[5] == (byte) icmpId) { + int receivedSequence = ((received[6] & 0xff) << 8) + (received[7] & 0xff); + if (receivedSequence <= seq) { + return true; + } } } to -= sockTo; diff --git a/ojluni/src/main/java/java/net/NetworkInterface.java b/ojluni/src/main/java/java/net/NetworkInterface.java index 673a1d2013..a30b6bf2cf 100644 --- a/ojluni/src/main/java/java/net/NetworkInterface.java +++ b/ojluni/src/main/java/java/net/NetworkInterface.java @@ -47,6 +47,7 @@ import static android.system.OsConstants.*; // Android-note: NetworkInterface has been rewritten to avoid native code. // Fix upstream bug not returning link-down interfaces. http://b/26238832 +// Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849 /** * This class represents a Network Interface made up of a name, * and a list of IP addresses assigned to this interface. @@ -54,6 +55,12 @@ import static android.system.OsConstants.*; * is joined. * * Interfaces are normally known by names such as "le0". + * <p> + * <a name="access-restrictions"></a>Note that information about + * {@link NetworkInterface}s may be restricted. For example, non-system apps + * with {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R} will only + * have access to information about {@link NetworkInterface}s that are + * associated with an {@link InetAddress}. * * @since 1.4 */ @@ -265,6 +272,7 @@ public final class NetworkInterface { return "".equals(displayName) ? null : displayName; } + // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849 /** * Searches for the network interface with the specified name. * @@ -272,8 +280,9 @@ public final class NetworkInterface { * The name of the network interface. * * @return A {@code NetworkInterface} with the specified name, - * or {@code null} if there is no network interface - * with the specified name. + * or {@code null} if the network interface with the specified + * name does not exist or <a href="#access-restrictions">can't be + * accessed</a>. * * @throws SocketException * If an I/O error occurs. @@ -295,12 +304,14 @@ public final class NetworkInterface { return null; } + // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849 /** * Get a network interface given its index. * * @param index an integer, the index of the interface * @return the NetworkInterface obtained from its index, or {@code null} if - * there is no interface with such an index on the system + * an interface with the specified index does not exist or + * <a href="#access-restrictions">can't be accessed</a>. * @throws SocketException if an I/O error occurs. * @throws IllegalArgumentException if index has a negative value * @see #getIndex() @@ -362,6 +373,7 @@ public final class NetworkInterface { return null; } + // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849 /** * Returns all the interfaces on this machine. The {@code Enumeration} * contains at least one element, possibly representing a loopback @@ -370,20 +382,44 @@ public final class NetworkInterface { * * NOTE: can use getNetworkInterfaces()+getInetAddresses() * to obtain all IP addresses for this node + * <p> + * For non-system apps with + * {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R}, this + * method will only return information for {@link NetworkInterface}s that + * are associated with an {@link InetAddress}. * * @return an Enumeration of NetworkInterfaces found on this machine + * that <a href="#access-restrictions">are accessible</a>. * @exception SocketException if an I/O error occurs. */ public static Enumeration<NetworkInterface> getNetworkInterfaces() throws SocketException { final NetworkInterface[] netifs = getAll(); - // Android-changed: Rewrote NetworkInterface on top of Libcore.io. - // specified to return null if no network interfaces + // // specified to return null if no network interfaces + // if (netifs == null) if (netifs.length == 0) return null; + // Android-changed: Rewrote NetworkInterface on top of Libcore.io. + /* + return new Enumeration<NetworkInterface>() { + private int i = 0; + public NetworkInterface nextElement() { + if (netifs != null && i < netifs.length) { + NetworkInterface netif = netifs[i++]; + return netif; + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasMoreElements() { + return (netifs != null && i < netifs.length); + } + }; + */ return Collections.enumeration(Arrays.asList(netifs)); } @@ -523,6 +559,7 @@ public final class NetworkInterface { return (getFlags() & IFF_MULTICAST) != 0; } + // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849 /** * Returns the hardware address (usually MAC) of the interface if it * has one and if it can be accessed given the current privileges. @@ -532,7 +569,10 @@ public final class NetworkInterface { * @return a byte array containing the address, or {@code null} if * the address doesn't exist, is not accessible or a security * manager is set and the caller does not have the permission - * NetPermission("getNetworkInformation") + * NetPermission("getNetworkInformation"). For example, this + * method will generally return {@code null} when called by + * non-system apps having + * {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R}. * * @exception SocketException if an I/O error occurs. * @since 1.6 diff --git a/ojluni/src/main/java/java/net/ServerSocket.java b/ojluni/src/main/java/java/net/ServerSocket.java index bb495e6c46..444a84deef 100644 --- a/ojluni/src/main/java/java/net/ServerSocket.java +++ b/ojluni/src/main/java/java/net/ServerSocket.java @@ -244,6 +244,7 @@ class ServerSocket implements java.io.Closeable { } } + // Android-changed: Made getImpl() public and @hide, for internal use. /** * Get the {@code SocketImpl} attached to this socket, creating * it if necessary. @@ -253,7 +254,6 @@ class ServerSocket implements java.io.Closeable { * @since 1.4 * @hide */ - // Android-changed: Make ctor public and @hide, for internal use. public SocketImpl getImpl() throws SocketException { if (!created) createImpl(); diff --git a/ojluni/src/main/java/java/net/Socket.java b/ojluni/src/main/java/java/net/Socket.java index e36d15b2d8..bae1d1c24a 100644 --- a/ojluni/src/main/java/java/net/Socket.java +++ b/ojluni/src/main/java/java/net/Socket.java @@ -139,7 +139,7 @@ class Socket implements java.io.Closeable { security.checkConnect(epoint.getAddress().getHostAddress(), epoint.getPort()); } - // Android-changed: Removed HTTP proxy suppport. + // Android-changed: Removed HTTP proxy support. // impl = type == Proxy.Type.SOCKS ? new SocksSocketImpl(p) // : new HttpConnectSocketImpl(p); impl = new SocksSocketImpl(p); diff --git a/ojluni/src/main/java/java/net/TEST_MAPPING b/ojluni/src/main/java/java/net/TEST_MAPPING new file mode 100644 index 0000000000..9149b154c2 --- /dev/null +++ b/ojluni/src/main/java/java/net/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "imports": [ + { + "path": "libcore/luni/src/main/java/java/net" + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/net/URI.java b/ojluni/src/main/java/java/net/URI.java index f5a51125f2..ebba41bc55 100644 --- a/ojluni/src/main/java/java/net/URI.java +++ b/ojluni/src/main/java/java/net/URI.java @@ -44,6 +44,7 @@ import java.lang.Character; // for javadoc import java.lang.NullPointerException; // for javadoc +// Android-changed: Reformat @see links. /** * Represents a Uniform Resource Identifier (URI) reference. * @@ -455,7 +456,7 @@ import java.lang.NullPointerException; // for javadoc * @see <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax</a> * @see <a href="http://www.ietf.org/rfc/rfc2732.txt">RFC 2732: Format for Literal IPv6 Addresses in URLs</a> */ -// Android-changed: Reformat @see links. + public final class URI implements Comparable<URI>, Serializable { diff --git a/ojluni/src/main/java/java/net/URLConnection.java b/ojluni/src/main/java/java/net/URLConnection.java index 1de7b3cafa..55ec26d9cc 100644 --- a/ojluni/src/main/java/java/net/URLConnection.java +++ b/ojluni/src/main/java/java/net/URLConnection.java @@ -288,13 +288,13 @@ public abstract class URLConnection { */ private static FileNameMap fileNameMap; - // BEGIN Android-removed: Android has its own mime table. + // BEGIN Android-changed: Android has its own mime table. /* + /** * @since 1.2.2 * private static boolean fileNameMapLoaded = false; - */ - // END Android-removed: Android has its own mime table. + /** * Loads filename map (a mimetable) from a data file. It will * first try to load the user-specific table, defined @@ -304,14 +304,36 @@ public abstract class URLConnection { * @return the FileNameMap * @since 1.2 * @see #setFileNameMap(java.net.FileNameMap) + * + public static synchronized FileNameMap getFileNameMap() { + if ((fileNameMap == null) && !fileNameMapLoaded) { + fileNameMap = sun.net.www.MimeTable.loadTable(); + fileNameMapLoaded = true; + } + + return new FileNameMap() { + private FileNameMap map = fileNameMap; + public String getContentTypeFor(String fileName) { + return map.getContentTypeFor(fileName); + } + }; + } + */ + /** + * Returns a {@link FileNameMap} implementation suitable for guessing a + * content type based on a URL's "file" component. + * + * @see #guessContentTypeFromName(String) + * @see #setFileNameMap(java.net.FileNameMap) + * */ public static synchronized FileNameMap getFileNameMap() { - // Android-changed: Android has its own mime table. if (fileNameMap == null) { fileNameMap = new DefaultFileNameMap(); } return fileNameMap; } + // END Android-changed: Android has its own mime table. /** * Sets the FileNameMap. diff --git a/ojluni/src/main/java/java/nio/TEST_MAPPING b/ojluni/src/main/java/java/nio/TEST_MAPPING new file mode 100644 index 0000000000..8a8180b315 --- /dev/null +++ b/ojluni/src/main/java/java/nio/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "imports": [ + { + "path": "libcore/luni/src/main/java/java/nio" + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/nio/channels/TEST_MAPPING b/ojluni/src/main/java/java/nio/channels/TEST_MAPPING new file mode 100644 index 0000000000..dfb741cebd --- /dev/null +++ b/ojluni/src/main/java/java/nio/channels/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.nio.channels" + }, + { + "include-filter": "org.apache.harmony.tests.java.nio.channels" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/nio/channels/spi/TEST_MAPPING b/ojluni/src/main/java/java/nio/channels/spi/TEST_MAPPING new file mode 100644 index 0000000000..7974b9ae4b --- /dev/null +++ b/ojluni/src/main/java/java/nio/channels/spi/TEST_MAPPING @@ -0,0 +1,18 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.nio.channels.spi" + }, + { + "include-filter": "org.apache.harmony.nio.tests.java.nio.channels.spi" + }, + { + "include-filter": "org.apache.harmony.tests.java.nio.channels.spi" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/nio/charset/Charset.java b/ojluni/src/main/java/java/nio/charset/Charset.java index 31543f016b..5a3b35a64e 100755 --- a/ojluni/src/main/java/java/nio/charset/Charset.java +++ b/ojluni/src/main/java/java/nio/charset/Charset.java @@ -26,13 +26,12 @@ package java.nio.charset; +import com.android.icu.charset.CharsetICU; import java.io.UnsupportedEncodingException; -import libcore.icu.NativeConverter; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.spi.CharsetProvider; import java.security.AccessController; -import java.security.AccessControlException; import java.security.PrivilegedAction; import java.util.AbstractMap; import java.util.Collections; @@ -52,6 +51,7 @@ import sun.nio.cs.ThreadLocalCoders; import sun.security.action.GetPropertyAction; +// Android-changed: Docs to say UTF-8 is always the platform default charset. /** * A named mapping between sequences of sixteen-bit Unicode <a * href="../../lang/Character.html#unicode">code units</a> and sequences of @@ -318,8 +318,8 @@ public abstract class Charset } } - /* The standard set of charsets */ // Android-removed: We use ICU's list of standard charsets. + /* The standard set of charsets */ // private static CharsetProvider standardProvider = new StandardCharsets(); // Cache of the most-recently-returned charsets, @@ -508,7 +508,7 @@ public abstract class Charset // Android-changed: Drop support for "standard" and "extended" // providers. - if ((cs = NativeConverter.charsetForName(charsetName)) != null || + if ((cs = CharsetICU.charsetForName(charsetName)) != null || (cs = lookupViaProviders(charsetName)) != null) { cache(charsetName, cs); @@ -566,7 +566,7 @@ public abstract class Charset throw new UnsupportedCharsetException(charsetName); } - + // BEGIN Android-added: forNameUEE(String) method. /** * Equivalent to {@code forName} but only throws {@code UnsupportedEncodingException}, * which is all pre-nio code claims to throw. @@ -582,7 +582,7 @@ public abstract class Charset throw ex; } } - + // END Android-added: forNameUEE(String) method. // Fold charsets from the given iterator into the given map, ignoring // charsets whose names already have entries in the map. @@ -628,8 +628,8 @@ public abstract class Charset TreeMap<String,Charset> m = new TreeMap<String,Charset>( ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); - for (String charsetName : NativeConverter.getAvailableCharsetNames()) { - Charset charset = NativeConverter.charsetForName(charsetName); + for (String charsetName : CharsetICU.getAvailableCharsetNames()) { + Charset charset = CharsetICU.charsetForName(charsetName); m.put(charset.name(), charset); } // Android-changed: No more "standard" provider. @@ -685,6 +685,7 @@ public abstract class Charset * @throws IllegalCharsetNameException * If the canonical name or any of the aliases are illegal */ + @libcore.api.IntraCoreApi protected Charset(String canonicalName, String[] aliases) { checkName(canonicalName); String[] as = (aliases == null) ? new String[0] : aliases; diff --git a/ojluni/src/main/java/java/nio/charset/CharsetEncoder.java b/ojluni/src/main/java/java/nio/charset/CharsetEncoder.java index 540199e254..98b4dea41c 100644 --- a/ojluni/src/main/java/java/nio/charset/CharsetEncoder.java +++ b/ojluni/src/main/java/java/nio/charset/CharsetEncoder.java @@ -197,8 +197,9 @@ public abstract class CharsetEncoder { * This constructor is for subclasses to specify whether {@code replacement} can be used as it * is ("trusted"). If it is trusted, {@link #replaceWith(byte[])} and * {@link #implReplaceWith(byte[])} will not be called. + * @hide */ - CharsetEncoder(Charset cs, float averageBytesPerChar, float maxBytesPerChar, byte[] replacement, + protected CharsetEncoder(Charset cs, float averageBytesPerChar, float maxBytesPerChar, byte[] replacement, boolean trusted) { // END Android-added: A hidden constructor for the CharsetEncoderICU subclass. diff --git a/ojluni/src/main/java/java/nio/charset/TEST_MAPPING b/ojluni/src/main/java/java/nio/charset/TEST_MAPPING new file mode 100644 index 0000000000..5fa13f1b0a --- /dev/null +++ b/ojluni/src/main/java/java/nio/charset/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "imports": [ + { + "path": "libcore/luni/src/main/java/java/nio/charset" + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/nio/file/TEST_MAPPING b/ojluni/src/main/java/java/nio/file/TEST_MAPPING new file mode 100644 index 0000000000..24bd29ae0c --- /dev/null +++ b/ojluni/src/main/java/java/nio/file/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.nio.file" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/nio/file/attribute/TEST_MAPPING b/ojluni/src/main/java/java/nio/file/attribute/TEST_MAPPING new file mode 100644 index 0000000000..b6c90d4453 --- /dev/null +++ b/ojluni/src/main/java/java/nio/file/attribute/TEST_MAPPING @@ -0,0 +1,20 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.nio.file.attribute" + } + ] + }, + { + "name": "CtsLibcoreOjTestCases", + "options": [ + { + "include-filter": "test.java.nio.file.attribute" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/nio/file/spi/TEST_MAPPING b/ojluni/src/main/java/java/nio/file/spi/TEST_MAPPING new file mode 100644 index 0000000000..632f30c3e9 --- /dev/null +++ b/ojluni/src/main/java/java/nio/file/spi/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.nio.file.spi" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/security/AlgorithmParameterGenerator.java b/ojluni/src/main/java/java/security/AlgorithmParameterGenerator.java index 4cab0c309f..7222b44f05 100644 --- a/ojluni/src/main/java/java/security/AlgorithmParameterGenerator.java +++ b/ojluni/src/main/java/java/security/AlgorithmParameterGenerator.java @@ -99,7 +99,7 @@ import java.security.spec.AlgorithmParameterSpec; * </table> * * These algorithms are described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator"> * AlgorithmParameterGenerator section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -164,7 +164,7 @@ public class AlgorithmParameterGenerator { * @param algorithm the name of the algorithm this * parameter generator is associated with. * See the AlgorithmParameterGenerator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -206,7 +206,7 @@ public class AlgorithmParameterGenerator { * @param algorithm the name of the algorithm this * parameter generator is associated with. * See the AlgorithmParameterGenerator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -252,7 +252,7 @@ public class AlgorithmParameterGenerator { * @param algorithm the string name of the algorithm this * parameter generator is associated with. * See the AlgorithmParameterGenerator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/java/security/AlgorithmParameters.java b/ojluni/src/main/java/java/security/AlgorithmParameters.java index 989159ec49..fd1966f1a9 100644 --- a/ojluni/src/main/java/java/security/AlgorithmParameters.java +++ b/ojluni/src/main/java/java/security/AlgorithmParameters.java @@ -153,7 +153,7 @@ import sun.security.jca.Providers; * </table> * * These algorithms are described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameters"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters"> * AlgorithmParameters section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -223,7 +223,7 @@ public class AlgorithmParameters { * * @param algorithm the name of the algorithm requested. * See the AlgorithmParameters section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameters"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -265,7 +265,7 @@ public class AlgorithmParameters { * * @param algorithm the name of the algorithm requested. * See the AlgorithmParameters section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameters"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -314,7 +314,7 @@ public class AlgorithmParameters { * * @param algorithm the name of the algorithm requested. * See the AlgorithmParameters section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameters"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/java/security/Key.java b/ojluni/src/main/java/java/security/Key.java index 37f4c84d1f..c0c63d7c7c 100644 --- a/ojluni/src/main/java/java/security/Key.java +++ b/ojluni/src/main/java/java/security/Key.java @@ -82,7 +82,7 @@ package java.security; * <p> A Key should use KeyRep as its serialized representation. * Note that a serialized Key may contain sensitive information * which should not be exposed in untrusted environments. See the - * <a href="https://docs.oracle.com/javase/8/docs/platform/serialization/spec/security.html"> + * <a href="../../../platform/serialization/spec/security.html"> * Security Appendix</a> * of the Serialization Specification for more information. * @@ -114,7 +114,7 @@ public interface Key extends java.io.Serializable { * Returns the standard algorithm name for this key. For * example, "DSA" would indicate that this key is a DSA key. * See Appendix A in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> + * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA"> * Java Cryptography Architecture API Specification & Reference </a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/java/security/KeyFactory.java b/ojluni/src/main/java/java/security/KeyFactory.java index f687d61ce7..716f62dc3e 100644 --- a/ojluni/src/main/java/java/security/KeyFactory.java +++ b/ojluni/src/main/java/java/security/KeyFactory.java @@ -100,7 +100,7 @@ import sun.security.jca.GetInstance.Instance; * </table> * * These algorithms are described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> * KeyFactory section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -178,7 +178,7 @@ public class KeyFactory { * * @param algorithm the name of the requested key algorithm. * See the KeyFactory section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -209,7 +209,7 @@ public class KeyFactory { * * @param algorithm the name of the requested key algorithm. * See the KeyFactory section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -250,7 +250,7 @@ public class KeyFactory { * * @param algorithm the name of the requested key algorithm. * See the KeyFactory section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/java/security/KeyPairGenerator.java b/ojluni/src/main/java/java/security/KeyPairGenerator.java index 1c4c2cba3d..7c6cdb547c 100644 --- a/ojluni/src/main/java/java/security/KeyPairGenerator.java +++ b/ojluni/src/main/java/java/security/KeyPairGenerator.java @@ -133,7 +133,7 @@ import sun.security.jca.GetInstance.Instance; * </table> * * These algorithms are described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator"> * KeyPairGenerator section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -162,7 +162,7 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { * * @param algorithm the standard string name of the algorithm. * See the KeyPairGenerator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. */ @@ -173,7 +173,7 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { /** * Returns the standard name of the algorithm for this key pair generator. * See the KeyPairGenerator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -220,7 +220,7 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { * * @param algorithm the standard string name of the algorithm. * See the KeyPairGenerator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -276,7 +276,7 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { * * @param algorithm the standard string name of the algorithm. * See the KeyPairGenerator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -317,7 +317,7 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { * * @param algorithm the standard string name of the algorithm. * See the KeyPairGenerator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/java/security/KeyRep.java b/ojluni/src/main/java/java/security/KeyRep.java index cae4c63656..0b1412c156 100644 --- a/ojluni/src/main/java/java/security/KeyRep.java +++ b/ojluni/src/main/java/java/security/KeyRep.java @@ -42,7 +42,7 @@ import javax.crypto.spec.SecretKeySpec; * * Note that a serialized Key may contain sensitive information * which should not be exposed in untrusted environments. See the - * <a href="https://docs.oracle.com/javase/8/docs/platform/serialization/spec/security.html"> + * <a href="../../../platform/serialization/spec/security.html"> * Security Appendix</a> * of the Serialization Specification for more information. * diff --git a/ojluni/src/main/java/java/security/KeyStore.java b/ojluni/src/main/java/java/security/KeyStore.java index 924f14f651..7781649b46 100644 --- a/ojluni/src/main/java/java/security/KeyStore.java +++ b/ojluni/src/main/java/java/security/KeyStore.java @@ -195,7 +195,7 @@ import javax.security.auth.callback.*; * </table> * * These types are described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyStore"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> * KeyStore section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -311,7 +311,7 @@ public class KeyStore { * @param protectionAlgorithm the encryption algorithm name, for * example, {@code PBEWithHmacSHA256AndAES_256}. * See the Cipher section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher"> * Java Cryptography Architecture Standard Algorithm Name * Documentation</a> * for information about standard encryption algorithm names. @@ -868,7 +868,7 @@ public class KeyStore { * * @param type the type of keystore. * See the KeyStore section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyStore"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard keystore types. * @@ -906,7 +906,7 @@ public class KeyStore { * * @param type the type of keystore. * See the KeyStore section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyStore"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard keystore types. * @@ -949,7 +949,7 @@ public class KeyStore { * * @param type the type of keystore. * See the KeyStore section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyStore"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard keystore types. * diff --git a/ojluni/src/main/java/java/security/MessageDigest.java b/ojluni/src/main/java/java/security/MessageDigest.java index 996339e69e..5b9359f0a8 100644 --- a/ojluni/src/main/java/java/security/MessageDigest.java +++ b/ojluni/src/main/java/java/security/MessageDigest.java @@ -120,7 +120,7 @@ import sun.security.jca.Providers; * </table> * * These algorithms are described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest"> * MessageDigest section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -155,7 +155,7 @@ public abstract class MessageDigest extends MessageDigestSpi { * * @param algorithm the standard name of the digest algorithm. * See the MessageDigest section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. */ @@ -178,7 +178,7 @@ public abstract class MessageDigest extends MessageDigestSpi { * * @param algorithm the name of the algorithm requested. * See the MessageDigest section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -232,7 +232,7 @@ public abstract class MessageDigest extends MessageDigestSpi { * * @param algorithm the name of the algorithm requested. * See the MessageDigest section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -283,7 +283,7 @@ public abstract class MessageDigest extends MessageDigestSpi { * * @param algorithm the name of the algorithm requested. * See the MessageDigest section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -511,7 +511,7 @@ public abstract class MessageDigest extends MessageDigestSpi { * implementation details. The name should be a standard * Java Security name (such as "SHA", "MD5", and so on). * See the MessageDigest section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/java/security/Provider.java b/ojluni/src/main/java/java/security/Provider.java index 43bb23f766..9936859ef1 100644 --- a/ojluni/src/main/java/java/security/Provider.java +++ b/ojluni/src/main/java/java/security/Provider.java @@ -57,7 +57,7 @@ import java.util.function.Function; * in each runtime it is installed in. * * <p>See <a href = - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#Provider">The Provider Class</a> + * "../../../technotes/guides/security/crypto/CryptoSpec.html#Provider">The Provider Class</a> * in the "Java Cryptography Architecture API Specification & Reference" * for information about how a particular type of provider, the * cryptographic service provider, works and is installed. However, @@ -1125,7 +1125,7 @@ public abstract class Provider extends Properties { * it is replaced by the new service. * This method also places information about this service * in the provider's Hashtable values in the format described in the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html"> + * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html"> * Java Cryptography Architecture API Specification & Reference </a>. * * <p>Also, if there is a security manager, its @@ -1415,7 +1415,7 @@ public abstract class Provider extends Properties { * suitable services and instantiates them. The valid arguments to those * methods depend on the type of service. For the service types defined * within Java SE, see the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html"> + * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html"> * Java Cryptography Architecture API Specification & Reference </a> * for the valid values. * Note that components outside of Java SE can define additional types of @@ -1591,7 +1591,7 @@ public abstract class Provider extends Properties { * instantiation in a different way. * For details and the values of constructorParameter that are * valid for the various types of services see the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html"> + * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html"> * Java Cryptography Architecture API Specification & * Reference</a>. * @@ -1740,7 +1740,7 @@ public abstract class Provider extends Properties { * * <p>For details and the values of parameter that are valid for the * various types of services see the top of this class and the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html"> + * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html"> * Java Cryptography Architecture API Specification & * Reference</a>. * Security providers can override it to implement their own test. diff --git a/ojluni/src/main/java/java/security/SecureRandom.java b/ojluni/src/main/java/java/security/SecureRandom.java index 4da178d9f9..79e3840bc2 100644 --- a/ojluni/src/main/java/java/security/SecureRandom.java +++ b/ojluni/src/main/java/java/security/SecureRandom.java @@ -151,7 +151,7 @@ public class SecureRandom extends java.util.Random { * the {@link Security#getProviders() Security.getProviders()} method. * * <p> See the SecureRandom section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecureRandom"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard RNG algorithm names. * @@ -189,7 +189,7 @@ public class SecureRandom extends java.util.Random { * the {@link Security#getProviders() Security.getProviders()} method. * * <p> See the SecureRandom section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecureRandom"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard RNG algorithm names. * @@ -278,7 +278,7 @@ public class SecureRandom extends java.util.Random { * * @param algorithm the name of the RNG algorithm. * See the SecureRandom section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecureRandom"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard RNG algorithm names. * @@ -321,7 +321,7 @@ public class SecureRandom extends java.util.Random { * * @param algorithm the name of the RNG algorithm. * See the SecureRandom section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecureRandom"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard RNG algorithm names. * @@ -369,7 +369,7 @@ public class SecureRandom extends java.util.Random { * * @param algorithm the name of the RNG algorithm. * See the SecureRandom section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecureRandom"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard RNG algorithm names. * diff --git a/ojluni/src/main/java/java/security/Security.java b/ojluni/src/main/java/java/security/Security.java index fda137e7ea..bb853a690c 100644 --- a/ojluni/src/main/java/java/security/Security.java +++ b/ojluni/src/main/java/java/security/Security.java @@ -207,7 +207,7 @@ public final class Security { /** * Gets a specified property for an algorithm. The algorithm name * should be a standard name. See the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -443,7 +443,7 @@ public final class Security { * </ul> * * <p> See the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard cryptographic service names, standard * algorithm names and standard attribute names. @@ -514,7 +514,7 @@ public final class Security { * </ul> * * <p> See the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html"> + * "../../../technotes/guides/security/StandardNames.html"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard cryptographic service names, standard * algorithm names and standard attribute names. @@ -1016,7 +1016,7 @@ public final class Security { * an empty Set if there is no provider that supports the * specified service or if serviceName is null. For a complete list * of Java cryptographic services, please see the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html">Java + * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">Java * Cryptography Architecture API Specification & Reference</a>. * Note: the returned set is immutable. * diff --git a/ojluni/src/main/java/java/security/Signature.java b/ojluni/src/main/java/java/security/Signature.java index a09409f7a1..bbe9640ac1 100644 --- a/ojluni/src/main/java/java/security/Signature.java +++ b/ojluni/src/main/java/java/security/Signature.java @@ -238,7 +238,7 @@ import sun.security.jca.GetInstance.Instance; * </table> * * These algorithms are described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Signature section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -298,7 +298,7 @@ public abstract class Signature extends SignatureSpi { * * @param algorithm the standard string name of the algorithm. * See the Signature section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. */ @@ -338,7 +338,7 @@ public abstract class Signature extends SignatureSpi { * * @param algorithm the standard name of the algorithm requested. * See the Signature section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -464,7 +464,7 @@ public abstract class Signature extends SignatureSpi { * * @param algorithm the name of the algorithm requested. * See the Signature section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -516,7 +516,7 @@ public abstract class Signature extends SignatureSpi { * * @param algorithm the name of the algorithm requested. * See the Signature section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/java/security/TEST_MAPPING b/ojluni/src/main/java/java/security/TEST_MAPPING new file mode 100644 index 0000000000..53b281876f --- /dev/null +++ b/ojluni/src/main/java/java/security/TEST_MAPPING @@ -0,0 +1,30 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.javax.security" + }, + { + "include-filter": "org.apache.harmony.security.tests.java.security" + }, + { + "include-filter": "tests.targets.security" + }, + { + "include-filter": "com.android.org.conscrypt.java.security" + }, + { + "include-filter": "tests.java.security" + }, + { + "include-filter": "tests.security" + }, + { + "include-filter": "libcore.java.security" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/security/acl/TEST_MAPPING b/ojluni/src/main/java/java/security/acl/TEST_MAPPING new file mode 100644 index 0000000000..864ca2885c --- /dev/null +++ b/ojluni/src/main/java/java/security/acl/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "tests.security.acl" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/security/cert/CRL.java b/ojluni/src/main/java/java/security/cert/CRL.java index 67ea6ef6cb..f8083c7233 100644 --- a/ojluni/src/main/java/java/security/cert/CRL.java +++ b/ojluni/src/main/java/java/security/cert/CRL.java @@ -53,7 +53,7 @@ public abstract class CRL { * * @param type the standard name of the CRL type. * See Appendix A in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> + * "../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA"> * Java Cryptography Architecture API Specification & Reference </a> * for information about standard CRL types. */ diff --git a/ojluni/src/main/java/java/security/cert/CertPath.java b/ojluni/src/main/java/java/security/cert/CertPath.java index fa88c39ee4..8717f94820 100644 --- a/ojluni/src/main/java/java/security/cert/CertPath.java +++ b/ojluni/src/main/java/java/security/cert/CertPath.java @@ -91,7 +91,7 @@ import java.util.List; * <li>{@code PkiPath}</li> * </ul> * These encodings are described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathEncodings"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathEncodings"> * CertPath Encodings section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * Consult the release documentation for your implementation to see if any diff --git a/ojluni/src/main/java/java/security/cert/CertPathBuilder.java b/ojluni/src/main/java/java/security/cert/CertPathBuilder.java index 2d54292b22..891d86ca9b 100644 --- a/ojluni/src/main/java/java/security/cert/CertPathBuilder.java +++ b/ojluni/src/main/java/java/security/cert/CertPathBuilder.java @@ -83,7 +83,7 @@ import sun.security.jca.GetInstance.Instance; * </table> * * This algorithm is described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathBuilder"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathBuilder"> * CertPathBuilder section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * Consult the release documentation for your implementation to see if any @@ -155,7 +155,7 @@ public class CertPathBuilder { * * @param algorithm the name of the requested {@code CertPathBuilder} * algorithm. See the CertPathBuilder section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathBuilder"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathBuilder"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -190,7 +190,7 @@ public class CertPathBuilder { * * @param algorithm the name of the requested {@code CertPathBuilder} * algorithm. See the CertPathBuilder section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathBuilder"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathBuilder"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -230,7 +230,7 @@ public class CertPathBuilder { * * @param algorithm the name of the requested {@code CertPathBuilder} * algorithm. See the CertPathBuilder section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathBuilder"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathBuilder"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/java/security/cert/CertPathValidator.java b/ojluni/src/main/java/java/security/cert/CertPathValidator.java index bcb3488feb..942c5facd2 100644 --- a/ojluni/src/main/java/java/security/cert/CertPathValidator.java +++ b/ojluni/src/main/java/java/security/cert/CertPathValidator.java @@ -85,7 +85,7 @@ import sun.security.jca.GetInstance.Instance; * </table> * * This algorithm is described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathValidator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator"> * CertPathValidator section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -154,7 +154,7 @@ public class CertPathValidator { * * @param algorithm the name of the requested {@code CertPathValidator} * algorithm. See the CertPathValidator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathValidator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -189,7 +189,7 @@ public class CertPathValidator { * * @param algorithm the name of the requested {@code CertPathValidator} * algorithm. See the CertPathValidator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathValidator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -230,7 +230,7 @@ public class CertPathValidator { * * @param algorithm the name of the requested {@code CertPathValidator} * algorithm. See the CertPathValidator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathValidator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/java/security/cert/CertStore.java b/ojluni/src/main/java/java/security/cert/CertStore.java index 7cfd0d2ced..6eaee5cedc 100644 --- a/ojluni/src/main/java/java/security/cert/CertStore.java +++ b/ojluni/src/main/java/java/security/cert/CertStore.java @@ -77,7 +77,7 @@ import sun.security.jca.GetInstance.Instance; * </table> * * This type is described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertStore"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertStore"> * CertStore section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -212,7 +212,7 @@ public class CertStore { * * @param type the name of the requested {@code CertStore} type. * See the CertStore section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertStore"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertStore"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard types. * @@ -272,7 +272,7 @@ public class CertStore { * * @param type the requested {@code CertStore} type. * See the CertStore section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertStore"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertStore"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard types. * @@ -330,7 +330,7 @@ public class CertStore { * * @param type the requested {@code CertStore} type. * See the CertStore section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertStore"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertStore"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard types. * diff --git a/ojluni/src/main/java/java/security/cert/Certificate.java b/ojluni/src/main/java/java/security/cert/Certificate.java index 4056416262..10544983d2 100644 --- a/ojluni/src/main/java/java/security/cert/Certificate.java +++ b/ojluni/src/main/java/java/security/cert/Certificate.java @@ -74,7 +74,7 @@ public abstract class Certificate implements java.io.Serializable { * * @param type the standard name of the certificate type. * See the CertificateFactory section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertificateFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertificateFactory"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard certificate types. */ diff --git a/ojluni/src/main/java/java/security/cert/CertificateFactory.java b/ojluni/src/main/java/java/security/cert/CertificateFactory.java index e34fddd290..a47b78867b 100644 --- a/ojluni/src/main/java/java/security/cert/CertificateFactory.java +++ b/ojluni/src/main/java/java/security/cert/CertificateFactory.java @@ -127,9 +127,9 @@ import sun.security.jca.GetInstance.Instance; * </table> * * The type and encodings are described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertificateFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertificateFactory"> * CertificateFactory section</a> and the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathEncodings"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathEncodings"> * CertPath Encodings section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -188,7 +188,7 @@ public class CertificateFactory { * * @param type the name of the requested certificate type. * See the CertificateFactory section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertificateFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertificateFactory"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard certificate types. * @@ -226,7 +226,7 @@ public class CertificateFactory { * * @param type the certificate type. * See the CertificateFactory section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertificateFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertificateFactory"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard certificate types. * @@ -272,7 +272,7 @@ public class CertificateFactory { * * @param type the certificate type. * See the CertificateFactory section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertificateFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertificateFactory"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard certificate types. * @param provider the provider. @@ -370,7 +370,7 @@ public class CertificateFactory { * Returns an iteration of the {@code CertPath} encodings supported * by this certificate factory, with the default encoding first. See * the CertPath Encodings section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathEncodings"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathEncodings"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard encoding names and their formats. * <p> @@ -410,7 +410,7 @@ public class CertificateFactory { * the data read from the {@code InputStream} inStream. The data * is assumed to be in the specified encoding. See * the CertPath Encodings section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathEncodings"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathEncodings"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard encoding names and their formats. * diff --git a/ojluni/src/main/java/java/security/cert/CertificateFactorySpi.java b/ojluni/src/main/java/java/security/cert/CertificateFactorySpi.java index 691777d02e..35aee847bb 100644 --- a/ojluni/src/main/java/java/security/cert/CertificateFactorySpi.java +++ b/ojluni/src/main/java/java/security/cert/CertificateFactorySpi.java @@ -183,7 +183,7 @@ public abstract class CertificateFactorySpi { * Returns an iteration of the {@code CertPath} encodings supported * by this certificate factory, with the default encoding first. See * the CertPath Encodings section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathEncodings"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathEncodings"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard encoding names. * <p> diff --git a/ojluni/src/main/java/java/security/cert/TEST_MAPPING b/ojluni/src/main/java/java/security/cert/TEST_MAPPING new file mode 100644 index 0000000000..267b914fac --- /dev/null +++ b/ojluni/src/main/java/java/security/cert/TEST_MAPPING @@ -0,0 +1,29 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "tests.security.cert" + }, + { + "include-filter": "tests.targets.security.cert" + }, + { + "include-filter": "com.android.org.conscrypt.java.security.cert" + }, + { + "include-filter": "libcore.java.security.cert" + } + ] + }, + { + "name": "CtsLibcoreOjTestCases", + "options": [ + { + "include-filter": "test.java.security.cert" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/security/cert/package-info.java b/ojluni/src/main/java/java/security/cert/package-info.java index 4830455a08..58f5fb77e0 100644 --- a/ojluni/src/main/java/java/security/cert/package-info.java +++ b/ojluni/src/main/java/java/security/cert/package-info.java @@ -32,14 +32,14 @@ * <h2>Package Specification</h2> * * <ul> - * <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html"> + * <li><a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html"> * <b>Java™ * Cryptography Architecture (JCA) Reference Guide</b></a> * <li>RFC 5280: Internet X.509 Public Key Infrastructure Certificate and * Certificate Revocation List (CRL) Profile * <li>RFC 2560: X.509 Internet Public Key Infrastructure Online Certificate * Status Protocol - OCSP - * <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html"> + * <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html"> * <b>Java™ * Cryptography Architecture Standard Algorithm Name * Documentation</b></a></li> @@ -52,10 +52,10 @@ * <li><a href="http://www.ietf.org/rfc/rfc5280.txt"> * http://www.ietf.org/rfc/rfc5280.txt</a> * <li><a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/certpath/CertPathProgGuide.html"> + * "{@docRoot}/../technotes/guides/security/certpath/CertPathProgGuide.html"> * <b>Java™ * PKI Programmer's Guide</b></a> - * <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/cert3.html"> + * <li><a href="{@docRoot}/../technotes/guides/security/cert3.html"> * <b>X.509 Certificates and Certificate Revocation Lists (CRLs)</b></a> * </ul> * diff --git a/ojluni/src/main/java/java/security/interfaces/TEST_MAPPING b/ojluni/src/main/java/java/security/interfaces/TEST_MAPPING new file mode 100644 index 0000000000..3c28d5162b --- /dev/null +++ b/ojluni/src/main/java/java/security/interfaces/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "tests.security.interfaces" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/security/interfaces/package-info.java b/ojluni/src/main/java/java/security/interfaces/package-info.java index 8942340927..54c9397e69 100644 --- a/ojluni/src/main/java/java/security/interfaces/package-info.java +++ b/ojluni/src/main/java/java/security/interfaces/package-info.java @@ -43,7 +43,7 @@ * to these cryptographic provider developer guides: * <ul> * <li><a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html"> + * "{@docRoot}/../technotes/guides/security/crypto/HowToImplAProvider.html"> * <b>How to Implement a Provider for the * Java™ Cryptography Architecture * </b></a></li> @@ -63,7 +63,7 @@ * <ul> * <li> * <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html"> + * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html"> * <b>Java™ * Cryptography Architecture API Specification and Reference * </b></a></li> diff --git a/ojluni/src/main/java/java/security/package-info.java b/ojluni/src/main/java/java/security/package-info.java index 60e9b4b5ac..2c8205b09b 100644 --- a/ojluni/src/main/java/java/security/package-info.java +++ b/ojluni/src/main/java/java/security/package-info.java @@ -46,14 +46,14 @@ * <h2>Package Specification</h2> * * <ul> - * <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html"> + * <li><a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html"> * <b>Java™ * Cryptography Architecture (JCA) Reference Guide</b></a></li> * * <li>PKCS #8: Private-Key Information Syntax Standard, Version 1.2, * November 1993</li> * - * <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html"> + * <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html"> * <b>Java™ * Cryptography Architecture Standard Algorithm Name * Documentation</b></a></li> @@ -64,44 +64,44 @@ * For further documentation, please see: * <ul> * <li><a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/spec/security-spec.doc.html"> + * "{@docRoot}/../technotes/guides/security/spec/security-spec.doc.html"> * <b>Java™ * SE Platform Security Architecture</b></a></li> * * <li><a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html"> + * "{@docRoot}/../technotes/guides/security/crypto/HowToImplAProvider.html"> * <b>How to Implement a Provider in the * Java™ Cryptography Architecture * </b></a></li> * * <li><a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/PolicyFiles.html"><b> + * "{@docRoot}/../technotes/guides/security/PolicyFiles.html"><b> * Default Policy Implementation and Policy File Syntax * </b></a></li> * * <li><a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html"><b> + * "{@docRoot}/../technotes/guides/security/permissions.html"><b> * Permissions in the * Java™ SE Development Kit (JDK) * </b></a></li> * * <li><a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/SecurityToolsSummary.html"><b> + * "{@docRoot}/../technotes/guides/security/SecurityToolsSummary.html"><b> * Summary of Tools for * Java™ Platform Security * </b></a></li> * * <li><b>keytool</b> - * (<a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html"> + * (<a href="{@docRoot}/../technotes/tools/unix/keytool.html"> * for Solaris/Linux</a>) - * (<a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html"> + * (<a href="{@docRoot}/../technotes/tools/windows/keytool.html"> * for Windows</a>) * </li> * * <li><b>jarsigner</b> - * (<a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jarsigner.html"> + * (<a href="{@docRoot}/../technotes/tools/unix/jarsigner.html"> * for Solaris/Linux</a>) - * (<a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html"> + * (<a href="{@docRoot}/../technotes/tools/windows/jarsigner.html"> * for Windows</a>) * </li> * diff --git a/ojluni/src/main/java/java/security/spec/TEST_MAPPING b/ojluni/src/main/java/java/security/spec/TEST_MAPPING new file mode 100644 index 0000000000..f54aac609a --- /dev/null +++ b/ojluni/src/main/java/java/security/spec/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.security.spec" + }, + { + "include-filter": "tests.security.spec" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/security/spec/package-info.java b/ojluni/src/main/java/java/security/spec/package-info.java index 68f0b8e26c..cb393088e5 100644 --- a/ojluni/src/main/java/java/security/spec/package-info.java +++ b/ojluni/src/main/java/java/security/spec/package-info.java @@ -56,13 +56,13 @@ * <ul> * <li> * <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html"> + * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html"> * <b>Java™ * Cryptography Architecture API Specification and Reference * </b></a></li> * <li> * <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html"> + * "{@docRoot}/../technotes/guides/security/crypto/HowToImplAProvider.html"> * <b>How to Implement a Provider for the * Java™ Cryptography Architecture * </b></a></li> diff --git a/ojluni/src/main/java/java/sql/DriverManager.java b/ojluni/src/main/java/java/sql/DriverManager.java index 2fc6acc324..08755b0e08 100644 --- a/ojluni/src/main/java/java/sql/DriverManager.java +++ b/ojluni/src/main/java/java/sql/DriverManager.java @@ -53,7 +53,7 @@ import sun.reflect.Reflection; * </pre> *<P> The <code>DriverManager</code> methods <code>getConnection</code> and * <code>getDrivers</code> have been enhanced to support the Java Standard Edition - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Service%20Provider">Service Provider</a> mechanism. JDBC 4.0 Drivers must + * <a href="../../../technotes/guides/jar/jar.html#Service%20Provider">Service Provider</a> mechanism. JDBC 4.0 Drivers must * include the file <code>META-INF/services/java.sql.Driver</code>. This file contains the name of the JDBC drivers * implementation of <code>java.sql.Driver</code>. For example, to load the <code>my.sql.Driver</code> class, * the <code>META-INF/services/java.sql.Driver</code> file would contain the entry: diff --git a/ojluni/src/main/java/java/sql/TEST_MAPPING b/ojluni/src/main/java/java/sql/TEST_MAPPING new file mode 100644 index 0000000000..28cf3b3bef --- /dev/null +++ b/ojluni/src/main/java/java/sql/TEST_MAPPING @@ -0,0 +1,18 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.sql.tests.java.sql" + }, + { + "include-filter": "tests.java.sql" + }, + { + "include-filter": "libcore.java.sql" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/sql/package.html b/ojluni/src/main/java/java/sql/package.html index 74d6225697..65d906b9a6 100644 --- a/ojluni/src/main/java/java/sql/package.html +++ b/ojluni/src/main/java/java/sql/package.html @@ -310,7 +310,7 @@ object back to its SQL type to store it in the data source. <h2>Related Documentation</h2> <ul> - <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/getstart/GettingStartedTOC.fm.html">Getting Started</a>--overviews of the major interfaces + <li><a href="../../../technotes/guides/jdbc/getstart/GettingStartedTOC.fm.html">Getting Started</a>--overviews of the major interfaces <P> <li><a href="http://java.sun.com/docs/books/tutorial/jdbc">Chapters on the JDBC API</a>--from the online version of <i>The Java Tutorial Continued</i> diff --git a/ojluni/src/main/java/java/text/Collator.java b/ojluni/src/main/java/java/text/Collator.java index ca3a220d06..e7fc8b78b7 100644 --- a/ojluni/src/main/java/java/text/Collator.java +++ b/ojluni/src/main/java/java/text/Collator.java @@ -226,14 +226,16 @@ public abstract class Collator * @see java.util.Locale * @see java.util.ResourceBundle */ - // Android-changed: Switched to ICU. - public static synchronized Collator getInstance(Locale desiredLocale) - { - if (desiredLocale == null) { - throw new NullPointerException("locale == null"); + public static Collator getInstance(Locale desiredLocale) { + // BEGIN Android-changed: Switched to ICU. + synchronized(Collator.class) { + if (desiredLocale == null) { + throw new NullPointerException("locale == null"); + } + return new RuleBasedCollator((android.icu.text.RuleBasedCollator) + android.icu.text.Collator.getInstance(desiredLocale)); } - return new RuleBasedCollator((android.icu.text.RuleBasedCollator) - android.icu.text.Collator.getInstance(desiredLocale)); + // END Android-changed: Switched to ICU. } /** @@ -386,7 +388,7 @@ public abstract class Collator icuColl.setDecomposition(decompositionMode_Java_ICU(decompositionMode)); } - // Android-changed: Removed references to CollatorProvider. + // Android-changed: Removed javadoc references to CollatorProvider. /** * Returns an array of all locales for which the * <code>getInstance</code> methods of this class can return @@ -397,7 +399,7 @@ public abstract class Collator */ public static synchronized Locale[] getAvailableLocales() { // Android-changed: Removed reference to CollatorProvider. Switched to ICU. - return ICU.getAvailableCollatorLocales(); + return android.icu.text.Collator.getAvailableLocales(); } // BEGIN Android-added: conversion method for decompositionMode constants. @@ -425,7 +427,7 @@ public abstract class Collator } // END Android-added: conversion method for decompositionMode constants. - // Android-changed: improve documentation. + // Android-changed: improve clone() documentation. /** * Returns a new collator with the same decomposition mode and * strength value as this collator. diff --git a/ojluni/src/main/java/java/text/DateFormatSymbols.java b/ojluni/src/main/java/java/text/DateFormatSymbols.java index 97dc528e51..5216928dc8 100644 --- a/ojluni/src/main/java/java/text/DateFormatSymbols.java +++ b/ojluni/src/main/java/java/text/DateFormatSymbols.java @@ -421,25 +421,27 @@ public class DateFormatSymbols implements Serializable, Cloneable { // BEGIN Android-changed: Replace getProviderInstance() with getCachedInstance(). // Android removed support for DateFormatSymbolsProviders, but still caches DFS. + // App compat change for b/159514442. /** * Returns a cached DateFormatSymbols if it's found in the * cache. Otherwise, this method returns a newly cached instance * for the given locale. */ private static DateFormatSymbols getCachedInstance(Locale locale) { - SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale); + Locale cacheKey = LocaleData.getCompatibleLocaleForBug159514442(locale); + SoftReference<DateFormatSymbols> ref = cachedInstances.get(cacheKey); DateFormatSymbols dfs; if (ref == null || (dfs = ref.get()) == null) { dfs = new DateFormatSymbols(locale); ref = new SoftReference<>(dfs); - SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref); + SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(cacheKey, ref); if (x != null) { DateFormatSymbols y = x.get(); if (y != null) { dfs = y; } else { // Replace the empty SoftReference with ref. - cachedInstances.put(locale, ref); + cachedInstances.put(cacheKey, ref); } } } @@ -818,7 +820,9 @@ public class DateFormatSymbols implements Serializable, Cloneable { * appropriate LocaleData object. Note: zoneStrings isn't initialized in this method. */ private void initializeData(Locale locale) { - SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale); + // Android-changed: App compat change for b/159514442. + Locale cacheKey = LocaleData.getCompatibleLocaleForBug159514442(locale); + SoftReference<DateFormatSymbols> ref = cachedInstances.get(cacheKey); DateFormatSymbols dfs; // Android-changed: invert cache presence check to simplify code flow. if (ref != null && (dfs = ref.get()) != null) { diff --git a/ojluni/src/main/java/java/text/DecimalFormat.java b/ojluni/src/main/java/java/text/DecimalFormat.java index d62cb27d98..a2a37b1ca3 100644 --- a/ojluni/src/main/java/java/text/DecimalFormat.java +++ b/ojluni/src/main/java/java/text/DecimalFormat.java @@ -39,6 +39,7 @@ package java.text; +import android.icu.impl.number.DecimalFormatProperties.ParseMode; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -52,7 +53,6 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import libcore.icu.LocaleData; - import android.icu.math.MathContext; /** @@ -385,8 +385,7 @@ public class DecimalFormat extends NumberFormat { // to implement DecimalFormat. // Android-added: ICU DecimalFormat to delegate to. - // TODO(b/68143370): switch back to ICU DecimalFormat once it can reproduce ICU 58 behavior. - private transient android.icu.text.DecimalFormat_ICU58_Android icuDecimalFormat; + private transient android.icu.text.DecimalFormat icuDecimalFormat; /** * Creates a DecimalFormat using the default pattern and symbols @@ -488,8 +487,10 @@ public class DecimalFormat extends NumberFormat { * {@link #icuDecimalFormat} in the process. This should only be called from constructors. */ private void initPattern(String pattern) { - this.icuDecimalFormat = new android.icu.text.DecimalFormat_ICU58_Android(pattern, + this.icuDecimalFormat = new android.icu.text.DecimalFormat(pattern, symbols.getIcuDecimalFormatSymbols()); + // Android-changed: Compatibility mode for j.t.DecimalFormat. http://b/112355520 + icuDecimalFormat.setParseStrictMode(ParseMode.JAVA_COMPATIBILITY); updateFieldsFromIcu(); } @@ -3083,7 +3084,7 @@ public class DecimalFormat extends NumberFormat { */ try { DecimalFormat other = (DecimalFormat) super.clone(); - other.icuDecimalFormat = (android.icu.text.DecimalFormat_ICU58_Android) icuDecimalFormat.clone(); + other.icuDecimalFormat = (android.icu.text.DecimalFormat) icuDecimalFormat.clone(); other.symbols = (DecimalFormatSymbols) symbols.clone(); return other; } catch (Exception e) { @@ -3149,7 +3150,7 @@ public class DecimalFormat extends NumberFormat { && compareIcuRoundingIncrement(other.icuDecimalFormat); } - private boolean compareIcuRoundingIncrement(android.icu.text.DecimalFormat_ICU58_Android other) { + private boolean compareIcuRoundingIncrement(android.icu.text.DecimalFormat other) { BigDecimal increment = this.icuDecimalFormat.getRoundingIncrement(); if (increment != null) { return (other.getRoundingIncrement() != null) diff --git a/ojluni/src/main/java/java/text/DecimalFormatSymbols.java b/ojluni/src/main/java/java/text/DecimalFormatSymbols.java index 6686d8baeb..a65a079809 100644 --- a/ojluni/src/main/java/java/text/DecimalFormatSymbols.java +++ b/ojluni/src/main/java/java/text/DecimalFormatSymbols.java @@ -792,6 +792,15 @@ public class DecimalFormatSymbols implements Cloneable, Serializable { cachedIcuDFS.setInfinity(infinity); cachedIcuDFS.setNaN(NaN); cachedIcuDFS.setExponentSeparator(exponentialSeparator); + // j.t.DecimalFormatSymbols doesn't insert whitespace before/after currency by default. + // Override ICU default value to retain historic Android behavior. + // http://b/112127077 + cachedIcuDFS.setPatternForCurrencySpacing( + android.icu.text.DecimalFormatSymbols.CURRENCY_SPC_INSERT, + false /* beforeCurrency */, ""); + cachedIcuDFS.setPatternForCurrencySpacing( + android.icu.text.DecimalFormatSymbols.CURRENCY_SPC_INSERT, + true /* beforeCurrency */, ""); try { cachedIcuDFS.setCurrency( diff --git a/ojluni/src/main/java/java/text/SimpleDateFormat.java b/ojluni/src/main/java/java/text/SimpleDateFormat.java index 0f6321a2b1..ca5a50405d 100644 --- a/ojluni/src/main/java/java/text/SimpleDateFormat.java +++ b/ojluni/src/main/java/java/text/SimpleDateFormat.java @@ -56,8 +56,10 @@ import java.util.GregorianCalendar; import java.util.HashSet; import java.util.Locale; import java.util.Map; +import java.util.NavigableMap; import java.util.Set; import java.util.SimpleTimeZone; +import java.util.SortedMap; import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -1911,12 +1913,16 @@ public class SimpleDateFormat extends DateFormat { private int matchString(String text, int start, int field, Map<String,Integer> data, CalendarBuilder calb) { if (data != null) { - // BEGIN Android-removed: SortedMap instance lookup optimization in matchString(). + // TODO: make this default when it's in the spec. + // BEGIN Android-changed: SortedMap instance lookup optimization in matchString(). // RI returns not the longest match as matchString(String[]) does. http://b/119913354 /* - // TODO: make this default when it's in the spec. if (data instanceof SortedMap) { for (String name : data.keySet()) { + */ + if (data instanceof NavigableMap && ((NavigableMap) data).comparator() == null) { + for (String name : ((NavigableMap<String, Integer>) data).descendingKeySet()) { + // END Android-changed: SortedMap instance lookup optimization in matchString(). if (text.regionMatches(true, start, name, 0, name.length())) { calb.set(field, data.get(name)); return start + name.length(); @@ -1924,8 +1930,6 @@ public class SimpleDateFormat extends DateFormat { } return -start; } - */ - // END Android-removed: SortedMap instance lookup optimization in matchString(). String bestMatch = null; diff --git a/ojluni/src/main/java/java/text/TEST_MAPPING b/ojluni/src/main/java/java/text/TEST_MAPPING new file mode 100644 index 0000000000..30747b2d1f --- /dev/null +++ b/ojluni/src/main/java/java/text/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.java.text" + }, + { + "include-filter": "libcore.java.text" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/time/TEST_MAPPING b/ojluni/src/main/java/java/time/TEST_MAPPING new file mode 100644 index 0000000000..5b24483bf2 --- /dev/null +++ b/ojluni/src/main/java/java/time/TEST_MAPPING @@ -0,0 +1,26 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.time" + } + ] + }, + { + "name": "CtsLibcoreOjTestCases", + "options": [ + { + "include-filter": "tck.java.time" + }, + { + "include-filter": "tck.java.time.serial" + }, + { + "include-filter": "test.java.time" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/time/chrono/JapaneseChronology.java b/ojluni/src/main/java/java/time/chrono/JapaneseChronology.java index 29e503ec81..034a3bc87c 100644 --- a/ojluni/src/main/java/java/time/chrono/JapaneseChronology.java +++ b/ojluni/src/main/java/java/time/chrono/JapaneseChronology.java @@ -368,12 +368,12 @@ public final class JapaneseChronology extends AbstractChronology implements Seri throw new DateTimeException("Invalid yearOfEra value"); } + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. /** * Returns the calendar system era object from the given numeric value. * - * See the description of each Era for the numeric values of: - * {@link JapaneseEra#HEISEI}, {@link JapaneseEra#SHOWA},{@link JapaneseEra#TAISHO}, - * {@link JapaneseEra#MEIJI}), only Meiji and later eras are supported. + * The numeric values supported by this method are the same as the + * numeric values supported by {@link JapaneseEra#of(int)}. * * @param eraValue the era value * @return the Japanese {@code Era} for the given numeric era value diff --git a/ojluni/src/main/java/java/time/chrono/JapaneseEra.java b/ojluni/src/main/java/java/time/chrono/JapaneseEra.java index d52f3c19c9..81805d0c51 100644 --- a/ojluni/src/main/java/java/time/chrono/JapaneseEra.java +++ b/ojluni/src/main/java/java/time/chrono/JapaneseEra.java @@ -150,12 +150,13 @@ public final class JapaneseEra * which has the value 2. */ public static final JapaneseEra HEISEI = new JapaneseEra(2, LocalDate.of(1989, 1, 8)); + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. /** * The singleton instance for the 'Reiwa' era (2019-05-01 - current) * which has the value 3. The end date of this era is not specified, unless * the Japanese Government defines it. */ - private static final JapaneseEra REIWA = new JapaneseEra(3, LocalDate.of(2019, 5, 1)); + public static final JapaneseEra REIWA = new JapaneseEra(3, LocalDate.of(2019, 5, 1)); // The number of predefined JapaneseEra constants. // There may be a supplemental era defined by the property. diff --git a/ojluni/src/main/java/java/time/chrono/TEST_MAPPING b/ojluni/src/main/java/java/time/chrono/TEST_MAPPING new file mode 100644 index 0000000000..461c15d4d5 --- /dev/null +++ b/ojluni/src/main/java/java/time/chrono/TEST_MAPPING @@ -0,0 +1,26 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.time.chrono" + } + ] + }, + { + "name": "CtsLibcoreOjTestCases", + "options": [ + { + "include-filter": "tck.java.time.chrono.serial" + }, + { + "include-filter": "tck.java.time.chrono" + }, + { + "include-filter": "test.java.time.chrono" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/time/format/TEST_MAPPING b/ojluni/src/main/java/java/time/format/TEST_MAPPING new file mode 100644 index 0000000000..42286e4466 --- /dev/null +++ b/ojluni/src/main/java/java/time/format/TEST_MAPPING @@ -0,0 +1,23 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.time.format" + } + ] + }, + { + "name": "CtsLibcoreOjTestCases", + "options": [ + { + "include-filter": "tck.java.time.format" + }, + { + "include-filter": "test.java.time.format" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/time/temporal/TEST_MAPPING b/ojluni/src/main/java/java/time/temporal/TEST_MAPPING new file mode 100644 index 0000000000..deac48a237 --- /dev/null +++ b/ojluni/src/main/java/java/time/temporal/TEST_MAPPING @@ -0,0 +1,26 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.time.temporal" + } + ] + }, + { + "name": "CtsLibcoreOjTestCases", + "options": [ + { + "include-filter": "test.java.time.temporal" + }, + { + "include-filter": "tck.java.time.temporal" + }, + { + "include-filter": "tck.java.time.temporal.serial" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/time/zone/TEST_MAPPING b/ojluni/src/main/java/java/time/zone/TEST_MAPPING new file mode 100644 index 0000000000..1c8c89e125 --- /dev/null +++ b/ojluni/src/main/java/java/time/zone/TEST_MAPPING @@ -0,0 +1,26 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.time.zone" + } + ] + }, + { + "name": "CtsLibcoreOjTestCases", + "options": [ + { + "include-filter": "tck.java.time.zone" + }, + { + "include-filter": "tck.java.time.zone.serial" + }, + { + "include-filter": "test.java.time.zone" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/util/AbstractCollection.java b/ojluni/src/main/java/java/util/AbstractCollection.java index 19c15f8814..1f7cdd9e09 100644 --- a/ojluni/src/main/java/java/util/AbstractCollection.java +++ b/ojluni/src/main/java/java/util/AbstractCollection.java @@ -49,7 +49,7 @@ package java.util; * the collection being implemented admits a more efficient implementation.<p> * * This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch diff --git a/ojluni/src/main/java/java/util/AbstractList.java b/ojluni/src/main/java/java/util/AbstractList.java index a156ec664e..c8c160de6a 100644 --- a/ojluni/src/main/java/java/util/AbstractList.java +++ b/ojluni/src/main/java/java/util/AbstractList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package java.util; +import java.util.function.Consumer; + /** * This class provides a skeletal implementation of the {@link List} * interface to minimize the effort required to implement this interface @@ -60,7 +62,7 @@ package java.util; * collection being implemented admits a more efficient implementation. * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch @@ -87,7 +89,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L * classes should clearly specify in their documentation any restrictions * on what elements may be added. * - * <p>This implementation calls {@code add(size(), e)}. + * @implSpec + * This implementation calls {@code add(size(), e)}. * * <p>Note that this implementation throws an * {@code UnsupportedOperationException} unless @@ -114,12 +117,13 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L * * @throws IndexOutOfBoundsException {@inheritDoc} */ - abstract public E get(int index); + public abstract E get(int index); /** * {@inheritDoc} * - * <p>This implementation always throws an + * @implSpec + * This implementation always throws an * {@code UnsupportedOperationException}. * * @throws UnsupportedOperationException {@inheritDoc} @@ -135,7 +139,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L /** * {@inheritDoc} * - * <p>This implementation always throws an + * @implSpec + * This implementation always throws an * {@code UnsupportedOperationException}. * * @throws UnsupportedOperationException {@inheritDoc} @@ -151,7 +156,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L /** * {@inheritDoc} * - * <p>This implementation always throws an + * @implSpec + * This implementation always throws an * {@code UnsupportedOperationException}. * * @throws UnsupportedOperationException {@inheritDoc} @@ -167,7 +173,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L /** * {@inheritDoc} * - * <p>This implementation first gets a list iterator (with + * @implSpec + * This implementation first gets a list iterator (with * {@code listIterator()}). Then, it iterates over the list until the * specified element is found or the end of the list is reached. * @@ -191,7 +198,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L /** * {@inheritDoc} * - * <p>This implementation first gets a list iterator that points to the end + * @implSpec + * This implementation first gets a list iterator that points to the end * of the list (with {@code listIterator(size())}). Then, it iterates * backwards over the list until the specified element is found, or the * beginning of the list is reached. @@ -220,7 +228,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L * Removes all of the elements from this list (optional operation). * The list will be empty after this call returns. * - * <p>This implementation calls {@code removeRange(0, size())}. + * @implSpec + * This implementation calls {@code removeRange(0, size())}. * * <p>Note that this implementation throws an * {@code UnsupportedOperationException} unless {@code remove(int @@ -237,7 +246,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L /** * {@inheritDoc} * - * <p>This implementation gets an iterator over the specified collection + * @implSpec + * This implementation gets an iterator over the specified collection * and iterates over it, inserting the elements obtained from the * iterator into this list at the appropriate position, one at a time, * using {@code add(int, E)}. @@ -269,7 +279,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L /** * Returns an iterator over the elements in this list in proper sequence. * - * <p>This implementation returns a straightforward implementation of the + * @implSpec + * This implementation returns a straightforward implementation of the * iterator interface, relying on the backing list's {@code size()}, * {@code get(int)}, and {@code remove(int)} methods. * @@ -291,7 +302,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L /** * {@inheritDoc} * - * <p>This implementation returns {@code listIterator(0)}. + * @implSpec + * This implementation returns {@code listIterator(0)}. * * @see #listIterator(int) */ @@ -302,7 +314,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L /** * {@inheritDoc} * - * <p>This implementation returns a straightforward implementation of the + * @implSpec + * This implementation returns a straightforward implementation of the * {@code ListIterator} interface that extends the implementation of the * {@code Iterator} interface returned by the {@code iterator()} method. * The {@code ListIterator} implementation relies on the backing list's @@ -448,12 +461,12 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L /** * {@inheritDoc} * - * <p>This implementation returns a list that subclasses + * @implSpec + * This implementation returns a list that subclasses * {@code AbstractList}. The subclass stores, in private fields, the - * offset of the subList within the backing list, the size of the subList - * (which can change over its lifetime), and the expected - * {@code modCount} value of the backing list. There are two variants - * of the subclass, one of which implements {@code RandomAccess}. + * size of the subList (which can change over its lifetime), and the + * expected {@code modCount} value of the backing list. There are two + * variants of the subclass, one of which implements {@code RandomAccess}. * If this list implements {@code RandomAccess} the returned list will * be an instance of the subclass that implements {@code RandomAccess}. * @@ -481,11 +494,22 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L * {@code (fromIndex > toIndex)} */ public List<E> subList(int fromIndex, int toIndex) { + subListRangeCheck(fromIndex, toIndex, size()); return (this instanceof RandomAccess ? new RandomAccessSubList<>(this, fromIndex, toIndex) : new SubList<>(this, fromIndex, toIndex)); } + static void subListRangeCheck(int fromIndex, int toIndex, int size) { + if (fromIndex < 0) + throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); + if (toIndex > size) + throw new IndexOutOfBoundsException("toIndex = " + toIndex); + if (fromIndex > toIndex) + throw new IllegalArgumentException("fromIndex(" + fromIndex + + ") > toIndex(" + toIndex + ")"); + } + // Comparison and hashing /** @@ -495,8 +519,9 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L * the two lists are <i>equal</i>. (Two elements {@code e1} and * {@code e2} are <i>equal</i> if {@code (e1==null ? e2==null : * e1.equals(e2))}.) In other words, two lists are defined to be - * equal if they contain the same elements in the same order.<p> + * equal if they contain the same elements in the same order. * + * @implSpec * This implementation first checks if the specified object is this * list. If so, it returns {@code true}; if not, it checks if the * specified object is a list. If not, it returns {@code false}; if so, @@ -529,7 +554,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L /** * Returns the hash code value for this list. * - * <p>This implementation uses exactly the code that is used to define the + * @implSpec + * This implementation uses exactly the code that is used to define the * list hash function in the documentation for the {@link List#hashCode} * method. * @@ -555,7 +581,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L * improve the performance of the {@code clear} operation on this list * and its subLists. * - * <p>This implementation gets a list iterator positioned before + * @implSpec + * This implementation gets a list iterator positioned before * {@code fromIndex}, and repeatedly calls {@code ListIterator.next} * followed by {@code ListIterator.remove} until the entire range has * been removed. <b>Note: if {@code ListIterator.remove} requires linear @@ -608,174 +635,308 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+size(); } -} -class SubList<E> extends AbstractList<E> { - private final AbstractList<E> l; - private final int offset; - private int size; + /** + * An index-based split-by-two, lazily initialized Spliterator covering + * a List that access elements via {@link List#get}. + * + * If access results in an IndexOutOfBoundsException then a + * ConcurrentModificationException is thrown instead (since the list has + * been structurally modified while traversing). + * + * If the List is an instance of AbstractList then concurrent modification + * checking is performed using the AbstractList's modCount field. + */ + static final class RandomAccessSpliterator<E> implements Spliterator<E> { - SubList(AbstractList<E> list, int fromIndex, int toIndex) { - if (fromIndex < 0) - throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); - if (toIndex > list.size()) - throw new IndexOutOfBoundsException("toIndex = " + toIndex); - if (fromIndex > toIndex) - throw new IllegalArgumentException("fromIndex(" + fromIndex + - ") > toIndex(" + toIndex + ")"); - l = list; - offset = fromIndex; - size = toIndex - fromIndex; - this.modCount = l.modCount; - } + private final List<E> list; + private int index; // current index, modified on advance/split + private int fence; // -1 until used; then one past last index - public E set(int index, E element) { - rangeCheck(index); - checkForComodification(); - return l.set(index+offset, element); - } + // The following fields are valid if covering an AbstractList + private final AbstractList<E> alist; + private int expectedModCount; // initialized when fence set - public E get(int index) { - rangeCheck(index); - checkForComodification(); - return l.get(index+offset); - } + RandomAccessSpliterator(List<E> list) { + assert list instanceof RandomAccess; - public int size() { - checkForComodification(); - return size; - } + this.list = list; + this.index = 0; + this.fence = -1; - public void add(int index, E element) { - rangeCheckForAdd(index); - checkForComodification(); - l.add(index+offset, element); - this.modCount = l.modCount; - size++; - } + this.alist = list instanceof AbstractList ? (AbstractList<E>) list : null; + this.expectedModCount = alist != null ? alist.modCount : 0; + } - public E remove(int index) { - rangeCheck(index); - checkForComodification(); - E result = l.remove(index+offset); - this.modCount = l.modCount; - size--; - return result; - } + /** Create new spliterator covering the given range */ + private RandomAccessSpliterator(RandomAccessSpliterator<E> parent, + int origin, int fence) { + this.list = parent.list; + this.index = origin; + this.fence = fence; - protected void removeRange(int fromIndex, int toIndex) { - checkForComodification(); - l.removeRange(fromIndex+offset, toIndex+offset); - this.modCount = l.modCount; - size -= (toIndex-fromIndex); - } + this.alist = parent.alist; + this.expectedModCount = parent.expectedModCount; + } - public boolean addAll(Collection<? extends E> c) { - return addAll(size, c); - } + private int getFence() { // initialize fence to size on first use + int hi; + List<E> lst = list; + if ((hi = fence) < 0) { + if (alist != null) { + expectedModCount = alist.modCount; + } + hi = fence = lst.size(); + } + return hi; + } - public boolean addAll(int index, Collection<? extends E> c) { - rangeCheckForAdd(index); - int cSize = c.size(); - if (cSize==0) - return false; + public Spliterator<E> trySplit() { + int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; + return (lo >= mid) ? null : // divide range in half unless too small + new RandomAccessSpliterator<>(this, lo, index = mid); + } - checkForComodification(); - l.addAll(offset+index, c); - this.modCount = l.modCount; - size += cSize; - return true; - } + public boolean tryAdvance(Consumer<? super E> action) { + if (action == null) + throw new NullPointerException(); + int hi = getFence(), i = index; + if (i < hi) { + index = i + 1; + action.accept(get(list, i)); + checkAbstractListModCount(alist, expectedModCount); + return true; + } + return false; + } - public Iterator<E> iterator() { - return listIterator(); - } + public void forEachRemaining(Consumer<? super E> action) { + Objects.requireNonNull(action); + List<E> lst = list; + int hi = getFence(); + int i = index; + index = hi; + for (; i < hi; i++) { + action.accept(get(lst, i)); + } + checkAbstractListModCount(alist, expectedModCount); + } - public ListIterator<E> listIterator(final int index) { - checkForComodification(); - rangeCheckForAdd(index); + public long estimateSize() { + return (long) (getFence() - index); + } - return new ListIterator<E>() { - private final ListIterator<E> i = l.listIterator(index+offset); + public int characteristics() { + return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED; + } - public boolean hasNext() { - return nextIndex() < size; + private static <E> E get(List<E> list, int i) { + try { + return list.get(i); + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); } + } - public E next() { - if (hasNext()) - return i.next(); - else - throw new NoSuchElementException(); + static void checkAbstractListModCount(AbstractList<?> alist, int expectedModCount) { + if (alist != null && alist.modCount != expectedModCount) { + throw new ConcurrentModificationException(); } + } + } - public boolean hasPrevious() { - return previousIndex() >= 0; - } + private static class SubList<E> extends AbstractList<E> { + private final AbstractList<E> root; + private final SubList<E> parent; + private final int offset; + protected int size; - public E previous() { - if (hasPrevious()) - return i.previous(); - else - throw new NoSuchElementException(); - } + /** + * Constructs a sublist of an arbitrary AbstractList, which is + * not a SubList itself. + */ + public SubList(AbstractList<E> root, int fromIndex, int toIndex) { + this.root = root; + this.parent = null; + this.offset = fromIndex; + this.size = toIndex - fromIndex; + this.modCount = root.modCount; + } - public int nextIndex() { - return i.nextIndex() - offset; - } + /** + * Constructs a sublist of another SubList. + */ + protected SubList(SubList<E> parent, int fromIndex, int toIndex) { + this.root = parent.root; + this.parent = parent; + this.offset = parent.offset + fromIndex; + this.size = toIndex - fromIndex; + this.modCount = root.modCount; + } - public int previousIndex() { - return i.previousIndex() - offset; - } + public E set(int index, E element) { + Objects.checkIndex(index, size); + checkForComodification(); + return root.set(offset + index, element); + } - public void remove() { - i.remove(); - SubList.this.modCount = l.modCount; - size--; - } + public E get(int index) { + Objects.checkIndex(index, size); + checkForComodification(); + return root.get(offset + index); + } - public void set(E e) { - i.set(e); - } + public int size() { + checkForComodification(); + return size; + } - public void add(E e) { - i.add(e); - SubList.this.modCount = l.modCount; - size++; - } - }; - } + public void add(int index, E element) { + rangeCheckForAdd(index); + checkForComodification(); + root.add(offset + index, element); + updateSizeAndModCount(1); + } - public List<E> subList(int fromIndex, int toIndex) { - return new SubList<>(this, fromIndex, toIndex); - } + public E remove(int index) { + Objects.checkIndex(index, size); + checkForComodification(); + E result = root.remove(offset + index); + updateSizeAndModCount(-1); + return result; + } - private void rangeCheck(int index) { - if (index < 0 || index >= size) - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } + protected void removeRange(int fromIndex, int toIndex) { + checkForComodification(); + root.removeRange(offset + fromIndex, offset + toIndex); + updateSizeAndModCount(fromIndex - toIndex); + } - private void rangeCheckForAdd(int index) { - if (index < 0 || index > size) - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } + public boolean addAll(Collection<? extends E> c) { + return addAll(size, c); + } - private String outOfBoundsMsg(int index) { - return "Index: "+index+", Size: "+size; - } + public boolean addAll(int index, Collection<? extends E> c) { + rangeCheckForAdd(index); + int cSize = c.size(); + if (cSize==0) + return false; + checkForComodification(); + root.addAll(offset + index, c); + updateSizeAndModCount(cSize); + return true; + } - private void checkForComodification() { - if (this.modCount != l.modCount) - throw new ConcurrentModificationException(); - } -} + public Iterator<E> iterator() { + return listIterator(); + } + + public ListIterator<E> listIterator(int index) { + checkForComodification(); + rangeCheckForAdd(index); + + return new ListIterator<E>() { + private final ListIterator<E> i = + root.listIterator(offset + index); + + public boolean hasNext() { + return nextIndex() < size; + } + + public E next() { + if (hasNext()) + return i.next(); + else + throw new NoSuchElementException(); + } + + public boolean hasPrevious() { + return previousIndex() >= 0; + } + + public E previous() { + if (hasPrevious()) + return i.previous(); + else + throw new NoSuchElementException(); + } + + public int nextIndex() { + return i.nextIndex() - offset; + } + + public int previousIndex() { + return i.previousIndex() - offset; + } + + public void remove() { + i.remove(); + updateSizeAndModCount(-1); + } + + public void set(E e) { + i.set(e); + } + + public void add(E e) { + i.add(e); + updateSizeAndModCount(1); + } + }; + } + + public List<E> subList(int fromIndex, int toIndex) { + subListRangeCheck(fromIndex, toIndex, size); + return new SubList<>(this, fromIndex, toIndex); + } + + private void rangeCheckForAdd(int index) { + if (index < 0 || index > size) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + private String outOfBoundsMsg(int index) { + return "Index: "+index+", Size: "+size; + } + + private void checkForComodification() { + if (root.modCount != this.modCount) + throw new ConcurrentModificationException(); + } -class RandomAccessSubList<E> extends SubList<E> implements RandomAccess { - RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) { - super(list, fromIndex, toIndex); + private void updateSizeAndModCount(int sizeChange) { + SubList<E> slist = this; + do { + slist.size += sizeChange; + slist.modCount = root.modCount; + slist = slist.parent; + } while (slist != null); + } } - public List<E> subList(int fromIndex, int toIndex) { - return new RandomAccessSubList<>(this, fromIndex, toIndex); + private static class RandomAccessSubList<E> + extends SubList<E> implements RandomAccess { + + /** + * Constructs a sublist of an arbitrary AbstractList, which is + * not a RandomAccessSubList itself. + */ + RandomAccessSubList(AbstractList<E> root, + int fromIndex, int toIndex) { + super(root, fromIndex, toIndex); + } + + /** + * Constructs a sublist of another RandomAccessSubList. + */ + RandomAccessSubList(RandomAccessSubList<E> parent, + int fromIndex, int toIndex) { + super(parent, fromIndex, toIndex); + } + + public List<E> subList(int fromIndex, int toIndex) { + subListRangeCheck(fromIndex, toIndex, size); + return new RandomAccessSubList<>(this, fromIndex, toIndex); + } } } diff --git a/ojluni/src/main/java/java/util/AbstractMap.java b/ojluni/src/main/java/java/util/AbstractMap.java index 09c2f949e8..948bf519a0 100644 --- a/ojluni/src/main/java/java/util/AbstractMap.java +++ b/ojluni/src/main/java/java/util/AbstractMap.java @@ -52,7 +52,7 @@ import java.util.Map.Entry; * map being implemented admits a more efficient implementation. * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <K> the type of keys maintained by this map diff --git a/ojluni/src/main/java/java/util/AbstractSequentialList.java b/ojluni/src/main/java/java/util/AbstractSequentialList.java index 37292dfaa8..36a91dabaa 100644 --- a/ojluni/src/main/java/java/util/AbstractSequentialList.java +++ b/ojluni/src/main/java/java/util/AbstractSequentialList.java @@ -54,7 +54,7 @@ package java.util; * specification.<p> * * This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch diff --git a/ojluni/src/main/java/java/util/AbstractSet.java b/ojluni/src/main/java/java/util/AbstractSet.java index 620f672194..b3fe0dc0bf 100644 --- a/ojluni/src/main/java/java/util/AbstractSet.java +++ b/ojluni/src/main/java/java/util/AbstractSet.java @@ -42,7 +42,7 @@ package java.util; * for <tt>equals</tt> and <tt>hashCode</tt>.<p> * * This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <E> the type of elements maintained by this set diff --git a/ojluni/src/main/java/java/util/ArrayList.java b/ojluni/src/main/java/java/util/ArrayList.java index 02f947919c..20c623ae74 100644 --- a/ojluni/src/main/java/java/util/ArrayList.java +++ b/ojluni/src/main/java/java/util/ArrayList.java @@ -92,7 +92,7 @@ import java.util.function.UnaryOperator; * should be used only to detect bugs.</i> * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch diff --git a/ojluni/src/main/java/java/util/Arrays.java b/ojluni/src/main/java/java/util/Arrays.java index 3f7b1bca45..6da3e5d30e 100644 --- a/ojluni/src/main/java/java/util/Arrays.java +++ b/ojluni/src/main/java/java/util/Arrays.java @@ -61,7 +61,7 @@ import java.util.stream.StreamSupport; * a MergeSort, but it does have to be <i>stable</i>.) * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch diff --git a/ojluni/src/main/java/java/util/Calendar.java b/ojluni/src/main/java/java/util/Calendar.java index 3a0343b8c8..7093533484 100644 --- a/ojluni/src/main/java/java/util/Calendar.java +++ b/ojluni/src/main/java/java/util/Calendar.java @@ -3376,6 +3376,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca */ private void setWeekCountData(Locale desiredLocale) { + desiredLocale = LocaleData.getCompatibleLocaleForBug159514442(desiredLocale); /* try to get the Locale data from the cache */ int[] data = cachedLocaleData.get(desiredLocale); if (data == null) { /* cache miss */ diff --git a/ojluni/src/main/java/java/util/Collection.java b/ojluni/src/main/java/java/util/Collection.java index 279ec9e995..2ae88727a0 100644 --- a/ojluni/src/main/java/java/util/Collection.java +++ b/ojluni/src/main/java/java/util/Collection.java @@ -112,7 +112,7 @@ import java.util.stream.StreamSupport; * however most current implementations do not do so. * * <p>This interface is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @implSpec diff --git a/ojluni/src/main/java/java/util/Collections.java b/ojluni/src/main/java/java/util/Collections.java index e7e8e72023..58ad86f516 100644 --- a/ojluni/src/main/java/java/util/Collections.java +++ b/ojluni/src/main/java/java/util/Collections.java @@ -70,7 +70,7 @@ import dalvik.system.VMRuntime; * already sorted may or may not throw <tt>UnsupportedOperationException</tt>. * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch diff --git a/ojluni/src/main/java/java/util/Comparator.java b/ojluni/src/main/java/java/util/Comparator.java index 27cfdd58da..ecf8d64ea9 100644 --- a/ojluni/src/main/java/java/util/Comparator.java +++ b/ojluni/src/main/java/java/util/Comparator.java @@ -94,7 +94,7 @@ import java.util.Comparators; * an equivalence relation. * * <p>This interface is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <T> the type of objects that may be compared by this comparator diff --git a/ojluni/src/main/java/java/util/Deque.java b/ojluni/src/main/java/java/util/Deque.java index dbd3d6f0e6..3d79952057 100644 --- a/ojluni/src/main/java/java/util/Deque.java +++ b/ojluni/src/main/java/java/util/Deque.java @@ -187,9 +187,10 @@ package java.util; * @since 1.6 * @param <E> the type of elements held in this deque */ -// Android-changed: fix framework docs link to "Collection#optional-restrictions" -// Several occurrences of the link have been fixed throughout. public interface Deque<E> extends Queue<E> { + // Android-changed: fix framework docs link to "Collection#optional-restrictions" + // Several occurrences of the link have been fixed throughout. + /** * Inserts the specified element at the front of this deque if it is * possible to do so immediately without violating capacity restrictions, diff --git a/ojluni/src/main/java/java/util/EnumMap.java b/ojluni/src/main/java/java/util/EnumMap.java index 30a8dce32b..cd1c5feec5 100644 --- a/ojluni/src/main/java/java/util/EnumMap.java +++ b/ojluni/src/main/java/java/util/EnumMap.java @@ -69,7 +69,7 @@ import java.util.Map.Entry; * {@link HashMap} counterparts. * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch diff --git a/ojluni/src/main/java/java/util/EnumSet.java b/ojluni/src/main/java/java/util/EnumSet.java index f1b0329b9c..95e0124a2f 100644 --- a/ojluni/src/main/java/java/util/EnumSet.java +++ b/ojluni/src/main/java/java/util/EnumSet.java @@ -68,7 +68,7 @@ package java.util; * constant time if their argument is also an enum set. * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch diff --git a/ojluni/src/main/java/java/util/HashMap.java b/ojluni/src/main/java/java/util/HashMap.java index 360f73664d..2c01f6fd92 100644 --- a/ojluni/src/main/java/java/util/HashMap.java +++ b/ojluni/src/main/java/java/util/HashMap.java @@ -117,7 +117,7 @@ import java.util.function.Function; * should be used only to detect bugs.</i> * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <K> the type of keys maintained by this map diff --git a/ojluni/src/main/java/java/util/HashSet.java b/ojluni/src/main/java/java/util/HashSet.java index 5805331705..f9b09ee4c8 100644 --- a/ojluni/src/main/java/java/util/HashSet.java +++ b/ojluni/src/main/java/java/util/HashSet.java @@ -72,7 +72,7 @@ import java.io.InvalidObjectException; * should be used only to detect bugs.</i> * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <E> the type of elements maintained by this set diff --git a/ojluni/src/main/java/java/util/Hashtable.java b/ojluni/src/main/java/java/util/Hashtable.java index fc163a75de..4c76a74e93 100644 --- a/ojluni/src/main/java/java/util/Hashtable.java +++ b/ojluni/src/main/java/java/util/Hashtable.java @@ -105,7 +105,7 @@ import java.util.function.Function; * * <p>As of the Java 2 platform v1.2, this class was retrofitted to * implement the {@link Map} interface, making it a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * * Java Collections Framework</a>. Unlike the new collection * implementations, {@code Hashtable} is synchronized. If a diff --git a/ojluni/src/main/java/java/util/IdentityHashMap.java b/ojluni/src/main/java/java/util/IdentityHashMap.java index 1ed9d76828..9dc0c26c13 100644 --- a/ojluni/src/main/java/java/util/IdentityHashMap.java +++ b/ojluni/src/main/java/java/util/IdentityHashMap.java @@ -122,7 +122,7 @@ import java.util.function.Consumer; * {@link HashMap} (which uses <i>chaining</i> rather than linear-probing). * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @see System#identityHashCode(Object) diff --git a/ojluni/src/main/java/java/util/ImmutableCollections.java b/ojluni/src/main/java/java/util/ImmutableCollections.java new file mode 100644 index 0000000000..2bc0cc1b5d --- /dev/null +++ b/ojluni/src/main/java/java/util/ImmutableCollections.java @@ -0,0 +1,964 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util; + +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; +import jdk.internal.vm.annotation.Stable; + +/** + * Container class for immutable collections. Not part of the public API. + * Mainly for namespace management and shared infrastructure. + * + * Serial warnings are suppressed throughout because all implementation + * classes use a serial proxy and thus have no need to declare serialVersionUID. + */ +@SuppressWarnings("serial") +class ImmutableCollections { + /** + * A "salt" value used for randomizing iteration order. This is initialized once + * and stays constant for the lifetime of the JVM. It need not be truly random, but + * it needs to vary sufficiently from one run to the next so that iteration order + * will vary between JVM runs. + */ + static final int SALT; + static { + long nt = System.nanoTime(); + SALT = (int)((nt >>> 32) ^ nt); + } + + /** No instances. */ + private ImmutableCollections() { } + + /** + * The reciprocal of load factor. Given a number of elements + * to store, multiply by this factor to get the table size. + */ + static final int EXPAND_FACTOR = 2; + + static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); } + + // ---------- List Implementations ---------- + + abstract static class AbstractImmutableList<E> extends AbstractList<E> + implements RandomAccess, Serializable { + @Override public boolean add(E e) { throw uoe(); } + @Override public boolean addAll(Collection<? extends E> c) { throw uoe(); } + @Override public boolean addAll(int index, Collection<? extends E> c) { throw uoe(); } + @Override public void clear() { throw uoe(); } + @Override public boolean remove(Object o) { throw uoe(); } + @Override public boolean removeAll(Collection<?> c) { throw uoe(); } + @Override public boolean removeIf(Predicate<? super E> filter) { throw uoe(); } + @Override public void replaceAll(UnaryOperator<E> operator) { throw uoe(); } + @Override public boolean retainAll(Collection<?> c) { throw uoe(); } + @Override public void sort(Comparator<? super E> c) { throw uoe(); } + } + + static final class List0<E> extends AbstractImmutableList<E> { + private static final List0<?> INSTANCE = new List0<>(); + + @SuppressWarnings("unchecked") + static <T> List0<T> instance() { + return (List0<T>) INSTANCE; + } + + private List0() { } + + @Override + public int size() { + return 0; + } + + @Override + public E get(int index) { + Objects.checkIndex(index, 0); // always throws IndexOutOfBoundsException + return null; // but the compiler doesn't know this + } + + @Override + public Iterator<E> iterator() { + return Collections.emptyIterator(); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new InvalidObjectException("not serial proxy"); + } + + private Object writeReplace() { + return new CollSer(CollSer.IMM_LIST); + } + + @Override + public boolean contains(Object o) { + Objects.requireNonNull(o); + return false; + } + + @Override + public boolean containsAll(Collection<?> o) { + return o.isEmpty(); // implicit nullcheck of o + } + + @Override + public int hashCode() { + return 1; + } + } + + static final class List1<E> extends AbstractImmutableList<E> { + @Stable + private final E e0; + + List1(E e0) { + this.e0 = Objects.requireNonNull(e0); + } + + @Override + public int size() { + return 1; + } + + @Override + public E get(int index) { + Objects.checkIndex(index, 1); + return e0; + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new InvalidObjectException("not serial proxy"); + } + + private Object writeReplace() { + return new CollSer(CollSer.IMM_LIST, e0); + } + + @Override + public boolean contains(Object o) { + return o.equals(e0); // implicit nullcheck of o + } + + @Override + public int hashCode() { + return 31 + e0.hashCode(); + } + } + + static final class List2<E> extends AbstractImmutableList<E> { + @Stable + private final E e0; + @Stable + private final E e1; + + List2(E e0, E e1) { + this.e0 = Objects.requireNonNull(e0); + this.e1 = Objects.requireNonNull(e1); + } + + @Override + public int size() { + return 2; + } + + @Override + public E get(int index) { + Objects.checkIndex(index, 2); + if (index == 0) { + return e0; + } else { // index == 1 + return e1; + } + } + + @Override + public boolean contains(Object o) { + return o.equals(e0) || o.equals(e1); // implicit nullcheck of o + } + + @Override + public int hashCode() { + int hash = 31 + e0.hashCode(); + return 31 * hash + e1.hashCode(); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new InvalidObjectException("not serial proxy"); + } + + private Object writeReplace() { + return new CollSer(CollSer.IMM_LIST, e0, e1); + } + } + + static final class ListN<E> extends AbstractImmutableList<E> { + @Stable + private final E[] elements; + + @SafeVarargs + ListN(E... input) { + // copy and check manually to avoid TOCTOU + @SuppressWarnings("unchecked") + E[] tmp = (E[])new Object[input.length]; // implicit nullcheck of input + for (int i = 0; i < input.length; i++) { + tmp[i] = Objects.requireNonNull(input[i]); + } + this.elements = tmp; + } + + @Override + public int size() { + return elements.length; + } + + @Override + public E get(int index) { + Objects.checkIndex(index, elements.length); + return elements[index]; + } + + @Override + public boolean contains(Object o) { + for (E e : elements) { + if (o.equals(e)) { // implicit nullcheck of o + return true; + } + } + return false; + } + + @Override + public int hashCode() { + int hash = 1; + for (E e : elements) { + hash = 31 * hash + e.hashCode(); + } + return hash; + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new InvalidObjectException("not serial proxy"); + } + + private Object writeReplace() { + return new CollSer(CollSer.IMM_LIST, elements); + } + } + + // ---------- Set Implementations ---------- + + abstract static class AbstractImmutableSet<E> extends AbstractSet<E> implements Serializable { + @Override public boolean add(E e) { throw uoe(); } + @Override public boolean addAll(Collection<? extends E> c) { throw uoe(); } + @Override public void clear() { throw uoe(); } + @Override public boolean remove(Object o) { throw uoe(); } + @Override public boolean removeAll(Collection<?> c) { throw uoe(); } + @Override public boolean removeIf(Predicate<? super E> filter) { throw uoe(); } + @Override public boolean retainAll(Collection<?> c) { throw uoe(); } + } + + static final class Set0<E> extends AbstractImmutableSet<E> { + private static final Set0<?> INSTANCE = new Set0<>(); + + @SuppressWarnings("unchecked") + static <T> Set0<T> instance() { + return (Set0<T>) INSTANCE; + } + + private Set0() { } + + @Override + public int size() { + return 0; + } + + @Override + public boolean contains(Object o) { + Objects.requireNonNull(o); + return false; + } + + @Override + public boolean containsAll(Collection<?> o) { + return o.isEmpty(); // implicit nullcheck of o + } + + @Override + public Iterator<E> iterator() { + return Collections.emptyIterator(); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new InvalidObjectException("not serial proxy"); + } + + private Object writeReplace() { + return new CollSer(CollSer.IMM_SET); + } + + @Override + public int hashCode() { + return 0; + } + } + + static final class Set1<E> extends AbstractImmutableSet<E> { + @Stable + private final E e0; + + Set1(E e0) { + this.e0 = Objects.requireNonNull(e0); + } + + @Override + public int size() { + return 1; + } + + @Override + public boolean contains(Object o) { + return o.equals(e0); // implicit nullcheck of o + } + + @Override + public Iterator<E> iterator() { + return Collections.singletonIterator(e0); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new InvalidObjectException("not serial proxy"); + } + + private Object writeReplace() { + return new CollSer(CollSer.IMM_SET, e0); + } + + @Override + public int hashCode() { + return e0.hashCode(); + } + } + + static final class Set2<E> extends AbstractImmutableSet<E> { + @Stable + final E e0; + @Stable + final E e1; + + Set2(E e0, E e1) { + if (e0.equals(Objects.requireNonNull(e1))) { // implicit nullcheck of e0 + throw new IllegalArgumentException("duplicate element: " + e0); + } + + if (SALT >= 0) { + this.e0 = e0; + this.e1 = e1; + } else { + this.e0 = e1; + this.e1 = e0; + } + } + + @Override + public int size() { + return 2; + } + + @Override + public boolean contains(Object o) { + return o.equals(e0) || o.equals(e1); // implicit nullcheck of o + } + + @Override + public int hashCode() { + return e0.hashCode() + e1.hashCode(); + } + + @Override + public Iterator<E> iterator() { + return new Iterator<E>() { + private int idx = 0; + + @Override + public boolean hasNext() { + return idx < 2; + } + + @Override + public E next() { + if (idx == 0) { + idx = 1; + return e0; + } else if (idx == 1) { + idx = 2; + return e1; + } else { + throw new NoSuchElementException(); + } + } + }; + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new InvalidObjectException("not serial proxy"); + } + + private Object writeReplace() { + return new CollSer(CollSer.IMM_SET, e0, e1); + } + } + + /** + * An array-based Set implementation. The element array must be strictly + * larger than the size (the number of contained elements) so that at + * least one null is always present. + * @param <E> the element type + */ + static final class SetN<E> extends AbstractImmutableSet<E> { + @Stable + final E[] elements; + @Stable + final int size; + + @SafeVarargs + @SuppressWarnings("unchecked") + SetN(E... input) { + size = input.length; // implicit nullcheck of input + + elements = (E[])new Object[EXPAND_FACTOR * input.length]; + for (int i = 0; i < input.length; i++) { + E e = input[i]; + int idx = probe(e); // implicit nullcheck of e + if (idx >= 0) { + throw new IllegalArgumentException("duplicate element: " + e); + } else { + elements[-(idx + 1)] = e; + } + } + } + + @Override + public int size() { + return size; + } + + @Override + public boolean contains(Object o) { + return probe(o) >= 0; // implicit nullcheck of o + } + + @Override + public Iterator<E> iterator() { + return new Iterator<E>() { + private int idx = 0; + + @Override + public boolean hasNext() { + while (idx < elements.length) { + if (elements[idx] != null) + return true; + idx++; + } + return false; + } + + @Override + public E next() { + if (! hasNext()) { + throw new NoSuchElementException(); + } + return elements[idx++]; + } + }; + } + + @Override + public int hashCode() { + int h = 0; + for (E e : elements) { + if (e != null) { + h += e.hashCode(); + } + } + return h; + } + + // returns index at which element is present; or if absent, + // (-i - 1) where i is location where element should be inserted. + // Callers are relying on this method to perform an implicit nullcheck + // of pe + private int probe(Object pe) { + int idx = Math.floorMod(pe.hashCode() ^ SALT, elements.length); + while (true) { + E ee = elements[idx]; + if (ee == null) { + return -idx - 1; + } else if (pe.equals(ee)) { + return idx; + } else if (++idx == elements.length) { + idx = 0; + } + } + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new InvalidObjectException("not serial proxy"); + } + + private Object writeReplace() { + Object[] array = new Object[size]; + int dest = 0; + for (Object o : elements) { + if (o != null) { + array[dest++] = o; + } + } + return new CollSer(CollSer.IMM_SET, array); + } + } + + // ---------- Map Implementations ---------- + + abstract static class AbstractImmutableMap<K,V> extends AbstractMap<K,V> implements Serializable { + @Override public void clear() { throw uoe(); } + @Override public V compute(K key, BiFunction<? super K,? super V,? extends V> rf) { throw uoe(); } + @Override public V computeIfAbsent(K key, Function<? super K,? extends V> mf) { throw uoe(); } + @Override public V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> rf) { throw uoe(); } + @Override public V merge(K key, V value, BiFunction<? super V,? super V,? extends V> rf) { throw uoe(); } + @Override public V put(K key, V value) { throw uoe(); } + @Override public void putAll(Map<? extends K,? extends V> m) { throw uoe(); } + @Override public V putIfAbsent(K key, V value) { throw uoe(); } + @Override public V remove(Object key) { throw uoe(); } + @Override public boolean remove(Object key, Object value) { throw uoe(); } + @Override public V replace(K key, V value) { throw uoe(); } + @Override public boolean replace(K key, V oldValue, V newValue) { throw uoe(); } + @Override public void replaceAll(BiFunction<? super K,? super V,? extends V> f) { throw uoe(); } + } + + static final class Map0<K,V> extends AbstractImmutableMap<K,V> { + private static final Map0<?,?> INSTANCE = new Map0<>(); + + @SuppressWarnings("unchecked") + static <K,V> Map0<K,V> instance() { + return (Map0<K,V>) INSTANCE; + } + + private Map0() { } + + @Override + public Set<Map.Entry<K,V>> entrySet() { + return Set.of(); + } + + @Override + public boolean containsKey(Object o) { + Objects.requireNonNull(o); + return false; + } + + @Override + public boolean containsValue(Object o) { + Objects.requireNonNull(o); + return false; + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new InvalidObjectException("not serial proxy"); + } + + private Object writeReplace() { + return new CollSer(CollSer.IMM_MAP); + } + + @Override + public int hashCode() { + return 0; + } + } + + static final class Map1<K,V> extends AbstractImmutableMap<K,V> { + @Stable + private final K k0; + @Stable + private final V v0; + + Map1(K k0, V v0) { + this.k0 = Objects.requireNonNull(k0); + this.v0 = Objects.requireNonNull(v0); + } + + @Override + public Set<Map.Entry<K,V>> entrySet() { + return Set.of(new KeyValueHolder<>(k0, v0)); + } + + @Override + public boolean containsKey(Object o) { + return o.equals(k0); // implicit nullcheck of o + } + + @Override + public boolean containsValue(Object o) { + return o.equals(v0); // implicit nullcheck of o + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new InvalidObjectException("not serial proxy"); + } + + private Object writeReplace() { + return new CollSer(CollSer.IMM_MAP, k0, v0); + } + + @Override + public int hashCode() { + return k0.hashCode() ^ v0.hashCode(); + } + } + + /** + * An array-based Map implementation. There is a single array "table" that + * contains keys and values interleaved: table[0] is kA, table[1] is vA, + * table[2] is kB, table[3] is vB, etc. The table size must be even. It must + * also be strictly larger than the size (the number of key-value pairs contained + * in the map) so that at least one null key is always present. + * @param <K> the key type + * @param <V> the value type + */ + static final class MapN<K,V> extends AbstractImmutableMap<K,V> { + @Stable + final Object[] table; // pairs of key, value + @Stable + final int size; // number of pairs + + MapN(Object... input) { + if ((input.length & 1) != 0) { // implicit nullcheck of input + throw new InternalError("length is odd"); + } + size = input.length >> 1; + + int len = EXPAND_FACTOR * input.length; + len = (len + 1) & ~1; // ensure table is even length + table = new Object[len]; + + for (int i = 0; i < input.length; i += 2) { + @SuppressWarnings("unchecked") + K k = Objects.requireNonNull((K)input[i]); + @SuppressWarnings("unchecked") + V v = Objects.requireNonNull((V)input[i+1]); + int idx = probe(k); + if (idx >= 0) { + throw new IllegalArgumentException("duplicate key: " + k); + } else { + int dest = -(idx + 1); + table[dest] = k; + table[dest+1] = v; + } + } + } + + @Override + public boolean containsKey(Object o) { + return probe(o) >= 0; // implicit nullcheck of o + } + + @Override + public boolean containsValue(Object o) { + for (int i = 1; i < table.length; i += 2) { + Object v = table[i]; + if (v != null && o.equals(v)) { // implicit nullcheck of o + return true; + } + } + return false; + } + + @Override + public int hashCode() { + int hash = 0; + for (int i = 0; i < table.length; i += 2) { + Object k = table[i]; + if (k != null) { + hash += k.hashCode() ^ table[i + 1].hashCode(); + } + } + return hash; + } + + @Override + @SuppressWarnings("unchecked") + public V get(Object o) { + int i = probe(o); + if (i >= 0) { + return (V)table[i+1]; + } else { + return null; + } + } + + @Override + public int size() { + return size; + } + + @Override + public Set<Map.Entry<K,V>> entrySet() { + return new AbstractSet<Map.Entry<K,V>>() { + @Override + public int size() { + return MapN.this.size; + } + + @Override + public Iterator<Map.Entry<K,V>> iterator() { + return new Iterator<Map.Entry<K,V>>() { + int idx = 0; + + @Override + public boolean hasNext() { + while (idx < table.length) { + if (table[idx] != null) + return true; + idx += 2; + } + return false; + } + + @Override + public Map.Entry<K,V> next() { + if (hasNext()) { + @SuppressWarnings("unchecked") + Map.Entry<K,V> e = + new KeyValueHolder<>((K)table[idx], (V)table[idx+1]); + idx += 2; + return e; + } else { + throw new NoSuchElementException(); + } + } + }; + } + }; + } + + // returns index at which the probe key is present; or if absent, + // (-i - 1) where i is location where element should be inserted. + // Callers are relying on this method to perform an implicit nullcheck + // of pk. + private int probe(Object pk) { + int idx = Math.floorMod(pk.hashCode() ^ SALT, table.length >> 1) << 1; + while (true) { + @SuppressWarnings("unchecked") + K ek = (K)table[idx]; + if (ek == null) { + return -idx - 1; + } else if (pk.equals(ek)) { + return idx; + } else if ((idx += 2) == table.length) { + idx = 0; + } + } + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new InvalidObjectException("not serial proxy"); + } + + private Object writeReplace() { + Object[] array = new Object[2 * size]; + int len = table.length; + int dest = 0; + for (int i = 0; i < len; i += 2) { + if (table[i] != null) { + array[dest++] = table[i]; + array[dest++] = table[i+1]; + } + } + return new CollSer(CollSer.IMM_MAP, array); + } + } +} + +// ---------- Serialization Proxy ---------- + +/** + * A unified serialization proxy class for the immutable collections. + * + * @serial + * @since 9 + */ +final class CollSer implements Serializable { + private static final long serialVersionUID = 6309168927139932177L; + + static final int IMM_LIST = 1; + static final int IMM_SET = 2; + static final int IMM_MAP = 3; + + /** + * Indicates the type of collection that is serialized. + * The low order 8 bits have the value 1 for an immutable + * {@code List}, 2 for an immutable {@code Set}, and 3 for + * an immutable {@code Map}. Any other value causes an + * {@link InvalidObjectException} to be thrown. The high + * order 24 bits are zero when an instance is serialized, + * and they are ignored when an instance is deserialized. + * They can thus be used by future implementations without + * causing compatibility issues. + * + * <p>The tag value also determines the interpretation of the + * transient {@code Object[] array} field. + * For {@code List} and {@code Set}, the array's length is the size + * of the collection, and the array contains the elements of the collection. + * Null elements are not allowed. For {@code Set}, duplicate elements + * are not allowed. + * + * <p>For {@code Map}, the array's length is twice the number of mappings + * present in the map. The array length is necessarily even. + * The array contains a succession of key and value pairs: + * {@code k1, v1, k2, v2, ..., kN, vN.} Nulls are not allowed, + * and duplicate keys are not allowed. + * + * @serial + * @since 9 + */ + private final int tag; + + /** + * @serial + * @since 9 + */ + private transient Object[] array; + + CollSer(int t, Object... a) { + tag = t; + array = a; + } + + /** + * Reads objects from the stream and stores them + * in the transient {@code Object[] array} field. + * + * @serialData + * A nonnegative int, indicating the count of objects, + * followed by that many objects. + * + * @param ois the ObjectInputStream from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + * @throws InvalidObjectException if the count is negative + * @since 9 + */ + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + int len = ois.readInt(); + + if (len < 0) { + throw new InvalidObjectException("negative length " + len); + } + + Object[] a = new Object[len]; + for (int i = 0; i < len; i++) { + a[i] = ois.readObject(); + } + + array = a; + } + + /** + * Writes objects to the stream from + * the transient {@code Object[] array} field. + * + * @serialData + * A nonnegative int, indicating the count of objects, + * followed by that many objects. + * + * @param oos the ObjectOutputStream to which data is written + * @throws IOException if an I/O error occurs + * @since 9 + */ + private void writeObject(ObjectOutputStream oos) throws IOException { + oos.defaultWriteObject(); + oos.writeInt(array.length); + for (int i = 0; i < array.length; i++) { + oos.writeObject(array[i]); + } + } + + /** + * Creates and returns an immutable collection from this proxy class. + * The instance returned is created as if by calling one of the + * static factory methods for + * <a href="List.html#immutable">List</a>, + * <a href="Map.html#immutable">Map</a>, or + * <a href="Set.html#immutable">Set</a>. + * This proxy class is the serial form for all immutable collection instances, + * regardless of implementation type. This is necessary to ensure that the + * existence of any particular implementation type is kept out of the + * serialized form. + * + * @return a collection created from this proxy object + * @throws InvalidObjectException if the tag value is illegal or if an exception + * is thrown during creation of the collection + * @throws ObjectStreamException if another serialization error has occurred + * @since 9 + */ + private Object readResolve() throws ObjectStreamException { + try { + if (array == null) { + throw new InvalidObjectException("null array"); + } + + // use low order 8 bits to indicate "kind" + // ignore high order 24 bits + switch (tag & 0xff) { + case IMM_LIST: + return List.of(array); + case IMM_SET: + return Set.of(array); + case IMM_MAP: + if (array.length == 0) { + return ImmutableCollections.Map0.instance(); + } else if (array.length == 2) { + return new ImmutableCollections.Map1<>(array[0], array[1]); + } else { + return new ImmutableCollections.MapN<>(array); + } + default: + throw new InvalidObjectException(String.format("invalid flags 0x%x", tag)); + } + } catch (NullPointerException|IllegalArgumentException ex) { + InvalidObjectException ioe = new InvalidObjectException("invalid object"); + ioe.initCause(ex); + throw ioe; + } + } +} diff --git a/ojluni/src/main/java/java/util/Iterator.java b/ojluni/src/main/java/java/util/Iterator.java index 02777b6e0a..7d2daf8f96 100644 --- a/ojluni/src/main/java/java/util/Iterator.java +++ b/ojluni/src/main/java/java/util/Iterator.java @@ -40,7 +40,7 @@ import java.util.function.Consumer; * </ul> * * <p>This interface is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <E> the type of elements returned by this iterator diff --git a/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java b/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java index a0ee15e6db..f0512c5691 100644 --- a/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java +++ b/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java @@ -101,10 +101,11 @@ class JapaneseImperialCalendar extends Calendar { */ public static final int HEISEI = 4; + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. /** * The ERA constant designating the Reiwa era. */ - private static final int REIWA = 5; + public static final int REIWA = 5; private static final int EPOCH_OFFSET = 719163; // Fixed date of January 1, 1970 (Gregorian) private static final int EPOCH_YEAR = 1970; diff --git a/ojluni/src/main/java/java/util/KeyValueHolder.java b/ojluni/src/main/java/java/util/KeyValueHolder.java new file mode 100644 index 0000000000..3b7250ee6a --- /dev/null +++ b/ojluni/src/main/java/java/util/KeyValueHolder.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util; + +import jdk.internal.vm.annotation.Stable; + +/** + * An immutable container for a key and a value, suitable for use + * in creating and populating {@code Map} instances. + * + * <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a> + * class; use of identity-sensitive operations (including reference equality + * ({@code ==}), identity hash code, or synchronization) on instances of + * {@code KeyValueHolder} may have unpredictable results and should be avoided. + * + * @apiNote + * This class is not public. Instances can be created using the + * {@link Map#entry Map.entry(k, v)} factory method, which is public. + * + * <p>This class differs from AbstractMap.SimpleImmutableEntry in the following ways: + * it is not serializable, it is final, and its key and value must be non-null. + * + * @param <K> the key type + * @param <V> the value type + * + * @see Map#ofEntries Map.ofEntries() + * @since 9 + */ +final class KeyValueHolder<K,V> implements Map.Entry<K,V> { + @Stable + final K key; + @Stable + final V value; + + KeyValueHolder(K k, V v) { + key = Objects.requireNonNull(k); + value = Objects.requireNonNull(v); + } + + /** + * Gets the key from this holder. + * + * @return the key + */ + @Override + public K getKey() { + return key; + } + + /** + * Gets the value from this holder. + * + * @return the value + */ + @Override + public V getValue() { + return value; + } + + /** + * Throws {@link UnsupportedOperationException}. + * + * @param value ignored + * @return never returns normally + */ + @Override + public V setValue(V value) { + throw new UnsupportedOperationException("not supported"); + } + + /** + * Compares the specified object with this entry for equality. + * Returns {@code true} if the given object is also a map entry and + * the two entries' keys and values are equal. Note that key and + * value are non-null, so equals() can be called safely on them. + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof Map.Entry)) + return false; + Map.Entry<?,?> e = (Map.Entry<?,?>)o; + return key.equals(e.getKey()) && value.equals(e.getValue()); + } + + /** + * Returns the hash code value for this map entry. The hash code + * is {@code key.hashCode() ^ value.hashCode()}. Note that key and + * value are non-null, so hashCode() can be called safely on them. + */ + @Override + public int hashCode() { + return key.hashCode() ^ value.hashCode(); + } + + /** + * Returns a String representation of this map entry. This + * implementation returns the string representation of this + * entry's key followed by the equals character ("{@code =}") + * followed by the string representation of this entry's value. + * + * @return a String representation of this map entry + */ + @Override + public String toString() { + return key + "=" + value; + } +} diff --git a/ojluni/src/main/java/java/util/LinkedHashMap.java b/ojluni/src/main/java/java/util/LinkedHashMap.java index a60c7e50e5..9d3815ff94 100644 --- a/ojluni/src/main/java/java/util/LinkedHashMap.java +++ b/ojluni/src/main/java/java/util/LinkedHashMap.java @@ -158,7 +158,7 @@ import java.io.IOException; * {@code LinkedHashMap}. * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @implNote diff --git a/ojluni/src/main/java/java/util/LinkedHashSet.java b/ojluni/src/main/java/java/util/LinkedHashSet.java index c573d7cea8..08606cfe4c 100644 --- a/ojluni/src/main/java/java/util/LinkedHashSet.java +++ b/ojluni/src/main/java/java/util/LinkedHashSet.java @@ -100,7 +100,7 @@ package java.util; * should be used only to detect bugs.</i> * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <E> the type of elements maintained by this set diff --git a/ojluni/src/main/java/java/util/LinkedList.java b/ojluni/src/main/java/java/util/LinkedList.java index 2683a90bd8..60f4c414bb 100644 --- a/ojluni/src/main/java/java/util/LinkedList.java +++ b/ojluni/src/main/java/java/util/LinkedList.java @@ -70,7 +70,7 @@ import java.util.function.Consumer; * should be used only to detect bugs.</i> * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch diff --git a/ojluni/src/main/java/java/util/List.java b/ojluni/src/main/java/java/util/List.java index f32d9ed8ce..1b9deb3183 100644 --- a/ojluni/src/main/java/java/util/List.java +++ b/ojluni/src/main/java/java/util/List.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package java.util; import java.util.function.UnaryOperator; +// Android-removed: removed link to collections framework docs /** * An ordered collection (also known as a <i>sequence</i>). The user of this * interface has precise control over where in the list each element is @@ -34,50 +35,50 @@ import java.util.function.UnaryOperator; * the list), and search for elements in the list.<p> * * Unlike sets, lists typically allow duplicate elements. More formally, - * lists typically allow pairs of elements <tt>e1</tt> and <tt>e2</tt> - * such that <tt>e1.equals(e2)</tt>, and they typically allow multiple + * lists typically allow pairs of elements {@code e1} and {@code e2} + * such that {@code e1.equals(e2)}, and they typically allow multiple * null elements if they allow null elements at all. It is not inconceivable * that someone might wish to implement a list that prohibits duplicates, by * throwing runtime exceptions when the user attempts to insert them, but we * expect this usage to be rare.<p> * - * The <tt>List</tt> interface places additional stipulations, beyond those - * specified in the <tt>Collection</tt> interface, on the contracts of the - * <tt>iterator</tt>, <tt>add</tt>, <tt>remove</tt>, <tt>equals</tt>, and - * <tt>hashCode</tt> methods. Declarations for other inherited methods are + * The {@code List} interface places additional stipulations, beyond those + * specified in the {@code Collection} interface, on the contracts of the + * {@code iterator}, {@code add}, {@code remove}, {@code equals}, and + * {@code hashCode} methods. Declarations for other inherited methods are * also included here for convenience.<p> * - * The <tt>List</tt> interface provides four methods for positional (indexed) + * The {@code List} interface provides four methods for positional (indexed) * access to list elements. Lists (like Java arrays) are zero based. Note * that these operations may execute in time proportional to the index value - * for some implementations (the <tt>LinkedList</tt> class, for + * for some implementations (the {@code LinkedList} class, for * example). Thus, iterating over the elements in a list is typically * preferable to indexing through it if the caller does not know the * implementation.<p> * - * The <tt>List</tt> interface provides a special iterator, called a - * <tt>ListIterator</tt>, that allows element insertion and replacement, and + * The {@code List} interface provides a special iterator, called a + * {@code ListIterator}, that allows element insertion and replacement, and * bidirectional access in addition to the normal operations that the - * <tt>Iterator</tt> interface provides. A method is provided to obtain a + * {@code Iterator} interface provides. A method is provided to obtain a * list iterator that starts at a specified position in the list.<p> * - * The <tt>List</tt> interface provides two methods to search for a specified + * The {@code List} interface provides two methods to search for a specified * object. From a performance standpoint, these methods should be used with * caution. In many implementations they will perform costly linear * searches.<p> * - * The <tt>List</tt> interface provides two methods to efficiently insert and + * The {@code List} interface provides two methods to efficiently insert and * remove multiple elements at an arbitrary point in the list.<p> * * Note: While it is permissible for lists to contain themselves as elements, - * extreme caution is advised: the <tt>equals</tt> and <tt>hashCode</tt> + * extreme caution is advised: the {@code equals} and {@code hashCode} * methods are no longer well defined on such a list. * * <p>Some list implementations have restrictions on the elements that * they may contain. For example, some implementations prohibit null elements, * and some have restrictions on the types of their elements. Attempting to * add an ineligible element throws an unchecked exception, typically - * <tt>NullPointerException</tt> or <tt>ClassCastException</tt>. Attempting + * {@code NullPointerException} or {@code ClassCastException}. Attempting * to query the presence of an ineligible element may throw an exception, * or it may simply return false; some implementations will exhibit the former * behavior and some will exhibit the latter. More generally, attempting an @@ -87,9 +88,31 @@ import java.util.function.UnaryOperator; * Such exceptions are marked as "optional" in the specification for this * interface. * - * <p>This interface is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> - * Java Collections Framework</a>. + * <h2><a id="immutable">Immutable List Static Factory Methods</a></h2> + * <p>The {@link List#of(Object...) List.of()} static factory methods + * provide a convenient way to create immutable lists. The {@code List} + * instances created by these methods have the following characteristics: + * + * <ul> + * <li>They are <em>structurally immutable</em>. Elements cannot be added, removed, + * or replaced. Calling any mutator method will always cause + * {@code UnsupportedOperationException} to be thrown. + * However, if the contained elements are themselves mutable, + * this may cause the List's contents to appear to change. + * <li>They disallow {@code null} elements. Attempts to create them with + * {@code null} elements result in {@code NullPointerException}. + * <li>They are serializable if all elements are serializable. + * <li>The order of elements in the list is the same as the order of the + * provided arguments, or of the elements in the provided array. + * <li>They are <a href="../lang/doc-files/ValueBased.html">value-based</a>. + * Callers should make no assumptions about the identity of the returned instances. + * Factories are free to create new instances or reuse existing ones. Therefore, + * identity-sensitive operations on these instances (reference equality ({@code ==}), + * identity hash code, and synchronization) are unreliable and should be avoided. + * <li>They are serialized as specified on the + * <a href="{@docRoot}/serialized-form.html#java.util.CollSer">Serialized Form</a> + * page. + * </ul> * * @param <E> the type of elements in this list * @@ -113,28 +136,28 @@ public interface List<E> extends Collection<E> { /** * Returns the number of elements in this list. If this list contains - * more than <tt>Integer.MAX_VALUE</tt> elements, returns - * <tt>Integer.MAX_VALUE</tt>. + * more than {@code Integer.MAX_VALUE} elements, returns + * {@code Integer.MAX_VALUE}. * * @return the number of elements in this list */ int size(); /** - * Returns <tt>true</tt> if this list contains no elements. + * Returns {@code true} if this list contains no elements. * - * @return <tt>true</tt> if this list contains no elements + * @return {@code true} if this list contains no elements */ boolean isEmpty(); /** - * Returns <tt>true</tt> if this list contains the specified element. - * More formally, returns <tt>true</tt> if and only if this list contains - * at least one element <tt>e</tt> such that - * <tt>(o==null ? e==null : o.equals(e))</tt>. + * Returns {@code true} if this list contains the specified element. + * More formally, returns {@code true} if and only if this list contains + * at least one element {@code e} such that + * {@code Objects.equals(o, e)}. * * @param o element whose presence in this list is to be tested - * @return <tt>true</tt> if this list contains the specified element + * @return {@code true} if this list contains the specified element * @throws ClassCastException if the type of the specified element * is incompatible with this list * (<a href="Collection.html#optional-restrictions">optional</a>) @@ -179,7 +202,7 @@ public interface List<E> extends Collection<E> { * * <p>If the list fits in the specified array with room to spare (i.e., * the array has more elements than the list), the element in the array - * immediately following the end of the list is set to <tt>null</tt>. + * immediately following the end of the list is set to {@code null}. * (This is useful in determining the length of the list <i>only</i> if * the caller knows that the list does not contain any null elements.) * @@ -188,16 +211,16 @@ public interface List<E> extends Collection<E> { * precise control over the runtime type of the output array, and may, * under certain circumstances, be used to save allocation costs. * - * <p>Suppose <tt>x</tt> is a list known to contain only strings. + * <p>Suppose {@code x} is a list known to contain only strings. * The following code can be used to dump the list into a newly - * allocated array of <tt>String</tt>: + * allocated array of {@code String}: * * <pre>{@code * String[] y = x.toArray(new String[0]); * }</pre> * - * Note that <tt>toArray(new Object[0])</tt> is identical in function to - * <tt>toArray()</tt>. + * Note that {@code toArray(new Object[0])} is identical in function to + * {@code toArray()}. * * @param a the array into which the elements of this list are to * be stored, if it is big enough; otherwise, a new array of the @@ -225,8 +248,8 @@ public interface List<E> extends Collection<E> { * on what elements may be added. * * @param e element to be appended to this list - * @return <tt>true</tt> (as specified by {@link Collection#add}) - * @throws UnsupportedOperationException if the <tt>add</tt> operation + * @return {@code true} (as specified by {@link Collection#add}) + * @throws UnsupportedOperationException if the {@code add} operation * is not supported by this list * @throws ClassCastException if the class of the specified element * prevents it from being added to this list @@ -241,21 +264,21 @@ public interface List<E> extends Collection<E> { * Removes the first occurrence of the specified element from this list, * if it is present (optional operation). If this list does not contain * the element, it is unchanged. More formally, removes the element with - * the lowest index <tt>i</tt> such that - * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> - * (if such an element exists). Returns <tt>true</tt> if this list + * the lowest index {@code i} such that + * {@code Objects.equals(o, get(i))} + * (if such an element exists). Returns {@code true} if this list * contained the specified element (or equivalently, if this list changed * as a result of the call). * * @param o element to be removed from this list, if present - * @return <tt>true</tt> if this list contained the specified element + * @return {@code true} if this list contained the specified element * @throws ClassCastException if the type of the specified element * is incompatible with this list * (<a href="Collection.html#optional-restrictions">optional</a>) * @throws NullPointerException if the specified element is null and this * list does not permit null elements * (<a href="Collection.html#optional-restrictions">optional</a>) - * @throws UnsupportedOperationException if the <tt>remove</tt> operation + * @throws UnsupportedOperationException if the {@code remove} operation * is not supported by this list */ boolean remove(Object o); @@ -264,11 +287,11 @@ public interface List<E> extends Collection<E> { // Bulk Modification Operations /** - * Returns <tt>true</tt> if this list contains all of the elements of the + * Returns {@code true} if this list contains all of the elements of the * specified collection. * * @param c collection to be checked for containment in this list - * @return <tt>true</tt> if this list contains all of the elements of the + * @return {@code true} if this list contains all of the elements of the * specified collection * @throws ClassCastException if the types of one or more elements * in the specified collection are incompatible with this @@ -292,8 +315,8 @@ public interface List<E> extends Collection<E> { * specified collection is this list, and it's nonempty.) * * @param c collection containing elements to be added to this list - * @return <tt>true</tt> if this list changed as a result of the call - * @throws UnsupportedOperationException if the <tt>addAll</tt> operation + * @return {@code true} if this list changed as a result of the call + * @throws UnsupportedOperationException if the {@code addAll} operation * is not supported by this list * @throws ClassCastException if the class of an element of the specified * collection prevents it from being added to this list @@ -320,8 +343,8 @@ public interface List<E> extends Collection<E> { * @param index index at which to insert the first element from the * specified collection * @param c collection containing elements to be added to this list - * @return <tt>true</tt> if this list changed as a result of the call - * @throws UnsupportedOperationException if the <tt>addAll</tt> operation + * @return {@code true} if this list changed as a result of the call + * @throws UnsupportedOperationException if the {@code addAll} operation * is not supported by this list * @throws ClassCastException if the class of an element of the specified * collection prevents it from being added to this list @@ -331,7 +354,7 @@ public interface List<E> extends Collection<E> { * @throws IllegalArgumentException if some property of an element of the * specified collection prevents it from being added to this list * @throws IndexOutOfBoundsException if the index is out of range - * (<tt>index < 0 || index > size()</tt>) + * ({@code index < 0 || index > size()}) */ boolean addAll(int index, Collection<? extends E> c); @@ -340,8 +363,8 @@ public interface List<E> extends Collection<E> { * specified collection (optional operation). * * @param c collection containing elements to be removed from this list - * @return <tt>true</tt> if this list changed as a result of the call - * @throws UnsupportedOperationException if the <tt>removeAll</tt> operation + * @return {@code true} if this list changed as a result of the call + * @throws UnsupportedOperationException if the {@code removeAll} operation * is not supported by this list * @throws ClassCastException if the class of an element of this list * is incompatible with the specified collection @@ -362,8 +385,8 @@ public interface List<E> extends Collection<E> { * specified collection. * * @param c collection containing elements to be retained in this list - * @return <tt>true</tt> if this list changed as a result of the call - * @throws UnsupportedOperationException if the <tt>retainAll</tt> operation + * @return {@code true} if this list changed as a result of the call + * @throws UnsupportedOperationException if the {@code retainAll} operation * is not supported by this list * @throws ClassCastException if the class of an element of this list * is incompatible with the specified collection @@ -443,12 +466,12 @@ public interface List<E> extends Collection<E> { * @Override * public void sort(Comparator<? super E> c) { * Object[] elements = toArray(); - * Arrays.sort(elements, c); - * ListIterator<E> iterator = (ListIterator<Object>) listIterator(); - * for (Object element : elements) { - * iterator.next(); - * iterator.set((E) element); - * } + * Arrays.sort(elements, c); + * ListIterator<E> iterator = (ListIterator<Object>) listIterator(); + * for (Object element : elements) { + * iterator.next(); + * iterator.set((E) element); + * } * } * </pre> * @@ -510,7 +533,7 @@ public interface List<E> extends Collection<E> { * Removes all of the elements from this list (optional operation). * The list will be empty after this call returns. * - * @throws UnsupportedOperationException if the <tt>clear</tt> operation + * @throws UnsupportedOperationException if the {@code clear} operation * is not supported by this list */ void clear(); @@ -520,17 +543,17 @@ public interface List<E> extends Collection<E> { /** * Compares the specified object with this list for equality. Returns - * <tt>true</tt> if and only if the specified object is also a list, both + * {@code true} if and only if the specified object is also a list, both * lists have the same size, and all corresponding pairs of elements in - * the two lists are <i>equal</i>. (Two elements <tt>e1</tt> and - * <tt>e2</tt> are <i>equal</i> if <tt>(e1==null ? e2==null : - * e1.equals(e2))</tt>.) In other words, two lists are defined to be + * the two lists are <i>equal</i>. (Two elements {@code e1} and + * {@code e2} are <i>equal</i> if {@code Objects.equals(e1, e2)}.) + * In other words, two lists are defined to be * equal if they contain the same elements in the same order. This * definition ensures that the equals method works properly across - * different implementations of the <tt>List</tt> interface. + * different implementations of the {@code List} interface. * * @param o the object to be compared for equality with this list - * @return <tt>true</tt> if the specified object is equal to this list + * @return {@code true} if the specified object is equal to this list */ boolean equals(Object o); @@ -542,9 +565,9 @@ public interface List<E> extends Collection<E> { * for (E e : list) * hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); * }</pre> - * This ensures that <tt>list1.equals(list2)</tt> implies that - * <tt>list1.hashCode()==list2.hashCode()</tt> for any two lists, - * <tt>list1</tt> and <tt>list2</tt>, as required by the general + * This ensures that {@code list1.equals(list2)} implies that + * {@code list1.hashCode()==list2.hashCode()} for any two lists, + * {@code list1} and {@code list2}, as required by the general * contract of {@link Object#hashCode}. * * @return the hash code value for this list @@ -562,7 +585,7 @@ public interface List<E> extends Collection<E> { * @param index index of the element to return * @return the element at the specified position in this list * @throws IndexOutOfBoundsException if the index is out of range - * (<tt>index < 0 || index >= size()</tt>) + * ({@code index < 0 || index >= size()}) */ E get(int index); @@ -573,7 +596,7 @@ public interface List<E> extends Collection<E> { * @param index index of the element to replace * @param element element to be stored at the specified position * @return the element previously at the specified position - * @throws UnsupportedOperationException if the <tt>set</tt> operation + * @throws UnsupportedOperationException if the {@code set} operation * is not supported by this list * @throws ClassCastException if the class of the specified element * prevents it from being added to this list @@ -582,7 +605,7 @@ public interface List<E> extends Collection<E> { * @throws IllegalArgumentException if some property of the specified * element prevents it from being added to this list * @throws IndexOutOfBoundsException if the index is out of range - * (<tt>index < 0 || index >= size()</tt>) + * ({@code index < 0 || index >= size()}) */ E set(int index, E element); @@ -594,7 +617,7 @@ public interface List<E> extends Collection<E> { * * @param index index at which the specified element is to be inserted * @param element element to be inserted - * @throws UnsupportedOperationException if the <tt>add</tt> operation + * @throws UnsupportedOperationException if the {@code add} operation * is not supported by this list * @throws ClassCastException if the class of the specified element * prevents it from being added to this list @@ -603,7 +626,7 @@ public interface List<E> extends Collection<E> { * @throws IllegalArgumentException if some property of the specified * element prevents it from being added to this list * @throws IndexOutOfBoundsException if the index is out of range - * (<tt>index < 0 || index > size()</tt>) + * ({@code index < 0 || index > size()}) */ void add(int index, E element); @@ -615,10 +638,10 @@ public interface List<E> extends Collection<E> { * * @param index the index of the element to be removed * @return the element previously at the specified position - * @throws UnsupportedOperationException if the <tt>remove</tt> operation + * @throws UnsupportedOperationException if the {@code remove} operation * is not supported by this list * @throws IndexOutOfBoundsException if the index is out of range - * (<tt>index < 0 || index >= size()</tt>) + * ({@code index < 0 || index >= size()}) */ E remove(int index); @@ -628,8 +651,8 @@ public interface List<E> extends Collection<E> { /** * Returns the index of the first occurrence of the specified element * in this list, or -1 if this list does not contain the element. - * More formally, returns the lowest index <tt>i</tt> such that - * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, + * More formally, returns the lowest index {@code i} such that + * {@code Objects.equals(o, get(i))}, * or -1 if there is no such index. * * @param o element to search for @@ -647,8 +670,8 @@ public interface List<E> extends Collection<E> { /** * Returns the index of the last occurrence of the specified element * in this list, or -1 if this list does not contain the element. - * More formally, returns the highest index <tt>i</tt> such that - * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, + * More formally, returns the highest index {@code i} such that + * {@code Objects.equals(o, get(i))}, * or -1 if there is no such index. * * @param o element to search for @@ -696,8 +719,8 @@ public interface List<E> extends Collection<E> { /** * Returns a view of the portion of this list between the specified - * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive. (If - * <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is + * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. (If + * {@code fromIndex} and {@code toIndex} are equal, the returned list is * empty.) The returned list is backed by this list, so non-structural * changes in the returned list are reflected in this list, and vice-versa. * The returned list supports all of the optional list operations supported @@ -711,9 +734,9 @@ public interface List<E> extends Collection<E> { * <pre>{@code * list.subList(from, to).clear(); * }</pre> - * Similar idioms may be constructed for <tt>indexOf</tt> and - * <tt>lastIndexOf</tt>, and all of the algorithms in the - * <tt>Collections</tt> class can be applied to a subList.<p> + * Similar idioms may be constructed for {@code indexOf} and + * {@code lastIndexOf}, and all of the algorithms in the + * {@code Collections} class can be applied to a subList.<p> * * The semantics of the list returned by this method become undefined if * the backing list (i.e., this list) is <i>structurally modified</i> in @@ -725,8 +748,8 @@ public interface List<E> extends Collection<E> { * @param toIndex high endpoint (exclusive) of the subList * @return a view of the specified range within this list * @throws IndexOutOfBoundsException for an illegal endpoint index value - * (<tt>fromIndex < 0 || toIndex > size || - * fromIndex > toIndex</tt>) + * ({@code fromIndex < 0 || toIndex > size || + * fromIndex > toIndex}) */ List<E> subList(int fromIndex, int toIndex); @@ -739,9 +762,22 @@ public interface List<E> extends Collection<E> { * * @implSpec * The default implementation creates a - * <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator - * from the list's {@code Iterator}. The spliterator inherits the - * <em>fail-fast</em> properties of the list's iterator. + * <em><a href="Spliterator.html#binding">late-binding</a></em> + * spliterator as follows: + * <ul> + * <li>If the list is an instance of {@link RandomAccess} then the default + * implementation creates a spliterator that traverses elements by + * invoking the method {@link List#get}. If such invocation results or + * would result in an {@code IndexOutOfBoundsException} then the + * spliterator will <em>fail-fast</em> and throw a + * {@code ConcurrentModificationException}. + * If the list is also an instance of {@link AbstractList} then the + * spliterator will use the list's {@link AbstractList#modCount modCount} + * field to provide additional <em>fail-fast</em> behavior. + * <li>Otherwise, the default implementation creates a spliterator from the + * list's {@code Iterator}. The spliterator inherits the + * <em>fail-fast</em> of the list's iterator. + * </ul> * * @implNote * The created {@code Spliterator} additionally reports @@ -752,6 +788,274 @@ public interface List<E> extends Collection<E> { */ @Override default Spliterator<E> spliterator() { - return Spliterators.spliterator(this, Spliterator.ORDERED); + if (this instanceof RandomAccess) { + return new AbstractList.RandomAccessSpliterator<>(this); + } else { + return Spliterators.spliterator(this, Spliterator.ORDERED); + } + } + + /** + * Returns an immutable list containing zero elements. + * + * See <a href="#immutable">Immutable List Static Factory Methods</a> for details. + * + * @param <E> the {@code List}'s element type + * @return an empty {@code List} + * + * @since 9 + */ + static <E> List<E> of() { + return ImmutableCollections.List0.instance(); + } + + /** + * Returns an immutable list containing one element. + * + * See <a href="#immutable">Immutable List Static Factory Methods</a> for details. + * + * @param <E> the {@code List}'s element type + * @param e1 the single element + * @return a {@code List} containing the specified element + * @throws NullPointerException if the element is {@code null} + * + * @since 9 + */ + static <E> List<E> of(E e1) { + return new ImmutableCollections.List1<>(e1); + } + + /** + * Returns an immutable list containing two elements. + * + * See <a href="#immutable">Immutable List Static Factory Methods</a> for details. + * + * @param <E> the {@code List}'s element type + * @param e1 the first element + * @param e2 the second element + * @return a {@code List} containing the specified elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> List<E> of(E e1, E e2) { + return new ImmutableCollections.List2<>(e1, e2); + } + + /** + * Returns an immutable list containing three elements. + * + * See <a href="#immutable">Immutable List Static Factory Methods</a> for details. + * + * @param <E> the {@code List}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @return a {@code List} containing the specified elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> List<E> of(E e1, E e2, E e3) { + return new ImmutableCollections.ListN<>(e1, e2, e3); + } + + /** + * Returns an immutable list containing four elements. + * + * See <a href="#immutable">Immutable List Static Factory Methods</a> for details. + * + * @param <E> the {@code List}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @return a {@code List} containing the specified elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> List<E> of(E e1, E e2, E e3, E e4) { + return new ImmutableCollections.ListN<>(e1, e2, e3, e4); + } + + /** + * Returns an immutable list containing five elements. + * + * See <a href="#immutable">Immutable List Static Factory Methods</a> for details. + * + * @param <E> the {@code List}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @param e5 the fifth element + * @return a {@code List} containing the specified elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> List<E> of(E e1, E e2, E e3, E e4, E e5) { + return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5); + } + + /** + * Returns an immutable list containing six elements. + * + * See <a href="#immutable">Immutable List Static Factory Methods</a> for details. + * + * @param <E> the {@code List}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @param e5 the fifth element + * @param e6 the sixth element + * @return a {@code List} containing the specified elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6) { + return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5, + e6); + } + + /** + * Returns an immutable list containing seven elements. + * + * See <a href="#immutable">Immutable List Static Factory Methods</a> for details. + * + * @param <E> the {@code List}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @param e5 the fifth element + * @param e6 the sixth element + * @param e7 the seventh element + * @return a {@code List} containing the specified elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { + return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5, + e6, e7); + } + + /** + * Returns an immutable list containing eight elements. + * + * See <a href="#immutable">Immutable List Static Factory Methods</a> for details. + * + * @param <E> the {@code List}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @param e5 the fifth element + * @param e6 the sixth element + * @param e7 the seventh element + * @param e8 the eighth element + * @return a {@code List} containing the specified elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { + return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5, + e6, e7, e8); + } + + /** + * Returns an immutable list containing nine elements. + * + * See <a href="#immutable">Immutable List Static Factory Methods</a> for details. + * + * @param <E> the {@code List}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @param e5 the fifth element + * @param e6 the sixth element + * @param e7 the seventh element + * @param e8 the eighth element + * @param e9 the ninth element + * @return a {@code List} containing the specified elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { + return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5, + e6, e7, e8, e9); + } + + /** + * Returns an immutable list containing ten elements. + * + * See <a href="#immutable">Immutable List Static Factory Methods</a> for details. + * + * @param <E> the {@code List}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @param e5 the fifth element + * @param e6 the sixth element + * @param e7 the seventh element + * @param e8 the eighth element + * @param e9 the ninth element + * @param e10 the tenth element + * @return a {@code List} containing the specified elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) { + return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5, + e6, e7, e8, e9, e10); + } + + /** + * Returns an immutable list containing an arbitrary number of elements. + * See <a href="#immutable">Immutable List Static Factory Methods</a> for details. + * + * @apiNote + * This method also accepts a single array as an argument. The element type of + * the resulting list will be the component type of the array, and the size of + * the list will be equal to the length of the array. To create a list with + * a single element that is an array, do the following: + * + * <pre>{@code + * String[] array = ... ; + * List<String[]> list = List.<String[]>of(array); + * }</pre> + * + * This will cause the {@link List#of(Object) List.of(E)} method + * to be invoked instead. + * + * @param <E> the {@code List}'s element type + * @param elements the elements to be contained in the list + * @return a {@code List} containing the specified elements + * @throws NullPointerException if an element is {@code null} or if the array is {@code null} + * + * @since 9 + */ + @SafeVarargs + @SuppressWarnings("varargs") + static <E> List<E> of(E... elements) { + switch (elements.length) { // implicit null check of elements + case 0: + return ImmutableCollections.List0.instance(); + case 1: + return new ImmutableCollections.List1<>(elements[0]); + case 2: + return new ImmutableCollections.List2<>(elements[0], elements[1]); + default: + return new ImmutableCollections.ListN<>(elements); + } } } diff --git a/ojluni/src/main/java/java/util/ListIterator.java b/ojluni/src/main/java/java/util/ListIterator.java index 85a2f25b18..6ad98fe3fa 100644 --- a/ojluni/src/main/java/java/util/ListIterator.java +++ b/ojluni/src/main/java/java/util/ListIterator.java @@ -46,7 +46,7 @@ package java.util; * {@link #previous()}. * * <p>This interface is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch diff --git a/ojluni/src/main/java/java/util/Locale.java b/ojluni/src/main/java/java/util/Locale.java index 3908fa3d5a..1ce4a20248 100644 --- a/ojluni/src/main/java/java/util/Locale.java +++ b/ojluni/src/main/java/java/util/Locale.java @@ -41,6 +41,7 @@ package java.util; +import com.android.icu.util.LocaleNative; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -524,8 +525,8 @@ import sun.util.locale.ParseStatus; * <td><a href="http://site.icu-project.org/download/60">ICU 60.2</a></td> * <td><a href="http://cldr.unicode.org/index/downloads/cldr-32">CLDR 32.0.1</a></td> * <td><a href="http://www.unicode.org/versions/Unicode10.0.0/">Unicode 10.0</a></td></tr> - * <tr><td>Android Q</td> - * <td><a href="http://site.icu-project.org/download/63">ICU 63.1</a></td> + * <tr><td>Android 10.0 (Q)</td> + * <td><a href="http://site.icu-project.org/download/63">ICU 63.2</a></td> * <td><a href="http://cldr.unicode.org/index/downloads/cldr-34">CLDR 34</a></td> * <td><a href="http://www.unicode.org/versions/Unicode11.0.0/">Unicode 11.0</a></td></tr> * </table> @@ -1874,9 +1875,9 @@ public final class Locale implements Cloneable, Serializable { // TODO: We need a new hack or a complete fix for http://b/8049507 --- We would // cover the frameworks' tracks when they were using "tl" instead of "fil". - String result = ICU.getDisplayLanguage(this, locale); + String result = LocaleNative.getDisplayLanguage(this, locale); if (result == null) { // TODO: do we need to do this, or does ICU do it for us? - result = ICU.getDisplayLanguage(this, Locale.getDefault()); + result = LocaleNative.getDisplayLanguage(this, Locale.getDefault()); } return result; } @@ -1949,9 +1950,9 @@ public final class Locale implements Cloneable, Serializable { return ""; } - String result = ICU.getDisplayScript(this, inLocale); + String result = LocaleNative.getDisplayScript(this, inLocale); if (result == null) { // TODO: do we need to do this, or does ICU do it for us? - result = ICU.getDisplayScript(this, Locale.getDefault(Category.DISPLAY)); + result = LocaleNative.getDisplayScript(this, Locale.getDefault(Category.DISPLAY)); } return result; @@ -2043,9 +2044,9 @@ public final class Locale implements Cloneable, Serializable { return countryCode; } - String result = ICU.getDisplayCountry(this, locale); + String result = LocaleNative.getDisplayCountry(this, locale); if (result == null) { // TODO: do we need to do this, or does ICU do it for us? - result = ICU.getDisplayCountry(this, Locale.getDefault()); + result = LocaleNative.getDisplayCountry(this, Locale.getDefault()); } return result; } @@ -2154,9 +2155,9 @@ public final class Locale implements Cloneable, Serializable { return variantCode; } - String result = ICU.getDisplayVariant(this, inLocale); + String result = LocaleNative.getDisplayVariant(this, inLocale); if (result == null) { // TODO: do we need to do this, or does ICU do it for us? - result = ICU.getDisplayVariant(this, Locale.getDefault()); + result = LocaleNative.getDisplayVariant(this, Locale.getDefault()); } // The "old style" locale constructors allow us to pass in variants that aren't @@ -2349,7 +2350,7 @@ public final class Locale implements Cloneable, Serializable { * <li>{@code new Locale("en").getDisplayName(Locale.US)} -> {@code English} * <li>{@code new Locale("en", "US").getDisplayName(Locale.US)} -> {@code English (United States)} * <li>{@code new Locale("en", "US", "POSIX").getDisplayName(Locale.US)} -> {@code English (United States,Computer)} - * <li>{@code Locale.fromLanguageTag("zh-Hant-CN").getDisplayName(Locale.US)} -> {@code Chinese (Traditional Han,China)} + * <li>{@code Locale.forLanguageTag("zh-Hant-CN").getDisplayName(Locale.US)} -> {@code Chinese (Traditional Han,China)} * <li>{@code new Locale("en").getDisplayName(Locale.FRANCE)} -> {@code anglais} * <li>{@code new Locale("en", "US").getDisplayName(Locale.FRANCE)} -> {@code anglais (États-Unis)} * <li>{@code new Locale("en", "US", "POSIX").getDisplayName(Locale.FRANCE)} -> {@code anglais (États-Unis,informatique)}. diff --git a/ojluni/src/main/java/java/util/Map.java b/ojluni/src/main/java/java/util/Map.java index 2715b15076..ed365ec20e 100644 --- a/ojluni/src/main/java/java/util/Map.java +++ b/ojluni/src/main/java/java/util/Map.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.io.Serializable; -// Android-changed: removed docs for removed OpenJDK 9 Immutable Map static methods // Android-changed: removed link to collections framework docs /** * An object that maps keys to values. A map cannot contain duplicate keys; @@ -112,6 +111,35 @@ import java.io.Serializable; * Implementations may optionally handle the self-referential scenario, however * most current implementations do not do so. * + * <h2><a id="immutable">Immutable Map Static Factory Methods</a></h2> + * <p>The {@link Map#of() Map.of()} and + * {@link Map#ofEntries(Map.Entry...) Map.ofEntries()} + * static factory methods provide a convenient way to create immutable maps. + * The {@code Map} + * instances created by these methods have the following characteristics: + * + * <ul> + * <li>They are <em>structurally immutable</em>. Keys and values cannot be added, + * removed, or updated. Calling any mutator method will always cause + * {@code UnsupportedOperationException} to be thrown. + * However, if the contained keys or values are themselves mutable, this may cause the + * Map to behave inconsistently or its contents to appear to change. + * <li>They disallow {@code null} keys and values. Attempts to create them with + * {@code null} keys or values result in {@code NullPointerException}. + * <li>They are serializable if all keys and values are serializable. + * <li>They reject duplicate keys at creation time. Duplicate keys + * passed to a static factory method result in {@code IllegalArgumentException}. + * <li>The iteration order of mappings is unspecified and is subject to change. + * <li>They are <a href="../lang/doc-files/ValueBased.html">value-based</a>. + * Callers should make no assumptions about the identity of the returned instances. + * Factories are free to create new instances or reuse existing ones. Therefore, + * identity-sensitive operations on these instances (reference equality ({@code ==}), + * identity hash code, and synchronization) are unreliable and should be avoided. + * <li>They are serialized as specified on the + * <a href="{@docRoot}/serialized-form.html#java.util.CollSer">Serialized Form</a> + * page. + * </ul> + * * @param <K> the type of keys maintained by this map * @param <V> the type of mapped values * @@ -1245,5 +1273,384 @@ public interface Map<K, V> { return newValue; } - // Android-removed: OpenJDK 9 Immutable Map static methods + /** + * Returns an immutable map containing zero mappings. + * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @return an empty {@code Map} + * + * @since 9 + */ + static <K, V> Map<K, V> of() { + return ImmutableCollections.Map0.instance(); + } + + /** + * Returns an immutable map containing a single mapping. + * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @param k1 the mapping's key + * @param v1 the mapping's value + * @return a {@code Map} containing the specified mapping + * @throws NullPointerException if the key or the value is {@code null} + * + * @since 9 + */ + static <K, V> Map<K, V> of(K k1, V v1) { + return new ImmutableCollections.Map1<>(k1, v1); + } + + /** + * Returns an immutable map containing two mappings. + * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @param k1 the first mapping's key + * @param v1 the first mapping's value + * @param k2 the second mapping's key + * @param v2 the second mapping's value + * @return a {@code Map} containing the specified mappings + * @throws IllegalArgumentException if the keys are duplicates + * @throws NullPointerException if any key or value is {@code null} + * + * @since 9 + */ + static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2) { + return new ImmutableCollections.MapN<>(k1, v1, k2, v2); + } + + /** + * Returns an immutable map containing three mappings. + * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @param k1 the first mapping's key + * @param v1 the first mapping's value + * @param k2 the second mapping's key + * @param v2 the second mapping's value + * @param k3 the third mapping's key + * @param v3 the third mapping's value + * @return a {@code Map} containing the specified mappings + * @throws IllegalArgumentException if there are any duplicate keys + * @throws NullPointerException if any key or value is {@code null} + * + * @since 9 + */ + static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) { + return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3); + } + + /** + * Returns an immutable map containing four mappings. + * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @param k1 the first mapping's key + * @param v1 the first mapping's value + * @param k2 the second mapping's key + * @param v2 the second mapping's value + * @param k3 the third mapping's key + * @param v3 the third mapping's value + * @param k4 the fourth mapping's key + * @param v4 the fourth mapping's value + * @return a {@code Map} containing the specified mappings + * @throws IllegalArgumentException if there are any duplicate keys + * @throws NullPointerException if any key or value is {@code null} + * + * @since 9 + */ + static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4); + } + + /** + * Returns an immutable map containing five mappings. + * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @param k1 the first mapping's key + * @param v1 the first mapping's value + * @param k2 the second mapping's key + * @param v2 the second mapping's value + * @param k3 the third mapping's key + * @param v3 the third mapping's value + * @param k4 the fourth mapping's key + * @param v4 the fourth mapping's value + * @param k5 the fifth mapping's key + * @param v5 the fifth mapping's value + * @return a {@code Map} containing the specified mappings + * @throws IllegalArgumentException if there are any duplicate keys + * @throws NullPointerException if any key or value is {@code null} + * + * @since 9 + */ + static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5); + } + + /** + * Returns an immutable map containing six mappings. + * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @param k1 the first mapping's key + * @param v1 the first mapping's value + * @param k2 the second mapping's key + * @param v2 the second mapping's value + * @param k3 the third mapping's key + * @param v3 the third mapping's value + * @param k4 the fourth mapping's key + * @param v4 the fourth mapping's value + * @param k5 the fifth mapping's key + * @param v5 the fifth mapping's value + * @param k6 the sixth mapping's key + * @param v6 the sixth mapping's value + * @return a {@code Map} containing the specified mappings + * @throws IllegalArgumentException if there are any duplicate keys + * @throws NullPointerException if any key or value is {@code null} + * + * @since 9 + */ + static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, + K k6, V v6) { + return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, + k6, v6); + } + + /** + * Returns an immutable map containing seven mappings. + * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @param k1 the first mapping's key + * @param v1 the first mapping's value + * @param k2 the second mapping's key + * @param v2 the second mapping's value + * @param k3 the third mapping's key + * @param v3 the third mapping's value + * @param k4 the fourth mapping's key + * @param v4 the fourth mapping's value + * @param k5 the fifth mapping's key + * @param v5 the fifth mapping's value + * @param k6 the sixth mapping's key + * @param v6 the sixth mapping's value + * @param k7 the seventh mapping's key + * @param v7 the seventh mapping's value + * @return a {@code Map} containing the specified mappings + * @throws IllegalArgumentException if there are any duplicate keys + * @throws NullPointerException if any key or value is {@code null} + * + * @since 9 + */ + static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, + K k6, V v6, K k7, V v7) { + return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, + k6, v6, k7, v7); + } + + /** + * Returns an immutable map containing eight mappings. + * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @param k1 the first mapping's key + * @param v1 the first mapping's value + * @param k2 the second mapping's key + * @param v2 the second mapping's value + * @param k3 the third mapping's key + * @param v3 the third mapping's value + * @param k4 the fourth mapping's key + * @param v4 the fourth mapping's value + * @param k5 the fifth mapping's key + * @param v5 the fifth mapping's value + * @param k6 the sixth mapping's key + * @param v6 the sixth mapping's value + * @param k7 the seventh mapping's key + * @param v7 the seventh mapping's value + * @param k8 the eighth mapping's key + * @param v8 the eighth mapping's value + * @return a {@code Map} containing the specified mappings + * @throws IllegalArgumentException if there are any duplicate keys + * @throws NullPointerException if any key or value is {@code null} + * + * @since 9 + */ + static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, + K k6, V v6, K k7, V v7, K k8, V v8) { + return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, + k6, v6, k7, v7, k8, v8); + } + + /** + * Returns an immutable map containing nine mappings. + * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @param k1 the first mapping's key + * @param v1 the first mapping's value + * @param k2 the second mapping's key + * @param v2 the second mapping's value + * @param k3 the third mapping's key + * @param v3 the third mapping's value + * @param k4 the fourth mapping's key + * @param v4 the fourth mapping's value + * @param k5 the fifth mapping's key + * @param v5 the fifth mapping's value + * @param k6 the sixth mapping's key + * @param v6 the sixth mapping's value + * @param k7 the seventh mapping's key + * @param v7 the seventh mapping's value + * @param k8 the eighth mapping's key + * @param v8 the eighth mapping's value + * @param k9 the ninth mapping's key + * @param v9 the ninth mapping's value + * @return a {@code Map} containing the specified mappings + * @throws IllegalArgumentException if there are any duplicate keys + * @throws NullPointerException if any key or value is {@code null} + * + * @since 9 + */ + static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, + K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) { + return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, + k6, v6, k7, v7, k8, v8, k9, v9); + } + + /** + * Returns an immutable map containing ten mappings. + * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @param k1 the first mapping's key + * @param v1 the first mapping's value + * @param k2 the second mapping's key + * @param v2 the second mapping's value + * @param k3 the third mapping's key + * @param v3 the third mapping's value + * @param k4 the fourth mapping's key + * @param v4 the fourth mapping's value + * @param k5 the fifth mapping's key + * @param v5 the fifth mapping's value + * @param k6 the sixth mapping's key + * @param v6 the sixth mapping's value + * @param k7 the seventh mapping's key + * @param v7 the seventh mapping's value + * @param k8 the eighth mapping's key + * @param v8 the eighth mapping's value + * @param k9 the ninth mapping's key + * @param v9 the ninth mapping's value + * @param k10 the tenth mapping's key + * @param v10 the tenth mapping's value + * @return a {@code Map} containing the specified mappings + * @throws IllegalArgumentException if there are any duplicate keys + * @throws NullPointerException if any key or value is {@code null} + * + * @since 9 + */ + static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, + K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) { + return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, + k6, v6, k7, v7, k8, v8, k9, v9, k10, v10); + } + + /** + * Returns an immutable map containing keys and values extracted from the given entries. + * The entries themselves are not stored in the map. + * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. + * + * @apiNote + * It is convenient to create the map entries using the {@link Map#entry Map.entry()} method. + * For example, + * + * <pre>{@code + * import static java.util.Map.entry; + * + * Map<Integer,String> map = Map.ofEntries( + * entry(1, "a"), + * entry(2, "b"), + * entry(3, "c"), + * ... + * entry(26, "z")); + * }</pre> + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @param entries {@code Map.Entry}s containing the keys and values from which the map is populated + * @return a {@code Map} containing the specified mappings + * @throws IllegalArgumentException if there are any duplicate keys + * @throws NullPointerException if any entry, key, or value is {@code null}, or if + * the {@code entries} array is {@code null} + * + * @see Map#entry Map.entry() + * @since 9 + */ + @SafeVarargs + @SuppressWarnings("varargs") + static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) { + if (entries.length == 0) { // implicit null check of entries + return ImmutableCollections.Map0.instance(); + } else if (entries.length == 1) { + return new ImmutableCollections.Map1<>(entries[0].getKey(), + entries[0].getValue()); + } else { + Object[] kva = new Object[entries.length << 1]; + int a = 0; + for (Entry<? extends K, ? extends V> entry : entries) { + kva[a++] = entry.getKey(); + kva[a++] = entry.getValue(); + } + return new ImmutableCollections.MapN<>(kva); + } + } + + /** + * Returns an immutable {@link Entry} containing the given key and value. + * These entries are suitable for populating {@code Map} instances using the + * {@link Map#ofEntries Map.ofEntries()} method. + * The {@code Entry} instances created by this method have the following characteristics: + * + * <ul> + * <li>They disallow {@code null} keys and values. Attempts to create them using a {@code null} + * key or value result in {@code NullPointerException}. + * <li>They are immutable. Calls to {@link Entry#setValue Entry.setValue()} + * on a returned {@code Entry} result in {@code UnsupportedOperationException}. + * <li>They are not serializable. + * <li>They are <a href="../lang/doc-files/ValueBased.html">value-based</a>. + * Callers should make no assumptions about the identity of the returned instances. + * This method is free to create new instances or reuse existing ones. Therefore, + * identity-sensitive operations on these instances (reference equality ({@code ==}), + * identity hash code, and synchronization) are unreliable and should be avoided. + * </ul> + * + * @apiNote + * For a serializable {@code Entry}, see {@link AbstractMap.SimpleEntry} or + * {@link AbstractMap.SimpleImmutableEntry}. + * + * @param <K> the key's type + * @param <V> the value's type + * @param k the key + * @param v the value + * @return an {@code Entry} containing the specified key and value + * @throws NullPointerException if the key or value is {@code null} + * + * @see Map#ofEntries Map.ofEntries() + * @since 9 + */ + static <K, V> Entry<K, V> entry(K k, V v) { + // KeyValueHolder checks for nulls + return new KeyValueHolder<>(k, v); + } } diff --git a/ojluni/src/main/java/java/util/Objects.java b/ojluni/src/main/java/java/util/Objects.java index e526079e37..1f7648796f 100644 --- a/ojluni/src/main/java/java/util/Objects.java +++ b/ojluni/src/main/java/java/util/Objects.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,30 @@ package java.util; +import jdk.internal.util.Preconditions; + import java.util.function.Supplier; /** * This class consists of {@code static} utility methods for operating - * on objects. These utilities include {@code null}-safe or {@code - * null}-tolerant methods for computing the hash code of an object, - * returning a string for an object, and comparing two objects. + * on objects, or checking certain conditions before operation. These utilities + * include {@code null}-safe or {@code null}-tolerant methods for computing the + * hash code of an object, returning a string for an object, comparing two + * objects, and checking if indexes or sub-range values are out-of-bounds. + * + * @apiNote + * Static methods such as {@link Objects#checkIndex}, + * {@link Objects#checkFromToIndex}, and {@link Objects#checkFromIndexSize} are + * provided for the convenience of checking if values corresponding to indexes + * and sub-ranges are out-of-bounds. + * Variations of these static methods support customization of the runtime + * exception, and corresponding exception detail message, that is thrown when + * values are out-of-bounds. Such methods accept a functional interface + * argument, instances of {@code BiFunction}, that maps out-of-bound values to a + * runtime exception. Care should be taken when using such methods in + * combination with an argument that is a lambda expression, method reference or + * class that capture values. In such cases the cost of capture, related to + * functional interface allocation, may exceed the cost of checking bounds. * * @since 1.7 */ @@ -266,6 +283,44 @@ public final class Objects { } /** + * Returns the first argument if it is non-{@code null} and + * otherwise returns the non-{@code null} second argument. + * + * @param obj an object + * @param defaultObj a non-{@code null} object to return if the first argument + * is {@code null} + * @param <T> the type of the reference + * @return the first argument if it is non-{@code null} and + * otherwise the second argument if it is non-{@code null} + * @throws NullPointerException if both {@code obj} is null and + * {@code defaultObj} is {@code null} + * @since 9 + */ + public static <T> T requireNonNullElse(T obj, T defaultObj) { + return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj"); + } + + /** + * Returns the first argument if it is non-{@code null} and otherwise + * returns the non-{@code null} value of {@code supplier.get()}. + * + * @param obj an object + * @param supplier of a non-{@code null} object to return if the first argument + * is {@code null} + * @param <T> the type of the first argument and return type + * @return the first argument if it is non-{@code null} and otherwise + * the value from {@code supplier.get()} if it is non-{@code null} + * @throws NullPointerException if both {@code obj} is null and + * either the {@code supplier} is {@code null} or + * the {@code supplier.get()} value is {@code null} + * @since 9 + */ + public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier) { + return (obj != null) ? obj + : requireNonNull(requireNonNull(supplier, "supplier").get(), "supplier.get()"); + } + + /** * Checks that the specified object reference is not {@code null} and * throws a customized {@link NullPointerException} if it is. * @@ -287,7 +342,86 @@ public final class Objects { */ public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier) { if (obj == null) - throw new NullPointerException(messageSupplier.get()); + throw new NullPointerException(messageSupplier == null ? + null : messageSupplier.get()); return obj; } + + /** + * Checks if the {@code index} is within the bounds of the range from + * {@code 0} (inclusive) to {@code length} (exclusive). + * + * <p>The {@code index} is defined to be out-of-bounds if any of the + * following inequalities is true: + * <ul> + * <li>{@code index < 0}</li> + * <li>{@code index >= length}</li> + * <li>{@code length < 0}, which is implied from the former inequalities</li> + * </ul> + * + * @param index the index + * @param length the upper-bound (exclusive) of the range + * @return {@code index} if it is within bounds of the range + * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds + * @since 9 + */ + // Android-removed: @ForceInline is an unsupported attribute. + //@ForceInline + public static + int checkIndex(int index, int length) { + return Preconditions.checkIndex(index, length, null); + } + + /** + * Checks if the sub-range from {@code fromIndex} (inclusive) to + * {@code toIndex} (exclusive) is within the bounds of range from {@code 0} + * (inclusive) to {@code length} (exclusive). + * + * <p>The sub-range is defined to be out-of-bounds if any of the following + * inequalities is true: + * <ul> + * <li>{@code fromIndex < 0}</li> + * <li>{@code fromIndex > toIndex}</li> + * <li>{@code toIndex > length}</li> + * <li>{@code length < 0}, which is implied from the former inequalities</li> + * </ul> + * + * @param fromIndex the lower-bound (inclusive) of the sub-range + * @param toIndex the upper-bound (exclusive) of the sub-range + * @param length the upper-bound (exclusive) the range + * @return {@code fromIndex} if the sub-range within bounds of the range + * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds + * @since 9 + */ + public static + int checkFromToIndex(int fromIndex, int toIndex, int length) { + return Preconditions.checkFromToIndex(fromIndex, toIndex, length, null); + } + + /** + * Checks if the sub-range from {@code fromIndex} (inclusive) to + * {@code fromIndex + size} (exclusive) is within the bounds of range from + * {@code 0} (inclusive) to {@code length} (exclusive). + * + * <p>The sub-range is defined to be out-of-bounds if any of the following + * inequalities is true: + * <ul> + * <li>{@code fromIndex < 0}</li> + * <li>{@code size < 0}</li> + * <li>{@code fromIndex + size > length}, taking into account integer overflow</li> + * <li>{@code length < 0}, which is implied from the former inequalities</li> + * </ul> + * + * @param fromIndex the lower-bound (inclusive) of the sub-interval + * @param size the size of the sub-range + * @param length the upper-bound (exclusive) of the range + * @return {@code fromIndex} if the sub-range within bounds of the range + * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds + * @since 9 + */ + public static + int checkFromIndexSize(int fromIndex, int size, int length) { + return Preconditions.checkFromIndexSize(fromIndex, size, length, null); + } + } diff --git a/ojluni/src/main/java/java/util/PriorityQueue.java b/ojluni/src/main/java/java/util/PriorityQueue.java index 90e59d16c6..7c929bda6d 100644 --- a/ojluni/src/main/java/java/util/PriorityQueue.java +++ b/ojluni/src/main/java/java/util/PriorityQueue.java @@ -72,7 +72,7 @@ import java.util.function.Consumer; * ({@code peek}, {@code element}, and {@code size}). * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @since 1.5 diff --git a/ojluni/src/main/java/java/util/RandomAccess.java b/ojluni/src/main/java/java/util/RandomAccess.java index 6b7e45389c..09ce29edce 100644 --- a/ojluni/src/main/java/java/util/RandomAccess.java +++ b/ojluni/src/main/java/java/util/RandomAccess.java @@ -59,7 +59,7 @@ package java.util; * </pre> * * <p>This interface is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @since 1.4 diff --git a/ojluni/src/main/java/java/util/Set.java b/ojluni/src/main/java/java/util/Set.java index ee22fcaef5..0499ea309d 100644 --- a/ojluni/src/main/java/java/util/Set.java +++ b/ojluni/src/main/java/java/util/Set.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,16 +27,16 @@ package java.util; /** * A collection that contains no duplicate elements. More formally, sets - * contain no pair of elements <code>e1</code> and <code>e2</code> such that - * <code>e1.equals(e2)</code>, and at most one null element. As implied by + * contain no pair of elements {@code e1} and {@code e2} such that + * {@code e1.equals(e2)}, and at most one null element. As implied by * its name, this interface models the mathematical <i>set</i> abstraction. * - * <p>The <tt>Set</tt> interface places additional stipulations, beyond those - * inherited from the <tt>Collection</tt> interface, on the contracts of all - * constructors and on the contracts of the <tt>add</tt>, <tt>equals</tt> and - * <tt>hashCode</tt> methods. Declarations for other inherited methods are + * <p>The {@code Set} interface places additional stipulations, beyond those + * inherited from the {@code Collection} interface, on the contracts of all + * constructors and on the contracts of the {@code add}, {@code equals} and + * {@code hashCode} methods. Declarations for other inherited methods are * also included here for convenience. (The specifications accompanying these - * declarations have been tailored to the <tt>Set</tt> interface, but they do + * declarations have been tailored to the {@code Set} interface, but they do * not contain any additional stipulations.) * * <p>The additional stipulation on constructors is, not surprisingly, @@ -45,7 +45,7 @@ package java.util; * * <p>Note: Great care must be exercised if mutable objects are used as set * elements. The behavior of a set is not specified if the value of an object - * is changed in a manner that affects <tt>equals</tt> comparisons while the + * is changed in a manner that affects {@code equals} comparisons while the * object is an element in the set. A special case of this prohibition is * that it is not permissible for a set to contain itself as an element. * @@ -53,7 +53,7 @@ package java.util; * they may contain. For example, some implementations prohibit null elements, * and some have restrictions on the types of their elements. Attempting to * add an ineligible element throws an unchecked exception, typically - * <tt>NullPointerException</tt> or <tt>ClassCastException</tt>. Attempting + * {@code NullPointerException} or {@code ClassCastException}. Attempting * to query the presence of an ineligible element may throw an exception, * or it may simply return false; some implementations will exhibit the former * behavior and some will exhibit the latter. More generally, attempting an @@ -63,8 +63,35 @@ package java.util; * Such exceptions are marked as "optional" in the specification for this * interface. * + * <h2><a id="immutable">Immutable Set Static Factory Methods</a></h2> + * <p>The {@link Set#of(Object...) Set.of()} static factory methods + * provide a convenient way to create immutable sets. The {@code Set} + * instances created by these methods have the following characteristics: + * + * <ul> + * <li>They are <em>structurally immutable</em>. Elements cannot be added or + * removed. Calling any mutator method will always cause + * {@code UnsupportedOperationException} to be thrown. + * However, if the contained elements are themselves mutable, this may cause the + * Set to behave inconsistently or its contents to appear to change. + * <li>They disallow {@code null} elements. Attempts to create them with + * {@code null} elements result in {@code NullPointerException}. + * <li>They are serializable if all elements are serializable. + * <li>They reject duplicate elements at creation time. Duplicate elements + * passed to a static factory method result in {@code IllegalArgumentException}. + * <li>The iteration order of set elements is unspecified and is subject to change. + * <li>They are <a href="../lang/doc-files/ValueBased.html">value-based</a>. + * Callers should make no assumptions about the identity of the returned instances. + * Factories are free to create new instances or reuse existing ones. Therefore, + * identity-sensitive operations on these instances (reference equality ({@code ==}), + * identity hash code, and synchronization) are unreliable and should be avoided. + * <li>They are serialized as specified on the + * <a href="{@docRoot}/serialized-form.html#java.util.CollSer">Serialized Form</a> + * page. + * </ul> + * * <p>This interface is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <E> the type of elements maintained by this set @@ -87,28 +114,28 @@ public interface Set<E> extends Collection<E> { /** * Returns the number of elements in this set (its cardinality). If this - * set contains more than <tt>Integer.MAX_VALUE</tt> elements, returns - * <tt>Integer.MAX_VALUE</tt>. + * set contains more than {@code Integer.MAX_VALUE} elements, returns + * {@code Integer.MAX_VALUE}. * * @return the number of elements in this set (its cardinality) */ int size(); /** - * Returns <tt>true</tt> if this set contains no elements. + * Returns {@code true} if this set contains no elements. * - * @return <tt>true</tt> if this set contains no elements + * @return {@code true} if this set contains no elements */ boolean isEmpty(); /** - * Returns <tt>true</tt> if this set contains the specified element. - * More formally, returns <tt>true</tt> if and only if this set - * contains an element <tt>e</tt> such that - * <tt>(o==null ? e==null : o.equals(e))</tt>. + * Returns {@code true} if this set contains the specified element. + * More formally, returns {@code true} if and only if this set + * contains an element {@code e} such that + * {@code Objects.equals(o, e)}. * * @param o element whose presence in this set is to be tested - * @return <tt>true</tt> if this set contains the specified element + * @return {@code true} if this set contains the specified element * @throws ClassCastException if the type of the specified element * is incompatible with this set * (<a href="Collection.html#optional-restrictions">optional</a>) @@ -155,7 +182,7 @@ public interface Set<E> extends Collection<E> { * <p>If this set fits in the specified array with room to spare * (i.e., the array has more elements than this set), the element in * the array immediately following the end of the set is set to - * <tt>null</tt>. (This is useful in determining the length of this + * {@code null}. (This is useful in determining the length of this * set <i>only</i> if the caller knows that this set does not contain * any null elements.) * @@ -168,15 +195,15 @@ public interface Set<E> extends Collection<E> { * precise control over the runtime type of the output array, and may, * under certain circumstances, be used to save allocation costs. * - * <p>Suppose <tt>x</tt> is a set known to contain only strings. + * <p>Suppose {@code x} is a set known to contain only strings. * The following code can be used to dump the set into a newly allocated - * array of <tt>String</tt>: + * array of {@code String}: * * <pre> * String[] y = x.toArray(new String[0]);</pre> * - * Note that <tt>toArray(new Object[0])</tt> is identical in function to - * <tt>toArray()</tt>. + * Note that {@code toArray(new Object[0])} is identical in function to + * {@code toArray()}. * * @param a the array into which the elements of this set are to be * stored, if it is big enough; otherwise, a new array of the same @@ -195,25 +222,25 @@ public interface Set<E> extends Collection<E> { /** * Adds the specified element to this set if it is not already present * (optional operation). More formally, adds the specified element - * <tt>e</tt> to this set if the set contains no element <tt>e2</tt> + * {@code e} to this set if the set contains no element {@code e2} * such that - * <tt>(e==null ? e2==null : e.equals(e2))</tt>. + * {@code Objects.equals(e, e2)}. * If this set already contains the element, the call leaves the set - * unchanged and returns <tt>false</tt>. In combination with the + * unchanged and returns {@code false}. In combination with the * restriction on constructors, this ensures that sets never contain * duplicate elements. * * <p>The stipulation above does not imply that sets must accept all * elements; sets may refuse to add any particular element, including - * <tt>null</tt>, and throw an exception, as described in the + * {@code null}, and throw an exception, as described in the * specification for {@link Collection#add Collection.add}. * Individual set implementations should clearly document any * restrictions on the elements that they may contain. * * @param e element to be added to this set - * @return <tt>true</tt> if this set did not already contain the specified + * @return {@code true} if this set did not already contain the specified * element - * @throws UnsupportedOperationException if the <tt>add</tt> operation + * @throws UnsupportedOperationException if the {@code add} operation * is not supported by this set * @throws ClassCastException if the class of the specified element * prevents it from being added to this set @@ -227,23 +254,23 @@ public interface Set<E> extends Collection<E> { /** * Removes the specified element from this set if it is present - * (optional operation). More formally, removes an element <tt>e</tt> + * (optional operation). More formally, removes an element {@code e} * such that - * <tt>(o==null ? e==null : o.equals(e))</tt>, if - * this set contains such an element. Returns <tt>true</tt> if this set + * {@code Objects.equals(o, e)}, if + * this set contains such an element. Returns {@code true} if this set * contained the element (or equivalently, if this set changed as a * result of the call). (This set will not contain the element once the * call returns.) * * @param o object to be removed from this set, if present - * @return <tt>true</tt> if this set contained the specified element + * @return {@code true} if this set contained the specified element * @throws ClassCastException if the type of the specified element * is incompatible with this set * (<a href="Collection.html#optional-restrictions">optional</a>) * @throws NullPointerException if the specified element is null and this * set does not permit null elements * (<a href="Collection.html#optional-restrictions">optional</a>) - * @throws UnsupportedOperationException if the <tt>remove</tt> operation + * @throws UnsupportedOperationException if the {@code remove} operation * is not supported by this set */ boolean remove(Object o); @@ -252,12 +279,12 @@ public interface Set<E> extends Collection<E> { // Bulk Operations /** - * Returns <tt>true</tt> if this set contains all of the elements of the + * Returns {@code true} if this set contains all of the elements of the * specified collection. If the specified collection is also a set, this - * method returns <tt>true</tt> if it is a <i>subset</i> of this set. + * method returns {@code true} if it is a <i>subset</i> of this set. * * @param c collection to be checked for containment in this set - * @return <tt>true</tt> if this set contains all of the elements of the + * @return {@code true} if this set contains all of the elements of the * specified collection * @throws ClassCastException if the types of one or more elements * in the specified collection are incompatible with this @@ -275,15 +302,15 @@ public interface Set<E> extends Collection<E> { /** * Adds all of the elements in the specified collection to this set if * they're not already present (optional operation). If the specified - * collection is also a set, the <tt>addAll</tt> operation effectively + * collection is also a set, the {@code addAll} operation effectively * modifies this set so that its value is the <i>union</i> of the two * sets. The behavior of this operation is undefined if the specified * collection is modified while the operation is in progress. * * @param c collection containing elements to be added to this set - * @return <tt>true</tt> if this set changed as a result of the call + * @return {@code true} if this set changed as a result of the call * - * @throws UnsupportedOperationException if the <tt>addAll</tt> operation + * @throws UnsupportedOperationException if the {@code addAll} operation * is not supported by this set * @throws ClassCastException if the class of an element of the * specified collection prevents it from being added to this set @@ -305,8 +332,8 @@ public interface Set<E> extends Collection<E> { * <i>intersection</i> of the two sets. * * @param c collection containing elements to be retained in this set - * @return <tt>true</tt> if this set changed as a result of the call - * @throws UnsupportedOperationException if the <tt>retainAll</tt> operation + * @return {@code true} if this set changed as a result of the call + * @throws UnsupportedOperationException if the {@code retainAll} operation * is not supported by this set * @throws ClassCastException if the class of an element of this set * is incompatible with the specified collection @@ -327,8 +354,8 @@ public interface Set<E> extends Collection<E> { * the two sets. * * @param c collection containing elements to be removed from this set - * @return <tt>true</tt> if this set changed as a result of the call - * @throws UnsupportedOperationException if the <tt>removeAll</tt> operation + * @return {@code true} if this set changed as a result of the call + * @throws UnsupportedOperationException if the {@code removeAll} operation * is not supported by this set * @throws ClassCastException if the class of an element of this set * is incompatible with the specified collection @@ -346,7 +373,7 @@ public interface Set<E> extends Collection<E> { * Removes all of the elements from this set (optional operation). * The set will be empty after this call returns. * - * @throws UnsupportedOperationException if the <tt>clear</tt> method + * @throws UnsupportedOperationException if the {@code clear} method * is not supported by this set */ void clear(); @@ -356,7 +383,7 @@ public interface Set<E> extends Collection<E> { /** * Compares the specified object with this set for equality. Returns - * <tt>true</tt> if the specified object is also a set, the two sets + * {@code true} if the specified object is also a set, the two sets * have the same size, and every member of the specified set is * contained in this set (or equivalently, every member of this set is * contained in the specified set). This definition ensures that the @@ -364,17 +391,17 @@ public interface Set<E> extends Collection<E> { * set interface. * * @param o object to be compared for equality with this set - * @return <tt>true</tt> if the specified object is equal to this set + * @return {@code true} if the specified object is equal to this set */ boolean equals(Object o); /** * Returns the hash code value for this set. The hash code of a set is * defined to be the sum of the hash codes of the elements in the set, - * where the hash code of a <tt>null</tt> element is defined to be zero. - * This ensures that <tt>s1.equals(s2)</tt> implies that - * <tt>s1.hashCode()==s2.hashCode()</tt> for any two sets <tt>s1</tt> - * and <tt>s2</tt>, as required by the general contract of + * where the hash code of a {@code null} element is defined to be zero. + * This ensures that {@code s1.equals(s2)} implies that + * {@code s1.hashCode()==s2.hashCode()} for any two sets {@code s1} + * and {@code s2}, as required by the general contract of * {@link Object#hashCode}. * * @return the hash code value for this set @@ -410,4 +437,267 @@ public interface Set<E> extends Collection<E> { default Spliterator<E> spliterator() { return Spliterators.spliterator(this, Spliterator.DISTINCT); } + + /** + * Returns an immutable set containing zero elements. + * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details. + * + * @param <E> the {@code Set}'s element type + * @return an empty {@code Set} + * + * @since 9 + */ + static <E> Set<E> of() { + return ImmutableCollections.Set0.instance(); + } + + /** + * Returns an immutable set containing one element. + * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details. + * + * @param <E> the {@code Set}'s element type + * @param e1 the single element + * @return a {@code Set} containing the specified element + * @throws NullPointerException if the element is {@code null} + * + * @since 9 + */ + static <E> Set<E> of(E e1) { + return new ImmutableCollections.Set1<>(e1); + } + + /** + * Returns an immutable set containing two elements. + * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details. + * + * @param <E> the {@code Set}'s element type + * @param e1 the first element + * @param e2 the second element + * @return a {@code Set} containing the specified elements + * @throws IllegalArgumentException if the elements are duplicates + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> Set<E> of(E e1, E e2) { + return new ImmutableCollections.Set2<>(e1, e2); + } + + /** + * Returns an immutable set containing three elements. + * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details. + * + * @param <E> the {@code Set}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @return a {@code Set} containing the specified elements + * @throws IllegalArgumentException if there are any duplicate elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> Set<E> of(E e1, E e2, E e3) { + return new ImmutableCollections.SetN<>(e1, e2, e3); + } + + /** + * Returns an immutable set containing four elements. + * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details. + * + * @param <E> the {@code Set}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @return a {@code Set} containing the specified elements + * @throws IllegalArgumentException if there are any duplicate elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> Set<E> of(E e1, E e2, E e3, E e4) { + return new ImmutableCollections.SetN<>(e1, e2, e3, e4); + } + + /** + * Returns an immutable set containing five elements. + * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details. + * + * @param <E> the {@code Set}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @param e5 the fifth element + * @return a {@code Set} containing the specified elements + * @throws IllegalArgumentException if there are any duplicate elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5) { + return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5); + } + + /** + * Returns an immutable set containing six elements. + * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details. + * + * @param <E> the {@code Set}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @param e5 the fifth element + * @param e6 the sixth element + * @return a {@code Set} containing the specified elements + * @throws IllegalArgumentException if there are any duplicate elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6) { + return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5, + e6); + } + + /** + * Returns an immutable set containing seven elements. + * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details. + * + * @param <E> the {@code Set}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @param e5 the fifth element + * @param e6 the sixth element + * @param e7 the seventh element + * @return a {@code Set} containing the specified elements + * @throws IllegalArgumentException if there are any duplicate elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { + return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5, + e6, e7); + } + + /** + * Returns an immutable set containing eight elements. + * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details. + * + * @param <E> the {@code Set}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @param e5 the fifth element + * @param e6 the sixth element + * @param e7 the seventh element + * @param e8 the eighth element + * @return a {@code Set} containing the specified elements + * @throws IllegalArgumentException if there are any duplicate elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { + return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5, + e6, e7, e8); + } + + /** + * Returns an immutable set containing nine elements. + * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details. + * + * @param <E> the {@code Set}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @param e5 the fifth element + * @param e6 the sixth element + * @param e7 the seventh element + * @param e8 the eighth element + * @param e9 the ninth element + * @return a {@code Set} containing the specified elements + * @throws IllegalArgumentException if there are any duplicate elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { + return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5, + e6, e7, e8, e9); + } + + /** + * Returns an immutable set containing ten elements. + * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details. + * + * @param <E> the {@code Set}'s element type + * @param e1 the first element + * @param e2 the second element + * @param e3 the third element + * @param e4 the fourth element + * @param e5 the fifth element + * @param e6 the sixth element + * @param e7 the seventh element + * @param e8 the eighth element + * @param e9 the ninth element + * @param e10 the tenth element + * @return a {@code Set} containing the specified elements + * @throws IllegalArgumentException if there are any duplicate elements + * @throws NullPointerException if an element is {@code null} + * + * @since 9 + */ + static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) { + return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5, + e6, e7, e8, e9, e10); + } + + /** + * Returns an immutable set containing an arbitrary number of elements. + * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details. + * + * @apiNote + * This method also accepts a single array as an argument. The element type of + * the resulting set will be the component type of the array, and the size of + * the set will be equal to the length of the array. To create a set with + * a single element that is an array, do the following: + * + * <pre>{@code + * String[] array = ... ; + * Set<String[]> list = Set.<String[]>of(array); + * }</pre> + * + * This will cause the {@link Set#of(Object) Set.of(E)} method + * to be invoked instead. + * + * @param <E> the {@code Set}'s element type + * @param elements the elements to be contained in the set + * @return a {@code Set} containing the specified elements + * @throws IllegalArgumentException if there are any duplicate elements + * @throws NullPointerException if an element is {@code null} or if the array is {@code null} + * + * @since 9 + */ + @SafeVarargs + @SuppressWarnings("varargs") + static <E> Set<E> of(E... elements) { + switch (elements.length) { // implicit null check of elements + case 0: + return ImmutableCollections.Set0.instance(); + case 1: + return new ImmutableCollections.Set1<>(elements[0]); + case 2: + return new ImmutableCollections.Set2<>(elements[0], elements[1]); + default: + return new ImmutableCollections.SetN<>(elements); + } + } } diff --git a/ojluni/src/main/java/java/util/SortedMap.java b/ojluni/src/main/java/java/util/SortedMap.java index 15ddba5a68..7f98152253 100644 --- a/ojluni/src/main/java/java/util/SortedMap.java +++ b/ojluni/src/main/java/java/util/SortedMap.java @@ -93,7 +93,7 @@ package java.util; * SortedMap<String, V> sub = m.subMap(low+"\0", high);</pre> * * <p>This interface is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <K> the type of keys maintained by this map diff --git a/ojluni/src/main/java/java/util/SortedSet.java b/ojluni/src/main/java/java/util/SortedSet.java index 1ba72ddb4f..3ea932949a 100644 --- a/ojluni/src/main/java/java/util/SortedSet.java +++ b/ojluni/src/main/java/java/util/SortedSet.java @@ -89,7 +89,7 @@ package java.util; * SortedSet<String> sub = s.subSet(low+"\0", high);</pre> * * <p>This interface is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <E> the type of elements maintained by this set diff --git a/ojluni/src/main/java/java/util/TEST_MAPPING b/ojluni/src/main/java/java/util/TEST_MAPPING new file mode 100644 index 0000000000..e1434fbbda --- /dev/null +++ b/ojluni/src/main/java/java/util/TEST_MAPPING @@ -0,0 +1,26 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.util" + }, + { + "include-filter": "org.apache.harmony.tests.java.util" + } + ] + }, + { + "name": "CtsLibcoreOjTestCases", + "options": [ + { + "include-filter": "test.java.util" + }, + { + "include-filter": "org.openjdk.tests.java.util" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/util/TimeZone.java b/ojluni/src/main/java/java/util/TimeZone.java index 61826ba5e5..cf5e5f8ccd 100644 --- a/ojluni/src/main/java/java/util/TimeZone.java +++ b/ojluni/src/main/java/java/util/TimeZone.java @@ -47,7 +47,7 @@ import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; import libcore.io.IoUtils; -import libcore.timezone.ZoneInfoDB; +import libcore.timezone.ZoneInfoDb; import dalvik.system.RuntimeHooks; @@ -557,7 +557,7 @@ abstract public class TimeZone implements Serializable, Cloneable { * @return the specified <code>TimeZone</code>, or the GMT zone if the given ID * cannot be understood. */ - // Android-changed: param s/ID/id; use ZoneInfoDB instead of ZoneInfo class. + // Android-changed: param s/ID/id; use ZoneInfoDb instead of ZoneInfo class. public static synchronized TimeZone getTimeZone(String id) { if (id == null) { throw new NullPointerException("id == null"); @@ -576,7 +576,7 @@ abstract public class TimeZone implements Serializable, Cloneable { // In the database? TimeZone zone = null; try { - zone = ZoneInfoDB.getInstance().makeTimeZone(id); + zone = ZoneInfoDb.getInstance().makeTimeZone(id); } catch (IOException ignored) { } @@ -666,7 +666,7 @@ abstract public class TimeZone implements Serializable, Cloneable { * @see #getRawOffset() */ public static synchronized String[] getAvailableIDs(int rawOffset) { - return ZoneInfoDB.getInstance().getAvailableIDs(rawOffset); + return ZoneInfoDb.getInstance().getAvailableIDs(rawOffset); } /** @@ -674,7 +674,7 @@ abstract public class TimeZone implements Serializable, Cloneable { * @return an array of IDs. */ public static synchronized String[] getAvailableIDs() { - return ZoneInfoDB.getInstance().getAvailableIDs(); + return ZoneInfoDb.getInstance().getAvailableIDs(); } /** diff --git a/ojluni/src/main/java/java/util/TreeMap.java b/ojluni/src/main/java/java/util/TreeMap.java index 7603cfc29b..20d98bc988 100644 --- a/ojluni/src/main/java/java/util/TreeMap.java +++ b/ojluni/src/main/java/java/util/TreeMap.java @@ -93,7 +93,7 @@ import java.util.function.Consumer; * associated map using {@code put}.) * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <K> the type of keys maintained by this map diff --git a/ojluni/src/main/java/java/util/TreeSet.java b/ojluni/src/main/java/java/util/TreeSet.java index be215ba2ed..54eeeda97c 100644 --- a/ojluni/src/main/java/java/util/TreeSet.java +++ b/ojluni/src/main/java/java/util/TreeSet.java @@ -74,7 +74,7 @@ package java.util; * should be used only to detect bugs.</i> * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <E> the type of elements maintained by this set diff --git a/ojluni/src/main/java/java/util/Vector.java b/ojluni/src/main/java/java/util/Vector.java index 6c5247cf91..f1844379ad 100644 --- a/ojluni/src/main/java/java/util/Vector.java +++ b/ojluni/src/main/java/java/util/Vector.java @@ -68,7 +68,7 @@ import java.util.function.UnaryOperator; * * <p>As of the Java 2 platform v1.2, this class was retrofitted to * implement the {@link List} interface, making it a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. Unlike the new collection * implementations, {@code Vector} is synchronized. If a thread-safe * implementation is not needed, it is recommended to use {@link diff --git a/ojluni/src/main/java/java/util/WeakHashMap.java b/ojluni/src/main/java/java/util/WeakHashMap.java index d977b61c49..7352391ac3 100644 --- a/ojluni/src/main/java/java/util/WeakHashMap.java +++ b/ojluni/src/main/java/java/util/WeakHashMap.java @@ -1,5 +1,4 @@ /* - * Copyright (C) 2014 The Android Open Source Project * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -28,6 +27,7 @@ package java.util; import java.lang.ref.WeakReference; import java.lang.ref.ReferenceQueue; +import java.util.concurrent.ThreadLocalRandom; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -120,7 +120,7 @@ import java.util.function.Consumer; * should be used only to detect bugs.</i> * * <p>This class is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <K> the type of keys maintained by this map diff --git a/ojluni/src/main/java/java/util/concurrent/BlockingDeque.java b/ojluni/src/main/java/java/util/concurrent/BlockingDeque.java index da1a4fdf83..290fee1825 100644 --- a/ojluni/src/main/java/java/util/concurrent/BlockingDeque.java +++ b/ojluni/src/main/java/java/util/concurrent/BlockingDeque.java @@ -197,7 +197,7 @@ import java.util.NoSuchElementException; * the {@code BlockingDeque} in another thread. * * <p>This interface is a member of the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html"> + * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @since 1.6 diff --git a/ojluni/src/main/java/java/util/concurrent/Flow.java b/ojluni/src/main/java/java/util/concurrent/Flow.java new file mode 100644 index 0000000000..0231790725 --- /dev/null +++ b/ojluni/src/main/java/java/util/concurrent/Flow.java @@ -0,0 +1,319 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent; + +// Android-changed: Remove reference to SubmissionPublisher class (not present on Android). +/** + * Interrelated interfaces and static methods for establishing + * flow-controlled components in which {@link Publisher Publishers} + * produce items consumed by one or more {@link Subscriber + * Subscribers}, each managed by a {@link Subscription + * Subscription}. + * + * <p>These interfaces correspond to the <a + * href="http://www.reactive-streams.org/"> reactive-streams</a> + * specification. They apply in both concurrent and distributed + * asynchronous settings: All (seven) methods are defined in {@code + * void} "one-way" message style. Communication relies on a simple form + * of flow control (method {@link Subscription#request}) that can be + * used to avoid resource management problems that may otherwise occur + * in "push" based systems. + * + * <p><b>Examples.</b> A {@link Publisher} usually defines its own + * {@link Subscription} implementation; constructing one in method + * {@code subscribe} and issuing it to the calling {@link + * Subscriber}. It publishes items to the subscriber asynchronously, + * normally using an {@link Executor}. For example, here is a very + * simple publisher that only issues (when requested) a single {@code + * TRUE} item to a single subscriber. Because the subscriber receives + * only a single item, this class does not use buffering and ordering + * control required in most implementations. + * + * <pre> {@code + * class OneShotPublisher implements Publisher<Boolean> { + * private final ExecutorService executor = ForkJoinPool.commonPool(); // daemon-based + * private boolean subscribed; // true after first subscribe + * public synchronized void subscribe(Subscriber<? super Boolean> subscriber) { + * if (subscribed) + * subscriber.onError(new IllegalStateException()); // only one allowed + * else { + * subscribed = true; + * subscriber.onSubscribe(new OneShotSubscription(subscriber, executor)); + * } + * } + * static class OneShotSubscription implements Subscription { + * private final Subscriber<? super Boolean> subscriber; + * private final ExecutorService executor; + * private Future<?> future; // to allow cancellation + * private boolean completed; + * OneShotSubscription(Subscriber<? super Boolean> subscriber, + * ExecutorService executor) { + * this.subscriber = subscriber; + * this.executor = executor; + * } + * public synchronized void request(long n) { + * if (n != 0 && !completed) { + * completed = true; + * if (n < 0) { + * IllegalArgumentException ex = new IllegalArgumentException(); + * executor.execute(() -> subscriber.onError(ex)); + * } else { + * future = executor.submit(() -> { + * subscriber.onNext(Boolean.TRUE); + * subscriber.onComplete(); + * }); + * } + * } + * } + * public synchronized void cancel() { + * completed = true; + * if (future != null) future.cancel(false); + * } + * } + * }}</pre> + * + * <p>A {@link Subscriber} arranges that items be requested and + * processed. Items (invocations of {@link Subscriber#onNext}) are + * not issued unless requested, but multiple items may be requested. + * Many Subscriber implementations can arrange this in the style of + * the following example, where a buffer size of 1 single-steps, and + * larger sizes usually allow for more efficient overlapped processing + * with less communication; for example with a value of 64, this keeps + * total outstanding requests between 32 and 64. + * Because Subscriber method invocations for a given {@link + * Subscription} are strictly ordered, there is no need for these + * methods to use locks or volatiles unless a Subscriber maintains + * multiple Subscriptions (in which case it is better to instead + * define multiple Subscribers, each with its own Subscription). + * + * <pre> {@code + * class SampleSubscriber<T> implements Subscriber<T> { + * final Consumer<? super T> consumer; + * Subscription subscription; + * final long bufferSize; + * long count; + * SampleSubscriber(long bufferSize, Consumer<? super T> consumer) { + * this.bufferSize = bufferSize; + * this.consumer = consumer; + * } + * public void onSubscribe(Subscription subscription) { + * long initialRequestSize = bufferSize; + * count = bufferSize - bufferSize / 2; // re-request when half consumed + * (this.subscription = subscription).request(initialRequestSize); + * } + * public void onNext(T item) { + * if (--count <= 0) + * subscription.request(count = bufferSize - bufferSize / 2); + * consumer.accept(item); + * } + * public void onError(Throwable ex) { ex.printStackTrace(); } + * public void onComplete() {} + * }}</pre> + * + * <p>The default value of {@link #defaultBufferSize} may provide a + * useful starting point for choosing request sizes and capacities in + * Flow components based on expected rates, resources, and usages. + * Or, when flow control is never needed, a subscriber may initially + * request an effectively unbounded number of items, as in: + * + * <pre> {@code + * class UnboundedSubscriber<T> implements Subscriber<T> { + * public void onSubscribe(Subscription subscription) { + * subscription.request(Long.MAX_VALUE); // effectively unbounded + * } + * public void onNext(T item) { use(item); } + * public void onError(Throwable ex) { ex.printStackTrace(); } + * public void onComplete() {} + * void use(T item) { ... } + * }}</pre> + * + * @author Doug Lea + * @since 9 + */ +public final class Flow { + + private Flow() {} // uninstantiable + + /** + * A producer of items (and related control messages) received by + * Subscribers. Each current {@link Subscriber} receives the same + * items (via method {@code onNext}) in the same order, unless + * drops or errors are encountered. If a Publisher encounters an + * error that does not allow items to be issued to a Subscriber, + * that Subscriber receives {@code onError}, and then receives no + * further messages. Otherwise, when it is known that no further + * messages will be issued to it, a subscriber receives {@code + * onComplete}. Publishers ensure that Subscriber method + * invocations for each subscription are strictly ordered in <a + * href="package-summary.html#MemoryVisibility"><i>happens-before</i></a> + * order. + * + * <p>Publishers may vary in policy about whether drops (failures + * to issue an item because of resource limitations) are treated + * as unrecoverable errors. Publishers may also vary about + * whether Subscribers receive items that were produced or + * available before they subscribed. + * + * @param <T> the published item type + */ + @FunctionalInterface + public static interface Publisher<T> { + /** + * Adds the given Subscriber if possible. If already + * subscribed, or the attempt to subscribe fails due to policy + * violations or errors, the Subscriber's {@code onError} + * method is invoked with an {@link IllegalStateException}. + * Otherwise, the Subscriber's {@code onSubscribe} method is + * invoked with a new {@link Subscription}. Subscribers may + * enable receiving items by invoking the {@code request} + * method of this Subscription, and may unsubscribe by + * invoking its {@code cancel} method. + * + * @param subscriber the subscriber + * @throws NullPointerException if subscriber is null + */ + public void subscribe(Subscriber<? super T> subscriber); + } + + /** + * A receiver of messages. The methods in this interface are + * invoked in strict sequential order for each {@link + * Subscription}. + * + * @param <T> the subscribed item type + */ + public static interface Subscriber<T> { + /** + * Method invoked prior to invoking any other Subscriber + * methods for the given Subscription. If this method throws + * an exception, resulting behavior is not guaranteed, but may + * cause the Subscription not to be established or to be cancelled. + * + * <p>Typically, implementations of this method invoke {@code + * subscription.request} to enable receiving items. + * + * @param subscription a new subscription + */ + public void onSubscribe(Subscription subscription); + + /** + * Method invoked with a Subscription's next item. If this + * method throws an exception, resulting behavior is not + * guaranteed, but may cause the Subscription to be cancelled. + * + * @param item the item + */ + public void onNext(T item); + + /** + * Method invoked upon an unrecoverable error encountered by a + * Publisher or Subscription, after which no other Subscriber + * methods are invoked by the Subscription. If this method + * itself throws an exception, resulting behavior is + * undefined. + * + * @param throwable the exception + */ + public void onError(Throwable throwable); + + /** + * Method invoked when it is known that no additional + * Subscriber method invocations will occur for a Subscription + * that is not already terminated by error, after which no + * other Subscriber methods are invoked by the Subscription. + * If this method throws an exception, resulting behavior is + * undefined. + */ + public void onComplete(); + } + + /** + * Message control linking a {@link Publisher} and {@link + * Subscriber}. Subscribers receive items only when requested, + * and may cancel at any time. The methods in this interface are + * intended to be invoked only by their Subscribers; usages in + * other contexts have undefined effects. + */ + public static interface Subscription { + /** + * Adds the given number {@code n} of items to the current + * unfulfilled demand for this subscription. If {@code n} is + * less than or equal to zero, the Subscriber will receive an + * {@code onError} signal with an {@link + * IllegalArgumentException} argument. Otherwise, the + * Subscriber will receive up to {@code n} additional {@code + * onNext} invocations (or fewer if terminated). + * + * @param n the increment of demand; a value of {@code + * Long.MAX_VALUE} may be considered as effectively unbounded + */ + public void request(long n); + + /** + * Causes the Subscriber to (eventually) stop receiving + * messages. Implementation is best-effort -- additional + * messages may be received after invoking this method. + * A cancelled subscription need not ever receive an + * {@code onComplete} or {@code onError} signal. + */ + public void cancel(); + } + + /** + * A component that acts as both a Subscriber and Publisher. + * + * @param <T> the subscribed item type + * @param <R> the published item type + */ + public static interface Processor<T,R> extends Subscriber<T>, Publisher<R> { + } + + static final int DEFAULT_BUFFER_SIZE = 256; + + /** + * Returns a default value for Publisher or Subscriber buffering, + * that may be used in the absence of other constraints. + * + * @implNote + * The current value returned is 256. + * + * @return the buffer size value + */ + public static int defaultBufferSize() { + return DEFAULT_BUFFER_SIZE; + } + +} diff --git a/ojluni/src/main/java/java/util/concurrent/TEST_MAPPING b/ojluni/src/main/java/java/util/concurrent/TEST_MAPPING new file mode 100644 index 0000000000..5730a289f9 --- /dev/null +++ b/ojluni/src/main/java/java/util/concurrent/TEST_MAPPING @@ -0,0 +1,20 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreJsr166TestCases", + "options": [ + { + "include-filter": "jsr166" + } + ] + }, + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.util.concurrent" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/util/function/TEST_MAPPING b/ojluni/src/main/java/java/util/function/TEST_MAPPING new file mode 100644 index 0000000000..5840cf90c3 --- /dev/null +++ b/ojluni/src/main/java/java/util/function/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.util.function" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/util/jar/Attributes.java b/ojluni/src/main/java/java/util/jar/Attributes.java index 6878aa8c90..795b80900d 100644 --- a/ojluni/src/main/java/java/util/jar/Attributes.java +++ b/ojluni/src/main/java/java/util/jar/Attributes.java @@ -1,5 +1,4 @@ /* - * Copyright (C) 2014 The Android Open Source Project * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -45,7 +44,7 @@ import sun.misc.ASCIICaseInsensitiveComparator; * the ASCII characters in the set [0-9a-zA-Z_-], and cannot exceed 70 * characters in length. Attribute values can contain any characters and * will be UTF8-encoded when written to the output stream. See the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html">JAR File Specification</a> + * <a href="../../../../technotes/guides/jar/jar.html">JAR File Specification</a> * for more information about valid attribute names and values. * * @author David Connelly @@ -442,7 +441,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { * to the ASCII characters in the set [0-9a-zA-Z_-], and cannot exceed * 70 characters in length. Attribute values can contain any characters * and will be UTF8-encoded when written to the output stream. See the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html">JAR File Specification</a> + * <a href="../../../../technotes/guides/jar/jar.html">JAR File Specification</a> * for more information about valid attribute names and values. */ public static class Name { @@ -528,7 +527,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { * <code>Name</code> object for <code>Manifest-Version</code> * manifest attribute. This attribute indicates the version number * of the manifest standard to which a JAR file's manifest conforms. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#JAR_Manifest"> + * @see <a href="../../../../technotes/guides/jar/jar.html#JAR_Manifest"> * Manifest and Signature Specification</a> */ public static final Name MANIFEST_VERSION = new Name("Manifest-Version"); @@ -536,7 +535,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { /** * <code>Name</code> object for <code>Signature-Version</code> * manifest attribute used when signing JAR files. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#JAR_Manifest"> + * @see <a href="../../../../technotes/guides/jar/jar.html#JAR_Manifest"> * Manifest and Signature Specification</a> */ public static final Name SIGNATURE_VERSION = new Name("Signature-Version"); @@ -551,7 +550,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { * <code>Name</code> object for <code>Class-Path</code> * manifest attribute. Bundled extensions can use this attribute * to find other JAR files containing needed classes. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#classpath"> + * @see <a href="../../../../technotes/guides/jar/jar.html#classpath"> * JAR file specification</a> */ public static final Name CLASS_PATH = new Name("Class-Path"); @@ -568,7 +567,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { /** * <code>Name</code> object for <code>Sealed</code> manifest attribute * used for sealing. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#sealing"> + * @see <a href="../../../../technotes/guides/jar/jar.html#sealing"> * Package Sealing</a> */ public static final Name SEALED = new Name("Sealed"); @@ -576,7 +575,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { /** * <code>Name</code> object for <code>Extension-List</code> manifest attribute * used for declaring dependencies on installed extensions. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/spec.html#dependency"> + * @see <a href="../../../../technotes/guides/extensions/spec.html#dependency"> * Installed extension dependency</a> */ public static final Name EXTENSION_LIST = new Name("Extension-List"); @@ -584,7 +583,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { /** * <code>Name</code> object for <code>Extension-Name</code> manifest attribute * used for declaring dependencies on installed extensions. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/spec.html#dependency"> + * @see <a href="../../../../technotes/guides/extensions/spec.html#dependency"> * Installed extension dependency</a> */ public static final Name EXTENSION_NAME = new Name("Extension-Name"); @@ -594,7 +593,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { * used for declaring dependencies on installed extensions. * @deprecated Extension mechanism will be removed in a future release. * Use class path instead. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/spec.html#dependency"> + * @see <a href="../../../../technotes/guides/extensions/spec.html#dependency"> * Installed extension dependency</a> */ @Deprecated @@ -603,7 +602,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { /** * <code>Name</code> object for <code>Implementation-Title</code> * manifest attribute used for package versioning. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp90779"> + * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> * Java Product Versioning Specification</a> */ public static final Name IMPLEMENTATION_TITLE = new Name("Implementation-Title"); @@ -611,7 +610,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { /** * <code>Name</code> object for <code>Implementation-Version</code> * manifest attribute used for package versioning. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp90779"> + * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> * Java Product Versioning Specification</a> */ public static final Name IMPLEMENTATION_VERSION = new Name("Implementation-Version"); @@ -619,7 +618,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { /** * <code>Name</code> object for <code>Implementation-Vendor</code> * manifest attribute used for package versioning. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp90779"> + * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> * Java Product Versioning Specification</a> */ public static final Name IMPLEMENTATION_VENDOR = new Name("Implementation-Vendor"); @@ -629,7 +628,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { * manifest attribute used for package versioning. * @deprecated Extension mechanism will be removed in a future release. * Use class path instead. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/versioning.html#applet"> + * @see <a href="../../../../technotes/guides/extensions/versioning.html#applet"> * Optional Package Versioning</a> */ @Deprecated @@ -640,7 +639,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { * manifest attribute used for package versioning. * @deprecated Extension mechanism will be removed in a future release. * Use class path instead. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/versioning.html#applet"> + * @see <a href="../../../../technotes/guides/extensions/versioning.html#applet"> * Optional Package Versioning</a> */ @Deprecated @@ -649,7 +648,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { /** * <code>Name</code> object for <code>Specification-Title</code> * manifest attribute used for package versioning. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp90779"> + * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> * Java Product Versioning Specification</a> */ public static final Name SPECIFICATION_TITLE = new Name("Specification-Title"); @@ -657,7 +656,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { /** * <code>Name</code> object for <code>Specification-Version</code> * manifest attribute used for package versioning. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp90779"> + * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> * Java Product Versioning Specification</a> */ public static final Name SPECIFICATION_VERSION = new Name("Specification-Version"); @@ -665,7 +664,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { /** * <code>Name</code> object for <code>Specification-Vendor</code> * manifest attribute used for package versioning. - * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp90779"> + * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> * Java Product Versioning Specification</a> */ public static final Name SPECIFICATION_VENDOR = new Name("Specification-Vendor"); diff --git a/ojluni/src/main/java/java/util/jar/Manifest.java b/ojluni/src/main/java/java/util/jar/Manifest.java index 4dfda783fa..976e44c53a 100644 --- a/ojluni/src/main/java/java/util/jar/Manifest.java +++ b/ojluni/src/main/java/java/util/jar/Manifest.java @@ -39,7 +39,7 @@ import java.util.Iterator; * associated Attributes. There are main Manifest Attributes as well as * per-entry Attributes. For information on the Manifest format, please * see the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html"> + * <a href="../../../../technotes/guides/jar/jar.html"> * Manifest format specification</a>. * * @author David Connelly diff --git a/ojluni/src/main/java/java/util/jar/Pack200.java b/ojluni/src/main/java/java/util/jar/Pack200.java index 26b2ce3d7a..9211f0ad87 100644 --- a/ojluni/src/main/java/java/util/jar/Pack200.java +++ b/ojluni/src/main/java/java/util/jar/Pack200.java @@ -96,7 +96,7 @@ import java.beans.PropertyChangeListener; * The deployment applications can use "Accept-Encoding=pack200-gzip". This * indicates to the server that the client application desires a version of * the file encoded with Pack200 and further compressed with gzip. Please - * refer to <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/deployment/deployment-guide/pack200.html">Java Deployment Guide</a> for more details and + * refer to <a href="{@docRoot}/../technotes/guides/deployment/deployment-guide/pack200.html">Java Deployment Guide</a> for more details and * techniques. * <p> * Unless otherwise noted, passing a <tt>null</tt> argument to a constructor or diff --git a/ojluni/src/main/java/java/util/jar/TEST_MAPPING b/ojluni/src/main/java/java/util/jar/TEST_MAPPING new file mode 100644 index 0000000000..5b26443fff --- /dev/null +++ b/ojluni/src/main/java/java/util/jar/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.util.jar" + }, + { + "include-filter": "org.apache.harmony.tests.java.util.jar" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/util/jar/package.html b/ojluni/src/main/java/java/util/jar/package.html index 921a8215da..dd9ad7377f 100644 --- a/ojluni/src/main/java/java/util/jar/package.html +++ b/ojluni/src/main/java/java/util/jar/package.html @@ -45,7 +45,7 @@ The <code>java.util.jar</code> package is based on the following specifications: package description.</a> <p> In JAR files, all file names must be encoded in the UTF-8 encoding. <p> - <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html"> + <li><a href="../../../../technotes/guides/jar/jar.html"> Manifest and Signature Specification</a> - The manifest format specification. </ul> diff --git a/ojluni/src/main/java/java/util/logging/TEST_MAPPING b/ojluni/src/main/java/java/util/logging/TEST_MAPPING new file mode 100644 index 0000000000..85f4d2bdf4 --- /dev/null +++ b/ojluni/src/main/java/java/util/logging/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.logging.tests.java.util.logging" + }, + { + "include-filter": "libcore.java.util.logging" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/util/logging/package.html b/ojluni/src/main/java/java/util/logging/package.html index a4c71f407d..cafcdad3f2 100644 --- a/ojluni/src/main/java/java/util/logging/package.html +++ b/ojluni/src/main/java/java/util/logging/package.html @@ -116,7 +116,7 @@ for all arguments except for the initial Level argument (if any). <P> For an overview of control flow, please refer to the -<a href="https://docs.oracle.com/javase/8/docs/technotes/guides/logging/overview.html"> +<a href="../../../../technotes/guides/logging/overview.html"> Java Logging Overview</a>. </P> diff --git a/ojluni/src/main/java/java/util/package.html b/ojluni/src/main/java/java/util/package.html index 8bb5efe6c3..a65593443a 100644 --- a/ojluni/src/main/java/java/util/package.html +++ b/ojluni/src/main/java/java/util/package.html @@ -35,8 +35,8 @@ classes (a string tokenizer, a random-number generator, and a bit array). <h2>Package Specification</h2> <ul> - <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/overview.html"><b>Collections Framework Overview</b></a> - <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/reference.html"><b> + <li><a href="../../../technotes/guides/collections/overview.html"><b>Collections Framework Overview</b></a> + <li><a href="../../../technotes/guides/collections/reference.html"><b> Collections Framework Annotated Outline</b></a> </ul> @@ -46,7 +46,7 @@ For overviews, tutorials, examples, guides, and tool documentation, please see: <li><a href="http://www.java.sun.com/docs/books/tutorial/collections/"> <b>Collections Framework Tutorial</b></a> <li><a - href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/designfaq.html"><b>Collections + href="../../../technotes/guides/collections/designfaq.html"><b>Collections Framework Design FAQ</b></a> </ul> diff --git a/ojluni/src/main/java/java/util/prefs/FileSystemPreferences.java b/ojluni/src/main/java/java/util/prefs/FileSystemPreferences.java index 17c50a8d63..b888c4dded 100644 --- a/ojluni/src/main/java/java/util/prefs/FileSystemPreferences.java +++ b/ojluni/src/main/java/java/util/prefs/FileSystemPreferences.java @@ -34,6 +34,7 @@ import java.security.PrivilegedActionException; import sun.util.logging.PlatformLogger; +// Android-changed: @hide. /** * Preferences implementation for Unix. Preferences are stored in the file * system, with one directory per preferences node. All of the preferences @@ -50,7 +51,6 @@ import sun.util.logging.PlatformLogger; * * @hide */ -// Android-changed: @hide. public class FileSystemPreferences extends AbstractPreferences { /** * Returns logger for error messages. Backing store exceptions are logged at diff --git a/ojluni/src/main/java/java/util/prefs/TEST_MAPPING b/ojluni/src/main/java/java/util/prefs/TEST_MAPPING new file mode 100644 index 0000000000..3a3445b65b --- /dev/null +++ b/ojluni/src/main/java/java/util/prefs/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.java.util.prefs" + }, + { + "include-filter": "libcore.java.util.prefs" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/util/regex/Matcher.java b/ojluni/src/main/java/java/util/regex/Matcher.java index 38f8046d54..d50ea32c3d 100644 --- a/ojluni/src/main/java/java/util/regex/Matcher.java +++ b/ojluni/src/main/java/java/util/regex/Matcher.java @@ -26,8 +26,7 @@ package java.util.regex; -import dalvik.annotation.optimization.ReachabilitySensitive; -import libcore.util.NativeAllocationRegistry; +import com.android.icu.util.regex.MatcherNative; /** * An engine that performs match operations on a {@linkplain java.lang.CharSequence @@ -109,10 +108,6 @@ public final class Matcher implements MatchResult { /** * The Pattern object that created this Matcher. */ - // Patterns also contain cleanup code and a ReachabilitySensitive field. - // This ensures that "this" and pattern remain reachable while we're using pattern.address - // directly. - @ReachabilitySensitive private Pattern parentPattern; /** @@ -137,21 +132,7 @@ public final class Matcher implements MatchResult { */ private boolean matchFound; - /** - * The address of the native peer. - * Uses of this must be manually synchronized to avoid native crashes. - */ - @ReachabilitySensitive - private long address; - - /** - * If non-null, a Runnable that can be used to explicitly deallocate address. - */ - private Runnable nativeFinalizer; - - private static final NativeAllocationRegistry registry = - NativeAllocationRegistry.createMalloced(Matcher.class.getClassLoader(), - getNativeFinalizer()); + private MatcherNative nativeMatcher; /** * The index of the last position appended in a substitution. @@ -227,17 +208,12 @@ public final class Matcher implements MatchResult { public Matcher usePattern(Pattern newPattern) { if (newPattern == null) throw new IllegalArgumentException("Pattern cannot be null"); - parentPattern = newPattern; synchronized (this) { - if (nativeFinalizer != null) { - nativeFinalizer.run(); - address = 0; // In case openImpl throws. - nativeFinalizer = null; - } - address = openImpl(parentPattern.address); - nativeFinalizer = registry.registerNativeAllocation(this, address); + // may throw + nativeMatcher = MatcherNative.create(newPattern.nativePattern); } + parentPattern = newPattern; if (text != null) { resetForInput(); @@ -533,7 +509,7 @@ public final class Matcher implements MatchResult { */ public int groupCount() { synchronized (this) { - return groupCountImpl(address); + return nativeMatcher.groupCount(); } } @@ -548,7 +524,7 @@ public final class Matcher implements MatchResult { */ public boolean matches() { synchronized (this) { - matchFound = matchesImpl(address, groups); + matchFound = nativeMatcher.matches(groups); } return matchFound; } @@ -570,7 +546,7 @@ public final class Matcher implements MatchResult { */ public boolean find() { synchronized (this) { - matchFound = findNextImpl(address, groups); + matchFound = nativeMatcher.findNext(groups); } return matchFound; } @@ -600,7 +576,7 @@ public final class Matcher implements MatchResult { throw new IndexOutOfBoundsException("Illegal start index"); reset(); synchronized (this) { - matchFound = findImpl(address, start, groups); + matchFound = nativeMatcher.find(start, groups); } return matchFound; } @@ -621,7 +597,7 @@ public final class Matcher implements MatchResult { */ public boolean lookingAt() { synchronized (this) { - matchFound = lookingAtImpl(address, groups); + matchFound = nativeMatcher.lookingAt(groups); } return matchFound; } @@ -764,16 +740,20 @@ public final class Matcher implements MatchResult { escape = true; } else if (c == '$' && !escape) { dollar = true; - } else if (c >= '0' && c <= '9' && dollar) { - buffer.append(group(c - '0')); + } else if (c >= '0' && c <= '9' && dollar && !escapeNamedGroup) { + String groupValue = group(c - '0'); + if (groupValue != null) { + buffer.append(groupValue); + } dollar = false; } else if (c == '{' && dollar) { escapeNamedGroup = true; escapeNamedGroupStart = i; } else if (c == '}' && dollar && escapeNamedGroup) { - String namedGroupName = - s.substring(escapeNamedGroupStart + 1, i); - buffer.append(group(namedGroupName)); + String groupValue = group(s.substring(escapeNamedGroupStart + 1, i)); + if (groupValue != null) { + buffer.append(groupValue); + } dollar = false; escapeNamedGroup = false; } else if (c != '}' && dollar && escapeNamedGroup) { @@ -1019,7 +999,7 @@ public final class Matcher implements MatchResult { public Matcher useTransparentBounds(boolean b) { synchronized (this) { transparentBounds = b; - useTransparentBoundsImpl(address, b); + nativeMatcher.useTransparentBounds(b); } return this; } @@ -1068,7 +1048,7 @@ public final class Matcher implements MatchResult { public Matcher useAnchoringBounds(boolean b) { synchronized (this) { anchoringBounds = b; - useAnchoringBoundsImpl(address, b); + nativeMatcher.useAnchoringBounds(b); } return this; } @@ -1108,7 +1088,7 @@ public final class Matcher implements MatchResult { */ public boolean hitEnd() { synchronized (this) { - return hitEndImpl(address); + return nativeMatcher.hitEnd(); } } @@ -1128,7 +1108,7 @@ public final class Matcher implements MatchResult { */ public boolean requireEnd() { synchronized (this) { - return requireEndImpl(address); + return nativeMatcher.requireEnd(); } } @@ -1191,9 +1171,9 @@ public final class Matcher implements MatchResult { private void resetForInput() { synchronized (this) { - setInputImpl(address, text, from, to); - useAnchoringBoundsImpl(address, anchoringBounds); - useTransparentBoundsImpl(address, transparentBounds); + nativeMatcher.setInput(text, from, to); + nativeMatcher.useAnchoringBounds(anchoringBounds); + nativeMatcher.useTransparentBounds(transparentBounds); } } @@ -1212,7 +1192,7 @@ public final class Matcher implements MatchResult { private int getMatchedGroupIndex(String name) { ensureMatch(); - int result = getMatchedGroupIndex0(parentPattern.address, name); + int result = nativeMatcher.getMatchedGroupIndex(name); if (result < 0) { throw new IllegalArgumentException("No capturing group in the pattern " + "with the name " + name); @@ -1220,20 +1200,6 @@ public final class Matcher implements MatchResult { return result; } - private static native int getMatchedGroupIndex0(long patternAddr, String name); - private static native boolean findImpl(long addr, int startIndex, int[] offsets); - private static native boolean findNextImpl(long addr, int[] offsets); - private static native long getNativeFinalizer(); - private static native int groupCountImpl(long addr); - private static native boolean hitEndImpl(long addr); - private static native boolean lookingAtImpl(long addr, int[] offsets); - private static native boolean matchesImpl(long addr, int[] offsets); - private static native long openImpl(long patternAddr); - private static native boolean requireEndImpl(long addr); - private static native void setInputImpl(long addr, String s, int start, int end); - private static native void useAnchoringBoundsImpl(long addr, boolean value); - private static native void useTransparentBoundsImpl(long addr, boolean value); - /** * A trivial match result implementation that's based on an array of integers * representing match offsets. The array is of the form diff --git a/ojluni/src/main/java/java/util/regex/Pattern.java b/ojluni/src/main/java/java/util/regex/Pattern.java index 55a48de906..a4ead58234 100644 --- a/ojluni/src/main/java/java/util/regex/Pattern.java +++ b/ojluni/src/main/java/java/util/regex/Pattern.java @@ -26,11 +26,9 @@ package java.util.regex; -import dalvik.annotation.optimization.ReachabilitySensitive; +import com.android.icu.util.regex.PatternNative; import dalvik.system.VMRuntime; -import libcore.util.NativeAllocationRegistry; - import java.util.Iterator; import java.util.ArrayList; import java.util.NoSuchElementException; @@ -945,12 +943,7 @@ public final class Pattern // BEGIN Android-changed: reimplement matching logic natively via ICU. // We only need some tie-ins to native memory, instead of a large number // of fields on the .java side. - @ReachabilitySensitive - transient long address; - - private static final NativeAllocationRegistry registry = - NativeAllocationRegistry.createMalloced(Pattern.class.getClassLoader(), - getNativeFinalizer()); + /* package */ transient PatternNative nativePattern; // END Android-changed: reimplement matching logic natively via ICU. /** @@ -1430,12 +1423,8 @@ public final class Pattern // These are the flags natively supported by ICU. // They even have the same value in native code. int icuFlags = flags & (CASE_INSENSITIVE | COMMENTS | MULTILINE | DOTALL | UNIX_LINES); - address = compileImpl(icuPattern, icuFlags); - registry.registerNativeAllocation(this, address); + nativePattern = PatternNative.create(icuPattern, icuFlags); } - - private static native long compileImpl(String regex, int flags); - private static native long getNativeFinalizer(); // END Android-changed: reimplement matching logic natively via ICU. /** diff --git a/ojluni/src/main/java/java/util/regex/TEST_MAPPING b/ojluni/src/main/java/java/util/regex/TEST_MAPPING new file mode 100644 index 0000000000..1bd44e2177 --- /dev/null +++ b/ojluni/src/main/java/java/util/regex/TEST_MAPPING @@ -0,0 +1,18 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.regex.tests.java.util.regex" + }, + { + "include-filter": "libcore.java.util.regex" + }, + { + "include-filter": "org.apache.harmony.tests.java.util.regex" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/util/stream/TEST_MAPPING b/ojluni/src/main/java/java/util/stream/TEST_MAPPING new file mode 100644 index 0000000000..9673e09d52 --- /dev/null +++ b/ojluni/src/main/java/java/util/stream/TEST_MAPPING @@ -0,0 +1,18 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreOjTestCases", + "options": [ + { + "include-filter": "java.util.stream" + }, + { + "include-filter": "org.openjdk.tests.java.util.stream" + }, + { + "include-filter": "org.openjdk.testlib.java.util.stream" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/util/zip/TEST_MAPPING b/ojluni/src/main/java/java/util/zip/TEST_MAPPING new file mode 100644 index 0000000000..52ac9327ce --- /dev/null +++ b/ojluni/src/main/java/java/util/zip/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.java.util.zip" + }, + { + "include-filter": "org.apache.harmony.tests.java.util.zip" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/java/util/zip/ZipInputStream.java b/ojluni/src/main/java/java/util/zip/ZipInputStream.java index 0413f478b4..aaebb49511 100644 --- a/ojluni/src/main/java/java/util/zip/ZipInputStream.java +++ b/ojluni/src/main/java/java/util/zip/ZipInputStream.java @@ -323,11 +323,16 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants { e.method = get16(tmpbuf, LOCHOW); e.xdostime = get32(tmpbuf, LOCTIM); if ((flag & 8) == 8) { - /* "Data Descriptor" present */ - if (e.method != DEFLATED) { - throw new ZipException( - "only DEFLATED entries can have EXT descriptor"); - } + // Android-Changed: Remove the requirement that only DEFLATED entries + // can have data descriptors. This is not required by the ZIP spec and + // is inconsistent with the behaviour of ZipFile and versions of Android + // prior to Android N. + // + // /* "Data Descriptor" present */ + // if (e.method != DEFLATED) { + // throw new ZipException( + // "only DEFLATED entries can have EXT descriptor"); + // } } else { e.crc = get32(tmpbuf, LOCCRC); e.csize = get32(tmpbuf, LOCSIZ); diff --git a/ojluni/src/main/java/javax/crypto/Cipher.java b/ojluni/src/main/java/javax/crypto/Cipher.java index a8723176e4..7968f2fc62 100644 --- a/ojluni/src/main/java/javax/crypto/Cipher.java +++ b/ojluni/src/main/java/javax/crypto/Cipher.java @@ -242,7 +242,7 @@ import sun.security.jca.*; * </table> * * These transformations are described in the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher"> + * <a href="{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher"> * Cipher section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -597,7 +597,7 @@ public class Cipher { * @param transformation the name of the transformation, e.g., * <i>DES/CBC/PKCS5Padding</i>. * See the Cipher section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard transformation names. * @@ -634,7 +634,7 @@ public class Cipher { * @param transformation the name of the transformation, * e.g., <i>DES/CBC/PKCS5Padding</i>. * See the Cipher section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard transformation names. * @@ -686,7 +686,7 @@ public class Cipher { * @param transformation the name of the transformation, * e.g., <i>DES/CBC/PKCS5Padding</i>. * See the Cipher section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard transformation names. * @@ -2477,7 +2477,7 @@ public class Cipher { * For more information on default key size in JCE jurisdiction * policy files, please see Appendix E in the * <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppC"> + * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppC"> * Java Cryptography Architecture Reference Guide</a>. * * @param transformation the cipher transformation. diff --git a/ojluni/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java b/ojluni/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java index b8bf1697bb..5eeb481dd6 100644 --- a/ojluni/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java +++ b/ojluni/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java @@ -115,7 +115,7 @@ public class EncryptedPrivateKeyInfo { * * @param algName encryption algorithm name. See Appendix A in the * <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> + * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA"> * Java Cryptography Architecture Reference Guide</a> * for information about standard Cipher algorithm names. * @param encryptedData encrypted data. The contents of @@ -198,7 +198,7 @@ public class EncryptedPrivateKeyInfo { * in the constructor when such mapping is available. * See Appendix A in the * <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> + * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA"> * Java Cryptography Architecture Reference Guide</a> * for information about standard Cipher algorithm names. * diff --git a/ojluni/src/main/java/javax/crypto/ExemptionMechanism.java b/ojluni/src/main/java/javax/crypto/ExemptionMechanism.java index f991a66dc9..b90ab43f1d 100644 --- a/ojluni/src/main/java/javax/crypto/ExemptionMechanism.java +++ b/ojluni/src/main/java/javax/crypto/ExemptionMechanism.java @@ -116,7 +116,7 @@ public class ExemptionMechanism { * mechanism. * See the ExemptionMechanism section in the * <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Exemption"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Exemption"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard exemption mechanism names. * @@ -155,7 +155,7 @@ public class ExemptionMechanism { * @param algorithm the standard name of the requested exemption mechanism. * See the ExemptionMechanism section in the * <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Exemption"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Exemption"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard exemption mechanism names. * @@ -199,7 +199,7 @@ public class ExemptionMechanism { * @param algorithm the standard name of the requested exemption mechanism. * See the ExemptionMechanism section in the * <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Exemption"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Exemption"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard exemption mechanism names. * diff --git a/ojluni/src/main/java/javax/crypto/KeyAgreement.java b/ojluni/src/main/java/javax/crypto/KeyAgreement.java index f6decbc7ea..fd79680c13 100644 --- a/ojluni/src/main/java/javax/crypto/KeyAgreement.java +++ b/ojluni/src/main/java/javax/crypto/KeyAgreement.java @@ -75,7 +75,7 @@ import sun.security.jca.GetInstance.Instance; * </table> * * This algorithm is described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyAgreement"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement"> * KeyAgreement section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -177,7 +177,7 @@ public class KeyAgreement { * @param algorithm the standard name of the requested key agreement * algorithm. * See the KeyAgreement section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyAgreement"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -226,7 +226,7 @@ public class KeyAgreement { * @param algorithm the standard name of the requested key agreement * algorithm. * See the KeyAgreement section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyAgreement"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -272,7 +272,7 @@ public class KeyAgreement { * @param algorithm the standard name of the requested key agreement * algorithm. * See the KeyAgreement section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyAgreement"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/javax/crypto/KeyGenerator.java b/ojluni/src/main/java/javax/crypto/KeyGenerator.java index 0b3033885b..5951eef3f0 100644 --- a/ojluni/src/main/java/javax/crypto/KeyGenerator.java +++ b/ojluni/src/main/java/javax/crypto/KeyGenerator.java @@ -156,7 +156,7 @@ import sun.security.jca.GetInstance.Instance; * </table> * * These algorithms are described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> * KeyGenerator section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -272,7 +272,7 @@ public class KeyGenerator { * * @param algorithm the standard name of the requested key algorithm. * See the KeyGenerator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -305,7 +305,7 @@ public class KeyGenerator { * * @param algorithm the standard name of the requested key algorithm. * See the KeyGenerator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -349,7 +349,7 @@ public class KeyGenerator { * * @param algorithm the standard name of the requested key algorithm. * See the KeyGenerator section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyGenerator"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/javax/crypto/Mac.java b/ojluni/src/main/java/javax/crypto/Mac.java index 749b627cab..f70a697bd3 100644 --- a/ojluni/src/main/java/javax/crypto/Mac.java +++ b/ojluni/src/main/java/javax/crypto/Mac.java @@ -142,7 +142,7 @@ import sun.security.jca.GetInstance.Instance; * </table> * * These algorithms are described in the - * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Mac"> + * <a href="{@docRoot}/../technotes/guides/security/StandardNames.html#Mac"> * Mac section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -243,7 +243,7 @@ public class Mac implements Cloneable { * * @param algorithm the standard name of the requested MAC algorithm. * See the Mac section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Mac"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -287,7 +287,7 @@ public class Mac implements Cloneable { * * @param algorithm the standard name of the requested MAC algorithm. * See the Mac section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Mac"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -327,7 +327,7 @@ public class Mac implements Cloneable { * * @param algorithm the standard name of the requested MAC algorithm. * See the Mac section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Mac"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/javax/crypto/SecretKeyFactory.java b/ojluni/src/main/java/javax/crypto/SecretKeyFactory.java index 659df8d2ac..bd8b27139a 100644 --- a/ojluni/src/main/java/javax/crypto/SecretKeyFactory.java +++ b/ojluni/src/main/java/javax/crypto/SecretKeyFactory.java @@ -251,7 +251,7 @@ import sun.security.jca.GetInstance.Instance; * </table> * * These algorithms are described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecretKeyFactory"> * SecretKeyFactory section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -324,7 +324,7 @@ public class SecretKeyFactory { * @param algorithm the standard name of the requested secret-key * algorithm. * See the SecretKeyFactory section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecretKeyFactory"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -359,7 +359,7 @@ public class SecretKeyFactory { * @param algorithm the standard name of the requested secret-key * algorithm. * See the SecretKeyFactory section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecretKeyFactory"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * @@ -405,7 +405,7 @@ public class SecretKeyFactory { * @param algorithm the standard name of the requested secret-key * algorithm. * See the SecretKeyFactory section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecretKeyFactory"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/javax/crypto/TEST_MAPPING b/ojluni/src/main/java/javax/crypto/TEST_MAPPING new file mode 100644 index 0000000000..6860a5c517 --- /dev/null +++ b/ojluni/src/main/java/javax/crypto/TEST_MAPPING @@ -0,0 +1,24 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.crypto.tests.javax.crypto" + }, + { + "include-filter": "org.apache.harmony.crypto.tests.javax.crypto.func" + }, + { + "include-filter": "libcore.javax.crypto" + }, + { + "include-filter": "com.android.org.conscrypt.javax.crypto" + }, + { + "include-filter": "org.apache.harmony.crypto.tests.javax.crypto.serialization" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/javax/crypto/interfaces/TEST_MAPPING b/ojluni/src/main/java/javax/crypto/interfaces/TEST_MAPPING new file mode 100644 index 0000000000..427bf7924a --- /dev/null +++ b/ojluni/src/main/java/javax/crypto/interfaces/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.crypto.tests.javax.crypto.interfaces" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/javax/crypto/interfaces/package.html b/ojluni/src/main/java/javax/crypto/interfaces/package.html index 75ef6feb21..8b18ce2df8 100644 --- a/ojluni/src/main/java/javax/crypto/interfaces/package.html +++ b/ojluni/src/main/java/javax/crypto/interfaces/package.html @@ -46,7 +46,7 @@ for hardware devices, please refer to the cryptographic provider developer guide: <ul> <li><a href= - "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html"> + "{@docRoot}/../technotes/guides/security/crypto/HowToImplAProvider.html"> <b>How to Implement a Provider for the Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture </b></a></li> @@ -65,7 +65,7 @@ For further documentation, please see: <ul> <li> <a href= - "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html"> + "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html"> <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture API Specification and Reference </b></a></li> diff --git a/ojluni/src/main/java/javax/crypto/package.html b/ojluni/src/main/java/javax/crypto/package.html index bd4c05a067..15185738e5 100644 --- a/ojluni/src/main/java/javax/crypto/package.html +++ b/ojluni/src/main/java/javax/crypto/package.html @@ -47,7 +47,7 @@ provider-based implementations without having to add or rewrite code. <h2>Package Specification</h2> <ul> - <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html"><b> + <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html"><b> <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture Standard Algorithm Name Documentation</b></a></li> @@ -59,13 +59,13 @@ For further documentation, please see: <ul> <li> <a href= - "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html"> + "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html"> <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture (JCA) Reference Guide </b></a></li> <li> <a href= - "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html"> + "{@docRoot}/../technotes/guides/security/crypto/HowToImplAProvider.html"> <b>How to Implement a Provider in the Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture </b></a></li> diff --git a/ojluni/src/main/java/javax/crypto/spec/SecretKeySpec.java b/ojluni/src/main/java/javax/crypto/spec/SecretKeySpec.java index ff1258c3ff..767c0d2a6f 100644 --- a/ojluni/src/main/java/javax/crypto/spec/SecretKeySpec.java +++ b/ojluni/src/main/java/javax/crypto/spec/SecretKeySpec.java @@ -82,7 +82,7 @@ public class SecretKeySpec implements KeySpec, SecretKey { * @param algorithm the name of the secret-key algorithm to be associated * with the given key material. * See Appendix A in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> + * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA"> * Java Cryptography Architecture Reference Guide</a> * for information about standard algorithm names. * @exception IllegalArgumentException if <code>algorithm</code> @@ -127,7 +127,7 @@ public class SecretKeySpec implements KeySpec, SecretKey { * @param algorithm the name of the secret-key algorithm to be associated * with the given key material. * See Appendix A in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> + * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA"> * Java Cryptography Architecture Reference Guide</a> * for information about standard algorithm names. * @exception IllegalArgumentException if <code>algorithm</code> diff --git a/ojluni/src/main/java/javax/crypto/spec/TEST_MAPPING b/ojluni/src/main/java/javax/crypto/spec/TEST_MAPPING new file mode 100644 index 0000000000..d1e9d5a1a6 --- /dev/null +++ b/ojluni/src/main/java/javax/crypto/spec/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.crypto.tests.javax.crypto.spec" + }, + { + "include-filter": "libcore.javax.crypto.spec" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/javax/crypto/spec/package.html b/ojluni/src/main/java/javax/crypto/spec/package.html index 3e30aa1a3c..b8fd80724d 100644 --- a/ojluni/src/main/java/javax/crypto/spec/package.html +++ b/ojluni/src/main/java/javax/crypto/spec/package.html @@ -61,13 +61,13 @@ and key specifications, please see: <ul> <li> <a href= - "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html"> + "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html"> <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture API Specification and Reference </b></a></li> <li> <a href= - "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html"> + "{@docRoot}/../technotes/guides/security/crypto/HowToImplAProvider.html"> <b>How to Implement a Provider for the Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture </b></a></li> diff --git a/ojluni/src/main/java/javax/net/TEST_MAPPING b/ojluni/src/main/java/javax/net/TEST_MAPPING new file mode 100644 index 0000000000..aeabde8143 --- /dev/null +++ b/ojluni/src/main/java/javax/net/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.javax.net" + }, + { + "include-filter": "libcore.javax.net" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java b/ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java index 2d832f3710..70f98ce221 100644 --- a/ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java +++ b/ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java @@ -45,7 +45,7 @@ public abstract class ExtendedSSLSession implements SSLSession { * The signature algorithm name must be a standard Java Security * name (such as "SHA1withRSA", "SHA256withECDSA", and so on). * See Appendix A in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> + * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA"> * Java Cryptography Architecture API Specification & Reference </a> * for information about standard algorithm names. * <p> @@ -73,7 +73,7 @@ public abstract class ExtendedSSLSession implements SSLSession { * The signature algorithm name must be a standard Java Security * name (such as "SHA1withRSA", "SHA256withECDSA", and so on). * See Appendix A in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> + * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA"> * Java Cryptography Architecture API Specification & Reference </a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java b/ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java index 143fa5ef92..c3e3c304db 100644 --- a/ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java +++ b/ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java @@ -30,6 +30,7 @@ import java.net.URL; import java.net.HttpURLConnection; import java.security.Principal; import java.security.cert.X509Certificate; +import libcore.api.CorePlatformApi; /** * <code>HttpsURLConnection</code> extends <code>HttpURLConnection</code> @@ -186,9 +187,10 @@ class HttpsURLConnection extends HttpURLConnection * Holds the default instance so class preloading doesn't create an instance of * it. */ + private static final String OK_HOSTNAME_VERIFIER_CLASS + = "com.android.okhttp.internal.tls.OkHostnameVerifier"; private static class NoPreloadHolder { public static HostnameVerifier defaultHostnameVerifier; - public static final Class<? extends HostnameVerifier> originalDefaultHostnameVerifierClass; static { try { /** @@ -198,9 +200,8 @@ class HttpsURLConnection extends HttpURLConnection * the server name from the certificate mismatch. */ defaultHostnameVerifier = (HostnameVerifier) - Class.forName("com.android.okhttp.internal.tls.OkHostnameVerifier") + Class.forName(OK_HOSTNAME_VERIFIER_CLASS) .getField("INSTANCE").get(null); - originalDefaultHostnameVerifierClass = defaultHostnameVerifier.getClass(); } catch (Exception e) { throw new AssertionError("Failed to obtain okhttp HostnameVerifier", e); } @@ -210,7 +211,7 @@ class HttpsURLConnection extends HttpURLConnection /** * The <code>hostnameVerifier</code> for this object. */ - protected HostnameVerifier hostnameVerifier; + protected HostnameVerifier hostnameVerifier = NoPreloadHolder.defaultHostnameVerifier; // END Android-changed: Use holder class idiom for a lazily-created OkHttp hostname verifier. // Android-changed: Modified the documentation to explain side effects / discourage method use. @@ -321,6 +322,30 @@ class HttpsURLConnection extends HttpURLConnection hostnameVerifier = v; } + // BEGIN Android-added: Core platform API to obtain a strict hostname verifier + /** + * Obtains a stricter <code>HostnameVerifier</code>. + * + * The <code>HostnameVerifier</code> returned by this method will reject certificates + * with wildcards for top-level domains such "*.com". + * + * @see com.squareup.okhttp.internal.tls.OkHostnameVerifier + * + * @hide + */ + @CorePlatformApi + public static HostnameVerifier getStrictHostnameVerifier() { + try { + return (HostnameVerifier) Class + .forName(OK_HOSTNAME_VERIFIER_CLASS) + .getMethod("strictInstance") + .invoke(null); + } catch (Exception e) { + return null; + } + } + // END Android-added: Core platform API to obtain a strict hostname verifier + /** * Gets the <code>HostnameVerifier</code> in place on this instance. * @@ -329,15 +354,6 @@ class HttpsURLConnection extends HttpURLConnection * @see #setDefaultHostnameVerifier(HostnameVerifier) */ public HostnameVerifier getHostnameVerifier() { - // Android-added: Use the default verifier if none is set. - // Note that this also has the side effect of *setting* (if unset) - // hostnameVerifier to be the default one. It's not clear why this - // was done (commit abd00f0eaa46f71f98e75a631c268c812d1ec7c1) but - // we're keeping this behavior for lack of a strong reason to do - // otherwise. - if (hostnameVerifier == null) { - hostnameVerifier = NoPreloadHolder.defaultHostnameVerifier; - } return hostnameVerifier; } diff --git a/ojluni/src/main/java/javax/net/ssl/KeyManagerFactory.java b/ojluni/src/main/java/javax/net/ssl/KeyManagerFactory.java index 04af51a639..7ae790c2b1 100644 --- a/ojluni/src/main/java/javax/net/ssl/KeyManagerFactory.java +++ b/ojluni/src/main/java/javax/net/ssl/KeyManagerFactory.java @@ -134,7 +134,7 @@ public class KeyManagerFactory { * * @param algorithm the standard name of the requested algorithm. * See the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html"> + * "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html"> * Java Secure Socket Extension Reference Guide </a> * for information about standard algorithm names. * @@ -170,7 +170,7 @@ public class KeyManagerFactory { * @param algorithm the standard name of the requested algorithm. * See the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html"> + * "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html"> * Java Secure Socket Extension Reference Guide </a> * for information about standard algorithm names. * @@ -211,7 +211,7 @@ public class KeyManagerFactory { * * @param algorithm the standard name of the requested algorithm. * See the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html"> + * "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html"> * Java Secure Socket Extension Reference Guide </a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/javax/net/ssl/SSLContext.java b/ojluni/src/main/java/javax/net/ssl/SSLContext.java index b580a72be3..eb7322c445 100644 --- a/ojluni/src/main/java/javax/net/ssl/SSLContext.java +++ b/ojluni/src/main/java/javax/net/ssl/SSLContext.java @@ -82,7 +82,7 @@ import sun.security.jca.GetInstance; * </table> * * This protocol is described in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SSLContext"> * SSLContext section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * @@ -180,7 +180,7 @@ public class SSLContext { * * @param protocol the standard name of the requested protocol. * See the SSLContext section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SSLContext"> * Java Cryptography Architecture Standard Algorithm Name * Documentation</a> * for information about standard protocol names. @@ -216,7 +216,7 @@ public class SSLContext { * * @param protocol the standard name of the requested protocol. * See the SSLContext section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SSLContext"> * Java Cryptography Architecture Standard Algorithm Name * Documentation</a> * for information about standard protocol names. @@ -256,7 +256,7 @@ public class SSLContext { * * @param protocol the standard name of the requested protocol. * See the SSLContext section in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext"> + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SSLContext"> * Java Cryptography Architecture Standard Algorithm Name * Documentation</a> * for information about standard protocol names. diff --git a/ojluni/src/main/java/javax/net/ssl/SSLParameters.java b/ojluni/src/main/java/javax/net/ssl/SSLParameters.java index 41dcf0fc63..1b9b3fb0df 100644 --- a/ojluni/src/main/java/javax/net/ssl/SSLParameters.java +++ b/ojluni/src/main/java/javax/net/ssl/SSLParameters.java @@ -257,7 +257,7 @@ public class SSLParameters { * * @param algorithm The standard string name of the endpoint * identification algorithm (or null). See Appendix A in the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> + * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA"> * Java Cryptography Architecture API Specification & Reference </a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/javax/net/ssl/TEST_MAPPING b/ojluni/src/main/java/javax/net/ssl/TEST_MAPPING new file mode 100644 index 0000000000..d3ae570f0e --- /dev/null +++ b/ojluni/src/main/java/javax/net/ssl/TEST_MAPPING @@ -0,0 +1,21 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.javax.net.ssl" + }, + { + "include-filter": "com.android.org.conscrypt.javax.net.ssl" + }, + { + "include-filter": "org.apache.harmony.tests.javax.net.ssl" + }, + { + "include-filter": "org.apache.harmony.luni.tests.internal.net.www.protocol.https" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/javax/net/ssl/TrustManagerFactory.java b/ojluni/src/main/java/javax/net/ssl/TrustManagerFactory.java index 73221698d6..d76f5fbeca 100644 --- a/ojluni/src/main/java/javax/net/ssl/TrustManagerFactory.java +++ b/ojluni/src/main/java/javax/net/ssl/TrustManagerFactory.java @@ -136,7 +136,7 @@ public class TrustManagerFactory { * * @param algorithm the standard name of the requested trust management * algorithm. See the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html"> + * "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html"> * Java Secure Socket Extension Reference Guide </a> * for information about standard algorithm names. * @@ -172,7 +172,7 @@ public class TrustManagerFactory { * * @param algorithm the standard name of the requested trust management * algorithm. See the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html"> + * "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html"> * Java Secure Socket Extension Reference Guide </a> * for information about standard algorithm names. * @@ -213,7 +213,7 @@ public class TrustManagerFactory { * * @param algorithm the standard name of the requested trust management * algorithm. See the <a href= - * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html"> + * "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html"> * Java Secure Socket Extension Reference Guide </a> * for information about standard algorithm names. * diff --git a/ojluni/src/main/java/javax/net/ssl/package.html b/ojluni/src/main/java/javax/net/ssl/package.html index 0f87f45838..52131379bd 100644 --- a/ojluni/src/main/java/javax/net/ssl/package.html +++ b/ojluni/src/main/java/javax/net/ssl/package.html @@ -37,7 +37,7 @@ and to optionally encrypt the data and/or authenticate the communicating peers. <h2>Package Specification</h2> <ul> - <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html"> + <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html"> <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture Standard Algorithm Name Documentation</b></a></li> diff --git a/ojluni/src/main/java/javax/security/auth/TEST_MAPPING b/ojluni/src/main/java/javax/security/auth/TEST_MAPPING new file mode 100644 index 0000000000..45bd9c79cc --- /dev/null +++ b/ojluni/src/main/java/javax/security/auth/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.javax.security.auth" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/javax/security/auth/callback/TEST_MAPPING b/ojluni/src/main/java/javax/security/auth/callback/TEST_MAPPING new file mode 100644 index 0000000000..e742b17123 --- /dev/null +++ b/ojluni/src/main/java/javax/security/auth/callback/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.javax.security.auth.callback" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/javax/security/auth/login/TEST_MAPPING b/ojluni/src/main/java/javax/security/auth/login/TEST_MAPPING new file mode 100644 index 0000000000..a22e2b315a --- /dev/null +++ b/ojluni/src/main/java/javax/security/auth/login/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.javax.security.auth.login" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/javax/security/auth/login/package-info.java b/ojluni/src/main/java/javax/security/auth/login/package-info.java index 6bb5a06b64..5b43480dc0 100644 --- a/ojluni/src/main/java/javax/security/auth/login/package-info.java +++ b/ojluni/src/main/java/javax/security/auth/login/package-info.java @@ -28,7 +28,7 @@ * <h2>Package Specification</h2> * * <ul> - * <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html"> + * <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html"> * <b>Java™ * Cryptography Architecture Standard Algorithm Name * Documentation</b></a></li> diff --git a/ojluni/src/main/java/javax/security/auth/x500/TEST_MAPPING b/ojluni/src/main/java/javax/security/auth/x500/TEST_MAPPING new file mode 100644 index 0000000000..3ba13dadfc --- /dev/null +++ b/ojluni/src/main/java/javax/security/auth/x500/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.javax.security.auth.x500" + }, + { + "include-filter": "org.apache.harmony.tests.javax.security.auth.x500" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/javax/security/cert/TEST_MAPPING b/ojluni/src/main/java/javax/security/cert/TEST_MAPPING new file mode 100644 index 0000000000..4603638c43 --- /dev/null +++ b/ojluni/src/main/java/javax/security/cert/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.javax.security.cert" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/javax/sql/TEST_MAPPING b/ojluni/src/main/java/javax/sql/TEST_MAPPING new file mode 100644 index 0000000000..bbbb56c71c --- /dev/null +++ b/ojluni/src/main/java/javax/sql/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.javax.sql" + }, + { + "include-filter": "org.apache.harmony.sql.tests.javax.sql" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/jdk/internal/util/Preconditions.java b/ojluni/src/main/java/jdk/internal/util/Preconditions.java new file mode 100644 index 0000000000..0e91afd869 --- /dev/null +++ b/ojluni/src/main/java/jdk/internal/util/Preconditions.java @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.util; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * Utility methods to check if state or arguments are correct. + * + */ +public class Preconditions { + + /** + * Maps out-of-bounds values to a runtime exception. + * + * @param checkKind the kind of bounds check, whose name may correspond + * to the name of one of the range check methods, checkIndex, + * checkFromToIndex, checkFromIndexSize + * @param args the out-of-bounds arguments that failed the range check. + * If the checkKind corresponds a the name of a range check method + * then the bounds arguments are those that can be passed in order + * to the method. + * @param oobef the exception formatter that when applied with a checkKind + * and a list out-of-bounds arguments returns a runtime exception. + * If {@code null} then, it is as if an exception formatter was + * supplied that returns {@link IndexOutOfBoundsException} for any + * given arguments. + * @return the runtime exception + */ + private static RuntimeException outOfBounds( + BiFunction<String, List<Integer>, ? extends RuntimeException> oobef, + String checkKind, + Integer... args) { + List<Integer> largs = List.of(args); + RuntimeException e = oobef == null + ? null : oobef.apply(checkKind, largs); + return e == null + ? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e; + } + + private static RuntimeException outOfBoundsCheckIndex( + BiFunction<String, List<Integer>, ? extends RuntimeException> oobe, + int index, int length) { + return outOfBounds(oobe, "checkIndex", index, length); + } + + private static RuntimeException outOfBoundsCheckFromToIndex( + BiFunction<String, List<Integer>, ? extends RuntimeException> oobe, + int fromIndex, int toIndex, int length) { + return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length); + } + + private static RuntimeException outOfBoundsCheckFromIndexSize( + BiFunction<String, List<Integer>, ? extends RuntimeException> oobe, + int fromIndex, int size, int length) { + return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length); + } + + /** + * Returns an out-of-bounds exception formatter from an given exception + * factory. The exception formatter is a function that formats an + * out-of-bounds message from its arguments and applies that message to the + * given exception factory to produce and relay an exception. + * + * <p>The exception formatter accepts two arguments: a {@code String} + * describing the out-of-bounds range check that failed, referred to as the + * <em>check kind</em>; and a {@code List<Integer>} containing the + * out-of-bound integer values that failed the check. The list of + * out-of-bound values is not modified. + * + * <p>Three check kinds are supported {@code checkIndex}, + * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding + * respectively to the specified application of an exception formatter as an + * argument to the out-of-bounds range check methods + * {@link #checkIndex(int, int, BiFunction) checkIndex}, + * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and + * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}. + * Thus a supported check kind corresponds to a method name and the + * out-of-bound integer values correspond to method argument values, in + * order, preceding the exception formatter argument (similar in many + * respects to the form of arguments required for a reflective invocation of + * such a range check method). + * + * <p>Formatter arguments conforming to such supported check kinds will + * produce specific exception messages describing failed out-of-bounds + * checks. Otherwise, more generic exception messages will be produced in + * any of the following cases: the check kind is supported but fewer + * or more out-of-bounds values are supplied, the check kind is not + * supported, the check kind is {@code null}, or the list of out-of-bound + * values is {@code null}. + * + * @apiNote + * This method produces an out-of-bounds exception formatter that can be + * passed as an argument to any of the supported out-of-bounds range check + * methods declared by {@code Objects}. For example, a formatter producing + * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a + * {@code static final} field as follows: + * <pre>{@code + * static final + * BiFunction<String, List<Integer>, ArrayIndexOutOfBoundsException> AIOOBEF = + * outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new); + * }</pre> + * The formatter instance {@code AIOOBEF} may be passed as an argument to an + * out-of-bounds range check method, such as checking if an {@code index} + * is within the bounds of a {@code limit}: + * <pre>{@code + * checkIndex(index, limit, AIOOBEF); + * }</pre> + * If the bounds check fails then the range check method will throw an + * {@code ArrayIndexOutOfBoundsException} with an appropriate exception + * message that is a produced from {@code AIOOBEF} as follows: + * <pre>{@code + * AIOOBEF.apply("checkIndex", List.of(index, limit)); + * }</pre> + * + * @param f the exception factory, that produces an exception from a message + * where the message is produced and formatted by the returned + * exception formatter. If this factory is stateless and side-effect + * free then so is the returned formatter. + * Exceptions thrown by the factory are relayed to the caller + * of the returned formatter. + * @param <X> the type of runtime exception to be returned by the given + * exception factory and relayed by the exception formatter + * @return the out-of-bounds exception formatter + */ + public static <X extends RuntimeException> + BiFunction<String, List<Integer>, X> outOfBoundsExceptionFormatter(Function<String, X> f) { + // Use anonymous class to avoid bootstrap issues if this method is + // used early in startup + return new BiFunction<String, List<Integer>, X>() { + @Override + public X apply(String checkKind, List<Integer> args) { + return f.apply(outOfBoundsMessage(checkKind, args)); + } + }; + } + + private static String outOfBoundsMessage(String checkKind, List<Integer> args) { + if (checkKind == null && args == null) { + return String.format("Range check failed"); + } else if (checkKind == null) { + return String.format("Range check failed: %s", args); + } else if (args == null) { + return String.format("Range check failed: %s", checkKind); + } + + int argSize = 0; + switch (checkKind) { + case "checkIndex": + argSize = 2; + break; + case "checkFromToIndex": + case "checkFromIndexSize": + argSize = 3; + break; + default: + } + + // Switch to default if fewer or more arguments than required are supplied + switch ((args.size() != argSize) ? "" : checkKind) { + case "checkIndex": + return String.format("Index %d out-of-bounds for length %d", + args.get(0), args.get(1)); + case "checkFromToIndex": + return String.format("Range [%d, %d) out-of-bounds for length %d", + args.get(0), args.get(1), args.get(2)); + case "checkFromIndexSize": + return String.format("Range [%d, %<d + %d) out-of-bounds for length %d", + args.get(0), args.get(1), args.get(2)); + default: + return String.format("Range check failed: %s %s", checkKind, args); + } + } + + /** + * Checks if the {@code index} is within the bounds of the range from + * {@code 0} (inclusive) to {@code length} (exclusive). + * + * <p>The {@code index} is defined to be out-of-bounds if any of the + * following inequalities is true: + * <ul> + * <li>{@code index < 0}</li> + * <li>{@code index >= length}</li> + * <li>{@code length < 0}, which is implied from the former inequalities</li> + * </ul> + * + * <p>If the {@code index} is out-of-bounds, then a runtime exception is + * thrown that is the result of applying the following arguments to the + * exception formatter: the name of this method, {@code checkIndex}; + * and an unmodifiable list integers whose values are, in order, the + * out-of-bounds arguments {@code index} and {@code length}. + * + * @param <X> the type of runtime exception to throw if the arguments are + * out-of-bounds + * @param index the index + * @param length the upper-bound (exclusive) of the range + * @param oobef the exception formatter that when applied with this + * method name and out-of-bounds arguments returns a runtime + * exception. If {@code null} or returns {@code null} then, it is as + * if an exception formatter produced from an invocation of + * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used + * instead (though it may be more efficient). + * Exceptions thrown by the formatter are relayed to the caller. + * @return {@code index} if it is within bounds of the range + * @throws X if the {@code index} is out-of-bounds and the exception + * formatter is non-{@code null} + * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds + * and the exception formatter is {@code null} + * @since 9 + * + * @implNote + * This method is made intrinsic in optimizing compilers to guide them to + * perform unsigned comparisons of the index and length when it is known the + * length is a non-negative value (such as that of an array length or from + * the upper bound of a loop) + */ + // Android-removed: @HotSpotIntrinsicCandidate not present on Android yet (could reconsider). + // @HotSpotIntrinsicCandidate + public static <X extends RuntimeException> + int checkIndex(int index, int length, + BiFunction<String, List<Integer>, X> oobef) { + if (index < 0 || index >= length) + throw outOfBoundsCheckIndex(oobef, index, length); + return index; + } + + /** + * Checks if the sub-range from {@code fromIndex} (inclusive) to + * {@code toIndex} (exclusive) is within the bounds of range from {@code 0} + * (inclusive) to {@code length} (exclusive). + * + * <p>The sub-range is defined to be out-of-bounds if any of the following + * inequalities is true: + * <ul> + * <li>{@code fromIndex < 0}</li> + * <li>{@code fromIndex > toIndex}</li> + * <li>{@code toIndex > length}</li> + * <li>{@code length < 0}, which is implied from the former inequalities</li> + * </ul> + * + * <p>If the sub-range is out-of-bounds, then a runtime exception is + * thrown that is the result of applying the following arguments to the + * exception formatter: the name of this method, {@code checkFromToIndex}; + * and an unmodifiable list integers whose values are, in order, the + * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}. + * + * @param <X> the type of runtime exception to throw if the arguments are + * out-of-bounds + * @param fromIndex the lower-bound (inclusive) of the sub-range + * @param toIndex the upper-bound (exclusive) of the sub-range + * @param length the upper-bound (exclusive) the range + * @param oobef the exception formatter that when applied with this + * method name and out-of-bounds arguments returns a runtime + * exception. If {@code null} or returns {@code null} then, it is as + * if an exception formatter produced from an invocation of + * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used + * instead (though it may be more efficient). + * Exceptions thrown by the formatter are relayed to the caller. + * @return {@code fromIndex} if the sub-range within bounds of the range + * @throws X if the sub-range is out-of-bounds and the exception factory + * function is non-{@code null} + * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and + * the exception factory function is {@code null} + * @since 9 + */ + public static <X extends RuntimeException> + int checkFromToIndex(int fromIndex, int toIndex, int length, + BiFunction<String, List<Integer>, X> oobef) { + if (fromIndex < 0 || fromIndex > toIndex || toIndex > length) + throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length); + return fromIndex; + } + + /** + * Checks if the sub-range from {@code fromIndex} (inclusive) to + * {@code fromIndex + size} (exclusive) is within the bounds of range from + * {@code 0} (inclusive) to {@code length} (exclusive). + * + * <p>The sub-range is defined to be out-of-bounds if any of the following + * inequalities is true: + * <ul> + * <li>{@code fromIndex < 0}</li> + * <li>{@code size < 0}</li> + * <li>{@code fromIndex + size > length}, taking into account integer overflow</li> + * <li>{@code length < 0}, which is implied from the former inequalities</li> + * </ul> + * + * <p>If the sub-range is out-of-bounds, then a runtime exception is + * thrown that is the result of applying the following arguments to the + * exception formatter: the name of this method, {@code checkFromIndexSize}; + * and an unmodifiable list integers whose values are, in order, the + * out-of-bounds arguments {@code fromIndex}, {@code size}, and + * {@code length}. + * + * @param <X> the type of runtime exception to throw if the arguments are + * out-of-bounds + * @param fromIndex the lower-bound (inclusive) of the sub-interval + * @param size the size of the sub-range + * @param length the upper-bound (exclusive) of the range + * @param oobef the exception formatter that when applied with this + * method name and out-of-bounds arguments returns a runtime + * exception. If {@code null} or returns {@code null} then, it is as + * if an exception formatter produced from an invocation of + * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used + * instead (though it may be more efficient). + * Exceptions thrown by the formatter are relayed to the caller. + * @return {@code fromIndex} if the sub-range within bounds of the range + * @throws X if the sub-range is out-of-bounds and the exception factory + * function is non-{@code null} + * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and + * the exception factory function is {@code null} + * @since 9 + */ + public static <X extends RuntimeException> + int checkFromIndexSize(int fromIndex, int size, int length, + BiFunction<String, List<Integer>, X> oobef) { + if ((length | fromIndex | size) < 0 || size > length - fromIndex) + throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length); + return fromIndex; + } +} diff --git a/ojluni/src/main/java/jdk/internal/vm/annotation/Stable.java b/ojluni/src/main/java/jdk/internal/vm/annotation/Stable.java new file mode 100644 index 0000000000..34b65403c6 --- /dev/null +++ b/ojluni/src/main/java/jdk/internal/vm/annotation/Stable.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.vm.annotation; + +import java.lang.annotation.*; + +// Android-removed: HotSpot-specific implementation notes not relevant for Android. +/** + * A field may be annotated as stable if all of its component variables + * changes value at most once. + * A field's value counts as its component value. + * If the field is typed as an array, then all the non-null components + * of the array, of depth up to the rank of the field's array type, + * also count as component values. + * By extension, any variable (either array or field) which has annotated + * as stable is called a stable variable, and its non-null or non-zero + * value is called a stable value. + * <p> + * Since all fields begin with a default value of null for references + * (resp., zero for primitives), it follows that this annotation indicates + * that the first non-null (resp., non-zero) value stored in the field + * will never be changed. + * <p> + * If the field is not of an array type, there are no array elements, + * then the value indicated as stable is simply the value of the field. + * If the dynamic type of the field value is an array but the static type + * is not, the components of the array are <em>not</em> regarded as stable. + * <p> + * If the field is an array type, then both the field value and + * all the components of the field value (if the field value is non-null) + * are indicated to be stable. + * If the field type is an array type with rank {@code N > 1}, + * then each component of the field value (if the field value is non-null), + * is regarded as a stable array of rank {@code N-1}. + * <p> + * Fields which are declared {@code final} may also be annotated as stable. + * Since final fields already behave as stable values, such an annotation + * conveys no additional information regarding change of the field's value, but + * still conveys information regarding change of additional components values if + * the type of the field is an array type (as described above). + * <p> + * It is (currently) undefined what happens if a field annotated as stable + * is given a third value (by explicitly updating a stable field, a component of + * a stable array, or a final stable field via reflection or other means). + * + * @implNote + * This annotation only takes effect for fields of classes loaded by the boot + * loader. Annoations on fields of classes loaded outside of the boot loader + * are ignored. + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Stable { +} diff --git a/ojluni/src/main/java/sun/invoke/util/TEST_MAPPING b/ojluni/src/main/java/sun/invoke/util/TEST_MAPPING new file mode 100644 index 0000000000..48ae161c6c --- /dev/null +++ b/ojluni/src/main/java/sun/invoke/util/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.sun.invoke.util" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/sun/misc/TEST_MAPPING b/ojluni/src/main/java/sun/misc/TEST_MAPPING new file mode 100644 index 0000000000..f0d2cec442 --- /dev/null +++ b/ojluni/src/main/java/sun/misc/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.org.apache.harmony.kernel.dalvik" + }, + { + "include-filter": "libcore.sun.misc" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/sun/net/util/TEST_MAPPING b/ojluni/src/main/java/sun/net/util/TEST_MAPPING new file mode 100644 index 0000000000..068b5da6b0 --- /dev/null +++ b/ojluni/src/main/java/sun/net/util/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.sun.net.util" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java index 49ad55c0bd..c680c9c266 100644 --- a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java +++ b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java @@ -237,6 +237,18 @@ class DatagramChannelImpl if (index == -1) throw new IOException("Network interface cannot be identified"); Net.setInterface6(fd, index); + // BEGIN Android-added: Apply IP_MULTICAST_IF to dual-stack sockets. + // On dual-stack sockets, IP_MULTICAST_IF sets inet_sk(sk)->mc_index and + // inet_sk(sk)->mc_addr, which are specific to IPv4, and IPV6_MULTICAST_IF sets + // inet6_sk(sk)->mcast_oif, which are specific to IPv6. For IPv4 multicast + // traffic to work over an interface that is not the default, we need to + // configure both. http://b/144222142 + Inet4Address target = Net.anyInet4Address(interf); + if (target != null) { + int targetAddress = Net.inet4AsInt(target); + Net.setInterface4(fd, targetAddress); + } + // END Android-added: Apply IP_MULTICAST_IF to dual-stack sockets. } else { // need IPv4 address to identify interface Inet4Address target = Net.anyInet4Address(interf); diff --git a/ojluni/src/main/java/sun/nio/fs/MimeTypesFileTypeDetector.java b/ojluni/src/main/java/sun/nio/fs/MimeTypesFileTypeDetector.java index 1c8f708470..585b673a00 100644 --- a/ojluni/src/main/java/sun/nio/fs/MimeTypesFileTypeDetector.java +++ b/ojluni/src/main/java/sun/nio/fs/MimeTypesFileTypeDetector.java @@ -37,7 +37,7 @@ import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import libcore.net.MimeUtils; +import libcore.content.type.MimeMap; /** * File type detector that uses a file extension to look up its MIME type @@ -46,7 +46,7 @@ import libcore.net.MimeUtils; class MimeTypesFileTypeDetector extends AbstractFileTypeDetector { - // BEGIN Android-removed: Delegate to libcore.net.MimeUtils. + // BEGIN Android-removed: Delegate to libcore.content.type.MimeMap. /* // path to mime.types file private final Path mimeTypesFile; @@ -61,7 +61,7 @@ class MimeTypesFileTypeDetector extends AbstractFileTypeDetector { mimeTypesFile = filePath; } */ - // END Android-removed: Delegate to libcore.net.MimeUtils. + // END Android-removed: Delegate to libcore.content.type.MimeMap. @Override @@ -74,7 +74,7 @@ class MimeTypesFileTypeDetector extends AbstractFileTypeDetector { if (ext.isEmpty()) return null; // no extension - // Android-removed: Delegate to libcore.net.MimeUtils. + // Android-removed: Delegate to libcore.content.type.MimeMap. // loadMimeTypes(); // if (mimeTypeMap == null || mimeTypeMap.isEmpty()) // return null; @@ -82,10 +82,10 @@ class MimeTypesFileTypeDetector extends AbstractFileTypeDetector { // Case-sensitive search String mimeType; do { - // BEGIN Android-changed: Delegate to libcore.net.MimeUtils. + // BEGIN Android-changed: Delegate to libcore.content.type.MimeMap. // mimeType = mimeTypeMap.get(ext); - mimeType = MimeUtils.guessMimeTypeFromExtension(ext); - // END Android-changed: Delegate to libcore.net.MimeUtils. + mimeType = MimeMap.getDefault().guessMimeTypeFromExtension(ext); + // END Android-changed: Delegate to libcore.content.type.MimeMap. if (mimeType == null) ext = getExtension(ext); } while (mimeType == null && !ext.isEmpty()); @@ -105,7 +105,7 @@ class MimeTypesFileTypeDetector extends AbstractFileTypeDetector { return ext; } - // BEGIN Android-removed: Delegate to libcore.net.MimeUtils. + // BEGIN Android-removed: Delegate to libcore.content.type.MimeMap. /* /** * Parse the mime types file, and store the type-extension mappings into @@ -218,5 +218,5 @@ class MimeTypesFileTypeDetector extends AbstractFileTypeDetector { } } */ - // END Android-removed: Delegate to libcore.net.MimeUtils. + // END Android-removed: Delegate to libcore.content.type.MimeMap. } diff --git a/ojluni/src/main/java/sun/nio/fs/UnixChannelFactory.java b/ojluni/src/main/java/sun/nio/fs/UnixChannelFactory.java index c6f074e594..9491fd9aae 100644 --- a/ojluni/src/main/java/sun/nio/fs/UnixChannelFactory.java +++ b/ojluni/src/main/java/sun/nio/fs/UnixChannelFactory.java @@ -47,6 +47,13 @@ class UnixChannelFactory { private static final JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); + static { + // b/151107960. This class is on the preloaded-classes-blacklist. + // It would be instantiated during AOT now without this magic + // function call and consequently fail 'atest PreloadCheck'. + dalvik.system.VMRuntime.doNotInitializeInAot(); + } + protected UnixChannelFactory() { } diff --git a/ojluni/src/main/java/sun/reflect/CallerSensitive.java b/ojluni/src/main/java/sun/reflect/CallerSensitive.java index 0c78da068f..41d6fd4d27 100644 --- a/ojluni/src/main/java/sun/reflect/CallerSensitive.java +++ b/ojluni/src/main/java/sun/reflect/CallerSensitive.java @@ -28,6 +28,7 @@ package sun.reflect; import java.lang.annotation.*; import static java.lang.annotation.ElementType.*; +// Android-added: @hide; CallerSensitive is used in source but not part of the public API /** * A method annotated @CallerSensitive is sensitive to its calling class, * via {@link sun.reflect.Reflection#getCallerClass Reflection.getCallerClass}, @@ -37,7 +38,6 @@ import static java.lang.annotation.ElementType.*; * * @hide */ -// Android-added @hide @Retention(RetentionPolicy.RUNTIME) @Target({METHOD}) public @interface CallerSensitive { diff --git a/ojluni/src/main/java/sun/security/jca/TEST_MAPPING b/ojluni/src/main/java/sun/security/jca/TEST_MAPPING new file mode 100644 index 0000000000..02e5a74982 --- /dev/null +++ b/ojluni/src/main/java/sun/security/jca/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.sun.security.jca" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/sun/security/pkcs/TEST_MAPPING b/ojluni/src/main/java/sun/security/pkcs/TEST_MAPPING new file mode 100644 index 0000000000..3f37df7409 --- /dev/null +++ b/ojluni/src/main/java/sun/security/pkcs/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.sun.security.pkcs" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/sun/security/x509/TEST_MAPPING b/ojluni/src/main/java/sun/security/x509/TEST_MAPPING new file mode 100644 index 0000000000..92012a6e6f --- /dev/null +++ b/ojluni/src/main/java/sun/security/x509/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.sun.security.x509" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/java/sun/util/logging/TEST_MAPPING b/ojluni/src/main/java/sun/util/logging/TEST_MAPPING new file mode 100644 index 0000000000..e3bb92a239 --- /dev/null +++ b/ojluni/src/main/java/sun/util/logging/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.sun.util.logging" + } + ] + } + ] +}
\ No newline at end of file diff --git a/ojluni/src/main/native/Android.bp b/ojluni/src/main/native/Android.bp index 38a2a23d33..45a5c98c7d 100644 --- a/ojluni/src/main/native/Android.bp +++ b/ojluni/src/main/native/Android.bp @@ -1,5 +1,22 @@ +// Copyright (C) 2017 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + filegroup { name: "libopenjdk_native_srcs", + visibility: [ + "//libcore", + ], srcs: [ "ZipFile.c", "Inflater.c", @@ -20,7 +37,6 @@ filegroup { "SocketChannelImpl.c", "FileChannelImpl.c", "FileDispatcherImpl.c", - "FileOutputStream_md.c", "FileInputStream.c", "FileSystemPreferences.c", "EPoll.c", diff --git a/ojluni/src/main/native/FileInputStream.c b/ojluni/src/main/native/FileInputStream.c index 58664a1f1d..650cb6c904 100644 --- a/ojluni/src/main/native/FileInputStream.c +++ b/ojluni/src/main/native/FileInputStream.c @@ -62,10 +62,15 @@ static void FileInputStream_initIDs(JNIEnv *env) { fis_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;"); } +// BEGIN Android-removed: Open files using IoBridge to share BlockGuard & StrictMode logic. +// http://b/112107427 +/* JNIEXPORT void JNICALL FileInputStream_open0(JNIEnv *env, jobject this, jstring path) { fileOpen(env, this, path, fis_fd, O_RDONLY); } +*/ +// END Android-removed: Open files using IoBridge to share BlockGuard & StrictMode logic. JNIEXPORT jlong JNICALL FileInputStream_skip0(JNIEnv *env, jobject this, jlong toSkip) { @@ -141,7 +146,6 @@ FileInputStream_available0(JNIEnv *env, jobject this) { } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(FileInputStream, open0, "(Ljava/lang/String;)V"), NATIVE_METHOD(FileInputStream, skip0, "(J)J"), NATIVE_METHOD(FileInputStream, available0, "()I"), }; diff --git a/ojluni/src/main/native/FileOutputStream_md.c b/ojluni/src/main/native/FileOutputStream_md.c deleted file mode 100644 index 73218d482e..0000000000 --- a/ojluni/src/main/native/FileOutputStream_md.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "jni.h" -#include "jni_util.h" -#include "jvm.h" - -#include "io_util.h" -#include "io_util_md.h" - -#include <fcntl.h> -#include <nativehelper/JNIHelp.h> - -#define NATIVE_METHOD(className, functionName, signature) \ -{ #functionName, signature, (void*)(className ## _ ## functionName) } - -/*******************************************************************/ -/* BEGIN JNI ********* BEGIN JNI *********** BEGIN JNI ************/ -/*******************************************************************/ - -jfieldID fos_fd; /* id for jobject 'fd' in java.io.FileOutputStream */ - -/************************************************************** - * Output stream - */ -static void FileOutputStream_initIDs(JNIEnv *env) { - jclass clazz = (*env)->FindClass(env, "java/io/FileOutputStream"); - fos_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;"); -} - - -JNIEXPORT void JNICALL -FileOutputStream_open0(JNIEnv *env, jobject this, - jstring path, jboolean append) { - fileOpen(env, this, path, fos_fd, - O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC)); -} - -static JNINativeMethod gMethods[] = { - NATIVE_METHOD(FileOutputStream, open0, "(Ljava/lang/String;Z)V"), -}; - -void register_java_io_FileOutputStream(JNIEnv* env) { - jniRegisterNativeMethods(env, "java/io/FileOutputStream", gMethods, NELEM(gMethods)); - FileOutputStream_initIDs(env); -} diff --git a/ojluni/src/main/native/OnLoad.cpp b/ojluni/src/main/native/OnLoad.cpp index ab13939a69..f0b8566d4a 100644 --- a/ojluni/src/main/native/OnLoad.cpp +++ b/ojluni/src/main/native/OnLoad.cpp @@ -35,7 +35,6 @@ extern "C" void register_sun_nio_ch_IOUtil(JNIEnv* env); extern "C" void register_sun_nio_ch_SocketChannelImpl(JNIEnv* env); extern "C" void register_sun_nio_ch_FileChannelImpl(JNIEnv* env); extern "C" void register_sun_nio_ch_FileDispatcherImpl(JNIEnv* env); -extern "C" void register_java_io_FileOutputStream(JNIEnv* env); extern "C" void register_java_io_FileInputStream(JNIEnv* env); extern "C" void register_java_util_prefs_FileSystemPreferences(JNIEnv* env); extern "C" void register_sun_nio_ch_NativeThread(JNIEnv* env); @@ -104,7 +103,6 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { register_sun_nio_ch_SocketChannelImpl(env); register_sun_nio_ch_FileChannelImpl(env); register_sun_nio_ch_FileDispatcherImpl(env); - register_java_io_FileOutputStream(env); register_java_io_FileInputStream(env); register_java_util_prefs_FileSystemPreferences(env); register_sun_nio_ch_NativeThread(env); diff --git a/ojluni/src/main/native/Register.cpp b/ojluni/src/main/native/Register.cpp deleted file mode 100644 index c550c765e7..0000000000 --- a/ojluni/src/main/native/Register.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* Copyright (C) 2014 The Android Open Source Project - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#define LOG_TAG "libcore" // We'll be next to "dalvikvm" in the log; make the distinction clear. - -#include <stdlib.h> - -#include <log/log.h> - -#include <nativehelper/ScopedLocalFrame.h> - -#include "JniConstants.h" - -extern "C" { - -extern void register_java_io_Console(JNIEnv* env); -extern void register_java_io_FileDescriptor(JNIEnv*); -extern void register_java_io_FileInputStream(JNIEnv*); -extern void register_java_io_FileOutputStream(JNIEnv*); -extern void register_java_io_ObjectInputStream(JNIEnv*); -extern void register_java_io_ObjectOutputStream(JNIEnv*); -extern void register_java_io_ObjectStreamClass(JNIEnv*); -extern void register_java_io_UnixFileSystem(JNIEnv*); -extern void register_java_lang_Double(JNIEnv*); -extern void register_java_lang_Float(JNIEnv*); -extern void register_java_lang_ProcessEnvironment(JNIEnv*); -extern void register_java_lang_Runtime(JNIEnv*); -extern void register_java_lang_StrictMath(JNIEnv*); -extern void register_java_lang_Math(JNIEnv*); -extern void register_java_lang_System(JNIEnv*); -extern void register_java_lang_Thread(JNIEnv*); -extern void register_java_lang_UNIXProcess(JNIEnv*); -extern void register_java_net_DatagramPacket(JNIEnv*); -extern void register_java_net_Inet4Address(JNIEnv*); -extern void register_java_net_Inet6Address(JNIEnv*); -extern void register_java_net_InetAddress(JNIEnv*); -extern void register_java_net_PlainDatagramSocketImpl(JNIEnv*); -extern void register_java_net_SocketInputStream(JNIEnv*); -extern void register_java_net_SocketOutputStream(JNIEnv*); -extern void register_java_nio_MappedByteBuffer(JNIEnv* env); -extern void register_java_util_zip_Adler32(JNIEnv* env); -extern void register_java_util_zip_CRC32(JNIEnv*); -extern void register_java_util_zip_Deflater(JNIEnv*); -extern void register_java_util_zip_Inflater(JNIEnv*); -extern void register_java_util_zip_ZipFile(JNIEnv*); -extern void register_java_util_prefs_FileSystemPreferences(JNIEnv*); -extern void register_sun_nio_ch_DatagramChannelImpl(JNIEnv*); -extern void register_sun_nio_ch_DatagramDispatcher(JNIEnv*); -extern void register_sun_nio_ch_FileChannelImpl(JNIEnv*); -extern void register_sun_nio_ch_FileDispatcherImpl(JNIEnv*); -extern void register_sun_nio_ch_FileKey(JNIEnv*); -extern void register_sun_nio_ch_IOUtil(JNIEnv*); -extern void register_sun_nio_ch_NativeThread(JNIEnv*); -extern void register_sun_nio_ch_Net(JNIEnv*); -extern void register_sun_nio_ch_ServerSocketChannelImpl(JNIEnv*); -extern void register_sun_nio_ch_SocketChannelImpl(JNIEnv* env); - -extern jint net_JNI_OnLoad(JavaVM*, void*); - -} - -extern void register_java_lang_Character(JNIEnv*); - -// DalvikVM calls this on startup, so we can statically register all our native methods. -jint JNI_OnLoad(JavaVM* vm, void*) { JNIEnv* env; - if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { - ALOGE("JavaVM::GetEnv() failed"); - abort(); - } - - ScopedLocalFrame localFrame(env); - register_java_util_zip_ZipFile(env); - register_java_util_zip_Inflater(env); - register_java_util_zip_Deflater(env); - register_java_util_zip_CRC32(env); - register_java_util_zip_Adler32(env); - register_sun_nio_ch_IOUtil(env); - register_sun_nio_ch_FileChannelImpl(env); - register_sun_nio_ch_FileDispatcherImpl(env); - register_java_io_Console(env); - register_java_io_FileOutputStream(env); - register_java_io_FileInputStream(env); - register_java_io_FileDescriptor(env); - register_java_io_ObjectInputStream(env); - register_java_io_ObjectOutputStream(env); - register_java_io_UnixFileSystem(env); - register_sun_nio_ch_NativeThread(env); - register_sun_nio_ch_FileKey(env); - register_java_io_ObjectStreamClass(env); - register_java_lang_Character(env); - register_java_lang_Float(env); - register_java_lang_Double(env); - register_java_lang_StrictMath(env); - register_java_lang_Math(env); - register_java_lang_ProcessEnvironment(env); - register_java_lang_Runtime(env); - register_java_lang_System(env); - register_java_lang_UNIXProcess(env); - // register_java_net_InetAddress depends on java_lang_Float & Math being - // fully registered (getMethodId on InetAddress class triggers its - // <clinit> which depends on java.lang.Float) - register_java_net_InetAddress(env); - register_java_net_Inet4Address(env); - register_java_net_Inet6Address(env); - register_java_net_SocketInputStream(env); - register_java_net_SocketOutputStream(env); - register_java_util_prefs_FileSystemPreferences(env); - register_sun_nio_ch_ServerSocketChannelImpl(env); - register_sun_nio_ch_SocketChannelImpl(env); - register_sun_nio_ch_Net(env); - register_sun_nio_ch_DatagramChannelImpl(env); - register_sun_nio_ch_DatagramDispatcher(env); - register_java_nio_MappedByteBuffer(env); - net_JNI_OnLoad(vm, NULL); - - JniConstants::Initialize(env); - return JNI_VERSION_1_6; -} - -void JNI_OnUnload(JavaVM* vm, void*) { - JniConstants::Invalidate(); -} diff --git a/ojluni/src/main/native/System.c b/ojluni/src/main/native/System.c index 6cfee92e5a..39332ce5ed 100644 --- a/ojluni/src/main/native/System.c +++ b/ojluni/src/main/native/System.c @@ -38,13 +38,12 @@ #include "openssl/opensslv.h" #include "zlib.h" #include <nativehelper/JNIHelp.h> +#include <nativehelper/jni_macros.h> + #if defined(__ANDROID__) void android_get_LD_LIBRARY_PATH(char*, size_t); #endif -#define NATIVE_METHOD(className, functionName, signature) \ -{ #functionName, signature, (void*)(className ## _ ## functionName) } - #define PUTPROP(props, key, val) \ if (1) { \ jstring jkey = (*env)->NewStringUTF(env, key); \ @@ -252,13 +251,13 @@ static void System_log(JNIEnv* env, jclass ignored, jchar type, jstring javaMess } } -static jlong System_nanoTime(JNIEnv* env, jclass unused) { +static jlong System_nanoTime() { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); return now.tv_sec * 1000000000LL + now.tv_nsec; } -static jlong System_currentTimeMillis(JNIEnv* env, jclass unused) { +static jlong System_currentTimeMillis() { return JVM_CurrentTimeMillis(NULL, NULL); } @@ -269,8 +268,8 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(System, setIn0, "(Ljava/io/InputStream;)V"), NATIVE_METHOD(System, specialProperties, "()[Ljava/lang/String;"), NATIVE_METHOD(System, log, "(CLjava/lang/String;Ljava/lang/Throwable;)V"), - NATIVE_METHOD(System, currentTimeMillis, "()J"), - NATIVE_METHOD(System, nanoTime, "()J"), + CRITICAL_NATIVE_METHOD(System, currentTimeMillis, "()J"), + CRITICAL_NATIVE_METHOD(System, nanoTime, "()J"), }; void register_java_lang_System(JNIEnv* env) { diff --git a/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java index 091b385076..c45cd96b4b 100644 --- a/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java +++ b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java @@ -176,7 +176,9 @@ public class TCKJapaneseChronology { @DataProvider(name="createByEra") Object[][] data_createByEra() { return new Object[][] { - {JapaneseEra.of(3), 2020 - YDIFF_REIWA, 2, 29, 60, LocalDate.of(2020, 2, 29)}, // NEWERA + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. + //{JapaneseEra.of(3), 2020 - YDIFF_REIWA, 2, 29, 60, LocalDate.of(2020, 2, 29)}, + {JapaneseEra.REIWA, 2020 - YDIFF_REIWA, 2, 29, 60, LocalDate.of(2020, 2, 29)}, {JapaneseEra.HEISEI, 1996 - YDIFF_HEISEI, 2, 29, 60, LocalDate.of(1996, 2, 29)}, {JapaneseEra.HEISEI, 2000 - YDIFF_HEISEI, 2, 29, 60, LocalDate.of(2000, 2, 29)}, {JapaneseEra.MEIJI, 1874 - YDIFF_MEIJI, 2, 28, 59, LocalDate.of(1874, 2, 28)}, @@ -369,8 +371,11 @@ public class TCKJapaneseChronology { @DataProvider(name="prolepticYear") Object[][] data_prolepticYear() { return new Object[][] { - {3, JapaneseEra.of(3), 1, 1 + YDIFF_REIWA, false}, - {3, JapaneseEra.of(3), 102, 102 + YDIFF_REIWA, true}, + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. + // {3, JapaneseEra.of(3), 1, 1 + YDIFF_REIWA, false}, + // {3, JapaneseEra.of(3), 102, 102 + YDIFF_REIWA, true}, + {3, JapaneseEra.REIWA, 1, 1 + YDIFF_REIWA, false}, + {3, JapaneseEra.REIWA, 102, 102 + YDIFF_REIWA, true}, {2, JapaneseEra.HEISEI, 1, 1 + YDIFF_HEISEI, false}, {2, JapaneseEra.HEISEI, 4, 4 + YDIFF_HEISEI, true}, @@ -555,7 +560,9 @@ public class TCKJapaneseChronology { { JapaneseEra.TAISHO, 0, "Taisho"}, { JapaneseEra.SHOWA, 1, "Showa"}, { JapaneseEra.HEISEI, 2, "Heisei"}, - { JapaneseEra.of(3), 3, "Reiwa"}, + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. + // { JapaneseEra.of(3), 3, "Reiwa"}, + { JapaneseEra.REIWA, 3, "Reiwa"}, }; } diff --git a/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java index e37a6a577d..afe25867e9 100644 --- a/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java +++ b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java @@ -77,7 +77,9 @@ public class TCKJapaneseEra { @DataProvider(name = "JapaneseEras") Object[][] data_of_eras() { return new Object[][] { - {JapaneseEra.of(3), "Reiwa", 3}, + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. + // {JapaneseEra.of(3), "Reiwa", 3}, + {JapaneseEra.REIWA, "Reiwa", 3}, {JapaneseEra.HEISEI, "Heisei", 2}, {JapaneseEra.SHOWA, "Showa", 1}, {JapaneseEra.TAISHO, "Taisho", 0}, diff --git a/ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java b/ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java index 03443d9158..7c6e25d3b0 100644 --- a/ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java +++ b/ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java @@ -60,7 +60,9 @@ public class TestJapaneseChronology { { JapaneseEra.SHOWA, 64, 1, 7, 1989 }, { JapaneseEra.HEISEI, 1, 1, 8, 1989 }, { JapaneseEra.HEISEI, 31, 4, 30, 2019 }, - { JapaneseEra.of(3), 1, 5, 1, 2019 }, + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. + // { JapaneseEra.of(3), 1, 5, 1, 2019 }, + { JapaneseEra.REIWA, 1, 5, 1, 2019 }, }; } @@ -78,7 +80,9 @@ public class TestJapaneseChronology { { JapaneseEra.HEISEI, 1, 1, 1, 8 }, { JapaneseEra.HEISEI, 2, 8, 1, 8 }, { JapaneseEra.HEISEI, 31, 120, 4, 30 }, - { JapaneseEra.of(3), 1, 1, 5, 1 }, + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. + // { JapaneseEra.of(3), 1, 1, 5, 1 }, + { JapaneseEra.REIWA, 1, 1, 5, 1 }, }; } @@ -111,8 +115,11 @@ public class TestJapaneseChronology { { JapaneseEra.HEISEI, 1, 1, 7 }, { JapaneseEra.HEISEI, 1, 2, 29 }, { JapaneseEra.HEISEI, 31, 5, 1 }, - { JapaneseEra.of(3), 1, 4, 30 }, - { JapaneseEra.of(3), Year.MAX_VALUE, 12, 31 }, + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. + // { JapaneseEra.of(3), 1, 4, 30 }, + // { JapaneseEra.of(3), Year.MAX_VALUE, 12, 31 }, + { JapaneseEra.REIWA, 1, 4, 30 }, + { JapaneseEra.REIWA, Year.MAX_VALUE, 12, 31 }, }; } @@ -132,9 +139,13 @@ public class TestJapaneseChronology { { JapaneseEra.HEISEI, -1 }, { JapaneseEra.HEISEI, 0 }, { JapaneseEra.HEISEI, 32 }, - { JapaneseEra.of(3), -1 }, - { JapaneseEra.of(3), 0 }, - { JapaneseEra.of(3), Year.MAX_VALUE }, + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. + // { JapaneseEra.of(3), -1 }, + // { JapaneseEra.of(3), 0 }, + // { JapaneseEra.of(3), Year.MAX_VALUE }, + { JapaneseEra.REIWA, -1 }, + { JapaneseEra.REIWA, 0 }, + { JapaneseEra.REIWA, Year.MAX_VALUE }, }; } @@ -152,8 +163,11 @@ public class TestJapaneseChronology { { JapaneseEra.HEISEI, 1, 360 }, { JapaneseEra.HEISEI, 2, 366 }, { JapaneseEra.HEISEI, 31, 121 }, - { JapaneseEra.of(3), 1, 246 }, - { JapaneseEra.of(3), 2, 367 }, + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. + // { JapaneseEra.of(3), 1, 246 }, + // { JapaneseEra.of(3), 2, 367 }, + { JapaneseEra.REIWA, 1, 246 }, + { JapaneseEra.REIWA, 2, 367 }, }; } @@ -165,7 +179,9 @@ public class TestJapaneseChronology { { "Taisho", JapaneseEra.TAISHO, null }, { "Showa", JapaneseEra.SHOWA, null }, { "Heisei", JapaneseEra.HEISEI, null }, - { "Reiwa", JapaneseEra.of(3), null }, + // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. + // { "Reiwa", JapaneseEra.of(3), null }, + { "Reiwa", JapaneseEra.REIWA, null }, { "NewEra", null, IllegalArgumentException.class}, }; } diff --git a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java index 7628eebcf2..76296dfefc 100644 --- a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java +++ b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java @@ -94,14 +94,14 @@ public class TestDateTimeTextProvider extends AbstractTestPrinterParser { {DAY_OF_WEEK, 6, TextStyle.SHORT, enUS, "Sat"}, {DAY_OF_WEEK, 7, TextStyle.SHORT, enUS, "Sun"}, - // Android-changed: upstream tests expect title case names for pt_BR, but CLDR has lower - {DAY_OF_WEEK, 1, TextStyle.SHORT, ptBR, "seg"}, - {DAY_OF_WEEK, 2, TextStyle.SHORT, ptBR, "ter"}, - {DAY_OF_WEEK, 3, TextStyle.SHORT, ptBR, "qua"}, - {DAY_OF_WEEK, 4, TextStyle.SHORT, ptBR, "qui"}, - {DAY_OF_WEEK, 5, TextStyle.SHORT, ptBR, "sex"}, - {DAY_OF_WEEK, 6, TextStyle.SHORT, ptBR, "s\u00E1b"}, - {DAY_OF_WEEK, 7, TextStyle.SHORT, ptBR, "dom"}, + // Android-changed: upstream tests expect title case names for pt_BR, but CLDR has lower with dot + {DAY_OF_WEEK, 1, TextStyle.SHORT, ptBR, "seg."}, + {DAY_OF_WEEK, 2, TextStyle.SHORT, ptBR, "ter."}, + {DAY_OF_WEEK, 3, TextStyle.SHORT, ptBR, "qua."}, + {DAY_OF_WEEK, 4, TextStyle.SHORT, ptBR, "qui."}, + {DAY_OF_WEEK, 5, TextStyle.SHORT, ptBR, "sex."}, + {DAY_OF_WEEK, 6, TextStyle.SHORT, ptBR, "s\u00E1b."}, + {DAY_OF_WEEK, 7, TextStyle.SHORT, ptBR, "dom."}, {DAY_OF_WEEK, 1, TextStyle.FULL, enUS, "Monday"}, {DAY_OF_WEEK, 2, TextStyle.FULL, enUS, "Tuesday"}, @@ -133,18 +133,19 @@ public class TestDateTimeTextProvider extends AbstractTestPrinterParser { {MONTH_OF_YEAR, 11, TextStyle.SHORT, enUS, "Nov"}, {MONTH_OF_YEAR, 12, TextStyle.SHORT, enUS, "Dec"}, - {MONTH_OF_YEAR, 1, TextStyle.SHORT, ptBR, "jan"}, - {MONTH_OF_YEAR, 2, TextStyle.SHORT, ptBR, "fev"}, - {MONTH_OF_YEAR, 3, TextStyle.SHORT, ptBR, "mar"}, - {MONTH_OF_YEAR, 4, TextStyle.SHORT, ptBR, "abr"}, - {MONTH_OF_YEAR, 5, TextStyle.SHORT, ptBR, "mai"}, - {MONTH_OF_YEAR, 6, TextStyle.SHORT, ptBR, "jun"}, - {MONTH_OF_YEAR, 7, TextStyle.SHORT, ptBR, "jul"}, - {MONTH_OF_YEAR, 8, TextStyle.SHORT, ptBR, "ago"}, - {MONTH_OF_YEAR, 9, TextStyle.SHORT, ptBR, "set"}, - {MONTH_OF_YEAR, 10, TextStyle.SHORT, ptBR, "out"}, - {MONTH_OF_YEAR, 11, TextStyle.SHORT, ptBR, "nov"}, - {MONTH_OF_YEAR, 12, TextStyle.SHORT, ptBR, "dez"}, + // Android-changed: upstream tests expect title case names for pt_BR, but CLDR has lower with dot + {MONTH_OF_YEAR, 1, TextStyle.SHORT, ptBR, "jan."}, + {MONTH_OF_YEAR, 2, TextStyle.SHORT, ptBR, "fev."}, + {MONTH_OF_YEAR, 3, TextStyle.SHORT, ptBR, "mar."}, + {MONTH_OF_YEAR, 4, TextStyle.SHORT, ptBR, "abr."}, + {MONTH_OF_YEAR, 5, TextStyle.SHORT, ptBR, "mai."}, + {MONTH_OF_YEAR, 6, TextStyle.SHORT, ptBR, "jun."}, + {MONTH_OF_YEAR, 7, TextStyle.SHORT, ptBR, "jul."}, + {MONTH_OF_YEAR, 8, TextStyle.SHORT, ptBR, "ago."}, + {MONTH_OF_YEAR, 9, TextStyle.SHORT, ptBR, "set."}, + {MONTH_OF_YEAR, 10, TextStyle.SHORT, ptBR, "out."}, + {MONTH_OF_YEAR, 11, TextStyle.SHORT, ptBR, "nov."}, + {MONTH_OF_YEAR, 12, TextStyle.SHORT, ptBR, "dez."}, {MONTH_OF_YEAR, 1, TextStyle.FULL, enUS, "January"}, {MONTH_OF_YEAR, 2, TextStyle.FULL, enUS, "February"}, diff --git a/openjdk_java_files.bp b/openjdk_java_files.bp index c1f29eaf7c..7ba860c757 100644 --- a/openjdk_java_files.bp +++ b/openjdk_java_files.bp @@ -950,6 +950,7 @@ filegroup { "ojluni/src/main/java/java/util/concurrent/ExecutorCompletionService.java", "ojluni/src/main/java/java/util/concurrent/ExecutorService.java", "ojluni/src/main/java/java/util/concurrent/Executors.java", + "ojluni/src/main/java/java/util/concurrent/Flow.java", "ojluni/src/main/java/java/util/concurrent/ForkJoinPool.java", "ojluni/src/main/java/java/util/concurrent/ForkJoinTask.java", "ojluni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java", @@ -1345,6 +1346,7 @@ filegroup { "ojluni/src/main/java/javax/sql/StatementEventListener.java", "ojluni/src/main/java/sun/reflect/CallerSensitive.java", ], + path: "ojluni/src/main/java", } // Stubs needed to satisfy javac's dependencies when compiling lambda code. These are @@ -1358,11 +1360,15 @@ filegroup { // any of these classes. filegroup { name: "openjdk_lambda_stub_files", + visibility: [ + "//libcore:__subpackages__", + ], srcs: [ "ojluni/src/lambda/java/java/lang/invoke/LambdaMetafactory.java", "ojluni/src/lambda/java/java/lang/invoke/SerializedLambda.java", ], } + filegroup { name: "openjdk_lambda_duplicate_stub_files", srcs: [ @@ -1374,6 +1380,21 @@ filegroup { ], } +// Stubs needed to satisfy javac when compiling source code that contains +// @Generated annotations, which are produced by some code generation tools. +// TODO: Remove this source file, this target, and all its dependencies, if +// the code generation tools (notably dagger) can be fixed. +// See http://b/123891440. +filegroup { + name: "openjdk_generated_annotation_stub_files", + visibility: [ + "//libcore:__subpackages__", + ], + srcs: [ + "ojluni/src/generated-annotation/java/javax/annotation/processing/Generated.java", + ], +} + // Classes which are exposed in the intra-core or core-platform APIs but not in // the public APIs. Unless they are annotated, these classes and all their // members will be exposed in all such APIs. To avoid patching the main ojluni @@ -1414,6 +1435,8 @@ filegroup { "ojluni/src/main/java/java/beans/ChangeListenerMap.java", "ojluni/src/main/java/java/time/zone/IcuZoneRulesProvider.java", "ojluni/src/main/java/java/time/zone/ZoneRulesProvider.java", + "ojluni/src/main/java/java/util/ImmutableCollections.java", + "ojluni/src/main/java/java/util/KeyValueHolder.java", "ojluni/src/main/java/java/util/JapaneseImperialCalendar.java", "ojluni/src/main/java/sun/misc/FDBigInteger.java", "ojluni/src/main/java/sun/misc/FloatingDecimal.java", @@ -1421,6 +1444,8 @@ filegroup { "ojluni/src/main/java/jdk/net/NetworkPermission.java", "ojluni/src/main/java/jdk/net/SocketFlow.java", "ojluni/src/main/java/jdk/net/Sockets.java", + "ojluni/src/main/java/jdk/internal/vm/annotation/Stable.java", + "ojluni/src/main/java/jdk/internal/util/Preconditions.java", "ojluni/src/main/java/sun/invoke/util/BytecodeDescriptor.java", "ojluni/src/main/java/sun/invoke/util/Wrapper.java", "ojluni/src/main/java/sun/invoke/util/VerifyAccess.java", @@ -1431,7 +1456,6 @@ filegroup { "ojluni/src/main/java/sun/misc/CEStreamExhausted.java", "ojluni/src/main/java/sun/misc/CharacterDecoder.java", "ojluni/src/main/java/sun/misc/CharacterEncoder.java", - "ojluni/src/main/java/sun/misc/Cleaner.java", "ojluni/src/main/java/sun/misc/CompoundEnumeration.java", "ojluni/src/main/java/sun/misc/DoubleConsts.java", "ojluni/src/main/java/sun/misc/FileURLMapper.java", @@ -1511,7 +1535,6 @@ filegroup { "ojluni/src/main/java/sun/nio/ch/DatagramSocketAdaptor.java", "ojluni/src/main/java/sun/nio/ch/DefaultAsynchronousChannelProvider.java", "ojluni/src/main/java/sun/nio/ch/DefaultSelectorProvider.java", - "ojluni/src/main/java/sun/nio/ch/DirectBuffer.java", "ojluni/src/main/java/sun/nio/ch/EPoll.java", "ojluni/src/main/java/sun/nio/ch/EPollPort.java", "ojluni/src/main/java/sun/nio/ch/ExtendedSocketOption.java", @@ -1621,13 +1644,10 @@ filegroup { "ojluni/src/main/java/sun/security/jca/JCAUtil.java", "ojluni/src/main/java/sun/security/jca/ProviderConfig.java", "ojluni/src/main/java/sun/security/jca/ProviderList.java", - "ojluni/src/main/java/sun/security/jca/Providers.java", "ojluni/src/main/java/sun/security/jca/ServiceId.java", - "ojluni/src/main/java/sun/security/pkcs/PKCS7.java", "ojluni/src/main/java/sun/security/pkcs/PKCS8Key.java", "ojluni/src/main/java/sun/security/pkcs/PKCS9Attribute.java", "ojluni/src/main/java/sun/security/pkcs/PKCS9Attributes.java", - "ojluni/src/main/java/sun/security/pkcs/SignerInfo.java", "ojluni/src/main/java/sun/security/pkcs/SigningCertificateInfo.java", "ojluni/src/main/java/sun/security/provider/CertPathProvider.java", "ojluni/src/main/java/sun/security/provider/certpath/AdaptableX509CertSelector.java", @@ -1793,11 +1813,15 @@ filegroup { // All classes, whether exposed in any API or not. filegroup { name: "openjdk_java_files", + visibility: [ + "//frameworks/base", + ], srcs: [ ":openjdk_javadoc_files", ":openjdk_mmodule_extra_files", ":openjdk_internal_files", ":openjdk_lambda_stub_files", + ":openjdk_generated_annotation_stub_files", ], } @@ -1814,8 +1838,9 @@ droidstubs { name: "openjdk-sdk-stubs-no-javadoc", srcs: [":openjdk_javadoc_files"], installable: false, - no_framework_libs: true, - args: "--exclude-documentation-from-stubs" + sdk_version: "none", + system_modules: "none", + args: "--exclude-documentation-from-stubs", } // Generates stub files for the classes exposed in the intra-core or @@ -1829,8 +1854,9 @@ droidstubs { ":openjdk_mmodule_extra_files", ], installable: false, - no_framework_libs: true, - args: "--exclude-documentation-from-stubs " - + "--hide-annotation libcore.api.Hide ", + sdk_version: "none", + system_modules: "none", + args: "--exclude-documentation-from-stubs " + + "--hide-annotation libcore.api.Hide ", merge_inclusion_annotations_dirs: ["ojluni-annotated-mmodule-stubs"], } diff --git a/support/src/test/java/libcore/java/security/CpuFeatures.java b/support/src/test/java/libcore/java/security/CpuFeatures.java index 8ab610f066..df65ed2c7b 100644 --- a/support/src/test/java/libcore/java/security/CpuFeatures.java +++ b/support/src/test/java/libcore/java/security/CpuFeatures.java @@ -16,47 +16,87 @@ package libcore.java.security; +import android.system.Os; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import dalvik.system.VMRuntime; -class CpuFeatures { - private CpuFeatures() { - } +public class CpuFeatures { + /** Machine architecture, determined from the "machine" value returned by uname() */ + private enum Arch { + // 64bit ARM can return armv8 or aarch64. + // 32bit ARM should return armv7 or armv7a + ARM("^aarch.*|^arm.*"), + // 64bit Android and Linux generally return x86_64. + // 32bit Android and Linux generally return i686 + // Other host architectures can potentially return x86 or i386. + X86("^x86.*|i386|i686"); + + private final String machineRegex; + + Arch(String machineRegex) { + this.machineRegex = machineRegex; + } - static boolean isAESHardwareAccelerated() { - // Expectations based on CPU type: If these aren't met then Conscrypt - // integration tests will fail and the cause should be investigated. - String instructionSet = VMRuntime.getCurrentInstructionSet(); - if (instructionSet.startsWith("arm")) { - // All ARM CPUs with the "aes" feature should have hardware AES. - List<String> features = getListFromCpuinfo("Features"); - if (features != null && features.contains("aes")) { - return true; + /** + * Returns the architecture of this machine by matching against output from uname() + * against the regex for each known family. + */ + public static Arch currentArch() { + String machine = Os.uname().machine; + for (Arch type : values()) { + if (machine.matches(type.machineRegex)) { + return type; + } } - } else if (instructionSet.startsWith("x86")) { - // x86 CPUs with the "aes" flag and running in 64bit mode should have hardware AES. - if ("x86_64".equals(instructionSet)) { - List<String> flags = getListFromCpuinfo("flags"); - if (flags != null && flags.contains("aes")) { - return true; + throw new IllegalStateException("Unknown machine value: " + machine); + } + } + + private enum InstructionSet { + ARM_32(Arch.ARM, "arm"), + ARM_64(Arch.ARM, "arm64"), + X86_32(Arch.X86, "x86"), + X86_64(Arch.X86, "x86_64"); + + private final Arch arch; + private final String name; + + InstructionSet(Arch arch, String name) { + this.arch = arch; + this.name = name; + } + + public Arch architecture() { + return arch; + } + + /** + * Returns the current InstructionSet set by matching against the name fields above. + */ + public static InstructionSet currentInstructionSet() { + // Always returns one of the values from VMRuntime.ABI_TO_INSTRUCTION_SET_MAP. + String instructionSet = VMRuntime.getCurrentInstructionSet(); + for (InstructionSet set : values()) { + if (instructionSet.equals(set.name)) { + return set; } - } else { - // Hardware AES not supported in 32bit mode. - return false; } + throw new IllegalStateException("Unknown instruction set: " + instructionSet); } + } - // Otherwise trust Conscrypt NativeCrypto's own checks, for example if we're in an - // emulated ABI, it might bridge to a library that has accelerated AES instructions. + private CpuFeatures() { + } + + /** + * Returns true if this device has hardware AES support as determined by BoringSSL. + */ + public static boolean isAesHardwareAccelerated() { try { Class<?> nativeCrypto = Class.forName("com.android.org.conscrypt.NativeCrypto"); Method EVP_has_aes_hardware = nativeCrypto.getDeclaredMethod("EVP_has_aes_hardware"); @@ -71,33 +111,51 @@ class CpuFeatures { return false; } - private static String getFieldFromCpuinfo(String field) { - try { - BufferedReader br = new BufferedReader(new FileReader("/proc/cpuinfo")); - Pattern p = Pattern.compile(field + "\\s*:\\s*(.*)"); - - try { - String line; - while ((line = br.readLine()) != null) { - Matcher m = p.matcher(line); - if (m.matches()) { - return m.group(1); - } - } - } finally { - br.close(); - } - } catch (IOException ignored) { + /** + * Returns true if this device should have hardware AES support based on CPU information. + * + * A return value of false means that acceleration isn't expected, but it may still be available + * e.g. via bridging to a native library in an emulated environment. + */ + public static boolean isKnownToSupportHardwareAes() { + Arch architecture = Arch.currentArch(); + InstructionSet instructionSet = InstructionSet.currentInstructionSet(); + + if (!instructionSet.architecture().equals(architecture)) { + // Different architectures imply an emulated environment, so unable to determine if + // hardware acceleration is expected. Assume not. + return false; } - return null; + if (architecture.equals(Arch.ARM)) { + // All ARM CPUs (32 and 64 bit) with the "aes" feature should have hardware AES. + return cpuFieldContainsAes("Features"); + } else if (instructionSet.equals(InstructionSet.X86_64)) { + // x86 CPUs with the "aes" flag and running in 64bit mode should have hardware AES. + // Hardware AES is not *expected* in 32bit mode, but may be available. + return cpuFieldContainsAes("flags"); + } + return false; } - private static List<String> getListFromCpuinfo(String fieldName) { - String features = getFieldFromCpuinfo(fieldName); - if (features == null) - return null; - return Arrays.asList(features.split("\\s")); + /** + * Returns true if any line in the output from /proc/cpuinfo matches the provided + * field name and contains the word "aes" in its list of values. + * + * Example line from /proc/cpuinfo: Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 + */ + private static boolean cpuFieldContainsAes(String fieldName) { + try (BufferedReader br = new BufferedReader(new FileReader("/proc/cpuinfo"))) { + String regex = "^" + fieldName + "\\s*:.*\\baes\\b.*"; + String line; + while ((line = br.readLine()) != null) { + if (line.matches(regex)) { + return true; + } + } + } catch (IOException ignored) { + } + return false; } } diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java index eb9cf458fc..7521cf962a 100644 --- a/support/src/test/java/libcore/java/security/StandardNames.java +++ b/support/src/test/java/libcore/java/security/StandardNames.java @@ -510,6 +510,7 @@ public final class StandardNames { provide("Cipher", "AES/ECB/PKCS5PADDING"); provide("Cipher", "AES/ECB/PKCS7PADDING"); provide("Cipher", "AES/GCM/NOPADDING"); + provide("Cipher", "AES/GCM-SIV/NOPADDING"); provide("Cipher", "AES/OFB/NOPADDING"); provide("Cipher", "AES/OFB/PKCS5PADDING"); provide("Cipher", "AES/OFB/PKCS7PADDING"); @@ -520,6 +521,7 @@ public final class StandardNames { provide("Cipher", "AES_128/ECB/PKCS5PADDING"); provide("Cipher", "AES_128/ECB/PKCS7PADDING"); provide("Cipher", "AES_128/GCM/NOPADDING"); + provide("Cipher", "AES_128/GCM-SIV/NOPADDING"); provide("Cipher", "AES_256/CBC/NOPADDING"); provide("Cipher", "AES_256/CBC/PKCS5PADDING"); provide("Cipher", "AES_256/CBC/PKCS7PADDING"); @@ -527,6 +529,7 @@ public final class StandardNames { provide("Cipher", "AES_256/ECB/PKCS5PADDING"); provide("Cipher", "AES_256/ECB/PKCS7PADDING"); provide("Cipher", "AES_256/GCM/NOPADDING"); + provide("Cipher", "AES_256/GCM-SIV/NOPADDING"); provide("Cipher", "DESEDE/CBC/NOPADDING"); provide("Cipher", "DESEDE/CBC/PKCS5PADDING"); provide("Cipher", "DESEDE/CBC/PKCS7PADDING"); @@ -754,7 +757,7 @@ public final class StandardNames { "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_RC4_128_MD5", "TLS_EMPTY_RENEGOTIATION_INFO_SCSV") - : CpuFeatures.isAESHardwareAccelerated() ? CIPHER_SUITES_ANDROID_AES_HARDWARE + : CpuFeatures.isAesHardwareAccelerated() ? CIPHER_SUITES_ANDROID_AES_HARDWARE : CIPHER_SUITES_ANDROID_SOFTWARE; private static final Map<String, Class<? extends KeySpec>> PRIVATE_KEY_SPEC_CLASSES; diff --git a/support/src/test/java/libcore/testing/io/TestIoUtils.java b/support/src/test/java/libcore/testing/io/TestIoUtils.java index 8e241df050..34a2cf7d4d 100644 --- a/support/src/test/java/libcore/testing/io/TestIoUtils.java +++ b/support/src/test/java/libcore/testing/io/TestIoUtils.java @@ -17,6 +17,10 @@ package libcore.testing.io; import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.Random; public class TestIoUtils { @@ -25,6 +29,13 @@ public class TestIoUtils { private TestIoUtils() {} /** + * Returns the contents of 'path' as a string. The contents are assumed to be UTF-8. + */ + public static String readFileAsString(String absolutePath) throws IOException { + return new String(Files.readAllBytes(Paths.get(absolutePath)), StandardCharsets.UTF_8); + } + + /** * Creates a unique new temporary directory under "java.io.tmpdir". */ public static File createTemporaryDirectory(String prefix) { diff --git a/support/src/test/java/org/apache/harmony/xnet/tests/support/MySSLContextSpi.java b/support/src/test/java/org/apache/harmony/xnet/tests/support/MySSLContextSpi.java index 54e2a03de3..94ca6a99e8 100644 --- a/support/src/test/java/org/apache/harmony/xnet/tests/support/MySSLContextSpi.java +++ b/support/src/test/java/org/apache/harmony/xnet/tests/support/MySSLContextSpi.java @@ -77,14 +77,14 @@ public class MySSLContextSpi extends SSLContextSpi { return null; } - protected SSLParameters engineGetDefaultSSLParameters() { + public SSLParameters engineGetDefaultSSLParameters() { engineGetSocketFactory(); - return null; + return super.engineGetDefaultSSLParameters(); } - protected SSLParameters engineGetSupportedSSLParameters() { + public SSLParameters engineGetSupportedSSLParameters() { engineGetSocketFactory(); - return null; + return super.engineGetSupportedSSLParameters(); } /* diff --git a/support/src/test/java/tests/support/Support_Configuration.java b/support/src/test/java/tests/support/Support_Configuration.java index 0856d44dee..d5fc705a6b 100644 --- a/support/src/test/java/tests/support/Support_Configuration.java +++ b/support/src/test/java/tests/support/Support_Configuration.java @@ -46,6 +46,8 @@ public class Support_Configuration { public static final String HomeAddressSoftware = "Jetty(6.0.x)"; + public static String ProxyServerTestHost = "jcltest.apache.org"; + public static final String SocksServerTestHost = "jcltest.apache.org"; public static final int SocksServerTestPort = 1080; diff --git a/test-rules/src/main/java/libcore/junit/util/EnableDeprecatedBouncyCastleAlgorithmsRule.java b/test-rules/src/main/java/libcore/junit/util/EnableDeprecatedBouncyCastleAlgorithmsRule.java new file mode 100644 index 0000000000..bfd45ef07c --- /dev/null +++ b/test-rules/src/main/java/libcore/junit/util/EnableDeprecatedBouncyCastleAlgorithmsRule.java @@ -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. + */ +package libcore.junit.util; + +import dalvik.system.VMRuntime; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.function.Supplier; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; +import sun.security.jca.Providers; + +/** + * Allows tests to temporarily enable deprecated BouncyCastle algorithms to verify that their + * behavior has not changed. + * + * <p>To use add the following to the test class. + * + * <pre> + * @Rule + * public TestRule enableDeprecatedBCAlgorithmsRule = + * EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance(); + * </pre> + * + * <p>It will give all test methods access to the deprecated algorithms. + */ +public class EnableDeprecatedBouncyCastleAlgorithmsRule implements TestRule { + + private static final TestRule INSTANCE = new EnableDeprecatedBouncyCastleAlgorithmsRule(); + + public static TestRule getInstance() { + return INSTANCE; + } + + private EnableDeprecatedBouncyCastleAlgorithmsRule() { + } + + @Override + public Statement apply(final Statement statement, Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + int currentMaximum = + Providers.getMaximumAllowableApiLevelForBcDeprecation(); + try { + int newMaximum = VMRuntime.getRuntime().getTargetSdkVersion(); + Providers.setMaximumAllowableApiLevelForBcDeprecation(newMaximum); + statement.evaluate(); + } finally { + Providers.setMaximumAllowableApiLevelForBcDeprecation(currentMaximum); + } + } + }; + } +} diff --git a/test-rules/src/main/java/libcore/junit/util/SwitchTargetSdkVersionRule.java b/test-rules/src/main/java/libcore/junit/util/SwitchTargetSdkVersionRule.java index 455d3cb8a1..b860ea68bd 100644 --- a/test-rules/src/main/java/libcore/junit/util/SwitchTargetSdkVersionRule.java +++ b/test-rules/src/main/java/libcore/junit/util/SwitchTargetSdkVersionRule.java @@ -135,8 +135,8 @@ public abstract class SwitchTargetSdkVersionRule implements TestRule { public void evaluate() throws Throwable { Object runtime = runtimeInstanceGetter.invoke(null); int oldTargetSdkVersion = (int) targetSdkVersionGetter.invoke(runtime); + targetSdkVersionSetter.invoke(runtime, targetSdkVersion); try { - targetSdkVersionSetter.invoke(runtime, targetSdkVersion); statement.evaluate(); } finally { targetSdkVersionSetter.invoke(runtime, oldTargetSdkVersion); diff --git a/test-rules/src/platform_compat/java/libcore/junit/util/CoreCompatChangeRule.java b/test-rules/src/platform_compat/java/libcore/junit/util/CoreCompatChangeRule.java new file mode 100644 index 0000000000..b526707135 --- /dev/null +++ b/test-rules/src/platform_compat/java/libcore/junit/util/CoreCompatChangeRule.java @@ -0,0 +1,123 @@ +/* + * 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. + */ + +package libcore.junit.util.compat; + +import android.compat.Compatibility; +import android.compat.Compatibility.Callbacks; +import android.compat.Compatibility.ChangeConfig; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.HashSet; +import java.util.Set; +import com.google.common.primitives.Longs; + +/** + * Allows tests to specify the which change to disable. + * + * <p>To use add the following to the test class. It will only change the behavior of a test method + * if it is annotated with {@link EnableCompatChanges} and/or {@link DisableCompatChanges}. + * + * <pre> + * @Rule + * public TestRule compatChangeRule = new CoreCompatChangeRule(); + * </pre> + * + * <p>Each test method that needs to disable a specific change needs to be annotated + * with {@link EnableCompatChanges} and/or {@link DisableCompatChanges} specifying the change id. + * e.g.: + * + * <pre> + * @Test + * @DisableCompatChanges({42}) + * public void testAsIfChange42Disabled() { + * // check behavior + * } + * + * @Test + * @EnableCompatChanges({42}) + * public void testAsIfChange42Enabled() { + * // check behavior + * + * </pre> + */ +public class CoreCompatChangeRule implements TestRule { + + @Override + public Statement apply(final Statement statement, Description description) { + Set<Long> enabled = new HashSet<>(); + Set<Long> disabled = new HashSet<>(); + EnableCompatChanges enableCompatChanges = description.getAnnotation( + EnableCompatChanges.class); + DisableCompatChanges disableCompatChanges = description.getAnnotation( + DisableCompatChanges.class); + if (enableCompatChanges != null) { + enabled.addAll(Longs.asList(enableCompatChanges.value())); + } + if (disableCompatChanges != null) { + disabled.addAll(Longs.asList(disableCompatChanges.value())); + } + ChangeConfig config = new ChangeConfig(enabled, disabled); + if (config.isEmpty()) { + return statement; + } else { + return createStatementForConfig(statement, config); + } + } + + protected Statement createStatementForConfig(final Statement statement, ChangeConfig config) { + return new CompatChangeStatement(statement, config); + } + + private static class CompatChangeStatement extends Statement { + private final Statement testStatement; + private final ChangeConfig config; + + private CompatChangeStatement(Statement testStatement, ChangeConfig config) { + this.testStatement = testStatement; + this.config = config; + } + + @Override + public void evaluate() throws Throwable { + Compatibility.setOverrides(config); + try { + testStatement.evaluate(); + } finally { + Compatibility.clearOverrides(); + } + } + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface EnableCompatChanges { + long[] value(); + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface DisableCompatChanges { + long[] value(); + } +} diff --git a/test-rules/src/test/java/android/compat/testing/DummyApi.java b/test-rules/src/test/java/android/compat/testing/DummyApi.java new file mode 100644 index 0000000000..dfe40cc022 --- /dev/null +++ b/test-rules/src/test/java/android/compat/testing/DummyApi.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.compat.testing; + +import android.compat.Compatibility; + +/** + * This is a dummy API to test gating + * + * @hide + */ +public class DummyApi { + + public static final long CHANGE_ID = 666013; + public static final long CHANGE_ID_1 = 666014; + public static final long CHANGE_ID_2 = 666015; + + /** + * Dummy method + * @return "A" if change is enabled, "B" otherwise. + */ + public static String dummyFunc() { + if (Compatibility.isChangeEnabled(CHANGE_ID)) { + return "A"; + } + return "B"; + } + + /** + * Dummy combined method + * @return "0" if {@link CHANGE_ID_1} is disabled and {@link CHANGE_ID_2} is disabled, + "1" if {@link CHANGE_ID_1} is disabled and {@link CHANGE_ID_2} is enabled, + "2" if {@link CHANGE_ID_1} is enabled and {@link CHANGE_ID_2} is disabled, + "3" if {@link CHANGE_ID_1} is enabled and {@link CHANGE_ID_2} is enabled. + */ + public static String dummyCombinedFunc() { + if (!Compatibility.isChangeEnabled(CHANGE_ID_1) + && !Compatibility.isChangeEnabled(CHANGE_ID_2)) { + return "0"; + } else if (!Compatibility.isChangeEnabled(CHANGE_ID_1) + && Compatibility.isChangeEnabled(CHANGE_ID_2)) { + return "1"; + } else if (Compatibility.isChangeEnabled(CHANGE_ID_1) + && !Compatibility.isChangeEnabled(CHANGE_ID_2)) { + return "2"; + } + return "3"; + } + +}
\ No newline at end of file diff --git a/test-rules/src/test/java/libcore/junit/util/EnableDeprecatedBouncyCastleAlgorithmsRuleTest.java b/test-rules/src/test/java/libcore/junit/util/EnableDeprecatedBouncyCastleAlgorithmsRuleTest.java new file mode 100644 index 0000000000..a08ed848c4 --- /dev/null +++ b/test-rules/src/test/java/libcore/junit/util/EnableDeprecatedBouncyCastleAlgorithmsRuleTest.java @@ -0,0 +1,56 @@ +/* + * 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. + */ +package libcore.junit.util; + +import dalvik.system.VMRuntime; +import libcore.junit.util.SwitchTargetSdkVersionRule.TargetSdkVersion; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.RuleChain; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import sun.security.jca.Providers; + +import static org.junit.Assert.assertEquals; + +/** + * Tests for {@link EnableDeprecatedBouncyCastleAlgorithmsRule}. + */ +@RunWith(JUnit4.class) +public class EnableDeprecatedBouncyCastleAlgorithmsRuleTest { + + /** + * Chain the rules together so that changes to the target sdk version will be visible in the + * bouncy castle rules. + */ + @Rule + public TestRule chain = RuleChain + .outerRule(SwitchTargetSdkVersionRule.getInstance()) + .around(EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance()); + + @Test + @TargetSdkVersion(23) + public void testRunningAsIfTargetedAtSDKVersion23() { + assertEquals(23, Providers.getMaximumAllowableApiLevelForBcDeprecation()); + } + + @Test + public void testRunningAsIfTargetedAtCurrentSDKVersion() { + assertEquals(VMRuntime.getRuntime().getTargetSdkVersion(), + Providers.getMaximumAllowableApiLevelForBcDeprecation()); + } +} diff --git a/test-rules/src/test/java/libcore/junit/util/compat/CoreCompatChangeRuleTest.java b/test-rules/src/test/java/libcore/junit/util/compat/CoreCompatChangeRuleTest.java new file mode 100644 index 0000000000..87b9446eac --- /dev/null +++ b/test-rules/src/test/java/libcore/junit/util/compat/CoreCompatChangeRuleTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package libcore.junit.util.compat; + +import static com.google.common.truth.Truth.assertThat; + +import android.compat.testing.DummyApi; + +import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; +import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests for compatibility change gating. + */ +@RunWith(JUnit4.class) +public class CoreCompatChangeRuleTest { + + @Rule + public TestRule compatChangeRule = new CoreCompatChangeRule(); + + @Test + @EnableCompatChanges({DummyApi.CHANGE_ID}) + public void testDummyGatingPositive() { + assertThat(DummyApi.dummyFunc()).isEqualTo("A"); + } + + @Test + @DisableCompatChanges({DummyApi.CHANGE_ID}) + public void testDummyGatingNegative() { + assertThat(DummyApi.dummyFunc()).isEqualTo("B"); + } + + @Test + @DisableCompatChanges({DummyApi.CHANGE_ID_1, DummyApi.CHANGE_ID_2}) + public void testDummyGatingCombined0() { + assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("0"); + } + + @Test + @DisableCompatChanges({DummyApi.CHANGE_ID_1}) + @EnableCompatChanges({DummyApi.CHANGE_ID_2}) + public void testDummyGatingCombined1() { + assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("1"); + } + + @Test + @EnableCompatChanges({DummyApi.CHANGE_ID_1}) + @DisableCompatChanges({DummyApi.CHANGE_ID_2}) + public void testDummyGatingCombined2() { + assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("2"); + } + + @Test + @EnableCompatChanges({DummyApi.CHANGE_ID_1, DummyApi.CHANGE_ID_2}) + public void testDummyGatingCombined3() { + assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("3"); + } +}
\ No newline at end of file diff --git a/tools/upstream/src/main/java/libcore/CompareUpstreams.java b/tools/upstream/src/main/java/libcore/CompareUpstreams.java index ca17f67a4a..d9588a7a4e 100644 --- a/tools/upstream/src/main/java/libcore/CompareUpstreams.java +++ b/tools/upstream/src/main/java/libcore/CompareUpstreams.java @@ -47,7 +47,7 @@ import java.util.regex.Pattern; * - The ANDROID_BUILD_TOP environment variable must be set to point to the * AOSP root directory (parent of libcore). * - * To check out upstreams OpenJDK 7u40, 8u60, 8u121-b13, and 9+181, run: + * To check out upstreams OpenJDK 7u40, 8u60, 8u121-b13, 8u222-b01 and 9+181, run: * * mkdir ~/openjdk * cd ~/openjdk @@ -58,6 +58,8 @@ import java.util.regex.Pattern; * (cd !$ ; hg update -r jdk8u121-b13 && sh get_source.sh && sh common/bin/hgforest.sh update -r jdk8u121-b13) * hg clone http://hg.openjdk.java.net/jdk8u/jdk8u60/ 8u60 * (cd !$ ; sh get_source.sh) + * hg clone http://hg.openjdk.java.net/jdk8u/jdk8u 8u222-b01 + * (cd !$ ; hg update -r jdk8u222-b01 && sh get_source.sh && sh common/bin/hgforest.sh update -r jdk8u222-b01) * hg clone http://hg.openjdk.java.net/jdk9/jdk9/ 9+181 * (cd !$ ; hg update -r jdk-9+181 && sh get_source.sh && sh common/bin/hgforest.sh update -r jdk-9+181) * @@ -69,6 +71,17 @@ import java.util.regex.Pattern; */ public class CompareUpstreams { + /** + * Whether to compare against snapshots based on (a) the output of {@link CopyUpstreamFiles}, + * as opposed to (b) directly against checked-out upstream source {@link Repository}s. + * + * Because the snapshots are currently kept on x20 which is slow to access, (b) run much + * faster (a few seconds vs. 30 minutes), but it requires the checked-out and compiled + * upstream repositories to exist which is not the case for everyone / not easily achievable + * (OpenJDK 8 requires an old C++ compiler to build). + */ + public static final boolean COMPARE_AGAINST_UPSTREAM_SNAPSHOT = true; + private final StandardRepositories standardRepositories; public CompareUpstreams(StandardRepositories standardRepositories) { @@ -153,9 +166,13 @@ public class CompareUpstreams { } headers.add("diff"); printTsv(out, headers); + + Path snapshotRoot = COMPARE_AGAINST_UPSTREAM_SNAPSHOT + ? Util.pathFromEnvOrThrow("OJLUNI_UPSTREAMS") + : null; + for (Path relPath : relPaths) { - Repository expectedUpstream = standardRepositories.referenceUpstreamAsOfAndroidP( - relPath); + Repository expectedUpstream = standardRepositories.referenceUpstream(relPath); out.print(relPath + "\t"); Path ojluniFile = standardRepositories.ojluni().absolutePath(relPath); List<String> linesB = Util.readLines(ojluniFile); @@ -167,7 +184,15 @@ public class CompareUpstreams { List<String> comparisons = new ArrayList<>(upstreams.size()); for (Repository upstream : upstreams) { final String comparison; - Path upstreamFile = upstream.absolutePath(relPath); + final Path upstreamFile; + if (COMPARE_AGAINST_UPSTREAM_SNAPSHOT) { + Path maybePath = snapshotRoot + .resolve(upstream.name()) + .resolve(relPath); + upstreamFile = maybePath.toFile().exists() ? maybePath : null; + } else { + upstreamFile = upstream.absolutePath(relPath); + } if (upstreamFile == null) { comparison = "missing"; } else { diff --git a/tools/upstream/src/main/java/libcore/CopyUpstreamFiles.java b/tools/upstream/src/main/java/libcore/CopyUpstreamFiles.java index 713786170e..807607fe4b 100644 --- a/tools/upstream/src/main/java/libcore/CopyUpstreamFiles.java +++ b/tools/upstream/src/main/java/libcore/CopyUpstreamFiles.java @@ -45,8 +45,7 @@ public class CopyUpstreamFiles { } } for (Path relPath : relPaths) { - Repository expectedUpstream = standardRepositories.referenceUpstreamAsOfAndroidP( - relPath); + Repository expectedUpstream = standardRepositories.referenceUpstream(relPath); for (Repository upstream : standardRepositories.upstreams()) { Path upstreamFile = upstream.absolutePath(relPath); if (upstreamFile != null) { diff --git a/tools/upstream/src/main/java/libcore/Repository.java b/tools/upstream/src/main/java/libcore/Repository.java index 89f64f0a7e..4c7bbd7aef 100644 --- a/tools/upstream/src/main/java/libcore/Repository.java +++ b/tools/upstream/src/main/java/libcore/Repository.java @@ -27,6 +27,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -232,18 +234,19 @@ abstract class Repository { */ public List<Path> loadRelPathsFromBlueprint() throws IOException { List<Path> result = new ArrayList<>(); - result.addAll(loadRelPathsFromBlueprint( + result.addAll(loadOrderedRelPathsSetFromBlueprint( "openjdk_java_files.bp", "\"ojluni/src/main/java/(.+\\.java)\"")); - result.addAll(loadRelPathsFromBlueprint( + result.addAll(loadOrderedRelPathsSetFromBlueprint( "ojluni/src/main/native/Android.bp", "\\s+\"(.+\\.(?:c|cpp))\",")); return result; } - private List<Path> loadRelPathsFromBlueprint( + private Set<Path> loadOrderedRelPathsSetFromBlueprint( String blueprintPathString, String patternString) throws IOException { Path blueprintPath = rootPath.resolve(blueprintPathString); Pattern pattern = Pattern.compile(patternString); - List<Path> result = new ArrayList<>(); + // Use TreeSet to sort and de-duplicate the result. + Set<Path> result = new TreeSet<>(); for (String line : Util.readLines(blueprintPath)) { Matcher matcher = pattern.matcher(line); while (matcher.find()) { @@ -251,7 +254,6 @@ abstract class Repository { result.add(relPath); } } - Collections.sort(result); return result; } diff --git a/tools/upstream/src/main/java/libcore/StandardRepositories.java b/tools/upstream/src/main/java/libcore/StandardRepositories.java index 3bdbebfdab..7047c6009f 100644 --- a/tools/upstream/src/main/java/libcore/StandardRepositories.java +++ b/tools/upstream/src/main/java/libcore/StandardRepositories.java @@ -35,8 +35,10 @@ public class StandardRepositories { private final List<Repository> allUpstreams; // upstreams older than what is currently the default private final List<Repository> historicUpstreams; + private final Repository openJdk8u222; private final Repository openJdk8u121; private final Repository openJdk9b113; + private final Repository openJdk9p181; private final Repository openJdk7u40; private final OjluniRepository ojluni; @@ -46,6 +48,8 @@ public class StandardRepositories { allUpstreams.add(openJdk9(upstreamRoot, "9+181")); this.openJdk9b113 = addAndReturn(allUpstreams, openJdk9(upstreamRoot, "9b113+")); this.openJdk8u121 = addAndReturn(allUpstreams, openJdkLegacy(upstreamRoot, "8u121-b13")); + this.openJdk8u222 = addAndReturn(allUpstreams, openJdkLegacy(upstreamRoot, "8u222-b01")); + this.openJdk9p181 = addAndReturn(allUpstreams, openJdk9(upstreamRoot, "9+181")); Repository openJdk8u60 = addAndReturn(allUpstreams, openJdkLegacy(upstreamRoot, "8u60")); this.openJdk7u40 = addAndReturn(allUpstreams, openJdkLegacy(upstreamRoot, "7u40")); this.allUpstreams = Collections.unmodifiableList(new ArrayList<>(allUpstreams)); @@ -76,19 +80,11 @@ public class StandardRepositories { } public static StandardRepositories fromEnv() { - Path androidBuildTop = Paths.get(getEnvOrThrow("ANDROID_BUILD_TOP")); - Path upstreamRoot = Paths.get(getEnvOrThrow("OPENJDK_HOME")); + Path androidBuildTop = Util.pathFromEnvOrThrow("ANDROID_BUILD_TOP"); + Path upstreamRoot = Util.pathFromEnvOrThrow("OPENJDK_HOME"); return new StandardRepositories(androidBuildTop, upstreamRoot); } - private static String getEnvOrThrow(String name) { - String result = System.getenv(name); - if (result == null) { - throw new IllegalStateException("Environment variable undefined: " + name); - } - return result; - } - private static final Set<String> juFilesFromJsr166 = Collections.unmodifiableSet( new HashSet<>(Arrays.asList( "AbstractQueue", @@ -117,9 +113,41 @@ public class StandardRepositories { return result; } - public Repository referenceUpstreamAsOfAndroidP(Path relPath) { + private static final Set<String> REL_PATHS_AT_OPENJDK9_181 = Collections.unmodifiableSet( + new HashSet<>(Arrays.asList( + "java/util/concurrent/Flow.java", + "java/util/AbstractList.java", + "java/util/ImmutableCollections.java", + "java/util/KeyValueHolder.java", + "java/util/List.java", + "java/util/Map.java", + "java/util/Objects.java", + "java/util/Set.java", + "jdk/internal/HotSpotIntrinsicCandidate.java", + "jdk/internal/vm/annotation/Stable.java", + "jdk/internal/util/Preconditions.java" + ))); + + private static final Set<String> REL_PATHS_AT_OPENJDK8_222 = Collections.unmodifiableSet( + new HashSet<>(Arrays.asList( + "java/time/chrono/JapaneseEra.java", + "java/util/JapaneseImperialCalendar.java", + "sun/util/calendar/Era.java", + // Tests: + "java/time/tck/java/time/chrono/TCKJapaneseChronology.java", + "java/time/tck/java/time/chrono/TCKJapaneseEra.java", + "java/time/test/java/time/chrono/TestJapaneseChronology.java", + "java/time/test/java/time/chrono/TestUmmAlQuraChronology.java", + "java/time/test/java/time/format/TestNonIsoFormatter.java" + ))); + + public Repository referenceUpstream(Path relPath) { boolean isJsr166 = isJsr166(relPath); - if (isJsr166) { + if (REL_PATHS_AT_OPENJDK9_181.contains(relPath.toString())) { + return openJdk9p181; + } else if (REL_PATHS_AT_OPENJDK8_222.contains(relPath.toString())) { + return openJdk8u222; + } else if (isJsr166) { return openJdk9b113; } else if (relPath.startsWith("java/sql/") || relPath.startsWith("javax/sql/")) { return openJdk7u40; diff --git a/tools/upstream/src/main/java/libcore/Util.java b/tools/upstream/src/main/java/libcore/Util.java index c50e99028f..0f69c5fdb0 100644 --- a/tools/upstream/src/main/java/libcore/Util.java +++ b/tools/upstream/src/main/java/libcore/Util.java @@ -26,6 +26,7 @@ import java.io.PrintWriter; import java.io.Reader; import java.io.Writer; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @@ -36,6 +37,23 @@ class Util { private Util() { } + public static Path pathFromEnvOrThrow(String name) { + String envValue = getEnvOrThrow(name); + Path result = Paths.get(envValue); + if (!result.toFile().exists()) { + throw new IllegalArgumentException("Path not found: " + result); + } + return result; + } + + private static String getEnvOrThrow(String name) { + String result = System.getenv(name); + if (result == null) { + throw new IllegalStateException("Environment variable undefined: " + name); + } + return result; + } + public static Lines readLines(Reader reader) throws IOException { List<String> result = new ArrayList<>(); BufferedReader br = (reader instanceof BufferedReader) diff --git a/xml/src/main/java/com/android/org/kxml2/io/TEST_MAPPING b/xml/src/main/java/com/android/org/kxml2/io/TEST_MAPPING new file mode 100644 index 0000000000..d8c9759fae --- /dev/null +++ b/xml/src/main/java/com/android/org/kxml2/io/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.xml" + } + ] + } + ] +}
\ No newline at end of file diff --git a/xml/src/main/java/org/xmlpull/v1/TEST_MAPPING b/xml/src/main/java/org/xmlpull/v1/TEST_MAPPING new file mode 100644 index 0000000000..d8c9759fae --- /dev/null +++ b/xml/src/main/java/org/xmlpull/v1/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "libcore.xml" + } + ] + } + ] +}
\ No newline at end of file diff --git a/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java b/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java index bb3d130249..b3cb8552b7 100644 --- a/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java +++ b/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java @@ -661,7 +661,7 @@ public interface XmlPullParser { int getLineNumber(); /** - * Returns the current column number, starting from 0. + * Returns the current column number, starting from 1. * When the parser does not know the current column number * or can not determine it, -1 is returned (e.g. for WBXML). * |