Decouple systemui shared componements from PipController(8/N)
1) Add PipAppOpsListener, PipMediaController,PipMenuActivityController in WMShellModule scope, and provided by dagger 2) Move system/task listeners/callbacks to WMShell 3) Refactor tv/PipController 4) Create WindowManagerShellWrapper for WMShell features (Separate from WindowManagerWrapper) 5) Remove WindowManagerWrapper.setPipVisibility to adapt new approach 6) Hook dump throught WMShell 7) Decouple SysUI DeviceConfigProxy(Wrapper), use DeviceConfig instead Bug: 161118569 Bug: 165793553 Fixes: 166181820 Test: make SystemUI Test: make ArcSystemUI Test: make WMShellUnitTests Test: lunch aosp_tv_arm-userdebug & make Test: atest SystemUITests Test: atest WindowManagerShellTests Test: atest WMShellUnitTests Test: adb shell input keyevent 171(KEYCODE_WINDOW) Test: manual test Pip demo AP Test: adb shell dumpsys activity service com.android.systemui Change-Id: I4862508a664023242565ff741f1bde5e1b05c8b7
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
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;
|
||||
|
||||
@@ -28,11 +30,6 @@ import java.io.PrintWriter;
|
||||
* 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,14 +197,6 @@ public interface Pip {
|
||||
default void setShelfHeight(boolean visible, int height) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pinned stack with {@link PipAnimationController.AnimationType}
|
||||
*
|
||||
* @param animationType The pre-defined {@link PipAnimationController.AnimationType}
|
||||
*/
|
||||
default void setPinnedStackAnimationType(int animationType) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the pinned stack animation listener.
|
||||
*
|
||||
@@ -152,6 +205,19 @@ public interface Pip {
|
||||
default void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pinned stack with {@link PipAnimationController.AnimationType}
|
||||
*
|
||||
* @param animationType The pre-defined {@link PipAnimationController.AnimationType}
|
||||
*/
|
||||
default void setPinnedStackAnimationType(int animationType) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when showing Pip menu.
|
||||
*/
|
||||
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) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -129,7 +129,6 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
|
||||
}
|
||||
}
|
||||
|
||||
private final Context mContext;
|
||||
private final Handler mMainHandler;
|
||||
private final Handler mUpdateHandler;
|
||||
private final PipBoundsHandler mPipBoundsHandler;
|
||||
@@ -248,7 +247,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;
|
||||
@@ -559,8 +557,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();
|
||||
@@ -652,6 +650,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
|
||||
*
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.systemui.pip.phone;
|
||||
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
||||
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
|
||||
|
||||
@@ -24,45 +23,28 @@ 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.PackageManager;
|
||||
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;
|
||||
|
||||
@@ -76,7 +58,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();
|
||||
@@ -85,13 +66,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 WindowManagerShellWrapper mWindowManagerShellWrapper;
|
||||
|
||||
private boolean mIsInFixedRotation;
|
||||
|
||||
protected PipMenuActivityController mMenuController;
|
||||
@@ -157,51 +138,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));
|
||||
@@ -239,7 +180,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
|
||||
@@ -251,32 +195,17 @@ 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();
|
||||
|
||||
PackageManager pm = context.getPackageManager();
|
||||
boolean supportsPip = pm.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
|
||||
@@ -291,28 +220,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);
|
||||
|
||||
@@ -322,26 +238,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -352,6 +311,11 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
mTouchHandler.getMotionHelper().expandLeavePip(false /* skipAnimation */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PipTouchHandler getPipTouchHandler() {
|
||||
return mTouchHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the PIP menu.
|
||||
*/
|
||||
@@ -466,7 +430,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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -145,9 +145,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();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ 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.pip.Pip;
|
||||
@@ -62,12 +61,11 @@ public class TvWMShellModule {
|
||||
@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
|
||||
@@ -83,9 +81,8 @@ public class TvWMShellModule {
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static PipNotification providePipNotification(Context context,
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
PipController pipController) {
|
||||
return new PipNotification(context, broadcastDispatcher, pipController);
|
||||
return new PipNotification(context, pipController);
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
|
||||
@@ -16,34 +16,54 @@
|
||||
|
||||
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;
|
||||
import com.android.systemui.model.SysUiState;
|
||||
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;
|
||||
@@ -57,7 +77,6 @@ import com.android.wm.shell.protolog.ShellProtoLogImpl;
|
||||
import com.android.wm.shell.splitscreen.SplitScreen;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
@@ -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,12 +115,14 @@ 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 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
|
||||
super(context);
|
||||
mCommandQueue = commandQueue;
|
||||
mCommandQueue.addCallback(this);
|
||||
mConfigurationController = configurationController;
|
||||
mInputConsumerController = inputConsumerController;
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mActivityManagerWrapper = activityManagerWrapper;
|
||||
mDisplayImeController = displayImeController;
|
||||
@@ -137,6 +172,78 @@ public final class WMShell extends SystemUI
|
||||
pip.showPictureInPictureMenu();
|
||||
}
|
||||
});
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -32,9 +32,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;
|
||||
@@ -54,9 +57,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;
|
||||
@@ -64,6 +69,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;
|
||||
@@ -72,10 +78,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
|
||||
|
||||
Reference in New Issue
Block a user