Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 13615a60 authored by Mark Renouf's avatar Mark Renouf
Browse files

Cleanup MULTI_DISPLAY_SCREENSHOT flag

Flag: None
Bug: 295143676
Test: TakeScreenshotServiceTest, TakeScreenshotExecutorTest
Change-Id: I83fb90d735c9f6e63f27de5dd69c801a7121fc71
parent f5a43e55
Loading
Loading
Loading
Loading
+0 −4
Original line number Original line Diff line number Diff line
@@ -394,10 +394,6 @@ object Flags {
    // TODO(b/251205791): Tracking Bug
    // TODO(b/251205791): Tracking Bug
    @JvmField val SCREENSHOT_APP_CLIPS = releasedFlag("screenshot_app_clips")
    @JvmField val SCREENSHOT_APP_CLIPS = releasedFlag("screenshot_app_clips")


    /** TODO(b/295143676): Tracking bug. When enable, captures a screenshot for each display. */
    @JvmField
    val MULTI_DISPLAY_SCREENSHOT = releasedFlag("multi_display_screenshot")

    // 1400 - columbus
    // 1400 - columbus
    // TODO(b/254512756): Tracking Bug
    // TODO(b/254512756): Tracking Bug
    val QUICK_TAP_IN_PCC = releasedFlag("quick_tap_in_pcc")
    val QUICK_TAP_IN_PCC = releasedFlag("quick_tap_in_pcc")
+0 −21
Original line number Original line Diff line number Diff line
@@ -19,10 +19,6 @@ package com.android.systemui.screenshot
import android.util.Log
import android.util.Log
import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.app.tracing.coroutines.launch
import kotlinx.coroutines.CoroutineScope
import java.util.function.Consumer
import javax.inject.Inject
import javax.inject.Inject


/** Processes a screenshot request sent from [ScreenshotHelper]. */
/** Processes a screenshot request sent from [ScreenshotHelper]. */
@@ -42,8 +38,6 @@ class RequestProcessor
constructor(
constructor(
    private val capture: ImageCapture,
    private val capture: ImageCapture,
    private val policy: ScreenshotPolicy,
    private val policy: ScreenshotPolicy,
    /** For the Java Async version, to invoke the callback. */
    @Application private val mainScope: CoroutineScope
) : ScreenshotRequestProcessor {
) : ScreenshotRequestProcessor {


    override suspend fun process(screenshot: ScreenshotData): ScreenshotData {
    override suspend fun process(screenshot: ScreenshotData): ScreenshotData {
@@ -78,21 +72,6 @@ constructor(


        return result
        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({ "$TAG#processAsync" }) {
            val result = process(screenshot)
            callback.accept(result)
        }
    }
}
}


private const val TAG = "RequestProcessor"
private const val TAG = "RequestProcessor"
+2 −2
Original line number Original line Diff line number Diff line
@@ -105,7 +105,7 @@ internal constructor(


    /** Factory for [ScreenshotNotificationsController]. */
    /** Factory for [ScreenshotNotificationsController]. */
    @AssistedFactory
    @AssistedFactory
    interface Factory {
    fun interface Factory {
        fun create(displayId: Int = Display.DEFAULT_DISPLAY): ScreenshotNotificationsController
        fun create(displayId: Int): ScreenshotNotificationsController
    }
    }
}
}
+26 −14
Original line number Original line Diff line number Diff line
@@ -5,7 +5,6 @@ import android.os.Trace
import android.util.Log
import android.util.Log
import android.view.Display
import android.view.Display
import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
import com.android.app.tracing.coroutines.launch
import com.android.internal.logging.UiEventLogger
import com.android.internal.logging.UiEventLogger
import com.android.internal.util.ScreenshotRequest
import com.android.internal.util.ScreenshotRequest
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.SysUISingleton
@@ -18,6 +17,23 @@ import java.util.function.Consumer
import javax.inject.Inject
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch

interface TakeScreenshotExecutor {
    suspend fun executeScreenshots(
        screenshotRequest: ScreenshotRequest,
        onSaved: (Uri) -> Unit,
        requestCallback: RequestCallback
    )
    fun onCloseSystemDialogsReceived()
    fun removeWindows()
    fun onDestroy()
    fun executeScreenshotsAsync(
        screenshotRequest: ScreenshotRequest,
        onSaved: Consumer<Uri>,
        requestCallback: RequestCallback
    )
}


/**
/**
 * Receives the signal to take a screenshot from [TakeScreenshotService], and calls back with the
 * Receives the signal to take a screenshot from [TakeScreenshotService], and calls back with the
@@ -26,7 +42,7 @@ import kotlinx.coroutines.flow.first
 * Captures a screenshot for each [Display] available.
 * Captures a screenshot for each [Display] available.
 */
 */
@SysUISingleton
@SysUISingleton
class TakeScreenshotExecutor
class TakeScreenshotExecutorImpl
@Inject
@Inject
constructor(
constructor(
    private val screenshotControllerFactory: ScreenshotController.Factory,
    private val screenshotControllerFactory: ScreenshotController.Factory,
@@ -35,7 +51,7 @@ constructor(
    private val screenshotRequestProcessor: ScreenshotRequestProcessor,
    private val screenshotRequestProcessor: ScreenshotRequestProcessor,
    private val uiEventLogger: UiEventLogger,
    private val uiEventLogger: UiEventLogger,
    private val screenshotNotificationControllerFactory: ScreenshotNotificationsController.Factory,
    private val screenshotNotificationControllerFactory: ScreenshotNotificationsController.Factory,
) {
) : TakeScreenshotExecutor {


    private val displays = displayRepository.displays
    private val displays = displayRepository.displays
    private val screenshotControllers = mutableMapOf<Int, ScreenshotController>()
    private val screenshotControllers = mutableMapOf<Int, ScreenshotController>()
@@ -47,7 +63,7 @@ constructor(
     * [onSaved] is invoked only on the default display result. [RequestCallback.onFinish] is
     * [onSaved] is invoked only on the default display result. [RequestCallback.onFinish] is
     * invoked only when both screenshot UIs are removed.
     * invoked only when both screenshot UIs are removed.
     */
     */
    suspend fun executeScreenshots(
    override suspend fun executeScreenshots(
        screenshotRequest: ScreenshotRequest,
        screenshotRequest: ScreenshotRequest,
        onSaved: (Uri) -> Unit,
        onSaved: (Uri) -> Unit,
        requestCallback: RequestCallback
        requestCallback: RequestCallback
@@ -128,12 +144,8 @@ constructor(
        }
        }
    }
    }


    /**
    /** Propagates the close system dialog signal to all controllers. */
     * Propagates the close system dialog signal to all controllers.
    override fun onCloseSystemDialogsReceived() {
     *
     * TODO(b/295143676): Move the receiver in this class once the flag is flipped.
     */
    fun onCloseSystemDialogsReceived() {
        screenshotControllers.forEach { (_, screenshotController) ->
        screenshotControllers.forEach { (_, screenshotController) ->
            if (!screenshotController.isPendingSharedTransition) {
            if (!screenshotController.isPendingSharedTransition) {
                screenshotController.requestDismissal(ScreenshotEvent.SCREENSHOT_DISMISSED_OTHER)
                screenshotController.requestDismissal(ScreenshotEvent.SCREENSHOT_DISMISSED_OTHER)
@@ -142,7 +154,7 @@ constructor(
    }
    }


    /** Removes all screenshot related windows. */
    /** Removes all screenshot related windows. */
    fun removeWindows() {
    override fun removeWindows() {
        screenshotControllers.forEach { (_, screenshotController) ->
        screenshotControllers.forEach { (_, screenshotController) ->
            screenshotController.removeWindow()
            screenshotController.removeWindow()
        }
        }
@@ -151,7 +163,7 @@ constructor(
    /**
    /**
     * Destroys the executor. Afterwards, this class is not expected to work as intended anymore.
     * Destroys the executor. Afterwards, this class is not expected to work as intended anymore.
     */
     */
    fun onDestroy() {
    override fun onDestroy() {
        screenshotControllers.forEach { (_, screenshotController) ->
        screenshotControllers.forEach { (_, screenshotController) ->
            screenshotController.onDestroy()
            screenshotController.onDestroy()
        }
        }
@@ -171,12 +183,12 @@ constructor(
    }
    }


    /** For java compatibility only. see [executeScreenshots] */
    /** For java compatibility only. see [executeScreenshots] */
    fun executeScreenshotsAsync(
    override fun executeScreenshotsAsync(
        screenshotRequest: ScreenshotRequest,
        screenshotRequest: ScreenshotRequest,
        onSaved: Consumer<Uri>,
        onSaved: Consumer<Uri>,
        requestCallback: RequestCallback
        requestCallback: RequestCallback
    ) {
    ) {
        mainScope.launch("TakeScreenshotService#executeScreenshotsAsync") {
        mainScope.launch {
            executeScreenshots(screenshotRequest, { uri -> onSaved.accept(uri) }, requestCallback)
            executeScreenshots(screenshotRequest, { uri -> onSaved.accept(uri) }, requestCallback)
        }
        }
    }
    }
+14 −69
Original line number Original line Diff line number Diff line
@@ -21,13 +21,11 @@ import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;


import static com.android.internal.util.ScreenshotHelper.SCREENSHOT_MSG_PROCESS_COMPLETE;
import static com.android.internal.util.ScreenshotHelper.SCREENSHOT_MSG_PROCESS_COMPLETE;
import static com.android.internal.util.ScreenshotHelper.SCREENSHOT_MSG_URI;
import static com.android.internal.util.ScreenshotHelper.SCREENSHOT_MSG_URI;
import static com.android.systemui.flags.Flags.MULTI_DISPLAY_SCREENSHOT;
import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK;
import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK;
import static com.android.systemui.screenshot.LogConfig.DEBUG_DISMISS;
import static com.android.systemui.screenshot.LogConfig.DEBUG_DISMISS;
import static com.android.systemui.screenshot.LogConfig.DEBUG_SERVICE;
import static com.android.systemui.screenshot.LogConfig.DEBUG_SERVICE;
import static com.android.systemui.screenshot.LogConfig.logTag;
import static com.android.systemui.screenshot.LogConfig.logTag;
import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_CAPTURE_FAILED;
import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_CAPTURE_FAILED;
import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_DISMISSED_OTHER;


import android.annotation.MainThread;
import android.annotation.MainThread;
import android.app.Service;
import android.app.Service;
@@ -50,24 +48,19 @@ import android.util.Log;
import android.view.Display;
import android.view.Display;
import android.widget.Toast;
import android.widget.Toast;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.ScreenshotRequest;
import com.android.internal.util.ScreenshotRequest;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.res.R;
import com.android.systemui.res.R;


import java.util.concurrent.Executor;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Consumer;


import javax.inject.Inject;
import javax.inject.Inject;
import javax.inject.Provider;


public class TakeScreenshotService extends Service {
public class TakeScreenshotService extends Service {
    private static final String TAG = logTag(TakeScreenshotService.class);
    private static final String TAG = logTag(TakeScreenshotService.class);


    private final ScreenshotController mScreenshot;

    private final UserManager mUserManager;
    private final UserManager mUserManager;
    private final DevicePolicyManager mDevicePolicyManager;
    private final DevicePolicyManager mDevicePolicyManager;
    private final UiEventLogger mUiEventLogger;
    private final UiEventLogger mUiEventLogger;
@@ -75,27 +68,20 @@ public class TakeScreenshotService extends Service {
    private final Handler mHandler;
    private final Handler mHandler;
    private final Context mContext;
    private final Context mContext;
    private final @Background Executor mBgExecutor;
    private final @Background Executor mBgExecutor;
    private final RequestProcessor mProcessor;
    private final TakeScreenshotExecutor mTakeScreenshotExecutor;
    private final FeatureFlags mFeatureFlags;


    @SuppressWarnings("deprecation")
    private final BroadcastReceiver mCloseSystemDialogs = new BroadcastReceiver() {
    private final BroadcastReceiver mCloseSystemDialogs = new BroadcastReceiver() {
        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
            if (ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction()) && mScreenshot != null) {
            if (ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
                if (DEBUG_DISMISS) {
                if (DEBUG_DISMISS) {
                    Log.d(TAG, "Received ACTION_CLOSE_SYSTEM_DIALOGS");
                    Log.d(TAG, "Received ACTION_CLOSE_SYSTEM_DIALOGS");
                }
                }
                if (mFeatureFlags.isEnabled(MULTI_DISPLAY_SCREENSHOT)) {
                mTakeScreenshotExecutor.onCloseSystemDialogsReceived();
                    // TODO(b/295143676): move receiver inside executor when the flag is enabled.
                    mTakeScreenshotExecutor.get().onCloseSystemDialogsReceived();
                } else if (!mScreenshot.isPendingSharedTransition()) {
                    mScreenshot.requestDismissal(SCREENSHOT_DISMISSED_OTHER);
                }
            }
            }
        }
        }
    };
    };
    private final Provider<TakeScreenshotExecutor> mTakeScreenshotExecutor;



    /** Informs about coarse grained state of the Controller. */
    /** Informs about coarse grained state of the Controller. */
    public interface RequestCallback {
    public interface RequestCallback {
@@ -111,12 +97,14 @@ public class TakeScreenshotService extends Service {
    }
    }


    @Inject
    @Inject
    public TakeScreenshotService(ScreenshotController.Factory screenshotControllerFactory,
    public TakeScreenshotService(
            UserManager userManager, DevicePolicyManager devicePolicyManager,
            UserManager userManager,
            DevicePolicyManager devicePolicyManager,
            UiEventLogger uiEventLogger,
            UiEventLogger uiEventLogger,
            ScreenshotNotificationsController.Factory notificationsControllerFactory,
            ScreenshotNotificationsController.Factory notificationsControllerFactory,
            Context context, @Background Executor bgExecutor, FeatureFlags featureFlags,
            Context context,
            RequestProcessor processor, Provider<TakeScreenshotExecutor> takeScreenshotExecutor) {
            @Background Executor bgExecutor,
            TakeScreenshotExecutor takeScreenshotExecutor) {
        if (DEBUG_SERVICE) {
        if (DEBUG_SERVICE) {
            Log.d(TAG, "new " + this);
            Log.d(TAG, "new " + this);
        }
        }
@@ -127,15 +115,7 @@ public class TakeScreenshotService extends Service {
        mNotificationsController = notificationsControllerFactory.create(Display.DEFAULT_DISPLAY);
        mNotificationsController = notificationsControllerFactory.create(Display.DEFAULT_DISPLAY);
        mContext = context;
        mContext = context;
        mBgExecutor = bgExecutor;
        mBgExecutor = bgExecutor;
        mFeatureFlags = featureFlags;
        mProcessor = processor;
        mTakeScreenshotExecutor = takeScreenshotExecutor;
        mTakeScreenshotExecutor = takeScreenshotExecutor;
        if (mFeatureFlags.isEnabled(MULTI_DISPLAY_SCREENSHOT)) {
            mScreenshot = null;
        } else {
            mScreenshot = screenshotControllerFactory.create(
                    Display.DEFAULT_DISPLAY, /* showUIOnExternalDisplay= */ false);
        }
    }
    }


    @Override
    @Override
@@ -161,11 +141,7 @@ public class TakeScreenshotService extends Service {
        if (DEBUG_SERVICE) {
        if (DEBUG_SERVICE) {
            Log.d(TAG, "onUnbind");
            Log.d(TAG, "onUnbind");
        }
        }
        if (mFeatureFlags.isEnabled(MULTI_DISPLAY_SCREENSHOT)) {
        mTakeScreenshotExecutor.removeWindows();
            mTakeScreenshotExecutor.get().removeWindows();
        } else {
            mScreenshot.removeWindow();
        }
        unregisterReceiver(mCloseSystemDialogs);
        unregisterReceiver(mCloseSystemDialogs);
        return false;
        return false;
    }
    }
@@ -173,11 +149,7 @@ public class TakeScreenshotService extends Service {
    @Override
    @Override
    public void onDestroy() {
    public void onDestroy() {
        super.onDestroy();
        super.onDestroy();
        if (mFeatureFlags.isEnabled(MULTI_DISPLAY_SCREENSHOT)) {
        mTakeScreenshotExecutor.onDestroy();
            mTakeScreenshotExecutor.get().onDestroy();
        } else {
            mScreenshot.onDestroy();
        }
        if (DEBUG_SERVICE) {
        if (DEBUG_SERVICE) {
            Log.d(TAG, "onDestroy");
            Log.d(TAG, "onDestroy");
        }
        }
@@ -190,6 +162,7 @@ public class TakeScreenshotService extends Service {
            mReplyTo = replyTo;
            mReplyTo = replyTo;
        }
        }


        @Override
        public void reportError() {
        public void reportError() {
            reportUri(mReplyTo, null);
            reportUri(mReplyTo, null);
            sendComplete(mReplyTo);
            sendComplete(mReplyTo);
@@ -214,7 +187,6 @@ public class TakeScreenshotService extends Service {
    }
    }


    @MainThread
    @MainThread
    @VisibleForTesting
    void handleRequest(ScreenshotRequest request, Consumer<Uri> onSaved,
    void handleRequest(ScreenshotRequest request, Consumer<Uri> onSaved,
            RequestCallback callback) {
            RequestCallback callback) {
        // If the storage for this user is locked, we have no place to store
        // If the storage for this user is locked, we have no place to store
@@ -245,36 +217,9 @@ public class TakeScreenshotService extends Service {
        }
        }


        Log.d(TAG, "Processing screenshot data");
        Log.d(TAG, "Processing screenshot data");

        mTakeScreenshotExecutor.executeScreenshotsAsync(request, onSaved, callback);

        if (mFeatureFlags.isEnabled(MULTI_DISPLAY_SCREENSHOT)) {
            mTakeScreenshotExecutor.get().executeScreenshotsAsync(request, onSaved, callback);
            return;
    }
    }
        // TODO(b/295143676): Delete the following after the flag is released.
        try {
            ScreenshotData screenshotData = ScreenshotData.fromRequest(
                    request, Display.DEFAULT_DISPLAY);
            mProcessor.processAsync(screenshotData, (data) ->
                    dispatchToController(data, onSaved, callback));


        } catch (IllegalStateException e) {
            Log.e(TAG, "Failed to process screenshot request!", e);
            logFailedRequest(request);
            mNotificationsController.notifyScreenshotError(
                    R.string.screenshot_failed_to_capture_text);
            callback.reportError();
        }
    }

    // TODO(b/295143676): Delete this.
    private void dispatchToController(ScreenshotData screenshot,
            Consumer<Uri> uriConsumer, RequestCallback callback) {
        mUiEventLogger.log(ScreenshotEvent.getScreenshotSource(screenshot.getSource()), 0,
                screenshot.getPackageNameString());
        Log.d(TAG, "Screenshot request: " + screenshot);
        mScreenshot.handleScreenshot(screenshot, uriConsumer, callback);
    }


    private void logFailedRequest(ScreenshotRequest request) {
    private void logFailedRequest(ScreenshotRequest request) {
        ComponentName topComponent = request.getTopComponent();
        ComponentName topComponent = request.getTopComponent();
Loading