Commit 7bb74836 authored by Evan Stade's avatar Evan Stade Committed by Commit Bot

Refactor Android MediaSession UI code.

This is the first refactor that prepares the code for
componentization. After further refacrtoring, the next step
will be to relocate the relevant code and resources
to //components/browser_ui/media_session/.

This patch splits MediaSessionTabHelper into two classes,
separated by what is componentizable and what is Chrome
specific.

Most of this class is moved into a new class MediaSessionHelper,
which operates on a WebContents rather than a (Chrome) Tab.
MediaSessionTabHelper remains as a thin wrapper and implementor
of MediaSessionHelper.Delegate. The most substantive change is
moving functionality from TabObserver (in MediaSessionTabHelper)
to WebContentsObserver (in MediaSessionHelper).

Bug: 1066263
Change-Id: I9259a082686c0e0f6b9788bc15a19e887c0e95e6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2204964
Commit-Queue: Evan Stade <estade@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Cr-Commit-Position: refs/heads/master@{#777374}
parent 7c3ba563
......@@ -900,9 +900,11 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/media/remote/RecordCastAction.java",
"java/src/org/chromium/chrome/browser/media/ui/MediaImageCallback.java",
"java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java",
"java/src/org/chromium/chrome/browser/media/ui/MediaNotificationImageUtils.java",
"java/src/org/chromium/chrome/browser/media/ui/MediaNotificationInfo.java",
"java/src/org/chromium/chrome/browser/media/ui/MediaNotificationListener.java",
"java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java",
"java/src/org/chromium/chrome/browser/media/ui/MediaSessionHelper.java",
"java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java",
"java/src/org/chromium/chrome/browser/metrics/ActivityTabStartupMetricsTracker.java",
"java/src/org/chromium/chrome/browser/metrics/BackgroundTaskMemoryMetricsEmitter.java",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.media.ui;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import androidx.annotation.Nullable;
import org.chromium.base.SysUtils;
/** A collection of utilities and constants for the images used in MediaSession notifications. */
public class MediaNotificationImageUtils {
static final int MINIMAL_MEDIA_IMAGE_SIZE_PX = 114;
// The media artwork image resolution on high-end devices.
private static final int HIGH_IMAGE_SIZE_PX = 512;
// The media artwork image resolution on high-end devices.
private static final int LOW_IMAGE_SIZE_PX = 256;
/**
* Downscale |icon| for display in the notification if needed. Returns null if |icon| is null.
* If |icon| is larger than {@link getIdealMediaImageSize()}, scale it down to
* {@link getIdealMediaImageSize()} and return. Otherwise return the original |icon|.
* @param icon The icon to be scaled.
*/
@Nullable
public static Bitmap downscaleIconToIdealSize(@Nullable Bitmap icon) {
if (icon == null) return null;
int targetSize = getIdealMediaImageSize();
Matrix m = new Matrix();
int dominantLength = Math.max(icon.getWidth(), icon.getHeight());
if (dominantLength < getIdealMediaImageSize()) return icon;
// Move the center to (0,0).
m.postTranslate(icon.getWidth() / -2.0f, icon.getHeight() / -2.0f);
// Scale to desired size.
float scale = 1.0f * targetSize / dominantLength;
m.postScale(scale, scale);
// Move to the desired place.
m.postTranslate(targetSize / 2.0f, targetSize / 2.0f);
// Draw the image.
Bitmap paddedBitmap = Bitmap.createBitmap(targetSize, targetSize, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(paddedBitmap);
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(icon, m, paint);
return paddedBitmap;
}
/**
* @return The ideal size of the media image.
*/
public static int getIdealMediaImageSize() {
return SysUtils.isLowEndDevice() ? LOW_IMAGE_SIZE_PX : HIGH_IMAGE_SIZE_PX;
}
/**
* @param icon The icon to be checked.
* @return Whether |icon| is suitable as the media image, i.e. bigger than the minimal size.
*/
public static boolean isBitmapSuitableAsMediaImage(Bitmap icon) {
return icon != null && icon.getWidth() >= MINIMAL_MEDIA_IMAGE_SIZE_PX
&& icon.getHeight() >= MINIMAL_MEDIA_IMAGE_SIZE_PX;
}
}
......@@ -157,7 +157,7 @@ public class MediaNotificationFaviconTest extends MediaNotificationManagerTestBa
}
private Bitmap getDisplayedIcon() {
return mTabHolder.mMediaSessionTabHelper.mFavicon;
return mTabHolder.mMediaSessionTabHelper.mMediaSessionHelper.mFavicon;
}
@Override
......
......@@ -5,6 +5,7 @@
package org.chromium.chrome.browser.media.ui;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.graphics.Bitmap;
......@@ -24,6 +25,7 @@ import org.chromium.media_session.mojom.MediaSessionAction;
import org.chromium.net.GURLUtils;
import org.chromium.net.GURLUtilsJni;
import org.chromium.services.media_session.MediaMetadata;
import org.chromium.url.GURL;
import java.util.Set;
import java.util.stream.Collectors;
......@@ -73,11 +75,9 @@ public class MediaNotificationTestTabHolder {
when(mTab.getWebContents()).thenReturn(mWebContents);
when(mTab.getId()).thenReturn(tabId);
when(mTab.isIncognito()).thenReturn(false);
when(mTab.getTitle()).thenAnswer(invocation -> mTitle);
when(mTab.getUrlString()).thenAnswer(invocation -> mUrl);
when(mWebContents.isIncognito()).thenReturn(false);
MediaSessionTabHelper.sOverriddenMediaSession = mMediaSession;
MediaSessionHelper.sOverriddenMediaSession = mMediaSession;
mMediaSessionTabHelper = new MediaSessionTabHelper(mTab);
mMediaSessionTabHelper.mLargeIconBridge = new TestLargeIconBridge();
......@@ -91,7 +91,7 @@ public class MediaNotificationTestTabHolder {
public void simulateTitleUpdated(String title) {
mTitle = title;
mMediaSessionTabHelper.mTabObserver.onTitleUpdated(mTab);
mMediaSessionTabHelper.mMediaSessionHelper.mWebContentsObserver.titleWasSet(title);
}
public void simulateFaviconUpdated(Bitmap icon) {
......@@ -99,29 +99,40 @@ public class MediaNotificationTestTabHolder {
}
public void simulateMediaSessionStateChanged(boolean isControllable, boolean isSuspended) {
mMediaSessionTabHelper.mMediaSessionObserver.mediaSessionStateChanged(
mMediaSessionTabHelper.mMediaSessionHelper.mMediaSessionObserver.mediaSessionStateChanged(
isControllable, isSuspended);
}
public void simulateMediaSessionMetadataChanged(MediaMetadata metadata) {
mMediaSessionTabHelper.mMediaSessionObserver.mediaSessionMetadataChanged(metadata);
mMediaSessionTabHelper.mMediaSessionHelper.mMediaSessionObserver
.mediaSessionMetadataChanged(metadata);
}
public void simulateMediaSessionActionsChanged(Set<Integer> actions) {
mMediaSessionTabHelper.mMediaSessionObserver.mediaSessionActionsChanged(actions);
mMediaSessionTabHelper.mMediaSessionHelper.mMediaSessionObserver.mediaSessionActionsChanged(
actions);
}
public void simulateNavigation(String url, boolean isSameDocument) {
mUrl = url;
// The following hoop jumping is necessary because loading real GURLs fails under junit.
GURL gurl = mock(GURL.class);
when(mWebContents.getVisibleUrl()).thenAnswer(invocation -> gurl);
GURL gurlOrigin = mock(GURL.class);
when(gurl.getOrigin()).thenAnswer(invocation -> gurlOrigin);
when(gurlOrigin.getSpec()).thenAnswer(invocation -> url);
NavigationHandle navigation = new NavigationHandle(0 /* navigationHandleProxy */, url,
true /* isInMainFrame */, isSameDocument, false /* isRendererInitiated */);
mMediaSessionTabHelper.mTabObserver.onDidStartNavigation(mTab, navigation);
mMediaSessionTabHelper.mMediaSessionHelper.mWebContentsObserver.didStartNavigation(
navigation);
navigation.didFinish(url, false /* isErrorPage */, true /* hasCommitted */,
false /* isFragmentNavigation */, false /* isDownload */,
false /* isValidSearchFormUrl */, 0 /* pageTransition */, 0 /* errorCode */,
200 /* httpStatusCode */);
mMediaSessionTabHelper.mTabObserver.onDidFinishNavigation(mTab, navigation);
mMediaSessionTabHelper.mMediaSessionHelper.mWebContentsObserver.didFinishNavigation(
navigation);
}
}
......@@ -40,7 +40,7 @@ public class MediaNotificationTitleUpdatedTest extends MediaNotificationManagerT
private static final int TAB_ID_2 = 2;
private static final int THROTTLE_MILLIS = MediaNotificationManager.Throttler.THROTTLE_MILLIS;
private static final int HIDE_NOTIFICATION_DELAY_MILLIS =
MediaSessionTabHelper.HIDE_NOTIFICATION_DELAY_MILLIS;
MediaSessionHelper.HIDE_NOTIFICATION_DELAY_MILLIS;
private MediaNotificationTestTabHolder mTabHolder;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment