/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.server.wm; import static android.server.wm.WindowManagerTestBase.startActivity; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import android.content.ComponentCallbacks; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; import android.platform.test.annotations.AppModeFull; import android.platform.test.annotations.Presubmit; import android.server.wm.WindowContextTests.TestWindowService.TestToken; import android.view.View; import android.view.WindowManager; import android.window.WindowProviderService; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.test.core.app.ApplicationProvider; import androidx.test.rule.ServiceTestRule; import org.junit.Test; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Tests that verify the behavior of window context * * Build/Install/Run: * atest CtsWindowManagerDeviceTestCases:WindowContextTests */ @Presubmit public class WindowContextTests extends WindowContextTestBase { @Test @AppModeFull public void testWindowContextConfigChanges() { createAllowSystemAlertWindowAppOpSession(); final WindowManagerState.DisplayContent display = createManagedVirtualDisplaySession() .setSimulateDisplay(true).createDisplay(); final Context windowContext = createWindowContext(display.mId); mInstrumentation.runOnMainSync(() -> { final View view = new View(windowContext); WindowManager wm = windowContext.getSystemService(WindowManager.class); wm.addView(view, new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY)); }); final DisplayMetricsSession displayMetricsSession = createManagedDisplayMetricsSession(display.mId); mWmState.computeState(); Rect bounds = windowContext.getSystemService(WindowManager.class).getCurrentWindowMetrics() .getBounds(); assertBoundsEquals(displayMetricsSession.getDisplayMetrics(), bounds); displayMetricsSession.changeDisplayMetrics(1.2 /* sizeRatio */, 1.1 /* densityRatio */); mWmState.computeState(); bounds = windowContext.getSystemService(WindowManager.class).getCurrentWindowMetrics() .getBounds(); assertBoundsEquals(displayMetricsSession.getDisplayMetrics(), bounds); } private void assertBoundsEquals(ReportedDisplayMetrics expectedMetrics, Rect bounds) { assertEquals(expectedMetrics.getSize().getWidth(), bounds.width()); assertEquals(expectedMetrics.getSize().getHeight(), bounds.height()); } @Test @AppModeFull public void testWindowContextBindService() { createAllowSystemAlertWindowAppOpSession(); final Context windowContext = createWindowContext(DEFAULT_DISPLAY); final ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) {} @Override public void onServiceDisconnected(ComponentName name) {} }; try { assertTrue("WindowContext must bind service successfully.", windowContext.bindService(new Intent(windowContext, TestLogService.class), serviceConnection, Context.BIND_AUTO_CREATE)); } finally { windowContext.unbindService(serviceConnection); } } /** * Verify if the {@link ComponentCallbacks#onConfigurationChanged(Configuration)} callback * is received when the window context configuration changes. */ @Test public void testWindowContextRegisterComponentCallbacks() throws Exception { final TestComponentCallbacks callbacks = new TestComponentCallbacks(); final WindowManagerState.DisplayContent display = createManagedVirtualDisplaySession() .setSimulateDisplay(true).createDisplay(); final Context windowContext = createWindowContext(display.mId); final DisplayMetricsSession displayMetricsSession = createManagedDisplayMetricsSession(display.mId); windowContext.registerComponentCallbacks(callbacks); callbacks.mLatch = new CountDownLatch(1); displayMetricsSession.changeDisplayMetrics(1.2 /* sizeRatio */, 1.1 /* densityRatio */); // verify if there is a callback from the window context configuration change. assertTrue(callbacks.mLatch.await(4, TimeUnit.SECONDS)); Rect bounds = callbacks.mConfiguration.windowConfiguration.getBounds(); assertBoundsEquals(displayMetricsSession.getDisplayMetrics(), bounds); windowContext.unregisterComponentCallbacks(callbacks); } /** * Verifies if window context on the secondary display receives global configuration changes. */ @Test public void testWindowContextGlobalConfigChanges() { final TestComponentCallbacks callbacks = new TestComponentCallbacks(); final WindowManagerState.DisplayContent display = createManagedVirtualDisplaySession() .setPublicDisplay(true).createDisplay(); final FontScaleSession fontScaleSession = createManagedFontScaleSession(); final Context windowContext = createWindowContext(display.mId); windowContext.registerComponentCallbacks(callbacks); final float expectedFontScale = fontScaleSession.get() + 0.3f; fontScaleSession.set(expectedFontScale); // Wait for TestComponentCallbacks#mConfiguration to be assigned. callbacks.waitForConfigChanged(); // We don't rely on latch to verify the result because we may receive two configuration // changes. One may from that WindowContext attaches to a DisplayArea although it is before // ComponentCallback registration), the other is from font the scale change, which is what // we want to verify. waitForOrFail("font scale to match " + expectedFontScale, () -> expectedFontScale == callbacks.mConfiguration.fontScale); windowContext.unregisterComponentCallbacks(callbacks); } /** * Verify the {@link WindowProviderService} lifecycle: *