Bug 1503978 - Force fullscreen after PiP only if media is playing; r=JanH

Otherwise the user should see and be able to interact with the whole page.

Refactored `PictureInPictureController` to check the media playing status for
only the current tab, the one the user has in front and for which we may allow
PiP because `GeckoMediaControlAgent.isMediaPlaying()` would give us false
positives in the case where the current Tab is in fullscreen but not playing
media, while at the same time a background Tab is playing media.

BrowserApp will only force fullscreen after returning from PiP if media
playback has ended, but will keep fullscreen for playing/paused media.

Differential Revision: https://phabricator.services.mozilla.com/D19750

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Petru-Mugurel Lingurar 2019-02-15 17:32:42 +00:00
Родитель 6c3d75cad6
Коммит ca5b6837e1
2 изменённых файлов: 48 добавлений и 11 удалений

Просмотреть файл

@ -1083,11 +1083,14 @@ public class BrowserApp extends GeckoApp
// by checking if the activity received onStop() or not.
final boolean userReturnedToFullApp = !isApplicationInBackground();
// After returning from Picture-in-picture mode the video will still be playing
// After returning from Picture-in-picture mode the video can still be playing
// in fullscreen. But now we have the status bar showing.
// Call setFullscreen(..) to hide it and offer the same fullscreen video experience
// that the user had before entering in Picture-in-picture mode.
if (userReturnedToFullApp) {
// If media is still playing / is paused we need to call setFullscreen(..) to hide
// the status bar and offer the same fullscreen video experience that the user had
// before entering in Picture-in-picture mode.
final boolean shouldKeepVideoInFullscreen =
mPipController.isMediaPlaying() || mPipController.isMediaPaused();
if (userReturnedToFullApp && shouldKeepVideoInFullscreen) {
ActivityUtils.setFullScreen(this, true);
} else {
// User closed the PIP mode.

Просмотреть файл

@ -18,6 +18,8 @@ import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.BuildConfig;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.R;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
import org.mozilla.gecko.util.ActivityUtils;
import org.mozilla.gecko.util.BundleEventListener;
import org.mozilla.gecko.util.EventCallback;
@ -32,6 +34,12 @@ public class PictureInPictureController implements BundleEventListener {
private final Activity pipActivity;
private boolean isInPipMode;
private PlaybackState playbackState = PlaybackState.STOPPED;
private enum PlaybackState {
PLAYING,
PAUSED,
STOPPED
}
public PictureInPictureController(Activity activity) {
pipActivity = activity;
@ -44,7 +52,7 @@ public class PictureInPictureController implements BundleEventListener {
*/
public void tryEnteringPictureInPictureMode() throws IllegalStateException {
if (shouldTryPipMode() &&
pipActivity.enterPictureInPictureMode(getPipParams(isMediaPlaying()))) {
pipActivity.enterPictureInPictureMode(getPipParams(isMediaPlayingForCurrentTab()))) {
EventDispatcher.getInstance().registerUiThreadListener(this, "MediaControlService:MediaPlayingStatus");
isInPipMode = true;
}
@ -61,6 +69,18 @@ public class PictureInPictureController implements BundleEventListener {
return isInPipMode;
}
public boolean isMediaPlaying() {
return playbackState == PlaybackState.PLAYING;
}
public boolean isMediaPaused() {
return playbackState == PlaybackState.PAUSED;
}
public boolean isMediaStopped() {
return playbackState == PlaybackState.STOPPED;
}
private boolean shouldTryPipMode() {
if (!AppConstants.Versions.feature26Plus) {
logDebugMessage("Picture In Picture is only available on Oreo+");
@ -93,7 +113,7 @@ public class PictureInPictureController implements BundleEventListener {
return false;
}
if (!isMediaPlaying()) {
if (!isMediaPlayingForCurrentTab()) {
logDebugMessage("Will not enter Picture in Picture mode if no media is playing");
return false;
}
@ -157,8 +177,10 @@ public class PictureInPictureController implements BundleEventListener {
return new Intent(action, null, pipActivity, MediaControlService.class);
}
private boolean isMediaPlaying() {
return GeckoMediaControlAgent.isMediaPlaying();
private boolean isMediaPlayingForCurrentTab() {
final Tab currentTab = Tabs.getInstance().getSelectedTab();
return currentTab != null && currentTab.isMediaPlaying();
}
/**
@ -193,15 +215,27 @@ public class PictureInPictureController implements BundleEventListener {
Log.w(LOGTAG, "Can't extract new media status");
return;
}
// Best hope scenario: we received this events for the current tab, for which we may allow PiP
// We check against `isMediaPlayingForCurrentTab()` to be sure.
switch (newMediaStatus) {
case "resumeMedia":
updatePictureInPictureActions(getPipParams(true));
if (isMediaPlayingForCurrentTab()) {
updatePictureInPictureActions(getPipParams(true));
playbackState = PlaybackState.PLAYING;
}
break;
case "mediaControlPaused":
updatePictureInPictureActions(getPipParams(false));
if (!isMediaPlayingForCurrentTab()) {
updatePictureInPictureActions(getPipParams(false));
playbackState = PlaybackState.PAUSED;
}
break;
case "mediaControlStopped":
updatePictureInPictureActions(getPipParams(false));
if (!isMediaPlayingForCurrentTab()) {
updatePictureInPictureActions(getPipParams(false));
playbackState = PlaybackState.STOPPED;
}
break;
default:
Log.w(LOGTAG, String.format("Unknown new media status: %s", newMediaStatus));