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

Commit cc2554f9 authored by Uwais Ashraf's avatar Uwais Ashraf
Browse files

Take screen density vs bitmap density into account when PPH scales

Fix: 419196782
Flag: com.android.launcher3.enable_refactor_task_thumbnail
Test: PreviewPositionHelperTest
Change-Id: I5b2b4f6f2763a4ca998c66cce24fac9dd253542d
parent 0c31f3e3
Loading
Loading
Loading
Loading
+89 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.shared.recents.utilities

import android.graphics.Bitmap
import android.graphics.Matrix
import android.graphics.Rect
import androidx.core.graphics.values
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.shared.recents.model.ThumbnailData
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever

@SmallTest
class PreviewPositionHelperTest : SysuiTestCase() {

    private val systemUnderTest = PreviewPositionHelper()

    @Test
    fun unequalDisplayAndBitmapDensity_contributesToScale() {
        systemUnderTest.updateThumbnailMatrix(
            Rect(0, 0, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT),
            getThumbnailData(bitmapDensityDpi = THUMBNAIL_DENSITY / 2),
            /* canvasWidth = */ CANVAS_WIDTH,
            /* canvasHeight = */ CANVAS_HEIGHT,
            /* isLargeScreen = */ false,
            /* currentRotation = */ 0,
            /* isRtl = */ false,
            /* deviceDensityDpi = */ THUMBNAIL_DENSITY,
        )

        assertThat(systemUnderTest.matrix.values()[Matrix.MSCALE_X]).isEqualTo(0.5f)
    }

    @Test
    fun equalDisplayAndBitmapDensity_scaleIsOne() {
        systemUnderTest.updateThumbnailMatrix(
            Rect(0, 0, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT),
            getThumbnailData(bitmapDensityDpi = THUMBNAIL_DENSITY),
            /* canvasWidth = */ CANVAS_WIDTH,
            /* canvasHeight = */ CANVAS_HEIGHT,
            /* isLargeScreen = */ false,
            /* currentRotation = */ 0,
            /* isRtl = */ false,
            /* deviceDensityDpi = */ THUMBNAIL_DENSITY,
        )

        assertThat(systemUnderTest.matrix.values()[Matrix.MSCALE_X]).isEqualTo(1f)
    }

    private fun getThumbnailData(
        bitmapWidth: Int = THUMBNAIL_WIDTH,
        bitmapHeight: Int = THUMBNAIL_HEIGHT,
        bitmapDensityDpi: Int = THUMBNAIL_DENSITY,
    ) =
        ThumbnailData(
            thumbnail =
                mock<Bitmap>().apply {
                    whenever(width).thenReturn(bitmapWidth)
                    whenever(height).thenReturn(bitmapHeight)
                    whenever(density).thenReturn(bitmapDensityDpi)
                }
        )

    companion object {
        private const val CANVAS_WIDTH = 100
        private const val CANVAS_HEIGHT = 200
        private const val THUMBNAIL_WIDTH = CANVAS_WIDTH
        private const val THUMBNAIL_HEIGHT = CANVAS_HEIGHT
        private const val THUMBNAIL_DENSITY = 320
    }
}
+14 −3
Original line number Diff line number Diff line
@@ -11,10 +11,12 @@ import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSIT
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;

import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -58,9 +60,9 @@ public class PreviewPositionHelper {
    /**
     * Updates the matrix based on the provided parameters
     */
    public void updateThumbnailMatrix(Rect thumbnailBounds, ThumbnailData thumbnailData,
    public void updateThumbnailMatrix(Rect thumbnailBounds, @NonNull ThumbnailData thumbnailData,
            int canvasWidth, int canvasHeight, boolean isLargeScreen, int currentRotation,
            boolean isRtl) {
            boolean isRtl, int deviceDensityDpi) {
        boolean isRotated = false;
        boolean isOrientationDifferent;

@@ -168,7 +170,16 @@ public class PreviewPositionHelper {
                thumbnailClipHint.bottom = 0;
            }

            thumbnailScale = targetW / (croppedWidth * scale);
            final float densityScale;
            if (thumbnailData.getThumbnail() != null
                    && thumbnailData.getThumbnail().getDensity() != Bitmap.DENSITY_NONE
                    && deviceDensityDpi > 0) {
                densityScale = (float) deviceDensityDpi / thumbnailData.getThumbnail().getDensity();
            } else {
                densityScale = 1f;
            }

            thumbnailScale = targetW / (croppedWidth * scale * densityScale);
            if (mSplitBounds != null
                    && mSplitBounds.snapPosition == SNAP_TO_2_10_90
                    && mSplitPosition == SPLIT_POSITION_TOP_OR_LEFT) {
+7 −6
Original line number Diff line number Diff line
@@ -27,16 +27,16 @@ import android.util.AttributeSet
import android.view.View
import android.view.WindowManager
import androidx.core.content.res.use
import com.android.systemui.res.R
import com.android.systemui.mediaprojection.appselector.data.RecentTask
import com.android.systemui.res.R
import com.android.systemui.shared.recents.model.ThumbnailData
import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
import com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen
import com.android.systemui.utils.windowmanager.WindowManagerUtils

/**
 * Custom view that shows a thumbnail preview of one recent task based on [ThumbnailData].
 * It handles proper cropping and positioning of the thumbnail using [PreviewPositionHelper].
 * Custom view that shows a thumbnail preview of one recent task based on [ThumbnailData]. It
 * handles proper cropping and positioning of the thumbnail using [PreviewPositionHelper].
 */
class MediaProjectionTaskView
@JvmOverloads
@@ -98,7 +98,7 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
            (height - 1).toFloat(),
            cornerRadius.toFloat(),
            cornerRadius.toFloat(),
            backgroundPaint
            backgroundPaint,
        )

        val drawBackgroundOnly = task == null || bitmapShader == null || thumbnailData == null
@@ -114,7 +114,7 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
            height.toFloat(),
            cornerRadius.toFloat(),
            cornerRadius.toFloat(),
            paint
            paint,
        )
    }

@@ -157,7 +157,8 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
            measuredHeight,
            isLargeScreen,
            currentRotation,
            isRtl
            isRtl,
            context.resources.displayMetrics.densityDpi,
        )

        bitmapShader.setLocalMatrix(previewPositionHelper.matrix)