Merge "Migrate to ScreenshotData object" into tm-qpr-dev

This commit is contained in:
Matt Casey
2023-01-24 19:45:03 +00:00
committed by Android (Google) Code Review
8 changed files with 487 additions and 52 deletions

View File

@@ -493,6 +493,9 @@ object Flags {
val SCREENSHOT_WORK_PROFILE_POLICY =
unreleasedFlag(1301, "screenshot_work_profile_policy", teamfood = true)
// TODO(b/264916608): Tracking Bug
@JvmField val SCREENSHOT_METADATA = unreleasedFlag(1302, "screenshot_metadata")
// 1400 - columbus
// TODO(b/254512756): Tracking Bug
val QUICK_TAP_IN_PCC = releasedFlag(1400, "quick_tap_in_pcc")

View File

@@ -45,6 +45,7 @@ class RequestProcessor @Inject constructor(
*
* @param request the request to process
*/
// TODO: Delete once SCREENSHOT_METADATA flag is launched
suspend fun process(request: ScreenshotRequest): ScreenshotRequest {
var result = request
@@ -93,12 +94,67 @@ class RequestProcessor @Inject constructor(
* @param request the request to process
* @param callback the callback to provide the processed request, invoked from the main thread
*/
// TODO: Delete once SCREENSHOT_METADATA flag is launched
fun processAsync(request: ScreenshotRequest, callback: Consumer<ScreenshotRequest>) {
mainScope.launch {
val result = process(request)
callback.accept(result)
}
}
/**
* Inspects the incoming ScreenshotData, potentially modifying it based upon policy.
*
* @param screenshot the screenshot to process
*/
suspend fun process(screenshot: ScreenshotData): ScreenshotData {
var result = screenshot
// Apply work profile screenshots policy:
//
// If the focused app belongs to a work profile, transforms a full screen
// (or partial) screenshot request to a task snapshot (provided image) screenshot.
// Whenever displayContentInfo is fetched, the topComponent is also populated
// regardless of the managed profile status.
if (screenshot.type != TAKE_SCREENSHOT_PROVIDED_IMAGE &&
flags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)
) {
val info = policy.findPrimaryContent(policy.getDefaultDisplayId())
Log.d(TAG, "findPrimaryContent: $info")
result.taskId = info.taskId
result.topComponent = info.component
result.userHandle = info.user
if (policy.isManagedProfile(info.user.identifier)) {
val image = capture.captureTask(info.taskId)
?: error("Task snapshot returned a null Bitmap!")
// Provide the task snapshot as the screenshot
result.type = TAKE_SCREENSHOT_PROVIDED_IMAGE
result.bitmap = image
result.screenBounds = info.bounds
}
}
return result
}
/**
* Note: This is for compatibility with existing Java. Prefer the suspending function when
* calling from a Coroutine context.
*
* @param screenshot the screenshot to process
* @param callback the callback to provide the processed screenshot, invoked from the main
* thread
*/
fun processAsync(screenshot: ScreenshotData, callback: Consumer<ScreenshotData>) {
mainScope.launch {
val result = process(screenshot)
callback.accept(result)
}
}
}
private const val TAG = "RequestProcessor"

View File

@@ -390,16 +390,131 @@ public class ScreenshotController {
ClipboardOverlayController.SELF_PERMISSION, null, Context.RECEIVER_NOT_EXPORTED);
}
void handleScreenshot(ScreenshotData screenshot, Consumer<Uri> finisher,
RequestCallback requestCallback) {
Assert.isMainThread();
mCurrentRequestCallback = requestCallback;
if (screenshot.getType() == WindowManager.TAKE_SCREENSHOT_FULLSCREEN) {
Rect bounds = getFullScreenRect();
screenshot.setBitmap(mImageCapture.captureDisplay(DEFAULT_DISPLAY, bounds));
screenshot.setScreenBounds(bounds);
}
if (screenshot.getBitmap() == null) {
Log.e(TAG, "handleScreenshot: Screenshot bitmap was null");
mNotificationsController.notifyScreenshotError(
R.string.screenshot_failed_to_capture_text);
if (mCurrentRequestCallback != null) {
mCurrentRequestCallback.reportError();
}
return;
}
if (!isUserSetupComplete(Process.myUserHandle())) {
Log.w(TAG, "User setup not complete, displaying toast only");
// User setup isn't complete, so we don't want to show any UI beyond a toast, as editing
// and sharing shouldn't be exposed to the user.
saveScreenshotAndToast(screenshot.getUserHandle(), finisher);
return;
}
mBroadcastSender.sendBroadcast(new Intent(ClipboardOverlayController.SCREENSHOT_ACTION),
ClipboardOverlayController.SELF_PERMISSION);
mScreenshotTakenInPortrait =
mContext.getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT;
String oldPackageName = mPackageName;
mPackageName = screenshot.getPackageNameString();
mScreenBitmap = screenshot.getBitmap();
// Optimizations
mScreenBitmap.setHasAlpha(false);
mScreenBitmap.prepareToDraw();
prepareViewForNewScreenshot(screenshot, oldPackageName);
saveScreenshotInWorkerThread(screenshot.getUserHandle(), finisher,
this::showUiOnActionsReady, this::showUiOnQuickShareActionReady);
// The window is focusable by default
setWindowFocusable(true);
mScreenshotView.requestFocus();
enqueueScrollCaptureRequest(screenshot.getUserHandle());
attachWindow();
boolean showFlash = true;
if (screenshot.getType() == WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE) {
if (screenshot.getScreenBounds() != null
&& aspectRatiosMatch(screenshot.getBitmap(), screenshot.getInsets(),
screenshot.getScreenBounds())) {
showFlash = false;
} else {
showFlash = true;
screenshot.setInsets(Insets.NONE);
screenshot.setScreenBounds(new Rect(0, 0, screenshot.getBitmap().getWidth(),
screenshot.getBitmap().getHeight()));
}
}
prepareAnimation(screenshot.getScreenBounds(), showFlash);
if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)) {
mScreenshotView.badgeScreenshot(mContext.getPackageManager().getUserBadgedIcon(
mContext.getDrawable(R.drawable.overlay_badge_background),
screenshot.getUserHandle()));
}
mScreenshotView.setScreenshot(mScreenBitmap, screenshot.getInsets());
if (DEBUG_WINDOW) {
Log.d(TAG, "setContentView: " + mScreenshotView);
}
setContentView(mScreenshotView);
// ignore system bar insets for the purpose of window layout
mWindow.getDecorView().setOnApplyWindowInsetsListener(
(v, insets) -> WindowInsets.CONSUMED);
mScreenshotHandler.cancelTimeout(); // restarted after animation
}
void prepareViewForNewScreenshot(ScreenshotData screenshot, String oldPackageName) {
withWindowAttached(() -> {
if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)
&& mUserManager.isManagedProfile(screenshot.getUserHandle().getIdentifier())) {
mScreenshotView.announceForAccessibility(mContext.getResources().getString(
R.string.screenshot_saving_work_profile_title));
} else {
mScreenshotView.announceForAccessibility(
mContext.getResources().getString(R.string.screenshot_saving_title));
}
});
mScreenshotView.reset();
if (mScreenshotView.isAttachedToWindow()) {
// if we didn't already dismiss for another reason
if (!mScreenshotView.isDismissing()) {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_REENTERED, 0,
oldPackageName);
}
if (DEBUG_WINDOW) {
Log.d(TAG, "saveScreenshot: screenshotView is already attached, resetting. "
+ "(dismissing=" + mScreenshotView.isDismissing() + ")");
}
}
mScreenshotView.setPackageName(mPackageName);
mScreenshotView.updateOrientation(
mWindowManager.getCurrentWindowMetrics().getWindowInsets());
}
@MainThread
void takeScreenshotFullscreen(ComponentName topComponent, Consumer<Uri> finisher,
RequestCallback requestCallback) {
Assert.isMainThread();
mCurrentRequestCallback = requestCallback;
DisplayMetrics displayMetrics = new DisplayMetrics();
getDefaultDisplay().getRealMetrics(displayMetrics);
takeScreenshotInternal(
topComponent, finisher,
new Rect(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels));
takeScreenshotInternal(topComponent, finisher, getFullScreenRect());
}
@MainThread
@@ -641,6 +756,42 @@ public class ScreenshotController {
setWindowFocusable(true);
mScreenshotView.requestFocus();
enqueueScrollCaptureRequest(owner);
attachWindow();
prepareAnimation(screenRect, showFlash);
if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)) {
mScreenshotView.badgeScreenshot(mContext.getPackageManager().getUserBadgedIcon(
mContext.getDrawable(R.drawable.overlay_badge_background), owner));
}
mScreenshotView.setScreenshot(mScreenBitmap, screenInsets);
if (DEBUG_WINDOW) {
Log.d(TAG, "setContentView: " + mScreenshotView);
}
setContentView(mScreenshotView);
// ignore system bar insets for the purpose of window layout
mWindow.getDecorView().setOnApplyWindowInsetsListener(
(v, insets) -> WindowInsets.CONSUMED);
mScreenshotHandler.cancelTimeout(); // restarted after animation
}
private void prepareAnimation(Rect screenRect, boolean showFlash) {
mScreenshotView.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (DEBUG_WINDOW) {
Log.d(TAG, "onPreDraw: startAnimation");
}
mScreenshotView.getViewTreeObserver().removeOnPreDrawListener(this);
startAnimation(screenRect, showFlash);
return true;
}
});
}
private void enqueueScrollCaptureRequest(UserHandle owner) {
// Wait until this window is attached to request because it is
// the reference used to locate the target window (below).
withWindowAttached(() -> {
@@ -678,30 +829,6 @@ public class ScreenshotController {
}
});
});
attachWindow();
mScreenshotView.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (DEBUG_WINDOW) {
Log.d(TAG, "onPreDraw: startAnimation");
}
mScreenshotView.getViewTreeObserver().removeOnPreDrawListener(this);
startAnimation(screenRect, showFlash);
return true;
}
});
if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)) {
mScreenshotView.badgeScreenshot(mContext.getPackageManager().getUserBadgedIcon(
mContext.getDrawable(R.drawable.overlay_badge_background), owner));
}
mScreenshotView.setScreenshot(mScreenBitmap, screenInsets);
// ignore system bar insets for the purpose of window layout
mWindow.getDecorView().setOnApplyWindowInsetsListener(
(v, insets) -> WindowInsets.CONSUMED);
mScreenshotHandler.cancelTimeout(); // restarted after animation
}
private void requestScrollCapture(UserHandle owner) {
@@ -1154,6 +1281,12 @@ public class ScreenshotController {
return !mIsLowRamDevice;
}
private Rect getFullScreenRect() {
DisplayMetrics displayMetrics = new DisplayMetrics();
getDefaultDisplay().getRealMetrics(displayMetrics);
return new Rect(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
}
/** Does the aspect ratio of the bitmap with insets removed match the bounds. */
private static boolean aspectRatiosMatch(Bitmap bitmap, Insets bitmapInsets,
Rect screenBounds) {

View File

@@ -0,0 +1,43 @@
package com.android.systemui.screenshot
import android.content.ComponentName
import android.graphics.Bitmap
import android.graphics.Insets
import android.graphics.Rect
import android.os.UserHandle
import android.view.WindowManager.ScreenshotSource
import android.view.WindowManager.ScreenshotType
import com.android.internal.util.ScreenshotRequest
/** ScreenshotData represents the current state of a single screenshot being acquired. */
data class ScreenshotData(
@ScreenshotType var type: Int,
@ScreenshotSource var source: Int,
/** UserHandle for the owner of the app being screenshotted, if known. */
var userHandle: UserHandle?,
/** ComponentName of the top-most app in the screenshot. */
var topComponent: ComponentName?,
var screenBounds: Rect?,
var taskId: Int,
var insets: Insets,
var bitmap: Bitmap?,
) {
val packageNameString: String
get() = if (topComponent == null) "" else topComponent!!.packageName
companion object {
@JvmStatic
fun fromRequest(request: ScreenshotRequest): ScreenshotData {
return ScreenshotData(
request.type,
request.source,
if (request.userId >= 0) UserHandle.of(request.userId) else null,
request.topComponent,
request.boundsInScreen,
request.taskId,
request.insets,
request.bitmap,
)
}
}
}

View File

@@ -59,6 +59,7 @@ import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.FlagListenable.FlagEvent;
import com.android.systemui.flags.Flags;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -221,8 +222,33 @@ public class TakeScreenshotService extends Service {
return;
}
mProcessor.processAsync(request,
(r) -> dispatchToController(r, onSaved, callback));
if (mFeatureFlags.isEnabled(Flags.SCREENSHOT_METADATA)) {
Log.d(TAG, "Processing screenshot data");
ScreenshotData screenshotData = ScreenshotData.fromRequest(request);
mProcessor.processAsync(screenshotData,
(data) -> dispatchToController(data, onSaved, callback));
} else {
mProcessor.processAsync(request,
(r) -> dispatchToController(r, onSaved, callback));
}
}
private void dispatchToController(ScreenshotData screenshot,
Consumer<Uri> uriConsumer, RequestCallback callback) {
mUiEventLogger.log(ScreenshotEvent.getScreenshotSource(screenshot.getSource()), 0,
screenshot.getPackageNameString());
if (screenshot.getType() == WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
&& screenshot.getBitmap() == null) {
Log.e(TAG, "Got null bitmap from screenshot message");
mNotificationsController.notifyScreenshotError(
R.string.screenshot_failed_to_capture_text);
callback.reportError();
return;
}
mScreenshot.handleScreenshot(screenshot, uriConsumer, callback);
}
private void dispatchToController(ScreenshotRequest request,

View File

@@ -73,6 +73,30 @@ class RequestProcessorTest {
assertThat(result).isEqualTo(request)
}
/** Tests the Java-compatible function wrapper, ensures callback is invoked. */
@Test
fun testProcessAsync_ScreenshotData() {
flags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, false)
val request = ScreenshotData.fromRequest(
ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD).build())
val processor = RequestProcessor(imageCapture, policy, flags, scope)
var result: ScreenshotData? = null
var callbackCount = 0
val callback: (ScreenshotData) -> Unit = { processedRequest: ScreenshotData ->
result = processedRequest
callbackCount++
}
// runs synchronously, using Unconfined Dispatcher
processor.processAsync(request, callback)
// Callback invoked once returning the same request (no changes)
assertThat(callbackCount).isEqualTo(1)
assertThat(result).isEqualTo(request)
}
@Test
fun testFullScreenshot_workProfilePolicyDisabled() = runBlocking {
flags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, false)
@@ -85,6 +109,11 @@ class RequestProcessorTest {
// No changes
assertThat(processedRequest).isEqualTo(request)
val screenshotData = ScreenshotData.fromRequest(request)
val processedData = processor.process(screenshotData)
assertThat(processedData).isEqualTo(screenshotData)
}
@Test
@@ -108,6 +137,13 @@ class RequestProcessorTest {
assertThat(processedRequest.type).isEqualTo(TAKE_SCREENSHOT_FULLSCREEN)
assertThat(processedRequest.source).isEqualTo(SCREENSHOT_OTHER)
assertThat(processedRequest.topComponent).isEqualTo(component)
val processedData = processor.process(ScreenshotData.fromRequest(request))
// Request has topComponent added, but otherwise unchanged.
assertThat(processedData.type).isEqualTo(TAKE_SCREENSHOT_FULLSCREEN)
assertThat(processedData.source).isEqualTo(SCREENSHOT_OTHER)
assertThat(processedData.topComponent).isEqualTo(component)
}
@Test
@@ -140,6 +176,18 @@ class RequestProcessorTest {
assertThat(imageCapture.requestedTaskId).isEqualTo(TASK_ID)
assertThat(processedRequest.userId).isEqualTo(USER_ID)
assertThat(processedRequest.topComponent).isEqualTo(component)
val processedData = processor.process(ScreenshotData.fromRequest(request))
// Expect a task snapshot is taken, overriding the full screen mode
assertThat(processedData.type).isEqualTo(TAKE_SCREENSHOT_PROVIDED_IMAGE)
assertThat(processedData.bitmap).isEqualTo(bitmap)
assertThat(processedData.screenBounds).isEqualTo(bounds)
assertThat(processedData.insets).isEqualTo(Insets.NONE)
assertThat(processedData.taskId).isEqualTo(TASK_ID)
assertThat(imageCapture.requestedTaskId).isEqualTo(TASK_ID)
assertThat(processedRequest.userId).isEqualTo(USER_ID)
assertThat(processedRequest.topComponent).isEqualTo(component)
}
@Test
@@ -165,6 +213,11 @@ class RequestProcessorTest {
// No changes
assertThat(processedRequest).isEqualTo(request)
val screenshotData = ScreenshotData.fromRequest(request)
val processedData = processor.process(screenshotData)
assertThat(processedData).isEqualTo(screenshotData)
}
@Test
@@ -192,6 +245,11 @@ class RequestProcessorTest {
// No changes
assertThat(processedRequest).isEqualTo(request)
val screenshotData = ScreenshotData.fromRequest(request)
val processedData = processor.process(screenshotData)
assertThat(processedData).isEqualTo(screenshotData)
}
@Test
@@ -220,6 +278,11 @@ class RequestProcessorTest {
// Work profile, but already a task snapshot, so no changes
assertThat(processedRequest).isEqualTo(request)
val screenshotData = ScreenshotData.fromRequest(request)
val processedData = processor.process(screenshotData)
assertThat(processedData).isEqualTo(screenshotData)
}
private fun makeHardwareBitmap(width: Int, height: Int): Bitmap {

View File

@@ -0,0 +1,85 @@
/*
* 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 com.android.systemui.screenshot
import android.content.ComponentName
import android.graphics.Insets
import android.graphics.Rect
import android.os.UserHandle
import android.view.WindowManager
import com.android.internal.util.ScreenshotRequest
import com.google.common.truth.Truth.assertThat
import org.junit.Test
class ScreenshotDataTest {
private val type = WindowManager.TAKE_SCREENSHOT_FULLSCREEN
private val source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER
private val bounds = Rect(1, 2, 3, 4)
private val taskId = 123
private val userId = 1
private val insets = Insets.of(1, 2, 3, 4)
private val component = ComponentName("android.test", "android.test.Component")
@Test
fun testConstruction() {
val request =
ScreenshotRequest.Builder(type, source)
.setBoundsOnScreen(bounds)
.setInsets(insets)
.setTaskId(taskId)
.setUserId(userId)
.setTopComponent(component)
.build()
val data = ScreenshotData.fromRequest(request)
assertThat(data.source).isEqualTo(source)
assertThat(data.type).isEqualTo(type)
assertThat(data.screenBounds).isEqualTo(bounds)
assertThat(data.insets).isEqualTo(insets)
assertThat(data.taskId).isEqualTo(taskId)
assertThat(data.userHandle).isEqualTo(UserHandle.of(userId))
assertThat(data.topComponent).isEqualTo(component)
}
@Test
fun testNegativeUserId() {
val request = ScreenshotRequest.Builder(type, source).setUserId(-1).build()
val data = ScreenshotData.fromRequest(request)
assertThat(data.userHandle).isNull()
}
@Test
fun testPackageNameAsString() {
val request = ScreenshotRequest.Builder(type, source).setTopComponent(component).build()
val data = ScreenshotData.fromRequest(request)
assertThat(data.packageNameString).isEqualTo("android.test")
}
@Test
fun testPackageNameAsString_null() {
val request = ScreenshotRequest.Builder(type, source).build()
val data = ScreenshotData.fromRequest(request)
assertThat(data.packageNameString).isEqualTo("")
}
}

View File

@@ -29,7 +29,7 @@ import android.hardware.HardwareBuffer
import android.os.UserHandle
import android.os.UserManager
import android.testing.AndroidTestingRunner
import android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD
import android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER
import android.view.WindowManager.ScreenshotSource.SCREENSHOT_OVERVIEW
import android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN
import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
@@ -39,7 +39,8 @@ import com.android.internal.util.ScreenshotRequest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.SCREENSHOT_WORK_PROFILE_POLICY
import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_REQUESTED_KEY_CHORD
import com.android.systemui.flags.Flags.SCREENSHOT_METADATA
import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_REQUESTED_KEY_OTHER
import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_REQUESTED_OVERVIEW
import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback
import com.android.systemui.util.mockito.any
@@ -106,15 +107,22 @@ class TakeScreenshotServiceTest : SysuiTestCase() {
// Stub request processor as a synchronous no-op for tests with the flag enabled
doAnswer {
val request: ScreenshotRequest = it.getArgument(0) as ScreenshotRequest
val consumer: Consumer<ScreenshotRequest> = it.getArgument(1)
consumer.accept(request)
}
.`when`(requestProcessor)
.processAsync(/* request= */ any(), /* callback= */ any())
val request: ScreenshotRequest = it.getArgument(0) as ScreenshotRequest
val consumer: Consumer<ScreenshotRequest> = it.getArgument(1)
consumer.accept(request)
}.`when`(requestProcessor).processAsync(
/* request= */ any(ScreenshotRequest::class.java), /* callback= */ any())
doAnswer {
val request: ScreenshotData = it.getArgument(0) as ScreenshotData
val consumer: Consumer<ScreenshotData> = it.getArgument(1)
consumer.accept(request)
}.`when`(requestProcessor).processAsync(
/* screenshot= */ any(ScreenshotData::class.java), /* callback= */ any())
// Flipped in selected test cases
flags.set(SCREENSHOT_WORK_PROFILE_POLICY, false)
flags.set(SCREENSHOT_METADATA, false)
service.attach(
mContext,
@@ -141,7 +149,7 @@ class TakeScreenshotServiceTest : SysuiTestCase() {
@Test
fun takeScreenshotFullscreen() {
val request =
ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD)
ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER)
.setTopComponent(topComponent)
.build()
@@ -157,16 +165,34 @@ class TakeScreenshotServiceTest : SysuiTestCase() {
assertEquals("Expected one UiEvent", eventLogger.numLogs(), 1)
val logEvent = eventLogger.get(0)
assertEquals(
"Expected SCREENSHOT_REQUESTED UiEvent",
logEvent.eventId,
SCREENSHOT_REQUESTED_KEY_CHORD.id
)
assertEquals(
"Expected supplied package name",
topComponent.packageName,
eventLogger.get(0).packageName
)
assertEquals("Expected SCREENSHOT_REQUESTED UiEvent",
logEvent.eventId, SCREENSHOT_REQUESTED_KEY_OTHER.id)
assertEquals("Expected supplied package name",
topComponent.packageName, eventLogger.get(0).packageName)
}
@Test
fun takeScreenshotFullscreen_screenshotDataEnabled() {
flags.set(SCREENSHOT_METADATA, true)
val request = ScreenshotRequest.Builder(
TAKE_SCREENSHOT_FULLSCREEN,
SCREENSHOT_KEY_OTHER).setTopComponent(topComponent).build()
service.handleRequest(request, { /* onSaved */ }, callback)
verify(controller, times(1)).handleScreenshot(
eq(ScreenshotData.fromRequest(request)),
/* onSavedListener = */ any(),
/* requestCallback = */ any())
assertEquals("Expected one UiEvent", eventLogger.numLogs(), 1)
val logEvent = eventLogger.get(0)
assertEquals("Expected SCREENSHOT_REQUESTED UiEvent",
logEvent.eventId, SCREENSHOT_REQUESTED_KEY_OTHER.id)
assertEquals("Expected supplied package name",
topComponent.packageName, eventLogger.get(0).packageName)
}
@Test
@@ -218,7 +244,7 @@ class TakeScreenshotServiceTest : SysuiTestCase() {
whenever(userManager.isUserUnlocked).thenReturn(false)
val request =
ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD)
ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER)
.setTopComponent(topComponent)
.build()
@@ -244,7 +270,7 @@ class TakeScreenshotServiceTest : SysuiTestCase() {
.thenReturn("SCREENSHOT_BLOCKED_BY_ADMIN")
val request =
ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD)
ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER)
.setTopComponent(topComponent)
.build()