diff options
Diffstat (limited to 'tests')
55 files changed, 1795 insertions, 372 deletions
diff --git a/tests/AttestationVerificationTest/OWNERS b/tests/AttestationVerificationTest/OWNERS new file mode 100644 index 000000000000..a7a6ef156eda --- /dev/null +++ b/tests/AttestationVerificationTest/OWNERS @@ -0,0 +1 @@ +include /core/java/android/security/attestationverification/OWNERS diff --git a/tests/BootImageProfileTest/OWNERS b/tests/BootImageProfileTest/OWNERS index 7ee0d9a5e77e..57303e748738 100644 --- a/tests/BootImageProfileTest/OWNERS +++ b/tests/BootImageProfileTest/OWNERS @@ -1,4 +1,4 @@ calin@google.com -mathieuc@google.com ngeoffray@google.com +vmarko@google.com yawanng@google.com diff --git a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java index 4ecca2dc4c39..cf5658644a61 100644 --- a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java +++ b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java @@ -31,6 +31,8 @@ public class BootImageProfileTest implements IDeviceTest { private static final String SYSTEM_SERVER_PROFILE = "/data/misc/profiles/cur/0/android/primary.prof"; private static final boolean USE_PHENOTYPE = false; + private static final String DALVIK_VM_EXTRA_OPTS = + "-Xusejit:false -Xint -Xjitsaveprofilinginfo"; @Override public void setDevice(ITestDevice testDevice) { @@ -54,10 +56,10 @@ public class BootImageProfileTest implements IDeviceTest { private String setProperty(String property, String value) throws Exception { if (USE_PHENOTYPE) { return mTestDevice.executeShellCommand( - "device_config put runtime_native_boot " + property + " " + value); + String.format("device_config put runtime_native_boot %s '%s'", property, value)); } else { return mTestDevice.executeShellCommand( - "setprop dalvik.vm." + property + " " + value); + String.format("setprop dalvik.vm.%s '%s'", property, value)); } } @@ -69,6 +71,8 @@ public class BootImageProfileTest implements IDeviceTest { assertTrue("profile boot class path not enabled: " + res, "true".equals(res)); res = getProperty("profilesystemserver"); assertTrue("profile system server not enabled: " + res, "true".equals(res)); + res = getProperty("extra-opts"); + assertTrue("extra options not set: " + res, DALVIK_VM_EXTRA_OPTS.equals(res)); } private boolean forceSaveProfile(String pkg) throws Exception { @@ -91,16 +95,20 @@ public class BootImageProfileTest implements IDeviceTest { boolean profileBootClassPath = "true".equals(pbcp); String pss = getProperty("profilesystemserver"); boolean profileSystemServer = "true".equals(pss); - if (profileBootClassPath && profileSystemServer) { + String extraOpts = getProperty("extra-opts"); + boolean extraOptsOk = DALVIK_VM_EXTRA_OPTS.equals(extraOpts); + if (profileBootClassPath && profileSystemServer && extraOptsOk) { break; } if (i == numIterations) { assertTrue("profile system server not enabled: " + pss, profileSystemServer); assertTrue("profile boot class path not enabled: " + pbcp, profileBootClassPath); + assertTrue("extra options not set: " + extraOpts, extraOptsOk); } setProperty("profilebootclasspath", "true"); setProperty("profilesystemserver", "true"); + setProperty("extra-opts", DALVIK_VM_EXTRA_OPTS); Thread.sleep(1000); } @@ -114,12 +122,15 @@ public class BootImageProfileTest implements IDeviceTest { boolean profileBootClassPath = "true".equals(pbcp); String pss = getProperty("profilesystemserver"); boolean profileSystemServer = "true".equals(pss); + String extraOpts = getProperty("extra-opts"); + boolean extraOptsOk = DALVIK_VM_EXTRA_OPTS.equals(extraOpts); if (profileBootClassPath && profileSystemServer) { break; } if (i == numIterations) { assertTrue("profile system server not enabled: " + pss, profileSystemServer); assertTrue("profile boot class path not enabled: " + pbcp, profileBootClassPath); + assertTrue("extra options not set: " + extraOpts, extraOptsOk); } Thread.sleep(1000); } diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/.project b/tests/Camera2Tests/SmartCamera/SimpleCamera/.project deleted file mode 100644 index 2517e2d4f93d..000000000000 --- a/tests/Camera2Tests/SmartCamera/SimpleCamera/.project +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>CameraShoot</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>org.eclipse.jdt.core.javabuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>com.android.ide.eclipse.adt.ApkBuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>com.android.ide.eclipse.adt.AndroidNature</nature> - <nature>org.eclipse.jdt.core.javanature</nature> - </natures> -</projectDescription> diff --git a/tests/DynamicCodeLoggerIntegrationTests/Android.bp b/tests/DynamicCodeLoggerIntegrationTests/Android.bp new file mode 100644 index 000000000000..448d46fe5e4e --- /dev/null +++ b/tests/DynamicCodeLoggerIntegrationTests/Android.bp @@ -0,0 +1,60 @@ +// +// 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. +// + +package { + default_applicable_licenses: ["frameworks_base_license"], +} + +java_test_helper_library { + name: "DynamicCodeLoggerTestLibrary", + srcs: ["src/com/android/dcl/**/*.java"], + +} + +cc_library_shared { + name: "DynamicCodeLoggerNativeTestLibrary", + srcs: ["src/cpp/com_android_dcl_Jni.cpp"], + header_libs: ["jni_headers"], + sdk_version: "28", + stl: "c++_static", +} + +cc_binary { + name: "DynamicCodeLoggerNativeExecutable", + srcs: ["src/cpp/test_executable.cpp"], +} + +android_test { + name: "DynamicCodeLoggerIntegrationTests", + + sdk_version: "current", + test_suites: ["device-tests"], + certificate: "shared", + srcs: ["src/com/android/server/pm/**/*.java"], + + static_libs: [ + "androidx.test.rules", + "truth-prebuilt", + ], + + compile_multilib: "both", + jni_libs: ["DynamicCodeLoggerNativeTestLibrary"], + + java_resources: [ + ":DynamicCodeLoggerTestLibrary", + ":DynamicCodeLoggerNativeExecutable", + ], +} diff --git a/tests/DynamicCodeLoggerIntegrationTests/Android.mk b/tests/DynamicCodeLoggerIntegrationTests/Android.mk deleted file mode 100644 index dab83046c28f..000000000000 --- a/tests/DynamicCodeLoggerIntegrationTests/Android.mk +++ /dev/null @@ -1,95 +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. -# - -LOCAL_PATH:= $(call my-dir) - -# Build a tiny library that the test app can dynamically load - -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests -LOCAL_MODULE := DynamicCodeLoggerTestLibrary -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE -LOCAL_SRC_FILES := $(call all-java-files-under, src/com/android/dcl) - -include $(BUILD_JAVA_LIBRARY) - -dynamiccodeloggertest_jar := $(LOCAL_BUILT_MODULE) - - -# Also build a native library that the test app can dynamically load - -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests -LOCAL_MODULE := DynamicCodeLoggerNativeTestLibrary -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE -LOCAL_SRC_FILES := src/cpp/com_android_dcl_Jni.cpp -LOCAL_HEADER_LIBRARIES := jni_headers -LOCAL_SDK_VERSION := 28 -LOCAL_NDK_STL_VARIANT := c++_static - -include $(BUILD_SHARED_LIBRARY) - -# And a standalone native executable that we can exec. - -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests -LOCAL_MODULE := DynamicCodeLoggerNativeExecutable -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE -LOCAL_SRC_FILES := src/cpp/test_executable.cpp - -include $(BUILD_EXECUTABLE) - -dynamiccodeloggertest_executable := $(LOCAL_BUILT_MODULE) - -# Build the test app itself - -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests -LOCAL_PACKAGE_NAME := DynamicCodeLoggerIntegrationTests -LOCAL_SDK_VERSION := current -LOCAL_COMPATIBILITY_SUITE := device-tests -LOCAL_CERTIFICATE := shared -LOCAL_SRC_FILES := $(call all-java-files-under, src/com/android/server/pm) - -LOCAL_STATIC_JAVA_LIBRARIES := \ - androidx.test.rules \ - truth-prebuilt \ - -# Include both versions of the .so if we have 2 arch -LOCAL_MULTILIB := both -LOCAL_JNI_SHARED_LIBRARIES := \ - DynamicCodeLoggerNativeTestLibrary \ - -# This gets us the javalib.jar built by DynamicCodeLoggerTestLibrary above as well as the various -# native binaries. -LOCAL_JAVA_RESOURCE_FILES := \ - $(dynamiccodeloggertest_jar) \ - $(dynamiccodeloggertest_executable) \ - -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE -include $(BUILD_PACKAGE) diff --git a/tests/DynamicCodeLoggerIntegrationTests/OWNERS b/tests/DynamicCodeLoggerIntegrationTests/OWNERS new file mode 100644 index 000000000000..d9eb1413cb1e --- /dev/null +++ b/tests/DynamicCodeLoggerIntegrationTests/OWNERS @@ -0,0 +1 @@ +file:/services/core/java/com/android/server/pm/dex/OWNERS diff --git a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java index 883c172e4990..5430dee5ca31 100644 --- a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java +++ b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java @@ -114,7 +114,8 @@ public final class DynamicCodeLoggerIntegrationTests { // Obtained via "echo -n copied.jar | sha256sum" String expectedNameHash = "1B6C71DB26F36582867432CCA12FB6A517470C9F9AABE9198DD4C5C030D6DC0C"; - String expectedContentHash = copyAndHashResource("/javalib.jar", privateCopyFile); + String expectedContentHash = copyAndHashResource( + "/DynamicCodeLoggerTestLibrary.jar", privateCopyFile); // Feed the jar to a class loader and make sure it contains what we expect. ClassLoader parentClassLoader = sContext.getClass().getClassLoader(); @@ -135,7 +136,8 @@ public final class DynamicCodeLoggerIntegrationTests { File privateCopyFile = privateFile("copied2.jar"); String expectedNameHash = "202158B6A3169D78F1722487205A6B036B3F2F5653FDCFB4E74710611AC7EB93"; - String expectedContentHash = copyAndHashResource("/javalib.jar", privateCopyFile); + String expectedContentHash = copyAndHashResource( + "/DynamicCodeLoggerTestLibrary.jar", privateCopyFile); // This time make sure an unknown class loader is an ancestor of the class loader we use. ClassLoader knownClassLoader = sContext.getClass().getClassLoader(); diff --git a/tests/FlickerTests/OWNERS b/tests/FlickerTests/OWNERS index b5561010e7f9..c1221e3940d2 100644 --- a/tests/FlickerTests/OWNERS +++ b/tests/FlickerTests/OWNERS @@ -1,3 +1,4 @@ # Bug component: 909476 include /services/core/java/com/android/server/wm/OWNERS -natanieljr@google.com
\ No newline at end of file +natanieljr@google.com +pablogamito@google.com diff --git a/tests/HwAccelerationTest/.project b/tests/HwAccelerationTest/.project deleted file mode 100644 index 7c04d3cb6426..000000000000 --- a/tests/HwAccelerationTest/.project +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>HwAccelerationTest</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>org.eclipse.jdt.core.javabuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>com.android.ide.eclipse.adt.ApkBuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>com.android.ide.eclipse.adt.AndroidNature</nature> - <nature>org.eclipse.jdt.core.javanature</nature> - </natures> -</projectDescription> diff --git a/tests/LockTaskTests/Android.bp b/tests/LockTaskTests/Android.bp new file mode 100644 index 000000000000..dce681ead4b0 --- /dev/null +++ b/tests/LockTaskTests/Android.bp @@ -0,0 +1,32 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["frameworks_base_license"], +} + +android_app { + name: "LockTaskTests", + + privileged: true, + + sdk_version: "current", + certificate: "platform", + + srcs: [ + "src/**/I*.aidl", + "src/**/*.java", + ], + +} diff --git a/tests/LockTaskTests/Android.mk b/tests/LockTaskTests/Android.mk deleted file mode 100644 index 5406ee19041b..000000000000 --- a/tests/LockTaskTests/Android.mk +++ /dev/null @@ -1,19 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/priv-app - -LOCAL_PACKAGE_NAME := LockTaskTests -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE -LOCAL_SDK_VERSION := current -LOCAL_CERTIFICATE := platform - -LOCAL_SRC_FILES := $(call all-Iaidl-files-under, src) $(call all-java-files-under, src) - -include $(BUILD_PACKAGE) - -# Use the following include to make our test apk. -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tests/SharedLibraryLoadingTest/Android.bp b/tests/SharedLibraryLoadingTest/Android.bp new file mode 100644 index 000000000000..088278d6ee89 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/Android.bp @@ -0,0 +1,37 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +java_test_host { + name: "SharedLibraryLoadingTests", + libs: [ + "tradefed", + "junit", + ], + test_suites: ["general-tests"], + data: [ + ":SharedLibraryLoadingTests_StandardSharedLibrary", + ":SharedLibraryLoadingTests_SharedLibraryLoadedAfter", + ":SharedLibraryLoadingTests_SharedLibraryClientTests", + ":SharedLibraryLoadingTests_Overlay", + ], +} diff --git a/tests/SharedLibraryLoadingTest/AndroidTest.xml b/tests/SharedLibraryLoadingTest/AndroidTest.xml new file mode 100644 index 000000000000..947453d07bd9 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/AndroidTest.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT 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="Host-driven test module config for SharedLibraryHostTests"> + <option name="test-tag" value="SharedLibraryLoadingTests" /> + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="apct-instrumentation" /> + + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" /> + <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher"> + <option name="cleanup" value="false" /> + <option name="remount-system" value="true" /> + <option name="push" + value="SharedLibraryLoadingTests_StandardSharedLibrary.apk->/product/app/SharedLibraryLoadingTests_StandardSharedLibrary.apk" /> + <option name="push" + value="SharedLibraryLoadingTests_SharedLibraryLoadedAfter.apk->/product/app/SharedLibraryLoadingTests_SharedLibraryLoadedAfter.apk" /> + <option name="push" + value="SharedLibraryLoadingTests_Overlay.apk->/product/overlay/SharedLibraryLoadingTests_Overlay.apk" /> + </target_preparer> + + <target_preparer class="com.android.tradefed.targetprep.RebootTargetPreparer" /> + + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="cleanup-apks" value="true" /> + <option name="test-file-name" value="SharedLibraryLoadingTests_SharedLibraryClientTests.apk" /> + </target_preparer> + + <test class="com.android.tradefed.testtype.AndroidJUnitTest"> + <option name="package" value="com.android.sharedlibloadingtest.client" /> + </test> +</configuration>
\ No newline at end of file diff --git a/tests/SharedLibraryLoadingTest/OWNERS b/tests/SharedLibraryLoadingTest/OWNERS new file mode 100644 index 000000000000..d7b4569b6bc0 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/OWNERS @@ -0,0 +1,2 @@ +stenning@google.com + diff --git a/tests/SharedLibraryLoadingTest/test-apps/Overlay/Android.bp b/tests/SharedLibraryLoadingTest/test-apps/Overlay/Android.bp new file mode 100644 index 000000000000..b2f4e8925b58 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/Overlay/Android.bp @@ -0,0 +1,29 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +android_test_helper_app { + name: "SharedLibraryLoadingTests_Overlay", + platform_apis: true, + certificate: "platform", + aaptflags: ["--no-resource-removal"], +} diff --git a/tests/SharedLibraryLoadingTest/test-apps/Overlay/AndroidManifest.xml b/tests/SharedLibraryLoadingTest/test-apps/Overlay/AndroidManifest.xml new file mode 100644 index 000000000000..ae2784ca0904 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/Overlay/AndroidManifest.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT 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="com.android.sharedlibloadingtest.overlay"> + <application android:hasCode="false" /> + <overlay android:targetPackage="android" + android:isStatic="true" + android:priority="1"/> +</manifest>
\ No newline at end of file diff --git a/tests/SharedLibraryLoadingTest/test-apps/Overlay/res/values/config.xml b/tests/SharedLibraryLoadingTest/test-apps/Overlay/res/values/config.xml new file mode 100644 index 000000000000..15da3dbafd84 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/Overlay/res/values/config.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2020 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<resources> + <string-array name="config_sharedLibrariesLoadedAfterApp" translatable="false"> + <item>com.android.sharedlibloadingtest.shared_library_after</item> + </string-array> +</resources>
\ No newline at end of file diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/Android.bp b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/Android.bp new file mode 100644 index 000000000000..0d204979cb92 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/Android.bp @@ -0,0 +1,35 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +android_test_helper_app { + name: "SharedLibraryLoadingTests_SharedLibraryClientTests", + srcs: ["**/*.java"], + resource_dirs: ["res"], + libs: [ + "SharedLibraryLoadingTests_StandardSharedLibrary", + "SharedLibraryLoadingTests_SharedLibraryLoadedAfter", + "android.test.base", + ], + static_libs: [ + "androidx.test.ext.junit", + "androidx.test.rules", + "androidx.test.core", + "testng", + ], + platform_apis: true, +} diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/AndroidManifest.xml b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/AndroidManifest.xml new file mode 100644 index 000000000000..e3a9b9bca78a --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/AndroidManifest.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT 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="com.android.sharedlibloadingtest.client"> + <application> + <uses-library android:name="android.test.runner" /> + <uses-library android:name="com.android.sharedlibloadingtest.shared_library"/> + <uses-library android:name="com.android.sharedlibloadingtest.shared_library_after"/> + </application> + + <instrumentation + android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.sharedlibloadingtest.client" /> +</manifest>
\ No newline at end of file diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/res/values/values.xml b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/res/values/values.xml new file mode 100644 index 000000000000..5e0544eb8696 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/res/values/values.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<resources> + <string name="identical_resource_key">client value</string> +</resources>
\ No newline at end of file diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/ClientClass.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/ClientClass.java new file mode 100644 index 000000000000..e48fb833bd76 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/ClientClass.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.sharedlibloadingtest; + +public class ClientClass { + @Override + public String toString() { + return "Client Code"; + } +} diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassA.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassA.java new file mode 100644 index 000000000000..4c771557e119 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassA.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.sharedlibloadingtest; + +public class DuplicateClassA { + @Override + public String toString() { + return "Client's Version"; + } +} diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassB.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassB.java new file mode 100644 index 000000000000..86aa6a1a0901 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassB.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.sharedlibloadingtest; + +public class DuplicateClassB { + @Override + public String toString() { + return "Client's Version B"; + } +} diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/client/SharedLibraryLoadingOrderTest.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/client/SharedLibraryLoadingOrderTest.java new file mode 100644 index 000000000000..43bcb1ad7d27 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/client/SharedLibraryLoadingOrderTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.sharedlibloadingtest.client; + +import static org.testng.Assert.assertEquals; + +import android.content.Context; +import android.content.res.Resources; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.internal.util.Preconditions; +import com.android.sharedlibloadingtest.ClientClass; +import com.android.sharedlibloadingtest.DuplicateClassA; +import com.android.sharedlibloadingtest.DuplicateClassB; +import com.android.sharedlibloadingtest.SharedClassAfter; +import com.android.sharedlibloadingtest.StdSharedClass; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Collections; +import java.util.HashSet; + +@RunWith(AndroidJUnit4.class) +public class SharedLibraryLoadingOrderTest { + + @Test + public void testLoadingOfStdShareLibsShouldBeFirst() { + Preconditions.checkArgument(!getLibsLoadedAfter() + .contains("com.android.sharedlibloadingtest.shared_library")); + DuplicateClassA clazz = new DuplicateClassA(); + assertEquals(clazz.toString(), "Standard Shared Lib's Version"); + + StdSharedClass stdSharedClass = new StdSharedClass(); + assertEquals(stdSharedClass.toString(), "Nothing Special Lib"); + + ClientClass clientCode = new ClientClass(); + assertEquals(clientCode.toString(), "Client Code"); + } + + @Test + public void testLoadingOfShareLibsIsAfter() { + Preconditions.checkArgument(getLibsLoadedAfter() + .contains("com.android.sharedlibloadingtest.shared_library_after")); + DuplicateClassB clazz = new DuplicateClassB(); + assertEquals(clazz.toString(), "Client's Version B"); + + SharedClassAfter stdSharedClass = new SharedClassAfter(); + assertEquals(stdSharedClass.toString(), "Also Nothing Special"); + + ClientClass clientCode = new ClientClass(); + assertEquals(clientCode.toString(), "Client Code"); + } + + @Test + public void testLoadingOfResource() { + // aapt compiler gives each lib their own namespace so this test just confirming + // the resources can be loaded from the same context object + Context context = ApplicationProvider.getApplicationContext(); + String clientString = context.getResources().getString(R.string.identical_resource_key); + assertEquals(clientString, "client value"); + assertEquals(StdSharedClass.getResString(context), "std lib value"); + assertEquals(SharedClassAfter.getResString(context), "loaded after value"); + + } + + private HashSet<String> getLibsLoadedAfter() { + Resources systemR = Resources.getSystem(); + HashSet<String> libsToLoadAfter = new HashSet<>(); + Collections.addAll(libsToLoadAfter, systemR.getStringArray( + com.android.internal.R.array.config_sharedLibrariesLoadedAfterApp)); + return libsToLoadAfter; + } +} diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/Android.bp b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/Android.bp new file mode 100644 index 000000000000..db9b3edfe6a2 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/Android.bp @@ -0,0 +1,30 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +android_test_helper_app { + name: "SharedLibraryLoadingTests_SharedLibraryLoadedAfter", + srcs: ["**/*.java"], + resource_dirs: ["res"], + sdk_version: "current", + aaptflags: ["--shared-lib"], +} diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/AndroidManifest.xml b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/AndroidManifest.xml new file mode 100644 index 000000000000..efedfcfeb515 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT 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="com.android.sharedlibloadingtest.shared_library_after"> + <application> + <library android:name="com.android.sharedlibloadingtest.shared_library_after" /> + </application> +</manifest>
\ No newline at end of file diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/res/values/values.xml b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/res/values/values.xml new file mode 100644 index 000000000000..4525944b060c --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/res/values/values.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<resources> + <string name="identical_resource_key">loaded after value</string> +</resources>
\ No newline at end of file diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/DuplicateClassB.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/DuplicateClassB.java new file mode 100644 index 000000000000..1e1f5aab5993 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/DuplicateClassB.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.sharedlibloadingtest; + +public class DuplicateClassB { + @Override + public String toString() { + return "Loaded After Shared Lib's Version"; + } +} diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/SharedClassAfter.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/SharedClassAfter.java new file mode 100644 index 000000000000..9e5b40fc38d8 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/SharedClassAfter.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.sharedlibloadingtest; + +import android.content.Context; + +import com.android.sharedlibloadingtest.shared_library_after.R; + +public class SharedClassAfter { + @Override + public String toString() { + return "Also Nothing Special"; + } + + public static String getResString(Context context) { + return context.getResources().getString(R.string.identical_resource_key); + } +} diff --git a/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/Android.bp b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/Android.bp new file mode 100644 index 000000000000..50456b0439c2 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/Android.bp @@ -0,0 +1,30 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +android_test_helper_app { + name: "SharedLibraryLoadingTests_StandardSharedLibrary", + srcs: ["**/*.java"], + resource_dirs: ["res"], + sdk_version: "current", + aaptflags: ["--shared-lib"], +} diff --git a/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/AndroidManifest.xml b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/AndroidManifest.xml new file mode 100644 index 000000000000..f1a079feb316 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT 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="com.android.sharedlibloadingtest.shared_library"> + <application> + <library android:name="com.android.sharedlibloadingtest.shared_library" /> + </application> +</manifest>
\ No newline at end of file diff --git a/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/res/values/values.xml b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/res/values/values.xml new file mode 100644 index 000000000000..941351aaea62 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/res/values/values.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<resources> + <string name="identical_resource_key">std lib value</string> +</resources>
\ No newline at end of file diff --git a/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/DuplicateClassA.java b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/DuplicateClassA.java new file mode 100644 index 000000000000..a3874aa3ad96 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/DuplicateClassA.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.sharedlibloadingtest; + +public class DuplicateClassA { + @Override + public String toString() { + return "Standard Shared Lib's Version"; + } +} diff --git a/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/StdSharedClass.java b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/StdSharedClass.java new file mode 100644 index 000000000000..429d65ca2439 --- /dev/null +++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/StdSharedClass.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.sharedlibloadingtest; + +import android.content.Context; + +import com.android.sharedlibloadingtest.shared_library.R; + +public class StdSharedClass { + @Override + public String toString() { + return "Nothing Special Lib"; + } + + public static String getResString(Context context) { + return context.getResources().getString(R.string.identical_resource_key); + } +} diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp index cac14a72a706..a5852b52ff19 100644 --- a/tests/StagedInstallTest/Android.bp +++ b/tests/StagedInstallTest/Android.bp @@ -31,12 +31,14 @@ android_test_helper_app { ], test_suites: ["general-tests"], java_resources: [ + ":apex.apexd_test_classpath", ":com.android.apex.apkrollback.test_v2", ":StagedInstallTestApexV2", ":StagedInstallTestApexV2_WrongSha", ":test.rebootless_apex_v1", ":test.rebootless_apex_v2", ], + platform_apis: true, } java_test_host { @@ -53,8 +55,9 @@ java_test_host { "cts-install-lib-host", ], data: [ + ":apex.apexd_test", ":com.android.apex.apkrollback.test_v1", - ":com.android.apex.cts.shim.v2_prebuilt", + ":StagedInstallTestApexV2", ":StagedInstallTestApexV2_WrongSha", ":TestAppAv1", ":test.rebootless_apex_v1", diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java index 4684f0182d03..06200cd99b5b 100644 --- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java @@ -17,16 +17,27 @@ package com.android.tests.stagedinstallinternal; import static com.android.cts.install.lib.InstallUtils.getPackageInstaller; +import static com.android.cts.install.lib.InstallUtils.waitForSessionReady; import static com.android.cts.shim.lib.ShimPackage.SHIM_APEX_PACKAGE_NAME; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; + import android.Manifest; +import android.content.pm.ApexStagedEvent; import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageManagerNative; +import android.content.pm.IStagedApexObserver; import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; +import android.content.pm.StagedApexInfo; +import android.os.IBinder; +import android.os.ServiceManager; import androidx.test.platform.app.InstrumentationRegistry; @@ -39,6 +50,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -61,6 +74,11 @@ public class StagedInstallInternalTest { "ApexV2", SHIM_APEX_PACKAGE_NAME, 2, /* isApex= */ true, "com.android.apex.cts.shim.v2.apex"); + private static final String TEST_APEX_PACKAGE_NAME = "com.android.apex.test_package"; + private static final TestApp TEST_APEX_CLASSPATH = new TestApp("TestApex", + TEST_APEX_PACKAGE_NAME, 1, /*isApex=*/true, + "apex.apexd_test_classpath.apex"); + private File mTestStateFile = new File( InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(), "stagedinstall_state"); @@ -401,9 +419,74 @@ public class StagedInstallInternalTest { AssertionError.class, "Staged session " + sessionId + " already contains " + SHIM_APEX_PACKAGE_NAME, Install.single(APEX_V2)); + } + + @Test + public void testGetStagedModuleNames() throws Exception { + // Before staging a session + String[] result = getPackageManagerNative().getStagedApexModuleNames(); + assertThat(result).hasLength(0); + // Stage an apex + int sessionId = Install.single(APEX_V2).setStaged().commit(); + waitForSessionReady(sessionId); + result = getPackageManagerNative().getStagedApexModuleNames(); + assertThat(result).hasLength(1); + assertThat(result).isEqualTo(new String[]{SHIM_APEX_PACKAGE_NAME}); + // Abandon the session + InstallUtils.openPackageInstallerSession(sessionId).abandon(); + result = getPackageManagerNative().getStagedApexModuleNames(); + assertThat(result).hasLength(0); + } + + @Test + public void testGetStagedApexInfo() throws Exception { + // Ask for non-existing module + StagedApexInfo result = getPackageManagerNative().getStagedApexInfo("not found"); + assertThat(result).isNull(); + // Stage an apex + int sessionId = Install.single(TEST_APEX_CLASSPATH).setStaged().commit(); + waitForSessionReady(sessionId); + // Query proper module name + result = getPackageManagerNative().getStagedApexInfo(TEST_APEX_PACKAGE_NAME); + assertThat(result.moduleName).isEqualTo(TEST_APEX_PACKAGE_NAME); + assertThat(result.hasClassPathJars).isTrue(); + InstallUtils.openPackageInstallerSession(sessionId).abandon(); + } + + public static class MockStagedApexObserver extends IStagedApexObserver.Stub { + @Override + public void onApexStaged(ApexStagedEvent event) { + assertThat(event).isNotNull(); + } + } + + @Test + public void testStagedApexObserver() throws Exception { + MockStagedApexObserver realObserver = new MockStagedApexObserver(); + IStagedApexObserver observer = spy(realObserver); + assertThat(observer).isNotNull(); + getPackageManagerNative().registerStagedApexObserver(observer); + + // Stage an apex and verify observer was called + int sessionId = Install.single(APEX_V2).setStaged().commit(); + waitForSessionReady(sessionId); + ArgumentCaptor<ApexStagedEvent> captor = ArgumentCaptor.forClass(ApexStagedEvent.class); + verify(observer, timeout(5000)).onApexStaged(captor.capture()); + assertThat(captor.getValue().stagedApexModuleNames).isEqualTo( + new String[] {SHIM_APEX_PACKAGE_NAME}); + // Abandon and verify observer is called + Mockito.clearInvocations(observer); + InstallUtils.openPackageInstallerSession(sessionId).abandon(); + verify(observer, timeout(5000)).onApexStaged(captor.capture()); + assertThat(captor.getValue().stagedApexModuleNames).hasLength(0); } + private IPackageManagerNative getPackageManagerNative() { + IBinder binder = ServiceManager.waitForService("package_native"); + assertThat(binder).isNotNull(); + return IPackageManagerNative.Stub.asInterface(binder); + } private static void assertSessionApplied(int sessionId) { assertSessionState(sessionId, (session) -> { assertThat(session.isStagedSessionApplied()).isTrue(); diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java index 5021009f65ae..cd0078363c4b 100644 --- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java @@ -61,6 +61,7 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { private static final String APEX_WRONG_SHA = "com.android.apex.cts.shim.v2_wrong_sha.apex"; private static final String APK_A = "TestAppAv1.apk"; private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test"; + private static final String APEXD_TEST_APEX = "apex.apexd_test.apex"; private static final String TEST_VENDOR_APEX_ALLOW_LIST = "/vendor/etc/sysconfig/test-vendor-apex-allow-list.xml"; @@ -478,6 +479,34 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { runPhase("testRebootlessUpdate_hasStagedSessionWithSameApex_fails"); } + @Test + public void testGetStagedModuleNames() throws Exception { + assumeTrue("Device does not support updating APEX", + mHostUtils.isApexUpdateSupported()); + + runPhase("testGetStagedModuleNames"); + } + + @Test + @LargeTest + public void testGetStagedApexInfo() throws Exception { + assumeTrue("Device does not support updating APEX", + mHostUtils.isApexUpdateSupported()); + + pushTestApex(APEXD_TEST_APEX); + getDevice().reboot(); + + runPhase("testGetStagedApexInfo"); + } + + @Test + public void testStagedApexObserver() throws Exception { + assumeTrue("Device does not support updating APEX", + mHostUtils.isApexUpdateSupported()); + + runPhase("testStagedApexObserver"); + } + private List<String> getStagingDirectories() throws DeviceNotAvailableException { String baseDir = "/data/app-staging"; try { diff --git a/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java b/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java index 7cda977d2115..5d639f6f6266 100644 --- a/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java +++ b/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java @@ -409,10 +409,10 @@ public class NotificationTests extends AndroidTestCase { sleepIfYouCan(500); L("Parceling notifications..."); - // we want to be able to use this test on older OSes that do not have getBlobAshmemSize - Method getBlobAshmemSize = null; + // we want to be able to use this test on older OSes that do not have getOpenAshmemSize + Method getOpenAshmemSize = null; try { - getBlobAshmemSize = Parcel.class.getMethod("getBlobAshmemSize"); + getOpenAshmemSize = Parcel.class.getMethod("getOpenAshmemSize"); } catch (NoSuchMethodException ex) { } for (int i=0; i<mNotifications.size(); i++) { @@ -424,8 +424,8 @@ public class NotificationTests extends AndroidTestCase { time = SystemClock.currentThreadTimeMillis() - time; L(" %s: write parcel=%dms size=%d ashmem=%s", summarize(n), time, p.dataPosition(), - (getBlobAshmemSize != null) - ? getBlobAshmemSize.invoke(p) + (getOpenAshmemSize != null) + ? getOpenAshmemSize.invoke(p) : "???"); p.setDataPosition(0); } diff --git a/tests/utils/hostutils/src/com/android/internal/util/test/SystemPreparer.java b/tests/utils/hostutils/src/com/android/internal/util/test/SystemPreparer.java index 84448333a8c6..525a78486efc 100644 --- a/tests/utils/hostutils/src/com/android/internal/util/test/SystemPreparer.java +++ b/tests/utils/hostutils/src/com/android/internal/util/test/SystemPreparer.java @@ -207,17 +207,6 @@ public class SystemPreparer extends ExternalResource { default: device.executeShellCommand("stop"); device.executeShellCommand("start"); - ITestDevice.RecoveryMode cachedRecoveryMode = device.getRecoveryMode(); - device.setRecoveryMode(ITestDevice.RecoveryMode.ONLINE); - - if (device.isEncryptionSupported()) { - if (device.isDeviceEncrypted()) { - LogUtil.CLog.e("Device is encrypted after userspace reboot!"); - device.unlockDevice(); - } - } - - device.setRecoveryMode(cachedRecoveryMode); device.waitForDeviceAvailable(); break; } diff --git a/tests/vcn/OWNERS b/tests/vcn/OWNERS index 33b9f0f75f81..2441e772468c 100644 --- a/tests/vcn/OWNERS +++ b/tests/vcn/OWNERS @@ -3,5 +3,5 @@ set noparent benedictwong@google.com ckesting@google.com evitayan@google.com +junyin@google.com nharold@google.com -jchalard@google.com
\ No newline at end of file diff --git a/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java b/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java new file mode 100644 index 000000000000..d03aee282ee1 --- /dev/null +++ b/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.vcn; + +import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_ANY; +import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +public class VcnCellUnderlyingNetworkTemplateTest { + private static final Set<String> ALLOWED_PLMN_IDS = new HashSet<>(); + private static final Set<Integer> ALLOWED_CARRIER_IDS = new HashSet<>(); + + // Package private for use in VcnGatewayConnectionConfigTest + static VcnCellUnderlyingNetworkTemplate getTestNetworkPriority() { + return new VcnCellUnderlyingNetworkTemplate.Builder() + .setNetworkQuality(NETWORK_QUALITY_OK) + .setAllowMetered(true /* allowMetered */) + .setAllowedOperatorPlmnIds(ALLOWED_PLMN_IDS) + .setAllowedSpecificCarrierIds(ALLOWED_CARRIER_IDS) + .setAllowRoaming(true /* allowRoaming */) + .setRequireOpportunistic(true /* requireOpportunistic */) + .build(); + } + + @Test + public void testBuilderAndGetters() { + final VcnCellUnderlyingNetworkTemplate networkPriority = getTestNetworkPriority(); + assertEquals(NETWORK_QUALITY_OK, networkPriority.getNetworkQuality()); + assertTrue(networkPriority.allowMetered()); + assertEquals(ALLOWED_PLMN_IDS, networkPriority.getAllowedOperatorPlmnIds()); + assertEquals(ALLOWED_CARRIER_IDS, networkPriority.getAllowedSpecificCarrierIds()); + assertTrue(networkPriority.allowRoaming()); + assertTrue(networkPriority.requireOpportunistic()); + } + + @Test + public void testBuilderAndGettersForDefaultValues() { + final VcnCellUnderlyingNetworkTemplate networkPriority = + new VcnCellUnderlyingNetworkTemplate.Builder().build(); + assertEquals(NETWORK_QUALITY_ANY, networkPriority.getNetworkQuality()); + assertFalse(networkPriority.allowMetered()); + assertEquals(new HashSet<String>(), networkPriority.getAllowedOperatorPlmnIds()); + assertEquals(new HashSet<Integer>(), networkPriority.getAllowedSpecificCarrierIds()); + assertFalse(networkPriority.allowRoaming()); + assertFalse(networkPriority.requireOpportunistic()); + } + + @Test + public void testPersistableBundle() { + final VcnCellUnderlyingNetworkTemplate networkPriority = getTestNetworkPriority(); + assertEquals( + networkPriority, + VcnUnderlyingNetworkTemplate.fromPersistableBundle( + networkPriority.toPersistableBundle())); + } +} diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java index dc338ae0fdc7..1f2905da08f4 100644 --- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java +++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java @@ -17,6 +17,8 @@ package android.net.vcn; import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE; +import static android.net.vcn.VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_PRIORITIES; +import static android.net.vcn.VcnGatewayConnectionConfig.UNDERLYING_NETWORK_PRIORITIES_KEY; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -30,6 +32,7 @@ import android.net.ipsec.ike.IkeSessionParams; import android.net.ipsec.ike.IkeTunnelConnectionParams; import android.net.vcn.persistablebundleutils.IkeSessionParamsUtilsTest; import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtilsTest; +import android.os.PersistableBundle; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -38,6 +41,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.Arrays; +import java.util.LinkedHashSet; import java.util.concurrent.TimeUnit; @RunWith(AndroidJUnit4.class) @@ -50,9 +54,17 @@ public class VcnGatewayConnectionConfigTest { }; public static final int[] UNDERLYING_CAPS = new int[] {NetworkCapabilities.NET_CAPABILITY_DUN}; + private static final LinkedHashSet<VcnUnderlyingNetworkTemplate> UNDERLYING_NETWORK_PRIORITIES = + new LinkedHashSet(); + static { Arrays.sort(EXPOSED_CAPS); Arrays.sort(UNDERLYING_CAPS); + + UNDERLYING_NETWORK_PRIORITIES.add( + VcnCellUnderlyingNetworkTemplateTest.getTestNetworkPriority()); + UNDERLYING_NETWORK_PRIORITIES.add( + VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkPriority()); } public static final long[] RETRY_INTERVALS_MS = @@ -82,7 +94,10 @@ public class VcnGatewayConnectionConfigTest { // Public for use in VcnGatewayConnectionTest public static VcnGatewayConnectionConfig buildTestConfig() { - return buildTestConfigWithExposedCaps(EXPOSED_CAPS); + final VcnGatewayConnectionConfig.Builder builder = + newBuilder().setVcnUnderlyingNetworkPriorities(UNDERLYING_NETWORK_PRIORITIES); + + return buildTestConfigWithExposedCaps(builder, EXPOSED_CAPS); } private static VcnGatewayConnectionConfig.Builder newBuilder() { @@ -159,6 +174,15 @@ public class VcnGatewayConnectionConfigTest { } @Test + public void testBuilderRequiresNonNullNetworkPriorities() { + try { + newBuilder().setVcnUnderlyingNetworkPriorities(null); + fail("Expected exception due to invalid underlyingNetworkPriorities"); + } catch (NullPointerException e) { + } + } + + @Test public void testBuilderRequiresNonNullRetryInterval() { try { newBuilder().setRetryIntervalsMillis(null); @@ -195,6 +219,7 @@ public class VcnGatewayConnectionConfigTest { Arrays.sort(exposedCaps); assertArrayEquals(EXPOSED_CAPS, exposedCaps); + assertEquals(UNDERLYING_NETWORK_PRIORITIES, config.getVcnUnderlyingNetworkPriorities()); assertEquals(TUNNEL_CONNECTION_PARAMS, config.getTunnelConnectionParams()); assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMillis()); @@ -208,6 +233,16 @@ public class VcnGatewayConnectionConfigTest { assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle())); } + @Test + public void testParsePersistableBundleWithoutVcnUnderlyingNetworkPriorities() { + PersistableBundle configBundle = buildTestConfig().toPersistableBundle(); + configBundle.putPersistableBundle(UNDERLYING_NETWORK_PRIORITIES_KEY, null); + + final VcnGatewayConnectionConfig config = new VcnGatewayConnectionConfig(configBundle); + assertEquals( + DEFAULT_UNDERLYING_NETWORK_PRIORITIES, config.getVcnUnderlyingNetworkPriorities()); + } + private static IkeTunnelConnectionParams buildTunnelConnectionParams(String ikePsk) { final IkeSessionParams ikeParams = IkeSessionParamsUtilsTest.createBuilderMinimum() @@ -249,4 +284,40 @@ public class VcnGatewayConnectionConfigTest { assertNotEquals(tunnelParams, anotherTunnelParams); assertNotEquals(config, anotherConfig); } + + private static VcnGatewayConnectionConfig buildTestConfigWithVcnUnderlyingNetworkPriorities( + LinkedHashSet<VcnUnderlyingNetworkTemplate> networkPriorities) { + return buildTestConfigWithExposedCaps( + new VcnGatewayConnectionConfig.Builder( + "buildTestConfigWithVcnUnderlyingNetworkPriorities", + TUNNEL_CONNECTION_PARAMS) + .setVcnUnderlyingNetworkPriorities(networkPriorities), + EXPOSED_CAPS); + } + + @Test + public void testVcnUnderlyingNetworkPrioritiesEquality() throws Exception { + final VcnGatewayConnectionConfig config = + buildTestConfigWithVcnUnderlyingNetworkPriorities(UNDERLYING_NETWORK_PRIORITIES); + + final LinkedHashSet<VcnUnderlyingNetworkTemplate> networkPrioritiesEqual = + new LinkedHashSet(); + networkPrioritiesEqual.add(VcnCellUnderlyingNetworkTemplateTest.getTestNetworkPriority()); + networkPrioritiesEqual.add(VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkPriority()); + final VcnGatewayConnectionConfig configEqual = + buildTestConfigWithVcnUnderlyingNetworkPriorities(networkPrioritiesEqual); + + final LinkedHashSet<VcnUnderlyingNetworkTemplate> networkPrioritiesNotEqual = + new LinkedHashSet(); + networkPrioritiesNotEqual.add( + VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkPriority()); + final VcnGatewayConnectionConfig configNotEqual = + buildTestConfigWithVcnUnderlyingNetworkPriorities(networkPrioritiesNotEqual); + + assertEquals(UNDERLYING_NETWORK_PRIORITIES, networkPrioritiesEqual); + assertEquals(config, configEqual); + + assertNotEquals(UNDERLYING_NETWORK_PRIORITIES, networkPrioritiesNotEqual); + assertNotEquals(config, configNotEqual); + } } diff --git a/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplateTest.java b/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplateTest.java new file mode 100644 index 000000000000..652057fd48c7 --- /dev/null +++ b/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplateTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.vcn; + +import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_ANY; +import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Test; + +public class VcnWifiUnderlyingNetworkTemplateTest { + private static final String SSID = "TestWifi"; + private static final int INVALID_NETWORK_QUALITY = -1; + + // Package private for use in VcnGatewayConnectionConfigTest + static VcnWifiUnderlyingNetworkTemplate getTestNetworkPriority() { + return new VcnWifiUnderlyingNetworkTemplate.Builder() + .setNetworkQuality(NETWORK_QUALITY_OK) + .setAllowMetered(true /* allowMetered */) + .setSsid(SSID) + .build(); + } + + @Test + public void testBuilderAndGetters() { + final VcnWifiUnderlyingNetworkTemplate networkPriority = getTestNetworkPriority(); + assertEquals(NETWORK_QUALITY_OK, networkPriority.getNetworkQuality()); + assertTrue(networkPriority.allowMetered()); + assertEquals(SSID, networkPriority.getSsid()); + } + + @Test + public void testBuilderAndGettersForDefaultValues() { + final VcnWifiUnderlyingNetworkTemplate networkPriority = + new VcnWifiUnderlyingNetworkTemplate.Builder().build(); + assertEquals(NETWORK_QUALITY_ANY, networkPriority.getNetworkQuality()); + assertFalse(networkPriority.allowMetered()); + assertNull(SSID, networkPriority.getSsid()); + } + + @Test + public void testBuildWithInvalidNetworkQuality() { + try { + new VcnWifiUnderlyingNetworkTemplate.Builder() + .setNetworkQuality(INVALID_NETWORK_QUALITY); + fail("Expected to fail due to the invalid network quality"); + } catch (Exception expected) { + } + } + + @Test + public void testPersistableBundle() { + final VcnWifiUnderlyingNetworkTemplate networkPriority = getTestNetworkPriority(); + assertEquals( + networkPriority, + VcnUnderlyingNetworkTemplate.fromPersistableBundle( + networkPriority.toPersistableBundle())); + } +} diff --git a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java index f3851130c68a..3b201f9d20dd 100644 --- a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java +++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java @@ -135,11 +135,12 @@ public class IkeSessionParamsUtilsTest { } @Test - public void testEncodeRecodeParamsWithIkeOptions() throws Exception { + public void testEncodeDecodeParamsWithIkeOptions() throws Exception { final IkeSessionParams params = createBuilderMinimum() .addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID) .addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE) + .addIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT) .build(); verifyPersistableBundleEncodeDecodeIsLossless(params); } diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index 7c7dc4d79e9a..bb98bc0bab53 100644 --- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java +++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java @@ -23,7 +23,6 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE; -import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; @@ -264,6 +263,7 @@ public class VcnManagementServiceTest { @Test public void testSystemReady() throws Exception { mVcnMgmtSvc.systemReady(); + mTestLooper.dispatchAll(); verify(mConnMgr).registerNetworkProvider(any(VcnNetworkProvider.class)); verify(mSubscriptionTracker).register(); @@ -475,10 +475,8 @@ public class VcnManagementServiceTest { mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet()); - - // Verify teardown after delay - mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); mTestLooper.dispatchAll(); + verify(vcn).teardownAsynchronously(); verify(mMockPolicyListener).onPolicyChanged(); } @@ -504,92 +502,6 @@ public class VcnManagementServiceTest { assertEquals(0, mVcnMgmtSvc.getAllVcns().size()); } - /** - * Tests an intermediate state where carrier privileges are marked as lost before active data - * subId changes during a SIM ejection. - * - * <p>The expected outcome is that the VCN is torn down after a delay, as opposed to - * immediately. - */ - @Test - public void testTelephonyNetworkTrackerCallbackLostCarrierPrivilegesBeforeActiveDataSubChanges() - throws Exception { - setupActiveSubscription(TEST_UUID_2); - - final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); - final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2); - - // Simulate privileges lost - triggerSubscriptionTrackerCbAndGetSnapshot( - TEST_SUBSCRIPTION_ID, - TEST_UUID_2, - Collections.emptySet(), - Collections.emptyMap(), - false /* hasCarrierPrivileges */); - - // Verify teardown after delay - mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); - mTestLooper.dispatchAll(); - verify(vcn).teardownAsynchronously(); - } - - @Test - public void testTelephonyNetworkTrackerCallbackSimSwitchesDoNotKillVcnInstances() - throws Exception { - setupActiveSubscription(TEST_UUID_2); - - final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); - final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2); - - // Simulate SIM unloaded - triggerSubscriptionTrackerCbAndGetSnapshot( - INVALID_SUBSCRIPTION_ID, - null /* activeDataSubscriptionGroup */, - Collections.emptySet(), - Collections.emptyMap(), - false /* hasCarrierPrivileges */); - - // Simulate new SIM loaded right during teardown delay. - mTestLooper.moveTimeForward( - VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2); - mTestLooper.dispatchAll(); - triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_2, Collections.singleton(TEST_UUID_2)); - - // Verify that even after the full timeout duration, the VCN instance is not torn down - mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); - mTestLooper.dispatchAll(); - verify(vcn, never()).teardownAsynchronously(); - } - - @Test - public void testTelephonyNetworkTrackerCallbackDoesNotKillNewVcnInstances() throws Exception { - setupActiveSubscription(TEST_UUID_2); - - final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); - final Vcn oldInstance = startAndGetVcnInstance(TEST_UUID_2); - - // Simulate SIM unloaded - triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet()); - - // Config cleared, SIM reloaded & config re-added right before teardown delay, staring new - // vcnInstance. - mTestLooper.moveTimeForward( - VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2); - mTestLooper.dispatchAll(); - mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME); - triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_2, Collections.singleton(TEST_UUID_2)); - final Vcn newInstance = startAndGetVcnInstance(TEST_UUID_2); - - // Verify that new instance was different, and the old one was torn down - assertTrue(oldInstance != newInstance); - verify(oldInstance).teardownAsynchronously(); - - // Verify that even after the full timeout duration, the new VCN instance is not torn down - mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); - mTestLooper.dispatchAll(); - verify(newInstance, never()).teardownAsynchronously(); - } - @Test public void testPackageChangeListenerRegistered() throws Exception { verify(mMockContext).registerReceiver(any(BroadcastReceiver.class), argThat(filter -> { @@ -925,6 +837,8 @@ public class VcnManagementServiceTest { private void setupSubscriptionAndStartVcn( int subId, ParcelUuid subGrp, boolean isVcnActive, boolean hasCarrierPrivileges) { mVcnMgmtSvc.systemReady(); + mTestLooper.dispatchAll(); + triggerSubscriptionTrackerCbAndGetSnapshot( subGrp, Collections.singleton(subGrp), @@ -1020,6 +934,7 @@ public class VcnManagementServiceTest { private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) { mVcnMgmtSvc.systemReady(); + mTestLooper.dispatchAll(); final ArgumentCaptor<NetworkCallback> captor = ArgumentCaptor.forClass(NetworkCallback.class); @@ -1264,15 +1179,14 @@ public class VcnManagementServiceTest { true /* isActive */, true /* hasCarrierPrivileges */); - // VCN is currently active. Lose carrier privileges for TEST_PACKAGE and hit teardown - // timeout so the VCN goes inactive. + // VCN is currently active. Lose carrier privileges for TEST_PACKAGE so the VCN goes + // inactive. final TelephonySubscriptionSnapshot snapshot = triggerSubscriptionTrackerCbAndGetSnapshot( TEST_UUID_1, Collections.singleton(TEST_UUID_1), Collections.singletonMap(TEST_SUBSCRIPTION_ID, TEST_UUID_1), false /* hasCarrierPrivileges */); - mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); mTestLooper.dispatchAll(); // Giving TEST_PACKAGE privileges again will restart the VCN (which will indicate ACTIVE diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java index 1f0df62fe72c..978bf3ed2e92 100644 --- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java +++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java @@ -22,6 +22,7 @@ import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX; import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener; +import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED; import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback; @@ -34,8 +35,10 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -57,6 +60,8 @@ import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; +import android.telephony.TelephonyManager.CarrierPrivilegesListener; +import android.util.ArrayMap; import android.util.ArraySet; import androidx.test.filters.SmallTest; @@ -83,7 +88,7 @@ public class TelephonySubscriptionTrackerTest { private static final String PACKAGE_NAME = TelephonySubscriptionTrackerTest.class.getPackage().getName(); private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID()); - private static final int TEST_SIM_SLOT_INDEX = 1; + private static final int TEST_SIM_SLOT_INDEX = 0; private static final int TEST_SUBSCRIPTION_ID_1 = 2; private static final SubscriptionInfo TEST_SUBINFO_1 = mock(SubscriptionInfo.class); private static final int TEST_SUBSCRIPTION_ID_2 = 3; @@ -151,6 +156,8 @@ public class TelephonySubscriptionTrackerTest { @Before public void setUp() throws Exception { + doReturn(2).when(mTelephonyManager).getActiveModemCount(); + mCallback = mock(TelephonySubscriptionTrackerCallback.class); mTelephonySubscriptionTracker = new TelephonySubscriptionTracker(mContext, mHandler, mCallback, mDeps); @@ -180,6 +187,15 @@ public class TelephonySubscriptionTrackerTest { return captor.getValue(); } + private List<CarrierPrivilegesListener> getCarrierPrivilegesListeners() { + final ArgumentCaptor<CarrierPrivilegesListener> captor = + ArgumentCaptor.forClass(CarrierPrivilegesListener.class); + verify(mTelephonyManager, atLeastOnce()) + .addCarrierPrivilegesListener(anyInt(), any(), captor.capture()); + + return captor.getAllValues(); + } + private ActiveDataSubscriptionIdListener getActiveDataSubscriptionIdListener() { final ArgumentCaptor<TelephonyCallback> captor = ArgumentCaptor.forClass(TelephonyCallback.class); @@ -188,6 +204,11 @@ public class TelephonySubscriptionTrackerTest { return (ActiveDataSubscriptionIdListener) captor.getValue(); } + private Intent buildTestMultiSimConfigBroadcastIntent() { + Intent intent = new Intent(ACTION_MULTI_SIM_CONFIG_CHANGED); + return intent; + } + private Intent buildTestBroadcastIntent(boolean hasValidSubscription) { Intent intent = new Intent(ACTION_CARRIER_CONFIG_CHANGED); intent.putExtra(EXTRA_SLOT_INDEX, TEST_SIM_SLOT_INDEX); @@ -239,12 +260,21 @@ public class TelephonySubscriptionTrackerTest { any(), eq(mHandler)); final IntentFilter filter = getIntentFilter(); - assertEquals(1, filter.countActions()); + assertEquals(2, filter.countActions()); assertTrue(filter.hasAction(ACTION_CARRIER_CONFIG_CHANGED)); + assertTrue(filter.hasAction(ACTION_MULTI_SIM_CONFIG_CHANGED)); verify(mSubscriptionManager) .addOnSubscriptionsChangedListener(any(HandlerExecutor.class), any()); assertNotNull(getOnSubscriptionsChangedListener()); + + verify(mTelephonyManager, times(2)) + .addCarrierPrivilegesListener(anyInt(), any(HandlerExecutor.class), any()); + verify(mTelephonyManager) + .addCarrierPrivilegesListener(eq(0), any(HandlerExecutor.class), any()); + verify(mTelephonyManager) + .addCarrierPrivilegesListener(eq(1), any(HandlerExecutor.class), any()); + assertEquals(2, getCarrierPrivilegesListeners().size()); } @Test @@ -255,6 +285,49 @@ public class TelephonySubscriptionTrackerTest { final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener(); verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(eq(listener)); + + for (CarrierPrivilegesListener carrierPrivilegesListener : + getCarrierPrivilegesListeners()) { + verify(mTelephonyManager) + .removeCarrierPrivilegesListener(eq(carrierPrivilegesListener)); + } + } + + @Test + public void testMultiSimConfigChanged() throws Exception { + final ArrayMap<Integer, Integer> readySubIdsBySlotId = new ArrayMap<>(); + readySubIdsBySlotId.put(TEST_SIM_SLOT_INDEX, TEST_SUBSCRIPTION_ID_1); + readySubIdsBySlotId.put(TEST_SIM_SLOT_INDEX + 1, TEST_SUBSCRIPTION_ID_1); + + mTelephonySubscriptionTracker.setReadySubIdsBySlotId(readySubIdsBySlotId); + doReturn(1).when(mTelephonyManager).getActiveModemCount(); + + List<CarrierPrivilegesListener> carrierPrivilegesListeners = + getCarrierPrivilegesListeners(); + + mTelephonySubscriptionTracker.onReceive(mContext, buildTestMultiSimConfigBroadcastIntent()); + mTestLooper.dispatchAll(); + + for (CarrierPrivilegesListener carrierPrivilegesListener : carrierPrivilegesListeners) { + verify(mTelephonyManager) + .removeCarrierPrivilegesListener(eq(carrierPrivilegesListener)); + } + + // Expect cache cleared for inactive slots. + assertNull( + mTelephonySubscriptionTracker + .getReadySubIdsBySlotId() + .get(TEST_SIM_SLOT_INDEX + 1)); + + // Expect a new CarrierPrivilegesListener to have been registered for slot 0, and none other + // (2 previously registered during startup, for slots 0 & 1) + verify(mTelephonyManager, times(3)) + .addCarrierPrivilegesListener(anyInt(), any(HandlerExecutor.class), any()); + verify(mTelephonyManager, times(2)) + .addCarrierPrivilegesListener(eq(0), any(HandlerExecutor.class), any()); + + // Verify that this triggers a re-evaluation + verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); } @Test @@ -314,6 +387,17 @@ public class TelephonySubscriptionTrackerTest { } @Test + public void testOnCarrierPrivilegesChanged() throws Exception { + setupReadySubIds(); + + final CarrierPrivilegesListener listener = getCarrierPrivilegesListeners().get(0); + listener.onCarrierPrivilegesChanged(Collections.emptyList(), new int[] {}); + mTestLooper.dispatchAll(); + + verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); + } + + @Test public void testReceiveBroadcast_ConfigReadyWithSubscriptions() throws Exception { mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); mTestLooper.dispatchAll(); diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index c9a8947ab5ef..e547400fff73 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -118,8 +118,10 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection @Test public void testNullNetworkDoesNotTriggerDisconnect() throws Exception { + doReturn(false).when(mDeps).isAirplaneModeOn(any()); + mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(null); mTestLooper.dispatchAll(); @@ -129,9 +131,22 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection } @Test + public void testNullNetworkAirplaneModeDisconnects() throws Exception { + doReturn(true).when(mDeps).isAirplaneModeOn(any()); + + mGatewayConnection + .getUnderlyingNetworkControllerCallback() + .onSelectedUnderlyingNetworkChanged(null); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + verify(mIkeSession).kill(); + } + + @Test public void testNewNetworkTriggersMigration() throws Exception { mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_2); mTestLooper.dispatchAll(); @@ -143,7 +158,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection @Test public void testSameNetworkDoesNotTriggerMigration() throws Exception { mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_1); mTestLooper.dispatchAll(); @@ -203,7 +218,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection triggerChildOpened(); mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_2); getChildSessionCallback() .onIpSecTransformsMigrated(makeDummyIpSecTransform(), makeDummyIpSecTransform()); @@ -297,8 +312,6 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection any(), any()); verify(mNetworkAgent).register(); - verify(mNetworkAgent) - .setUnderlyingNetworks(eq(singletonList(TEST_UNDERLYING_NETWORK_RECORD_1.network))); verify(mNetworkAgent).markConnected(); verify(mIpSecSvc) @@ -313,6 +326,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection final NetworkCapabilities nc = ncCaptor.getValue(); assertTrue(nc.hasTransport(TRANSPORT_CELLULAR)); assertFalse(nc.hasTransport(TRANSPORT_WIFI)); + assertEquals(List.of(TEST_UNDERLYING_NETWORK_RECORD_1.network), nc.getUnderlyingNetworks()); for (int cap : mConfig.getAllExposedCapabilities()) { assertTrue(nc.hasCapability(cap)); } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java index d1f3a210d870..3c70759a2fa6 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java @@ -64,7 +64,7 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio @Test public void testNullNetworkTriggersDisconnect() throws Exception { mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(null); mTestLooper.dispatchAll(); @@ -76,7 +76,7 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio @Test public void testNewNetworkTriggersReconnect() throws Exception { mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_2); mTestLooper.dispatchAll(); @@ -89,7 +89,7 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio @Test public void testSameNetworkDoesNotTriggerReconnect() throws Exception { mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_1); mTestLooper.dispatchAll(); diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java index 2056eea42ce6..f3eb82f46de7 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java @@ -78,7 +78,7 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect @Test public void testNetworkChangesTriggerStateTransitions() throws Exception { mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_1); mTestLooper.dispatchAll(); @@ -89,7 +89,7 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect @Test public void testNullNetworkDoesNotTriggerStateTransition() throws Exception { mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(null); mTestLooper.dispatchAll(); diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java index 1c859790a2fe..6568cdd44377 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java @@ -58,7 +58,7 @@ public class VcnGatewayConnectionRetryTimeoutStateTest extends VcnGatewayConnect @Test public void testNewNetworkTriggerRetry() throws Exception { mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_2); mTestLooper.dispatchAll(); @@ -72,7 +72,7 @@ public class VcnGatewayConnectionRetryTimeoutStateTest extends VcnGatewayConnect @Test public void testSameNetworkDoesNotTriggerRetry() throws Exception { mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_1); mTestLooper.dispatchAll(); @@ -86,7 +86,7 @@ public class VcnGatewayConnectionRetryTimeoutStateTest extends VcnGatewayConnect @Test public void testNullNetworkTriggersDisconnect() throws Exception { mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(null); mTestLooper.dispatchAll(); diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java index a7001713533c..b9dfda38a01c 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java @@ -16,6 +16,7 @@ package com.android.server.vcn; +import static android.net.IpSecManager.IpSecTunnelInterface; import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; @@ -24,6 +25,8 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR; +import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration; import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession; import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent; @@ -36,8 +39,11 @@ import static org.mockito.Matchers.eq; import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import android.net.IpSecManager; +import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; @@ -53,14 +59,17 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; -import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord; +import com.android.server.vcn.routeselection.UnderlyingNetworkRecord; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.net.InetAddress; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -70,6 +79,8 @@ import java.util.UUID; public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { private static final int TEST_UID = Process.myUid() + 1; + private static final String LOOPBACK_IFACE = "lo"; + private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID()); private static final int TEST_SIM_SLOT_INDEX = 1; private static final int TEST_SUBSCRIPTION_ID_1 = 2; @@ -77,6 +88,12 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { private static final int TEST_SUBSCRIPTION_ID_2 = 3; private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class); private static final Map<Integer, ParcelUuid> TEST_SUBID_TO_GROUP_MAP; + private static final String TEST_TCP_BUFFER_SIZES = "1,2,3,4,5,6"; + private static final int TEST_MTU = 1300; + private static final int TEST_MTU_DELTA = 64; + private static final List<LinkAddress> TEST_INTERNAL_ADDRESSES = + Arrays.asList(new LinkAddress(DUMMY_ADDR, 16)); + private static final List<InetAddress> TEST_DNS_ADDRESSES = Arrays.asList(DUMMY_ADDR); private static final int TEST_UPSTREAM_BANDWIDTH = 1234; private static final int TEST_DOWNSTREAM_BANDWIDTH = 2345; @@ -116,8 +133,9 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { capBuilder.setLinkUpstreamBandwidthKbps(TEST_UPSTREAM_BANDWIDTH); capBuilder.setLinkDownstreamBandwidthKbps(TEST_DOWNSTREAM_BANDWIDTH); capBuilder.setAdministratorUids(new int[] {TEST_UID}); + final Network underlyingNetwork = mock(Network.class, CALLS_REAL_METHODS); UnderlyingNetworkRecord record = new UnderlyingNetworkRecord( - mock(Network.class, CALLS_REAL_METHODS), + underlyingNetwork, capBuilder.build(), new LinkProperties(), false); final NetworkCapabilities vcnCaps = VcnGatewayConnection.buildNetworkCapabilities( @@ -128,6 +146,7 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { assertTrue(vcnCaps.hasTransport(TRANSPORT_CELLULAR)); assertTrue(vcnCaps.hasCapability(NET_CAPABILITY_NOT_METERED)); assertTrue(vcnCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); + assertTrue(vcnCaps.getUnderlyingNetworks().equals(List.of(underlyingNetwork))); for (int cap : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) { if (cap == NET_CAPABILITY_INTERNET || cap == NET_CAPABILITY_DUN) { @@ -166,14 +185,67 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { } @Test - public void testSubscriptionSnapshotUpdateNotifiesUnderlyingNetworkTracker() { + public void testBuildLinkProperties() throws Exception { + final IpSecTunnelInterface tunnelIface = + mContext.getSystemService(IpSecManager.class) + .createIpSecTunnelInterface( + DUMMY_ADDR, DUMMY_ADDR, TEST_UNDERLYING_NETWORK_RECORD_1.network); + + final LinkProperties underlyingLp = new LinkProperties(); + underlyingLp.setInterfaceName(LOOPBACK_IFACE); + underlyingLp.setTcpBufferSizes(TEST_TCP_BUFFER_SIZES); + doReturn(TEST_MTU).when(mDeps).getUnderlyingIfaceMtu(LOOPBACK_IFACE); + + final VcnChildSessionConfiguration childSessionConfig = + mock(VcnChildSessionConfiguration.class); + doReturn(TEST_INTERNAL_ADDRESSES).when(childSessionConfig).getInternalAddresses(); + doReturn(TEST_DNS_ADDRESSES).when(childSessionConfig).getInternalDnsServers(); + + UnderlyingNetworkRecord record = + new UnderlyingNetworkRecord( + mock(Network.class, CALLS_REAL_METHODS), + new NetworkCapabilities.Builder().build(), + underlyingLp, + false); + + final LinkProperties vcnLp1 = + mGatewayConnection.buildConnectedLinkProperties( + VcnGatewayConnectionConfigTest.buildTestConfig(), + tunnelIface, + childSessionConfig, + record); + + verify(mDeps).getUnderlyingIfaceMtu(LOOPBACK_IFACE); + + // Instead of having to recalculate the final MTU (after accounting for IPsec overhead), + // calculate another set of Link Properties with a lower MTU, and calculate the delta. + doReturn(TEST_MTU - TEST_MTU_DELTA).when(mDeps).getUnderlyingIfaceMtu(LOOPBACK_IFACE); + + final LinkProperties vcnLp2 = + mGatewayConnection.buildConnectedLinkProperties( + VcnGatewayConnectionConfigTest.buildTestConfig(), + tunnelIface, + childSessionConfig, + record); + + verify(mDeps, times(2)).getUnderlyingIfaceMtu(LOOPBACK_IFACE); + + assertEquals(tunnelIface.getInterfaceName(), vcnLp1.getInterfaceName()); + assertEquals(TEST_INTERNAL_ADDRESSES, vcnLp1.getLinkAddresses()); + assertEquals(TEST_DNS_ADDRESSES, vcnLp1.getDnsServers()); + assertEquals(TEST_TCP_BUFFER_SIZES, vcnLp1.getTcpBufferSizes()); + assertEquals(TEST_MTU_DELTA, vcnLp1.getMtu() - vcnLp2.getMtu()); + } + + @Test + public void testSubscriptionSnapshotUpdateNotifiesUnderlyingNetworkController() { verifyWakeLockSetUp(); final TelephonySubscriptionSnapshot updatedSnapshot = mock(TelephonySubscriptionSnapshot.class); mGatewayConnection.updateSubscriptionSnapshot(updatedSnapshot); - verify(mUnderlyingNetworkTracker).updateSubscriptionSnapshot(eq(updatedSnapshot)); + verify(mUnderlyingNetworkController).updateSubscriptionSnapshot(eq(updatedSnapshot)); verifyWakeLockAcquired(); mTestLooper.dispatchAll(); @@ -184,13 +256,13 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { @Test public void testNonNullUnderlyingNetworkRecordUpdateCancelsAlarm() { mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(null); verifyDisconnectRequestAlarmAndGetCallback(false /* expectCanceled */); mGatewayConnection - .getUnderlyingNetworkTrackerCallback() + .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_1); verify(mDisconnectRequestAlarm).cancel(); diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java index 64d0bca15ce9..5628321b5975 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java @@ -16,7 +16,6 @@ package com.android.server.vcn; -import static com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord; import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession; import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent; import static com.android.server.vcn.VcnTestUtils.setupIpSecManager; @@ -62,6 +61,8 @@ import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscription import com.android.server.vcn.Vcn.VcnGatewayStatusCallback; import com.android.server.vcn.VcnGatewayConnection.VcnChildSessionCallback; import com.android.server.vcn.VcnGatewayConnection.VcnWakeLock; +import com.android.server.vcn.routeselection.UnderlyingNetworkController; +import com.android.server.vcn.routeselection.UnderlyingNetworkRecord; import org.junit.Before; import org.mockito.ArgumentCaptor; @@ -137,7 +138,7 @@ public class VcnGatewayConnectionTestBase { @NonNull protected final VcnGatewayConnectionConfig mConfig; @NonNull protected final VcnGatewayStatusCallback mGatewayStatusCallback; @NonNull protected final VcnGatewayConnection.Dependencies mDeps; - @NonNull protected final UnderlyingNetworkTracker mUnderlyingNetworkTracker; + @NonNull protected final UnderlyingNetworkController mUnderlyingNetworkController; @NonNull protected final VcnWakeLock mWakeLock; @NonNull protected final WakeupMessage mTeardownTimeoutAlarm; @NonNull protected final WakeupMessage mDisconnectRequestAlarm; @@ -158,7 +159,7 @@ public class VcnGatewayConnectionTestBase { mConfig = VcnGatewayConnectionConfigTest.buildTestConfig(); mGatewayStatusCallback = mock(VcnGatewayStatusCallback.class); mDeps = mock(VcnGatewayConnection.Dependencies.class); - mUnderlyingNetworkTracker = mock(UnderlyingNetworkTracker.class); + mUnderlyingNetworkController = mock(UnderlyingNetworkController.class); mWakeLock = mock(VcnWakeLock.class); mTeardownTimeoutAlarm = mock(WakeupMessage.class); mDisconnectRequestAlarm = mock(WakeupMessage.class); @@ -176,9 +177,9 @@ public class VcnGatewayConnectionTestBase { doReturn(mTestLooper.getLooper()).when(mVcnContext).getLooper(); doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider(); - doReturn(mUnderlyingNetworkTracker) + doReturn(mUnderlyingNetworkController) .when(mDeps) - .newUnderlyingNetworkTracker(any(), any(), any(), any()); + .newUnderlyingNetworkController(any(), any(), any(), any(), any()); doReturn(mWakeLock) .when(mDeps) .newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any()); diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java new file mode 100644 index 000000000000..f23d5bf67ebf --- /dev/null +++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java @@ -0,0 +1,383 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.server.vcn.routeselection; + +import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK; + +import static com.android.server.vcn.VcnTestUtils.setupSystemService; +import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.PRIORITY_ANY; +import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.calculatePriorityClass; +import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.checkMatchesCellPriorityRule; +import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.checkMatchesPriorityRule; +import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.checkMatchesWifiPriorityRule; +import static com.android.server.vcn.routeselection.UnderlyingNetworkControllerTest.getLinkPropertiesWithName; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.TelephonyNetworkSpecifier; +import android.net.vcn.VcnCellUnderlyingNetworkTemplate; +import android.net.vcn.VcnGatewayConnectionConfig; +import android.net.vcn.VcnManager; +import android.net.vcn.VcnWifiUnderlyingNetworkTemplate; +import android.os.ParcelUuid; +import android.os.PersistableBundle; +import android.os.test.TestLooper; +import android.telephony.TelephonyManager; +import android.util.ArraySet; + +import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; +import com.android.server.vcn.VcnContext; +import com.android.server.vcn.VcnNetworkProvider; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Set; +import java.util.UUID; + +public class NetworkPriorityClassifierTest { + private static final String SSID = "TestWifi"; + private static final String SSID_OTHER = "TestWifiOther"; + private static final String PLMN_ID = "123456"; + private static final String PLMN_ID_OTHER = "234567"; + + private static final int SUB_ID = 1; + private static final int WIFI_RSSI = -60; + private static final int WIFI_RSSI_HIGH = -50; + private static final int WIFI_RSSI_LOW = -80; + private static final int CARRIER_ID = 1; + private static final int CARRIER_ID_OTHER = 2; + + private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0)); + + private static final NetworkCapabilities WIFI_NETWORK_CAPABILITIES = + new NetworkCapabilities.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .setSignalStrength(WIFI_RSSI) + .setSsid(SSID) + .build(); + + private static final TelephonyNetworkSpecifier TEL_NETWORK_SPECIFIER = + new TelephonyNetworkSpecifier.Builder().setSubscriptionId(SUB_ID).build(); + private static final NetworkCapabilities CELL_NETWORK_CAPABILITIES = + new NetworkCapabilities.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .setSubscriptionIds(Set.of(SUB_ID)) + .setNetworkSpecifier(TEL_NETWORK_SPECIFIER) + .build(); + + private static final LinkProperties LINK_PROPERTIES = getLinkPropertiesWithName("test_iface"); + + @Mock private Network mNetwork; + @Mock private TelephonySubscriptionSnapshot mSubscriptionSnapshot; + @Mock private TelephonyManager mTelephonyManager; + + private TestLooper mTestLooper; + private VcnContext mVcnContext; + private UnderlyingNetworkRecord mWifiNetworkRecord; + private UnderlyingNetworkRecord mCellNetworkRecord; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + final Context mockContext = mock(Context.class); + mTestLooper = new TestLooper(); + mVcnContext = + spy( + new VcnContext( + mockContext, + mTestLooper.getLooper(), + mock(VcnNetworkProvider.class), + false /* isInTestMode */)); + doNothing().when(mVcnContext).ensureRunningOnLooperThread(); + + mWifiNetworkRecord = + new UnderlyingNetworkRecord( + mNetwork, + WIFI_NETWORK_CAPABILITIES, + LINK_PROPERTIES, + false /* isBlocked */); + + mCellNetworkRecord = + new UnderlyingNetworkRecord( + mNetwork, + CELL_NETWORK_CAPABILITIES, + LINK_PROPERTIES, + false /* isBlocked */); + + setupSystemService( + mockContext, mTelephonyManager, Context.TELEPHONY_SERVICE, TelephonyManager.class); + when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager); + when(mTelephonyManager.getNetworkOperator()).thenReturn(PLMN_ID); + when(mTelephonyManager.getSimSpecificCarrierId()).thenReturn(CARRIER_ID); + } + + @Test + public void testMatchWithoutNotMeteredBit() { + final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority = + new VcnWifiUnderlyingNetworkTemplate.Builder() + .setNetworkQuality(NETWORK_QUALITY_OK) + .setAllowMetered(false /* allowMetered */) + .build(); + + assertFalse( + checkMatchesPriorityRule( + mVcnContext, + wifiNetworkPriority, + mWifiNetworkRecord, + SUB_GROUP, + mSubscriptionSnapshot, + null /* currentlySelecetd */, + null /* carrierConfig */)); + } + + private void verifyMatchWifi( + boolean isSelectedNetwork, PersistableBundle carrierConfig, boolean expectMatch) { + final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority = + new VcnWifiUnderlyingNetworkTemplate.Builder() + .setNetworkQuality(NETWORK_QUALITY_OK) + .setAllowMetered(true /* allowMetered */) + .build(); + final UnderlyingNetworkRecord selectedNetworkRecord = + isSelectedNetwork ? mWifiNetworkRecord : null; + assertEquals( + expectMatch, + checkMatchesWifiPriorityRule( + wifiNetworkPriority, + mWifiNetworkRecord, + selectedNetworkRecord, + carrierConfig)); + } + + @Test + public void testMatchSelectedWifi() { + verifyMatchWifi( + true /* isSelectedNetwork */, null /* carrierConfig */, true /* expectMatch */); + } + + @Test + public void testMatchSelectedWifiBelowRssiThreshold() { + final PersistableBundle carrierConfig = new PersistableBundle(); + carrierConfig.putInt( + VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY, WIFI_RSSI_HIGH); + carrierConfig.putInt( + VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY, WIFI_RSSI_HIGH); + + verifyMatchWifi(true /* isSelectedNetwork */, carrierConfig, false /* expectMatch */); + } + + @Test + public void testMatchUnselectedWifi() { + verifyMatchWifi( + false /* isSelectedNetwork */, null /* carrierConfig */, true /* expectMatch */); + } + + @Test + public void testMatchUnselectedWifiBelowRssiThreshold() { + final PersistableBundle carrierConfig = new PersistableBundle(); + carrierConfig.putInt( + VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY, WIFI_RSSI_HIGH); + + verifyMatchWifi(false /* isSelectedNetwork */, carrierConfig, false /* expectMatch */); + } + + private void verifyMatchWifiWithSsid(boolean useMatchedSsid, boolean expectMatch) { + final String nwPrioritySsid = useMatchedSsid ? SSID : SSID_OTHER; + final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority = + new VcnWifiUnderlyingNetworkTemplate.Builder() + .setNetworkQuality(NETWORK_QUALITY_OK) + .setAllowMetered(true /* allowMetered */) + .setSsid(nwPrioritySsid) + .build(); + + assertEquals( + expectMatch, + checkMatchesWifiPriorityRule( + wifiNetworkPriority, + mWifiNetworkRecord, + null /* currentlySelecetd */, + null /* carrierConfig */)); + } + + @Test + public void testMatchWifiWithSsid() { + verifyMatchWifiWithSsid(true /* useMatchedSsid */, true /* expectMatch */); + } + + @Test + public void testMatchWifiFailWithWrongSsid() { + verifyMatchWifiWithSsid(false /* useMatchedSsid */, false /* expectMatch */); + } + + private static VcnCellUnderlyingNetworkTemplate.Builder getCellNetworkPriorityBuilder() { + return new VcnCellUnderlyingNetworkTemplate.Builder() + .setNetworkQuality(NETWORK_QUALITY_OK) + .setAllowMetered(true /* allowMetered */) + .setAllowRoaming(true /* allowRoaming */); + } + + @Test + public void testMatchMacroCell() { + assertTrue( + checkMatchesCellPriorityRule( + mVcnContext, + getCellNetworkPriorityBuilder().build(), + mCellNetworkRecord, + SUB_GROUP, + mSubscriptionSnapshot)); + } + + @Test + public void testMatchOpportunisticCell() { + final VcnCellUnderlyingNetworkTemplate opportunisticCellNetworkPriority = + getCellNetworkPriorityBuilder() + .setRequireOpportunistic(true /* requireOpportunistic */) + .build(); + + when(mSubscriptionSnapshot.isOpportunistic(SUB_ID)).thenReturn(true); + when(mSubscriptionSnapshot.getAllSubIdsInGroup(SUB_GROUP)).thenReturn(new ArraySet<>()); + + assertTrue( + checkMatchesCellPriorityRule( + mVcnContext, + opportunisticCellNetworkPriority, + mCellNetworkRecord, + SUB_GROUP, + mSubscriptionSnapshot)); + } + + private void verifyMatchMacroCellWithAllowedPlmnIds( + boolean useMatchedPlmnId, boolean expectMatch) { + final String networkPriorityPlmnId = useMatchedPlmnId ? PLMN_ID : PLMN_ID_OTHER; + final VcnCellUnderlyingNetworkTemplate networkPriority = + getCellNetworkPriorityBuilder() + .setAllowedOperatorPlmnIds(Set.of(networkPriorityPlmnId)) + .build(); + + assertEquals( + expectMatch, + checkMatchesCellPriorityRule( + mVcnContext, + networkPriority, + mCellNetworkRecord, + SUB_GROUP, + mSubscriptionSnapshot)); + } + + @Test + public void testMatchMacroCellWithAllowedPlmnIds() { + verifyMatchMacroCellWithAllowedPlmnIds(true /* useMatchedPlmnId */, true /* expectMatch */); + } + + @Test + public void testMatchMacroCellFailWithDisallowedPlmnIds() { + verifyMatchMacroCellWithAllowedPlmnIds( + false /* useMatchedPlmnId */, false /* expectMatch */); + } + + private void verifyMatchMacroCellWithAllowedSpecificCarrierIds( + boolean useMatchedCarrierId, boolean expectMatch) { + final int networkPriorityCarrierId = useMatchedCarrierId ? CARRIER_ID : CARRIER_ID_OTHER; + final VcnCellUnderlyingNetworkTemplate networkPriority = + getCellNetworkPriorityBuilder() + .setAllowedSpecificCarrierIds(Set.of(networkPriorityCarrierId)) + .build(); + + assertEquals( + expectMatch, + checkMatchesCellPriorityRule( + mVcnContext, + networkPriority, + mCellNetworkRecord, + SUB_GROUP, + mSubscriptionSnapshot)); + } + + @Test + public void testMatchMacroCellWithAllowedSpecificCarrierIds() { + verifyMatchMacroCellWithAllowedSpecificCarrierIds( + true /* useMatchedCarrierId */, true /* expectMatch */); + } + + @Test + public void testMatchMacroCellFailWithDisallowedSpecificCarrierIds() { + verifyMatchMacroCellWithAllowedSpecificCarrierIds( + false /* useMatchedCarrierId */, false /* expectMatch */); + } + + @Test + public void testMatchWifiFailWithoutNotRoamingBit() { + final VcnCellUnderlyingNetworkTemplate networkPriority = + getCellNetworkPriorityBuilder().setAllowRoaming(false /* allowRoaming */).build(); + + assertFalse( + checkMatchesCellPriorityRule( + mVcnContext, + networkPriority, + mCellNetworkRecord, + SUB_GROUP, + mSubscriptionSnapshot)); + } + + private void verifyCalculatePriorityClass( + UnderlyingNetworkRecord networkRecord, int expectedIndex) { + final int priorityIndex = + calculatePriorityClass( + mVcnContext, + networkRecord, + VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_PRIORITIES, + SUB_GROUP, + mSubscriptionSnapshot, + null /* currentlySelected */, + null /* carrierConfig */); + + assertEquals(expectedIndex, priorityIndex); + } + + @Test + public void testCalculatePriorityClass() throws Exception { + verifyCalculatePriorityClass(mCellNetworkRecord, 2); + } + + @Test + public void testCalculatePriorityClassFailToMatchAny() throws Exception { + final NetworkCapabilities nc = + new NetworkCapabilities.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .setSignalStrength(WIFI_RSSI_LOW) + .setSsid(SSID) + .build(); + final UnderlyingNetworkRecord wifiNetworkRecord = + new UnderlyingNetworkRecord(mNetwork, nc, LINK_PROPERTIES, false /* isBlocked */); + + verifyCalculatePriorityClass(wifiNetworkRecord, PRIORITY_ANY); + } +} diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java index 5af69b5d1bf2..fad9669911bb 100644 --- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java +++ b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java @@ -14,9 +14,11 @@ * limitations under the License. */ -package com.android.server.vcn; +package com.android.server.vcn.routeselection; import static com.android.server.vcn.VcnTestUtils.setupSystemService; +import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT; +import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.WIFI_EXIT_RSSI_THRESHOLD_DEFAULT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; @@ -40,6 +42,7 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.TelephonyNetworkSpecifier; +import android.net.vcn.VcnGatewayConnectionConfigTest; import android.os.ParcelUuid; import android.os.test.TestLooper; import android.telephony.CarrierConfigManager; @@ -48,10 +51,11 @@ import android.telephony.TelephonyManager; import android.util.ArraySet; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; -import com.android.server.vcn.UnderlyingNetworkTracker.NetworkBringupCallback; -import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkListener; -import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord; -import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback; +import com.android.server.vcn.VcnContext; +import com.android.server.vcn.VcnNetworkProvider; +import com.android.server.vcn.routeselection.UnderlyingNetworkController.NetworkBringupCallback; +import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkControllerCallback; +import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkListener; import org.junit.Before; import org.junit.Test; @@ -64,7 +68,7 @@ import java.util.Arrays; import java.util.Set; import java.util.UUID; -public class UnderlyingNetworkTrackerTest { +public class UnderlyingNetworkControllerTest { private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0)); private static final int INITIAL_SUB_ID_1 = 1; private static final int INITIAL_SUB_ID_2 = 2; @@ -102,14 +106,14 @@ public class UnderlyingNetworkTrackerTest { @Mock private TelephonyManager mTelephonyManager; @Mock private CarrierConfigManager mCarrierConfigManager; @Mock private TelephonySubscriptionSnapshot mSubscriptionSnapshot; - @Mock private UnderlyingNetworkTrackerCallback mNetworkTrackerCb; + @Mock private UnderlyingNetworkControllerCallback mNetworkControllerCb; @Mock private Network mNetwork; @Captor private ArgumentCaptor<UnderlyingNetworkListener> mUnderlyingNetworkListenerCaptor; private TestLooper mTestLooper; private VcnContext mVcnContext; - private UnderlyingNetworkTracker mUnderlyingNetworkTracker; + private UnderlyingNetworkController mUnderlyingNetworkController; @Before public void setUp() { @@ -140,12 +144,13 @@ public class UnderlyingNetworkTrackerTest { when(mSubscriptionSnapshot.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(INITIAL_SUB_IDS); - mUnderlyingNetworkTracker = - new UnderlyingNetworkTracker( + mUnderlyingNetworkController = + new UnderlyingNetworkController( mVcnContext, + VcnGatewayConnectionConfigTest.buildTestConfig(), SUB_GROUP, mSubscriptionSnapshot, - mNetworkTrackerCb); + mNetworkControllerCb); } private void resetVcnContext() { @@ -153,7 +158,8 @@ public class UnderlyingNetworkTrackerTest { doNothing().when(mVcnContext).ensureRunningOnLooperThread(); } - private static LinkProperties getLinkPropertiesWithName(String iface) { + // Package private for use in NetworkPriorityClassifierTest + static LinkProperties getLinkPropertiesWithName(String iface) { LinkProperties linkProperties = new LinkProperties(); linkProperties.setInterfaceName(iface); return linkProperties; @@ -181,11 +187,12 @@ public class UnderlyingNetworkTrackerTest { mVcnNetworkProvider, true /* isInTestMode */); - new UnderlyingNetworkTracker( + new UnderlyingNetworkController( vcnContext, + VcnGatewayConnectionConfigTest.buildTestConfig(), SUB_GROUP, mSubscriptionSnapshot, - mNetworkTrackerCb); + mNetworkControllerCb); verify(cm) .registerNetworkCallback( @@ -233,7 +240,7 @@ public class UnderlyingNetworkTrackerTest { mock(TelephonySubscriptionSnapshot.class); when(subscriptionUpdate.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(UPDATED_SUB_IDS); - mUnderlyingNetworkTracker.updateSubscriptionSnapshot(subscriptionUpdate); + mUnderlyingNetworkController.updateSubscriptionSnapshot(subscriptionUpdate); // verify that initially-filed bringup requests are unregistered (cell + wifi) verify(mConnectivityManager, times(INITIAL_SUB_IDS.size() + 3)) @@ -255,7 +262,7 @@ public class UnderlyingNetworkTrackerTest { return getExpectedRequestBase() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .setSubscriptionIds(netCapsSubIds) - .setSignalStrength(UnderlyingNetworkTracker.WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT) + .setSignalStrength(WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT) .build(); } @@ -264,7 +271,7 @@ public class UnderlyingNetworkTrackerTest { return getExpectedRequestBase() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .setSubscriptionIds(netCapsSubIds) - .setSignalStrength(UnderlyingNetworkTracker.WIFI_EXIT_RSSI_THRESHOLD_DEFAULT) + .setSignalStrength(WIFI_EXIT_RSSI_THRESHOLD_DEFAULT) .build(); } @@ -304,7 +311,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testTeardown() { - mUnderlyingNetworkTracker.teardown(); + mUnderlyingNetworkController.teardown(); // Expect 5 NetworkBringupCallbacks to be unregistered: 1 for WiFi, 2 for Cellular (1x for // each subId), and 1 for each of the Wifi signal strength thresholds @@ -348,6 +355,17 @@ public class UnderlyingNetworkTrackerTest { return verifyRegistrationOnAvailableAndGetCallback(INITIAL_NETWORK_CAPABILITIES); } + private static NetworkCapabilities buildResponseNwCaps( + NetworkCapabilities requestNetworkCaps, Set<Integer> netCapsSubIds) { + final TelephonyNetworkSpecifier telephonyNetworkSpecifier = + new TelephonyNetworkSpecifier.Builder() + .setSubscriptionId(netCapsSubIds.iterator().next()) + .build(); + return new NetworkCapabilities.Builder(requestNetworkCaps) + .setNetworkSpecifier(telephonyNetworkSpecifier) + .build(); + } + private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback( NetworkCapabilities networkCapabilities) { verify(mConnectivityManager) @@ -358,17 +376,20 @@ public class UnderlyingNetworkTrackerTest { UnderlyingNetworkListener cb = mUnderlyingNetworkListenerCaptor.getValue(); cb.onAvailable(mNetwork); - cb.onCapabilitiesChanged(mNetwork, networkCapabilities); + + final NetworkCapabilities responseNetworkCaps = + buildResponseNwCaps(networkCapabilities, INITIAL_SUB_IDS); + cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps); cb.onLinkPropertiesChanged(mNetwork, INITIAL_LINK_PROPERTIES); cb.onBlockedStatusChanged(mNetwork, false /* isFalse */); UnderlyingNetworkRecord expectedRecord = new UnderlyingNetworkRecord( mNetwork, - networkCapabilities, + responseNetworkCaps, INITIAL_LINK_PROPERTIES, false /* isBlocked */); - verify(mNetworkTrackerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); + verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); return cb; } @@ -376,15 +397,17 @@ public class UnderlyingNetworkTrackerTest { public void testRecordTrackerCallbackNotifiedForNetworkCapabilitiesChange() { UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); - cb.onCapabilitiesChanged(mNetwork, UPDATED_NETWORK_CAPABILITIES); + final NetworkCapabilities responseNetworkCaps = + buildResponseNwCaps(UPDATED_NETWORK_CAPABILITIES, UPDATED_SUB_IDS); + cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps); UnderlyingNetworkRecord expectedRecord = new UnderlyingNetworkRecord( mNetwork, - UPDATED_NETWORK_CAPABILITIES, + responseNetworkCaps, INITIAL_LINK_PROPERTIES, false /* isBlocked */); - verify(mNetworkTrackerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); + verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); } @Test @@ -396,29 +419,33 @@ public class UnderlyingNetworkTrackerTest { UnderlyingNetworkRecord expectedRecord = new UnderlyingNetworkRecord( mNetwork, - INITIAL_NETWORK_CAPABILITIES, + buildResponseNwCaps(INITIAL_NETWORK_CAPABILITIES, INITIAL_SUB_IDS), UPDATED_LINK_PROPERTIES, false /* isBlocked */); - verify(mNetworkTrackerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); + verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); } @Test public void testRecordTrackerCallbackNotifiedForNetworkSuspended() { UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); - cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES); + final NetworkCapabilities responseNetworkCaps = + buildResponseNwCaps(SUSPENDED_NETWORK_CAPABILITIES, UPDATED_SUB_IDS); + cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps); UnderlyingNetworkRecord expectedRecord = new UnderlyingNetworkRecord( mNetwork, - SUSPENDED_NETWORK_CAPABILITIES, + responseNetworkCaps, INITIAL_LINK_PROPERTIES, false /* isBlocked */); - verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); + verify(mNetworkControllerCb, times(1)) + .onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); // onSelectedUnderlyingNetworkChanged() won't be fired twice if network capabilities doesn't // change. - cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES); - verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); + cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps); + verify(mNetworkControllerCb, times(1)) + .onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); } @Test @@ -426,19 +453,23 @@ public class UnderlyingNetworkTrackerTest { UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(SUSPENDED_NETWORK_CAPABILITIES); - cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES); + final NetworkCapabilities responseNetworkCaps = + buildResponseNwCaps(INITIAL_NETWORK_CAPABILITIES, INITIAL_SUB_IDS); + cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps); UnderlyingNetworkRecord expectedRecord = new UnderlyingNetworkRecord( mNetwork, - INITIAL_NETWORK_CAPABILITIES, + responseNetworkCaps, INITIAL_LINK_PROPERTIES, false /* isBlocked */); - verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); + verify(mNetworkControllerCb, times(1)) + .onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); // onSelectedUnderlyingNetworkChanged() won't be fired twice if network capabilities doesn't // change. - cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES); - verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); + cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps); + verify(mNetworkControllerCb, times(1)) + .onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); } @Test @@ -450,10 +481,10 @@ public class UnderlyingNetworkTrackerTest { UnderlyingNetworkRecord expectedRecord = new UnderlyingNetworkRecord( mNetwork, - INITIAL_NETWORK_CAPABILITIES, + buildResponseNwCaps(INITIAL_NETWORK_CAPABILITIES, INITIAL_SUB_IDS), INITIAL_LINK_PROPERTIES, true /* isBlocked */); - verify(mNetworkTrackerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); + verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord)); } @Test @@ -462,29 +493,31 @@ public class UnderlyingNetworkTrackerTest { cb.onLost(mNetwork); - verify(mNetworkTrackerCb).onSelectedUnderlyingNetworkChanged(null); + verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(null); } @Test public void testRecordTrackerCallbackIgnoresDuplicateRecord() { UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); - cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES); + cb.onCapabilitiesChanged( + mNetwork, buildResponseNwCaps(INITIAL_NETWORK_CAPABILITIES, INITIAL_SUB_IDS)); - // Verify no more calls to the UnderlyingNetworkTrackerCallback when the + // Verify no more calls to the UnderlyingNetworkControllerCallback when the // UnderlyingNetworkRecord does not actually change - verifyNoMoreInteractions(mNetworkTrackerCb); + verifyNoMoreInteractions(mNetworkControllerCb); } @Test public void testRecordTrackerCallbackNotifiedAfterTeardown() { UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); - mUnderlyingNetworkTracker.teardown(); + mUnderlyingNetworkController.teardown(); - cb.onCapabilitiesChanged(mNetwork, UPDATED_NETWORK_CAPABILITIES); + cb.onCapabilitiesChanged( + mNetwork, buildResponseNwCaps(UPDATED_NETWORK_CAPABILITIES, INITIAL_SUB_IDS)); // Verify that the only call was during onAvailable() - verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(any()); + verify(mNetworkControllerCb, times(1)).onSelectedUnderlyingNetworkChanged(any()); } // TODO (b/187991063): Add tests for network prioritization |