summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/ApkVerityTest/AndroidTest.xml2
-rw-r--r--tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java3
-rw-r--r--tests/CanvasCompare/Android.bp63
-rw-r--r--tests/CanvasCompare/AndroidManifest.xml48
-rw-r--r--tests/CanvasCompare/OWNERS1
-rw-r--r--tests/CanvasCompare/res/drawable/sunset1.jpgbin28050 -> 0 bytes
-rw-r--r--tests/CanvasCompare/res/layout/automatic_layout.xml38
-rw-r--r--tests/CanvasCompare/res/layout/manual_layout.xml119
-rw-r--r--tests/CanvasCompare/res/values/strings.xml31
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/AutomaticActivity.java310
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java122
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java532
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java187
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/MainView.java56
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/ManualActivity.java212
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java136
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/Test.java46
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rscript61
-rw-r--r--tests/Codegen/Android.bp8
-rw-r--r--tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java4
-rw-r--r--tests/EnforcePermission/Android.bp22
-rw-r--r--tests/EnforcePermission/OWNERS3
-rw-r--r--tests/EnforcePermission/TEST_MAPPING7
-rw-r--r--tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl25
-rw-r--r--tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl34
-rw-r--r--tests/EnforcePermission/service-app/Android.bp32
-rw-r--r--tests/EnforcePermission/service-app/AndroidManifest.xml (renamed from tests/CanvasCompare/res/values/values.xml)22
-rw-r--r--tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java48
-rw-r--r--tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java119
-rw-r--r--tests/EnforcePermission/test-app/Android.bp38
-rw-r--r--tests/EnforcePermission/test-app/AndroidManifest.xml32
-rw-r--r--tests/EnforcePermission/test-app/AndroidTest.xml28
-rw-r--r--tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java129
-rw-r--r--tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java2
-rw-r--r--tests/FlickerTests/Android.bp3
-rw-r--r--tests/HandwritingIme/OWNERS3
-rw-r--r--tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/ViewDumpParser.java2
-rw-r--r--tests/Input/Android.bp2
-rw-r--r--tests/Input/src/com/android/test/input/AnrTest.kt9
-rw-r--r--tests/Internal/src/com/android/internal/app/OWNERS2
-rw-r--r--tests/JankBench/app/src/main/java/com/android/benchmark/app/HomeActivity.java2
-rw-r--r--tests/JankBench/app/src/main/java/com/android/benchmark/app/RunLocalBenchmarksActivity.java1
-rw-r--r--tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java4
-rw-r--r--tests/OdmApps/Android.bp4
-rw-r--r--tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java16
-rw-r--r--tests/RollbackTest/Android.bp2
-rw-r--r--tests/RollbackTest/SampleRollbackApp/Android.bp33
-rw-r--r--tests/RollbackTest/SampleRollbackApp/AndroidManifest.xml31
-rw-r--r--tests/RollbackTest/SampleRollbackApp/res/layout/activity_main.xml37
-rw-r--r--tests/RollbackTest/SampleRollbackApp/res/layout/listitem_rollbackinfo.xml41
-rw-r--r--tests/RollbackTest/SampleRollbackApp/res/values/strings.xml20
-rw-r--r--tests/RollbackTest/SampleRollbackApp/src/com/android/sample/rollbackapp/MainActivity.java160
-rw-r--r--tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp.java1
-rw-r--r--tests/SoundTriggerTestApp/OWNERS2
-rw-r--r--tests/SoundTriggerTests/OWNERS2
-rw-r--r--tests/StagedInstallTest/Android.bp1
-rw-r--r--tests/SurfaceControlViewHostTest/OWNERS1
-rw-r--r--tests/SystemMemoryTest/host/Android.bp3
-rw-r--r--tests/TouchLatency/OWNERS2
-rw-r--r--tests/TrustTests/Android.bp2
-rw-r--r--tests/UpdatableSystemFontTest/Android.bp1
-rw-r--r--tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java4
-rw-r--r--tests/UsbManagerTests/lib/src/com/android/server/usblib/UsbManagerTestLib.java14
-rw-r--r--tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java16
-rw-r--r--tests/VectorDrawableTest/OWNERS3
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java4
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java5
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java5
-rw-r--r--tests/WindowAnimationJank/Android.bp2
-rw-r--r--tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java11
-rw-r--r--tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java3
-rw-r--r--tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java64
-rw-r--r--tests/utils/testutils/java/android/os/test/OWNERS1
-rw-r--r--tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java35
-rw-r--r--tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java77
-rw-r--r--tests/vcn/java/android/net/vcn/VcnConfigTest.java91
-rw-r--r--tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java103
-rw-r--r--tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java34
-rw-r--r--tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java14
-rw-r--r--tests/vcn/java/com/android/server/VcnManagementServiceTest.java363
-rw-r--r--tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java35
-rw-r--r--tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java172
-rw-r--r--tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java74
-rw-r--r--tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java38
-rw-r--r--tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java123
-rw-r--r--tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java380
86 files changed, 2419 insertions, 2159 deletions
diff --git a/tests/ApkVerityTest/AndroidTest.xml b/tests/ApkVerityTest/AndroidTest.xml
index 39b75cc27acb..2a0a2c76e50f 100644
--- a/tests/ApkVerityTest/AndroidTest.xml
+++ b/tests/ApkVerityTest/AndroidTest.xml
@@ -43,6 +43,8 @@
<option name="push" value="block_device_writer->/data/local/tmp/block_device_writer" />
</target_preparer>
+ <!-- Skip on HWASan. TODO(b/232288278): Re-enable -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.SkipHWASanModuleController" />
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="ApkVerityTest.jar" />
</test>
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index 90ddb6ffb34a..d2a6bf288be4 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -31,6 +31,7 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -299,6 +300,8 @@ public final class BackgroundDexOptServiceIntegrationTests {
// Test that background dexopt under low storage conditions downgrades unused packages.
@Test
+ @Ignore("b/251438180: This test has been failing for a long time; temporarily disable it while"
+ + " we investigate this issue.")
public void testBackgroundDexOptDowngradeSuccessful() throws IOException {
// Should be more than DOWNGRADE_AFTER_DAYS.
long deltaDays = DOWNGRADE_AFTER_DAYS + 1;
diff --git a/tests/CanvasCompare/Android.bp b/tests/CanvasCompare/Android.bp
deleted file mode 100644
index 98831154ddc2..000000000000
--- a/tests/CanvasCompare/Android.bp
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package {
- // See: http://go/android-license-faq
- default_applicable_licenses: [
- "frameworks_base_license",
- ],
-}
-
-android_test {
- name: "CanvasCompare",
- srcs: [
- "src/**/*.java",
- ":CanvasCompare-rscript{CanvasCompare.srcjar}",
- ],
- resource_zips: [
- ":CanvasCompare-rscript{CanvasCompare.res.zip}",
- ],
- platform_apis: true,
- libs: [
- "android.test.runner",
- "android.test.base",
- ],
- static_libs: ["junit"],
-}
-
-genrule {
- name: "CanvasCompare-rscript",
- srcs: [
- "src/**/*.rscript",
- ":rs_script_api",
- ":rs_clang_headers",
- ],
- tools: [
- "llvm-rs-cc",
- "soong_zip",
- ],
- out: [
- "CanvasCompare.srcjar",
- "CanvasCompare.res.zip",
- ],
- cmd: "for f in $(locations src/**/*.rscript); do " +
- " $(location llvm-rs-cc) -o $(genDir)/res/raw -p $(genDir)/src " +
- " -I $$(dirname $$(echo $(locations :rs_script_api) | awk '{ print $$1 }')) " +
- " -I $$(dirname $$(echo $(locations :rs_clang_headers) | awk '{ print $$1 }')) $${f}; " +
- "done && " +
- "$(location soong_zip) -srcjar -o $(location CanvasCompare.srcjar) -C $(genDir)/src -D $(genDir)/src &&" +
- "$(location soong_zip) -o $(location CanvasCompare.res.zip) -C $(genDir)/res -D $(genDir)/res",
-}
diff --git a/tests/CanvasCompare/AndroidManifest.xml b/tests/CanvasCompare/AndroidManifest.xml
deleted file mode 100644
index 2734e7f07f27..000000000000
--- a/tests/CanvasCompare/AndroidManifest.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.test.hwuicompare">
-
- <uses-permission android:name="android.permission.INTERNET"/>
- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-
- <application android:label="@string/app_name"
- android:theme="@android:style/Theme.Holo.Light.NoActionBar">
- <activity android:name="AutomaticActivity"
- android:label="CanvasAutoCompare"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- <activity android:name="ManualActivity"
- android:label="CanvasManualCompare"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- <uses-library android:name="android.test.runner"/>
- </application>
- <instrumentation android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="com.android.test.hwuicompare"
- android:label="HW/SW Canvas comparison tool."/>
-
-</manifest>
diff --git a/tests/CanvasCompare/OWNERS b/tests/CanvasCompare/OWNERS
deleted file mode 100644
index c88a9f82c347..000000000000
--- a/tests/CanvasCompare/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /libs/hwui/OWNERS
diff --git a/tests/CanvasCompare/res/drawable/sunset1.jpg b/tests/CanvasCompare/res/drawable/sunset1.jpg
deleted file mode 100644
index 3b4e056b70d0..000000000000
--- a/tests/CanvasCompare/res/drawable/sunset1.jpg
+++ /dev/null
Binary files differ
diff --git a/tests/CanvasCompare/res/layout/automatic_layout.xml b/tests/CanvasCompare/res/layout/automatic_layout.xml
deleted file mode 100644
index e049ec0a5000..000000000000
--- a/tests/CanvasCompare/res/layout/automatic_layout.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <com.android.test.hwuicompare.MainView
- android:id="@+id/hardware_view"
- android:layout_width="@dimen/layer_width"
- android:layout_height="@dimen/layer_width" />
-
- <ImageView
- android:id="@+id/software_image_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true" />
-
- <ImageView
- android:id="@+id/hardware_image_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentRight="true" />
-
-</RelativeLayout>
diff --git a/tests/CanvasCompare/res/layout/manual_layout.xml b/tests/CanvasCompare/res/layout/manual_layout.xml
deleted file mode 100644
index 1a9288ce1993..000000000000
--- a/tests/CanvasCompare/res/layout/manual_layout.xml
+++ /dev/null
@@ -1,119 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center_horizontal"
- android:orientation="vertical" >
-
- <HorizontalScrollView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" >
-
- <LinearLayout
- android:id="@+id/spinner_layout"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal" />
- </HorizontalScrollView>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:baselineAligned="true"
- android:orientation="horizontal" >
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:gravity="center"
- android:orientation="horizontal" >
-
- <com.android.test.hwuicompare.MainView
- android:id="@+id/hardware_view"
- android:layout_width="@dimen/layer_width"
- android:layout_height="@dimen/layer_width" />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:gravity="center"
- android:orientation="horizontal" >
-
- <com.android.test.hwuicompare.MainView
- android:id="@+id/software_view"
- android:layout_width="@dimen/layer_width"
- android:layout_height="@dimen/layer_width" />
- </LinearLayout>
- </LinearLayout>
-
- <ImageView
- android:id="@+id/compare_image_view"
- android:layout_width="@dimen/layer_width_double"
- android:layout_height="@dimen/layer_height_double"
- android:filter="false" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:orientation="horizontal" >
-
- <ImageButton
- android:id="@+id/previous"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@string/previous_combination"
- android:src="@android:drawable/ic_media_previous" />
-
- <ImageButton
- android:id="@+id/next"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@string/next_combination"
- android:src="@android:drawable/ic_media_next" />
-
- <TextView
- android:id="@+id/current_error"
- android:layout_width="100dp"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:textAppearance="?android:attr/textAppearanceLarge" />
-
- <Button
- android:id="@+id/show_hardware_version"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/show_hardware_version" />
-
- <Button
- android:id="@+id/show_software_version"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/show_software_version" />
-
- <Button
- android:id="@+id/show_error_heatmap"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/show_error_heatmap" />
- </LinearLayout>
-
-</LinearLayout>
diff --git a/tests/CanvasCompare/res/values/strings.xml b/tests/CanvasCompare/res/values/strings.xml
deleted file mode 100644
index edd46103f4f5..000000000000
--- a/tests/CanvasCompare/res/values/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources>
- <string name="app_name">Canvas Compare Test</string>
-
- <!-- show hardware rendered version of the layer -->
- <string name="show_hardware_version">Hardware</string>
- <!-- show software rendered version of the layer -->
- <string name="show_software_version">Software</string>
- <!-- show layer error -->
- <string name="show_error_values">Error</string>
- <!-- show layer error heatmap -->
- <string name="show_error_heatmap">Heatmap</string>
- <!-- select and display the next combination of painting options-->
- <string name="next_combination">Next Combination</string>
- <!-- select and display the previous combination of painting options-->
- <string name="previous_combination">Previous Combination</string>
-</resources>
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/AutomaticActivity.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/AutomaticActivity.java
deleted file mode 100644
index 8ccd4e2181ed..000000000000
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/AutomaticActivity.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.test.hwuicompare;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.TreeSet;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.Trace;
-import android.util.Log;
-import android.widget.ImageView;
-import android.widget.Toast;
-
-public class AutomaticActivity extends CompareActivity {
- private static final String LOG_TAG = "AutomaticActivity";
- private static final float ERROR_DISPLAY_THRESHOLD = 0.01f;
- protected static final boolean DRAW_BITMAPS = false;
-
- /**
- * Threshold of error change required to consider a test regressed/improved
- */
- private static final float ERROR_CHANGE_THRESHOLD = 0.001f;
-
- private static final float[] ERROR_CUTOFFS = {
- 0, 0.005f, 0.01f, 0.02f, 0.05f, 0.1f, 0.25f, 0.5f, 1f, 2f
- };
-
- private final float[] mErrorRates = new float[ERROR_CUTOFFS.length];
- private float mTotalTests = 0;
- private float mTotalError = 0;
- private int mTestsRegressed = 0;
- private int mTestsImproved = 0;
-
- private ImageView mSoftwareImageView = null;
- private ImageView mHardwareImageView = null;
-
-
- public abstract static class FinalCallback {
- abstract void report(String name, float value);
- void complete() {};
- }
-
- private final ArrayList<FinalCallback> mFinalCallbacks = new ArrayList<FinalCallback>();
-
- Runnable mRunnable = new Runnable() {
- @Override
- public void run() {
- loadBitmaps();
- if (mSoftwareBitmap == null || mHardwareBitmap == null) {
- Log.e(LOG_TAG, "bitmap is null");
- return;
- }
-
- if (DRAW_BITMAPS) {
- mSoftwareImageView.setImageBitmap(mSoftwareBitmap);
- mHardwareImageView.setImageBitmap(mHardwareBitmap);
- }
-
- Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, "calculateError");
- float error = mErrorCalculator.calcErrorRS(mSoftwareBitmap, mHardwareBitmap);
- Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
-
- final String[] modifierNames = DisplayModifier.getLastAppliedModifications();
- handleError(modifierNames, error);
-
- if (DisplayModifier.step()) {
- finishTest();
- } else {
- mHardwareView.invalidate();
- if (DRAW_BITMAPS) {
- mSoftwareImageView.invalidate();
- mHardwareImageView.invalidate();
- }
- }
- mHandler.removeCallbacks(mRunnable);
- }
- };
-
- @Override
- protected void onPause() {
- super.onPause();
- mHandler.removeCallbacks(mRunnable);
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.automatic_layout);
-
- mSoftwareImageView = findViewById(R.id.software_image_view);
- mHardwareImageView = findViewById(R.id.hardware_image_view);
-
- onCreateCommon(mRunnable);
- beginTest();
- }
-
- private static class TestResult {
- TestResult(String label, float error) {
- mLabel = label;
- mTotalError = error;
- mCount = 1;
- }
- public void addInto(float error) {
- mTotalError += error;
- mCount++;
- }
- public float getAverage() {
- return mTotalError / mCount;
- }
- final String mLabel;
- float mTotalError;
- int mCount;
- }
-
- JSONObject mOutputJson = null;
- JSONObject mInputJson = null;
- final HashMap<String, TestResult> mModifierResults = new HashMap<String, TestResult>();
- final HashMap<String, TestResult> mIndividualResults = new HashMap<String, TestResult>();
- final HashMap<String, TestResult> mModifierDiffResults = new HashMap<String, TestResult>();
- final HashMap<String, TestResult> mIndividualDiffResults = new HashMap<String, TestResult>();
- private void beginTest() {
- mFinalCallbacks.add(new FinalCallback() {
- @Override
- void report(String name, float value) {
- Log.d(LOG_TAG, name + " " + value);
- };
- });
-
- File inputFile = new File(Environment.getExternalStorageDirectory(),
- "CanvasCompareInput.json");
- if (inputFile.exists() && inputFile.canRead() && inputFile.length() > 0) {
- try {
- FileInputStream inputStream = new FileInputStream(inputFile);
- Log.d(LOG_TAG, "Parsing input file...");
- StringBuffer content = new StringBuffer((int)inputFile.length());
- byte[] buffer = new byte[1024];
- while (inputStream.read(buffer) != -1) {
- content.append(new String(buffer));
- }
- mInputJson = new JSONObject(content.toString());
- inputStream.close();
- Log.d(LOG_TAG, "Parsed input file with " + mInputJson.length() + " entries");
- } catch (JSONException e) {
- Log.e(LOG_TAG, "error parsing input json", e);
- } catch (IOException e) {
- Log.e(LOG_TAG, "error reading input json from sd", e);
- }
- }
-
- mOutputJson = new JSONObject();
- }
-
- private static void logTestResultHash(String label, HashMap<String, TestResult> map) {
- Log.d(LOG_TAG, "---------------");
- Log.d(LOG_TAG, label + ":");
- Log.d(LOG_TAG, "---------------");
- TreeSet<TestResult> set = new TreeSet<TestResult>(new Comparator<TestResult>() {
- @Override
- public int compare(TestResult lhs, TestResult rhs) {
- if (lhs == rhs) return 0; // don't need to worry about complex equality
-
- int cmp = Float.compare(lhs.getAverage(), rhs.getAverage());
- if (cmp != 0) {
- return cmp;
- }
- return lhs.mLabel.compareTo(rhs.mLabel);
- }
- });
-
- for (TestResult t : map.values()) {
- set.add(t);
- }
-
- for (TestResult t : set.descendingSet()) {
- if (Math.abs(t.getAverage()) > ERROR_DISPLAY_THRESHOLD) {
- Log.d(LOG_TAG, String.format("%2.4f : %s", t.getAverage(), t.mLabel));
- }
- }
- Log.d(LOG_TAG, "");
- }
-
- private void finishTest() {
- for (FinalCallback c : mFinalCallbacks) {
- c.report("averageError", (mTotalError / mTotalTests));
- for (int i = 1; i < ERROR_CUTOFFS.length; i++) {
- c.report(String.format("tests with error over %1.3f", ERROR_CUTOFFS[i]),
- mErrorRates[i]);
- }
- if (mInputJson != null) {
- c.report("tests regressed", mTestsRegressed);
- c.report("tests improved", mTestsImproved);
- }
- c.complete();
- }
-
- try {
- if (mOutputJson != null) {
- String outputString = mOutputJson.toString(4);
- File outputFile = new File(Environment.getExternalStorageDirectory(),
- "CanvasCompareOutput.json");
- FileOutputStream outputStream = new FileOutputStream(outputFile);
- outputStream.write(outputString.getBytes());
- outputStream.close();
- Log.d(LOG_TAG, "Saved output file with " + mOutputJson.length() + " entries");
- }
- } catch (JSONException e) {
- Log.e(LOG_TAG, "error during JSON stringify", e);
- } catch (IOException e) {
- Log.e(LOG_TAG, "error storing JSON output on sd", e);
- }
-
- logTestResultHash("Modifier change vs previous", mModifierDiffResults);
- logTestResultHash("Invidual test change vs previous", mIndividualDiffResults);
- logTestResultHash("Modifier average test results", mModifierResults);
- logTestResultHash("Individual test results", mIndividualResults);
-
- Toast.makeText(getApplicationContext(), "done!", Toast.LENGTH_SHORT).show();
- finish();
- }
-
- /**
- * Inserts the error value into all TestResult objects, associated with each of its modifiers
- */
- private static void addForAllModifiers(String fullName, float error, String[] modifierNames,
- HashMap<String, TestResult> modifierResults) {
- for (String modifierName : modifierNames) {
- TestResult r = modifierResults.get(fullName);
- if (r == null) {
- modifierResults.put(modifierName, new TestResult(modifierName, error));
- } else {
- r.addInto(error);
- }
- }
- }
-
- private void handleError(final String[] modifierNames, final float error) {
- String fullName = "";
- for (String s : modifierNames) {
- fullName = fullName.concat("." + s);
- }
- fullName = fullName.substring(1);
-
- float deltaError = 0;
- if (mInputJson != null) {
- try {
- deltaError = error - (float)mInputJson.getDouble(fullName);
- } catch (JSONException e) {
- Log.w(LOG_TAG, "Warning: unable to read from input json", e);
- }
- if (deltaError > ERROR_CHANGE_THRESHOLD) mTestsRegressed++;
- if (deltaError < -ERROR_CHANGE_THRESHOLD) mTestsImproved++;
- mIndividualDiffResults.put(fullName, new TestResult(fullName, deltaError));
- addForAllModifiers(fullName, deltaError, modifierNames, mModifierDiffResults);
- }
-
- mIndividualResults.put(fullName, new TestResult(fullName, error));
- addForAllModifiers(fullName, error, modifierNames, mModifierResults);
-
- try {
- if (mOutputJson != null) {
- mOutputJson.put(fullName, error);
- }
- } catch (JSONException e) {
- Log.e(LOG_TAG, "exception during JSON recording", e);
- mOutputJson = null;
- }
-
- for (int i = 0; i < ERROR_CUTOFFS.length; i++) {
- if (error <= ERROR_CUTOFFS[i]) break;
- mErrorRates[i]++;
- }
- mTotalError += error;
- mTotalTests++;
- }
-
- @Override
- protected boolean forceRecreateBitmaps() {
- // disable, unless needed for drawing into imageviews
- return DRAW_BITMAPS;
- }
-
- // FOR TESTING
- public void setFinalCallback(FinalCallback c) {
- mFinalCallbacks.add(c);
- }
-}
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java
deleted file mode 100644
index 0dec1de79a46..000000000000
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.test.hwuicompare;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import com.android.test.hwuicompare.R;
-
-import android.app.Activity;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Handler;
-import android.os.Trace;
-import android.util.Log;
-import android.view.View;
-
-abstract public class CompareActivity extends Activity {
- private static final String LOG_TAG = "CompareActivity";
-
- protected MainView mHardwareView = null;
-
- protected Bitmap mSoftwareBitmap;
- protected Bitmap mHardwareBitmap;
-
- protected ErrorCalculator mErrorCalculator;
-
- protected Handler mHandler;
-
- Runnable mDrawCallback = null;
- protected boolean mRedrewFlag = true;
-
- protected void onCreateCommon(final Runnable postDrawCallback) {
- mDrawCallback = new Runnable() {
- @Override
- public void run() {
- mRedrewFlag = true;
- mHandler.post(postDrawCallback);
- };
- };
- getWindow().setBackgroundDrawable(new ColorDrawable(0xffefefef));
- ResourceModifiers.init(getResources());
-
- mHardwareView = findViewById(R.id.hardware_view);
- mHardwareView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- mHardwareView.setBackgroundColor(Color.WHITE);
- mHardwareView.addDrawCallback(mDrawCallback);
-
- int width = getResources().getDimensionPixelSize(R.dimen.layer_width);
- int height = getResources().getDimensionPixelSize(R.dimen.layer_height);
- mSoftwareBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- mHardwareBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-
- mErrorCalculator = new ErrorCalculator(getApplicationContext(), getResources());
-
- mHandler = new Handler();
- }
-
- protected abstract boolean forceRecreateBitmaps();
-
- protected void loadBitmaps() {
- Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, "loadBitmaps");
- if (forceRecreateBitmaps()) {
- int width = mSoftwareBitmap.getWidth();
- int height = mSoftwareBitmap.getHeight();
-
- mSoftwareBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- mHardwareBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- }
-
- Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, "softwareDraw");
- mHardwareView.draw(new Canvas(mSoftwareBitmap));
- Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
-
- try {
- Method getHardwareLayer = View.class.getDeclaredMethod("getHardwareLayer");
- if (!getHardwareLayer.isAccessible())
- getHardwareLayer.setAccessible(true);
- Object hardwareLayer = getHardwareLayer.invoke(mHardwareView);
- if (hardwareLayer == null) {
- Log.d(LOG_TAG, "failure to access hardware layer");
- return;
- }
- Method copyInto = hardwareLayer.getClass()
- .getDeclaredMethod("copyInto", Bitmap.class);
- if (!copyInto.isAccessible())
- copyInto.setAccessible(true);
-
- Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, "copyInto");
- boolean success = (Boolean) copyInto.invoke(hardwareLayer, mHardwareBitmap);
- Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
- if (!success) {
- Log.d(LOG_TAG, "failure to copy hardware layer into bitmap");
- }
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- }
- Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
- }
-}
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
deleted file mode 100644
index 0f4e122d147a..000000000000
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.test.hwuicompare;
-
-import java.util.LinkedHashMap;
-import java.util.Map.Entry;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.RectF;
-import android.util.Log;
-
-public abstract class DisplayModifier {
-
- // automated tests ignore any combination of operations that don't together return TOTAL_MASK
- protected final static int TOTAL_MASK = 0x1F;
-
- // if we're filling, ensure we're not also sweeping over stroke parameters
- protected final static int SWEEP_STROKE_WIDTH_BIT = 0x1 << 0;
- protected final static int SWEEP_STROKE_CAP_BIT = 0x1 << 1;
- protected final static int SWEEP_STROKE_JOIN_BIT = 0x1 << 2;
-
- protected final static int SWEEP_SHADER_BIT = 0x1 << 3; // only allow non-simple shaders to use rectangle drawing
- protected final static int SWEEP_TRANSFORM_BIT = 0x1 << 4; // only sweep over specified transforms
-
- abstract public void modifyDrawing(Paint paint, Canvas canvas);
- protected int mask() { return 0x0; };
-
- private static final RectF gRect = new RectF(0, 0, 200, 175);
- private static final float[] gPts = new float[] {
- 0, 100, 100, 0, 100, 200, 200, 100
- };
-
- private static final int NUM_PARALLEL_LINES = 24;
- private static final float[] gTriPts = new float[] {
- 75, 0, 130, 130, 130, 130, 0, 130, 0, 130, 75, 0
- };
- private static final float[] gLinePts = new float[NUM_PARALLEL_LINES * 8 + gTriPts.length];
- static {
- int index;
- for (index = 0; index < gTriPts.length; index++) {
- gLinePts[index] = gTriPts[index];
- }
- float val = 0;
- for (int i = 0; i < NUM_PARALLEL_LINES; i++) {
- gLinePts[index + 0] = 150;
- gLinePts[index + 1] = val;
- gLinePts[index + 2] = 300;
- gLinePts[index + 3] = val;
- index += 4;
- val += 8 + (2.0f/NUM_PARALLEL_LINES);
- }
- val = 0;
- for (int i = 0; i < NUM_PARALLEL_LINES; i++) {
- gLinePts[index + 0] = val;
- gLinePts[index + 1] = 150;
- gLinePts[index + 2] = val;
- gLinePts[index + 3] = 300;
- index += 4;
- val += 8 + (2.0f/NUM_PARALLEL_LINES);
- }
- };
-
- @SuppressWarnings("serial")
- private static final LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>> gMaps = new LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>>() {
- {
- put("aa", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("true", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setAntiAlias(true);
- }
- });
- put("false", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setAntiAlias(false);
- }
- });
- }
- });
- put("style", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("fill", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStyle(Paint.Style.FILL);
- }
- });
- put("stroke", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStyle(Paint.Style.STROKE);
- }
- @Override
- protected int mask() { return SWEEP_STROKE_WIDTH_BIT; }
- });
- put("fillAndStroke", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStyle(Paint.Style.FILL_AND_STROKE);
- }
-
- @Override
- protected int mask() { return SWEEP_STROKE_WIDTH_BIT; }
- });
- }
- });
- put("strokeWidth", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("hair", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStrokeWidth(0);
- }
- @Override
- protected int mask() { return SWEEP_STROKE_WIDTH_BIT; }
- });
- put("0.3", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStrokeWidth(0.3f);
- }
- });
- put("1", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStrokeWidth(1);
- }
- });
- put("5", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStrokeWidth(5);
- }
- });
- put("30", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStrokeWidth(30);
- }
- });
- }
- });
- put("strokeCap", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("butt", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStrokeCap(Paint.Cap.BUTT);
- }
- @Override
- protected int mask() { return SWEEP_STROKE_CAP_BIT; }
- });
- put("round", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStrokeCap(Paint.Cap.ROUND);
- }
- });
- put("square", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStrokeCap(Paint.Cap.SQUARE);
- }
- });
- }
- });
- put("strokeJoin", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("bevel", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStrokeJoin(Paint.Join.BEVEL);
- }
- @Override
- protected int mask() { return SWEEP_STROKE_JOIN_BIT; }
- });
- put("round", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStrokeJoin(Paint.Join.ROUND);
- }
- });
- put("miter", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setStrokeJoin(Paint.Join.MITER);
- }
- });
- // TODO: add miter0, miter1 etc to test miter distances
- }
- });
-
- put("transform", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("noTransform", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {}
- @Override
- protected int mask() { return SWEEP_TRANSFORM_BIT; };
- });
- put("rotate5", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.rotate(5);
- }
- });
- put("rotate45", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.rotate(45);
- }
- });
- put("rotate90", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.rotate(90);
- canvas.translate(0, -200);
- }
- });
- put("scale2x2", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.scale(2, 2);
- }
- @Override
- protected int mask() { return SWEEP_TRANSFORM_BIT; };
- });
- put("rot20scl1x4", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.rotate(20);
- canvas.scale(1, 4);
- }
- @Override
- protected int mask() { return SWEEP_TRANSFORM_BIT; };
- });
- }
- });
-
- put("shader", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("noShader", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {}
- @Override
- protected int mask() { return SWEEP_SHADER_BIT; };
- });
- put("repeatShader", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setShader(ResourceModifiers.instance().mRepeatShader);
- }
- @Override
- protected int mask() { return SWEEP_SHADER_BIT; };
- });
- put("translatedShader", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setShader(ResourceModifiers.instance().mTranslatedShader);
- }
- });
- put("scaledShader", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setShader(ResourceModifiers.instance().mScaledShader);
- }
- });
- put("horGradient", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setShader(ResourceModifiers.instance().mHorGradient);
- }
- });
- put("diagGradient", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setShader(ResourceModifiers.instance().mDiagGradient);
- }
- @Override
- protected int mask() { return SWEEP_SHADER_BIT; };
- });
- put("vertGradient", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setShader(ResourceModifiers.instance().mVertGradient);
- }
- });
- put("radGradient", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setShader(ResourceModifiers.instance().mRadGradient);
- }
- });
- put("sweepGradient", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setShader(ResourceModifiers.instance().mSweepGradient);
- }
- });
- put("composeShader", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setShader(ResourceModifiers.instance().mComposeShader);
- }
- });
- put("bad composeShader", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setShader(ResourceModifiers.instance().mBadComposeShader);
- }
- });
- put("bad composeShader 2", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setShader(ResourceModifiers.instance().mAnotherBadComposeShader);
- }
- });
- }
- });
-
- // FINAL MAP: DOES ACTUAL DRAWING
- put("drawing", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("roundRect", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.drawRoundRect(gRect, 20, 20, paint);
- }
- });
- put("rect", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.drawRect(gRect, paint);
- }
- @Override
- protected int mask() { return SWEEP_SHADER_BIT | SWEEP_STROKE_CAP_BIT; };
- });
- put("circle", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.drawCircle(100, 100, 75, paint);
- }
- });
- put("oval", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.drawOval(gRect, paint);
- }
- });
- put("lines", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.drawLines(gLinePts, paint);
- }
- @Override
- protected int mask() { return SWEEP_STROKE_CAP_BIT; };
- });
- put("plusPoints", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.drawPoints(gPts, paint);
- }
- });
- put("text", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setTextSize(36);
- canvas.drawText("TEXTTEST", 0, 50, paint);
- }
- });
- put("shadowtext", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- paint.setTextSize(36);
- paint.setShadowLayer(3.0f, 0.0f, 3.0f, 0xffff00ff);
- canvas.drawText("TEXTTEST", 0, 50, paint);
- }
- });
- put("bitmapMesh", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.drawBitmapMesh(ResourceModifiers.instance().mBitmap, 3, 3,
- ResourceModifiers.instance().mBitmapVertices, 0, null, 0, null);
- }
- });
- put("arc", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.drawArc(gRect, 260, 285, false, paint);
- }
- @Override
- protected int mask() { return SWEEP_STROKE_CAP_BIT; };
- });
- put("arcFromCenter", new DisplayModifier() {
- @Override
- public void modifyDrawing(Paint paint, Canvas canvas) {
- canvas.drawArc(gRect, 260, 285, true, paint);
- }
- @Override
- protected int mask() { return SWEEP_STROKE_JOIN_BIT; };
- });
- }
- });
- // WARNING: DON'T PUT MORE MAPS BELOW THIS
- }
- };
-
- private static LinkedHashMap<String, DisplayModifier> getMapAtIndex(int index) {
- for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
- if (index == 0) {
- return map;
- }
- index--;
- }
- return null;
- }
-
- // indices instead of iterators for easier bidirectional traversal
- private static final int mIndices[] = new int[gMaps.size()];
- private static final String[] mLastAppliedModifications = new String[gMaps.size()];
-
- private static boolean stepInternal(boolean forward) {
- int modifierMapIndex = gMaps.size() - 1;
- while (modifierMapIndex >= 0) {
- LinkedHashMap<String, DisplayModifier> map = getMapAtIndex(modifierMapIndex);
- mIndices[modifierMapIndex] += (forward ? 1 : -1);
-
- if (mIndices[modifierMapIndex] >= 0 && mIndices[modifierMapIndex] < map.size()) {
- break;
- }
-
- mIndices[modifierMapIndex] = (forward ? 0 : map.size() - 1);
- modifierMapIndex--;
- }
- return modifierMapIndex < 0; // true if resetting
- }
-
- public static boolean step() {
- boolean ret = false;
- do {
- ret |= stepInternal(true);
- } while (!checkModificationStateMask());
- return ret;
- }
-
- public static boolean stepBack() {
- boolean ret = false;
- do {
- ret |= stepInternal(false);
- } while (!checkModificationStateMask());
- return ret;
- }
-
- private static boolean checkModificationStateMask() {
- int operatorMask = 0x0;
- int mapIndex = 0;
- for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
- int displayModifierIndex = mIndices[mapIndex];
- for (Entry<String, DisplayModifier> modifierEntry : map.entrySet()) {
- if (displayModifierIndex == 0) {
- mLastAppliedModifications[mapIndex] = modifierEntry.getKey();
- operatorMask |= modifierEntry.getValue().mask();
- break;
- }
- displayModifierIndex--;
- }
- mapIndex++;
- }
- return operatorMask == TOTAL_MASK;
- }
-
- public static void apply(Paint paint, Canvas canvas) {
- int mapIndex = 0;
- for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
- int displayModifierIndex = mIndices[mapIndex];
- for (Entry<String, DisplayModifier> modifierEntry : map.entrySet()) {
- if (displayModifierIndex == 0) {
- mLastAppliedModifications[mapIndex] = modifierEntry.getKey();
- modifierEntry.getValue().modifyDrawing(paint, canvas);
- break;
- }
- displayModifierIndex--;
- }
- mapIndex++;
- }
- }
-
- public static String[] getLastAppliedModifications() {
- return mLastAppliedModifications.clone();
- }
-
- public static String[][] getStrings() {
- String[][] keys = new String[gMaps.size()][];
-
- int i = 0;
- for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
- keys[i] = new String[map.size()];
- int j = 0;
- for (String key : map.keySet()) {
- keys[i][j++] = key;
- }
- i++;
- }
-
- return keys;
- }
-
- public static void setIndex(int mapIndex, int newIndexValue) {
- mIndices[mapIndex] = newIndexValue;
- }
-
- public static int[] getIndices() {
- return mIndices;
- }
-}
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java
deleted file mode 100644
index d402699b0979..000000000000
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.test.hwuicompare;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RenderScript;
-import android.util.Log;
-
-public class ErrorCalculator {
- private static final String LOG_TAG = "ErrorCalculator";
- private static final int REGION_SIZE = 8;
-
- private static final boolean LOG_TIMING = false;
- private static final boolean LOG_CALC = false;
-
- private RenderScript mRS;
- private Allocation mIdealPixelsAllocation;
- private Allocation mGivenPixelsAllocation;
- private Allocation mOutputPixelsAllocation;
-
- private Allocation mInputRowsAllocation;
- private Allocation mOutputRegionsAllocation;
-
- private ScriptC_errorCalculator mScript;
-
- private int[] mOutputRowRegions;
-
- public ErrorCalculator(Context c, Resources resources) {
- int width = resources.getDimensionPixelSize(R.dimen.layer_width);
- int height = resources.getDimensionPixelSize(R.dimen.layer_height);
- mOutputRowRegions = new int[height / REGION_SIZE];
-
- mRS = RenderScript.create(c);
- int[] rowIndices = new int[height / REGION_SIZE];
- for (int i = 0; i < rowIndices.length; i++)
- rowIndices[i] = i * REGION_SIZE;
-
- mScript = new ScriptC_errorCalculator(mRS);
- mScript.set_HEIGHT(height);
- mScript.set_WIDTH(width);
- mScript.set_REGION_SIZE(REGION_SIZE);
-
- mInputRowsAllocation = Allocation.createSized(mRS, Element.I32(mRS), rowIndices.length,
- Allocation.USAGE_SCRIPT);
- mInputRowsAllocation.copyFrom(rowIndices);
- mOutputRegionsAllocation = Allocation.createSized(mRS, Element.I32(mRS),
- mOutputRowRegions.length, Allocation.USAGE_SCRIPT);
- }
-
-
- private static long startMillis, middleMillis;
-
- public float calcErrorRS(Bitmap ideal, Bitmap given) {
- if (LOG_TIMING) {
- startMillis = System.currentTimeMillis();
- }
-
- mIdealPixelsAllocation = Allocation.createFromBitmap(mRS, ideal,
- Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
- mGivenPixelsAllocation = Allocation.createFromBitmap(mRS, given,
- Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
-
- mScript.set_ideal(mIdealPixelsAllocation);
- mScript.set_given(mGivenPixelsAllocation);
-
- mScript.forEach_countInterestingRegions(mInputRowsAllocation, mOutputRegionsAllocation);
- mOutputRegionsAllocation.copyTo(mOutputRowRegions);
-
- int regionCount = 0;
- for (int region : mOutputRowRegions) {
- regionCount += region;
- }
- int interestingPixels = Math.max(1, regionCount) * REGION_SIZE * REGION_SIZE;
-
- if (LOG_TIMING) {
- long startMillis2 = System.currentTimeMillis();
- }
-
- mScript.forEach_accumulateError(mInputRowsAllocation, mOutputRegionsAllocation);
- mOutputRegionsAllocation.copyTo(mOutputRowRegions);
- float totalError = 0;
- for (int row : mOutputRowRegions) {
- totalError += row;
- }
- totalError /= 1024.0f;
-
- if (LOG_TIMING) {
- long finalMillis = System.currentTimeMillis();
- Log.d(LOG_TAG, "rs: first part took " + (middleMillis - startMillis) + "ms");
- Log.d(LOG_TAG, "rs: last part took " + (finalMillis - middleMillis) + "ms");
- }
- if (LOG_CALC) {
- Log.d(LOG_TAG, "rs: error " + totalError + ", pixels " + interestingPixels);
- }
- return totalError / interestingPixels;
- }
-
- public void calcErrorHeatmapRS(Bitmap ideal, Bitmap given, Bitmap output) {
- mIdealPixelsAllocation = Allocation.createFromBitmap(mRS, ideal,
- Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
- mGivenPixelsAllocation = Allocation.createFromBitmap(mRS, given,
- Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
-
- mScript.set_ideal(mIdealPixelsAllocation);
- mScript.set_given(mGivenPixelsAllocation);
-
- mOutputPixelsAllocation = Allocation.createFromBitmap(mRS, output,
- Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
- mScript.forEach_displayDifference(mOutputPixelsAllocation, mOutputPixelsAllocation);
- mOutputPixelsAllocation.copyTo(output);
- }
-
- public static float calcError(Bitmap ideal, Bitmap given) {
- if (LOG_TIMING) {
- startMillis = System.currentTimeMillis();
- }
-
- int interestingRegions = 0;
- for (int x = 0; x < ideal.getWidth(); x += REGION_SIZE) {
- for (int y = 0; y < ideal.getWidth(); y += REGION_SIZE) {
- if (inspectRegion(ideal, x, y)) {
- interestingRegions++;
- }
- }
- }
-
- int interestingPixels = Math.max(1, interestingRegions) * REGION_SIZE * REGION_SIZE;
-
- if (LOG_TIMING) {
- long startMillis2 = System.currentTimeMillis();
- }
-
- float totalError = 0;
- for (int x = 0; x < ideal.getWidth(); x++) {
- for (int y = 0; y < ideal.getHeight(); y++) {
- int idealColor = ideal.getPixel(x, y);
- int givenColor = given.getPixel(x, y);
- if (idealColor == givenColor)
- continue;
- totalError += Math.abs(Color.red(idealColor) - Color.red(givenColor));
- totalError += Math.abs(Color.green(idealColor) - Color.green(givenColor));
- totalError += Math.abs(Color.blue(idealColor) - Color.blue(givenColor));
- totalError += Math.abs(Color.alpha(idealColor) - Color.alpha(givenColor));
- }
- }
- totalError /= 1024.0f;
- if (LOG_TIMING) {
- long finalMillis = System.currentTimeMillis();
- Log.d(LOG_TAG, "dvk: first part took " + (middleMillis - startMillis) + "ms");
- Log.d(LOG_TAG, "dvk: last part took " + (finalMillis - middleMillis) + "ms");
- }
- if (LOG_CALC) {
- Log.d(LOG_TAG, "dvk: error " + totalError + ", pixels " + interestingPixels);
- }
- return totalError / interestingPixels;
- }
-
- private static boolean inspectRegion(Bitmap ideal, int x, int y) {
- int regionColor = ideal.getPixel(x, y);
- for (int i = 0; i < REGION_SIZE; i++) {
- for (int j = 0; j < REGION_SIZE; j++) {
- if (ideal.getPixel(x + i, y + j) != regionColor)
- return true;
- }
- }
- return false;
- }
-}
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/MainView.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/MainView.java
deleted file mode 100644
index 454fe7b50ad7..000000000000
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/MainView.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.test.hwuicompare;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.view.View;
-
-public class MainView extends View {
- Paint mPaint = new Paint();
-
- public MainView(Context context) {
- super(context);
- }
-
- public MainView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public MainView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- mPaint.reset();
- DisplayModifier.apply(mPaint, canvas);
-
- if (mDrawCallback != null) {
- mDrawCallback.run();
- }
- }
-
- private Runnable mDrawCallback;
- public void addDrawCallback(Runnable drawCallback) {
- mDrawCallback = drawCallback;
- }
-}
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/ManualActivity.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/ManualActivity.java
deleted file mode 100644
index 405ff65a34fd..000000000000
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/ManualActivity.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.test.hwuicompare;
-
-import com.android.test.hwuicompare.R;
-
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.Spinner;
-import android.widget.TextView;
-
-public class ManualActivity extends CompareActivity {
- private static final String LOG_TAG = "ManualActivity";
- private ImageView mCompareImageView;
- private Bitmap mCompareBitmap;
- private TextView mErrorTextView;
- private MainView mSoftwareView;
-
- private static final int COMPARE_VIEW_UNINITIALIZED = -1;
- private static final int COMPARE_VIEW_HARDWARE = 0;
- private static final int COMPARE_VIEW_SOFTWARE = 1;
- private static final int COMPARE_VIEW_HEATMAP = 2; // TODO: add more like this? any ideas?
-
- private int mCompareImageViewState = COMPARE_VIEW_UNINITIALIZED;
- private int mLastCompareImageViewState = COMPARE_VIEW_UNINITIALIZED;
-
- Runnable mRunnable = new Runnable() {
- @Override
- public void run() {
- Log.d(LOG_TAG, "mRunnable running, mRedrewFlag = " + mRedrewFlag);
-
- if (mRedrewFlag) {
- loadBitmaps();
- // recalculate error
- float error = mErrorCalculator.calcErrorRS(mSoftwareBitmap, mHardwareBitmap);
- String modname = "";
- for (String s : DisplayModifier.getLastAppliedModifications()) {
- modname = modname.concat(s + ".");
- }
-
- Log.d(LOG_TAG, "error for " + modname + " is " + error);
- mErrorTextView.setText(String.format("%.4f", error));
- }
-
- if (mCompareImageViewState != mLastCompareImageViewState || mRedrewFlag) {
- switch (mCompareImageViewState) {
- case COMPARE_VIEW_UNINITIALIZED:
- // set to hardware
- case COMPARE_VIEW_HARDWARE:
- mCompareImageView.setImageBitmap(mHardwareBitmap);
- break;
- case COMPARE_VIEW_SOFTWARE:
- mCompareImageView.setImageBitmap(mSoftwareBitmap);
- break;
- case COMPARE_VIEW_HEATMAP:
- mErrorCalculator.calcErrorHeatmapRS(mSoftwareBitmap, mHardwareBitmap,
- mCompareBitmap);
- mCompareImageView.setImageBitmap(mCompareBitmap);
- break;
- }
- mCompareImageView.getDrawable().setFilterBitmap(false);
- mCompareImageView.invalidate();
- }
-
- mLastCompareImageViewState = mCompareImageViewState;
- mRedrewFlag = false;
- mHandler.removeCallbacks(mRunnable);
- }
- };
-
- private void redrawViews() {
- mHardwareView.invalidate();
- mSoftwareView.invalidate();
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.manual_layout);
- onCreateCommon(mRunnable);
-
- mSoftwareView = (MainView) findViewById(R.id.software_view);
- mSoftwareView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
- mSoftwareView.setBackgroundColor(Color.WHITE);
- mSoftwareView.addDrawCallback(mDrawCallback);
-
- mCompareImageView = (ImageView) findViewById(R.id.compare_image_view);
-
- int width = getResources().getDimensionPixelSize(R.dimen.layer_width);
- int height = getResources().getDimensionPixelSize(R.dimen.layer_height);
- mCompareBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-
- mErrorTextView = (TextView) findViewById(R.id.current_error);
- ((ImageButton) findViewById(R.id.next)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- DisplayModifier.step();
- updateSpinners();
- redrawViews();
- }
- });
- ((ImageButton) findViewById(R.id.previous)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- DisplayModifier.stepBack();
- updateSpinners();
- redrawViews();
- }
- });
- ((Button) findViewById(R.id.show_hardware_version))
- .setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mCompareImageViewState = COMPARE_VIEW_HARDWARE;
- mHandler.post(mRunnable);
- }
- });
- ((Button) findViewById(R.id.show_software_version))
- .setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mCompareImageViewState = COMPARE_VIEW_SOFTWARE;
- mHandler.post(mRunnable);
- }
- });
- ((Button) findViewById(R.id.show_error_heatmap)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mCompareImageViewState = COMPARE_VIEW_HEATMAP;
- mHandler.post(mRunnable);
- }
- });
-
- buildSpinnerLayout();
- }
-
- private class DisplayModifierSpinner extends Spinner {
- private final int mIndex;
-
- public DisplayModifierSpinner(int index) {
- super(ManualActivity.this);
- mIndex = index;
- setOnItemSelectedListener(new OnItemSelectedListener() {
-
- @Override
- public void onItemSelected(AdapterView<?> parentView, View selectedItem,
- int position, long id) {
- DisplayModifier.setIndex(mIndex, position);
- redrawViews();
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parentView) {
- }
- });
- }
- }
-
- private Spinner[] mSpinners;
-
- private void buildSpinnerLayout() {
- LinearLayout layout = (LinearLayout) findViewById(R.id.spinner_layout);
- String[][] mapsStrings = DisplayModifier.getStrings();
- mSpinners = new Spinner[mapsStrings.length];
- int index = 0;
- for (String[] spinnerValues : mapsStrings) {
- mSpinners[index] = new DisplayModifierSpinner(index);
- mSpinners[index].setAdapter(new ArrayAdapter<String>(this,
- android.R.layout.simple_spinner_dropdown_item, spinnerValues));
- layout.addView(mSpinners[index]);
- index++;
- }
- Log.d(LOG_TAG, "created " + index + " spinners");
- }
-
- private void updateSpinners() {
- int[] indices = DisplayModifier.getIndices();
- for (int i = 0; i < mSpinners.length; i++) {
- mSpinners[i].setSelection(indices[i]);
- }
- }
-
- @Override
- protected boolean forceRecreateBitmaps() {
- // continually recreate bitmaps to avoid modifying bitmaps currently being drawn
- return true;
- }
-}
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java
deleted file mode 100644
index d5224813c0bc..000000000000
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.test.hwuicompare;
-
-import com.android.test.hwuicompare.R;
-
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapShader;
-import android.graphics.Color;
-import android.graphics.ComposeShader;
-import android.graphics.LinearGradient;
-import android.graphics.PorterDuff;
-import android.graphics.RadialGradient;
-import android.graphics.SweepGradient;
-import android.graphics.Matrix;
-import android.graphics.Shader;
-
-public class ResourceModifiers {
- public final BitmapShader mRepeatShader;
- public final BitmapShader mTranslatedShader;
- public final BitmapShader mScaledShader;
- private final int mTexWidth;
- private final int mTexHeight;
- private final float mDrawWidth;
- private final float mDrawHeight;
- public final LinearGradient mHorGradient;
- public final LinearGradient mDiagGradient;
- public final LinearGradient mVertGradient;
- public final RadialGradient mRadGradient;
- public final SweepGradient mSweepGradient;
- public final ComposeShader mComposeShader;
- public final ComposeShader mBadComposeShader;
- public final ComposeShader mAnotherBadComposeShader;
- public final Bitmap mBitmap;
- private final Matrix mMtx1;
- private final Matrix mMtx2;
- private final Matrix mMtx3;
-
- public final float[] mBitmapVertices;
- public final int[] mBitmapColors;
-
- private static ResourceModifiers sInstance = null;
- public static ResourceModifiers instance() { return sInstance; }
- public static void init(Resources resources) {
- sInstance = new ResourceModifiers(resources);
- }
-
- public ResourceModifiers(Resources resources) {
- mBitmap = BitmapFactory.decodeResource(resources, R.drawable.sunset1);
- mTexWidth = mBitmap.getWidth();
- mTexHeight = mBitmap.getHeight();
-
- mDrawWidth = resources.getDimensionPixelSize(R.dimen.layer_width);
- mDrawHeight = resources.getDimensionPixelSize(R.dimen.layer_height);
-
- mRepeatShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT,
- Shader.TileMode.REPEAT);
-
- mTranslatedShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT,
- Shader.TileMode.REPEAT);
- mMtx1 = new Matrix();
- mMtx1.setTranslate(mTexWidth / 2.0f, mTexHeight / 2.0f);
- mMtx1.postRotate(45, 0, 0);
- mTranslatedShader.setLocalMatrix(mMtx1);
-
- mScaledShader = new BitmapShader(mBitmap, Shader.TileMode.MIRROR,
- Shader.TileMode.MIRROR);
- mMtx2 = new Matrix();
- mMtx2.setScale(0.5f, 0.5f);
- mScaledShader.setLocalMatrix(mMtx2);
-
- mHorGradient = new LinearGradient(0.0f, 0.0f, 1.0f, 0.0f,
- Color.RED, Color.GREEN, Shader.TileMode.CLAMP);
- mMtx3 = new Matrix();
- mMtx3.setScale(mDrawHeight, 1.0f);
- mMtx3.postRotate(-90.0f);
- mMtx3.postTranslate(0.0f, mDrawHeight);
- mHorGradient.setLocalMatrix(mMtx3);
-
- mDiagGradient = new LinearGradient(0.0f, 0.0f, mDrawWidth / 2.0f, mDrawHeight / 2.0f,
- Color.BLUE, Color.RED, Shader.TileMode.CLAMP);
-
- mVertGradient = new LinearGradient(0.0f, 0.0f, 0.0f, mDrawHeight / 2.0f,
- Color.YELLOW, Color.MAGENTA, Shader.TileMode.MIRROR);
-
- mSweepGradient = new SweepGradient(mDrawWidth / 2.0f, mDrawHeight / 2.0f,
- Color.YELLOW, Color.MAGENTA);
-
- mComposeShader = new ComposeShader(mRepeatShader, mHorGradient,
- PorterDuff.Mode.MULTIPLY);
-
- final float width = mBitmap.getWidth() / 8.0f;
- final float height = mBitmap.getHeight() / 8.0f;
-
- mBitmapVertices = new float[] {
- 0.0f, 0.0f, width, 0.0f, width * 2, 0.0f, width * 3, 0.0f,
- 0.0f, height, width, height, width * 2, height, width * 4, height,
- 0.0f, height * 2, width, height * 2, width * 2, height * 2, width * 3, height * 2,
- 0.0f, height * 4, width, height * 4, width * 2, height * 4, width * 4, height * 4,
- };
-
- mBitmapColors = new int[] {
- 0xffff0000, 0xff00ff00, 0xff0000ff, 0xffff0000,
- 0xff0000ff, 0xffff0000, 0xff00ff00, 0xff00ff00,
- 0xff00ff00, 0xff0000ff, 0xffff0000, 0xff00ff00,
- 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00ff0000,
- };
-
- // Use a repeating gradient with many colors to test the non simple case.
- mRadGradient = new RadialGradient(mDrawWidth / 4.0f, mDrawHeight / 4.0f, 4.0f,
- mBitmapColors, null, Shader.TileMode.REPEAT);
-
- mBadComposeShader = new ComposeShader(mRadGradient, mComposeShader,
- PorterDuff.Mode.MULTIPLY);
-
- mAnotherBadComposeShader = new ComposeShader(mRadGradient, mVertGradient,
- PorterDuff.Mode.MULTIPLY);
- }
-
-}
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/Test.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/Test.java
deleted file mode 100644
index 1ff153c003c1..000000000000
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/Test.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.android.test.hwuicompare;
-
-import com.android.test.hwuicompare.AutomaticActivity.FinalCallback;
-
-import android.os.Bundle;
-import android.test.ActivityInstrumentationTestCase2;
-
-public class Test extends ActivityInstrumentationTestCase2<AutomaticActivity> {
- AutomaticActivity mActivity;
- private Bundle mBundle;
-
- public Test() {
- super(AutomaticActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mBundle = new Bundle();
- mActivity = getActivity();
- mActivity.setFinalCallback(new FinalCallback() {
-
- @Override
- void report(String key, float value) {
- mBundle.putFloat(key, value);
- }
- @Override
- void complete() {
- synchronized(mBundle) {
- mBundle.notify();
- }
- }
- });
- }
-
- public void testCanvas() {
- synchronized(mBundle) {
- try {
- mBundle.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- getInstrumentation().sendStatus(0, mBundle);
- }
-}
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rscript b/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rscript
deleted file mode 100644
index 0a1742ef3867..000000000000
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rscript
+++ /dev/null
@@ -1,61 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(com.android.test.hwuicompare)
-
-int REGION_SIZE;
-int WIDTH;
-int HEIGHT;
-
-rs_allocation ideal;
-rs_allocation given;
-
-void countInterestingRegions(const int32_t *v_in, int32_t *v_out) {
- int y = v_in[0];
- v_out[0] = 0;
-
- for (int x = 0; x < HEIGHT; x += REGION_SIZE) {
- bool interestingRegion = false;
- uchar4 regionColor = rsGetElementAt_uchar4(ideal, x, y);
- for (int i = 0; i < REGION_SIZE && !interestingRegion; i++) {
- for (int j = 0; j < REGION_SIZE && !interestingRegion; j++) {
- uchar4 testVal = rsGetElementAt_uchar4(ideal, x + j, y + i);
- interestingRegion |= (testVal.r != regionColor.r);
- interestingRegion |= (testVal.g != regionColor.g);
- interestingRegion |= (testVal.b != regionColor.b);
- interestingRegion |= (testVal.a != regionColor.a);
- }
- }
- if (interestingRegion) {
- v_out[0]++;
- }
- }
-}
-
-void accumulateError(const int32_t *v_in, int32_t *v_out) {
- int startY = v_in[0];
- int error = 0;
- for (int y = startY; y < startY + REGION_SIZE; y++) {
- for (int x = 0; x < HEIGHT; x++) {
- uchar4 idealPixel = rsGetElementAt_uchar4(ideal, x, y);
- uchar4 givenPixel = rsGetElementAt_uchar4(given, x, y);
-
- error += abs(idealPixel.x - givenPixel.x);
- error += abs(idealPixel.y - givenPixel.y);
- error += abs(idealPixel.z - givenPixel.z);
- error += abs(idealPixel.w - givenPixel.w);
- }
- }
- v_out[0] = error;
-}
-
-void displayDifference(const uchar4 *v_in, uchar4 *v_out, uint32_t x, uint32_t y) {
- float4 idealPixel = rsGetElementAt_float4(ideal, x, y);
- float4 givenPixel = rsGetElementAt_float4(given, x, y);
-
- float4 diff = idealPixel - givenPixel;
- float totalDiff = diff.x + diff.y + diff.z + diff.w;
- if (totalDiff < 0) {
- v_out[0] = rsPackColorTo8888(0, 0, clamp(-totalDiff/2.f, 0.f, 1.f));
- } else {
- v_out[0] = rsPackColorTo8888(clamp(totalDiff/2.f, 0.f, 1.f), 0, 0);
- }
-}
diff --git a/tests/Codegen/Android.bp b/tests/Codegen/Android.bp
index ddbf16817b94..7fbe3b37f99e 100644
--- a/tests/Codegen/Android.bp
+++ b/tests/Codegen/Android.bp
@@ -24,6 +24,14 @@ android_test {
plugins: [
"staledataclass-annotation-processor",
],
+ // Exports needed for staledataclass-annotation-processor, see b/139342589.
+ javacflags: [
+ "-J--add-modules=jdk.compiler",
+ "-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
+ "-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
+ "-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+ "-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+ ],
static_libs: [
"junit",
"hamcrest",
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 5430dee5ca31..afa4ff80b6e3 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
+++ b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
@@ -84,7 +84,7 @@ public final class DynamicCodeLoggerIntegrationTests {
// avoid flakiness we run these tests multiple times, allowing progressively longer between
// code loading and checking the logs on each try.)
private static final int AUDIT_LOG_RETRIES = 10;
- private static final int RETRY_DELAY_MS = 2_000;
+ private static final int RETRY_DELAY_MS = 500;
private static Context sContext;
private static int sMyUid;
@@ -245,7 +245,7 @@ public final class DynamicCodeLoggerIntegrationTests {
"/DynamicCodeLoggerNativeExecutable", privateCopyFile);
EventLog.writeEvent(EventLog.getTagCode("auditd"),
- "type=1400 avc: granted { execute_no_trans } "
+ "type=1400 avc: granted { execute_no_trans } "
+ "path=\"" + privateCopyFile + "\" "
+ "scontext=u:r:untrusted_app: "
+ "tcontext=u:object_r:app_data_file: "
diff --git a/tests/EnforcePermission/Android.bp b/tests/EnforcePermission/Android.bp
new file mode 100644
index 000000000000..719a89817a9d
--- /dev/null
+++ b/tests/EnforcePermission/Android.bp
@@ -0,0 +1,22 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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"],
+}
+
+filegroup {
+ name: "frameworks-enforce-permission-test-aidl",
+ srcs: ["aidl/**/*.aidl"],
+}
diff --git a/tests/EnforcePermission/OWNERS b/tests/EnforcePermission/OWNERS
new file mode 100644
index 000000000000..39550a394f33
--- /dev/null
+++ b/tests/EnforcePermission/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 315013
+tweek@google.com
+brufino@google.com
diff --git a/tests/EnforcePermission/TEST_MAPPING b/tests/EnforcePermission/TEST_MAPPING
new file mode 100644
index 000000000000..a1bf42a44e86
--- /dev/null
+++ b/tests/EnforcePermission/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "EnforcePermissionTests"
+ }
+ ]
+}
diff --git a/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl b/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl
new file mode 100644
index 000000000000..1eb773dc19b8
--- /dev/null
+++ b/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.tests.enforcepermission;
+
+interface INested {
+ @EnforcePermission("ACCESS_NETWORK_STATE")
+ void ProtectedByAccessNetworkState();
+
+ @EnforcePermission("READ_SYNC_SETTINGS")
+ void ProtectedByReadSyncSettings();
+}
diff --git a/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
new file mode 100644
index 000000000000..18e3aecfa832
--- /dev/null
+++ b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.tests.enforcepermission;
+
+interface IProtected {
+ @EnforcePermission("INTERNET")
+ void ProtectedByInternet();
+
+ @EnforcePermission("VIBRATE")
+ void ProtectedByVibrate();
+
+ @EnforcePermission("INTERNET")
+ void ProtectedByInternetAndVibrateImplicitly();
+
+ @EnforcePermission("INTERNET")
+ void ProtectedByInternetAndAccessNetworkStateImplicitly();
+
+ @EnforcePermission("INTERNET")
+ void ProtectedByInternetAndReadSyncSettingsImplicitly();
+}
diff --git a/tests/EnforcePermission/service-app/Android.bp b/tests/EnforcePermission/service-app/Android.bp
new file mode 100644
index 000000000000..a4ac1d7c6134
--- /dev/null
+++ b/tests/EnforcePermission/service-app/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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: "EnforcePermissionTestHelper",
+ srcs: [
+ "src/**/*.java",
+ ":frameworks-enforce-permission-test-aidl",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/tests/CanvasCompare/res/values/values.xml b/tests/EnforcePermission/service-app/AndroidManifest.xml
index f69378d34f65..ddafe15ab88f 100644
--- a/tests/CanvasCompare/res/values/values.xml
+++ b/tests/EnforcePermission/service-app/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- Copyright (C) 2023 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,13 +13,15 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.tests.enforcepermission.service">
+ <application>
+ <service
+ android:name=".TestService"
+ android:exported="true" />
- <!-- NOTE: the below MUST be multiples of 64 -->
- <dimen name="layer_height">320px</dimen>
- <dimen name="layer_width">320px</dimen>
-
- <dimen name="layer_height_double">640px</dimen>
- <dimen name="layer_width_double">640px</dimen>
-
-</resources>
+ <service
+ android:name=".NestedTestService"
+ android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
new file mode 100644
index 000000000000..7879a1214c01
--- /dev/null
+++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.tests.enforcepermission.service;
+
+import android.annotation.EnforcePermission;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.tests.enforcepermission.INested;
+import android.util.Log;
+
+public class NestedTestService extends Service {
+ private static final String TAG = "EnforcePermission.NestedTestService";
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ Log.i(TAG, "onBind");
+ return mBinder;
+ }
+
+ private final INested.Stub mBinder = new INested.Stub() {
+ @Override
+ @EnforcePermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+ public void ProtectedByAccessNetworkState() {
+ ProtectedByAccessNetworkState_enforcePermission();
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.READ_SYNC_SETTINGS)
+ public void ProtectedByReadSyncSettings() {
+ ProtectedByReadSyncSettings_enforcePermission();
+ }
+ };
+}
diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
new file mode 100644
index 000000000000..e9b897db1294
--- /dev/null
+++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
@@ -0,0 +1,119 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.tests.enforcepermission.service;
+
+import android.annotation.EnforcePermission;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.tests.enforcepermission.INested;
+import android.tests.enforcepermission.IProtected;
+import android.util.Log;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class TestService extends Service {
+
+ private static final String TAG = "EnforcePermission.TestService";
+ private volatile ServiceConnection mNestedServiceConnection;
+
+ @Override
+ public void onCreate() {
+ mNestedServiceConnection = new ServiceConnection();
+ Intent intent = new Intent(this, NestedTestService.class);
+ boolean bound = bindService(intent, mNestedServiceConnection, Context.BIND_AUTO_CREATE);
+ if (!bound) {
+ Log.wtf(TAG, "bindService() on NestedTestService failed");
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ unbindService(mNestedServiceConnection);
+ }
+
+ private static final class ServiceConnection implements android.content.ServiceConnection {
+ private volatile CompletableFuture<INested> mFuture = new CompletableFuture<>();
+
+ public INested get() {
+ try {
+ return mFuture.get(1, TimeUnit.SECONDS);
+ } catch (ExecutionException | InterruptedException | TimeoutException e) {
+ throw new RuntimeException("Unable to reach NestedTestService: " + e.getMessage());
+ }
+ }
+
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ mFuture.complete(INested.Stub.asInterface(service));
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ mFuture = new CompletableFuture<>();
+ }
+ };
+
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ private final IProtected.Stub mBinder = new IProtected.Stub() {
+ @Override
+ @EnforcePermission(android.Manifest.permission.INTERNET)
+ public void ProtectedByInternet() {
+ ProtectedByInternet_enforcePermission();
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.VIBRATE)
+ public void ProtectedByVibrate() {
+ ProtectedByVibrate_enforcePermission();
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.INTERNET)
+ public void ProtectedByInternetAndVibrateImplicitly() {
+ ProtectedByInternetAndVibrateImplicitly_enforcePermission();
+
+ ProtectedByVibrate();
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.INTERNET)
+ public void ProtectedByInternetAndAccessNetworkStateImplicitly() throws RemoteException {
+ ProtectedByInternetAndAccessNetworkStateImplicitly_enforcePermission();
+
+ mNestedServiceConnection.get().ProtectedByAccessNetworkState();
+
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.INTERNET)
+ public void ProtectedByInternetAndReadSyncSettingsImplicitly() throws RemoteException {
+ ProtectedByInternetAndReadSyncSettingsImplicitly_enforcePermission();
+
+ mNestedServiceConnection.get().ProtectedByReadSyncSettings();
+ }
+ };
+}
diff --git a/tests/EnforcePermission/test-app/Android.bp b/tests/EnforcePermission/test-app/Android.bp
new file mode 100644
index 000000000000..cd53854189b7
--- /dev/null
+++ b/tests/EnforcePermission/test-app/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_test {
+ name: "EnforcePermissionTests",
+ srcs: [
+ "src/**/*.java",
+ ":frameworks-enforce-permission-test-aidl",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ ],
+ libs: [
+ "android.test.base",
+ "android.test.runner",
+ ],
+ data: [
+ ":EnforcePermissionTestHelper",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+ test_suites: ["device-tests"],
+}
diff --git a/tests/EnforcePermission/test-app/AndroidManifest.xml b/tests/EnforcePermission/test-app/AndroidManifest.xml
new file mode 100644
index 000000000000..4a0c6a86628f
--- /dev/null
+++ b/tests/EnforcePermission/test-app/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.tests.enforcepermission.tests">
+
+ <!-- Expected for the tests (not actually used) -->
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
+
+ <queries>
+ <package android:name="android.tests.enforcepermission.service" />
+ </queries>
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.tests.enforcepermission.tests"/>
+</manifest>
diff --git a/tests/EnforcePermission/test-app/AndroidTest.xml b/tests/EnforcePermission/test-app/AndroidTest.xml
new file mode 100644
index 000000000000..120381a7fb83
--- /dev/null
+++ b/tests/EnforcePermission/test-app/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="Runs EnforcePermission End-to-End Tests">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="EnforcePermissionTestHelper.apk"/>
+ <option name="test-file-name" value="EnforcePermissionTests.apk"/>
+ <option name="cleanup-apks" value="true" />
+ </target_preparer>
+
+ <option name="test-tag" value="EnforcePermissionTests"/>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="android.tests.enforcepermission.tests"/>
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+ </test>
+</configuration>
diff --git a/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
new file mode 100644
index 000000000000..d2a4a037f125
--- /dev/null
+++ b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.tests.enforcepermission.tests;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.tests.enforcepermission.IProtected;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class ServiceTest {
+
+ private static final String TAG = "EnforcePermission.Tests";
+ private static final String SERVICE_NAME = "android.tests.enforcepermission.service";
+ private static final int SERVICE_TIMEOUT_SEC = 5;
+
+ private Context mContext;
+ private volatile ServiceConnection mServiceConnection;
+
+ @Before
+ public void bindTestService() throws Exception {
+ Log.d(TAG, "bindTestService");
+ mContext = InstrumentationRegistry.getTargetContext();
+ mServiceConnection = new ServiceConnection();
+ Intent intent = new Intent();
+ intent.setClassName(SERVICE_NAME, SERVICE_NAME + ".TestService");
+ assertTrue(mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE));
+ }
+
+ @After
+ public void unbindTestService() throws Exception {
+ mContext.unbindService(mServiceConnection);
+ }
+
+ private static final class ServiceConnection implements android.content.ServiceConnection {
+ private volatile CompletableFuture<IProtected> mFuture = new CompletableFuture<>();
+
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ mFuture.complete(IProtected.Stub.asInterface(service));
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ mFuture = new CompletableFuture<>();
+ }
+
+ public IProtected get() {
+ try {
+ return mFuture.get(SERVICE_TIMEOUT_SEC, TimeUnit.SECONDS);
+ } catch (ExecutionException | InterruptedException | TimeoutException e) {
+ throw new RuntimeException("Unable to reach TestService: " + e.toString());
+ }
+ }
+ }
+
+ @Test
+ public void testImmediatePermissionGranted_succeeds()
+ throws RemoteException {
+ mServiceConnection.get().ProtectedByInternet();
+ }
+
+ @Test
+ public void testImmediatePermissionNotGranted_fails()
+ throws RemoteException {
+ final Exception ex = assertThrows(SecurityException.class,
+ () -> mServiceConnection.get().ProtectedByVibrate());
+ assertThat(ex.getMessage(), containsString("VIBRATE"));
+ }
+
+ @Test
+ public void testImmediatePermissionGrantedButImplicitLocalNotGranted_fails()
+ throws RemoteException {
+ final Exception ex = assertThrows(SecurityException.class,
+ () -> mServiceConnection.get().ProtectedByInternetAndVibrateImplicitly());
+ assertThat(ex.getMessage(), containsString("VIBRATE"));
+ }
+
+ @Test
+ public void testImmediatePermissionGrantedButImplicitNestedNotGranted_fails()
+ throws RemoteException {
+ final Exception ex = assertThrows(SecurityException.class,
+ () -> mServiceConnection.get()
+ .ProtectedByInternetAndAccessNetworkStateImplicitly());
+ assertThat(ex.getMessage(), containsString("ACCESS_NETWORK_STATE"));
+ }
+
+ @Test
+ public void testImmediatePermissionGrantedAndImplicitNestedGranted_succeeds()
+ throws RemoteException {
+ mServiceConnection.get().ProtectedByInternetAndReadSyncSettingsImplicitly();
+ }
+}
diff --git a/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java b/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
index 2e515705a253..761efe4a8484 100644
--- a/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
+++ b/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
@@ -110,7 +110,7 @@ public class FixVibrateSetting extends Activity implements View.OnClickListener
private void test() {
Intent intent = new Intent(this, FixVibrateSetting.class);
- PendingIntent pending = PendingIntent.getActivity(this, 0, intent, 0);
+ PendingIntent pending = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
Notification n = new Notification.Builder(this)
.setSmallIcon(R.drawable.stat_sys_warning)
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
index 7731e098d9f5..5301d674bacf 100644
--- a/tests/FlickerTests/Android.bp
+++ b/tests/FlickerTests/Android.bp
@@ -47,6 +47,9 @@ android_test {
"launcher-aosp-tapl",
"platform-test-annotations",
],
+ data: [
+ ":FlickerTestApp",
+ ],
}
java_library {
diff --git a/tests/HandwritingIme/OWNERS b/tests/HandwritingIme/OWNERS
new file mode 100644
index 000000000000..6bb4b17ed4eb
--- /dev/null
+++ b/tests/HandwritingIme/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 34867
+
+include /services/core/java/com/android/server/inputmethod/OWNERS
diff --git a/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/ViewDumpParser.java b/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/ViewDumpParser.java
index 2ad0da98c409..8b9c02049351 100644
--- a/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/ViewDumpParser.java
+++ b/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/ViewDumpParser.java
@@ -58,7 +58,7 @@ public class ViewDumpParser {
Object hash = getProperty(props, "__hash__");
if (name instanceof String && hash instanceof Integer) {
- return String.format(Locale.US, "%s@%x", name, hash);
+ return String.format(Locale.US, "%s@%x", name, (Integer) hash);
} else {
return null;
}
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index de9bbb6ef9fa..a92a6ae5a7a4 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -21,7 +21,7 @@ android_test {
"services.core.unboosted",
"testables",
"truth-prebuilt",
- "ub-uiautomator",
+ "androidx.test.uiautomator_uiautomator",
],
test_suites: ["device-tests"],
}
diff --git a/tests/Input/src/com/android/test/input/AnrTest.kt b/tests/Input/src/com/android/test/input/AnrTest.kt
index 1d65cc35c3bc..8025406499d8 100644
--- a/tests/Input/src/com/android/test/input/AnrTest.kt
+++ b/tests/Input/src/com/android/test/input/AnrTest.kt
@@ -27,14 +27,15 @@ import android.os.IInputConstants.UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLI
import android.os.SystemClock
import android.provider.Settings
import android.provider.Settings.Global.HIDE_ERROR_DIALOGS
-import android.support.test.uiautomator.By
-import android.support.test.uiautomator.UiDevice
-import android.support.test.uiautomator.UiObject2
-import android.support.test.uiautomator.Until
import android.testing.PollingCheck
import android.view.InputDevice
import android.view.MotionEvent
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.Until
+
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
diff --git a/tests/Internal/src/com/android/internal/app/OWNERS b/tests/Internal/src/com/android/internal/app/OWNERS
new file mode 100644
index 000000000000..d55dc78b8c0a
--- /dev/null
+++ b/tests/Internal/src/com/android/internal/app/OWNERS
@@ -0,0 +1,2 @@
+# Locale related test
+per-file *Locale* = file:/services/core/java/com/android/server/locales/OWNERS
diff --git a/tests/JankBench/app/src/main/java/com/android/benchmark/app/HomeActivity.java b/tests/JankBench/app/src/main/java/com/android/benchmark/app/HomeActivity.java
index 4de51fb57308..43dc9de6c90a 100644
--- a/tests/JankBench/app/src/main/java/com/android/benchmark/app/HomeActivity.java
+++ b/tests/JankBench/app/src/main/java/com/android/benchmark/app/HomeActivity.java
@@ -140,9 +140,9 @@ public class HomeActivity extends AppCompatActivity implements Button.OnClickLis
handleNextBenchmark();
}
+ @SuppressWarnings("MissingSuperCall") // TODO: Fix me
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-
}
private void handleNextBenchmark() {
diff --git a/tests/JankBench/app/src/main/java/com/android/benchmark/app/RunLocalBenchmarksActivity.java b/tests/JankBench/app/src/main/java/com/android/benchmark/app/RunLocalBenchmarksActivity.java
index c16efbda1830..d015a5695ec0 100644
--- a/tests/JankBench/app/src/main/java/com/android/benchmark/app/RunLocalBenchmarksActivity.java
+++ b/tests/JankBench/app/src/main/java/com/android/benchmark/app/RunLocalBenchmarksActivity.java
@@ -367,6 +367,7 @@ public class RunLocalBenchmarksActivity extends AppCompatActivity {
}
}
+ @SuppressWarnings("MissingSuperCall") // TODO: Fix me
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
diff --git a/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java b/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java
index 8afe8411a790..17fa210a1db6 100644
--- a/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java
+++ b/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java
@@ -295,8 +295,8 @@ public class MirrorSurfaceActivity extends Activity implements View.OnClickListe
private void updateMirror(Rect displayFrame, float scale) {
if (displayFrame.isEmpty()) {
Rect bounds = mWindowBounds;
- int defaultCropW = Math.round(bounds.width() / 2);
- int defaultCropH = Math.round(bounds.height() / 2);
+ int defaultCropW = bounds.width() / 2;
+ int defaultCropH = bounds.height() / 2;
displayFrame.set(0, 0, defaultCropW, defaultCropH);
}
diff --git a/tests/OdmApps/Android.bp b/tests/OdmApps/Android.bp
index de86498afd27..a5c6d6513f50 100644
--- a/tests/OdmApps/Android.bp
+++ b/tests/OdmApps/Android.bp
@@ -26,4 +26,8 @@ java_test_host {
srcs: ["src/**/*.java"],
libs: ["tradefed"],
test_suites: ["device-tests"],
+ data: [
+ ":TestOdmApp",
+ ":TestOdmPrivApp",
+ ],
}
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index 241206d8919b..65b7549f22d1 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -24,18 +24,14 @@ public class MainActivity extends Activity implements OnItemClickListener {
static final String KEY_NAME = "name";
static final String KEY_CLASS = "clazz";
- static Map<String,?> make(String name) {
- Map<String,Object> ret = new HashMap<String,Object>();
- ret.put(KEY_NAME, name);
- return ret;
- }
-
- @SuppressWarnings("serial")
- static final ArrayList<Map<String,?>> SAMPLES = new ArrayList<Map<String,?>>() {{
+ static final ArrayList<Map<String, ?>> SAMPLES = new ArrayList<>();
+ static {
for (int i = 1; i < 25; i++) {
- add(make("List Item: " + i));
+ Map<String, Object> sample = new HashMap<String, Object>();
+ sample.put(KEY_NAME, "List Item: " + i);
+ SAMPLES.add(sample);
}
- }};
+ }
Handler mHandler = new Handler();
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 9f6ce4e8425b..f2234fb64108 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -51,6 +51,7 @@ java_test_host {
data: [
":com.android.apex.apkrollback.test_v1",
":test.rebootless_apex_v1",
+ ":RollbackTest",
],
}
@@ -61,6 +62,7 @@ java_test_host {
static_libs: ["RollbackTestLib", "frameworks-base-hostutils"],
test_suites: ["general-tests"],
test_config: "NetworkStagedRollbackTest.xml",
+ data: [":RollbackTest"],
}
java_test_host {
diff --git a/tests/RollbackTest/SampleRollbackApp/Android.bp b/tests/RollbackTest/SampleRollbackApp/Android.bp
new file mode 100644
index 000000000000..074c7bc39155
--- /dev/null
+++ b/tests/RollbackTest/SampleRollbackApp/Android.bp
@@ -0,0 +1,33 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_app {
+ name: "SampleRollbackApp",
+ srcs: [
+ "src/**/*.java",
+ ],
+ resource_dirs: ["res"],
+ certificate: "platform",
+ sdk_version: "system_current",
+ min_sdk_version: "29",
+}
diff --git a/tests/RollbackTest/SampleRollbackApp/AndroidManifest.xml b/tests/RollbackTest/SampleRollbackApp/AndroidManifest.xml
new file mode 100644
index 000000000000..7fe4bae2a3fe
--- /dev/null
+++ b/tests/RollbackTest/SampleRollbackApp/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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.sample.rollbackapp" >
+ <uses-permission android:name="android.permission.MANAGE_ROLLBACKS" />
+ <application
+ android:label="@string/title_activity_main">
+ <activity
+ android:name="com.android.sample.rollbackapp.MainActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/RollbackTest/SampleRollbackApp/res/layout/activity_main.xml b/tests/RollbackTest/SampleRollbackApp/res/layout/activity_main.xml
new file mode 100644
index 000000000000..3fb987bb539c
--- /dev/null
+++ b/tests/RollbackTest/SampleRollbackApp/res/layout/activity_main.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:id="@+id/trigger_rollback_button"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ style="?android:attr/buttonBarButtonStyle"
+ android:text="Rollback Selected" />
+
+ <ListView
+ android:id="@+id/listView"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:divider="?android:attr/dividerHorizontal"
+ android:dividerHeight="1dp" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/tests/RollbackTest/SampleRollbackApp/res/layout/listitem_rollbackinfo.xml b/tests/RollbackTest/SampleRollbackApp/res/layout/listitem_rollbackinfo.xml
new file mode 100644
index 000000000000..f650dd5d2230
--- /dev/null
+++ b/tests/RollbackTest/SampleRollbackApp/res/layout/listitem_rollbackinfo.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingTop="10dp"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp">
+ <TextView android:id="@+id/rollback_id"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="20dp"/>
+ <TextView android:id="@+id/rollback_packages"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="16dp"/>
+ <CheckBox android:id="@+id/checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Roll Back"/>
+ </LinearLayout>
+</RelativeLayout> \ No newline at end of file
diff --git a/tests/RollbackTest/SampleRollbackApp/res/values/strings.xml b/tests/RollbackTest/SampleRollbackApp/res/values/strings.xml
new file mode 100644
index 000000000000..a85b6800a146
--- /dev/null
+++ b/tests/RollbackTest/SampleRollbackApp/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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="title_activity_main" description="Launcher title">Rollback Sample App</string>
+</resources> \ No newline at end of file
diff --git a/tests/RollbackTest/SampleRollbackApp/src/com/android/sample/rollbackapp/MainActivity.java b/tests/RollbackTest/SampleRollbackApp/src/com/android/sample/rollbackapp/MainActivity.java
new file mode 100644
index 000000000000..79a2f1f5f4de
--- /dev/null
+++ b/tests/RollbackTest/SampleRollbackApp/src/com/android/sample/rollbackapp/MainActivity.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.sample.rollbackapp;
+
+import static android.app.PendingIntent.FLAG_MUTABLE;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.RollbackInfo;
+import android.content.rollback.RollbackManager;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class MainActivity extends Activity {
+
+ List<Integer> mIdsToRollback = new ArrayList<>();
+ Button mTriggerRollbackButton;
+ RollbackManager mRollbackManager;
+ static final String ROLLBACK_ID_EXTRA = "rollbackId";
+ static final String ACTION_NAME = MainActivity.class.getName();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ ListView rollbackListView = findViewById(R.id.listView);
+ mRollbackManager = getApplicationContext().getSystemService(RollbackManager.class);
+ initTriggerRollbackButton();
+
+ // Populate list of available rollbacks.
+ List<RollbackInfo> availableRollbacks = mRollbackManager.getAvailableRollbacks();
+ CustomAdapter adapter = new CustomAdapter(availableRollbacks);
+ rollbackListView.setAdapter(adapter);
+
+ // Register receiver for rollback status events.
+ getApplicationContext().registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context,
+ Intent intent) {
+ int rollbackId = intent.getIntExtra(ROLLBACK_ID_EXTRA, -1);
+ int rollbackStatusCode = intent.getIntExtra(RollbackManager.EXTRA_STATUS,
+ RollbackManager.STATUS_FAILURE);
+ String rollbackStatus = "FAILED";
+ if (rollbackStatusCode == RollbackManager.STATUS_SUCCESS) {
+ rollbackStatus = "SUCCESS";
+ mTriggerRollbackButton.setClickable(false);
+ }
+ makeToast("Status for rollback ID " + rollbackId + " is " + rollbackStatus);
+ }}, new IntentFilter(ACTION_NAME), Context.RECEIVER_NOT_EXPORTED);
+ }
+
+ private void initTriggerRollbackButton() {
+ mTriggerRollbackButton = findViewById(R.id.trigger_rollback_button);
+ mTriggerRollbackButton.setClickable(false);
+ mTriggerRollbackButton.setOnClickListener(v -> {
+ // Commits all selected rollbacks. Rollback status events will be sent to our receiver.
+ for (int i = 0; i < mIdsToRollback.size(); i++) {
+ Intent intent = new Intent(ACTION_NAME);
+ intent.putExtra(ROLLBACK_ID_EXTRA, mIdsToRollback.get(i));
+ PendingIntent pendingIntent = PendingIntent.getBroadcast(
+ getApplicationContext(), 0, intent, FLAG_MUTABLE);
+ mRollbackManager.commitRollback(mIdsToRollback.get(i),
+ Collections.emptyList(),
+ pendingIntent.getIntentSender());
+ }
+ });
+ }
+
+
+
+ private void makeToast(String message) {
+ runOnUiThread(() -> Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show());
+ }
+
+ public class CustomAdapter extends BaseAdapter {
+ List<RollbackInfo> mRollbackInfos;
+ LayoutInflater mInflater = LayoutInflater.from(getApplicationContext());
+
+ CustomAdapter(List<RollbackInfo> rollbackInfos) {
+ mRollbackInfos = rollbackInfos;
+ }
+
+ @Override
+ public int getCount() {
+ return mRollbackInfos.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mRollbackInfos.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return mRollbackInfos.get(position).getRollbackId();
+ }
+
+ @Override
+ public View getView(int position, View view, ViewGroup parent) {
+ if (view == null) {
+ view = mInflater.inflate(R.layout.listitem_rollbackinfo, null);
+ }
+ RollbackInfo rollbackInfo = mRollbackInfos.get(position);
+ TextView rollbackIdView = view.findViewById(R.id.rollback_id);
+ rollbackIdView.setText("Rollback ID " + rollbackInfo.getRollbackId());
+ TextView rollbackPackagesTextView = view.findViewById(R.id.rollback_packages);
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < rollbackInfo.getPackages().size(); i++) {
+ PackageRollbackInfo pkgInfo = rollbackInfo.getPackages().get(i);
+ sb.append(pkgInfo.getPackageName() + ": "
+ + pkgInfo.getVersionRolledBackFrom().getLongVersionCode() + " -> "
+ + pkgInfo.getVersionRolledBackTo().getLongVersionCode() + ",");
+ }
+ sb.deleteCharAt(sb.length() - 1);
+ rollbackPackagesTextView.setText(sb.toString());
+ CheckBox checkbox = view.findViewById(R.id.checkbox);
+ checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ if (isChecked) {
+ mIdsToRollback.add(rollbackInfo.getRollbackId());
+ } else {
+ mIdsToRollback.remove(Integer.valueOf(rollbackInfo.getRollbackId()));
+ }
+ mTriggerRollbackButton.setClickable(mIdsToRollback.size() > 0);
+ });
+ return view;
+ }
+ }
+}
diff --git a/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp.java b/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp.java
index c11b0f3acf79..f85fb0f267d5 100644
--- a/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp.java
+++ b/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp.java
@@ -30,6 +30,7 @@ public class CrashyApp extends Activity {
setContentView(tv);
}
+ @SuppressWarnings("ReturnValueIgnored")
@Override
public void onResume() {
((String) null).length();
diff --git a/tests/SoundTriggerTestApp/OWNERS b/tests/SoundTriggerTestApp/OWNERS
index 9db19a37812b..a0fcfc52704d 100644
--- a/tests/SoundTriggerTestApp/OWNERS
+++ b/tests/SoundTriggerTestApp/OWNERS
@@ -1,2 +1,2 @@
-include /core/java/android/media/soundtrigger/OWNERS
+include /media/java/android/media/soundtrigger/OWNERS
mdooley@google.com
diff --git a/tests/SoundTriggerTests/OWNERS b/tests/SoundTriggerTests/OWNERS
index 816bc6bba639..1e41886fe716 100644
--- a/tests/SoundTriggerTests/OWNERS
+++ b/tests/SoundTriggerTests/OWNERS
@@ -1 +1 @@
-include /core/java/android/media/soundtrigger/OWNERS
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
index cce0dde9e6b9..38e74470e3d5 100644
--- a/tests/StagedInstallTest/Android.bp
+++ b/tests/StagedInstallTest/Android.bp
@@ -55,6 +55,7 @@ java_test_host {
"cts-install-lib-host",
],
data: [
+ ":StagedInstallInternalTestApp",
":apex.apexd_test",
":com.android.apex.apkrollback.test_v1",
":StagedInstallTestApexV2",
diff --git a/tests/SurfaceControlViewHostTest/OWNERS b/tests/SurfaceControlViewHostTest/OWNERS
new file mode 100644
index 000000000000..0862c05e0ee4
--- /dev/null
+++ b/tests/SurfaceControlViewHostTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/tests/SystemMemoryTest/host/Android.bp b/tests/SystemMemoryTest/host/Android.bp
index 79744625b752..cc8bc45a7411 100644
--- a/tests/SystemMemoryTest/host/Android.bp
+++ b/tests/SystemMemoryTest/host/Android.bp
@@ -26,4 +26,7 @@ java_test_host {
srcs: ["src/**/*.java"],
libs: ["tradefed"],
test_suites: ["general-tests"],
+ data: [
+ ":SystemMemoryTestDevice",
+ ],
}
diff --git a/tests/TouchLatency/OWNERS b/tests/TouchLatency/OWNERS
new file mode 100644
index 000000000000..2b7de2555587
--- /dev/null
+++ b/tests/TouchLatency/OWNERS
@@ -0,0 +1,2 @@
+include platform/frameworks/base:/graphics/java/android/graphics/OWNERS
+include platform/frameworks/native:/services/surfaceflinger/OWNERS \ No newline at end of file
diff --git a/tests/TrustTests/Android.bp b/tests/TrustTests/Android.bp
index 77f98e88f1eb..a1b888aef934 100644
--- a/tests/TrustTests/Android.bp
+++ b/tests/TrustTests/Android.bp
@@ -24,7 +24,7 @@ android_test {
static_libs: [
"androidx.test.rules",
"androidx.test.ext.junit",
- "androidx.test.uiautomator",
+ "androidx.test.uiautomator_uiautomator",
"mockito-target-minus-junit4",
"servicestests-utils",
"truth-prebuilt",
diff --git a/tests/UpdatableSystemFontTest/Android.bp b/tests/UpdatableSystemFontTest/Android.bp
index 9a9e42bfc300..9bfcc18ee301 100644
--- a/tests/UpdatableSystemFontTest/Android.bp
+++ b/tests/UpdatableSystemFontTest/Android.bp
@@ -37,6 +37,7 @@ android_test {
"vts",
],
data: [
+ ":EmojiRenderingTestApp",
":UpdatableSystemFontTestCertDer",
":UpdatableSystemFontTest_NotoColorEmoji.ttf",
":UpdatableSystemFontTest_NotoColorEmoji.sig",
diff --git a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java
index cbe13d9aa149..650686ff3b85 100644
--- a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java
+++ b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java
@@ -373,6 +373,10 @@ public class UpdatableSystemFontTest {
try (InputStream is = new FileInputStream(certPath)) {
result = runShellCommand("mini-keyctl padd asymmetric fsv_test .fs-verity", is);
}
+ // /data/local/tmp is not readable by system server. Copy a cert file to /data/fonts
+ final String copiedCert = "/data/fonts/debug_cert.der";
+ runShellCommand("cp " + certPath + " " + copiedCert, null);
+ runShellCommand("cmd font install-debug-cert " + copiedCert, null);
// Assert that there are no errors.
assertThat(result.second).isEmpty();
String keyId = result.first.trim();
diff --git a/tests/UsbManagerTests/lib/src/com/android/server/usblib/UsbManagerTestLib.java b/tests/UsbManagerTests/lib/src/com/android/server/usblib/UsbManagerTestLib.java
index 782439f80fc8..98bf541944c3 100644
--- a/tests/UsbManagerTests/lib/src/com/android/server/usblib/UsbManagerTestLib.java
+++ b/tests/UsbManagerTests/lib/src/com/android/server/usblib/UsbManagerTestLib.java
@@ -24,12 +24,15 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.usb.UsbManager;
+import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.concurrent.atomic.AtomicInteger;
+
/**
* Unit tests lib for {@link android.hardware.usb.UsbManager}.
*/
@@ -42,6 +45,11 @@ public class UsbManagerTestLib {
private UsbManager mUsbManagerMock;
@Mock private android.hardware.usb.IUsbManager mMockUsbService;
+ /**
+ * Counter for tracking UsbOperation operations.
+ */
+ private static final AtomicInteger sUsbOperationCount = new AtomicInteger();
+
public UsbManagerTestLib(Context context) {
MockitoAnnotations.initMocks(this);
mContext = context;
@@ -82,10 +90,11 @@ public class UsbManagerTestLib {
}
private void testSetCurrentFunctionsMock_Matched(long functions) {
+ int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid();
try {
setCurrentFunctions(functions);
- verify(mMockUsbService).setCurrentFunctions(eq(functions));
+ verify(mMockUsbService).setCurrentFunctions(eq(functions), operationId);
} catch (RemoteException remEx) {
Log.w(TAG, "RemoteException");
}
@@ -106,9 +115,10 @@ public class UsbManagerTestLib {
}
public void testSetCurrentFunctionsEx(long functions) throws Exception {
+ int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid();
setCurrentFunctions(functions);
- verify(mMockUsbService).setCurrentFunctions(eq(functions));
+ verify(mMockUsbService).setCurrentFunctions(eq(functions), operationId);
}
public void testGetCurrentFunctions_shouldMatched() {
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
index 861d221238ff..e06a4cb92609 100644
--- a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
+++ b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
@@ -98,7 +98,7 @@ public class UsbHandlerTest {
}
@Override
- protected void setEnabledFunctions(long functions, boolean force) {
+ protected void setEnabledFunctions(long functions, boolean force, int operationId) {
mCurrentFunctions = functions;
}
@@ -134,6 +134,20 @@ public class UsbHandlerTest {
protected void sendStickyBroadcast(Intent intent) {
mBroadcastedIntent = intent;
}
+
+ @Override
+ public void handlerInitDone(int operationId) {
+ }
+
+ @Override
+ public void setCurrentUsbFunctionsCb(long functions,
+ int status, int mRequest, long mFunctions, boolean mChargingFunctions){
+ }
+
+ @Override
+ public void getUsbSpeedCb(int speed){
+ }
+
}
@Before
diff --git a/tests/VectorDrawableTest/OWNERS b/tests/VectorDrawableTest/OWNERS
new file mode 100644
index 000000000000..27e16681899e
--- /dev/null
+++ b/tests/VectorDrawableTest/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 24939
+
+include /graphics/java/android/graphics/OWNERS
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index db4898492ac5..661dd845757b 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -33,6 +33,8 @@ import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
+import java.util.Arrays;
+
public class MainInteractionSession extends VoiceInteractionSession
implements View.OnClickListener {
static final String TAG = "MainInteractionSession";
@@ -403,7 +405,7 @@ public class MainInteractionSession extends VoiceInteractionSession
@Override
public void onRequestPickOption(PickOptionRequest request) {
Log.i(TAG, "onPickOption: prompt=" + request.getVoicePrompt() + " options="
- + request.getOptions() + " extras=" + request.getExtras());
+ + Arrays.toString(request.getOptions()) + " extras=" + request.getExtras());
mConfirmButton.setText("Pick Option");
mPendingRequest = request;
setPrompt(request.getVoicePrompt());
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java
index 733f602f6c14..8ae7186461d3 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java
@@ -24,6 +24,8 @@ import android.view.View;
import android.widget.Button;
import android.widget.TextView;
+import java.util.Arrays;
+
public class StartVoiceInteractionActivity extends Activity implements View.OnClickListener {
static final String TAG = "LocalVoiceInteractionActivity";
@@ -187,7 +189,8 @@ public class StartVoiceInteractionActivity extends Activity implements View.OnCl
}
@Override
public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) {
- Log.i(TAG, "Pick result: finished=" + finished + " selections=" + selections
+ Log.i(TAG, "Pick result: finished=" + finished
+ + " selections=" + Arrays.toString(selections)
+ " result=" + result);
StringBuilder sb = new StringBuilder();
if (finished) {
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
index ada0e21e059a..4fc3a15ac38d 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
@@ -28,6 +28,8 @@ import android.view.View;
import android.widget.Button;
import android.widget.TextView;
+import java.util.Arrays;
+
public class TestInteractionActivity extends Activity implements View.OnClickListener {
static final String TAG = "TestInteractionActivity";
@@ -240,7 +242,8 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis
}
@Override
public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) {
- Log.i(TAG, "Pick result: finished=" + finished + " selections=" + selections
+ Log.i(TAG, "Pick result: finished=" + finished
+ + " selections=" + Arrays.toString(selections)
+ " result=" + result);
StringBuilder sb = new StringBuilder();
if (finished) {
diff --git a/tests/WindowAnimationJank/Android.bp b/tests/WindowAnimationJank/Android.bp
index ed86aa5f90ea..8542f885d645 100644
--- a/tests/WindowAnimationJank/Android.bp
+++ b/tests/WindowAnimationJank/Android.bp
@@ -25,7 +25,7 @@ android_test {
name: "WindowAnimationJank",
srcs: ["src/**/*.java"],
static_libs: [
- "ub-uiautomator",
+ "androidx.test.uiautomator_uiautomator",
"androidx.test.janktesthelper",
"junit",
],
diff --git a/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java b/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java
index 25314644ca7e..48a359c4d0c6 100644
--- a/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java
+++ b/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java
@@ -18,11 +18,12 @@ import android.app.UiAutomation;
import android.content.ComponentName;
import android.content.Intent;
import android.os.SystemClock;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.Until;
+
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
/**
* Set of helpers to manipulate test activities.
diff --git a/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java b/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java
index a8ace162c4d0..cb7c5112cba7 100644
--- a/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java
+++ b/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java
@@ -16,9 +16,8 @@
package android.windowanimationjank;
-import android.support.test.uiautomator.UiDevice;
-
import androidx.test.jank.JankTestBase;
+import androidx.test.uiautomator.UiDevice;
/**
* This adds additional system level jank monitor and its result is merged with primary monitor
diff --git a/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java b/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java
new file mode 100644
index 000000000000..b94bb41c0988
--- /dev/null
+++ b/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.os.test;
+
+import static android.permission.PermissionManager.PERMISSION_GRANTED;
+import static android.permission.PermissionManager.PERMISSION_HARD_DENIED;
+
+import android.annotation.NonNull;
+import android.content.AttributionSource;
+import android.os.PermissionEnforcer;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Fake for {@link PermissionEnforcer}. Useful for tests wanting to mock the
+ * permission checks of an AIDL service. FakePermissionEnforcer may be passed
+ * to the constructor of the AIDL-generated Stub class.
+ *
+ */
+public class FakePermissionEnforcer extends PermissionEnforcer {
+ private Set<String> mGranted;
+
+ public FakePermissionEnforcer() {
+ mGranted = new HashSet();
+ }
+
+ public void grant(String permission) {
+ mGranted.add(permission);
+ }
+
+ public void revoke(String permission) {
+ mGranted.remove(permission);
+ }
+
+ private boolean granted(String permission) {
+ return mGranted.contains(permission);
+ }
+
+ @Override
+ protected int checkPermission(@NonNull String permission,
+ @NonNull AttributionSource source) {
+ return granted(permission) ? PERMISSION_GRANTED : PERMISSION_HARD_DENIED;
+ }
+
+ @Override
+ protected int checkPermission(@NonNull String permission, int pid, int uid) {
+ return granted(permission) ? PERMISSION_GRANTED : PERMISSION_HARD_DENIED;
+ }
+}
diff --git a/tests/utils/testutils/java/android/os/test/OWNERS b/tests/utils/testutils/java/android/os/test/OWNERS
new file mode 100644
index 000000000000..3a9129e1bb69
--- /dev/null
+++ b/tests/utils/testutils/java/android/os/test/OWNERS
@@ -0,0 +1 @@
+per-file FakePermissionEnforcer.java = file:/tests/EnforcePermission/OWNERS
diff --git a/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java b/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java
index 3da8b460df13..cc3781a0bfb3 100644
--- a/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java
+++ b/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java
@@ -147,12 +147,39 @@ public class BroadcastInterceptingContext extends ContextWrapper {
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
- return registerReceiver(receiver, filter, null, null);
+ return registerReceiver(receiver, filter, null, null, 0);
+ }
+
+ /**
+ * Registers the specified {@code receiver} to listen for broadcasts that match the {@code
+ * filter} in the current process.
+ *
+ * <p>Since this method only listens for broadcasts in the current process, the provided {@code
+ * flags} are ignored; this method is primarily intended to allow receivers that register with
+ * flags to register in the current process during tests.
+ */
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, int flags) {
+ return registerReceiver(receiver, filter, null, null, flags);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
+ return registerReceiver(receiver, filter, broadcastPermission, scheduler, 0);
+ }
+
+ /**
+ * Registers the specified {@code receiver} to listen for broadcasts that match the {@code
+ * filter} to run in the context of the specified {@code scheduler} in the current process.
+ *
+ * <p>Since this method only listens for broadcasts in the current process, the provided {@code
+ * flags} are ignored; this method is primarily intended to allow receivers that register with
+ * flags to register in the current process during tests.
+ */
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
+ String broadcastPermission, Handler scheduler, int flags) {
synchronized (mInterceptors) {
mInterceptors.add(new BroadcastInterceptor(receiver, filter, scheduler));
}
@@ -219,6 +246,12 @@ public class BroadcastInterceptingContext extends ContextWrapper {
}
@Override
+ public void sendBroadcastAsUser(Intent intent, UserHandle user,
+ String receiverPermission, Bundle options) {
+ sendBroadcast(intent);
+ }
+
+ @Override
public void sendStickyBroadcast(Intent intent) {
sendBroadcast(intent);
}
diff --git a/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java b/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java
index 2fbcf9d87bd4..156961312323 100644
--- a/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java
@@ -20,6 +20,7 @@ import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.fail;
import org.junit.Test;
@@ -31,8 +32,8 @@ public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTe
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 getTestNetworkTemplate() {
+ // Public for use in UnderlyingNetworkControllerTest
+ public static VcnCellUnderlyingNetworkTemplate.Builder getTestNetworkTemplateBuilder() {
return new VcnCellUnderlyingNetworkTemplate.Builder()
.setMetered(MATCH_FORBIDDEN)
.setMinUpstreamBandwidthKbps(
@@ -44,13 +45,44 @@ public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTe
.setOperatorPlmnIds(ALLOWED_PLMN_IDS)
.setSimSpecificCarrierIds(ALLOWED_CARRIER_IDS)
.setRoaming(MATCH_FORBIDDEN)
- .setOpportunistic(MATCH_REQUIRED)
- .build();
+ .setOpportunistic(MATCH_REQUIRED);
+ }
+
+ // Package private for use in VcnGatewayConnectionConfigTest
+ static VcnCellUnderlyingNetworkTemplate getTestNetworkTemplate() {
+ return getTestNetworkTemplateBuilder().build();
+ }
+
+ private void setAllCapabilities(
+ VcnCellUnderlyingNetworkTemplate.Builder builder, int matchCriteria) {
+ builder.setCbs(matchCriteria);
+ builder.setDun(matchCriteria);
+ builder.setIms(matchCriteria);
+ builder.setInternet(matchCriteria);
+ builder.setMms(matchCriteria);
+ builder.setRcs(matchCriteria);
+ }
+
+ private void verifyAllCapabilities(
+ VcnCellUnderlyingNetworkTemplate template,
+ int expectMatchCriteriaforNonInternet,
+ int expectMatchCriteriaforInternet) {
+ assertEquals(expectMatchCriteriaforNonInternet, template.getCbs());
+ assertEquals(expectMatchCriteriaforNonInternet, template.getDun());
+ assertEquals(expectMatchCriteriaforNonInternet, template.getIms());
+ assertEquals(expectMatchCriteriaforNonInternet, template.getMms());
+ assertEquals(expectMatchCriteriaforNonInternet, template.getRcs());
+
+ assertEquals(expectMatchCriteriaforInternet, template.getInternet());
}
@Test
public void testBuilderAndGetters() {
- final VcnCellUnderlyingNetworkTemplate networkPriority = getTestNetworkTemplate();
+ final VcnCellUnderlyingNetworkTemplate.Builder builder = getTestNetworkTemplateBuilder();
+ setAllCapabilities(builder, MATCH_REQUIRED);
+
+ final VcnCellUnderlyingNetworkTemplate networkPriority = builder.build();
+
assertEquals(MATCH_FORBIDDEN, networkPriority.getMetered());
assertEquals(
TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS,
@@ -68,6 +100,8 @@ public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTe
assertEquals(ALLOWED_CARRIER_IDS, networkPriority.getSimSpecificCarrierIds());
assertEquals(MATCH_FORBIDDEN, networkPriority.getRoaming());
assertEquals(MATCH_REQUIRED, networkPriority.getOpportunistic());
+
+ verifyAllCapabilities(networkPriority, MATCH_REQUIRED, MATCH_REQUIRED);
}
@Test
@@ -86,6 +120,8 @@ public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTe
assertEquals(new HashSet<Integer>(), networkPriority.getSimSpecificCarrierIds());
assertEquals(MATCH_ANY, networkPriority.getRoaming());
assertEquals(MATCH_ANY, networkPriority.getOpportunistic());
+
+ verifyAllCapabilities(networkPriority, MATCH_ANY, MATCH_REQUIRED);
}
@Test
@@ -112,6 +148,25 @@ public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTe
}
@Test
+ public void testBuildFailWithoutRequiredCapabilities() {
+ try {
+ new VcnCellUnderlyingNetworkTemplate.Builder().setInternet(MATCH_ANY).build();
+
+ fail("Expected IAE for missing required capabilities");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testEqualsWithDifferentCapabilities() {
+ final VcnCellUnderlyingNetworkTemplate left =
+ new VcnCellUnderlyingNetworkTemplate.Builder().setDun(MATCH_REQUIRED).build();
+ final VcnCellUnderlyingNetworkTemplate right =
+ new VcnCellUnderlyingNetworkTemplate.Builder().setMms(MATCH_REQUIRED).build();
+ assertNotEquals(left, right);
+ }
+
+ @Test
public void testPersistableBundle() {
final VcnCellUnderlyingNetworkTemplate networkPriority = getTestNetworkTemplate();
assertEquals(
@@ -119,4 +174,16 @@ public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTe
VcnUnderlyingNetworkTemplate.fromPersistableBundle(
networkPriority.toPersistableBundle()));
}
+
+ @Test
+ public void testPersistableBundleWithCapabilities() {
+ final VcnCellUnderlyingNetworkTemplate.Builder builder = getTestNetworkTemplateBuilder();
+ setAllCapabilities(builder, MATCH_REQUIRED);
+
+ final VcnCellUnderlyingNetworkTemplate networkPriority = builder.build();
+ assertEquals(
+ networkPriority,
+ VcnUnderlyingNetworkTemplate.fromPersistableBundle(
+ networkPriority.toPersistableBundle()));
+ }
}
diff --git a/tests/vcn/java/android/net/vcn/VcnConfigTest.java b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
index 7ac51b7e3342..73a0a6183cb6 100644
--- a/tests/vcn/java/android/net/vcn/VcnConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
@@ -16,7 +16,13 @@
package android.net.vcn;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -24,6 +30,7 @@ import static org.mockito.Mockito.mock;
import android.annotation.NonNull;
import android.content.Context;
import android.os.Parcel;
+import android.util.ArraySet;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -42,19 +49,36 @@ public class VcnConfigTest {
private static final Set<VcnGatewayConnectionConfig> GATEWAY_CONNECTION_CONFIGS =
Collections.singleton(VcnGatewayConnectionConfigTest.buildTestConfig());
+ private static final Set<Integer> RESTRICTED_TRANSPORTS = new ArraySet<>();
+
+ static {
+ RESTRICTED_TRANSPORTS.add(TRANSPORT_WIFI);
+ RESTRICTED_TRANSPORTS.add(TRANSPORT_CELLULAR);
+ }
+
private final Context mContext = mock(Context.class);
// Public visibility for VcnManagementServiceTest
- public static VcnConfig buildTestConfig(@NonNull Context context) {
+ public static VcnConfig buildTestConfig(
+ @NonNull Context context, Set<Integer> restrictedTransports) {
VcnConfig.Builder builder = new VcnConfig.Builder(context);
for (VcnGatewayConnectionConfig gatewayConnectionConfig : GATEWAY_CONNECTION_CONFIGS) {
builder.addGatewayConnectionConfig(gatewayConnectionConfig);
}
+ if (restrictedTransports != null) {
+ builder.setRestrictedUnderlyingNetworkTransports(restrictedTransports);
+ }
+
return builder.build();
}
+ // Public visibility for VcnManagementServiceTest
+ public static VcnConfig buildTestConfig(@NonNull Context context) {
+ return buildTestConfig(context, null);
+ }
+
@Before
public void setUp() throws Exception {
doReturn(TEST_PACKAGE_NAME).when(mContext).getOpPackageName();
@@ -91,11 +115,25 @@ public class VcnConfigTest {
}
@Test
- public void testBuilderAndGetters() {
+ public void testBuilderAndGettersDefaultValues() {
final VcnConfig config = buildTestConfig(mContext);
assertEquals(TEST_PACKAGE_NAME, config.getProvisioningPackageName());
assertEquals(GATEWAY_CONNECTION_CONFIGS, config.getGatewayConnectionConfigs());
+ assertFalse(config.isTestModeProfile());
+ assertEquals(
+ Collections.singleton(TRANSPORT_WIFI),
+ config.getRestrictedUnderlyingNetworkTransports());
+ }
+
+ @Test
+ public void testBuilderAndGettersConfigRestrictedTransports() {
+ final VcnConfig config = buildTestConfig(mContext, RESTRICTED_TRANSPORTS);
+
+ assertEquals(TEST_PACKAGE_NAME, config.getProvisioningPackageName());
+ assertEquals(GATEWAY_CONNECTION_CONFIGS, config.getGatewayConnectionConfigs());
+ assertFalse(config.isTestModeProfile());
+ assertEquals(RESTRICTED_TRANSPORTS, config.getRestrictedUnderlyingNetworkTransports());
}
@Test
@@ -106,6 +144,55 @@ public class VcnConfigTest {
}
@Test
+ public void testPersistableBundleWithRestrictedTransports() {
+ final VcnConfig config = buildTestConfig(mContext, RESTRICTED_TRANSPORTS);
+
+ assertEquals(config, new VcnConfig(config.toPersistableBundle()));
+ }
+
+ @Test
+ public void testEqualityWithRestrictedTransports() {
+ final VcnConfig config = buildTestConfig(mContext, RESTRICTED_TRANSPORTS);
+ final VcnConfig configEqual = buildTestConfig(mContext, RESTRICTED_TRANSPORTS);
+ final VcnConfig configNotEqual =
+ buildTestConfig(mContext, Collections.singleton(TRANSPORT_WIFI));
+
+ assertEquals(config, configEqual);
+ assertNotEquals(config, configNotEqual);
+ }
+
+ private VcnConfig buildConfigRestrictTransportTest(boolean isTestMode) throws Exception {
+ VcnConfig.Builder builder =
+ new VcnConfig.Builder(mContext)
+ .setRestrictedUnderlyingNetworkTransports(Set.of(TRANSPORT_TEST));
+ if (isTestMode) {
+ builder.setIsTestModeProfile();
+ }
+
+ for (VcnGatewayConnectionConfig gatewayConnectionConfig : GATEWAY_CONNECTION_CONFIGS) {
+ builder.addGatewayConnectionConfig(gatewayConnectionConfig);
+ }
+
+ return builder.build();
+ }
+
+ @Test
+ public void testRestrictTransportTestInTestModeProfile() throws Exception {
+ final VcnConfig config = buildConfigRestrictTransportTest(true /* isTestMode */);
+ assertEquals(Set.of(TRANSPORT_TEST), config.getRestrictedUnderlyingNetworkTransports());
+ }
+
+ @Test
+ public void testRestrictTransportTestInNonTestModeProfile() throws Exception {
+ try {
+ buildConfigRestrictTransportTest(false /* isTestMode */);
+ fail("Expected exception because the config is not a test mode profile");
+ } catch (Exception expected) {
+
+ }
+ }
+
+ @Test
public void testParceling() {
final VcnConfig config = buildTestConfig(mContext);
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
index 2aef9ae7ca32..a1a39ff173b4 100644
--- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -19,9 +19,11 @@ package android.net.vcn;
import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
import static android.net.vcn.VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES;
import static android.net.vcn.VcnGatewayConnectionConfig.UNDERLYING_NETWORK_TEMPLATES_KEY;
+import static android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
@@ -42,7 +44,9 @@ import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
@@ -78,6 +82,10 @@ public class VcnGatewayConnectionConfigTest {
TimeUnit.MINUTES.toMillis(30)
};
public static final int MAX_MTU = 1360;
+ public static final int MIN_UDP_PORT_4500_NAT_TIMEOUT = 120;
+
+ private static final Set<Integer> GATEWAY_OPTIONS =
+ Collections.singleton(VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY);
public static final IkeTunnelConnectionParams TUNNEL_CONNECTION_PARAMS =
TunnelConnectionParamsUtilsTest.buildTestParams();
@@ -93,14 +101,22 @@ public class VcnGatewayConnectionConfigTest {
EXPOSED_CAPS);
}
- // Public for use in VcnGatewayConnectionTest
- public static VcnGatewayConnectionConfig buildTestConfig() {
+ // Public for use in UnderlyingNetworkControllerTest
+ public static VcnGatewayConnectionConfig buildTestConfig(
+ List<VcnUnderlyingNetworkTemplate> nwTemplates) {
final VcnGatewayConnectionConfig.Builder builder =
- newBuilder().setVcnUnderlyingNetworkPriorities(UNDERLYING_NETWORK_TEMPLATES);
+ newBuilder()
+ .setVcnUnderlyingNetworkPriorities(nwTemplates)
+ .setMinUdpPort4500NatTimeoutSeconds(MIN_UDP_PORT_4500_NAT_TIMEOUT);
return buildTestConfigWithExposedCaps(builder, EXPOSED_CAPS);
}
+ // Public for use in VcnGatewayConnectionTest
+ public static VcnGatewayConnectionConfig buildTestConfig() {
+ return buildTestConfig(UNDERLYING_NETWORK_TEMPLATES);
+ }
+
private static VcnGatewayConnectionConfig.Builder newBuilder() {
// Append a unique identifier to the name prefix to guarantee that all created
// VcnGatewayConnectionConfigs have a unique name (required by VcnConfig).
@@ -109,10 +125,16 @@ public class VcnGatewayConnectionConfigTest {
TUNNEL_CONNECTION_PARAMS);
}
- private static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(
- VcnGatewayConnectionConfig.Builder builder, int... exposedCaps) {
+ private static VcnGatewayConnectionConfig buildTestConfigWithExposedCapsAndOptions(
+ VcnGatewayConnectionConfig.Builder builder,
+ Set<Integer> gatewayOptions,
+ int... exposedCaps) {
builder.setRetryIntervalsMillis(RETRY_INTERVALS_MS).setMaxMtu(MAX_MTU);
+ for (int option : gatewayOptions) {
+ builder.addGatewayOption(option);
+ }
+
for (int caps : exposedCaps) {
builder.addExposedCapability(caps);
}
@@ -120,11 +142,28 @@ public class VcnGatewayConnectionConfigTest {
return builder.build();
}
+ private static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(
+ VcnGatewayConnectionConfig.Builder builder, int... exposedCaps) {
+ return buildTestConfigWithExposedCapsAndOptions(
+ builder, Collections.emptySet(), exposedCaps);
+ }
+
// Public for use in VcnGatewayConnectionTest
public static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(int... exposedCaps) {
return buildTestConfigWithExposedCaps(newBuilder(), exposedCaps);
}
+ private static VcnGatewayConnectionConfig buildTestConfigWithGatewayOptions(
+ VcnGatewayConnectionConfig.Builder builder, Set<Integer> gatewayOptions) {
+ return buildTestConfigWithExposedCapsAndOptions(builder, gatewayOptions, EXPOSED_CAPS);
+ }
+
+ // Public for use in VcnGatewayConnectionTest
+ public static VcnGatewayConnectionConfig buildTestConfigWithGatewayOptions(
+ Set<Integer> gatewayOptions) {
+ return buildTestConfigWithExposedCapsAndOptions(newBuilder(), gatewayOptions, EXPOSED_CAPS);
+ }
+
@Test
public void testBuilderRequiresNonNullGatewayConnectionName() {
try {
@@ -211,6 +250,15 @@ public class VcnGatewayConnectionConfigTest {
}
@Test
+ public void testBuilderRequiresValidOption() {
+ try {
+ newBuilder().addGatewayOption(-1);
+ fail("Expected exception due to the invalid VCN gateway option");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
public void testBuilderAndGetters() {
final VcnGatewayConnectionConfig config = buildTestConfig();
@@ -225,6 +273,20 @@ public class VcnGatewayConnectionConfigTest {
assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMillis());
assertEquals(MAX_MTU, config.getMaxMtu());
+
+ assertFalse(
+ config.hasGatewayOption(
+ VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY));
+ }
+
+ @Test
+ public void testBuilderAndGettersWithOptions() {
+ final VcnGatewayConnectionConfig config =
+ buildTestConfigWithGatewayOptions(GATEWAY_OPTIONS);
+
+ for (int option : GATEWAY_OPTIONS) {
+ assertTrue(config.hasGatewayOption(option));
+ }
}
@Test
@@ -235,6 +297,14 @@ public class VcnGatewayConnectionConfigTest {
}
@Test
+ public void testPersistableBundleWithOptions() {
+ final VcnGatewayConnectionConfig config =
+ buildTestConfigWithGatewayOptions(GATEWAY_OPTIONS);
+
+ assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle()));
+ }
+
+ @Test
public void testParsePersistableBundleWithoutVcnUnderlyingNetworkTemplates() {
PersistableBundle configBundle = buildTestConfig().toPersistableBundle();
configBundle.putPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY, null);
@@ -318,4 +388,27 @@ public class VcnGatewayConnectionConfigTest {
assertNotEquals(UNDERLYING_NETWORK_TEMPLATES, networkTemplatesNotEqual);
assertNotEquals(config, configNotEqual);
}
+
+ private static VcnGatewayConnectionConfig buildConfigWithGatewayOptionsForEqualityTest(
+ Set<Integer> gatewayOptions) {
+ return buildTestConfigWithGatewayOptions(
+ new VcnGatewayConnectionConfig.Builder(
+ "buildConfigWithGatewayOptionsForEqualityTest", TUNNEL_CONNECTION_PARAMS),
+ gatewayOptions);
+ }
+
+ @Test
+ public void testVcnGatewayOptionsEquality() throws Exception {
+ final VcnGatewayConnectionConfig config =
+ buildConfigWithGatewayOptionsForEqualityTest(GATEWAY_OPTIONS);
+
+ final VcnGatewayConnectionConfig configEqual =
+ buildConfigWithGatewayOptionsForEqualityTest(GATEWAY_OPTIONS);
+
+ final VcnGatewayConnectionConfig configNotEqual =
+ buildConfigWithGatewayOptionsForEqualityTest(Collections.emptySet());
+
+ assertEquals(config, configEqual);
+ assertNotEquals(config, configNotEqual);
+ }
}
diff --git a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
index 19df3c75266c..81814b67f5ee 100644
--- a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
@@ -19,6 +19,7 @@ package android.net.vcn;
import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION;
import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
import static android.net.NetworkCapabilities.REDACT_NONE;
+import static android.net.vcn.VcnGatewayConnectionConfig.MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static org.junit.Assert.assertEquals;
@@ -37,11 +38,14 @@ import java.util.Arrays;
public class VcnTransportInfoTest {
private static final int SUB_ID = 1;
private static final int NETWORK_ID = 5;
+ private static final int MIN_UDP_PORT_4500_NAT_TIMEOUT = 120;
private static final WifiInfo WIFI_INFO =
new WifiInfo.Builder().setNetworkId(NETWORK_ID).build();
- private static final VcnTransportInfo CELL_UNDERLYING_INFO = new VcnTransportInfo(SUB_ID);
- private static final VcnTransportInfo WIFI_UNDERLYING_INFO = new VcnTransportInfo(WIFI_INFO);
+ private static final VcnTransportInfo CELL_UNDERLYING_INFO =
+ new VcnTransportInfo(SUB_ID, MIN_UDP_PORT_4500_NAT_TIMEOUT);
+ private static final VcnTransportInfo WIFI_UNDERLYING_INFO =
+ new VcnTransportInfo(WIFI_INFO, MIN_UDP_PORT_4500_NAT_TIMEOUT);
@Test
public void testGetWifiInfo() {
@@ -58,6 +62,16 @@ public class VcnTransportInfoTest {
}
@Test
+ public void testGetMinUdpPort4500NatTimeoutSeconds() {
+ assertEquals(
+ MIN_UDP_PORT_4500_NAT_TIMEOUT,
+ CELL_UNDERLYING_INFO.getMinUdpPort4500NatTimeoutSeconds());
+ assertEquals(
+ MIN_UDP_PORT_4500_NAT_TIMEOUT,
+ WIFI_UNDERLYING_INFO.getMinUdpPort4500NatTimeoutSeconds());
+ }
+
+ @Test
public void testMakeCopyRedactForNetworkSettings() {
for (VcnTransportInfo info : Arrays.asList(CELL_UNDERLYING_INFO, WIFI_UNDERLYING_INFO)) {
assertEquals(
@@ -67,6 +81,10 @@ public class VcnTransportInfoTest {
assertNull(
((VcnTransportInfo) info.makeCopy(REDACT_FOR_NETWORK_SETTINGS))
.getWifiInfo());
+ assertEquals(
+ MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET,
+ ((VcnTransportInfo) info.makeCopy(REDACT_FOR_NETWORK_SETTINGS))
+ .getMinUdpPort4500NatTimeoutSeconds());
}
}
@@ -77,9 +95,17 @@ public class VcnTransportInfoTest {
((VcnTransportInfo) CELL_UNDERLYING_INFO.makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION))
.getSubId());
assertEquals(
+ MIN_UDP_PORT_4500_NAT_TIMEOUT,
+ ((VcnTransportInfo) CELL_UNDERLYING_INFO.makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION))
+ .getMinUdpPort4500NatTimeoutSeconds());
+ assertEquals(
WifiConfiguration.INVALID_NETWORK_ID,
((VcnTransportInfo) WIFI_UNDERLYING_INFO.makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION))
.getWifiInfo().getNetworkId());
+ assertEquals(
+ MIN_UDP_PORT_4500_NAT_TIMEOUT,
+ ((VcnTransportInfo) WIFI_UNDERLYING_INFO.makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION))
+ .getMinUdpPort4500NatTimeoutSeconds());
}
@Test
@@ -110,8 +136,12 @@ public class VcnTransportInfoTest {
public void testParcelNotRedactedForSysUi() {
VcnTransportInfo cellRedacted = parcelForSysUi(CELL_UNDERLYING_INFO);
assertEquals(SUB_ID, cellRedacted.getSubId());
+ assertEquals(
+ MIN_UDP_PORT_4500_NAT_TIMEOUT, cellRedacted.getMinUdpPort4500NatTimeoutSeconds());
VcnTransportInfo wifiRedacted = parcelForSysUi(WIFI_UNDERLYING_INFO);
assertEquals(NETWORK_ID, wifiRedacted.getWifiInfo().getNetworkId());
+ assertEquals(
+ MIN_UDP_PORT_4500_NAT_TIMEOUT, wifiRedacted.getMinUdpPort4500NatTimeoutSeconds());
}
private VcnTransportInfo parcelForSysUi(VcnTransportInfo vcnTransportInfo) {
diff --git a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
index e4add8098105..9f7d2390938f 100644
--- a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
+++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
@@ -16,9 +16,9 @@
package android.net.vcn.persistablebundleutils;
+import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_AUTOMATIC_KEEPALIVE_ON_OFF;
import static android.net.vcn.persistablebundleutils.IkeSessionParamsUtils.IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION;
import static android.net.vcn.persistablebundleutils.IkeSessionParamsUtils.IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES;
-import static android.net.vcn.persistablebundleutils.IkeSessionParamsUtils.isIkeOptionValid;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
import static android.telephony.TelephonyManager.APPTYPE_USIM;
@@ -160,13 +160,11 @@ public class IkeSessionParamsUtilsTest {
.addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE)
.addIkeOption(IkeSessionParams.IKE_OPTION_FORCE_PORT_4500)
.addIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT)
- .addIkeOption(IkeSessionParams.IKE_OPTION_REKEY_MOBILITY);
- if (isIkeOptionValid(IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION)) {
- builder.addIkeOption(IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION);
- }
- if (isIkeOptionValid(IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES)) {
- builder.addIkeOption(IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES);
- }
+ .addIkeOption(IkeSessionParams.IKE_OPTION_REKEY_MOBILITY)
+ .addIkeOption(IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION)
+ .addIkeOption(IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES)
+ .addIkeOption(IKE_OPTION_AUTOMATIC_KEEPALIVE_ON_OFF);
+
verifyPersistableBundleEncodeDecodeIsLossless(builder.build());
}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index f924b2e9b932..4123f8070e36 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -17,10 +17,14 @@
package com.android.server;
import static android.net.ConnectivityManager.NetworkCallback;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
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 android.net.vcn.VcnManager.VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY;
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;
@@ -65,7 +69,6 @@ import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
-import android.net.TelephonyNetworkSpecifier;
import android.net.Uri;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
@@ -95,6 +98,7 @@ import com.android.server.vcn.Vcn;
import com.android.server.vcn.VcnContext;
import com.android.server.vcn.VcnNetworkProvider;
import com.android.server.vcn.util.PersistableBundleUtils;
+import com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
import org.junit.Before;
import org.junit.Test;
@@ -125,6 +129,15 @@ public class VcnManagementServiceTest {
private static final VcnConfig TEST_VCN_CONFIG;
private static final VcnConfig TEST_VCN_CONFIG_PKG_2;
private static final int TEST_UID = Process.FIRST_APPLICATION_UID;
+ private static final String TEST_IFACE_NAME = "TEST_IFACE";
+ private static final String TEST_IFACE_NAME_2 = "TEST_IFACE2";
+ private static final LinkProperties TEST_LP_1 = new LinkProperties();
+ private static final LinkProperties TEST_LP_2 = new LinkProperties();
+
+ static {
+ TEST_LP_1.setInterfaceName(TEST_IFACE_NAME);
+ TEST_LP_2.setInterfaceName(TEST_IFACE_NAME_2);
+ }
static {
final Context mockConfigContext = mock(Context.class);
@@ -252,6 +265,10 @@ public class VcnManagementServiceTest {
.when(mMockContext)
.enforceCallingOrSelfPermission(
eq(android.Manifest.permission.NETWORK_FACTORY), any());
+
+ doReturn(Collections.singleton(TRANSPORT_WIFI))
+ .when(mMockDeps)
+ .getRestrictedTransports(any(), any(), any());
}
@@ -637,8 +654,7 @@ public class VcnManagementServiceTest {
final BroadcastReceiver receiver = getPackageChangeReceiver();
verify(mMockContext).registerReceiver(any(), argThat(filter -> {
- return filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)
- && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED);
+ return filter.hasAction(Intent.ACTION_PACKAGE_REMOVED);
}), any(), any());
receiver.onReceive(mMockContext, new Intent(Intent.ACTION_PACKAGE_REMOVED));
@@ -1028,70 +1044,232 @@ public class VcnManagementServiceTest {
setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive);
return mVcnMgmtSvc.getUnderlyingNetworkPolicy(
- getNetworkCapabilitiesBuilderForTransport(subId, transport).build(),
- new LinkProperties());
+ getNetworkCapabilitiesBuilderForTransport(subId, transport).build(), TEST_LP_1);
+ }
+
+ private void checkGetRestrictedTransportsFromCarrierConfig(
+ ParcelUuid subGrp,
+ TelephonySubscriptionSnapshot lastSnapshot,
+ Set<Integer> expectedTransports) {
+ Set<Integer> result =
+ new VcnManagementService.Dependencies()
+ .getRestrictedTransportsFromCarrierConfig(subGrp, lastSnapshot);
+ assertEquals(expectedTransports, result);
+ }
+
+ @Test
+ public void testGetRestrictedTransportsFromCarrierConfig() {
+ final Set<Integer> restrictedTransports = new ArraySet<>();
+ restrictedTransports.add(TRANSPORT_CELLULAR);
+ restrictedTransports.add(TRANSPORT_WIFI);
+
+ PersistableBundle carrierConfigBundle = new PersistableBundle();
+ carrierConfigBundle.putIntArray(
+ VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY,
+ restrictedTransports.stream().mapToInt(i -> i).toArray());
+ final PersistableBundleWrapper carrierConfig =
+ new PersistableBundleWrapper(carrierConfigBundle);
+
+ final TelephonySubscriptionSnapshot lastSnapshot =
+ mock(TelephonySubscriptionSnapshot.class);
+ doReturn(carrierConfig).when(lastSnapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2));
+
+ checkGetRestrictedTransportsFromCarrierConfig(
+ TEST_UUID_2, lastSnapshot, restrictedTransports);
+ }
+
+ @Test
+ public void testGetRestrictedTransportsFromCarrierConfig_noRestrictPolicyConfigured() {
+ final Set<Integer> restrictedTransports = Collections.singleton(TRANSPORT_WIFI);
+
+ final PersistableBundleWrapper carrierConfig =
+ new PersistableBundleWrapper(new PersistableBundle());
+ final TelephonySubscriptionSnapshot lastSnapshot =
+ mock(TelephonySubscriptionSnapshot.class);
+ doReturn(carrierConfig).when(lastSnapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2));
+
+ checkGetRestrictedTransportsFromCarrierConfig(
+ TEST_UUID_2, lastSnapshot, restrictedTransports);
}
@Test
- public void testGetUnderlyingNetworkPolicyCellular() throws Exception {
+ public void testGetRestrictedTransportsFromCarrierConfig_noCarrierConfig() {
+ final Set<Integer> restrictedTransports = Collections.singleton(TRANSPORT_WIFI);
+
+ final TelephonySubscriptionSnapshot lastSnapshot =
+ mock(TelephonySubscriptionSnapshot.class);
+
+ checkGetRestrictedTransportsFromCarrierConfig(
+ TEST_UUID_2, lastSnapshot, restrictedTransports);
+ }
+
+ @Test
+ public void testGetRestrictedTransportsFromCarrierConfigAndVcnConfig() {
+ // Configure restricted transport in CarrierConfig
+ final Set<Integer> restrictedTransportInCarrierConfig =
+ Collections.singleton(TRANSPORT_WIFI);
+
+ PersistableBundle carrierConfigBundle = new PersistableBundle();
+ carrierConfigBundle.putIntArray(
+ VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY,
+ restrictedTransportInCarrierConfig.stream().mapToInt(i -> i).toArray());
+ final PersistableBundleWrapper carrierConfig =
+ new PersistableBundleWrapper(carrierConfigBundle);
+
+ final TelephonySubscriptionSnapshot lastSnapshot =
+ mock(TelephonySubscriptionSnapshot.class);
+ doReturn(carrierConfig).when(lastSnapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2));
+
+ // Configure restricted transport in VcnConfig
+ final Context mockContext = mock(Context.class);
+ doReturn(TEST_PACKAGE_NAME).when(mockContext).getOpPackageName();
+ final VcnConfig vcnConfig =
+ VcnConfigTest.buildTestConfig(
+ mockContext, Collections.singleton(TRANSPORT_CELLULAR));
+
+ // Verifications
+ final Set<Integer> expectedTransports = new ArraySet<>();
+ expectedTransports.add(TRANSPORT_CELLULAR);
+ expectedTransports.add(TRANSPORT_WIFI);
+
+ Set<Integer> result =
+ new VcnManagementService.Dependencies()
+ .getRestrictedTransports(TEST_UUID_2, lastSnapshot, vcnConfig);
+ assertEquals(expectedTransports, result);
+ }
+
+ private void checkGetUnderlyingNetworkPolicy(
+ int transportType,
+ boolean isTransportRestricted,
+ boolean isActive,
+ boolean expectVcnManaged,
+ boolean expectRestricted)
+ throws Exception {
+
+ final Set<Integer> restrictedTransports = new ArraySet();
+ if (isTransportRestricted) {
+ restrictedTransports.add(transportType);
+ }
+ doReturn(restrictedTransports).when(mMockDeps).getRestrictedTransports(any(), any(), any());
+
final VcnUnderlyingNetworkPolicy policy =
startVcnAndGetPolicyForTransport(
- TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */, TRANSPORT_CELLULAR);
+ TEST_SUBSCRIPTION_ID, TEST_UUID_2, isActive, transportType);
assertFalse(policy.isTeardownRequested());
verifyMergedNetworkCapabilities(
policy.getMergedNetworkCapabilities(),
+ transportType,
+ expectVcnManaged,
+ expectRestricted);
+ }
+
+ @Test
+ public void testGetUnderlyingNetworkPolicy_unrestrictCell() throws Exception {
+ checkGetUnderlyingNetworkPolicy(
TRANSPORT_CELLULAR,
- true /* isVcnManaged */,
- false /* isRestricted */);
+ false /* isTransportRestricted */,
+ true /* isActive */,
+ true /* expectVcnManaged */,
+ false /* expectRestricted */);
}
@Test
- public void testGetUnderlyingNetworkPolicyCellular_safeMode() throws Exception {
- final VcnUnderlyingNetworkPolicy policy =
- startVcnAndGetPolicyForTransport(
- TEST_SUBSCRIPTION_ID,
- TEST_UUID_2,
- false /* isActive */,
- TRANSPORT_CELLULAR);
+ public void testGetUnderlyingNetworkPolicy_unrestrictCellSafeMode() throws Exception {
+ checkGetUnderlyingNetworkPolicy(
+ TRANSPORT_CELLULAR,
+ false /* isTransportRestricted */,
+ false /* isActive */,
+ false /* expectVcnManaged */,
+ false /* expectRestricted */);
+ }
- assertFalse(policy.isTeardownRequested());
- verifyMergedNetworkCapabilities(
- policy.getMergedNetworkCapabilities(),
- NetworkCapabilities.TRANSPORT_CELLULAR,
- false /* isVcnManaged */,
- false /* isRestricted */);
+ @Test
+ public void testGetUnderlyingNetworkPolicy_restrictCell() throws Exception {
+ checkGetUnderlyingNetworkPolicy(
+ TRANSPORT_CELLULAR,
+ true /* isTransportRestricted */,
+ true /* isActive */,
+ true /* expectVcnManaged */,
+ true /* expectRestricted */);
}
@Test
- public void testGetUnderlyingNetworkPolicyWifi() throws Exception {
- final VcnUnderlyingNetworkPolicy policy =
- startVcnAndGetPolicyForTransport(
- TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */, TRANSPORT_WIFI);
+ public void testGetUnderlyingNetworkPolicy_restrictCellSafeMode() throws Exception {
+ checkGetUnderlyingNetworkPolicy(
+ TRANSPORT_CELLULAR,
+ true /* isTransportRestricted */,
+ false /* isActive */,
+ false /* expectVcnManaged */,
+ false /* expectRestricted */);
+ }
- assertFalse(policy.isTeardownRequested());
- verifyMergedNetworkCapabilities(
- policy.getMergedNetworkCapabilities(),
- NetworkCapabilities.TRANSPORT_WIFI,
- true /* isVcnManaged */,
- true /* isRestricted */);
+ @Test
+ public void testGetUnderlyingNetworkPolicy_unrestrictWifi() throws Exception {
+ checkGetUnderlyingNetworkPolicy(
+ TRANSPORT_WIFI,
+ false /* isTransportRestricted */,
+ true /* isActive */,
+ true /* expectVcnManaged */,
+ false /* expectRestricted */);
+ }
+
+ @Test
+ public void testGetUnderlyingNetworkPolicy_unrestrictWifiSafeMode() throws Exception {
+ checkGetUnderlyingNetworkPolicy(
+ TRANSPORT_WIFI,
+ false /* isTransportRestricted */,
+ false /* isActive */,
+ false /* expectVcnManaged */,
+ false /* expectRestricted */);
+ }
+
+ @Test
+ public void testGetUnderlyingNetworkPolicy_restrictWifi() throws Exception {
+ checkGetUnderlyingNetworkPolicy(
+ TRANSPORT_WIFI,
+ true /* isTransportRestricted */,
+ true /* isActive */,
+ true /* expectVcnManaged */,
+ true /* expectRestricted */);
+ }
+
+ @Test
+ public void testGetUnderlyingNetworkPolicy_restrictWifiSafeMode() throws Exception {
+ checkGetUnderlyingNetworkPolicy(
+ TRANSPORT_WIFI,
+ true /* isTransportRestricted */,
+ false /* isActive */,
+ false /* expectVcnManaged */,
+ true /* expectRestricted */);
}
@Test
- public void testGetUnderlyingNetworkPolicyVcnWifi_safeMode() throws Exception {
+ public void testGetUnderlyingNetworkPolicyCell_restrictWifi() throws Exception {
+ doReturn(Collections.singleton(TRANSPORT_WIFI))
+ .when(mMockDeps)
+ .getRestrictedTransports(any(), any(), any());
+
+ setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isVcnActive */);
+
+ // Get the policy for a cellular network and expect it won't be affected by the wifi
+ // restriction policy
final VcnUnderlyingNetworkPolicy policy =
- startVcnAndGetPolicyForTransport(
- TEST_SUBSCRIPTION_ID, TEST_UUID_2, false /* isActive */, TRANSPORT_WIFI);
+ mVcnMgmtSvc.getUnderlyingNetworkPolicy(
+ getNetworkCapabilitiesBuilderForTransport(
+ TEST_SUBSCRIPTION_ID, TRANSPORT_CELLULAR)
+ .build(),
+ new LinkProperties());
assertFalse(policy.isTeardownRequested());
verifyMergedNetworkCapabilities(
policy.getMergedNetworkCapabilities(),
- NetworkCapabilities.TRANSPORT_WIFI,
- false /* isVcnManaged */,
- true /* isRestricted */);
+ TRANSPORT_CELLULAR,
+ true /* expectVcnManaged */,
+ false /* expectRestricted */);
}
- private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) {
+ private void setupTrackedNetwork(NetworkCapabilities caps, LinkProperties lp) {
mVcnMgmtSvc.systemReady();
final ArgumentCaptor<NetworkCallback> captor =
@@ -1100,7 +1278,10 @@ public class VcnManagementServiceTest {
.registerNetworkCallback(
eq(new NetworkRequest.Builder().clearCapabilities().build()),
captor.capture());
- captor.getValue().onCapabilitiesChanged(mock(Network.class, CALLS_REAL_METHODS), caps);
+
+ Network mockNetwork = mock(Network.class, CALLS_REAL_METHODS);
+ captor.getValue().onCapabilitiesChanged(mockNetwork, caps);
+ captor.getValue().onLinkPropertiesChanged(mockNetwork, lp);
}
@Test
@@ -1110,7 +1291,7 @@ public class VcnManagementServiceTest {
getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
.removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
.build();
- setupTrackedCarrierWifiNetwork(existingNetworkCaps);
+ setupTrackedNetwork(existingNetworkCaps, TEST_LP_1);
// Trigger test without VCN instance alive; expect restart due to change of NOT_RESTRICTED
// immutable capability
@@ -1119,7 +1300,7 @@ public class VcnManagementServiceTest {
getNetworkCapabilitiesBuilderForTransport(
TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
.build(),
- new LinkProperties());
+ TEST_LP_1);
assertTrue(policy.isTeardownRequested());
}
@@ -1129,7 +1310,7 @@ public class VcnManagementServiceTest {
final NetworkCapabilities existingNetworkCaps =
getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
.build();
- setupTrackedCarrierWifiNetwork(existingNetworkCaps);
+ setupTrackedNetwork(existingNetworkCaps, TEST_LP_1);
final VcnUnderlyingNetworkPolicy policy =
startVcnAndGetPolicyForTransport(
@@ -1139,6 +1320,27 @@ public class VcnManagementServiceTest {
}
@Test
+ public void testGetUnderlyingNetworkPolicyForRestrictedImsWhenUnrestrictingCell()
+ throws Exception {
+ final NetworkCapabilities existingNetworkCaps =
+ getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ .removeCapability(NET_CAPABILITY_IMS)
+ .build();
+ setupTrackedNetwork(existingNetworkCaps, TEST_LP_1);
+
+ final VcnUnderlyingNetworkPolicy policy =
+ mVcnMgmtSvc.getUnderlyingNetworkPolicy(
+ getNetworkCapabilitiesBuilderForTransport(
+ TEST_SUBSCRIPTION_ID, TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_IMS)
+ .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ .build(),
+ new LinkProperties());
+ assertFalse(policy.isTeardownRequested());
+ }
+
+ @Test
public void testGetUnderlyingNetworkPolicyNonVcnNetwork() throws Exception {
setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_1, true /* isActive */);
@@ -1146,7 +1348,7 @@ public class VcnManagementServiceTest {
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
- .setNetworkSpecifier(new TelephonyNetworkSpecifier(TEST_SUBSCRIPTION_ID_2))
+ .setSubscriptionIds(Collections.singleton(TEST_SUBSCRIPTION_ID_2))
.build();
VcnUnderlyingNetworkPolicy policy =
@@ -1156,6 +1358,38 @@ public class VcnManagementServiceTest {
assertEquals(nc, policy.getMergedNetworkCapabilities());
}
+ /**
+ * Checks that networks with similar capabilities do not clobber each other.
+ *
+ * <p>In previous iterations, the VcnMgmtSvc used capability-matching to check if a network
+ * undergoing policy checks were the same as an existing networks. However, this meant that if
+ * there were newly added capabilities that the VCN did not check, two networks differing only
+ * by that capability would restart each other constantly.
+ */
+ @Test
+ public void testGetUnderlyingNetworkPolicySimilarNetworks() throws Exception {
+ NetworkCapabilities nc1 =
+ new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .setSubscriptionIds(Collections.singleton(TEST_SUBSCRIPTION_ID_2))
+ .build();
+
+ NetworkCapabilities nc2 =
+ new NetworkCapabilities.Builder(nc1)
+ .addCapability(NET_CAPABILITY_ENTERPRISE)
+ .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ .build();
+
+ setupTrackedNetwork(nc1, TEST_LP_1);
+
+ VcnUnderlyingNetworkPolicy policy = mVcnMgmtSvc.getUnderlyingNetworkPolicy(nc2, TEST_LP_2);
+
+ assertFalse(policy.isTeardownRequested());
+ assertEquals(nc2, policy.getMergedNetworkCapabilities());
+ }
+
@Test(expected = SecurityException.class)
public void testGetUnderlyingNetworkPolicyInvalidPermission() {
doReturn(PackageManager.PERMISSION_DENIED)
@@ -1192,6 +1426,23 @@ public class VcnManagementServiceTest {
}
@Test
+ public void testVcnConfigChangeUpdatesPolicyListener() throws Exception {
+ setupActiveSubscription(TEST_UUID_2);
+
+ mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
+ mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
+
+ final Context mockContext = mock(Context.class);
+ doReturn(TEST_PACKAGE_NAME).when(mockContext).getOpPackageName();
+ final VcnConfig vcnConfig =
+ VcnConfigTest.buildTestConfig(
+ mockContext, Collections.singleton(TRANSPORT_CELLULAR));
+ mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, vcnConfig, TEST_PACKAGE_NAME);
+
+ verify(mMockPolicyListener).onPolicyChanged();
+ }
+
+ @Test
public void testRemoveVcnUpdatesPolicyListener() throws Exception {
setupActiveSubscription(TEST_UUID_2);
@@ -1218,6 +1469,30 @@ public class VcnManagementServiceTest {
verify(mMockPolicyListener).onPolicyChanged();
}
+ @Test
+ public void testVcnCarrierConfigChangeUpdatesPolicyListener() throws Exception {
+ setupActiveSubscription(TEST_UUID_2);
+
+ mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
+ mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
+
+ final TelephonySubscriptionSnapshot snapshot =
+ buildSubscriptionSnapshot(
+ TEST_SUBSCRIPTION_ID,
+ TEST_UUID_2,
+ Collections.singleton(TEST_UUID_2),
+ Collections.emptyMap(),
+ true /* hasCarrierPrivileges */);
+
+ final PersistableBundleWrapper mockCarrierConfig = mock(PersistableBundleWrapper.class);
+ doReturn(mockCarrierConfig).when(snapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2));
+
+ final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback();
+ cb.onNewSnapshot(snapshot);
+
+ verify(mMockPolicyListener).onPolicyChanged();
+ }
+
private void triggerVcnSafeMode(
@NonNull ParcelUuid subGroup,
@NonNull TelephonySubscriptionSnapshot snapshot,
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
index 09080be9ee41..965b073ff0db 100644
--- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -16,6 +16,9 @@
package com.android.server.vcn;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.vcn.VcnManager.VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY;
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
import static android.telephony.CarrierConfigManager.EXTRA_SLOT_INDEX;
import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX;
@@ -39,6 +42,7 @@ 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.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -494,6 +498,37 @@ public class TelephonySubscriptionTrackerTest {
}
@Test
+ public void testCarrierConfigUpdatedAfterValidTriggersCallbacks() throws Exception {
+ mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+ mTestLooper.dispatchAll();
+ verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
+ reset(mCallback);
+
+ final PersistableBundle updatedConfig = new PersistableBundle();
+ updatedConfig.putIntArray(
+ VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY,
+ new int[] {TRANSPORT_WIFI, TRANSPORT_CELLULAR});
+ doReturn(updatedConfig)
+ .when(mCarrierConfigManager)
+ .getConfigForSubId(eq(TEST_SUBSCRIPTION_ID_1));
+
+ Map<Integer, PersistableBundleWrapper> subIdToCarrierConfigMap = new HashMap<>();
+ subIdToCarrierConfigMap.put(
+ TEST_SUBSCRIPTION_ID_1, new PersistableBundleWrapper(updatedConfig));
+ mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+ mTestLooper.dispatchAll();
+
+ verify(mCallback)
+ .onNewSnapshot(
+ eq(
+ buildExpectedSnapshot(
+ 0,
+ TEST_SUBID_TO_INFO_MAP,
+ subIdToCarrierConfigMap,
+ TEST_PRIVILEGED_PACKAGES)));
+ }
+
+ @Test
public void testSlotClearedAfterValidTriggersCallbacks() 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 15d4f1097108..89271e1218d8 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -25,6 +25,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED;
import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_TEMPORARY_FAILURE;
+import static android.net.vcn.VcnGatewayConnectionConfigTest.MIN_UDP_PORT_4500_NAT_TIMEOUT;
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR;
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_INTERNAL_ERROR;
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR;
@@ -50,23 +51,30 @@ import static org.mockito.Mockito.when;
import static java.util.Collections.singletonList;
+import android.net.ConnectivityDiagnosticsManager.DataStallReport;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.ipsec.ike.ChildSaProposal;
import android.net.ipsec.ike.IkeSessionConnectionInfo;
+import android.net.ipsec.ike.TunnelModeChildSessionParams;
import android.net.ipsec.ike.exceptions.IkeException;
import android.net.ipsec.ike.exceptions.IkeInternalException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.net.vcn.VcnGatewayConnectionConfig;
import android.net.vcn.VcnGatewayConnectionConfigTest;
import android.net.vcn.VcnManager.VcnErrorCode;
+import android.net.vcn.VcnTransportInfo;
+import android.os.PersistableBundle;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.vcn.VcnGatewayConnection.VcnChildSessionCallback;
+import com.android.server.vcn.routeselection.UnderlyingNetworkRecord;
import com.android.server.vcn.util.MtuUtils;
import org.junit.Before;
@@ -86,8 +94,11 @@ import java.util.function.Consumer;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnectionTestBase {
+ private static final int PARALLEL_SA_COUNT = 4;
+
private VcnIkeSession mIkeSession;
private VcnNetworkAgent mNetworkAgent;
+ private Network mVcnNetwork;
@Before
public void setUp() throws Exception {
@@ -98,6 +109,9 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
.when(mDeps)
.newNetworkAgent(any(), any(), any(), any(), any(), any(), any(), any(), any());
+ mVcnNetwork = mock(Network.class);
+ doReturn(mVcnNetwork).when(mNetworkAgent).getNetwork();
+
mGatewayConnection.setUnderlyingNetwork(TEST_UNDERLYING_NETWORK_RECORD_1);
mIkeSession = mGatewayConnection.buildIkeSession(TEST_UNDERLYING_NETWORK_RECORD_1.network);
@@ -166,19 +180,82 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
}
+ private void verifyDataStallTriggersMigration(
+ UnderlyingNetworkRecord networkRecord,
+ Network networkWithDataStall,
+ boolean expectMobilityUpdate)
+ throws Exception {
+ mGatewayConnection.setUnderlyingNetwork(networkRecord);
+ triggerChildOpened();
+ mTestLooper.dispatchAll();
+
+ final DataStallReport report =
+ new DataStallReport(
+ networkWithDataStall,
+ 1234 /* reportTimestamp */,
+ 1 /* detectionMethod */,
+ new LinkProperties(),
+ new NetworkCapabilities(),
+ new PersistableBundle());
+
+ mGatewayConnection.getConnectivityDiagnosticsCallback().onDataStallSuspected(report);
+ mTestLooper.dispatchAll();
+
+ assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
+
+ if (expectMobilityUpdate) {
+ verify(mIkeSession).setNetwork(networkRecord.network);
+ } else {
+ verify(mIkeSession, never()).setNetwork(any(Network.class));
+ }
+ }
+
+ @Test
+ public void testDataStallTriggersMigration() throws Exception {
+ verifyDataStallTriggersMigration(
+ TEST_UNDERLYING_NETWORK_RECORD_1, mVcnNetwork, true /* expectMobilityUpdate */);
+ }
+
+ @Test
+ public void testDataStallWontTriggerMigrationWhenOnOtherNetwork() throws Exception {
+ verifyDataStallTriggersMigration(
+ TEST_UNDERLYING_NETWORK_RECORD_1,
+ mock(Network.class),
+ false /* expectMobilityUpdate */);
+ }
+
+ @Test
+ public void testDataStallWontTriggerMigrationWhenUnderlyingNetworkLost() throws Exception {
+ verifyDataStallTriggersMigration(
+ null /* networkRecord */, mock(Network.class), false /* expectMobilityUpdate */);
+ }
+
private void verifyVcnTransformsApplied(
VcnGatewayConnection vcnGatewayConnection, boolean expectForwardTransform)
throws Exception {
+ verifyVcnTransformsApplied(
+ vcnGatewayConnection,
+ expectForwardTransform,
+ Collections.singletonList(getChildSessionCallback()));
+ }
+
+ private void verifyVcnTransformsApplied(
+ VcnGatewayConnection vcnGatewayConnection,
+ boolean expectForwardTransform,
+ List<VcnChildSessionCallback> callbacks)
+ throws Exception {
for (int direction : new int[] {DIRECTION_IN, DIRECTION_OUT}) {
- getChildSessionCallback().onIpSecTransformCreated(makeDummyIpSecTransform(), direction);
+ for (VcnChildSessionCallback cb : callbacks) {
+ cb.onIpSecTransformCreated(makeDummyIpSecTransform(), direction);
+ }
mTestLooper.dispatchAll();
- verify(mIpSecSvc)
+ verify(mIpSecSvc, times(callbacks.size()))
.applyTunnelModeTransform(
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(direction), anyInt(), any());
}
- verify(mIpSecSvc, expectForwardTransform ? times(1) : never())
+ verify(mIpSecSvc, expectForwardTransform ? times(callbacks.size()) : never())
.applyTunnelModeTransform(
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(DIRECTION_FWD), anyInt(), any());
@@ -350,6 +427,12 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
assertTrue(nc.hasCapability(cap));
}
+ assertTrue(nc.getTransportInfo() instanceof VcnTransportInfo);
+ final VcnTransportInfo vcnTransportInfo = (VcnTransportInfo) nc.getTransportInfo();
+ assertEquals(
+ MIN_UDP_PORT_4500_NAT_TIMEOUT,
+ vcnTransportInfo.getMinUdpPort4500NatTimeoutSeconds());
+
// Now that Vcn Network is up, notify it as validated and verify the SafeMode alarm is
// canceled
triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
@@ -358,6 +441,89 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
verifySafeModeStateAndCallbackFired(1 /* invocationCount */, false /* isInSafeMode */);
}
+ private List<VcnChildSessionCallback> openChildAndVerifyParallelSasRequested()
+ throws Exception {
+ doReturn(PARALLEL_SA_COUNT)
+ .when(mDeps)
+ .getParallelTunnelCount(eq(TEST_SUBSCRIPTION_SNAPSHOT), eq(TEST_SUB_GRP));
+
+ // Verify scheduled but not canceled when entering ConnectedState
+ verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */);
+ triggerChildOpened();
+ mTestLooper.dispatchAll();
+
+ // Verify new child sessions requested
+ final ArgumentCaptor<VcnChildSessionCallback> captor =
+ ArgumentCaptor.forClass(VcnChildSessionCallback.class);
+ verify(mIkeSession, times(PARALLEL_SA_COUNT - 1))
+ .openChildSession(any(TunnelModeChildSessionParams.class), captor.capture());
+
+ return captor.getAllValues();
+ }
+
+ private List<VcnChildSessionCallback> verifyChildOpenedRequestsAndAppliesParallelSas()
+ throws Exception {
+ List<VcnChildSessionCallback> callbacks = openChildAndVerifyParallelSasRequested();
+
+ verifyVcnTransformsApplied(mGatewayConnection, false, callbacks);
+
+ // Mock IKE calling of onOpened()
+ for (VcnChildSessionCallback cb : callbacks) {
+ cb.onOpened(mock(VcnChildSessionConfiguration.class));
+ }
+ mTestLooper.dispatchAll();
+
+ assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
+ return callbacks;
+ }
+
+ @Test
+ public void testChildOpenedWithParallelSas() throws Exception {
+ verifyChildOpenedRequestsAndAppliesParallelSas();
+ }
+
+ @Test
+ public void testOpportunisticSa_ignoresPreOpenFailures() throws Exception {
+ List<VcnChildSessionCallback> callbacks = openChildAndVerifyParallelSasRequested();
+
+ for (VcnChildSessionCallback cb : callbacks) {
+ cb.onClosed();
+ cb.onClosedExceptionally(mock(IkeException.class));
+ }
+ mTestLooper.dispatchAll();
+
+ assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
+ assertEquals(mIkeConnectionInfo, mGatewayConnection.getIkeConnectionInfo());
+ }
+
+ private void verifyPostOpenFailuresCloseSession(boolean shouldCloseWithException)
+ throws Exception {
+ List<VcnChildSessionCallback> callbacks = verifyChildOpenedRequestsAndAppliesParallelSas();
+
+ for (VcnChildSessionCallback cb : callbacks) {
+ if (shouldCloseWithException) {
+ cb.onClosed();
+ } else {
+ cb.onClosedExceptionally(mock(IkeException.class));
+ }
+ }
+ mTestLooper.dispatchAll();
+
+ assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
+ verify(mIkeSession).close();
+ }
+
+ @Test
+ public void testOpportunisticSa_handlesPostOpenFailures_onClosed() throws Exception {
+ verifyPostOpenFailuresCloseSession(false /* shouldCloseWithException */);
+ }
+
+ @Test
+ public void testOpportunisticSa_handlesPostOpenFailures_onClosedExceptionally()
+ throws Exception {
+ verifyPostOpenFailuresCloseSession(true /* shouldCloseWithException */);
+ }
+
@Test
public void testInternalAndDnsAddressesChanged() throws Exception {
final List<LinkAddress> startingInternalAddrs =
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
index 6a9a1e22cab1..692c8a8f0898 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
@@ -24,6 +24,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
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 android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY;
import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR;
import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration;
@@ -34,20 +35,25 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.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.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback;
import android.net.IpSecManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
+import android.net.vcn.VcnGatewayConnectionConfig;
import android.net.vcn.VcnGatewayConnectionConfigTest;
import android.net.vcn.VcnTransportInfo;
import android.net.wifi.WifiInfo;
@@ -64,6 +70,7 @@ import com.android.server.vcn.routeselection.UnderlyingNetworkRecord;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import java.net.InetAddress;
import java.util.Arrays;
@@ -71,7 +78,9 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.Executor;
/** Tests for TelephonySubscriptionTracker */
@RunWith(AndroidJUnit4.class)
@@ -134,9 +143,9 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase {
capBuilder.setLinkDownstreamBandwidthKbps(TEST_DOWNSTREAM_BANDWIDTH);
capBuilder.setAdministratorUids(new int[] {TEST_UID});
final Network underlyingNetwork = mock(Network.class, CALLS_REAL_METHODS);
- UnderlyingNetworkRecord record = new UnderlyingNetworkRecord(
- underlyingNetwork,
- capBuilder.build(), new LinkProperties(), false);
+ UnderlyingNetworkRecord record =
+ getTestNetworkRecord(
+ underlyingNetwork, capBuilder.build(), new LinkProperties(), false);
final NetworkCapabilities vcnCaps =
VcnGatewayConnection.buildNetworkCapabilities(
VcnGatewayConnectionConfigTest.buildTestConfig(),
@@ -202,7 +211,7 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase {
doReturn(TEST_DNS_ADDRESSES).when(childSessionConfig).getInternalDnsServers();
UnderlyingNetworkRecord record =
- new UnderlyingNetworkRecord(
+ getTestNetworkRecord(
mock(Network.class, CALLS_REAL_METHODS),
new NetworkCapabilities.Builder().build(),
underlyingLp,
@@ -287,5 +296,60 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase {
verify(vcnNetworkAgent).unregister();
verifyWakeLockReleased();
+
+ verify(mConnDiagMgr)
+ .unregisterConnectivityDiagnosticsCallback(
+ mGatewayConnection.getConnectivityDiagnosticsCallback());
+ }
+
+ private VcnGatewayConnection buildConnectionWithDataStallHandling(
+ boolean datatStallHandlingEnabled) throws Exception {
+ Set<Integer> options =
+ datatStallHandlingEnabled
+ ? Collections.singleton(
+ VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY)
+ : Collections.emptySet();
+ final VcnGatewayConnectionConfig gatewayConfig =
+ VcnGatewayConnectionConfigTest.buildTestConfigWithGatewayOptions(options);
+ final VcnGatewayConnection gatewayConnection =
+ new VcnGatewayConnection(
+ mVcnContext,
+ TEST_SUB_GRP,
+ TEST_SUBSCRIPTION_SNAPSHOT,
+ gatewayConfig,
+ mGatewayStatusCallback,
+ true /* isMobileDataEnabled */,
+ mDeps);
+ return gatewayConnection;
+ }
+
+ @Test
+ public void testDataStallHandlingEnabled() throws Exception {
+ final VcnGatewayConnection gatewayConnection =
+ buildConnectionWithDataStallHandling(true /* datatStallHandlingEnabled */);
+
+ final ArgumentCaptor<NetworkRequest> networkRequestCaptor =
+ ArgumentCaptor.forClass(NetworkRequest.class);
+ verify(mConnDiagMgr)
+ .registerConnectivityDiagnosticsCallback(
+ networkRequestCaptor.capture(),
+ any(Executor.class),
+ eq(gatewayConnection.getConnectivityDiagnosticsCallback()));
+
+ final NetworkRequest nr = networkRequestCaptor.getValue();
+ final NetworkRequest expected =
+ new NetworkRequest.Builder().addTransportType(TRANSPORT_CELLULAR).build();
+ assertEquals(expected, nr);
+ }
+
+ @Test
+ public void testDataStallHandlingDisabled() throws Exception {
+ buildConnectionWithDataStallHandling(false /* datatStallHandlingEnabled */);
+
+ verify(mConnDiagMgr, never())
+ .registerConnectivityDiagnosticsCallback(
+ any(NetworkRequest.class),
+ any(Executor.class),
+ any(ConnectivityDiagnosticsCallback.class));
}
}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index 785bff167ad2..5efbf598f941 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -16,6 +16,8 @@
package com.android.server.vcn;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
import static com.android.server.vcn.VcnTestUtils.setupIpSecManager;
@@ -35,6 +37,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.annotation.NonNull;
import android.content.Context;
+import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager;
import android.net.InetAddresses;
import android.net.IpSecConfig;
@@ -45,6 +48,7 @@ import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
+import android.net.TelephonyNetworkSpecifier;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.IkeSessionConfiguration;
@@ -108,11 +112,28 @@ public class VcnGatewayConnectionTestBase {
protected static final long ELAPSED_REAL_TIME = 123456789L;
protected static final String TEST_IPSEC_TUNNEL_IFACE = "IPSEC_IFACE";
+ protected static UnderlyingNetworkRecord getTestNetworkRecord(
+ Network network,
+ NetworkCapabilities networkCapabilities,
+ LinkProperties linkProperties,
+ boolean isBlocked) {
+ return new UnderlyingNetworkRecord(
+ network,
+ networkCapabilities,
+ linkProperties,
+ isBlocked,
+ false /* isSelected */,
+ 0 /* priorityClass */);
+ }
+
protected static final String TEST_TCP_BUFFER_SIZES_1 = "1,2,3,4";
protected static final UnderlyingNetworkRecord TEST_UNDERLYING_NETWORK_RECORD_1 =
- new UnderlyingNetworkRecord(
+ getTestNetworkRecord(
mock(Network.class, CALLS_REAL_METHODS),
- new NetworkCapabilities(),
+ new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_CELLULAR)
+ .setNetworkSpecifier(new TelephonyNetworkSpecifier(TEST_SUB_ID))
+ .build(),
new LinkProperties(),
false /* blocked */);
@@ -123,7 +144,7 @@ public class VcnGatewayConnectionTestBase {
protected static final String TEST_TCP_BUFFER_SIZES_2 = "2,3,4,5";
protected static final UnderlyingNetworkRecord TEST_UNDERLYING_NETWORK_RECORD_2 =
- new UnderlyingNetworkRecord(
+ getTestNetworkRecord(
mock(Network.class, CALLS_REAL_METHODS),
new NetworkCapabilities(),
new LinkProperties(),
@@ -157,6 +178,7 @@ public class VcnGatewayConnectionTestBase {
@NonNull protected final IpSecService mIpSecSvc;
@NonNull protected final ConnectivityManager mConnMgr;
+ @NonNull protected final ConnectivityDiagnosticsManager mConnDiagMgr;
@NonNull protected final IkeSessionConnectionInfo mIkeConnectionInfo;
@NonNull protected final IkeSessionConfiguration mIkeSessionConfiguration;
@@ -186,6 +208,13 @@ public class VcnGatewayConnectionTestBase {
VcnTestUtils.setupSystemService(
mContext, mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
+ mConnDiagMgr = mock(ConnectivityDiagnosticsManager.class);
+ VcnTestUtils.setupSystemService(
+ mContext,
+ mConnDiagMgr,
+ Context.CONNECTIVITY_DIAGNOSTICS_SERVICE,
+ ConnectivityDiagnosticsManager.class);
+
mIkeConnectionInfo =
new IkeSessionConnectionInfo(TEST_ADDR, TEST_ADDR_2, mock(Network.class));
mIkeSessionConfiguration = new IkeSessionConfiguration.Builder(mIkeConnectionInfo).build();
@@ -200,6 +229,9 @@ public class VcnGatewayConnectionTestBase {
doReturn(mWakeLock)
.when(mDeps)
.newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any());
+ doReturn(1)
+ .when(mDeps)
+ .getParallelTunnelCount(eq(TEST_SUBSCRIPTION_SNAPSHOT), eq(TEST_SUB_GRP));
setUpWakeupMessage(mTeardownTimeoutAlarm, VcnGatewayConnection.TEARDOWN_TIMEOUT_ALARM);
setUpWakeupMessage(mDisconnectRequestAlarm, VcnGatewayConnection.DISCONNECT_REQUEST_ALARM);
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
index b0d68952c39d..226604108522 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
@@ -16,6 +16,7 @@
package com.android.server.vcn.routeselection;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
import static android.net.vcn.VcnUnderlyingNetworkTemplateTestBase.TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS;
@@ -24,8 +25,8 @@ import static android.net.vcn.VcnUnderlyingNetworkTemplateTestBase.TEST_MIN_EXIT
import static android.net.vcn.VcnUnderlyingNetworkTemplateTestBase.TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS;
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.PRIORITY_FALLBACK;
+import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.PRIORITY_INVALID;
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;
@@ -48,6 +49,7 @@ import android.net.TelephonyNetworkSpecifier;
import android.net.vcn.VcnCellUnderlyingNetworkTemplate;
import android.net.vcn.VcnGatewayConnectionConfig;
import android.net.vcn.VcnManager;
+import android.net.vcn.VcnUnderlyingNetworkTemplate;
import android.net.vcn.VcnWifiUnderlyingNetworkTemplate;
import android.os.ParcelUuid;
import android.os.PersistableBundle;
@@ -64,6 +66,8 @@ import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Collections;
+import java.util.List;
import java.util.Set;
import java.util.UUID;
@@ -91,6 +95,7 @@ public class NetworkPriorityClassifierTest {
private static final NetworkCapabilities WIFI_NETWORK_CAPABILITIES =
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setSignalStrength(WIFI_RSSI)
.setSsid(SSID)
.setLinkUpstreamBandwidthKbps(LINK_UPSTREAM_BANDWIDTH_KBPS)
@@ -102,6 +107,7 @@ public class NetworkPriorityClassifierTest {
private static final NetworkCapabilities CELL_NETWORK_CAPABILITIES =
new NetworkCapabilities.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.setSubscriptionIds(Set.of(SUB_ID))
.setNetworkSpecifier(TEL_NETWORK_SPECIFIER)
@@ -135,25 +141,35 @@ public class NetworkPriorityClassifierTest {
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);
+
+ mWifiNetworkRecord =
+ getTestNetworkRecord(
+ WIFI_NETWORK_CAPABILITIES,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES);
+ mCellNetworkRecord =
+ getTestNetworkRecord(
+ CELL_NETWORK_CAPABILITIES,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES);
+ }
+
+ private UnderlyingNetworkRecord getTestNetworkRecord(
+ NetworkCapabilities nc, List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates) {
+ return new UnderlyingNetworkRecord(
+ mNetwork,
+ nc,
+ LINK_PROPERTIES,
+ false /* isBlocked */,
+ mVcnContext,
+ underlyingNetworkTemplates,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ null /* currentlySelected */,
+ null /* carrierConfig */);
}
@Test
@@ -490,37 +506,74 @@ public class NetworkPriorityClassifierTest {
mSubscriptionSnapshot));
}
- private void verifyCalculatePriorityClass(
- UnderlyingNetworkRecord networkRecord, int expectedIndex) {
- final int priorityIndex =
- calculatePriorityClass(
+ private void verifyMatchCellWithRequiredCapabilities(
+ VcnCellUnderlyingNetworkTemplate template, boolean expectMatch) {
+ assertEquals(
+ expectMatch,
+ checkMatchesPriorityRule(
mVcnContext,
- networkRecord,
- VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ template,
+ mCellNetworkRecord,
SUB_GROUP,
mSubscriptionSnapshot,
null /* currentlySelected */,
- null /* carrierConfig */);
+ null /* carrierConfig */));
+ }
- assertEquals(expectedIndex, priorityIndex);
+ @Test
+ public void testMatchCell() {
+ final VcnCellUnderlyingNetworkTemplate template =
+ getCellNetworkPriorityBuilder().setInternet(MATCH_REQUIRED).build();
+ verifyMatchCellWithRequiredCapabilities(template, true /* expectMatch */);
}
@Test
- public void testCalculatePriorityClass() throws Exception {
- verifyCalculatePriorityClass(mCellNetworkRecord, 2);
+ public void testMatchCellFail_RequiredCapabilitiesMissing() {
+ final VcnCellUnderlyingNetworkTemplate template =
+ getCellNetworkPriorityBuilder().setCbs(MATCH_REQUIRED).build();
+ verifyMatchCellWithRequiredCapabilities(template, false /* expectMatch */);
}
@Test
- public void testCalculatePriorityClassFailToMatchAny() throws Exception {
- final NetworkCapabilities nc =
+ public void testMatchCellFail_ForbiddenCapabilitiesFound() {
+ final VcnCellUnderlyingNetworkTemplate template =
+ getCellNetworkPriorityBuilder().setDun(MATCH_FORBIDDEN).build();
+ verifyMatchCellWithRequiredCapabilities(template, false /* expectMatch */);
+ }
+
+ @Test
+ public void testCalculatePriorityClass() throws Exception {
+ assertEquals(2, mCellNetworkRecord.priorityClass);
+ }
+
+ private void checkCalculatePriorityClassFailToMatchAny(
+ boolean hasInternet, int expectedPriorityClass) throws Exception {
+ final List<VcnUnderlyingNetworkTemplate> templatesRequireDun =
+ Collections.singletonList(
+ new VcnCellUnderlyingNetworkTemplate.Builder()
+ .setDun(MATCH_REQUIRED)
+ .build());
+
+ final NetworkCapabilities.Builder ncBuilder =
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 */);
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ if (hasInternet) {
+ ncBuilder.addCapability(NET_CAPABILITY_INTERNET);
+ }
+
+ final UnderlyingNetworkRecord nonDunNetworkRecord =
+ getTestNetworkRecord(ncBuilder.build(), templatesRequireDun);
+
+ assertEquals(expectedPriorityClass, nonDunNetworkRecord.priorityClass);
+ }
- verifyCalculatePriorityClass(wifiNetworkRecord, PRIORITY_ANY);
+ @Test
+ public void testCalculatePriorityClassFailToMatchAny_InternetNetwork() throws Exception {
+ checkCalculatePriorityClassFailToMatchAny(true /* hasInternet */, PRIORITY_FALLBACK);
+ }
+
+ @Test
+ public void testCalculatePriorityClassFailToMatchAny_NonInternetNetwork() throws Exception {
+ checkCalculatePriorityClassFailToMatchAny(false /* hasInternet */, PRIORITY_INVALID);
}
}
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java
index fad9669911bb..2941fdea20bb 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java
@@ -16,18 +16,29 @@
package com.android.server.vcn.routeselection;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
+import static android.net.vcn.VcnCellUnderlyingNetworkTemplate.MATCH_ANY;
+import static android.net.vcn.VcnCellUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
+import static android.net.vcn.VcnCellUnderlyingNetworkTemplate.MATCH_REQUIRED;
+
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.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -42,7 +53,10 @@ import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
+import android.net.vcn.VcnCellUnderlyingNetworkTemplate;
+import android.net.vcn.VcnCellUnderlyingNetworkTemplateTest;
import android.net.vcn.VcnGatewayConnectionConfigTest;
+import android.net.vcn.VcnUnderlyingNetworkTemplate;
import android.os.ParcelUuid;
import android.os.test.TestLooper;
import android.telephony.CarrierConfigManager;
@@ -64,7 +78,10 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import java.util.Set;
import java.util.UUID;
@@ -95,11 +112,39 @@ public class UnderlyingNetworkControllerTest {
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.build();
+ private static final NetworkCapabilities DUN_NETWORK_CAPABILITIES =
+ new NetworkCapabilities.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ .build();
+
+ private static final NetworkCapabilities CBS_NETWORK_CAPABILITIES =
+ new NetworkCapabilities.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ .build();
+
private static final LinkProperties INITIAL_LINK_PROPERTIES =
getLinkPropertiesWithName("initial_iface");
private static final LinkProperties UPDATED_LINK_PROPERTIES =
getLinkPropertiesWithName("updated_iface");
+ private static final VcnCellUnderlyingNetworkTemplate CELL_TEMPLATE_DUN =
+ new VcnCellUnderlyingNetworkTemplate.Builder()
+ .setInternet(MATCH_ANY)
+ .setDun(MATCH_REQUIRED)
+ .build();
+
+ private static final VcnCellUnderlyingNetworkTemplate CELL_TEMPLATE_CBS =
+ new VcnCellUnderlyingNetworkTemplate.Builder()
+ .setInternet(MATCH_ANY)
+ .setCbs(MATCH_REQUIRED)
+ .build();
+
@Mock private Context mContext;
@Mock private VcnNetworkProvider mVcnNetworkProvider;
@Mock private ConnectivityManager mConnectivityManager;
@@ -201,6 +246,107 @@ public class UnderlyingNetworkControllerTest {
any());
}
+ private void verifyRequestBackgroundNetwork(
+ ConnectivityManager cm,
+ int expectedSubId,
+ Set<Integer> expectedRequiredCaps,
+ Set<Integer> expectedForbiddenCaps) {
+ verify(cm)
+ .requestBackgroundNetwork(
+ eq(
+ getCellRequestForSubId(
+ expectedSubId,
+ expectedRequiredCaps,
+ expectedForbiddenCaps)),
+ any(NetworkBringupCallback.class),
+ any());
+ }
+
+ @Test
+ public void testNetworkCallbacksRegisteredOnStartupForNonInternetCapabilities() {
+ final ConnectivityManager cm = mock(ConnectivityManager.class);
+ setupSystemService(mContext, cm, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
+
+ // Build network templates
+ final List<VcnUnderlyingNetworkTemplate> networkTemplates = new ArrayList();
+
+ networkTemplates.add(
+ VcnCellUnderlyingNetworkTemplateTest.getTestNetworkTemplateBuilder()
+ .setDun(MATCH_REQUIRED)
+ .setInternet(MATCH_ANY)
+ .build());
+
+ networkTemplates.add(
+ VcnCellUnderlyingNetworkTemplateTest.getTestNetworkTemplateBuilder()
+ .setMms(MATCH_REQUIRED)
+ .setCbs(MATCH_FORBIDDEN)
+ .setInternet(MATCH_ANY)
+ .build());
+
+ // Start UnderlyingNetworkController
+ new UnderlyingNetworkController(
+ mVcnContext,
+ VcnGatewayConnectionConfigTest.buildTestConfig(networkTemplates),
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mNetworkControllerCb);
+
+ // Verifications
+ for (final int subId : INITIAL_SUB_IDS) {
+ verifyRequestBackgroundNetwork(
+ cm,
+ subId,
+ Collections.singleton(NET_CAPABILITY_INTERNET),
+ Collections.emptySet());
+ verifyRequestBackgroundNetwork(
+ cm, subId, Collections.singleton(NET_CAPABILITY_DUN), Collections.emptySet());
+ verifyRequestBackgroundNetwork(
+ cm,
+ subId,
+ Collections.singleton(NET_CAPABILITY_MMS),
+ Collections.singleton(NET_CAPABILITY_CBS));
+ }
+ }
+
+ @Test
+ public void testNetworkCallbacksRegisteredOnStartupWithDedupedtCapabilities() {
+ final ConnectivityManager cm = mock(ConnectivityManager.class);
+ setupSystemService(mContext, cm, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
+
+ // Build network templates
+ final List<VcnUnderlyingNetworkTemplate> networkTemplates = new ArrayList();
+ final VcnCellUnderlyingNetworkTemplate.Builder builder =
+ new VcnCellUnderlyingNetworkTemplate.Builder()
+ .setMms(MATCH_REQUIRED)
+ .setCbs(MATCH_FORBIDDEN)
+ .setInternet(MATCH_ANY);
+
+ networkTemplates.add(builder.setMetered(MATCH_REQUIRED).build());
+ networkTemplates.add(builder.setMetered(MATCH_FORBIDDEN).build());
+
+ // Start UnderlyingNetworkController
+ new UnderlyingNetworkController(
+ mVcnContext,
+ VcnGatewayConnectionConfigTest.buildTestConfig(networkTemplates),
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mNetworkControllerCb);
+
+ // Verifications
+ for (final int subId : INITIAL_SUB_IDS) {
+ verifyRequestBackgroundNetwork(
+ cm,
+ subId,
+ Collections.singleton(NET_CAPABILITY_INTERNET),
+ Collections.emptySet());
+ verifyRequestBackgroundNetwork(
+ cm,
+ subId,
+ Collections.singleton(NET_CAPABILITY_MMS),
+ Collections.singleton(NET_CAPABILITY_CBS));
+ }
+ }
+
private void verifyNetworkRequestsRegistered(Set<Integer> expectedSubIds) {
verify(mConnectivityManager)
.requestBackgroundNetwork(
@@ -210,8 +356,13 @@ public class UnderlyingNetworkControllerTest {
for (final int subId : expectedSubIds) {
verify(mConnectivityManager)
.requestBackgroundNetwork(
- eq(getCellRequestForSubId(subId)),
- any(NetworkBringupCallback.class), any());
+ eq(
+ getCellRequestForSubId(
+ subId,
+ Collections.singleton(NET_CAPABILITY_INTERNET),
+ Collections.emptySet())),
+ any(NetworkBringupCallback.class),
+ any());
}
verify(mConnectivityManager)
@@ -253,6 +404,7 @@ public class UnderlyingNetworkControllerTest {
private NetworkRequest getWifiRequest(Set<Integer> netCapsSubIds) {
return getExpectedRequestBase()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setSubscriptionIds(netCapsSubIds)
.build();
}
@@ -261,6 +413,7 @@ public class UnderlyingNetworkControllerTest {
// TODO (b/187991063): Add tests for carrier-config based thresholds
return getExpectedRequestBase()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setSubscriptionIds(netCapsSubIds)
.setSignalStrength(WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT)
.build();
@@ -270,16 +423,27 @@ public class UnderlyingNetworkControllerTest {
// TODO (b/187991063): Add tests for carrier-config based thresholds
return getExpectedRequestBase()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setSubscriptionIds(netCapsSubIds)
.setSignalStrength(WIFI_EXIT_RSSI_THRESHOLD_DEFAULT)
.build();
}
- private NetworkRequest getCellRequestForSubId(int subId) {
- return getExpectedRequestBase()
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
- .setNetworkSpecifier(new TelephonyNetworkSpecifier(subId))
- .build();
+ private NetworkRequest getCellRequestForSubId(
+ int subId, Set<Integer> requiredCaps, Set<Integer> forbiddenCaps) {
+ final NetworkRequest.Builder nqBuilder =
+ getExpectedRequestBase()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .setNetworkSpecifier(new TelephonyNetworkSpecifier(subId));
+
+ for (int cap : requiredCaps) {
+ nqBuilder.addCapability(cap);
+ }
+ for (int cap : forbiddenCaps) {
+ nqBuilder.addForbiddenCapability(cap);
+ }
+
+ return nqBuilder.build();
}
private NetworkRequest getRouteSelectionRequest(Set<Integer> netCapsSubIds) {
@@ -301,7 +465,6 @@ public class UnderlyingNetworkControllerTest {
private NetworkRequest.Builder getExpectedRequestBase() {
final NetworkRequest.Builder builder =
new NetworkRequest.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
@@ -321,16 +484,30 @@ public class UnderlyingNetworkControllerTest {
.unregisterNetworkCallback(any(UnderlyingNetworkListener.class));
}
+ private static UnderlyingNetworkRecord getTestNetworkRecord(
+ Network network,
+ NetworkCapabilities networkCapabilities,
+ LinkProperties linkProperties,
+ boolean isBlocked) {
+ return new UnderlyingNetworkRecord(
+ network,
+ networkCapabilities,
+ linkProperties,
+ isBlocked,
+ false /* isSelected */,
+ 0 /* priorityClass */);
+ }
+
@Test
public void testUnderlyingNetworkRecordEquals() {
UnderlyingNetworkRecord recordA =
- new UnderlyingNetworkRecord(
+ getTestNetworkRecord(
mNetwork,
INITIAL_NETWORK_CAPABILITIES,
INITIAL_LINK_PROPERTIES,
false /* isBlocked */);
UnderlyingNetworkRecord recordB =
- new UnderlyingNetworkRecord(
+ getTestNetworkRecord(
mNetwork,
INITIAL_NETWORK_CAPABILITIES,
INITIAL_LINK_PROPERTIES,
@@ -338,12 +515,24 @@ public class UnderlyingNetworkControllerTest {
UnderlyingNetworkRecord recordC =
new UnderlyingNetworkRecord(
mNetwork,
+ INITIAL_NETWORK_CAPABILITIES,
+ INITIAL_LINK_PROPERTIES,
+ false /* isBlocked */,
+ true /* isSelected */,
+ -1 /* priorityClass */);
+ UnderlyingNetworkRecord recordD =
+ getTestNetworkRecord(
+ mNetwork,
UPDATED_NETWORK_CAPABILITIES,
UPDATED_LINK_PROPERTIES,
false /* isBlocked */);
assertEquals(recordA, recordB);
- assertNotEquals(recordA, recordC);
+ assertEquals(recordA, recordC);
+ assertNotEquals(recordA, recordD);
+
+ assertTrue(UnderlyingNetworkRecord.isEqualIncludingPriorities(recordA, recordB));
+ assertFalse(UnderlyingNetworkRecord.isEqualIncludingPriorities(recordA, recordC));
}
@Test
@@ -366,6 +555,10 @@ public class UnderlyingNetworkControllerTest {
.build();
}
+ private void verifyOnSelectedUnderlyingNetworkChanged(UnderlyingNetworkRecord expectedRecord) {
+ verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ }
+
private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback(
NetworkCapabilities networkCapabilities) {
verify(mConnectivityManager)
@@ -384,12 +577,12 @@ public class UnderlyingNetworkControllerTest {
cb.onBlockedStatusChanged(mNetwork, false /* isFalse */);
UnderlyingNetworkRecord expectedRecord =
- new UnderlyingNetworkRecord(
+ getTestNetworkRecord(
mNetwork,
responseNetworkCaps,
INITIAL_LINK_PROPERTIES,
false /* isBlocked */);
- verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ verifyOnSelectedUnderlyingNetworkChanged(expectedRecord);
return cb;
}
@@ -402,12 +595,12 @@ public class UnderlyingNetworkControllerTest {
cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps);
UnderlyingNetworkRecord expectedRecord =
- new UnderlyingNetworkRecord(
+ getTestNetworkRecord(
mNetwork,
responseNetworkCaps,
INITIAL_LINK_PROPERTIES,
false /* isBlocked */);
- verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ verifyOnSelectedUnderlyingNetworkChanged(expectedRecord);
}
@Test
@@ -417,12 +610,12 @@ public class UnderlyingNetworkControllerTest {
cb.onLinkPropertiesChanged(mNetwork, UPDATED_LINK_PROPERTIES);
UnderlyingNetworkRecord expectedRecord =
- new UnderlyingNetworkRecord(
+ getTestNetworkRecord(
mNetwork,
buildResponseNwCaps(INITIAL_NETWORK_CAPABILITIES, INITIAL_SUB_IDS),
UPDATED_LINK_PROPERTIES,
false /* isBlocked */);
- verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ verifyOnSelectedUnderlyingNetworkChanged(expectedRecord);
}
@Test
@@ -434,18 +627,16 @@ public class UnderlyingNetworkControllerTest {
cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps);
UnderlyingNetworkRecord expectedRecord =
- new UnderlyingNetworkRecord(
+ getTestNetworkRecord(
mNetwork,
responseNetworkCaps,
INITIAL_LINK_PROPERTIES,
false /* isBlocked */);
- verify(mNetworkControllerCb, times(1))
- .onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ verifyOnSelectedUnderlyingNetworkChanged(expectedRecord);
// onSelectedUnderlyingNetworkChanged() won't be fired twice if network capabilities doesn't
// change.
cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps);
- verify(mNetworkControllerCb, times(1))
- .onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ verifyOnSelectedUnderlyingNetworkChanged(expectedRecord);
}
@Test
@@ -458,18 +649,16 @@ public class UnderlyingNetworkControllerTest {
cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps);
UnderlyingNetworkRecord expectedRecord =
- new UnderlyingNetworkRecord(
+ getTestNetworkRecord(
mNetwork,
responseNetworkCaps,
INITIAL_LINK_PROPERTIES,
false /* isBlocked */);
- verify(mNetworkControllerCb, times(1))
- .onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ verifyOnSelectedUnderlyingNetworkChanged(expectedRecord);
// onSelectedUnderlyingNetworkChanged() won't be fired twice if network capabilities doesn't
// change.
cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps);
- verify(mNetworkControllerCb, times(1))
- .onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ verifyOnSelectedUnderlyingNetworkChanged(expectedRecord);
}
@Test
@@ -478,13 +667,7 @@ public class UnderlyingNetworkControllerTest {
cb.onBlockedStatusChanged(mNetwork, true /* isBlocked */);
- UnderlyingNetworkRecord expectedRecord =
- new UnderlyingNetworkRecord(
- mNetwork,
- buildResponseNwCaps(INITIAL_NETWORK_CAPABILITIES, INITIAL_SUB_IDS),
- INITIAL_LINK_PROPERTIES,
- true /* isBlocked */);
- verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ verifyOnSelectedUnderlyingNetworkChanged(null);
}
@Test
@@ -520,5 +703,132 @@ public class UnderlyingNetworkControllerTest {
verify(mNetworkControllerCb, times(1)).onSelectedUnderlyingNetworkChanged(any());
}
- // TODO (b/187991063): Add tests for network prioritization
+ private UnderlyingNetworkListener setupControllerAndGetNetworkListener(
+ List<VcnUnderlyingNetworkTemplate> networkTemplates) {
+ final ConnectivityManager cm = mock(ConnectivityManager.class);
+ setupSystemService(mContext, cm, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
+
+ new UnderlyingNetworkController(
+ mVcnContext,
+ VcnGatewayConnectionConfigTest.buildTestConfig(networkTemplates),
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mNetworkControllerCb);
+
+ verify(cm)
+ .registerNetworkCallback(
+ eq(getRouteSelectionRequest(INITIAL_SUB_IDS)),
+ mUnderlyingNetworkListenerCaptor.capture(),
+ any());
+
+ return mUnderlyingNetworkListenerCaptor.getValue();
+ }
+
+ private UnderlyingNetworkRecord bringupNetworkAndGetRecord(
+ UnderlyingNetworkListener cb,
+ NetworkCapabilities requestNetworkCaps,
+ List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
+ UnderlyingNetworkRecord currentlySelected) {
+ final Network network = mock(Network.class);
+ final NetworkCapabilities responseNetworkCaps =
+ buildResponseNwCaps(requestNetworkCaps, INITIAL_SUB_IDS);
+
+ cb.onAvailable(network);
+ cb.onCapabilitiesChanged(network, responseNetworkCaps);
+ cb.onLinkPropertiesChanged(network, INITIAL_LINK_PROPERTIES);
+ cb.onBlockedStatusChanged(network, false /* isFalse */);
+ return new UnderlyingNetworkRecord(
+ network,
+ responseNetworkCaps,
+ INITIAL_LINK_PROPERTIES,
+ false /* isBlocked */,
+ mVcnContext,
+ underlyingNetworkTemplates,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ currentlySelected,
+ null /* carrierConfig */);
+ }
+
+ @Test
+ public void testSelectMorePreferredNetwork() {
+ final List<VcnUnderlyingNetworkTemplate> networkTemplates = new ArrayList();
+ networkTemplates.add(CELL_TEMPLATE_DUN);
+ networkTemplates.add(CELL_TEMPLATE_CBS);
+
+ UnderlyingNetworkListener cb = setupControllerAndGetNetworkListener(networkTemplates);
+
+ // Bring up CBS network
+ final UnderlyingNetworkRecord cbsNetworkRecord =
+ bringupNetworkAndGetRecord(
+ cb,
+ CBS_NETWORK_CAPABILITIES,
+ networkTemplates,
+ null /* currentlySelected */);
+ verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(cbsNetworkRecord));
+
+ // Bring up DUN network
+ final UnderlyingNetworkRecord dunNetworkRecord =
+ bringupNetworkAndGetRecord(
+ cb, DUN_NETWORK_CAPABILITIES, networkTemplates, cbsNetworkRecord);
+ verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(dunNetworkRecord));
+ }
+
+ @Test
+ public void testNeverSelectLessPreferredNetwork() {
+ final List<VcnUnderlyingNetworkTemplate> networkTemplates = new ArrayList();
+ networkTemplates.add(CELL_TEMPLATE_DUN);
+ networkTemplates.add(CELL_TEMPLATE_CBS);
+
+ UnderlyingNetworkListener cb = setupControllerAndGetNetworkListener(networkTemplates);
+
+ // Bring up DUN network
+ final UnderlyingNetworkRecord dunNetworkRecord =
+ bringupNetworkAndGetRecord(
+ cb,
+ DUN_NETWORK_CAPABILITIES,
+ networkTemplates,
+ null /* currentlySelected */);
+ verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(dunNetworkRecord));
+
+ // Bring up CBS network
+ final UnderlyingNetworkRecord cbsNetworkRecord =
+ bringupNetworkAndGetRecord(
+ cb, CBS_NETWORK_CAPABILITIES, networkTemplates, dunNetworkRecord);
+ verify(mNetworkControllerCb, never())
+ .onSelectedUnderlyingNetworkChanged(eq(cbsNetworkRecord));
+ }
+
+ @Test
+ public void testFailtoMatchTemplateAndFallBackToInternetNetwork() {
+ final List<VcnUnderlyingNetworkTemplate> networkTemplates = new ArrayList();
+
+ networkTemplates.add(
+ new VcnCellUnderlyingNetworkTemplate.Builder().setDun(MATCH_REQUIRED).build());
+ UnderlyingNetworkListener cb = setupControllerAndGetNetworkListener(networkTemplates);
+
+ // Bring up an Internet network without DUN capability
+ final UnderlyingNetworkRecord networkRecord =
+ bringupNetworkAndGetRecord(
+ cb,
+ INITIAL_NETWORK_CAPABILITIES,
+ networkTemplates,
+ null /* currentlySelected */);
+ verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(networkRecord));
+ }
+
+ @Test
+ public void testFailtoMatchTemplateAndNeverFallBackToNonInternetNetwork() {
+ final List<VcnUnderlyingNetworkTemplate> networkTemplates = new ArrayList();
+
+ networkTemplates.add(
+ new VcnCellUnderlyingNetworkTemplate.Builder().setDun(MATCH_REQUIRED).build());
+ UnderlyingNetworkListener cb = setupControllerAndGetNetworkListener(networkTemplates);
+
+ bringupNetworkAndGetRecord(
+ cb, CBS_NETWORK_CAPABILITIES, networkTemplates, null /* currentlySelected */);
+
+ verify(mNetworkControllerCb, never())
+ .onSelectedUnderlyingNetworkChanged(any(UnderlyingNetworkRecord.class));
+ }
}