1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.server.wm.jetpack; 18 19 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 20 21 import static com.android.window.flags.Flags.FLAG_ENABLE_WM_EXTENSIONS_FOR_ALL_FLAG; 22 23 import static org.junit.Assert.assertNotNull; 24 import static org.junit.Assert.assertTrue; 25 import static org.junit.Assume.assumeFalse; 26 import static org.junit.Assume.assumeTrue; 27 28 import android.app.ActivityTaskManager; 29 import android.content.Context; 30 import android.content.pm.PackageManager; 31 import android.hardware.display.DisplayManager; 32 import android.platform.test.annotations.Presubmit; 33 import android.platform.test.annotations.RequiresFlagsDisabled; 34 import android.platform.test.annotations.RequiresFlagsEnabled; 35 import android.platform.test.flag.junit.CheckFlagsRule; 36 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 37 import android.server.wm.jetpack.extensions.util.ExtensionsUtil; 38 import android.server.wm.jetpack.extensions.util.SidecarUtil; 39 import android.server.wm.jetpack.utils.WindowManagerJetpackTestBase; 40 import android.view.Display; 41 import android.view.WindowManager; 42 43 import androidx.annotation.NonNull; 44 import androidx.test.core.app.ApplicationProvider; 45 import androidx.test.ext.junit.runners.AndroidJUnit4; 46 import androidx.window.extensions.WindowExtensions; 47 import androidx.window.extensions.embedding.ActivityEmbeddingComponent; 48 49 import com.android.compatibility.common.util.ApiTest; 50 import com.android.compatibility.common.util.CddTest; 51 52 import org.junit.Before; 53 import org.junit.Rule; 54 import org.junit.Test; 55 import org.junit.runner.RunWith; 56 57 import java.util.Arrays; 58 59 /** 60 * Tests for devices implementations include an Android-compatible display(s) 61 * that has a minimum screen dimension greater than or equal to 62 * {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP} and support multi window. 63 * For more information, read 64 * <a href="https://source.android.com/docs/core/display/windowmanager-extensions">WindowManager 65 * Extensions</a> 66 * 67 * Build/Install/Run: 68 * atest CtsWindowManagerJetpackTestCases:SdkAvailabilityTest 69 */ 70 @Presubmit 71 @RunWith(AndroidJUnit4.class) 72 @CddTest(requirements = {"3.8.14/C-5-1"}) 73 public class SdkAvailabilityTest extends WindowManagerJetpackTestBase { 74 75 @Rule 76 public final CheckFlagsRule mCheckFlagsRule = 77 DeviceFlagsValueProvider.createCheckFlagsRule(); 78 79 @Before 80 @Override setUp()81 public void setUp() throws Exception { 82 super.setUp(); 83 assumeFalse("Skip Watch for WM Jetpack/Extensions availability", 84 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)); 85 assumeTrue("Device's default display doesn't support multi window", 86 ActivityTaskManager.supportsMultiWindow(mContext)); 87 } 88 89 /** 90 * MUST implement the latest available stable version of the extensions API 91 * to be used by Window Manager Jetpack library, and declares the window extension 92 * is enabled. 93 */ 94 @RequiresFlagsDisabled(FLAG_ENABLE_WM_EXTENSIONS_FOR_ALL_FLAG) 95 @ApiTest(apis = { 96 "androidx.window.extensions.WindowExtensionsProvider#getWindowExtensions", 97 "androidx.window.extensions.WindowExtensions#getVendorApiLevel", 98 "android.view.WindowManager#hasWindowExtensionsEnabled" 99 }) 100 @Test testWindowExtensionsAvailability()101 public void testWindowExtensionsAvailability() { 102 assumeHasLargeScreenDisplayOrExtensionEnabled(); 103 assertTrue("WindowExtension version is not latest", 104 ExtensionsUtil.isExtensionVersionLatest()); 105 assertTrue("Device must declared that the WindowExtension is enabled", 106 WindowManager.hasWindowExtensionsEnabled()); 107 } 108 109 /** 110 * MUST implement the latest available stable version of the extensions API 111 * to be used by Window Manager Jetpack library, and declares the window extension 112 * is enabled. 113 */ 114 @RequiresFlagsEnabled(FLAG_ENABLE_WM_EXTENSIONS_FOR_ALL_FLAG) 115 @ApiTest(apis = { 116 "androidx.window.extensions.WindowExtensionsProvider#getWindowExtensions", 117 "androidx.window.extensions.WindowExtensions#getVendorApiLevel", 118 "android.view.WindowManager#hasWindowExtensionsEnabled" 119 }) 120 @Test testWindowExtensionsOnAllDevices()121 public void testWindowExtensionsOnAllDevices() { 122 assertTrue("WindowExtension version is not latest", 123 ExtensionsUtil.isExtensionVersionLatest()); 124 assertTrue("Device must declared that the WindowExtension is enabled", 125 WindowManager.hasWindowExtensionsEnabled()); 126 } 127 128 /** 129 * MUST support Activity Embedding APIs and make ActivityEmbeddingComponent available via 130 * WindowExtensions interface. 131 */ 132 @RequiresFlagsDisabled(FLAG_ENABLE_WM_EXTENSIONS_FOR_ALL_FLAG) 133 @ApiTest(apis = {"androidx.window.extensions.WindowExtensions#getActivityEmbeddingComponent"}) 134 @Test testActivityEmbeddingAvailability()135 public void testActivityEmbeddingAvailability() { 136 assumeHasLargeScreenDisplay(); 137 WindowExtensions windowExtensions = ExtensionsUtil.getWindowExtensions(); 138 assertNotNull("WindowExtensions is not available", windowExtensions); 139 ActivityEmbeddingComponent activityEmbeddingComponent = 140 windowExtensions.getActivityEmbeddingComponent(); 141 assertNotNull("ActivityEmbeddingComponent is not available", activityEmbeddingComponent); 142 } 143 144 /** 145 * MUST support Activity Embedding APIs and make ActivityEmbeddingComponent available via 146 * WindowExtensions interface. 147 */ 148 @RequiresFlagsEnabled(FLAG_ENABLE_WM_EXTENSIONS_FOR_ALL_FLAG) 149 @ApiTest(apis = {"androidx.window.extensions.WindowExtensions#getActivityEmbeddingComponent"}) 150 @Test testActivityEmbeddingOnAllDevices()151 public void testActivityEmbeddingOnAllDevices() { 152 final WindowExtensions windowExtensions = ExtensionsUtil.getWindowExtensions(); 153 assertNotNull("WindowExtensions is not available", windowExtensions); 154 final ActivityEmbeddingComponent activityEmbeddingComponent = 155 windowExtensions.getActivityEmbeddingComponent(); 156 assertNotNull("ActivityEmbeddingComponent is not available", activityEmbeddingComponent); 157 } 158 159 /** 160 * MUST also implement the stable version of sidecar API for compatibility with older 161 * applications. 162 */ 163 @ApiTest(apis = {"androidx.window.sidecar.SidecarProvider#getApiVersion"}) 164 @Test testSidecarAvailability()165 public void testSidecarAvailability() { 166 assumeHasLargeScreenDisplayOrExtensionEnabled(); 167 assertTrue("Sidecar is not available", SidecarUtil.isSidecarVersionValid()); 168 } 169 hasLargeScreenDisplay()170 private boolean hasLargeScreenDisplay() { 171 final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class); 172 return Arrays.stream(displayManager.getDisplays()) 173 .filter(display -> display.getType() == Display.TYPE_INTERNAL) 174 .anyMatch(this::isLargeScreenDisplay); 175 } 176 assumeHasLargeScreenDisplay()177 private void assumeHasLargeScreenDisplay() { 178 assumeTrue("Device does not has a minimum screen dimension greater than or equal to " 179 + WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP + "dp", 180 hasLargeScreenDisplay()); 181 } 182 assumeHasLargeScreenDisplayOrExtensionEnabled()183 private void assumeHasLargeScreenDisplayOrExtensionEnabled() { 184 assumeTrue("Device does not has a minimum screen dimension greater than or equal to " 185 + WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP + "dp and window " 186 + "extensions are not enabled.", 187 hasLargeScreenDisplay() || WindowManager.hasWindowExtensionsEnabled()); 188 } 189 isLargeScreenDisplay(@onNull Display display)190 private boolean isLargeScreenDisplay(@NonNull Display display) { 191 // Use WindowContext with type application overlay to prevent the metrics overridden by 192 // activity bounds. Note that process configuration may still be overridden by 193 // foreground Activity. 194 final Context appContext = ApplicationProvider.getApplicationContext(); 195 final Context windowContext = appContext.createWindowContext(display, 196 TYPE_APPLICATION_OVERLAY, null /* options */); 197 return windowContext.getResources().getConfiguration().smallestScreenWidthDp 198 >= WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP; 199 } 200 } 201