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

Commit 5b4fc366 authored by Uwais Ashraf's avatar Uwais Ashraf Committed by Android (Google) Code Review
Browse files

Merge "Take screen density vs bitmap density into account when PPH scales" into main

parents 91adddbc cc2554f9
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)