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

Commit 09f4e926 authored by Miranda Kephart's avatar Miranda Kephart
Browse files

Use PhoneWindow for screenshots

Bug: 174554386
Bug: 159419046
Fix: 174554386

Test: manual

Change-Id: Ie2df84d8650adf6e3d5d4b37b645122983045e92
parent 343b6dda
Loading
Loading
Loading
Loading
+0 −14
Original line number Diff line number Diff line
@@ -40,18 +40,4 @@
        android:visibility="gone"
        android:pointerIcon="crosshair"/>
    <include layout="@layout/global_screenshot_static"/>
    <FrameLayout
        android:id="@+id/global_screenshot_dismiss_button"
        android:layout_width="@dimen/screenshot_dismiss_button_tappable_size"
        android:layout_height="@dimen/screenshot_dismiss_button_tappable_size"
        android:elevation="7dp"
        android:visibility="gone"
        android:contentDescription="@string/screenshot_dismiss_description">
        <ImageView
            android:id="@+id/global_screenshot_dismiss_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="@dimen/screenshot_dismiss_button_margin"
            android:src="@drawable/screenshot_cancel"/>
    </FrameLayout>
</com.android.systemui.screenshot.ScreenshotView>
+18 −1
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:fitsSystemWindows="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
@@ -62,4 +61,22 @@
        </LinearLayout>
    </HorizontalScrollView>
    <include layout="@layout/global_screenshot_preview"/>
    <FrameLayout
        android:id="@+id/global_screenshot_dismiss_button"
        android:layout_width="@dimen/screenshot_dismiss_button_tappable_size"
        android:layout_height="@dimen/screenshot_dismiss_button_tappable_size"
        android:elevation="7dp"
        android:visibility="gone"
        app:layout_constraintStart_toEndOf="@id/global_screenshot_preview"
        app:layout_constraintEnd_toEndOf="@id/global_screenshot_preview"
        app:layout_constraintTop_toTopOf="@id/global_screenshot_preview"
        app:layout_constraintBottom_toTopOf="@id/global_screenshot_preview"
        android:contentDescription="@string/screenshot_dismiss_description">
        <ImageView
            android:id="@+id/global_screenshot_dismiss_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="@dimen/screenshot_dismiss_button_margin"
            android:src="@drawable/screenshot_cancel"/>
    </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
+38 −17
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.systemui.screenshot;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;

import static java.util.Objects.requireNonNull;

@@ -52,7 +54,8 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -60,6 +63,7 @@ import android.widget.Toast;

import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.policy.PhoneWindow;
import com.android.systemui.R;
import com.android.systemui.util.DeviceConfigProxy;

@@ -147,6 +151,8 @@ public class ScreenshotController {
    private final MediaActionSound mCameraSound;
    private final ScrollCaptureClient mScrollCaptureClient;
    private final DeviceConfigProxy mConfigProxy;
    private final PhoneWindow mWindow;
    private final View mDecorView;

    private final Binder mWindowToken;
    private ScreenshotView mScreenshotView;
@@ -189,13 +195,12 @@ public class ScreenshotController {

        final DisplayManager dm = requireNonNull(context.getSystemService(DisplayManager.class));
        mDisplay = dm.getDisplay(DEFAULT_DISPLAY);
        mContext = context.createDisplayContext(mDisplay);
        mContext = context.createWindowContext(TYPE_SCREENSHOT, null);
        mWindowManager = mContext.getSystemService(WindowManager.class);

        mAccessibilityManager = AccessibilityManager.getInstance(mContext);
        mConfigProxy = configProxy;

        reloadAssets();
        Configuration config = mContext.getResources().getConfiguration();
        mInDarkMode = config.isNightModeActive();
        mDirectionLTR = config.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
@@ -204,9 +209,8 @@ public class ScreenshotController {
        mScrollCaptureClient.setHostWindowToken(mWindowToken);

        // Setup the window that we are going to use
        mWindowLayoutParams = new WindowManager.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
                WindowManager.LayoutParams.TYPE_SCREENSHOT,
        mWindowLayoutParams = new WindowManager.LayoutParams(MATCH_PARENT, MATCH_PARENT, 0, 0,
                TYPE_SCREENSHOT,
                WindowManager.LayoutParams.FLAG_FULLSCREEN
                        | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
@@ -217,11 +221,19 @@ public class ScreenshotController {
        mWindowLayoutParams.setTitle("ScreenshotAnimation");
        mWindowLayoutParams.layoutInDisplayCutoutMode =
                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        mWindowLayoutParams.setFitInsetsTypes(0 /* types */);
        mWindowLayoutParams.token = mWindowToken;
        // This is needed to let touches pass through outside the touchable areas
        mWindowLayoutParams.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;

        mWindow = new PhoneWindow(mContext);
        mWindow.setWindowManager(mWindowManager, null, null);
        mWindow.requestFeature(Window.FEATURE_NO_TITLE);
        mWindow.requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
        mWindow.setBackgroundDrawableResource(android.R.color.transparent);
        mDecorView = mWindow.getDecorView();

        reloadAssets();

        mDisplayMetrics = new DisplayMetrics();
        mDisplay.getRealMetrics(mDisplayMetrics);

@@ -355,11 +367,21 @@ public class ScreenshotController {
     * button and the actions container background, since the buttons are re-inflated on demand.
     */
    private void reloadAssets() {
        boolean wasAttached = mScreenshotView != null && mScreenshotView.isAttachedToWindow();
        boolean wasAttached = mDecorView.isAttachedToWindow();
        if (wasAttached) {
            mWindowManager.removeView(mScreenshotView);
            mWindowManager.removeView(mDecorView);
        }

        // respect the display cutout in landscape (since we'd otherwise overlap) but not portrait
        mWindowLayoutParams.setFitInsetsTypes(
                mOrientationPortrait ? 0 : WindowInsets.Type.displayCutout());

        // ignore system bar insets for the purpose of window layout
        mDecorView.setOnApplyWindowInsetsListener((v, insets) -> v.onApplyWindowInsets(
                new WindowInsets.Builder(insets)
                        .setInsets(WindowInsets.Type.all(), Insets.NONE)
                        .build()));

        // Inflate the screenshot layout
        mScreenshotView = (ScreenshotView)
                LayoutInflater.from(mContext).inflate(R.layout.global_screenshot, null);
@@ -382,9 +404,8 @@ public class ScreenshotController {
            return false;
        });

        if (wasAttached) {
            mWindowManager.addView(mScreenshotView, mWindowLayoutParams);
        }
        // view is added to window manager in startAnimation
        mWindow.setContentView(mScreenshotView, mWindowLayoutParams);
    }

    /**
@@ -510,10 +531,10 @@ public class ScreenshotController {
        mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
        mScreenshotHandler.post(() -> {
            if (!mScreenshotView.isAttachedToWindow()) {
                mWindowManager.addView(mScreenshotView, mWindowLayoutParams);
                mWindowManager.addView(mWindow.getDecorView(), mWindowLayoutParams);
            }

            mScreenshotView.prepareForAnimation(mScreenBitmap, screenRect, screenInsets);
            mScreenshotView.prepareForAnimation(mScreenBitmap, screenInsets);

            mScreenshotHandler.post(() -> {
                mScreenshotView.getViewTreeObserver().addOnComputeInternalInsetsListener(
@@ -541,7 +562,7 @@ public class ScreenshotController {

    private void resetScreenshotView() {
        if (mScreenshotView.isAttachedToWindow()) {
            mWindowManager.removeView(mScreenshotView);
            mWindowManager.removeView(mDecorView);
        }
        mScreenshotView.reset();
        mOnCompleteRunnable.run();
@@ -636,8 +657,8 @@ public class ScreenshotController {
        } else {
            mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        }
        if (mScreenshotView.isAttachedToWindow()) {
            mWindowManager.updateViewLayout(mScreenshotView, mWindowLayoutParams);
        if (mDecorView.isAttachedToWindow()) {
            mWindowManager.updateViewLayout(mDecorView, mWindowLayoutParams);
        }
    }

+6 −4
Original line number Diff line number Diff line
@@ -240,8 +240,7 @@ public class ScreenshotView extends FrameLayout implements

        setOnApplyWindowInsetsListener((v, insets) -> {
            if (QuickStepContract.isGesturalMode(mNavMode)) {
                Insets gestureInsets = insets.getInsets(
                        WindowInsets.Type.systemGestures());
                Insets gestureInsets = insets.getInsets(WindowInsets.Type.systemGestures());
                mLeftInset = gestureInsets.left;
                mRightInset = gestureInsets.right;
            } else {
@@ -272,7 +271,7 @@ public class ScreenshotView extends FrameLayout implements
        mScreenshotSelectorView.requestFocus();
    }

    void prepareForAnimation(Bitmap bitmap, Rect screenRect, Insets screenInsets) {
    void prepareForAnimation(Bitmap bitmap, Insets screenInsets) {
        mScreenshotPreview.setImageDrawable(createScreenDrawable(mResources, bitmap, screenInsets));
        // make static preview invisible (from gone) so we can query its location on screen
        mScreenshotPreview.setVisibility(View.INVISIBLE);
@@ -284,6 +283,8 @@ public class ScreenshotView extends FrameLayout implements

        Rect previewBounds = new Rect();
        mScreenshotPreview.getBoundsOnScreen(previewBounds);
        int[] previewLocation = new int[2];
        mScreenshotPreview.getLocationInWindow(previewLocation);

        float cornerScale =
                mCornerSizeX / (mOrientationPortrait ? bounds.width() : bounds.height());
@@ -310,7 +311,8 @@ public class ScreenshotView extends FrameLayout implements

        // animate from the current location, to the static preview location
        final PointF startPos = new PointF(bounds.centerX(), bounds.centerY());
        final PointF finalPos = new PointF(previewBounds.centerX(), previewBounds.centerY());
        final PointF finalPos = new PointF(previewLocation[0] + previewBounds.width() / 2f,
                previewLocation[1] + previewBounds.height() / 2f);

        ValueAnimator toCorner = ValueAnimator.ofFloat(0, 1);
        toCorner.setDuration(SCREENSHOT_TO_CORNER_Y_DURATION_MS);