Merge changes from topic "pip_migration_8"

* changes:
  Use consumer to dispatch signal between Launcher & SysUI OPS Pip(8-2/N)
  Re-landing Decouple systemui shared componements from PipController(8/N)
This commit is contained in:
TreeHugger Robot
2020-09-24 11:33:23 +00:00
committed by Android (Google) Code Review
29 changed files with 674 additions and 502 deletions

View File

@@ -33,7 +33,6 @@ import android.view.WindowManagerGlobal;
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
import com.android.systemui.shared.recents.view.RecentsTransition;
import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
public class WindowManagerWrapper {
@@ -75,7 +74,7 @@ public class WindowManagerWrapper {
WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
public static final int WINDOWING_MODE_MULTI_WINDOW =
WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
public static final int WINDOWING_MODE_PINNED = WindowConfiguration.WINDOWING_MODE_PINNED;
public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY =
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY =
@@ -84,13 +83,6 @@ public class WindowManagerWrapper {
private static final WindowManagerWrapper sInstance = new WindowManagerWrapper();
/**
* Forwarder to which we can add multiple pinned stack listeners. Each listener will receive
* updates from the window manager service.
*/
private PinnedStackListenerForwarder mPinnedStackListenerForwarder =
new PinnedStackListenerForwarder();
public static WindowManagerWrapper getInstance() {
return sInstance;
}
@@ -187,23 +179,6 @@ public class WindowManagerWrapper {
return NAV_BAR_POS_INVALID;
}
/**
* Adds a pinned stack listener, which will receive updates from the window manager service
* along with any other pinned stack listeners that were added via this method.
*/
public void addPinnedStackListener(PinnedStackListener listener) throws RemoteException {
mPinnedStackListenerForwarder.addListener(listener);
WindowManagerGlobal.getWindowManagerService().registerPinnedStackListener(
DEFAULT_DISPLAY, mPinnedStackListenerForwarder);
}
/**
* Removes a pinned stack listener.
*/
public void removePinnedStackListener(PinnedStackListener listener) {
mPinnedStackListenerForwarder.removeListener(listener);
}
/**
* Mirrors a specified display. The SurfaceControl returned is the root of the mirrored
* hierarchy.

View File

@@ -33,7 +33,6 @@ import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_CONTROLLER;
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
@@ -91,7 +90,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.PinnedStackListenerForwarder;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
@@ -115,6 +113,7 @@ import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.systemui.wmshell.WindowManagerShellWrapper;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -366,6 +365,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
INotificationManager notificationManager,
@Nullable IStatusBarService statusBarService,
WindowManager windowManager,
WindowManagerShellWrapper windowManagerShellWrapper,
LauncherApps launcherApps) {
dumpManager.registerDumpable(TAG, this);
mContext = context;
@@ -441,7 +441,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
try {
WindowManagerWrapper.getInstance().addPinnedStackListener(new BubblesImeListener());
windowManagerShellWrapper.addPinnedStackListener(new BubblesImeListener());
} catch (RemoteException e) {
e.printStackTrace();
}

View File

@@ -40,6 +40,7 @@ import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.systemui.wmshell.WindowManagerShellWrapper;
import dagger.Module;
import dagger.Provides;
@@ -73,6 +74,7 @@ public interface BubbleModule {
INotificationManager notifManager,
IStatusBarService statusBarService,
WindowManager windowManager,
WindowManagerShellWrapper windowManagerShellWrapper,
LauncherApps launcherApps) {
return new BubbleController(
context,
@@ -96,6 +98,7 @@ public interface BubbleModule {
notifManager,
statusBarService,
windowManager,
windowManagerShellWrapper,
launcherApps);
}
}

View File

@@ -66,6 +66,7 @@ import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -312,6 +313,13 @@ public class DependencyProvider {
/** */
@Provides
public WindowManagerWrapper providesWindowManagerWrapper() {
return WindowManagerWrapper.getInstance();
}
/** */
@Provides
@SysUISingleton
public SystemActions providesSystemActions(Context context) {
return new SystemActions(context);
}

View File

@@ -16,23 +16,20 @@
package com.android.systemui.pip;
import android.content.res.Configuration;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.media.session.MediaController;
import com.android.systemui.pip.phone.PipTouchHandler;
import com.android.systemui.pip.tv.PipController;
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
import java.io.PrintWriter;
import java.util.function.Consumer;
/**
* Interface to engage picture in picture feature.
*/
public interface Pip {
/**
* Called when showing Pip menu.
*/
void showPictureInPictureMenu();
/**
* Registers {@link com.android.systemui.pip.tv.PipController.Listener} that gets called.
* whenever receiving notification on changes in PIP.
@@ -52,6 +49,14 @@ public interface Pip {
default void closePip() {
}
/**
* Dump the current state and information if need.
*
* @param pw The stream to dump information to.
*/
default void dump(PrintWriter pw) {
}
/**
* Expand PIP, it's possible that specific request to activate the window via Alt-tab.
*/
@@ -64,7 +69,11 @@ public interface Pip {
* @return The state of defined in PipController.
*/
default int getPlaybackState() {
return 0;
return -1;
}
default PipTouchHandler getPipTouchHandler() {
return null;
}
/**
@@ -95,9 +104,61 @@ public interface Pip {
}
/**
* Called when configuration change invoked.
* Called whenever an Activity is moved to the pinned stack from another stack.
*/
void onConfigurationChanged(Configuration newConfig);
default void onActivityPinned(String packageName) {
}
/**
* Called whenever an Activity is moved from the pinned stack to another stack
*/
default void onActivityUnpinned(ComponentName topActivity) {
}
/**
* Called whenever IActivityManager.startActivity is called on an activity that is already
* running, but the task is either brought to the front or a new Intent is delivered to it.
*
* @param task information about the task the activity was relaunched into
* @param clearedTask whether or not the launch activity also cleared the task as a part of
* starting
*/
default void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
boolean clearedTask) {
}
/**
* Called when display size or font size of settings changed
*/
default void onDensityOrFontScaleChanged() {
}
/**
* Called when overlay package change invoked.
*/
default void onOverlayChanged() {
}
/**
* Registers the session listener for the current user.
*/
default void registerSessionListenerForCurrentUser() {
}
/**
* Called when SysUI state changed.
*
* @param isSysUiStateValid Is SysUI state valid or not.
* @param flag Current SysUI state.
*/
default void onSystemUiStateChanged(boolean isSysUiStateValid, int flag) {
}
/**
* Called when task stack changed.
*/
default void onTaskStackChanged() {
}
/**
* Removes a {@link PipController.Listener} from PipController.
@@ -136,6 +197,14 @@ public interface Pip {
default void setShelfHeight(boolean visible, int height) {
}
/**
* Registers the pinned stack animation listener.
*
* @param callback The callback of pinned stack animation.
*/
default void setPinnedStackAnimationListener(Consumer<Boolean> callback) {
}
/**
* Set the pinned stack with {@link PipAnimationController.AnimationType}
*
@@ -145,12 +214,9 @@ public interface Pip {
}
/**
* Registers the pinned stack animation listener.
*
* @param listener The listener of pinned stack animation.
* Called when showing Pip menu.
*/
default void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) {
}
void showPictureInPictureMenu();
/**
* Suspends resizing operation on the Pip until {@link #resumePipResizing} is called.
@@ -159,12 +225,4 @@ public interface Pip {
*/
default void suspendPipResizing(int reason) {
}
/**
* Dump the current state and information if need.
*
* @param pw The stream to dump information to.
*/
default void dump(PrintWriter pw) {
}
}

View File

@@ -24,16 +24,14 @@ import android.graphics.RectF;
import android.view.SurfaceControl;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.wm.shell.R;
/**
* Abstracts the common operations on {@link SurfaceControl.Transaction} for PiP transition.
*/
@SysUISingleton
public class PipSurfaceTransactionHelper implements ConfigurationController.ConfigurationListener {
public class PipSurfaceTransactionHelper {
private final Context mContext;
private final boolean mEnableCornerRadius;
private int mCornerRadius;
@@ -44,17 +42,21 @@ public class PipSurfaceTransactionHelper implements ConfigurationController.Conf
private final RectF mTmpDestinationRectF = new RectF();
private final Rect mTmpDestinationRect = new Rect();
public PipSurfaceTransactionHelper(Context context, ConfigurationController configController) {
public PipSurfaceTransactionHelper(Context context) {
final Resources res = context.getResources();
mContext = context;
mEnableCornerRadius = res.getBoolean(R.bool.config_pipEnableRoundCorner);
configController.addCallback(this);
}
@Override
public void onDensityOrFontScaleChanged() {
final Resources res = mContext.getResources();
mCornerRadius = res.getDimensionPixelSize(R.dimen.pip_corner_radius);
/**
* Called when display size or font size of settings changed
*
* @param context the current context
*/
public void onDensityOrFontScaleChanged(Context context) {
if (mEnableCornerRadius) {
final Resources res = context.getResources();
mCornerRadius = res.getDimensionPixelSize(R.dimen.pip_corner_radius);
}
}
/**

View File

@@ -130,7 +130,6 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
}
}
private final Context mContext;
private final Handler mMainHandler;
private final Handler mUpdateHandler;
private final PipBoundsHandler mPipBoundsHandler;
@@ -249,7 +248,6 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
@NonNull DisplayController displayController,
@NonNull PipUiEventLogger pipUiEventLogger,
@NonNull ShellTaskOrganizer shellTaskOrganizer) {
mContext = context;
mMainHandler = new Handler(Looper.getMainLooper());
mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks);
mPipBoundsHandler = boundsHandler;
@@ -565,8 +563,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
if (Looper.getMainLooper() != Looper.myLooper()) {
throw new RuntimeException("PipMenuView needs to be attached on the main thread.");
}
mPipViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(),
final Context context = menuView.getContext();
mPipViewHost = new SurfaceControlViewHost(context, context.getDisplay(),
(android.os.Binder) null);
mPipMenuSurface = mPipViewHost.getSurfacePackage().getSurfaceControl();
SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
@@ -658,6 +656,13 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
mShouldDeferEnteringPip = false;
}
/**
* Called when display size or font size of settings changed
*/
public void onDensityOrFontScaleChanged(Context context) {
mSurfaceTransactionHelper.onDensityOrFontScaleChanged(context);
}
/**
* TODO(b/152809058): consolidate the display info handling logic in SysUI
*

View File

@@ -16,55 +16,37 @@
package com.android.systemui.pip.phone;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static com.android.systemui.pip.PipAnimationController.isOutPipDirection;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.IActivityManager;
import android.app.RemoteAction;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import android.util.Pair;
import android.view.DisplayInfo;
import android.view.IPinnedStackController;
import android.window.WindowContainerTransaction;
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.model.SysUiState;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.pip.PipUiEventLogger;
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.systemui.shared.system.PinnedStackListenerForwarder;
import com.android.systemui.wmshell.WindowManagerShellWrapper;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
import java.io.PrintWriter;
import java.util.function.Consumer;
/**
* Manages the picture-in-picture (PIP) UI and states for Phones.
@@ -74,7 +56,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
private static final String TAG = "PipController";
private Context mContext;
private IActivityManager mActivityManager;
private Handler mHandler = new Handler();
private final DisplayInfo mTmpDisplayInfo = new DisplayInfo();
@@ -83,13 +64,13 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
protected final Rect mReentryBounds = new Rect();
private DisplayController mDisplayController;
private InputConsumerController mInputConsumerController;
private PipAppOpsListener mAppOpsListener;
private PipBoundsHandler mPipBoundsHandler;
private PipMediaController mMediaController;
private PipTouchHandler mTouchHandler;
private PipSurfaceTransactionHelper mPipSurfaceTransactionHelper;
private IPinnedStackAnimationListener mPinnedStackAnimationRecentsListener;
private Consumer<Boolean> mPinnedStackAnimationRecentsCallback;
private WindowManagerShellWrapper mWindowManagerShellWrapper;
private boolean mIsInFixedRotation;
protected PipMenuActivityController mMenuController;
@@ -155,51 +136,11 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
}
};
/**
* Handler for system task stack changes.
*/
private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
mTouchHandler.onActivityPinned();
mMediaController.onActivityPinned();
mMenuController.onActivityPinned();
mAppOpsListener.onActivityPinned(packageName);
Dependency.get(UiOffloadThread.class).execute(() -> {
WindowManagerWrapper.getInstance().setPipVisibility(true);
});
}
@Override
public void onActivityUnpinned() {
final Pair<ComponentName, Integer> topPipActivityInfo = PipUtils.getTopPipActivity(
mContext, mActivityManager);
final ComponentName topActivity = topPipActivityInfo.first;
mMenuController.onActivityUnpinned();
mTouchHandler.onActivityUnpinned(topActivity);
mAppOpsListener.onActivityUnpinned();
Dependency.get(UiOffloadThread.class).execute(() -> {
WindowManagerWrapper.getInstance().setPipVisibility(topActivity != null);
});
}
@Override
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
if (task.configuration.windowConfiguration.getWindowingMode()
!= WINDOWING_MODE_PINNED) {
return;
}
mTouchHandler.getMotionHelper().expandLeavePip(clearedTask /* skipAnimation */);
}
};
/**
* Handler for messages from the PIP controller.
*/
private class PipControllerPinnedStackListener extends PinnedStackListener {
private class PipControllerPinnedStackListener extends
PinnedStackListenerForwarder.PinnedStackListener {
@Override
public void onListenerRegistered(IPinnedStackController controller) {
mHandler.post(() -> mTouchHandler.setPinnedStackController(controller));
@@ -237,7 +178,10 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
@Override
public void onConfigurationChanged() {
mHandler.post(() -> mPipBoundsHandler.onConfigurationChanged(mContext));
mHandler.post(() -> {
mPipBoundsHandler.onConfigurationChanged(mContext);
mTouchHandler.onConfigurationChanged();
});
}
@Override
@@ -249,52 +193,36 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
}
}
public ConfigurationController.ConfigurationListener mOverlayChangedListener =
new ConfigurationController.ConfigurationListener() {
@Override
public void onOverlayChanged() {
mHandler.post(() -> {
mPipBoundsHandler.onOverlayChanged(mContext, mContext.getDisplay());
updateMovementBounds(null /* toBounds */,
false /* fromRotation */, false /* fromImeAdjustment */,
false /* fromShelfAdjustment */,
null /* windowContainerTransaction */);
});
}
};
public PipController(Context context, BroadcastDispatcher broadcastDispatcher,
ConfigurationController configController,
DeviceConfigProxy deviceConfig,
public PipController(Context context,
DisplayController displayController,
FloatingContentCoordinator floatingContentCoordinator,
SysUiState sysUiState,
PipAppOpsListener pipAppOpsListener,
PipBoundsHandler pipBoundsHandler,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
PipMediaController pipMediaController,
PipMenuActivityController pipMenuActivityController,
PipTaskOrganizer pipTaskOrganizer,
PipUiEventLogger pipUiEventLogger) {
PipTouchHandler pipTouchHandler,
WindowManagerShellWrapper windowManagerShellWrapper
) {
mContext = context;
mActivityManager = ActivityManager.getService();
if (PipUtils.hasSystemFeature(mContext)) {
initController(context, broadcastDispatcher, configController, deviceConfig,
displayController, floatingContentCoordinator, sysUiState, pipBoundsHandler,
pipSurfaceTransactionHelper, pipTaskOrganizer, pipUiEventLogger);
initController(context, displayController, pipAppOpsListener, pipBoundsHandler,
pipMediaController, pipMenuActivityController, pipTaskOrganizer,
pipTouchHandler, windowManagerShellWrapper);
} else {
Log.w(TAG, "Device not support PIP feature");
}
}
private void initController(Context context, BroadcastDispatcher broadcastDispatcher,
ConfigurationController configController,
DeviceConfigProxy deviceConfig,
private void initController(Context context,
DisplayController displayController,
FloatingContentCoordinator floatingContentCoordinator,
SysUiState sysUiState,
PipAppOpsListener pipAppOpsListener,
PipBoundsHandler pipBoundsHandler,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
PipMediaController pipMediaController,
PipMenuActivityController pipMenuActivityController,
PipTaskOrganizer pipTaskOrganizer,
PipUiEventLogger pipUiEventLogger) {
PipTouchHandler pipTouchHandler,
WindowManagerShellWrapper windowManagerShellWrapper) {
// Ensure that we are the primary user's SystemUI.
final int processUser = UserManager.get(context).getUserHandle();
@@ -302,28 +230,15 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
throw new IllegalStateException("Non-primary Pip component not currently supported.");
}
try {
WindowManagerWrapper.getInstance().addPinnedStackListener(
new PipControllerPinnedStackListener());
} catch (RemoteException e) {
Log.e(TAG, "Failed to register pinned stack listener", e);
}
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
mWindowManagerShellWrapper = windowManagerShellWrapper;
mDisplayController = displayController;
mPipBoundsHandler = pipBoundsHandler;
mPipSurfaceTransactionHelper = pipSurfaceTransactionHelper;
mPipTaskOrganizer = pipTaskOrganizer;
mPipTaskOrganizer.registerPipTransitionCallback(this);
mInputConsumerController = InputConsumerController.getPipInputConsumer();
mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher);
mMenuController = new PipMenuActivityController(context,
mMediaController, mInputConsumerController, mPipTaskOrganizer);
mTouchHandler = new PipTouchHandler(context, mActivityManager,
mMenuController, mInputConsumerController, mPipBoundsHandler, mPipTaskOrganizer,
floatingContentCoordinator, deviceConfig, sysUiState, pipUiEventLogger);
mAppOpsListener = new PipAppOpsListener(context, mActivityManager,
mTouchHandler.getMotionHelper());
mMediaController = pipMediaController;
mMenuController = pipMenuActivityController;
mTouchHandler = pipTouchHandler;
mAppOpsListener = pipAppOpsListener;
displayController.addDisplayChangingController(mRotationController);
displayController.addDisplayWindowListener(mFixedRotationListener);
@@ -333,26 +248,69 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
context.getDisplay().getDisplayInfo(displayInfo);
mPipBoundsHandler.onDisplayInfoChanged(displayInfo);
configController.addCallback(mOverlayChangedListener);
try {
RootTaskInfo taskInfo = ActivityTaskManager.getService().getRootTaskInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
if (taskInfo != null) {
// If SystemUI restart, and it already existed a pinned stack,
// register the pip input consumer to ensure touch can send to it.
mInputConsumerController.registerInputConsumer(true /* withSfVsync */);
}
} catch (RemoteException | UnsupportedOperationException e) {
e.printStackTrace();
mWindowManagerShellWrapper.addPinnedStackListener(
new PipControllerPinnedStackListener());
} catch (RemoteException e) {
Log.e(TAG, "Failed to register pinned stack listener", e);
}
}
/**
* Updates the PIP per configuration changed.
*/
public void onConfigurationChanged(Configuration newConfig) {
mTouchHandler.onConfigurationChanged();
@Override
public void onDensityOrFontScaleChanged() {
mHandler.post(() -> {
mPipTaskOrganizer.onDensityOrFontScaleChanged(mContext);
});
}
@Override
public void onActivityPinned(String packageName) {
mHandler.post(() -> {
mTouchHandler.onActivityPinned();
mMediaController.onActivityPinned();
mMenuController.onActivityPinned();
mAppOpsListener.onActivityPinned(packageName);
});
}
@Override
public void onActivityUnpinned(ComponentName topActivity) {
mHandler.post(() -> {
mMenuController.onActivityUnpinned();
mTouchHandler.onActivityUnpinned(topActivity);
mAppOpsListener.onActivityUnpinned();
});
}
@Override
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
boolean clearedTask) {
if (task.configuration.windowConfiguration.getWindowingMode()
!= WINDOWING_MODE_PINNED) {
return;
}
mTouchHandler.getMotionHelper().expandLeavePip(clearedTask /* skipAnimation */);
}
@Override
public void onOverlayChanged() {
mHandler.post(() -> {
mPipBoundsHandler.onOverlayChanged(mContext, mContext.getDisplay());
updateMovementBounds(null /* toBounds */,
false /* fromRotation */, false /* fromImeAdjustment */,
false /* fromShelfAdjustment */,
null /* windowContainerTransaction */);
});
}
@Override
public void registerSessionListenerForCurrentUser() {
mMediaController.registerSessionListenerForCurrentUser();
}
@Override
public void onSystemUiStateChanged(boolean isValidState, int flag) {
mTouchHandler.onSystemUiStateChanged(isValidState);
}
/**
@@ -363,6 +321,11 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
mTouchHandler.getMotionHelper().expandLeavePip(false /* skipAnimation */);
}
@Override
public PipTouchHandler getPipTouchHandler() {
return mTouchHandler;
}
/**
* Hides the PIP menu.
*/
@@ -408,8 +371,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
}
@Override
public void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) {
mHandler.post(() -> mPinnedStackAnimationRecentsListener = listener);
public void setPinnedStackAnimationListener(Consumer<Boolean> callback) {
mHandler.post(() -> mPinnedStackAnimationRecentsCallback = callback);
}
@Override
@@ -421,12 +384,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
}
// Disable touches while the animation is running
mTouchHandler.setTouchEnabled(false);
if (mPinnedStackAnimationRecentsListener != null) {
try {
mPinnedStackAnimationRecentsListener.onPinnedStackAnimationStarted();
} catch (RemoteException e) {
Log.e(TAG, "Failed to callback recents", e);
}
if (mPinnedStackAnimationRecentsCallback != null) {
mPinnedStackAnimationRecentsCallback.accept(true);
}
}
@@ -477,7 +436,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
public void dump(PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG);
mInputConsumerController.dump(pw, innerPrefix);
mMenuController.dump(pw, innerPrefix);
mTouchHandler.dump(pw, innerPrefix);
mPipBoundsHandler.dump(pw, innerPrefix);

View File

@@ -26,19 +26,14 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.MediaSessionManager.OnActiveSessionsChangedListener;
import android.media.session.PlaybackState;
import android.os.UserHandle;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.policy.UserInfoController;
import java.util.ArrayList;
import java.util.Collections;
@@ -101,17 +96,11 @@ public class PipMediaController {
};
private final MediaSessionManager.OnActiveSessionsChangedListener mSessionsChangedListener =
new OnActiveSessionsChangedListener() {
@Override
public void onActiveSessionsChanged(List<MediaController> controllers) {
resolveActiveMediaController(controllers);
}
};
controllers -> resolveActiveMediaController(controllers);
private ArrayList<ActionListener> mListeners = new ArrayList<>();
public PipMediaController(Context context, IActivityManager activityManager,
BroadcastDispatcher broadcastDispatcher) {
public PipMediaController(Context context, IActivityManager activityManager) {
mContext = context;
mActivityManager = activityManager;
IntentFilter mediaControlFilter = new IntentFilter();
@@ -119,16 +108,12 @@ public class PipMediaController {
mediaControlFilter.addAction(ACTION_PAUSE);
mediaControlFilter.addAction(ACTION_NEXT);
mediaControlFilter.addAction(ACTION_PREV);
broadcastDispatcher.registerReceiver(mPlayPauseActionReceiver, mediaControlFilter);
mContext.registerReceiver(mPlayPauseActionReceiver, mediaControlFilter,
UserHandle.USER_ALL);
createMediaActions();
mMediaSessionManager =
(MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
// The media session listener needs to be re-registered when switching users
UserInfoController userInfoController = Dependency.get(UserInfoController.class);
userInfoController.addCallback((String name, Drawable picture, String userAccount) ->
registerSessionListenerForCurrentUser());
}
/**
@@ -220,7 +205,7 @@ public class PipMediaController {
/**
* Re-registers the session listener for the current user.
*/
private void registerSessionListenerForCurrentUser() {
public void registerSessionListenerForCurrentUser() {
mMediaSessionManager.removeOnActiveSessionsChangedListener(mSessionsChangedListener);
mMediaSessionManager.addOnActiveSessionsChangedListener(mSessionsChangedListener, null,
UserHandle.USER_CURRENT, null);

View File

@@ -34,7 +34,6 @@ import android.view.WindowManager;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.pip.phone.PipMediaController.ActionListener;
import com.android.systemui.shared.system.InputConsumerController;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -86,7 +85,6 @@ public class PipMenuActivityController {
private Context mContext;
private PipTaskOrganizer mPipTaskOrganizer;
private PipMediaController mMediaController;
private InputConsumerController mInputConsumerController;
private ArrayList<Listener> mListeners = new ArrayList<>();
private ParceledListSlice<RemoteAction> mAppActions;
@@ -104,12 +102,9 @@ public class PipMenuActivityController {
};
public PipMenuActivityController(Context context,
PipMediaController mediaController, InputConsumerController inputConsumerController,
PipTaskOrganizer pipTaskOrganizer
) {
PipMediaController mediaController, PipTaskOrganizer pipTaskOrganizer) {
mContext = context;
mMediaController = mediaController;
mInputConsumerController = inputConsumerController;
mPipTaskOrganizer = pipTaskOrganizer;
}
@@ -119,12 +114,10 @@ public class PipMenuActivityController {
public void onActivityPinned() {
attachPipMenuView();
mInputConsumerController.registerInputConsumer(true /* withSfVsync */);
}
public void onActivityUnpinned() {
hideMenu();
mInputConsumerController.unregisterInputConsumer();
mPipTaskOrganizer.detachPipMenuViewHost();
mPipMenuView = null;
}

View File

@@ -21,13 +21,6 @@ import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_LEFT;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_RIGHT;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_TOP;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_GLOBAL_ACTIONS_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
import android.content.Context;
import android.content.res.Resources;
@@ -50,11 +43,9 @@ import android.view.ScaleGestureDetector;
import android.view.ViewConfiguration;
import com.android.internal.policy.TaskResizingAlgorithm;
import com.android.systemui.model.SysUiState;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.pip.PipUiEventLogger;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.wm.shell.R;
import java.io.PrintWriter;
@@ -71,21 +62,11 @@ public class PipResizeGestureHandler {
private static final float PINCH_THRESHOLD = 0.05f;
private static final float STARTING_SCALE_FACTOR = 1.0f;
private static final int INVALID_SYSUI_STATE_MASK =
SYSUI_STATE_GLOBAL_ACTIONS_SHOWING
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
| SYSUI_STATE_BOUNCER_SHOWING
| SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
| SYSUI_STATE_BUBBLES_EXPANDED
| SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
private final Context mContext;
private final PipBoundsHandler mPipBoundsHandler;
private final PipMotionHelper mMotionHelper;
private final int mDisplayId;
private final Executor mMainExecutor;
private final SysUiState mSysUiState;
private final ScaleGestureDetector mScaleGestureDetector;
private final Region mTmpRegion = new Region();
@@ -110,6 +91,7 @@ public class PipResizeGestureHandler {
private boolean mIsAttached;
private boolean mIsEnabled;
private boolean mEnablePinchResize;
private boolean mIsSysUiStateValid;
private boolean mThresholdCrossed;
private boolean mUsingPinchToZoom = false;
private float mScaleFactor = STARTING_SCALE_FACTOR;
@@ -123,9 +105,8 @@ public class PipResizeGestureHandler {
private int mCtrlType;
public PipResizeGestureHandler(Context context, PipBoundsHandler pipBoundsHandler,
PipMotionHelper motionHelper, DeviceConfigProxy deviceConfig,
PipTaskOrganizer pipTaskOrganizer, Function<Rect, Rect> movementBoundsSupplier,
Runnable updateMovementBoundsRunnable, SysUiState sysUiState,
PipMotionHelper motionHelper, PipTaskOrganizer pipTaskOrganizer,
Function<Rect, Rect> movementBoundsSupplier, Runnable updateMovementBoundsRunnable,
PipUiEventLogger pipUiEventLogger, PipMenuActivityController menuActivityController) {
mContext = context;
mDisplayId = context.getDisplayId();
@@ -135,7 +116,6 @@ public class PipResizeGestureHandler {
mPipTaskOrganizer = pipTaskOrganizer;
mMovementBoundsSupplier = movementBoundsSupplier;
mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable;
mSysUiState = sysUiState;
mPipMenuActivityController = menuActivityController;
mPipUiEventLogger = pipUiEventLogger;
@@ -202,7 +182,7 @@ public class PipResizeGestureHandler {
DeviceConfig.NAMESPACE_SYSTEMUI,
PIP_PINCH_RESIZE,
/* defaultValue = */ false);
deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, mMainExecutor,
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, mMainExecutor,
new DeviceConfig.OnPropertiesChangedListener() {
@Override
public void onPropertiesChanged(DeviceConfig.Properties properties) {
@@ -218,6 +198,15 @@ public class PipResizeGestureHandler {
reloadResources();
}
/**
* Called when SysUI state changed.
*
* @param isSysUiStateValid Is SysUI valid or not.
*/
public void onSystemUiStateChanged(boolean isSysUiStateValid) {
mIsSysUiStateValid = isSysUiStateValid;
}
private void reloadResources() {
final Resources res = mContext.getResources();
mDelta = res.getDimensionPixelSize(R.dimen.pip_resize_edge_size);
@@ -401,7 +390,7 @@ public class PipResizeGestureHandler {
}
private boolean isInValidSysUiState() {
return (mSysUiState.getFlags() & INVALID_SYSUI_STATE_MASK) == 0;
return mIsSysUiStateValid;
}
private void onDragCornerResize(MotionEvent ev) {

View File

@@ -23,7 +23,6 @@ import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STAT
import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
import android.annotation.SuppressLint;
import android.app.IActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
@@ -57,13 +56,10 @@ import androidx.dynamicanimation.animation.SpringForce;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
import com.android.systemui.model.SysUiState;
import com.android.systemui.pip.PipAnimationController;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.pip.PipUiEventLogger;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.DismissCircleView;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.systemui.util.animation.PhysicsAnimator;
@@ -92,7 +88,6 @@ public class PipTouchHandler {
private final boolean mEnableResize;
private final Context mContext;
private final WindowManager mWindowManager;
private final IActivityManager mActivityManager;
private final PipBoundsHandler mPipBoundsHandler;
private final PipUiEventLogger mPipUiEventLogger;
@@ -216,18 +211,14 @@ public class PipTouchHandler {
}
@SuppressLint("InflateParams")
public PipTouchHandler(Context context, IActivityManager activityManager,
public PipTouchHandler(Context context,
PipMenuActivityController menuController,
InputConsumerController inputConsumerController,
PipBoundsHandler pipBoundsHandler,
PipTaskOrganizer pipTaskOrganizer,
FloatingContentCoordinator floatingContentCoordinator,
DeviceConfigProxy deviceConfig,
SysUiState sysUiState,
PipUiEventLogger pipUiEventLogger) {
// Initialize the Pip input consumer
mContext = context;
mActivityManager = activityManager;
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
mPipBoundsHandler = pipBoundsHandler;
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
@@ -238,22 +229,18 @@ public class PipTouchHandler {
mPipBoundsHandler.getSnapAlgorithm(), floatingContentCoordinator);
mPipResizeGestureHandler =
new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper,
deviceConfig, pipTaskOrganizer, this::getMovementBounds,
this::updateMovementBounds, sysUiState, pipUiEventLogger, menuController);
pipTaskOrganizer, this::getMovementBounds,
this::updateMovementBounds, pipUiEventLogger, menuController);
mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler,
() -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(),
true /* allowMenuTimeout */, willResizeMenu(), shouldShowResizeHandle()),
menuController::hideMenu);
menuController::hideMenu);
Resources res = context.getResources();
mEnableDismissDragToEdge = res.getBoolean(R.bool.config_pipEnableDismissDragToEdge);
mEnableResize = res.getBoolean(R.bool.config_pipEnableResizeForMenu);
reloadResources();
// Register the listener for input consumer touch events
inputConsumerController.setInputListener(this::handleTouchEvent);
inputConsumerController.setRegistrationListener(this::onRegistrationChanged);
mFloatingContentCoordinator = floatingContentCoordinator;
mConnection = new PipAccessibilityInteractionConnection(mContext, mMotionHelper,
pipTaskOrganizer, mPipBoundsHandler.getSnapAlgorithm(),
@@ -320,15 +307,12 @@ public class PipTouchHandler {
DeviceConfig.NAMESPACE_SYSTEMUI,
PIP_STASHING,
/* defaultValue = */ false);
deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
context.getMainExecutor(),
new DeviceConfig.OnPropertiesChangedListener() {
@Override
public void onPropertiesChanged(DeviceConfig.Properties properties) {
if (properties.getKeyset().contains(PIP_STASHING)) {
mEnableStash = properties.getBoolean(
PIP_STASHING, /* defaultValue = */ false);
}
properties -> {
if (properties.getKeyset().contains(PIP_STASHING)) {
mEnableStash = properties.getBoolean(
PIP_STASHING, /* defaultValue = */ false);
}
});
}
@@ -438,6 +422,15 @@ public class PipTouchHandler {
mShelfHeight = shelfHeight;
}
/**
* Called when SysUI state changed.
*
* @param isSysUiStateValid Is SysUI valid or not.
*/
public void onSystemUiStateChanged(boolean isSysUiStateValid) {
mPipResizeGestureHandler.onSystemUiStateChanged(isSysUiStateValid);
}
public void adjustBoundsForRotation(Rect outBounds, Rect curBounds, Rect insetBounds) {
final Rect toMovementBounds = new Rect();
mPipBoundsHandler.getSnapAlgorithm().getMovementBounds(outBounds, insetBounds,
@@ -648,7 +641,10 @@ public class PipTouchHandler {
}
}
private void onRegistrationChanged(boolean isRegistered) {
/**
* TODO Add appropriate description
*/
public void onRegistrationChanged(boolean isRegistered) {
mAccessibilityManager.setPictureInPictureActionReplacingConnection(isRegistered
? mConnection : null);
if (!isRegistered && mTouchState.isUserInteracting()) {
@@ -664,7 +660,10 @@ public class PipTouchHandler {
shouldShowResizeHandle());
}
private boolean handleTouchEvent(InputEvent inputEvent) {
/**
* TODO Add appropriate description
*/
public boolean handleTouchEvent(InputEvent inputEvent) {
// Skip any non motion events
if (!(inputEvent instanceof MotionEvent)) {
return true;

View File

@@ -20,7 +20,7 @@ import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.IActivityTaskManager;
@@ -45,23 +45,16 @@ import android.text.TextUtils;
import android.util.Log;
import android.view.DisplayInfo;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.shared.system.PinnedStackListenerForwarder;
import com.android.systemui.wmshell.WindowManagerShellWrapper;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* Manages the picture-in-picture (PIP) UI and states.
@@ -113,7 +106,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
private Context mContext;
private PipBoundsHandler mPipBoundsHandler;
private PipTaskOrganizer mPipTaskOrganizer;
private PipSurfaceTransactionHelper mPipSurfaceTransactionHelper;
private IActivityTaskManager mActivityTaskManager;
private MediaSessionManager mMediaSessionManager;
private int mState = STATE_NO_PIP;
@@ -133,6 +125,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
private String[] mLastPackagesResourceGranted;
private PipNotification mPipNotification;
private ParceledListSlice<RemoteAction> mCustomActions;
private WindowManagerShellWrapper mWindowManagerShellWrapper;
private int mResizeAnimationDuration;
// Used to calculate the movement bounds
@@ -143,21 +136,9 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
private boolean mImeVisible;
private int mImeHeightAdjustment;
private final PinnedStackListener mPinnedStackListener = new PipControllerPinnedStackListener();
private final Runnable mResizePinnedStackRunnable = new Runnable() {
@Override
public void run() {
resizePinnedStack(mResumeResizePinnedStackRunnableState);
}
};
private final Runnable mClosePipRunnable = new Runnable() {
@Override
public void run() {
closePip();
}
};
private final Runnable mResizePinnedStackRunnable =
() -> resizePinnedStack(mResumeResizePinnedStackRunnableState);
private final Runnable mClosePipRunnable = () -> closePip();
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -175,17 +156,23 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
}
};
private final MediaSessionManager.OnActiveSessionsChangedListener mActiveMediaSessionListener =
new MediaSessionManager.OnActiveSessionsChangedListener() {
@Override
public void onActiveSessionsChanged(List<MediaController> controllers) {
updateMediaController(controllers);
}
};
controllers -> updateMediaController(controllers);
private final PinnedStackListenerForwarder.PinnedStackListener mPinnedStackListener =
new PipControllerPinnedStackListener();
@Override
public void registerSessionListenerForCurrentUser() {
// TODO Need confirm if TV have to re-registers when switch user
mMediaSessionManager.removeOnActiveSessionsChangedListener(mActiveMediaSessionListener);
mMediaSessionManager.addOnActiveSessionsChangedListener(mActiveMediaSessionListener, null,
UserHandle.USER_CURRENT, null);
}
/**
* Handler for messages from the PIP controller.
*/
private class PipControllerPinnedStackListener extends PinnedStackListener {
private class PipControllerPinnedStackListener extends
PinnedStackListenerForwarder.PinnedStackListener {
@Override
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
mHandler.post(() -> {
@@ -227,18 +214,18 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
}
}
public PipController(Context context, BroadcastDispatcher broadcastDispatcher,
public PipController(Context context,
PipBoundsHandler pipBoundsHandler,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
PipTaskOrganizer pipTaskOrganizer) {
PipTaskOrganizer pipTaskOrganizer,
WindowManagerShellWrapper windowManagerShellWrapper
) {
if (mInitialized) {
return;
}
mInitialized = true;
mContext = context;
mPipNotification = new PipNotification(context, broadcastDispatcher,
Optional.of(this).get());
mPipNotification = new PipNotification(context, this);
mPipBoundsHandler = pipBoundsHandler;
// Ensure that we have the display info in case we get calls to update the bounds before the
// listener calls back
@@ -248,15 +235,12 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
mResizeAnimationDuration = context.getResources()
.getInteger(R.integer.config_pipResizeAnimationDuration);
mPipSurfaceTransactionHelper = pipSurfaceTransactionHelper;
mPipTaskOrganizer = pipTaskOrganizer;
mPipTaskOrganizer.registerPipTransitionCallback(this);
mActivityTaskManager = ActivityTaskManager.getService();
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
broadcastDispatcher.registerReceiver(mBroadcastReceiver, intentFilter,
null /* handler */, UserHandle.ALL);
mContext.registerReceiver(mBroadcastReceiver, intentFilter, UserHandle.USER_ALL);
// Initialize the last orientation and apply the current configuration
Configuration initialConfig = mContext.getResources().getConfiguration();
@@ -265,10 +249,10 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
mMediaSessionManager =
(MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
mWindowManagerShellWrapper = windowManagerShellWrapper;
try {
WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener);
} catch (RemoteException | UnsupportedOperationException e) {
mWindowManagerShellWrapper.addPinnedStackListener(mPinnedStackListener);
} catch (RemoteException e) {
Log.e(TAG, "Failed to register pinned stack listener", e);
}
}
@@ -344,7 +328,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
mListeners.get(i).onPipActivityClosed();
}
mHandler.removeCallbacks(mClosePipRunnable);
updatePipVisibility(false);
}
/**
@@ -358,7 +341,77 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
mListeners.get(i).onMoveToFullscreen();
}
resizePinnedStack(STATE_NO_PIP);
updatePipVisibility(false);
}
@Override
public void onActivityPinned(String packageName) {
if (DEBUG) Log.d(TAG, "onActivityPinned()");
RootTaskInfo taskInfo = getPinnedTaskInfo();
if (taskInfo == null) {
Log.w(TAG, "Cannot find pinned stack");
return;
}
if (DEBUG) Log.d(TAG, "PINNED_STACK:" + taskInfo);
mPinnedStackId = taskInfo.taskId;
mPipTaskId = taskInfo.childTaskIds[taskInfo.childTaskIds.length - 1];
mPipComponentName = ComponentName.unflattenFromString(
taskInfo.childTaskNames[taskInfo.childTaskNames.length - 1]);
// Set state to STATE_PIP so we show it when the pinned stack animation ends.
mState = STATE_PIP;
mMediaSessionManager.addOnActiveSessionsChangedListener(
mActiveMediaSessionListener, null);
updateMediaController(mMediaSessionManager.getActiveSessions(null));
for (int i = mListeners.size() - 1; i >= 0; i--) {
mListeners.get(i).onPipEntered(packageName);
}
}
@Override
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
boolean clearedTask) {
if (task.configuration.windowConfiguration.getWindowingMode()
!= WINDOWING_MODE_PINNED) {
return;
}
if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()");
// If PIPed activity is launched again by Launcher or intent, make it fullscreen.
movePipToFullscreen();
}
@Override
public void onTaskStackChanged() {
if (DEBUG) Log.d(TAG, "onTaskStackChanged()");
if (getState() != STATE_NO_PIP) {
boolean hasPip = false;
RootTaskInfo taskInfo = getPinnedTaskInfo();
if (taskInfo == null || taskInfo.childTaskIds == null) {
Log.w(TAG, "There is nothing in pinned stack");
closePipInternal(false);
return;
}
for (int i = taskInfo.childTaskIds.length - 1; i >= 0; --i) {
if (taskInfo.childTaskIds[i] == mPipTaskId) {
// PIP task is still alive.
hasPip = true;
break;
}
}
if (!hasPip) {
// PIP task doesn't exist anymore in PINNED_STACK.
closePipInternal(true);
return;
}
}
if (getState() == STATE_PIP) {
if (mPipBounds != mDefaultPipBounds) {
mPipBounds = mDefaultPipBounds;
resizePinnedStack(STATE_PIP);
}
}
}
/**
@@ -603,80 +656,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
return PLAYBACK_STATE_UNAVAILABLE;
}
private TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
public void onTaskStackChanged() {
if (DEBUG) Log.d(TAG, "onTaskStackChanged()");
if (getState() != STATE_NO_PIP) {
boolean hasPip = false;
RootTaskInfo taskInfo = getPinnedTaskInfo();
if (taskInfo == null || taskInfo.childTaskIds == null) {
Log.w(TAG, "There is nothing in pinned stack");
closePipInternal(false);
return;
}
for (int i = taskInfo.childTaskIds.length - 1; i >= 0; --i) {
if (taskInfo.childTaskIds[i] == mPipTaskId) {
// PIP task is still alive.
hasPip = true;
break;
}
}
if (!hasPip) {
// PIP task doesn't exist anymore in PINNED_STACK.
closePipInternal(true);
return;
}
}
if (getState() == STATE_PIP) {
if (mPipBounds != mDefaultPipBounds) {
mPipBounds = mDefaultPipBounds;
resizePinnedStack(STATE_PIP);
}
}
}
@Override
public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
if (DEBUG) Log.d(TAG, "onActivityPinned()");
RootTaskInfo taskInfo = getPinnedTaskInfo();
if (taskInfo == null) {
Log.w(TAG, "Cannot find pinned stack");
return;
}
if (DEBUG) Log.d(TAG, "PINNED_STACK:" + taskInfo);
mPinnedStackId = taskInfo.taskId;
mPipTaskId = taskInfo.childTaskIds[taskInfo.childTaskIds.length - 1];
mPipComponentName = ComponentName.unflattenFromString(
taskInfo.childTaskNames[taskInfo.childTaskNames.length - 1]);
// Set state to STATE_PIP so we show it when the pinned stack animation ends.
mState = STATE_PIP;
mMediaSessionManager.addOnActiveSessionsChangedListener(
mActiveMediaSessionListener, null);
updateMediaController(mMediaSessionManager.getActiveSessions(null));
for (int i = mListeners.size() - 1; i >= 0; i--) {
mListeners.get(i).onPipEntered(packageName);
}
updatePipVisibility(true);
}
@Override
public void onActivityRestartAttempt(RunningTaskInfo task, boolean homeTaskVisible,
boolean clearedTask, boolean wasVisible) {
if (task.configuration.windowConfiguration.getWindowingMode()
!= WINDOWING_MODE_PINNED) {
return;
}
if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()");
// If PIPed activity is launched again by Launcher or intent, make it fullscreen.
movePipToFullscreen();
}
};
@Override
public void onPipTransitionStarted(ComponentName activity, int direction, Rect pipBounds) {
}
@@ -730,12 +709,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
void onMediaControllerChanged();
}
private void updatePipVisibility(final boolean visible) {
Dependency.get(UiOffloadThread.class).execute(() -> {
WindowManagerWrapper.getInstance().setPipVisibility(visible);
});
}
private String getStateDescription() {
if (mSuspendPipResizingReason == 0) {
return stateToName(mState);

View File

@@ -147,9 +147,10 @@ public class PipControlsViewController {
return;
}
mPipOptional.ifPresent(pip -> {
if (pip.getPlaybackState() == PipController.PLAYBACK_STATE_PAUSED) {
final int playbackState = pip.getPlaybackState();
if (playbackState == PipController.PLAYBACK_STATE_PAUSED) {
mMediaController.getTransportControls().play();
} else if (pip.getPlaybackState() == PipController.PLAYBACK_STATE_PLAYING) {
} else if (playbackState == PipController.PLAYBACK_STATE_PLAYING) {
mMediaController.getTransportControls().pause();
}
});

View File

@@ -32,11 +32,11 @@ import android.graphics.Bitmap;
import android.media.MediaMetadata;
import android.media.session.MediaController;
import android.media.session.PlaybackState;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.util.NotificationChannels;
import com.android.wm.shell.R;
@@ -163,8 +163,7 @@ public class PipNotification {
}
};
public PipNotification(Context context, BroadcastDispatcher broadcastDispatcher,
PipController pipController) {
public PipNotification(Context context, PipController pipController) {
mPackageManager = context.getPackageManager();
mNotificationManager = (NotificationManager) context.getSystemService(
@@ -185,7 +184,7 @@ public class PipNotification {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_MENU);
intentFilter.addAction(ACTION_CLOSE);
broadcastDispatcher.registerReceiver(mEventReceiver, intentFilter);
context.registerReceiver(mEventReceiver, intentFilter, UserHandle.USER_ALL);
onConfigurationChanged(context);
}

View File

@@ -19,7 +19,6 @@ package com.android.systemui.pip.tv.dagger;
import android.app.Activity;
import android.content.Context;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipBoundsHandler;
@@ -29,6 +28,7 @@ import com.android.systemui.pip.PipUiEventLogger;
import com.android.systemui.pip.tv.PipController;
import com.android.systemui.pip.tv.PipMenuActivity;
import com.android.systemui.pip.tv.PipNotification;
import com.android.systemui.wmshell.WindowManagerShellWrapper;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.splitscreen.SplitScreen;
@@ -56,20 +56,18 @@ public abstract class TvPipModule {
@SysUISingleton
@Provides
static Pip providePipController(Context context,
BroadcastDispatcher broadcastDispatcher,
PipBoundsHandler pipBoundsHandler,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
PipTaskOrganizer pipTaskOrganizer) {
return new PipController(context, broadcastDispatcher, pipBoundsHandler,
pipSurfaceTransactionHelper, pipTaskOrganizer);
PipTaskOrganizer pipTaskOrganizer,
WindowManagerShellWrapper windowManagerShellWrapper) {
return new PipController(context, pipBoundsHandler, pipTaskOrganizer,
windowManagerShellWrapper);
}
@SysUISingleton
@Provides
static PipNotification providePipNotification(Context context,
BroadcastDispatcher broadcastDispatcher,
PipController pipController) {
return new PipNotification(context, broadcastDispatcher, pipController);
return new PipNotification(context, pipController);
}
@SysUISingleton

View File

@@ -102,6 +102,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import javax.inject.Inject;
@@ -142,6 +143,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
private Region mActiveNavBarRegion;
private IPinnedStackAnimationListener mIPinnedStackAnimationListener;
private IOverviewProxy mOverviewProxy;
private int mConnectionBackoffAttempts;
private boolean mBound;
@@ -158,7 +160,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
@VisibleForTesting
public ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() {
@Override
public void startScreenPinning(int taskId) {
if (!verifyCaller("startScreenPinning")) {
@@ -438,10 +439,11 @@ public class OverviewProxyService extends CurrentUserTracker implements
+ mHasPipFeature);
return;
}
mIPinnedStackAnimationListener = listener;
long token = Binder.clearCallingIdentity();
try {
mPipOptional.ifPresent(
pip -> pip.setPinnedStackAnimationListener(listener));
pip -> pip.setPinnedStackAnimationListener(mPinnedStackAnimationCallback));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -607,6 +609,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
private final StatusBarWindowCallback mStatusBarWindowCallback = this::onStatusBarStateChanged;
private final BiConsumer<Rect, Rect> mSplitScreenBoundsChangeListener =
this::notifySplitScreenBoundsChanged;
private final Consumer<Boolean> mPinnedStackAnimationCallback =
this::notifyPinnedStackAnimationStarted;
// This is the death handler for the binder from the launcher service
private final IBinder.DeathRecipient mOverviewServiceDeathRcpt
@@ -736,6 +740,17 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
}
private void notifyPinnedStackAnimationStarted(Boolean isAnimationStarted) {
if (mIPinnedStackAnimationListener == null) {
return;
}
try {
mIPinnedStackAnimationListener.onPinnedStackAnimationStarted();
} catch (RemoteException e) {
Log.e(TAG_OPS, "Failed to call onPinnedStackAnimationStarted()", e);
}
}
private void onStatusBarStateChanged(boolean keyguardShowing, boolean keyguardOccluded,
boolean bouncerShowing) {
mSysUiState.setFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
@@ -766,7 +781,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
public void cleanupAfterDeath() {
if (mInputFocusTransferStarted) {
mHandler.post(()-> {
mHandler.post(() -> {
mStatusBarOptionalLazy.ifPresent(statusBarLazy -> {
mInputFocusTransferStarted = false;
statusBarLazy.get().onInputFocusTransfer(false, true /* cancel */,

View File

@@ -49,8 +49,6 @@ public class TvWMShellModule {
return new DisplayImeController(wmService, displayController, mainHandler, transactionPool);
}
@SysUISingleton
@Provides
static SplitScreen provideSplitScreen(Context context,
DisplayController displayController, SystemWindows systemWindows,
DisplayImeController displayImeController, @Main Handler handler,

View File

@@ -16,24 +16,40 @@
package com.android.systemui.wmshell;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_GLOBAL_ACTIONS_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ONE_HANDED_ACTIVE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.InputMethodService;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
import android.util.Pair;
import android.view.KeyEvent;
import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.keyguard.ScreenLifecycle;
@@ -42,9 +58,12 @@ import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.phone.PipUtils;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.tracing.nano.SystemUiTraceProto;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -70,8 +89,20 @@ import javax.inject.Inject;
@SysUISingleton
public final class WMShell extends SystemUI
implements CommandQueue.Callbacks, ProtoTraceable<SystemUiTraceProto> {
private static final String TAG = WMShell.class.getName();
private static final int INVALID_SYSUI_STATE_MASK =
SYSUI_STATE_GLOBAL_ACTIONS_SHOWING
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
| SYSUI_STATE_BOUNCER_SHOWING
| SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
| SYSUI_STATE_BUBBLES_EXPANDED
| SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
private final CommandQueue mCommandQueue;
private final ConfigurationController mConfigurationController;
private final DisplayImeController mDisplayImeController;
private final InputConsumerController mInputConsumerController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final ActivityManagerWrapper mActivityManagerWrapper;
private final NavigationModeController mNavigationModeController;
@@ -84,13 +115,15 @@ public final class WMShell extends SystemUI
// are non-optional windowing features like FULLSCREEN.
private final ShellTaskOrganizer mShellTaskOrganizer;
private final ProtoTracer mProtoTracer;
private boolean mIsSysUiStateValid;
private KeyguardUpdateMonitorCallback mSplitScreenKeyguardCallback;
private KeyguardUpdateMonitorCallback mPipKeyguardCallback;
private KeyguardUpdateMonitorCallback mOneHandedKeyguardCallback;
@Inject
public WMShell(Context context, CommandQueue commandQueue,
ConfigurationController configurationController,
InputConsumerController inputConsumerController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
ActivityManagerWrapper activityManagerWrapper,
DisplayImeController displayImeController,
@@ -104,6 +137,8 @@ public final class WMShell extends SystemUI
ProtoTracer protoTracer) {
super(context);
mCommandQueue = commandQueue;
mConfigurationController = configurationController;
mInputConsumerController = inputConsumerController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mActivityManagerWrapper = activityManagerWrapper;
mDisplayImeController = displayImeController;
@@ -141,6 +176,7 @@ public final class WMShell extends SystemUI
pip.showPictureInPictureMenu();
}
});
mPipKeyguardCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onKeyguardVisibilityChanged(boolean showing) {
@@ -150,6 +186,80 @@ public final class WMShell extends SystemUI
}
};
mKeyguardUpdateMonitor.registerCallback(mPipKeyguardCallback);
mSysUiState.addCallback(sysUiStateFlag -> {
mIsSysUiStateValid = (sysUiStateFlag & INVALID_SYSUI_STATE_MASK) == 0;
pip.onSystemUiStateChanged(mIsSysUiStateValid, sysUiStateFlag);
});
mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() {
@Override
public void onDensityOrFontScaleChanged() {
pip.onDensityOrFontScaleChanged();
}
@Override
public void onOverlayChanged() {
pip.onOverlayChanged();
}
});
// Handle for system task stack changes.
mActivityManagerWrapper.registerTaskStackListener(
new TaskStackChangeListener() {
@Override
public void onTaskStackChanged() {
pip.onTaskStackChanged();
}
@Override
public void onActivityPinned(String packageName, int userId, int taskId,
int stackId) {
pip.onActivityPinned(packageName);
mInputConsumerController.registerInputConsumer(true /* withSfVsync */);
}
@Override
public void onActivityUnpinned() {
final Pair<ComponentName, Integer> topPipActivityInfo =
PipUtils.getTopPipActivity(
mContext, ActivityManager.getService());
final ComponentName topActivity = topPipActivityInfo.first;
pip.onActivityUnpinned(topActivity);
mInputConsumerController.unregisterInputConsumer();
}
@Override
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
pip.onActivityRestartAttempt(task, clearedTask);
}
});
try {
RootTaskInfo taskInfo = ActivityTaskManager.getService().getRootTaskInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
if (taskInfo != null) {
// If SystemUI restart, and it already existed a pinned stack,
// register the pip input consumer to ensure touch can send to it.
mInputConsumerController.registerInputConsumer(true /* withSfVsync */);
}
} catch (RemoteException | UnsupportedOperationException e) {
Log.e(TAG, "Failed to register pinned stack listener", e);
e.printStackTrace();
}
// Register the listener for input consumer touch events. Only for Phone
if (pip.getPipTouchHandler() != null) {
mInputConsumerController.setInputListener(pip.getPipTouchHandler()::handleTouchEvent);
mInputConsumerController.setRegistrationListener(
pip.getPipTouchHandler()::onRegistrationChanged);
}
// The media session listener needs to be re-registered when switching users
UserInfoController userInfoController = Dependency.get(UserInfoController.class);
userInfoController.addCallback((String name, Drawable picture, String userAccount) ->
pip.registerSessionListenerForCurrentUser());
}
@VisibleForTesting

View File

@@ -16,6 +16,7 @@
package com.android.systemui.wmshell;
import android.app.IActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Handler;
@@ -28,7 +29,10 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
import com.android.systemui.pip.PipUiEventLogger;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.pip.phone.PipAppOpsListener;
import com.android.systemui.pip.phone.PipMediaController;
import com.android.systemui.pip.phone.PipTouchHandler;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -69,12 +73,33 @@ public abstract class WMShellBaseModule {
return new DeviceConfigProxy();
}
@SysUISingleton
@Provides
static InputConsumerController provideInputConsumerController() {
return InputConsumerController.getPipInputConsumer();
}
@SysUISingleton
@Provides
static FloatingContentCoordinator provideFloatingContentCoordinator() {
return new FloatingContentCoordinator();
}
@SysUISingleton
@Provides
static PipAppOpsListener providesPipAppOpsListener(Context context,
IActivityManager activityManager,
PipTouchHandler pipTouchHandler) {
return new PipAppOpsListener(context, activityManager, pipTouchHandler.getMotionHelper());
}
@SysUISingleton
@Provides
static PipMediaController providesPipMediaController(Context context,
IActivityManager activityManager) {
return new PipMediaController(context, activityManager);
}
@SysUISingleton
@Provides
static PipUiEventLogger providePipUiEventLogger(UiEventLogger uiEventLogger,
@@ -84,9 +109,8 @@ public abstract class WMShellBaseModule {
@SysUISingleton
@Provides
static PipSurfaceTransactionHelper providesPipSurfaceTransactionHelper(Context context,
ConfigurationController configController) {
return new PipSurfaceTransactionHelper(context, configController);
static PipSurfaceTransactionHelper providesPipSurfaceTransactionHelper(Context context) {
return new PipSurfaceTransactionHelper(context);
}
@SysUISingleton
@@ -104,6 +128,12 @@ public abstract class WMShellBaseModule {
return organizer;
}
@SysUISingleton
@Provides
static WindowManagerShellWrapper provideWindowManagerShellWrapper() {
return new WindowManagerShellWrapper();
}
@SysUISingleton
@Provides
static FlingAnimationUtils.Builder provideFlingAnimationUtilsBuilder(

View File

@@ -20,18 +20,18 @@ import android.content.Context;
import android.os.Handler;
import android.view.IWindowManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.model.SysUiState;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.pip.PipUiEventLogger;
import com.android.systemui.pip.phone.PipAppOpsListener;
import com.android.systemui.pip.phone.PipController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.pip.phone.PipMediaController;
import com.android.systemui.pip.phone.PipMenuActivityController;
import com.android.systemui.pip.phone.PipTouchHandler;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
@@ -66,21 +66,17 @@ public class WMShellModule {
@SysUISingleton
@Provides
static Pip providePipController(Context context,
BroadcastDispatcher broadcastDispatcher,
ConfigurationController configController,
DeviceConfigProxy deviceConfig,
DisplayController displayController,
FloatingContentCoordinator floatingContentCoordinator,
SysUiState sysUiState,
PipAppOpsListener pipAppOpsListener,
PipBoundsHandler pipBoundsHandler,
PipSurfaceTransactionHelper surfaceTransactionHelper,
PipMediaController pipMediaController,
PipMenuActivityController pipMenuActivityController,
PipTaskOrganizer pipTaskOrganizer,
PipUiEventLogger pipUiEventLogger) {
return new PipController(context, broadcastDispatcher, configController, deviceConfig,
displayController, floatingContentCoordinator, sysUiState, pipBoundsHandler,
surfaceTransactionHelper,
pipTaskOrganizer,
pipUiEventLogger);
PipTouchHandler pipTouchHandler,
WindowManagerShellWrapper windowManagerShellWrapper) {
return new PipController(context, displayController,
pipAppOpsListener, pipBoundsHandler, pipMediaController, pipMenuActivityController,
pipTaskOrganizer, pipTouchHandler, windowManagerShellWrapper);
}
@SysUISingleton
@@ -99,6 +95,24 @@ public class WMShellModule {
return new PipBoundsHandler(context);
}
@SysUISingleton
@Provides
static PipMenuActivityController providesPipMenuActivityController(Context context,
PipMediaController pipMediaController, PipTaskOrganizer pipTaskOrganizer) {
return new PipMenuActivityController(context, pipMediaController, pipTaskOrganizer);
}
@SysUISingleton
@Provides
static PipTouchHandler providesPipTouchHandler(Context context,
PipMenuActivityController menuActivityController, PipBoundsHandler pipBoundsHandler,
PipTaskOrganizer pipTaskOrganizer,
FloatingContentCoordinator floatingContentCoordinator,
PipUiEventLogger pipUiEventLogger) {
return new PipTouchHandler(context, menuActivityController, pipBoundsHandler,
pipTaskOrganizer, floatingContentCoordinator, pipUiEventLogger);
}
@SysUISingleton
@Provides
static PipTaskOrganizer providesPipTaskOrganizer(Context context,

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2020 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.wmshell;
import static android.view.Display.DEFAULT_DISPLAY;
import android.app.WindowConfiguration;
import android.os.RemoteException;
import android.view.WindowManagerGlobal;
import com.android.systemui.shared.system.PinnedStackListenerForwarder;
/**
* The singleton wrapper to communicate between WindowManagerService and WMShell features
* (e.g: PIP, SplitScreen, Bubble, OneHandedMode...etc)
*/
public class WindowManagerShellWrapper {
private static final String TAG = WindowManagerShellWrapper.class.getSimpleName();
public static final int WINDOWING_MODE_PINNED = WindowConfiguration.WINDOWING_MODE_PINNED;
/**
* Forwarder to which we can add multiple pinned stack listeners. Each listener will receive
* updates from the window manager service.
*/
private PinnedStackListenerForwarder mPinnedStackListenerForwarder =
new PinnedStackListenerForwarder();
/**
* Adds a pinned stack listener, which will receive updates from the window manager service
* along with any other pinned stack listeners that were added via this method.
*/
public void addPinnedStackListener(PinnedStackListenerForwarder.PinnedStackListener listener)
throws
RemoteException {
mPinnedStackListenerForwarder.addListener(listener);
WindowManagerGlobal.getWindowManagerService().registerPinnedStackListener(
DEFAULT_DISPLAY, mPinnedStackListenerForwarder);
}
/**
* Removes a pinned stack listener.
*/
public void removePinnedStackListener(
PinnedStackListenerForwarder.PinnedStackListener listener) {
mPinnedStackListenerForwarder.removeListener(listener);
}
}

View File

@@ -92,6 +92,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.systemui.wmshell.WindowManagerShellWrapper;
import com.google.common.collect.ImmutableList;
@@ -191,6 +192,8 @@ public class BubbleControllerTest extends SysuiTestCase {
private LauncherApps mLauncherApps;
@Mock private LockscreenLockIconController mLockIconController;
@Mock private WindowManagerShellWrapper mWindowManagerShellWrapper;
private BubbleData mBubbleData;
private TestableLooper mTestableLooper;
@@ -269,6 +272,7 @@ public class BubbleControllerTest extends SysuiTestCase {
mock(INotificationManager.class),
mStatusBarService,
mWindowManager,
mWindowManagerShellWrapper,
mLauncherApps);
mBubbleController.setExpandListener(mBubbleExpandListener);

View File

@@ -92,6 +92,7 @@ import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.wmshell.WindowManagerShellWrapper;
import org.junit.Before;
import org.junit.Ignore;
@@ -185,6 +186,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
private IStatusBarService mStatusBarService;
@Mock
private LauncherApps mLauncherApps;
@Mock
private WindowManagerShellWrapper mWindowManagerShellWrapper;
private BubbleData mBubbleData;
@@ -271,6 +274,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
mock(INotificationManager.class),
mStatusBarService,
mWindowManager,
mWindowManagerShellWrapper,
mLauncherApps);
mBubbleController.addNotifCallback(mNotifCallback);
mBubbleController.setExpandListener(mBubbleExpandListener);

View File

@@ -36,6 +36,7 @@ import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.systemui.wmshell.WindowManagerShellWrapper;
/**
* Testable BubbleController subclass that immediately synchronizes surfaces.
@@ -63,6 +64,7 @@ public class TestableBubbleController extends BubbleController {
INotificationManager notificationManager,
IStatusBarService statusBarService,
WindowManager windowManager,
WindowManagerShellWrapper windowManagerShellWrapper,
LauncherApps launcherApps) {
super(context,
notificationShadeWindowController, statusBarStateController, shadeController,
@@ -70,7 +72,7 @@ public class TestableBubbleController extends BubbleController {
zenModeController, lockscreenUserManager, groupManager, entryManager,
notifPipeline, featureFlags, dumpManager, floatingContentCoordinator,
dataRepository, sysUiState, notificationManager, statusBarService,
windowManager, launcherApps);
windowManager, windowManagerShellWrapper, launcherApps);
setInflateSynchronously(true);
}
}

View File

@@ -22,7 +22,6 @@ import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTI
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.graphics.Matrix;
@@ -34,7 +33,6 @@ import android.view.SurfaceControl;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.policy.ConfigurationController;
import org.junit.Before;
import org.junit.Test;
@@ -61,7 +59,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
@Before
public void setUp() throws Exception {
mPipAnimationController = new PipAnimationController(
new PipSurfaceTransactionHelper(mContext, mock(ConfigurationController.class)));
new PipSurfaceTransactionHelper(mContext));
mLeash = new SurfaceControl.Builder()
.setContainerLayer()
.setName("FakeLeash")

View File

@@ -32,16 +32,11 @@ import android.testing.TestableContext;
import android.testing.TestableLooper;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.model.SysUiState;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.pip.PipUiEventLogger;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.systemui.wmshell.WindowManagerShellWrapper;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
@@ -61,17 +56,16 @@ public class PipControllerTest extends SysuiTestCase {
private TestableContext mSpiedContext;
@Mock private ActivityManagerWrapper mMockActivityManagerWrapper;
@Mock private BroadcastDispatcher mMockBroadcastDispatcher;
@Mock private ConfigurationController mMockConfigurationController;
@Mock private DeviceConfigProxy mMockDeviceConfigProxy;
@Mock private DisplayController mMockdDisplayController;
@Mock private FloatingContentCoordinator mMockFloatingContentCoordinator;
@Mock private PackageManager mPackageManager;
@Mock private PipMenuActivityController mMockPipMenuActivityController;
@Mock private PipAppOpsListener mMockPipAppOpsListener;
@Mock private PipBoundsHandler mMockPipBoundsHandler;
@Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper;
@Mock private PipMediaController mMockPipMediaController;
@Mock private PipTaskOrganizer mMockPipTaskOrganizer;
@Mock private PipUiEventLogger mPipUiEventLogger;
@Mock private SysUiState mMockSysUiState;
@Mock private PipTouchHandler mMockPipTouchHandler;
@Mock private WindowManagerShellWrapper mMockWindowManagerShellWrapper;
@Before
public void setUp() throws RemoteException {
@@ -82,10 +76,10 @@ public class PipControllerTest extends SysuiTestCase {
when(mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false);
when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager);
mPipController = new PipController(mSpiedContext, mMockBroadcastDispatcher,
mMockConfigurationController, mMockDeviceConfigProxy, mMockdDisplayController,
mMockFloatingContentCoordinator, mMockSysUiState, mMockPipBoundsHandler,
mMockPipSurfaceTransactionHelper, mMockPipTaskOrganizer, mPipUiEventLogger);
mPipController = new PipController(mSpiedContext, mMockdDisplayController,
mMockPipAppOpsListener,
mMockPipBoundsHandler, mMockPipMediaController, mMockPipMenuActivityController,
mMockPipTaskOrganizer, mMockPipTouchHandler, mMockWindowManagerShellWrapper);
}
@Test

View File

@@ -22,7 +22,6 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.IActivityManager;
import android.graphics.Point;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
@@ -33,13 +32,10 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.model.SysUiState;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipSnapAlgorithm;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.pip.PipUiEventLogger;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.FloatingContentCoordinator;
import org.junit.Before;
@@ -62,27 +58,15 @@ public class PipTouchHandlerTest extends SysuiTestCase {
private PipTouchHandler mPipTouchHandler;
@Mock
private IActivityManager mActivityManager;
@Mock
private PipMenuActivityController mPipMenuActivityController;
@Mock
private InputConsumerController mInputConsumerController;
@Mock
private PipTaskOrganizer mPipTaskOrganizer;
@Mock
private FloatingContentCoordinator mFloatingContentCoordinator;
@Mock
private DeviceConfigProxy mDeviceConfigProxy;
@Mock
private SysUiState mSysUiState;
@Mock
private PipUiEventLogger mPipUiEventLogger;
@@ -105,9 +89,8 @@ public class PipTouchHandlerTest extends SysuiTestCase {
mPipBoundsHandler = new PipBoundsHandler(mContext);
mPipSnapAlgorithm = mPipBoundsHandler.getSnapAlgorithm();
mPipSnapAlgorithm = new PipSnapAlgorithm(mContext);
mPipTouchHandler = new PipTouchHandler(mContext, mActivityManager,
mPipMenuActivityController, mInputConsumerController, mPipBoundsHandler,
mPipTaskOrganizer, mFloatingContentCoordinator, mDeviceConfigProxy, mSysUiState,
mPipTouchHandler = new PipTouchHandler(mContext, mPipMenuActivityController,
mPipBoundsHandler, mPipTaskOrganizer, mFloatingContentCoordinator,
mPipUiEventLogger);
mMotionHelper = Mockito.spy(mPipTouchHandler.getMotionHelper());
mPipResizeGestureHandler = Mockito.spy(mPipTouchHandler.getPipResizeGestureHandler());

View File

@@ -37,9 +37,12 @@ import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.phone.PipTouchHandler;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.tracing.ProtoTracer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayImeController;
@@ -59,9 +62,11 @@ import java.util.Optional;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class WMShellTest extends SysuiTestCase {
InputConsumerController mInputConsumerController;
WMShell mWMShell;
@Mock CommandQueue mCommandQueue;
@Mock ConfigurationController mConfigurationController;
@Mock KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock ActivityManagerWrapper mActivityManagerWrapper;
@Mock DisplayImeController mDisplayImeController;
@@ -69,6 +74,7 @@ public class WMShellTest extends SysuiTestCase {
@Mock ScreenLifecycle mScreenLifecycle;
@Mock SysUiState mSysUiState;
@Mock Pip mPip;
@Mock PipTouchHandler mPipTouchHandler;
@Mock SplitScreen mSplitScreen;
@Mock OneHanded mOneHanded;
@Mock ShellTaskOrganizer mTaskOrganizer;
@@ -78,10 +84,16 @@ public class WMShellTest extends SysuiTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mWMShell = new WMShell(mContext, mCommandQueue, mKeyguardUpdateMonitor,
mActivityManagerWrapper, mDisplayImeController, mNavigationModeController,
mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen),
Optional.of(mOneHanded), mTaskOrganizer, mProtoTracer);
mInputConsumerController = InputConsumerController.getPipInputConsumer();
mWMShell = new WMShell(mContext, mCommandQueue, mConfigurationController,
mInputConsumerController, mKeyguardUpdateMonitor, mActivityManagerWrapper,
mDisplayImeController, mNavigationModeController, mScreenLifecycle, mSysUiState,
Optional.of(mPip), Optional.of(mSplitScreen), Optional.of(mOneHanded),
mTaskOrganizer, mProtoTracer);
when(mPip.getPipTouchHandler()).thenReturn(mPipTouchHandler);
}
@Test
@@ -103,9 +115,8 @@ public class WMShellTest extends SysuiTestCase {
TestableContext spiedContext = spy(mContext);
when(mMockPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false);
when(spiedContext.getPackageManager()).thenReturn(mMockPackageManager);
final WMShell nonPipWMShell = new WMShell(spiedContext, mCommandQueue,
mKeyguardUpdateMonitor,
mConfigurationController, mInputConsumerController, mKeyguardUpdateMonitor,
mActivityManagerWrapper, mDisplayImeController, mNavigationModeController,
mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen),
Optional.of(mOneHanded), mTaskOrganizer, mProtoTracer);