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

Commit 4fecd669 authored by Beth Thibodeau's avatar Beth Thibodeau Committed by Android (Google) Code Review
Browse files

Merge "Restrict image size when loading via URI" into udc-dev

parents a30e71c8 49e5fb48
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.service.notification.StatusBarNotification
import android.support.v4.media.MediaMetadataCompat
import android.text.TextUtils
import android.util.Log
import android.util.Pair as APair
import androidx.media.utils.MediaConstants
import com.android.internal.logging.InstanceId
import com.android.keyguard.KeyguardUpdateMonitor
@@ -217,6 +218,13 @@ class MediaDataManager(
    private var smartspaceSession: SmartspaceSession? = null
    private var allowMediaRecommendations = allowMediaRecommendations(context)

    private val artworkWidth =
        context.resources.getDimensionPixelSize(
            com.android.internal.R.dimen.config_mediaMetadataBitmapMaxSize
        )
    private val artworkHeight =
        context.resources.getDimensionPixelSize(R.dimen.qs_media_session_height_expanded)

    /** Check whether this notification is an RCN */
    private fun isRemoteCastNotification(sbn: StatusBarNotification): Boolean {
        return sbn.notification.extras.containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE)
@@ -1250,9 +1258,21 @@ class MediaDataManager(
            return null
        }

        val source = ImageDecoder.createSource(context.getContentResolver(), uri)
        val source = ImageDecoder.createSource(context.contentResolver, uri)
        return try {
            ImageDecoder.decodeBitmap(source) { decoder, _, _ ->
            ImageDecoder.decodeBitmap(source) { decoder, info, _ ->
                val width = info.size.width
                val height = info.size.height
                val scale =
                    MediaDataUtils.getScaleFactor(
                        APair(width, height),
                        APair(artworkWidth, artworkHeight)
                    )

                // Downscale if needed
                if (scale != 0f && scale < 1) {
                    decoder.setTargetSize((scale * width).toInt(), (scale * height).toInt())
                }
                decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE
            }
        } catch (e: IOException) {
+9 −16
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import android.os.Process;
import android.os.Trace;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
@@ -122,6 +123,11 @@ import com.android.systemui.util.animation.TransitionLayout;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.time.SystemClock;

import dagger.Lazy;

import kotlin.Triple;
import kotlin.Unit;

import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
@@ -129,10 +135,6 @@ import java.util.concurrent.Executor;

import javax.inject.Inject;

import dagger.Lazy;
import kotlin.Triple;
import kotlin.Unit;

/**
 * A view controller used for Media Playback.
 */
@@ -1000,18 +1002,9 @@ public class MediaControlPanel {

        int width = drawable.getIntrinsicWidth();
        int height = drawable.getIntrinsicHeight();
        if (width == 0 || height == 0 || targetWidth == 0 || targetHeight == 0) {
            return;
        }

        float scale;
        if ((width / (float) height) > (targetWidth / (float) targetHeight)) {
            // Drawable is wider than target view, scale to match height
            scale = targetHeight / (float) height;
        } else {
            // Drawable is taller than target view, scale to match width
            scale = targetWidth / (float) width;
        }
        float scale = MediaDataUtils.getScaleFactor(new Pair(width, height),
                new Pair(targetWidth, targetHeight));
        if (scale == 0) return;
        transitionDrawable.setLayerSize(layer, (int) (scale * width), (int) (scale * height));
    }

+29 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Pair;

import androidx.core.math.MathUtils;
import androidx.media.utils.MediaConstants;
@@ -87,4 +88,32 @@ public class MediaDataUtils {
        }
        return null;
    }

    /**
     * Calculate a scale factor that will allow the input to fill the target size.
     *
     * @param input width, height of the input view
     * @param target width, height of the target view
     * @return the scale factor; 0 if any given dimension is 0
     */
    public static float getScaleFactor(Pair<Integer, Integer> input,
            Pair<Integer, Integer> target) {
        float width = (float) input.first;
        float height = (float) input.second;

        float targetWidth = (float) target.first;
        float targetHeight = (float) target.second;

        if (width == 0 || height == 0 || targetWidth == 0 || targetHeight == 0) {
            return 0f;
        }

        if ((width / height) > (targetWidth / targetHeight)) {
            // Input is wider than target view, scale to match height
            return targetHeight / height;
        } else {
            // Input is taller than target view, scale to match width
            return targetWidth / width;
        }
    }
}
+75 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.media.controls.util

import android.testing.AndroidTestingRunner
import android.util.Pair as APair
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidTestingRunner::class)
class MediaDataUtilsTest : SysuiTestCase() {

    @Test
    fun testScaleFactor_zeroInput_returnsZero() {
        val input = APair(0, 0)
        val target = APair(100, 100)

        val scale = MediaDataUtils.getScaleFactor(input, target)
        assertThat(scale).isEqualTo(0f)
    }

    @Test
    fun testScaleFactor_tooWide_scaleDown() {
        val input = APair(400, 200)
        val target = APair(100, 100)

        val scale = MediaDataUtils.getScaleFactor(input, target)
        assertThat(scale).isEqualTo(0.5f)
    }

    @Test
    fun testScaleFactor_tooTall_scaleDown() {
        val input = APair(200, 400)
        val target = APair(100, 100)

        val scale = MediaDataUtils.getScaleFactor(input, target)
        assertThat(scale).isEqualTo(0.5f)
    }

    @Test
    fun testScaleFactor_lessWide_scaleUp() {
        val input = APair(50, 100)
        val target = APair(100, 100)

        val scale = MediaDataUtils.getScaleFactor(input, target)
        assertThat(scale).isEqualTo(2f)
    }

    @Test
    fun testScaleFactor_lessTall_scaleUp() {
        val input = APair(100, 50)
        val target = APair(100, 100)

        val scale = MediaDataUtils.getScaleFactor(input, target)
        assertThat(scale).isEqualTo(2f)
    }
}