diff options
| author | 2024-04-05 13:20:26 -0400 | |
|---|---|---|
| committer | 2024-04-06 02:14:42 +0000 | |
| commit | f9343dc4a871867a13689928e4d9903090b9a9b6 (patch) | |
| tree | 190d89c0051adecfed098d12b8273bd5af8f5f0b | |
| parent | b4972f57912549be1d8eed29508f4bc534b0b798 (diff) | |
Pull scroll request/capture code out of ScreenshotController
Test: manual, atest
Flag: NONE
Change-Id: I561ec589a9debfd13d95089b2b333f40c139d8b1
8 files changed, 233 insertions, 195 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionExecutor.kt index 0e3dba47da93..caa67dff086f 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionExecutor.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionExecutor.kt @@ -50,8 +50,15 @@ constructor( fun startSharedTransition(intent: Intent, user: UserHandle, overrideTransition: Boolean) { isPendingSharedTransition = true + val windowTransition = createWindowTransition() applicationScope.launch("$TAG#launchIntentAsync") { - intentExecutor.launchIntent(intent, createWindowTransition(), user, overrideTransition) + intentExecutor.launchIntent( + intent, + user, + overrideTransition, + windowTransition.first, + windowTransition.second + ) } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt index 8e9769ab7d0e..a0cef529ecde 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt @@ -23,7 +23,9 @@ import android.content.ContentProvider import android.content.Context import android.content.Intent import android.net.Uri +import android.os.UserHandle import com.android.systemui.res.R +import com.android.systemui.screenshot.scroll.LongScreenshotActivity object ActionIntentCreator { /** @return a chooser intent to share the given URI. */ @@ -89,6 +91,14 @@ object ActionIntentCreator { .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) } + /** @return an Intent to start the LongScreenshotActivity */ + fun createLongScreenshotIntent(owner: UserHandle, context: Context): Intent { + return Intent(context, LongScreenshotActivity::class.java) + .putExtra(LongScreenshotActivity.EXTRA_SCREENSHOT_USER_HANDLE, owner) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + } + private const val EXTRA_EDIT_SOURCE = "edit_source" private const val EDIT_SOURCE_SCREENSHOT = "screenshot" } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt index 1f9853b17a28..4eca51d47a36 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt @@ -25,7 +25,6 @@ import android.os.Process.myUserHandle import android.os.RemoteException import android.os.UserHandle import android.util.Log -import android.util.Pair import android.view.IRemoteAnimationFinishedCallback import android.view.IRemoteAnimationRunner import android.view.RemoteAnimationAdapter @@ -67,20 +66,22 @@ constructor( */ fun launchIntentAsync( intent: Intent, - transition: Pair<ActivityOptions, ExitTransitionCoordinator>?, user: UserHandle, overrideTransition: Boolean, + options: ActivityOptions?, + transitionCoordinator: ExitTransitionCoordinator?, ) { applicationScope.launch("$TAG#launchIntentAsync") { - launchIntent(intent, transition, user, overrideTransition) + launchIntent(intent, user, overrideTransition, options, transitionCoordinator) } } suspend fun launchIntent( intent: Intent, - transition: Pair<ActivityOptions, ExitTransitionCoordinator>?, user: UserHandle, overrideTransition: Boolean, + options: ActivityOptions?, + transitionCoordinator: ExitTransitionCoordinator?, ) { if (screenshotActionDismissSystemWindows()) { keyguardController.dismiss() @@ -90,14 +91,12 @@ constructor( } else { dismissKeyguard() } - transition?.second?.startExit() + transitionCoordinator?.startExit() if (user == myUserHandle()) { - withContext(mainDispatcher) { - context.startActivity(intent, transition?.first?.toBundle()) - } + withContext(mainDispatcher) { context.startActivity(intent, options?.toBundle()) } } else { - launchCrossProfileIntent(user, intent, transition?.first?.toBundle()) + launchCrossProfileIntent(user, intent, options?.toBundle()) } if (overrideTransition) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index effd16ca4780..ccbe08b841c7 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java @@ -34,7 +34,6 @@ import android.animation.AnimatorListenerAdapter; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ExitTransitionCoordinator; import android.app.ICompatCameraControlCallback; @@ -51,7 +50,6 @@ import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.Process; -import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -59,17 +57,12 @@ import android.util.DisplayMetrics; import android.util.Log; import android.util.Pair; import android.view.Display; -import android.view.IRemoteAnimationFinishedCallback; -import android.view.IRemoteAnimationRunner; -import android.view.RemoteAnimationAdapter; -import android.view.RemoteAnimationTarget; import android.view.ScrollCaptureResponse; import android.view.View; import android.view.ViewRootImpl; import android.view.ViewTreeObserver; import android.view.WindowInsets; import android.view.WindowManager; -import android.view.WindowManagerGlobal; import android.widget.Toast; import android.window.WindowContext; @@ -84,10 +77,7 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.res.R; import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback; -import com.android.systemui.screenshot.scroll.LongScreenshotActivity; -import com.android.systemui.screenshot.scroll.LongScreenshotData; -import com.android.systemui.screenshot.scroll.ScrollCaptureClient; -import com.android.systemui.screenshot.scroll.ScrollCaptureController; +import com.android.systemui.screenshot.scroll.ScrollCaptureExecutor; import com.android.systemui.util.Assert; import com.google.common.util.concurrent.ListenableFuture; @@ -100,12 +90,9 @@ import kotlin.Unit; import java.util.List; import java.util.UUID; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.Future; import java.util.function.Consumer; import javax.inject.Provider; @@ -117,34 +104,6 @@ import javax.inject.Provider; public class ScreenshotController { private static final String TAG = logTag(ScreenshotController.class); - private ScrollCaptureResponse mLastScrollCaptureResponse; - private ListenableFuture<ScrollCaptureResponse> mLastScrollCaptureRequest; - - /** - * This is effectively a no-op, but we need something non-null to pass in, in order to - * successfully override the pending activity entrance animation. - */ - static final IRemoteAnimationRunner.Stub SCREENSHOT_REMOTE_RUNNER = - new IRemoteAnimationRunner.Stub() { - @Override - public void onAnimationStart( - @WindowManager.TransitionOldType int transit, - RemoteAnimationTarget[] apps, - RemoteAnimationTarget[] wallpapers, - RemoteAnimationTarget[] nonApps, - final IRemoteAnimationFinishedCallback finishedCallback) { - try { - finishedCallback.onAnimationFinished(); - } catch (RemoteException e) { - Log.e(TAG, "Error finishing screenshot remote animation", e); - } - } - - @Override - public void onAnimationCancelled() { - } - }; - /** * POD used in the AsyncTask which saves an image in the background. */ @@ -248,13 +207,10 @@ public class ScreenshotController { private final WindowManager.LayoutParams mWindowLayoutParams; @Nullable private final ScreenshotSoundController mScreenshotSoundController; - private final ScrollCaptureClient mScrollCaptureClient; private final PhoneWindow mWindow; private final DisplayManager mDisplayManager; private final int mDisplayId; - private final ScrollCaptureController mScrollCaptureController; - private final LongScreenshotData mLongScreenshotHolder; - private final boolean mIsLowRamDevice; + private final ScrollCaptureExecutor mScrollCaptureExecutor; private final ScreenshotNotificationSmartActionsProvider mScreenshotNotificationSmartActionsProvider; private final TimeoutHandler mScreenshotHandler; @@ -300,14 +256,11 @@ public class ScreenshotController { ScreenshotActionsProvider.Factory actionsProviderFactory, ScreenshotSmartActions screenshotSmartActions, ScreenshotNotificationsController.Factory screenshotNotificationsControllerFactory, - ScrollCaptureClient scrollCaptureClient, UiEventLogger uiEventLogger, ImageExporter imageExporter, ImageCapture imageCapture, @Main Executor mainExecutor, - ScrollCaptureController scrollCaptureController, - LongScreenshotData longScreenshotHolder, - ActivityManager activityManager, + ScrollCaptureExecutor scrollCaptureExecutor, TimeoutHandler timeoutHandler, BroadcastSender broadcastSender, BroadcastDispatcher broadcastDispatcher, @@ -324,14 +277,11 @@ public class ScreenshotController { mScreenshotSmartActions = screenshotSmartActions; mActionsProviderFactory = actionsProviderFactory; mNotificationsController = screenshotNotificationsControllerFactory.create(displayId); - mScrollCaptureClient = scrollCaptureClient; mUiEventLogger = uiEventLogger; mImageExporter = imageExporter; mImageCapture = imageCapture; mMainExecutor = mainExecutor; - mScrollCaptureController = scrollCaptureController; - mLongScreenshotHolder = longScreenshotHolder; - mIsLowRamDevice = activityManager.isLowRamDevice(); + mScrollCaptureExecutor = scrollCaptureExecutor; mScreenshotNotificationSmartActionsProvider = screenshotNotificationSmartActionsProvider; mBgExecutor = Executors.newSingleThreadExecutor(); mBroadcastSender = broadcastSender; @@ -604,8 +554,9 @@ public class ScreenshotController { @Override public void onAction(Intent intent, UserHandle owner, boolean overrideTransition) { + Pair<ActivityOptions, ExitTransitionCoordinator> exit = createWindowTransition(); mActionIntentExecutor.launchIntentAsync( - intent, createWindowTransition(), owner, overrideTransition); + intent, owner, overrideTransition, exit.first, exit.second); } @Override @@ -642,9 +593,8 @@ public class ScreenshotController { mViewProxy.hideScrollChip(); // Delay scroll capture eval a bit to allow the underlying activity // to set up in the new orientation. - mScreenshotHandler.postDelayed(() -> { - requestScrollCapture(owner); - }, 150); + mScreenshotHandler.postDelayed( + () -> requestScrollCapture(owner), 150); mViewProxy.updateInsets( mWindowManager.getCurrentWindowMetrics().getWindowInsets()); // Screenshot animation calculations won't be valid anymore, @@ -667,119 +617,39 @@ public class ScreenshotController { } private void requestScrollCapture(UserHandle owner) { - if (!allowLongScreenshots()) { - Log.d(TAG, "Long screenshots not supported on this device"); - return; - } - mScrollCaptureClient.setHostWindowToken(mWindow.getDecorView().getWindowToken()); - if (mLastScrollCaptureRequest != null) { - mLastScrollCaptureRequest.cancel(true); - } - final ListenableFuture<ScrollCaptureResponse> future = mScrollCaptureClient.request( - mDisplayId); - mLastScrollCaptureRequest = future; - mLastScrollCaptureRequest.addListener(() -> - onScrollCaptureResponseReady(future, owner), mMainExecutor); - } - - private void onScrollCaptureResponseReady(Future<ScrollCaptureResponse> responseFuture, - UserHandle owner) { - try { - if (mLastScrollCaptureResponse != null) { - mLastScrollCaptureResponse.close(); - mLastScrollCaptureResponse = null; - } - if (responseFuture.isCancelled()) { - return; - } - mLastScrollCaptureResponse = responseFuture.get(); - if (!mLastScrollCaptureResponse.isConnected()) { - // No connection means that the target window wasn't found - // or that it cannot support scroll capture. - Log.d(TAG, "ScrollCapture: " + mLastScrollCaptureResponse.getDescription() + " [" - + mLastScrollCaptureResponse.getWindowTitle() + "]"); - return; - } - Log.d(TAG, "ScrollCapture: connected to window [" - + mLastScrollCaptureResponse.getWindowTitle() + "]"); - - final ScrollCaptureResponse response = mLastScrollCaptureResponse; - mViewProxy.showScrollChip(response.getPackageName(), /* onClick */ () -> { - Bitmap newScreenshot = - mImageCapture.captureDisplay(mDisplayId, getFullScreenRect()); - - if (newScreenshot != null) { - // delay starting scroll capture to make sure scrim is up before the app - // moves - mViewProxy.prepareScrollingTransition( - response, mScreenBitmap, newScreenshot, mScreenshotTakenInPortrait, - () -> runBatchScrollCapture(response, owner)); - } else { - Log.wtf(TAG, "failed to capture current screenshot for scroll transition"); + mScrollCaptureExecutor.requestScrollCapture( + mDisplayId, + mWindow.getDecorView().getWindowToken(), + (response) -> { + mViewProxy.showScrollChip(response.getPackageName(), + () -> onScrollButtonClicked(owner, response)); + return Unit.INSTANCE; } - }); - } catch (InterruptedException | ExecutionException e) { - Log.e(TAG, "requestScrollCapture failed", e); - } + ); } - ListenableFuture<ScrollCaptureController.LongScreenshot> mLongScreenshotFuture; - - private void runBatchScrollCapture(ScrollCaptureResponse response, UserHandle owner) { - // Clear the reference to prevent close() in dismissScreenshot - mLastScrollCaptureResponse = null; - - if (mLongScreenshotFuture != null) { - mLongScreenshotFuture.cancel(true); + private void onScrollButtonClicked(UserHandle owner, ScrollCaptureResponse response) { + Bitmap newScreenshot = mImageCapture.captureDisplay(mDisplayId, getFullScreenRect()); + if (newScreenshot == null) { + Log.e(TAG, "Failed to capture current screenshot for scroll transition!"); + return; } - mLongScreenshotFuture = mScrollCaptureController.run(response); - mLongScreenshotFuture.addListener(() -> { - ScrollCaptureController.LongScreenshot longScreenshot; - try { - longScreenshot = mLongScreenshotFuture.get(); - } catch (CancellationException e) { - Log.e(TAG, "Long screenshot cancelled"); - return; - } catch (InterruptedException | ExecutionException e) { - Log.e(TAG, "Exception", e); - mViewProxy.restoreNonScrollingUi(); - return; - } + // delay starting scroll capture to make sure scrim is up before the app moves + mViewProxy.prepareScrollingTransition(response, mScreenBitmap, newScreenshot, + mScreenshotTakenInPortrait, () -> executeBatchScrollCapture(response, owner)); + } - if (longScreenshot.getHeight() == 0) { - mViewProxy.restoreNonScrollingUi(); - return; - } + private void executeBatchScrollCapture(ScrollCaptureResponse response, UserHandle owner) { + mScrollCaptureExecutor.executeBatchScrollCapture(response, + () -> { + final Intent intent = ActionIntentCreator.INSTANCE.createLongScreenshotIntent( + owner, mContext); + mActionIntentExecutor.launchIntentAsync(intent, owner, true, + ActivityOptions.makeCustomAnimation(mContext, 0, 0), null); - mLongScreenshotHolder.setLongScreenshot(longScreenshot); - mLongScreenshotHolder.setTransitionDestinationCallback( - (transitionDestination, onTransitionEnd) -> { - mViewProxy.startLongScreenshotTransition( - transitionDestination, onTransitionEnd, - longScreenshot); - // TODO: Do this via ActionIntentExecutor instead. - mContext.closeSystemDialogs(); - } - ); - - final Intent intent = new Intent(mContext, LongScreenshotActivity.class); - intent.putExtra(LongScreenshotActivity.EXTRA_SCREENSHOT_USER_HANDLE, - owner); - intent.setFlags( - Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); - - mContext.startActivity(intent, - ActivityOptions.makeCustomAnimation(mContext, 0, 0).toBundle()); - RemoteAnimationAdapter runner = new RemoteAnimationAdapter( - SCREENSHOT_REMOTE_RUNNER, 0, 0); - try { - WindowManagerGlobal.getWindowManagerService() - .overridePendingAppTransitionRemote(runner, - mDisplayId); - } catch (Exception e) { - Log.e(TAG, "Error overriding screenshot app transition", e); - } - }, mMainExecutor); + }, + mViewProxy::restoreNonScrollingUi, + mViewProxy::startLongScreenshotTransition); } private void withWindowAttached(Runnable action) { @@ -924,17 +794,7 @@ public class ScreenshotController { /** Reset screenshot view and then call onCompleteRunnable */ private void finishDismiss() { Log.d(TAG, "finishDismiss"); - if (mLastScrollCaptureRequest != null) { - mLastScrollCaptureRequest.cancel(true); - mLastScrollCaptureRequest = null; - } - if (mLastScrollCaptureResponse != null) { - mLastScrollCaptureResponse.close(); - mLastScrollCaptureResponse = null; - } - if (mLongScreenshotFuture != null) { - mLongScreenshotFuture.cancel(true); - } + mScrollCaptureExecutor.close(); if (mCurrentRequestCallback != null) { mCurrentRequestCallback.onFinish(); mCurrentRequestCallback = null; @@ -1118,10 +978,6 @@ public class ScreenshotController { return mDisplayManager.getDisplay(mDisplayId); } - private boolean allowLongScreenshots() { - return !mIsLowRamDevice; - } - private Rect getFullScreenRect() { DisplayMetrics displayMetrics = new DisplayMetrics(); getDisplay().getRealMetrics(displayMetrics); diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/scroll/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/scroll/LongScreenshotActivity.java index 1e1a577ebd4a..706ac9c46be1 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/scroll/LongScreenshotActivity.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/scroll/LongScreenshotActivity.java @@ -335,8 +335,8 @@ public class LongScreenshotActivity extends Activity { // TODO: Fix transition for work profile. Omitting it in the meantime. mActionExecutor.launchIntentAsync( ActionIntentCreator.INSTANCE.createEdit(uri, this), - null, - mScreenshotUserHandle, false); + mScreenshotUserHandle, false, + /* activityOptions */ null, /* transitionCoordinator */ null); } else { String editorPackage = getString(R.string.config_screenshotEditor); Intent intent = new Intent(Intent.ACTION_EDIT); @@ -363,7 +363,8 @@ public class LongScreenshotActivity extends Activity { private void doShare(Uri uri) { Intent shareIntent = ActionIntentCreator.INSTANCE.createShare(uri); - mActionExecutor.launchIntentAsync(shareIntent, null, mScreenshotUserHandle, false); + mActionExecutor.launchIntentAsync(shareIntent, mScreenshotUserHandle, false, + /* activityOptions */ null, /* transitionCoordinator */ null); } private void onClicked(View v) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ScrollCaptureExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ScrollCaptureExecutor.kt new file mode 100644 index 000000000000..6c4ee3e9e89b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ScrollCaptureExecutor.kt @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2024 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.scroll + +import android.app.ActivityManager +import android.graphics.Rect +import android.os.IBinder +import android.util.Log +import android.view.ScrollCaptureResponse +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.screenshot.scroll.ScrollCaptureController.LongScreenshot +import com.google.common.util.concurrent.ListenableFuture +import java.util.concurrent.ExecutionException +import java.util.concurrent.Executor +import java.util.concurrent.Future +import javax.inject.Inject + +class ScrollCaptureExecutor +@Inject +constructor( + activityManager: ActivityManager, + private val scrollCaptureClient: ScrollCaptureClient, + private val scrollCaptureController: ScrollCaptureController, + private val longScreenshotHolder: LongScreenshotData, + @Main private val mainExecutor: Executor +) { + private val isLowRamDevice = activityManager.isLowRamDevice + private var lastScrollCaptureRequest: ListenableFuture<ScrollCaptureResponse>? = null + private var lastScrollCaptureResponse: ScrollCaptureResponse? = null + private var longScreenshotFuture: ListenableFuture<LongScreenshot>? = null + + fun requestScrollCapture( + displayId: Int, + token: IBinder, + callback: (ScrollCaptureResponse) -> Unit + ) { + if (!allowLongScreenshots()) { + Log.d(TAG, "Long screenshots not supported on this device") + return + } + scrollCaptureClient.setHostWindowToken(token) + lastScrollCaptureRequest?.cancel(true) + val scrollRequest = + scrollCaptureClient.request(displayId).apply { + addListener( + { onScrollCaptureResponseReady(this)?.let { callback.invoke(it) } }, + mainExecutor + ) + } + lastScrollCaptureRequest = scrollRequest + } + + fun interface ScrollTransitionReady { + fun onTransitionReady( + destRect: Rect, + onTransitionEnd: Runnable, + longScreenshot: LongScreenshot + ) + } + + fun executeBatchScrollCapture( + response: ScrollCaptureResponse, + onCaptureComplete: Runnable, + onFailure: Runnable, + transition: ScrollTransitionReady, + ) { + // Clear the reference to prevent close() on reset + lastScrollCaptureResponse = null + longScreenshotFuture?.cancel(true) + longScreenshotFuture = + scrollCaptureController.run(response).apply { + addListener( + { + getLongScreenshotChecked(this, onFailure)?.let { + longScreenshotHolder.setLongScreenshot(it) + longScreenshotHolder.setTransitionDestinationCallback { + destinationRect: Rect, + onTransitionEnd: Runnable -> + transition.onTransitionReady(destinationRect, onTransitionEnd, it) + } + onCaptureComplete.run() + } + }, + mainExecutor + ) + } + } + + fun close() { + lastScrollCaptureRequest?.cancel(true) + lastScrollCaptureRequest = null + lastScrollCaptureResponse?.close() + lastScrollCaptureResponse = null + longScreenshotFuture?.cancel(true) + } + + private fun getLongScreenshotChecked( + future: ListenableFuture<LongScreenshot>, + onFailure: Runnable + ): LongScreenshot? { + var longScreenshot: LongScreenshot? = null + runCatching { longScreenshot = future.get() } + .onFailure { + Log.e(TAG, "Caught exception", it) + onFailure.run() + return null + } + if (longScreenshot?.height != 0) { + return longScreenshot + } + onFailure.run() + return null + } + + private fun onScrollCaptureResponseReady( + responseFuture: Future<ScrollCaptureResponse> + ): ScrollCaptureResponse? { + try { + lastScrollCaptureResponse?.close() + lastScrollCaptureResponse = null + if (responseFuture.isCancelled) { + return null + } + val captureResponse = responseFuture.get().apply { lastScrollCaptureResponse = this } + if (!captureResponse.isConnected) { + // No connection means that the target window wasn't found + // or that it cannot support scroll capture. + Log.d( + TAG, + "ScrollCapture: ${captureResponse.description} [${captureResponse.windowTitle}]" + ) + return null + } + Log.d(TAG, "ScrollCapture: connected to window [${captureResponse.windowTitle}]") + return captureResponse + } catch (e: InterruptedException) { + Log.e(TAG, "requestScrollCapture interrupted", e) + } catch (e: ExecutionException) { + Log.e(TAG, "requestScrollCapture failed", e) + } + return null + } + + private fun allowLongScreenshots(): Boolean { + return !isLowRamDevice + } + + private companion object { + private const val TAG = "ScrollCaptureExecutor" + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt index 611e853c7d49..5e7d8fb5df02 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt @@ -64,7 +64,7 @@ class ActionExecutorTest : SysuiTestCase() { val intentCaptor = argumentCaptor<Intent>() verifyBlocking(intentExecutor) { - launchIntent(capture(intentCaptor), any(), eq(UserHandle.CURRENT), eq(true)) + launchIntent(capture(intentCaptor), eq(UserHandle.CURRENT), eq(true), any(), any()) } assertThat(intentCaptor.value.action).isEqualTo(Intent.ACTION_EDIT) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt index 0c324706857f..5e53fe16534d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt @@ -64,7 +64,7 @@ class ActionIntentExecutorTest : SysuiTestCase() { val intent = Intent(Intent.ACTION_EDIT).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK } val userHandle = myUserHandle() - actionIntentExecutor.launchIntent(intent, null, userHandle, false) + actionIntentExecutor.launchIntent(intent, userHandle, false, null, null) scheduler.advanceUntilIdle() verify(activityManagerWrapper) |