Merge "Handle PiP params changes in onTaskInfoChanged" into tm-dev

This commit is contained in:
Jacqueline Bronger
2022-05-02 08:35:59 +00:00
committed by Android (Google) Code Review
21 changed files with 462 additions and 413 deletions

View File

@@ -43,12 +43,6 @@ oneway interface IPinnedTaskListener {
*/
void onImeVisibilityChanged(boolean imeVisible, int imeHeight);
/**
* Called when the set of actions for the current PiP activity changes, or when the listener
* is first registered to allow the listener to synchronize its state with the controller.
*/
void onActionsChanged(in ParceledListSlice<RemoteAction> actions, in RemoteAction closeAction);
/**
* Called by the window manager to notify the listener that Activity (was or is in pinned mode)
* is hidden (either stopped or removed). This is generally used as a signal to reset saved
@@ -56,14 +50,4 @@ oneway interface IPinnedTaskListener {
* {@param componentName} represents the application component of PiP window.
*/
void onActivityHidden(in ComponentName componentName);
/**
* Called by the window manager when the aspect ratio is reset.
*/
void onAspectRatioChanged(float aspectRatio);
/**
* Called by the window manager when the expanded aspect ratio is reset.
*/
void onExpandedAspectRatioChanged(float aspectRatio);
}

View File

@@ -30,6 +30,7 @@ import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.pip.PipMediaController;
import com.android.wm.shell.pip.PipParamsChangedForwarder;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipSurfaceTransactionHelper;
import com.android.wm.shell.pip.PipTaskOrganizer;
@@ -41,6 +42,7 @@ import com.android.wm.shell.pip.tv.TvPipBoundsState;
import com.android.wm.shell.pip.tv.TvPipController;
import com.android.wm.shell.pip.tv.TvPipMenuController;
import com.android.wm.shell.pip.tv.TvPipNotificationController;
import com.android.wm.shell.pip.tv.TvPipTaskOrganizer;
import com.android.wm.shell.pip.tv.TvPipTransition;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.transition.Transitions;
@@ -67,6 +69,7 @@ public abstract class TvPipModule {
PipTransitionController pipTransitionController,
TvPipNotificationController tvPipNotificationController,
TaskStackListenerImpl taskStackListener,
PipParamsChangedForwarder pipParamsChangedForwarder,
DisplayController displayController,
WindowManagerShellWrapper windowManagerShellWrapper,
@ShellMainThread ShellExecutor mainExecutor,
@@ -82,6 +85,7 @@ public abstract class TvPipModule {
pipMediaController,
tvPipNotificationController,
taskStackListener,
pipParamsChangedForwarder,
displayController,
windowManagerShellWrapper,
mainExecutor,
@@ -163,15 +167,22 @@ public abstract class TvPipModule {
TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
PipAnimationController pipAnimationController,
PipTransitionController pipTransitionController,
PipParamsChangedForwarder pipParamsChangedForwarder,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
Optional<SplitScreenController> splitScreenControllerOptional,
DisplayController displayController,
PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
@ShellMainThread ShellExecutor mainExecutor) {
return new PipTaskOrganizer(context,
return new TvPipTaskOrganizer(context,
syncTransactionQueue, pipTransitionState, tvPipBoundsState, tvPipBoundsAlgorithm,
tvPipMenuController, pipAnimationController, pipSurfaceTransactionHelper,
pipTransitionController, splitScreenControllerOptional,
pipTransitionController, pipParamsChangedForwarder, splitScreenControllerOptional,
displayController, pipUiEventLogger, shellTaskOrganizer, mainExecutor);
}
@WMSingleton
@Provides
static PipParamsChangedForwarder providePipParamsChangedForwarder() {
return new PipParamsChangedForwarder();
}
}

View File

@@ -54,6 +54,7 @@ import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipMediaController;
import com.android.wm.shell.pip.PipParamsChangedForwarder;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipSurfaceTransactionHelper;
import com.android.wm.shell.pip.PipTaskOrganizer;
@@ -216,14 +217,14 @@ public class WMShellModule {
PipTouchHandler pipTouchHandler, PipTransitionController pipTransitionController,
WindowManagerShellWrapper windowManagerShellWrapper,
TaskStackListenerImpl taskStackListener,
PipParamsChangedForwarder pipParamsChangedForwarder,
Optional<OneHandedController> oneHandedController,
@ShellMainThread ShellExecutor mainExecutor) {
return Optional.ofNullable(PipController.create(context, displayController,
pipAppOpsListener, pipBoundsAlgorithm, pipKeepClearAlgorithm, pipBoundsState,
pipMotionHelper,
pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTouchHandler,
pipTransitionController, windowManagerShellWrapper, taskStackListener,
oneHandedController, mainExecutor));
pipMotionHelper, pipMediaController, phonePipMenuController, pipTaskOrganizer,
pipTouchHandler, pipTransitionController, windowManagerShellWrapper,
taskStackListener, pipParamsChangedForwarder, oneHandedController, mainExecutor));
}
@WMSingleton
@@ -297,6 +298,7 @@ public class WMShellModule {
PipAnimationController pipAnimationController,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
PipTransitionController pipTransitionController,
PipParamsChangedForwarder pipParamsChangedForwarder,
Optional<SplitScreenController> splitScreenControllerOptional,
DisplayController displayController,
PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
@@ -304,7 +306,7 @@ public class WMShellModule {
return new PipTaskOrganizer(context,
syncTransactionQueue, pipTransitionState, pipBoundsState, pipBoundsAlgorithm,
menuPhoneController, pipAnimationController, pipSurfaceTransactionHelper,
pipTransitionController, splitScreenControllerOptional,
pipTransitionController, pipParamsChangedForwarder, splitScreenControllerOptional,
displayController, pipUiEventLogger, shellTaskOrganizer, mainExecutor);
}
@@ -391,4 +393,10 @@ public class WMShellModule {
rootTaskDisplayAreaOrganizer
);
}
@WMSingleton
@Provides
static PipParamsChangedForwarder providePipParamsChangedForwarder() {
return new PipParamsChangedForwarder();
}
}

View File

@@ -16,9 +16,7 @@
package com.android.wm.shell.pip;
import android.app.RemoteAction;
import android.content.ComponentName;
import android.content.pm.ParceledListSlice;
import android.os.RemoteException;
import android.view.IPinnedTaskListener;
import android.view.WindowManagerGlobal;
@@ -72,31 +70,12 @@ public class PinnedStackListenerForwarder {
}
}
private void onActionsChanged(ParceledListSlice<RemoteAction> actions,
RemoteAction closeAction) {
for (PinnedTaskListener listener : mListeners) {
listener.onActionsChanged(actions, closeAction);
}
}
private void onActivityHidden(ComponentName componentName) {
for (PinnedTaskListener listener : mListeners) {
listener.onActivityHidden(componentName);
}
}
private void onAspectRatioChanged(float aspectRatio) {
for (PinnedTaskListener listener : mListeners) {
listener.onAspectRatioChanged(aspectRatio);
}
}
private void onExpandedAspectRatioChanged(float aspectRatio) {
for (PinnedTaskListener listener : mListeners) {
listener.onExpandedAspectRatioChanged(aspectRatio);
}
}
@BinderThread
private class PinnedTaskListenerImpl extends IPinnedTaskListener.Stub {
@Override
@@ -113,36 +92,12 @@ public class PinnedStackListenerForwarder {
});
}
@Override
public void onActionsChanged(ParceledListSlice<RemoteAction> actions,
RemoteAction closeAction) {
mMainExecutor.execute(() -> {
PinnedStackListenerForwarder.this.onActionsChanged(actions, closeAction);
});
}
@Override
public void onActivityHidden(ComponentName componentName) {
mMainExecutor.execute(() -> {
PinnedStackListenerForwarder.this.onActivityHidden(componentName);
});
}
@Override
public void onAspectRatioChanged(float aspectRatio) {
mMainExecutor.execute(() -> {
PinnedStackListenerForwarder.this.onAspectRatioChanged(aspectRatio);
});
}
@Override
public void onExpandedAspectRatioChanged(float aspectRatio) {
mMainExecutor.execute(() -> {
PinnedStackListenerForwarder.this.onExpandedAspectRatioChanged(aspectRatio);
});
}
}
/**
@@ -154,13 +109,6 @@ public class PinnedStackListenerForwarder {
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {}
public void onActionsChanged(ParceledListSlice<RemoteAction> actions,
RemoteAction closeAction) {}
public void onActivityHidden(ComponentName componentName) {}
public void onAspectRatioChanged(float aspectRatio) {}
public void onExpandedAspectRatioChanged(float aspectRatio) {}
}
}

View File

@@ -26,12 +26,13 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import android.annotation.Nullable;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.RemoteAction;
import android.content.pm.ParceledListSlice;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.view.SurfaceControl;
import android.view.WindowManager;
import java.util.List;
/**
* Interface to allow {@link com.android.wm.shell.pip.PipTaskOrganizer} to call into
* PiP menu when certain events happen (task appear/vanish, PiP move, etc.)
@@ -66,7 +67,7 @@ public interface PipMenuController {
/**
* Given a set of actions, update the menu.
*/
void setAppActions(ParceledListSlice<RemoteAction> appActions, RemoteAction closeAction);
void setAppActions(List<RemoteAction> appActions, RemoteAction closeAction);
/**
* Resize the PiP menu with the given bounds. The PiP SurfaceControl is given if there is a

View File

@@ -0,0 +1,125 @@
/*
* Copyright (C) 2022 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.wm.shell.pip;
import android.app.RemoteAction;
import java.util.ArrayList;
import java.util.List;
/**
* Forwards changes to the Picture-in-Picture params to all listeners.
*/
public class PipParamsChangedForwarder {
private final List<PipParamsChangedCallback>
mPipParamsChangedListeners = new ArrayList<>();
/**
* Add a listener that implements at least one of the callbacks.
*/
public void addListener(PipParamsChangedCallback listener) {
if (mPipParamsChangedListeners.contains(listener)) {
return;
}
mPipParamsChangedListeners.add(listener);
}
/**
* Call to notify all listeners of the changed aspect ratio.
*/
public void notifyAspectRatioChanged(float aspectRatio) {
for (PipParamsChangedCallback listener : mPipParamsChangedListeners) {
listener.onAspectRatioChanged(aspectRatio);
}
}
/**
* Call to notify all listeners of the changed expanded aspect ratio.
*/
public void notifyExpandedAspectRatioChanged(float aspectRatio) {
for (PipParamsChangedCallback listener : mPipParamsChangedListeners) {
listener.onExpandedAspectRatioChanged(aspectRatio);
}
}
/**
* Call to notify all listeners of the changed title.
*/
public void notifyTitleChanged(CharSequence title) {
String value = title == null ? null : title.toString();
for (PipParamsChangedCallback listener : mPipParamsChangedListeners) {
listener.onTitleChanged(value);
}
}
/**
* Call to notify all listeners of the changed subtitle.
*/
public void notifySubtitleChanged(CharSequence subtitle) {
String value = subtitle == null ? null : subtitle.toString();
for (PipParamsChangedCallback listener : mPipParamsChangedListeners) {
listener.onSubtitleChanged(value);
}
}
/**
* Call to notify all listeners of the changed app actions or close action.
*/
public void notifyActionsChanged(List<RemoteAction> actions, RemoteAction closeAction) {
for (PipParamsChangedCallback listener : mPipParamsChangedListeners) {
listener.onActionsChanged(actions, closeAction);
}
}
/**
* Contains callbacks for PiP params changes. Subclasses can choose which changes they want to
* listen to by only overriding those selectively.
*/
public interface PipParamsChangedCallback {
/**
* Called if aspect ratio changed.
*/
default void onAspectRatioChanged(float aspectRatio) {
}
/**
* Called if expanded aspect ratio changed.
*/
default void onExpandedAspectRatioChanged(float aspectRatio) {
}
/**
* Called if either the actions or the close action changed.
*/
default void onActionsChanged(List<RemoteAction> actions, RemoteAction closeAction) {
}
/**
* Called if the title changed.
*/
default void onTitleChanged(String title) {
}
/**
* Called if the subtitle changed.
*/
default void onSubtitleChanged(String subtitle) {
}
}
}

View File

@@ -62,7 +62,6 @@ import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Rational;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -127,6 +126,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
private final @NonNull PipMenuController mPipMenuController;
private final PipAnimationController mPipAnimationController;
private final PipTransitionController mPipTransitionController;
protected final PipParamsChangedForwarder mPipParamsChangedForwarder;
private final PipUiEventLogger mPipUiEventLoggerLogger;
private final int mEnterAnimationDuration;
private final int mExitAnimationDuration;
@@ -219,7 +219,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
private long mLastOneShotAlphaAnimationTime;
private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
mSurfaceControlTransactionFactory;
private PictureInPictureParams mPictureInPictureParams;
protected PictureInPictureParams mPictureInPictureParams;
private IntConsumer mOnDisplayIdChangeCallback;
/**
* The end transaction of PiP animation for switching between PiP and fullscreen with
@@ -259,6 +259,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
@NonNull PipAnimationController pipAnimationController,
@NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
@NonNull PipTransitionController pipTransitionController,
@NonNull PipParamsChangedForwarder pipParamsChangedForwarder,
Optional<SplitScreenController> splitScreenOptional,
@NonNull DisplayController displayController,
@NonNull PipUiEventLogger pipUiEventLogger,
@@ -271,6 +272,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
mPipBoundsAlgorithm = boundsHandler;
mPipMenuController = pipMenuController;
mPipTransitionController = pipTransitionController;
mPipParamsChangedForwarder = pipParamsChangedForwarder;
mEnterAnimationDuration = context.getResources()
.getInteger(R.integer.config_pipEnterAnimationDuration);
mExitAnimationDuration = context.getResources()
@@ -559,6 +561,14 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
mPictureInPictureParams = mTaskInfo.pictureInPictureParams;
setBoundsStateForEntry(mTaskInfo.topActivity, mPictureInPictureParams,
mTaskInfo.topActivityInfo);
if (mPictureInPictureParams != null) {
mPipParamsChangedForwarder.notifyActionsChanged(mPictureInPictureParams.getActions(),
mPictureInPictureParams.getCloseAction());
mPipParamsChangedForwarder.notifyTitleChanged(
mPictureInPictureParams.getTitle());
mPipParamsChangedForwarder.notifySubtitleChanged(
mPictureInPictureParams.getSubtitle());
}
mPipUiEventLoggerLogger.setTaskInfo(mTaskInfo);
mPipUiEventLoggerLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_ENTER);
@@ -819,17 +829,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
mPipBoundsState.setOverrideMinSize(
mPipBoundsAlgorithm.getMinimalSize(info.topActivityInfo));
final PictureInPictureParams newParams = info.pictureInPictureParams;
if (newParams == null || !applyPictureInPictureParams(newParams)) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: Ignored onTaskInfoChanged with PiP param: %s", TAG, newParams);
// mPictureInPictureParams is only null if there is no PiP
if (newParams == null || mPictureInPictureParams == null) {
return;
}
// Aspect ratio changed, re-calculate bounds if valid.
final Rect destinationBounds = mPipBoundsAlgorithm.getAdjustedDestinationBounds(
mPipBoundsState.getBounds(), mPipBoundsState.getAspectRatio());
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
scheduleAnimateResizePip(destinationBounds, mEnterAnimationDuration,
null /* updateBoundsCallback */);
applyNewPictureInPictureParams(newParams);
mPictureInPictureParams = newParams;
}
@Override
@@ -1076,20 +1082,19 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
}
/**
* @return {@code true} if the aspect ratio is changed since no other parameters within
* {@link PictureInPictureParams} would affect the bounds.
* Handles all changes to the PictureInPictureParams.
*/
private boolean applyPictureInPictureParams(@NonNull PictureInPictureParams params) {
final Rational currentAspectRatio =
mPictureInPictureParams != null ? mPictureInPictureParams.getAspectRatio()
: null;
final boolean aspectRatioChanged = !Objects.equals(currentAspectRatio,
params.getAspectRatio());
mPictureInPictureParams = params;
if (aspectRatioChanged) {
mPipBoundsState.setAspectRatio(params.getAspectRatioFloat());
protected void applyNewPictureInPictureParams(@NonNull PictureInPictureParams params) {
if (PipUtils.aspectRatioChanged(params.getAspectRatioFloat(),
mPictureInPictureParams.getAspectRatioFloat())) {
mPipParamsChangedForwarder.notifyAspectRatioChanged(params.getAspectRatioFloat());
}
if (PipUtils.remoteActionsChanged(params.getActions(), mPictureInPictureParams.getActions())
|| !PipUtils.remoteActionsMatch(params.getCloseAction(),
mPictureInPictureParams.getCloseAction())) {
mPipParamsChangedForwarder.notifyActionsChanged(params.getActions(),
params.getCloseAction());
}
return aspectRatioChanged;
}
/**

View File

@@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.RemoteAction;
import android.content.ComponentName;
import android.content.Context;
import android.os.RemoteException;
@@ -29,10 +30,16 @@ import android.util.Pair;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import java.util.List;
import java.util.Objects;
/** A class that includes convenience methods. */
public class PipUtils {
private static final String TAG = "PipUtils";
// Minimum difference between two floats (e.g. aspect ratios) to consider them not equal.
private static final double EPSILON = 1e-7;
/**
* @return the ComponentName and user id of the top non-SystemUI activity in the pinned stack.
* The component name may be null if no such activity exists.
@@ -58,4 +65,45 @@ public class PipUtils {
}
return new Pair<>(null, 0);
}
/**
* @return true if the aspect ratios differ
*/
public static boolean aspectRatioChanged(float aspectRatio1, float aspectRatio2) {
return Math.abs(aspectRatio1 - aspectRatio2) > EPSILON;
}
/**
* Checks whether title, description and intent match.
* Comparing icons would be good, but using equals causes false negatives
*/
public static boolean remoteActionsMatch(RemoteAction action1, RemoteAction action2) {
if (action1 == action2) return true;
if (action1 == null || action2 == null) return false;
return Objects.equals(action1.getTitle(), action2.getTitle())
&& Objects.equals(action1.getContentDescription(), action2.getContentDescription())
&& Objects.equals(action1.getActionIntent(), action2.getActionIntent());
}
/**
* Returns true if the actions in the lists match each other according to {@link
* PipUtils#remoteActionsMatch(RemoteAction, RemoteAction)}, including their position.
*/
public static boolean remoteActionsChanged(List<RemoteAction> list1, List<RemoteAction> list2) {
if (list1 == null && list2 == null) {
return false;
}
if (list1 == null || list2 == null) {
return true;
}
if (list1.size() != list2.size()) {
return true;
}
for (int i = 0; i < list1.size(); i++) {
if (!remoteActionsMatch(list1.get(i), list2.get(i))) {
return true;
}
}
return false;
}
}

View File

@@ -22,7 +22,6 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.RemoteAction;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -120,9 +119,11 @@ public class PhonePipMenuController implements PipMenuController {
private final SystemWindows mSystemWindows;
private final Optional<SplitScreenController> mSplitScreenController;
private final PipUiEventLogger mPipUiEventLogger;
private ParceledListSlice<RemoteAction> mAppActions;
private List<RemoteAction> mAppActions;
private RemoteAction mCloseAction;
private ParceledListSlice<RemoteAction> mMediaActions;
private List<RemoteAction> mMediaActions;
private SyncRtSurfaceTransactionApplier mApplier;
private int mMenuState;
@@ -131,7 +132,7 @@ public class PhonePipMenuController implements PipMenuController {
private ActionListener mMediaActionListener = new ActionListener() {
@Override
public void onMediaActionsChanged(List<RemoteAction> mediaActions) {
mMediaActions = new ParceledListSlice<>(mediaActions);
mMediaActions = new ArrayList<>(mediaActions);
updateMenuActions();
}
};
@@ -183,6 +184,9 @@ public class PhonePipMenuController implements PipMenuController {
getPipMenuLayoutParams(MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */),
0, SHELL_ROOT_LAYER_PIP);
setShellRootAccessibilityWindow();
// Make sure the initial actions are set
updateMenuActions();
}
private void detachPipMenuView() {
@@ -457,7 +461,7 @@ public class PhonePipMenuController implements PipMenuController {
* Sets the menu actions to the actions provided by the current PiP menu.
*/
@Override
public void setAppActions(ParceledListSlice<RemoteAction> appActions,
public void setAppActions(List<RemoteAction> appActions,
RemoteAction closeAction) {
mAppActions = appActions;
mCloseAction = closeAction;
@@ -479,7 +483,7 @@ public class PhonePipMenuController implements PipMenuController {
/**
* @return the best set of actions to show in the PiP menu.
*/
private ParceledListSlice<RemoteAction> resolveMenuActions() {
private List<RemoteAction> resolveMenuActions() {
if (isValidActions(mAppActions)) {
return mAppActions;
}
@@ -491,17 +495,16 @@ public class PhonePipMenuController implements PipMenuController {
*/
private void updateMenuActions() {
if (mPipMenuView != null) {
final ParceledListSlice<RemoteAction> menuActions = resolveMenuActions();
mPipMenuView.setActions(mPipBoundsState.getBounds(),
menuActions == null ? null : menuActions.getList(), mCloseAction);
resolveMenuActions(), mCloseAction);
}
}
/**
* Returns whether the set of actions are valid.
*/
private static boolean isValidActions(ParceledListSlice<?> actions) {
return actions != null && actions.getList().size() > 0;
private static boolean isValidActions(List<?> actions) {
return actions != null && actions.size() > 0;
}
/**

View File

@@ -40,7 +40,6 @@ import android.app.RemoteAction;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ParceledListSlice;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.RemoteException;
@@ -80,6 +79,7 @@ import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipMediaController;
import com.android.wm.shell.pip.PipParamsChangedForwarder;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
@@ -88,6 +88,8 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.transition.Transitions;
import java.io.PrintWriter;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
@@ -113,10 +115,12 @@ public class PipController implements PipTransitionController.PipTransitionCallb
private PipTouchHandler mTouchHandler;
private PipTransitionController mPipTransitionController;
private TaskStackListenerImpl mTaskStackListener;
private PipParamsChangedForwarder mPipParamsChangedForwarder;
private Optional<OneHandedController> mOneHandedController;
protected final PipImpl mImpl;
private final Rect mTmpInsetBounds = new Rect();
private final int mEnterAnimationDuration;
private boolean mIsInFixedRotation;
private PipAnimationListener mPinnedStackAnimationRecentsCallback;
@@ -269,12 +273,6 @@ public class PipController implements PipTransitionController.PipTransitionCallb
null /* windowContainerTransaction */);
}
@Override
public void onActionsChanged(ParceledListSlice<RemoteAction> actions,
RemoteAction closeAction) {
mMenuController.setAppActions(actions, closeAction);
}
@Override
public void onActivityHidden(ComponentName componentName) {
if (componentName.equals(mPipBoundsState.getLastPipComponentName())) {
@@ -283,14 +281,6 @@ public class PipController implements PipTransitionController.PipTransitionCallb
mPipBoundsState.setLastPipComponentName(null);
}
}
@Override
public void onAspectRatioChanged(float aspectRatio) {
// TODO(b/169373982): Remove this callback as it is redundant with PipTaskOrg params
// change.
mPipBoundsState.setAspectRatio(aspectRatio);
mTouchHandler.onAspectRatioChanged();
}
}
/**
@@ -305,6 +295,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
PipTouchHandler pipTouchHandler, PipTransitionController pipTransitionController,
WindowManagerShellWrapper windowManagerShellWrapper,
TaskStackListenerImpl taskStackListener,
PipParamsChangedForwarder pipParamsChangedForwarder,
Optional<OneHandedController> oneHandedController,
ShellExecutor mainExecutor) {
if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
@@ -315,8 +306,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb
return new PipController(context, displayController, pipAppOpsListener, pipBoundsAlgorithm,
pipKeepClearAlgorithm, pipBoundsState, pipMotionHelper, pipMediaController,
phonePipMenuController, pipTaskOrganizer, pipTouchHandler, pipTransitionController,
windowManagerShellWrapper, taskStackListener, oneHandedController, mainExecutor)
phonePipMenuController, pipTaskOrganizer, pipTouchHandler, pipTransitionController,
windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder,
oneHandedController, mainExecutor)
.mImpl;
}
@@ -334,6 +326,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
PipTransitionController pipTransitionController,
WindowManagerShellWrapper windowManagerShellWrapper,
TaskStackListenerImpl taskStackListener,
PipParamsChangedForwarder pipParamsChangedForwarder,
Optional<OneHandedController> oneHandedController,
ShellExecutor mainExecutor
) {
@@ -360,6 +353,11 @@ public class PipController implements PipTransitionController.PipTransitionCallb
mOneHandedController = oneHandedController;
mPipTransitionController = pipTransitionController;
mTaskStackListener = taskStackListener;
mEnterAnimationDuration = mContext.getResources()
.getInteger(R.integer.config_pipEnterAnimationDuration);
mPipParamsChangedForwarder = pipParamsChangedForwarder;
//TODO: move this to ShellInit when PipController can be injected
mMainExecutor.execute(this::init);
}
@@ -457,6 +455,34 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
});
mPipParamsChangedForwarder.addListener(
new PipParamsChangedForwarder.PipParamsChangedCallback() {
@Override
public void onAspectRatioChanged(float ratio) {
mPipBoundsState.setAspectRatio(ratio);
final Rect destinationBounds =
mPipBoundsAlgorithm.getAdjustedDestinationBounds(
mPipBoundsState.getBounds(),
mPipBoundsState.getAspectRatio());
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
mPipTaskOrganizer.scheduleAnimateResizePip(destinationBounds,
mEnterAnimationDuration,
null /* updateBoundsCallback */);
mTouchHandler.onAspectRatioChanged();
updateMovementBounds(null /* toBounds */, false /* fromRotation */,
false /* fromImeAdjustment */, false /* fromShelfAdjustment */,
null /* windowContainerTransaction */);
}
@Override
public void onActionsChanged(List<RemoteAction> actions,
RemoteAction closeAction) {
mMenuController.setAppActions(actions, closeAction);
}
});
mOneHandedController.ifPresent(controller -> {
controller.asOneHanded().registerTransitionCallback(
new OneHandedTransitionCallback() {

View File

@@ -77,6 +77,9 @@ public class TvPipBoundsState extends PipBoundsState {
public void setBoundsStateForEntry(ComponentName componentName, ActivityInfo activityInfo,
PictureInPictureParams params, PipBoundsAlgorithm pipBoundsAlgorithm) {
super.setBoundsStateForEntry(componentName, activityInfo, params, pipBoundsAlgorithm);
if (params == null) {
return;
}
setDesiredTvExpandedAspectRatio(params.getExpandedAspectRatioFloat(), true);
}

View File

@@ -27,7 +27,6 @@ import android.app.RemoteAction;
import android.app.TaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
@@ -48,6 +47,7 @@ import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipMediaController;
import com.android.wm.shell.pip.PipParamsChangedForwarder;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip.tv.TvPipKeepClearAlgorithm.Placement;
@@ -55,6 +55,7 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Set;
/**
@@ -66,7 +67,6 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
private static final String TAG = "TvPipController";
static final boolean DEBUG = false;
private static final double EPS = 1e-7;
private static final int NONEXISTENT_TASK_ID = -1;
@Retention(RetentionPolicy.SOURCE)
@@ -127,6 +127,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
PipMediaController pipMediaController,
TvPipNotificationController pipNotificationController,
TaskStackListenerImpl taskStackListener,
PipParamsChangedForwarder pipParamsChangedForwarder,
DisplayController displayController,
WindowManagerShellWrapper wmShell,
ShellExecutor mainExecutor,
@@ -141,6 +142,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
pipMediaController,
pipNotificationController,
taskStackListener,
pipParamsChangedForwarder,
displayController,
wmShell,
mainExecutor,
@@ -157,6 +159,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
PipMediaController pipMediaController,
TvPipNotificationController pipNotificationController,
TaskStackListenerImpl taskStackListener,
PipParamsChangedForwarder pipParamsChangedForwarder,
DisplayController displayController,
WindowManagerShellWrapper wmShell,
ShellExecutor mainExecutor,
@@ -183,6 +186,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
loadConfigurations();
registerPipParamsChangedListener(pipParamsChangedForwarder);
registerTaskStackListenerCallback(taskStackListener);
registerWmShellPinnedStackListener(wmShell);
displayController.addDisplayWindowListener(this);
@@ -540,6 +544,72 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
});
}
private void registerPipParamsChangedListener(PipParamsChangedForwarder provider) {
provider.addListener(new PipParamsChangedForwarder.PipParamsChangedCallback() {
@Override
public void onActionsChanged(List<RemoteAction> actions,
RemoteAction closeAction) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: onActionsChanged()", TAG);
mTvPipMenuController.setAppActions(actions, closeAction);
mCloseAction = closeAction;
}
@Override
public void onAspectRatioChanged(float ratio) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: onAspectRatioChanged: %f", TAG, ratio);
mTvPipBoundsState.setAspectRatio(ratio);
if (!mTvPipBoundsState.isTvPipExpanded()) {
updatePinnedStackBounds();
}
}
@Override
public void onExpandedAspectRatioChanged(float ratio) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: onExpandedAspectRatioChanged: %f", TAG, ratio);
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(ratio, false);
// 1) PiP is expanded and only aspect ratio changed, but wasn't disabled
// --> update bounds, but don't toggle
if (mTvPipBoundsState.isTvPipExpanded() && ratio != 0) {
mTvPipBoundsAlgorithm.updateExpandedPipSize();
updatePinnedStackBounds();
}
// 2) PiP is expanded, but expanded PiP was disabled
// --> collapse PiP
if (mTvPipBoundsState.isTvPipExpanded() && ratio == 0) {
int saveGravity = mTvPipBoundsAlgorithm
.updateGravityOnExpandToggled(mPreviousGravity, false);
if (saveGravity != Gravity.NO_GRAVITY) {
mPreviousGravity = saveGravity;
}
mTvPipBoundsState.setTvPipExpanded(false);
updatePinnedStackBounds();
}
// 3) PiP not expanded and not manually collapsed and expand was enabled
// --> expand to new ratio
if (!mTvPipBoundsState.isTvPipExpanded() && ratio != 0
&& !mTvPipBoundsState.isTvPipManuallyCollapsed()) {
mTvPipBoundsAlgorithm.updateExpandedPipSize();
int saveGravity = mTvPipBoundsAlgorithm
.updateGravityOnExpandToggled(mPreviousGravity, true);
if (saveGravity != Gravity.NO_GRAVITY) {
mPreviousGravity = saveGravity;
}
mTvPipBoundsState.setTvPipExpanded(true);
updatePinnedStackBounds();
}
}
});
}
private void registerWmShellPinnedStackListener(WindowManagerShellWrapper wmShell) {
try {
wmShell.addPinnedStackListener(new PinnedStackListenerForwarder.PinnedTaskListener() {
@@ -563,86 +633,6 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
updatePinnedStackBounds();
}
}
@Override
public void onAspectRatioChanged(float ratio) {
if (DEBUG) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: onAspectRatioChanged: %f", TAG, ratio);
}
boolean ratioChanged = mTvPipBoundsState.getAspectRatio() != ratio;
mTvPipBoundsState.setAspectRatio(ratio);
if (!mTvPipBoundsState.isTvPipExpanded() && ratioChanged) {
updatePinnedStackBounds();
}
}
@Override
public void onExpandedAspectRatioChanged(float ratio) {
if (DEBUG) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: onExpandedAspectRatioChanged: %f", TAG, ratio);
}
// 0) No update to the ratio --> don't do anything
if (Math.abs(mTvPipBoundsState.getDesiredTvExpandedAspectRatio() - ratio)
< EPS) {
return;
}
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(ratio, false);
// 1) PiP is expanded and only aspect ratio changed, but wasn't disabled
// --> update bounds, but don't toggle
if (mTvPipBoundsState.isTvPipExpanded() && ratio != 0) {
mTvPipBoundsAlgorithm.updateExpandedPipSize();
updatePinnedStackBounds();
}
// 2) PiP is expanded, but expanded PiP was disabled
// --> collapse PiP
if (mTvPipBoundsState.isTvPipExpanded() && ratio == 0) {
int saveGravity = mTvPipBoundsAlgorithm
.updateGravityOnExpandToggled(mPreviousGravity, false);
if (saveGravity != Gravity.NO_GRAVITY) {
mPreviousGravity = saveGravity;
}
mTvPipBoundsState.setTvPipExpanded(false);
updatePinnedStackBounds();
}
// 3) PiP not expanded and not manually collapsed and expand was enabled
// --> expand to new ratio
if (!mTvPipBoundsState.isTvPipExpanded() && ratio != 0
&& !mTvPipBoundsState.isTvPipManuallyCollapsed()) {
mTvPipBoundsAlgorithm.updateExpandedPipSize();
int saveGravity = mTvPipBoundsAlgorithm
.updateGravityOnExpandToggled(mPreviousGravity, true);
if (saveGravity != Gravity.NO_GRAVITY) {
mPreviousGravity = saveGravity;
}
mTvPipBoundsState.setTvPipExpanded(true);
updatePinnedStackBounds();
}
}
@Override
public void onMovementBoundsChanged(boolean fromImeAdjustment) {}
@Override
public void onActionsChanged(ParceledListSlice<RemoteAction> actions,
RemoteAction closeAction) {
if (DEBUG) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: onActionsChanged()", TAG);
}
mTvPipMenuController.setAppActions(actions, closeAction);
mCloseAction = closeAction;
}
});
} catch (RemoteException e) {
ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,

View File

@@ -24,7 +24,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ParceledListSlice;
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Rect;
@@ -169,6 +168,7 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
mPipMenuView.setListener(this);
setUpViewSurfaceZOrder(mPipMenuView, 1);
addPipMenuViewToSystemWindows(mPipMenuView, MENU_WINDOW_TITLE);
maybeUpdateMenuViewActions();
}
private void attachPipBackgroundView() {
@@ -336,12 +336,12 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
}
@Override
public void setAppActions(ParceledListSlice<RemoteAction> actions, RemoteAction closeAction) {
public void setAppActions(List<RemoteAction> actions, RemoteAction closeAction) {
if (DEBUG) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: setAppActions()", TAG);
}
updateAdditionalActionsList(mAppActions, actions.getList(), closeAction);
updateAdditionalActionsList(mAppActions, actions, closeAction);
}
private void onMediaActionsChanged(List<RemoteAction> actions) {

View File

@@ -53,12 +53,12 @@ import androidx.annotation.Nullable;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.R;
import com.android.wm.shell.pip.PipUtils;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* A View that represents Pip Menu on TV. It's responsible for displaying 3 ever-present Pip Menu
@@ -398,7 +398,7 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
final TvPipMenuActionButton button = mAdditionalButtons.get(index);
// Remove action if it matches the custom close action.
if (actionsMatch(action, closeAction)) {
if (PipUtils.remoteActionsMatch(action, closeAction)) {
button.setVisibility(GONE);
continue;
}
@@ -406,18 +406,6 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
}
}
/**
* Checks whether title, description and intent match.
* Comparing icons would be good, but using equals causes false negatives
*/
private boolean actionsMatch(RemoteAction action1, RemoteAction action2) {
if (action1 == action2) return true;
if (action1 == null || action2 == null) return false;
return Objects.equals(action1.getTitle(), action2.getTitle())
&& Objects.equals(action1.getContentDescription(), action2.getContentDescription())
&& Objects.equals(action1.getActionIntent(), action2.getActionIntent());
}
private void setActionForButton(RemoteAction action, TvPipMenuActionButton button,
Handler mainHandler) {
button.setVisibility(View.VISIBLE); // Ensure the button is visible.

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2022 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.wm.shell.pip.tv;
import android.app.PictureInPictureParams;
import android.content.Context;
import androidx.annotation.NonNull;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipMenuController;
import com.android.wm.shell.pip.PipParamsChangedForwarder;
import com.android.wm.shell.pip.PipSurfaceTransactionHelper;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip.PipTransitionState;
import com.android.wm.shell.pip.PipUiEventLogger;
import com.android.wm.shell.pip.PipUtils;
import com.android.wm.shell.splitscreen.SplitScreenController;
import java.util.Objects;
import java.util.Optional;
/**
* TV specific changes to the PipTaskOrganizer.
*/
public class TvPipTaskOrganizer extends PipTaskOrganizer {
public TvPipTaskOrganizer(Context context,
@NonNull SyncTransactionQueue syncTransactionQueue,
@NonNull PipTransitionState pipTransitionState,
@NonNull PipBoundsState pipBoundsState,
@NonNull PipBoundsAlgorithm boundsHandler,
@NonNull PipMenuController pipMenuController,
@NonNull PipAnimationController pipAnimationController,
@NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
@NonNull PipTransitionController pipTransitionController,
@NonNull PipParamsChangedForwarder pipParamsChangedForwarder,
Optional<SplitScreenController> splitScreenOptional,
@NonNull DisplayController displayController,
@NonNull PipUiEventLogger pipUiEventLogger,
@NonNull ShellTaskOrganizer shellTaskOrganizer,
ShellExecutor mainExecutor) {
super(context, syncTransactionQueue, pipTransitionState, pipBoundsState, boundsHandler,
pipMenuController, pipAnimationController, surfaceTransactionHelper,
pipTransitionController, pipParamsChangedForwarder, splitScreenOptional,
displayController, pipUiEventLogger, shellTaskOrganizer, mainExecutor);
}
@Override
protected void applyNewPictureInPictureParams(@NonNull PictureInPictureParams params) {
super.applyNewPictureInPictureParams(params);
if (PipUtils.aspectRatioChanged(params.getExpandedAspectRatioFloat(),
mPictureInPictureParams.getExpandedAspectRatioFloat())) {
mPipParamsChangedForwarder.notifyExpandedAspectRatioChanged(
params.getExpandedAspectRatioFloat());
}
if (!Objects.equals(params.getTitle(), mPictureInPictureParams.getTitle())) {
mPipParamsChangedForwarder.notifyTitleChanged(params.getTitle());
}
if (!Objects.equals(params.getSubtitle(), mPictureInPictureParams.getSubtitle())) {
mPipParamsChangedForwarder.notifySubtitleChanged(params.getSubtitle());
}
}
}

View File

@@ -81,6 +81,7 @@ public class PipTaskOrganizerTest extends ShellTestCase {
private PipBoundsState mPipBoundsState;
private PipTransitionState mPipTransitionState;
private PipBoundsAlgorithm mPipBoundsAlgorithm;
private PipParamsChangedForwarder mPipParamsChangedForwarder;
private ComponentName mComponent1;
private ComponentName mComponent2;
@@ -97,11 +98,10 @@ public class PipTaskOrganizerTest extends ShellTestCase {
mMainExecutor = new TestShellExecutor();
mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mContext,
mMockSyncTransactionQueue, mPipTransitionState, mPipBoundsState,
mPipBoundsAlgorithm, mMockPhonePipMenuController,
mMockPipAnimationController, mMockPipSurfaceTransactionHelper,
mMockPipTransitionController, mMockOptionalSplitScreen,
mMockDisplayController, mMockPipUiEventLogger,
mMockShellTaskOrganizer, mMainExecutor));
mPipBoundsAlgorithm, mMockPhonePipMenuController, mMockPipAnimationController,
mMockPipSurfaceTransactionHelper, mMockPipTransitionController,
mPipParamsChangedForwarder, mMockOptionalSplitScreen, mMockDisplayController,
mMockPipUiEventLogger, mMockShellTaskOrganizer, mMainExecutor));
mMainExecutor.flushAll();
preparePipTaskOrg();
}

View File

@@ -48,6 +48,7 @@ import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipMediaController;
import com.android.wm.shell.pip.PipParamsChangedForwarder;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
@@ -86,6 +87,7 @@ public class PipControllerTest extends ShellTestCase {
@Mock private TaskStackListenerImpl mMockTaskStackListener;
@Mock private ShellExecutor mMockExecutor;
@Mock private Optional<OneHandedController> mMockOneHandedController;
@Mock private PipParamsChangedForwarder mPipParamsChangedForwarder;
@Mock private DisplayLayout mMockDisplayLayout1;
@Mock private DisplayLayout mMockDisplayLayout2;
@@ -102,7 +104,8 @@ public class PipControllerTest extends ShellTestCase {
mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController,
mMockPhonePipMenuController, mMockPipTaskOrganizer, mMockPipTouchHandler,
mMockPipTransitionController, mMockWindowManagerShellWrapper,
mMockTaskStackListener, mMockOneHandedController, mMockExecutor);
mMockTaskStackListener, mPipParamsChangedForwarder, mMockOneHandedController,
mMockExecutor);
when(mMockPipBoundsAlgorithm.getSnapAlgorithm()).thenReturn(mMockPipSnapAlgorithm);
when(mMockPipTouchHandler.getMotionHelper()).thenReturn(mMockPipMotionHelper);
}
@@ -134,7 +137,8 @@ public class PipControllerTest extends ShellTestCase {
mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController,
mMockPhonePipMenuController, mMockPipTaskOrganizer, mMockPipTouchHandler,
mMockPipTransitionController, mMockWindowManagerShellWrapper,
mMockTaskStackListener, mMockOneHandedController, mMockExecutor));
mMockTaskStackListener, mPipParamsChangedForwarder, mMockOneHandedController,
mMockExecutor));
}
@Test

View File

@@ -739,20 +739,7 @@ class ActivityClientController extends IActivityClientController.Stub {
synchronized (mGlobalLock) {
final ActivityRecord r = ensureValidPictureInPictureActivityParams(
"setPictureInPictureParams", token, params);
// Only update the saved args from the args that are set.
r.setPictureInPictureParams(params);
if (r.inPinnedWindowingMode()) {
// If the activity is already in picture-in-picture, update the pinned task now
// if it is not already expanding to fullscreen. Otherwise, the arguments will
// be used the next time the activity enters PiP.
final Task rootTask = r.getRootTask();
rootTask.setPictureInPictureAspectRatio(
r.pictureInPictureArgs.getAspectRatioFloat(),
r.pictureInPictureArgs.getExpandedAspectRatioFloat());
rootTask.setPictureInPictureActions(r.pictureInPictureArgs.getActions(),
r.pictureInPictureArgs.getCloseAction());
}
}
} finally {
Binder.restoreCallingIdentity(origId);

View File

@@ -148,7 +148,6 @@ import android.app.PendingIntent;
import android.app.PictureInPictureParams;
import android.app.PictureInPictureUiState;
import android.app.ProfilerInfo;
import android.app.RemoteAction;
import android.app.WaitResult;
import android.app.admin.DevicePolicyCache;
import android.app.assist.AssistContent;
@@ -3471,19 +3470,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
Slog.e(TAG, "Skip enterPictureInPictureMode, destroyed " + r);
return;
}
// Only update the saved args from the args that are set
r.setPictureInPictureParams(params);
final float aspectRatio = r.pictureInPictureArgs.getAspectRatioFloat();
final float expandedAspectRatio =
r.pictureInPictureArgs.getExpandedAspectRatioFloat();
final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
final RemoteAction closeAction = r.pictureInPictureArgs.getCloseAction();
mRootWindowContainer.moveActivityToPinnedRootTask(r,
null /* launchIntoPipHostActivity */, "enterPictureInPictureMode");
final Task task = r.getTask();
task.setPictureInPictureAspectRatio(aspectRatio, expandedAspectRatio);
task.setPictureInPictureActions(actions, closeAction);
// Continue the pausing process after entering pip.
if (task.getPausingActivity() == r) {
task.schedulePauseActivity(r, false /* userLeaving */,

View File

@@ -22,9 +22,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.app.PictureInPictureParams;
import android.app.RemoteAction;
import android.content.ComponentName;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.Matrix;
@@ -40,8 +38,6 @@ import android.view.SurfaceControl;
import android.window.PictureInPictureSurfaceTransaction;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
* Holds the common state of the pinned task between the system and SystemUI. If SystemUI ever
@@ -90,12 +86,6 @@ class PinnedTaskController {
private boolean mIsImeShowing;
private int mImeHeight;
// The set of actions and aspect-ratio for the that are currently allowed on the PiP activity
private ArrayList<RemoteAction> mActions = new ArrayList<>();
private RemoteAction mCloseAction;
private float mAspectRatio = -1f;
private float mExpandedAspectRatio = 0f;
// The aspect ratio bounds of the PIP.
private float mMinAspectRatio;
private float mMaxAspectRatio;
@@ -155,7 +145,6 @@ class PinnedTaskController {
mPinnedTaskListener = listener;
notifyImeVisibilityChanged(mIsImeShowing, mImeHeight);
notifyMovementBoundsChanged(false /* fromImeAdjustment */);
notifyActionsChanged(mActions, mCloseAction);
} catch (RemoteException e) {
Log.e(TAG, "Failed to register pinned task listener", e);
}
@@ -369,55 +358,6 @@ class PinnedTaskController {
notifyMovementBoundsChanged(true /* fromImeAdjustment */);
}
/**
* Sets the current aspect ratio.
*/
void setAspectRatio(float aspectRatio) {
if (Float.compare(mAspectRatio, aspectRatio) != 0) {
mAspectRatio = aspectRatio;
notifyAspectRatioChanged(aspectRatio);
notifyMovementBoundsChanged(false /* fromImeAdjustment */);
}
}
/**
* @return the current aspect ratio.
*/
float getAspectRatio() {
return mAspectRatio;
}
/**
* Sets the current aspect ratio.
*/
void setExpandedAspectRatio(float aspectRatio) {
if (Float.compare(mExpandedAspectRatio, aspectRatio) != 0) {
mExpandedAspectRatio = aspectRatio;
notifyExpandedAspectRatioChanged(aspectRatio);
notifyMovementBoundsChanged(false /* fromImeAdjustment */);
}
}
/**
* @return the current aspect ratio.
*/
float getExpandedAspectRatio() {
return mExpandedAspectRatio;
}
/**
* Sets the current set of actions.
*/
void setActions(List<RemoteAction> actions, RemoteAction closeAction) {
mActions.clear();
if (actions != null) {
mActions.addAll(actions);
}
mCloseAction = closeAction;
notifyActionsChanged(mActions, closeAction);
}
/**
* Notifies listeners that the PIP needs to be adjusted for the IME.
*/
@@ -431,37 +371,6 @@ class PinnedTaskController {
}
}
private void notifyAspectRatioChanged(float aspectRatio) {
if (mPinnedTaskListener == null) return;
try {
mPinnedTaskListener.onAspectRatioChanged(aspectRatio);
} catch (RemoteException e) {
Slog.e(TAG_WM, "Error delivering aspect ratio changed event.", e);
}
}
private void notifyExpandedAspectRatioChanged(float aspectRatio) {
if (mPinnedTaskListener == null) return;
try {
mPinnedTaskListener.onExpandedAspectRatioChanged(aspectRatio);
} catch (RemoteException e) {
Slog.e(TAG_WM, "Error delivering aspect ratio changed event.", e);
}
}
/**
* Notifies listeners that the PIP actions have changed.
*/
private void notifyActionsChanged(List<RemoteAction> actions, RemoteAction closeAction) {
if (mPinnedTaskListener != null) {
try {
mPinnedTaskListener.onActionsChanged(new ParceledListSlice(actions), closeAction);
} catch (RemoteException e) {
Slog.e(TAG_WM, "Error delivering actions changed event.", e);
}
}
}
/**
* Notifies listeners that the PIP movement bounds have changed.
*/
@@ -490,19 +399,7 @@ class PinnedTaskController {
}
pw.println(prefix + " mIsImeShowing=" + mIsImeShowing);
pw.println(prefix + " mImeHeight=" + mImeHeight);
pw.println(prefix + " mAspectRatio=" + mAspectRatio);
pw.println(prefix + " mMinAspectRatio=" + mMinAspectRatio);
pw.println(prefix + " mMaxAspectRatio=" + mMaxAspectRatio);
if (mActions.isEmpty()) {
pw.println(prefix + " mActions=[]");
} else {
pw.println(prefix + " mActions=[");
for (int i = 0; i < mActions.size(); i++) {
RemoteAction action = mActions.get(i);
pw.print(prefix + " Action[" + i + "]: ");
action.dump("", pw);
}
pw.println(prefix + " ]");
}
}
}

View File

@@ -149,7 +149,6 @@ import android.app.ActivityTaskManager;
import android.app.AppGlobals;
import android.app.IActivityController;
import android.app.PictureInPictureParams;
import android.app.RemoteAction;
import android.app.TaskInfo;
import android.app.WindowConfiguration;
import android.content.ComponentName;
@@ -218,7 +217,6 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -6076,58 +6074,6 @@ class Task extends TaskFragment {
}
}
/**
* Sets the current picture-in-picture aspect ratios.
*/
void setPictureInPictureAspectRatio(float aspectRatio, float expandedAspectRatio) {
if (!mWmService.mAtmService.mSupportsPictureInPicture) {
return;
}
final DisplayContent displayContent = getDisplayContent();
if (displayContent == null) {
return;
}
if (!inPinnedWindowingMode()) {
return;
}
final PinnedTaskController pinnedTaskController =
getDisplayContent().getPinnedTaskController();
// Notify the pinned stack controller about aspect ratio change.
// This would result a callback delivered from SystemUI to WM to start animation,
// if the bounds are ought to be altered due to aspect ratio change.
if (Float.compare(aspectRatio, pinnedTaskController.getAspectRatio()) != 0) {
pinnedTaskController.setAspectRatio(
pinnedTaskController.isValidPictureInPictureAspectRatio(aspectRatio)
? aspectRatio : -1f);
}
if (mWmService.mAtmService.mSupportsExpandedPictureInPicture && Float.compare(
expandedAspectRatio, pinnedTaskController.getExpandedAspectRatio()) != 0) {
pinnedTaskController.setExpandedAspectRatio(pinnedTaskController
.isValidExpandedPictureInPictureAspectRatio(expandedAspectRatio)
? expandedAspectRatio : 0f);
}
}
/**
* Sets the current picture-in-picture actions.
*/
void setPictureInPictureActions(List<RemoteAction> actions, RemoteAction closeAction) {
if (!mWmService.mAtmService.mSupportsPictureInPicture) {
return;
}
if (!inPinnedWindowingMode()) {
return;
}
getDisplayContent().getPinnedTaskController().setActions(actions, closeAction);
}
public DisplayInfo getDisplayInfo() {
return mDisplayContent.getDisplayInfo();
}