1 /* 2 * Copyright (C) 2022 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; 18 19 import static android.view.Display.DEFAULT_DISPLAY; 20 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertTrue; 23 import static org.junit.Assume.assumeTrue; 24 25 import android.Manifest; 26 import android.platform.test.annotations.Presubmit; 27 28 import com.android.compatibility.common.util.ApiTest; 29 30 import org.junit.After; 31 import org.junit.Before; 32 import org.junit.Test; 33 34 import java.util.concurrent.CountDownLatch; 35 import java.util.concurrent.Executors; 36 import java.util.concurrent.TimeUnit; 37 38 /** 39 * Ensure Activity screencapture callback is invoked as expected. 40 * 41 * <p>Build/Install/Run: atest CtsWindowManagerDeviceTestCases:ActivityCaptureCallbackTests 42 */ 43 @Presubmit 44 @ApiTest(apis = {"android.app.Activity#registerScreenCaptureCallback", 45 "android.app.Activity#unregisterScreenCaptureCallback"}) 46 public class ActivityCaptureCallbackTests extends WindowManagerTestBase { 47 private PrimaryActivity mPrimaryActivity; 48 49 @Before 50 @Override setUp()51 public void setUp() throws Exception { 52 super.setUp(); 53 mPrimaryActivity = startActivity(PrimaryActivity.class, DEFAULT_DISPLAY); 54 } 55 56 @After tearDown()57 public void tearDown() throws Exception { 58 mInstrumentation.getUiAutomation().dropShellPermissionIdentity(); 59 } 60 61 /** Test a registered Activity callback invocation. */ 62 @Test testScreencaptureInvokeCallback()63 public void testScreencaptureInvokeCallback() { 64 mInstrumentation 65 .getUiAutomation() 66 .adoptShellPermissionIdentity(Manifest.permission.STATUS_BAR_SERVICE); 67 mWm.notifyScreenshotListeners(DEFAULT_DISPLAY); 68 mPrimaryActivity.waitAndAssertCallbackInvokedOnActivity(); 69 } 70 71 /** Test multi-window activities, both callbacks are invoked. */ 72 @Test testScreencaptureInvokeCallbackOnAllVisibleActivities()73 public void testScreencaptureInvokeCallbackOnAllVisibleActivities() { 74 assumeTrue(supportsMultiDisplay()); 75 76 final WindowManagerState.DisplayContent newDisplay = 77 createManagedExternalDisplaySession().createVirtualDisplay(); 78 final SecondaryActivity secondaryActivity = 79 startActivity(SecondaryActivity.class, newDisplay.mId, /* hasFocus */ false); 80 mInstrumentation 81 .getUiAutomation() 82 .adoptShellPermissionIdentity(Manifest.permission.STATUS_BAR_SERVICE); 83 mWm.notifyScreenshotListeners(DEFAULT_DISPLAY); 84 mWm.notifyScreenshotListeners(newDisplay.mId); 85 mPrimaryActivity.waitAndAssertCallbackInvokedOnActivity(); 86 secondaryActivity.waitAndAssertCallbackInvokedOnActivity(); 87 } 88 89 /** Test screenshotting only one display. */ 90 @Test testScreencaptureInvokeCallbackOnOneDisplay()91 public void testScreencaptureInvokeCallbackOnOneDisplay() { 92 assumeTrue(supportsMultiDisplay()); 93 94 final WindowManagerState.DisplayContent newDisplay = 95 createManagedExternalDisplaySession().createVirtualDisplay(); 96 final SecondaryActivity secondaryActivity = 97 startActivity(SecondaryActivity.class, newDisplay.mId, /* hasFocus */ false); 98 mInstrumentation 99 .getUiAutomation() 100 .adoptShellPermissionIdentity(Manifest.permission.STATUS_BAR_SERVICE); 101 mWm.notifyScreenshotListeners(DEFAULT_DISPLAY); 102 mPrimaryActivity.waitAndAssertCallbackInvokedOnActivity(); 103 secondaryActivity.waitAndAssertCallbackNotInvoked(); 104 } 105 /** Test multi-window activities, only registered callback is invoked. */ 106 @Test testScreencaptureInvokeCallbackOnRegisteredVisibleActivities()107 public void testScreencaptureInvokeCallbackOnRegisteredVisibleActivities() { 108 assumeTrue(supportsMultiDisplay()); 109 110 mPrimaryActivity.unregisterScreencaptureCallback(); 111 final WindowManagerState.DisplayContent newDisplay = 112 createManagedExternalDisplaySession().createVirtualDisplay(); 113 final SecondaryActivity secondaryActivity = 114 startActivity(SecondaryActivity.class, newDisplay.mId, /* hasFocus */ false); 115 mInstrumentation 116 .getUiAutomation() 117 .adoptShellPermissionIdentity(Manifest.permission.STATUS_BAR_SERVICE); 118 mWm.notifyScreenshotListeners(DEFAULT_DISPLAY); 119 mWm.notifyScreenshotListeners(newDisplay.mId); 120 mPrimaryActivity.waitAndAssertCallbackNotInvoked(); 121 secondaryActivity.waitAndAssertCallbackInvokedOnActivity(); 122 } 123 124 /** Test only the top activity callback is invoked */ 125 @Test testScreencaptureInvokeCallbackOnVisibleOnly()126 public void testScreencaptureInvokeCallbackOnVisibleOnly() { 127 final SecondaryActivity topActivity = 128 startActivity(SecondaryActivity.class, DEFAULT_DISPLAY); 129 mInstrumentation 130 .getUiAutomation() 131 .adoptShellPermissionIdentity(Manifest.permission.STATUS_BAR_SERVICE); 132 mWm.notifyScreenshotListeners(DEFAULT_DISPLAY); 133 topActivity.waitAndAssertCallbackInvokedOnActivity(); 134 mPrimaryActivity.waitAndAssertCallbackNotInvoked(); 135 } 136 137 /** Test unregister callback */ 138 @Test testScreencaptureUnregisterCallback()139 public void testScreencaptureUnregisterCallback() { 140 mInstrumentation 141 .getUiAutomation() 142 .adoptShellPermissionIdentity(Manifest.permission.STATUS_BAR_SERVICE); 143 mPrimaryActivity.unregisterScreencaptureCallback(); 144 mWm.notifyScreenshotListeners(DEFAULT_DISPLAY); 145 mPrimaryActivity.waitAndAssertCallbackNotInvoked(); 146 } 147 148 public static class PrimaryActivity extends ScreencaptureCallbackActivity {} 149 150 public static class SecondaryActivity extends ScreencaptureCallbackActivity {} 151 152 private static class ScreencaptureCallbackActivity extends FocusableActivity { 153 private static final long TIMEOUT_SCREENCAPTURE_CALLBACK_INVOKED = 1000; // milliseconds 154 155 private CountDownLatch mCountDownLatch = new CountDownLatch(1); 156 157 final ScreenCaptureCallback mCallback = 158 new ScreenCaptureCallback() { 159 160 @Override 161 public void onScreenCaptured() { 162 mCountDownLatch.countDown(); 163 } 164 }; 165 waitAndAssertCallbackInvokedOnActivity()166 void waitAndAssertCallbackInvokedOnActivity() { 167 try { 168 boolean invoked = mCountDownLatch.await( 169 TIMEOUT_SCREENCAPTURE_CALLBACK_INVOKED, TimeUnit.MILLISECONDS); 170 assertTrue(invoked); 171 } catch (InterruptedException e) { 172 // This shouldn't happen 173 } 174 } 175 waitAndAssertCallbackNotInvoked()176 void waitAndAssertCallbackNotInvoked() { 177 try { 178 boolean invoked = mCountDownLatch.await( 179 TIMEOUT_SCREENCAPTURE_CALLBACK_INVOKED, TimeUnit.MILLISECONDS); 180 assertFalse(invoked); 181 } catch (InterruptedException e) { 182 // This shouldn't happen 183 } 184 } 185 unregisterScreencaptureCallback()186 public void unregisterScreencaptureCallback() { 187 unregisterScreenCaptureCallback(mCallback); 188 } 189 190 @Override onStart()191 protected void onStart() { 192 super.onStart(); 193 registerScreenCaptureCallback(Executors.newSingleThreadExecutor(), mCallback); 194 } 195 } 196 } 197