Merge "Integrate PipUI PipManager to PipController (7/N)"
This commit is contained in:
committed by
Android (Google) Code Review
commit
f998fa1bd1
@@ -123,7 +123,6 @@
|
||||
<item>com.android.systemui.volume.VolumeUI</item>
|
||||
<item>com.android.systemui.statusbar.phone.StatusBar</item>
|
||||
<item>com.android.systemui.keyboard.KeyboardUI</item>
|
||||
<item>com.android.systemui.pip.PipUI</item>
|
||||
<item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
|
||||
<item>com.android.systemui.LatencyTester</item>
|
||||
<item>com.android.systemui.globalactions.GlobalActionsComponent</item>
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.android.systemui.dagger.DependencyProvider;
|
||||
import com.android.systemui.dagger.SysUIComponent;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.SystemUIModule;
|
||||
import com.android.systemui.pip.phone.dagger.PipModule;
|
||||
|
||||
import dagger.Subcomponent;
|
||||
|
||||
@@ -31,7 +30,6 @@ import dagger.Subcomponent;
|
||||
@Subcomponent(modules = {
|
||||
CarComponentBinder.class,
|
||||
DependencyProvider.class,
|
||||
PipModule.class,
|
||||
SystemUIModule.class,
|
||||
CarSystemUIModule.class,
|
||||
CarSystemUIBinder.class})
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.android.systemui.globalactions.GlobalActionsComponent;
|
||||
import com.android.systemui.keyguard.KeyguardViewMediator;
|
||||
import com.android.systemui.keyguard.dagger.KeyguardModule;
|
||||
import com.android.systemui.onehanded.OneHandedUI;
|
||||
import com.android.systemui.pip.PipUI;
|
||||
import com.android.systemui.power.PowerUI;
|
||||
import com.android.systemui.recents.Recents;
|
||||
import com.android.systemui.recents.RecentsModule;
|
||||
@@ -101,12 +100,6 @@ public abstract class CarSystemUIBinder {
|
||||
@ClassKey(OneHandedUI.class)
|
||||
public abstract SystemUI bindOneHandedUI(OneHandedUI sysui);
|
||||
|
||||
/** Inject into PipUI. */
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(PipUI.class)
|
||||
public abstract SystemUI bindPipUI(PipUI sysui);
|
||||
|
||||
/** Inject into PowerUI. */
|
||||
@Binds
|
||||
@IntoMap
|
||||
|
||||
@@ -516,7 +516,7 @@
|
||||
android:excludeFromRecents="true"
|
||||
android:visibleToInstantApps="true"/>
|
||||
|
||||
<!-- started from PipUI -->
|
||||
<!-- started from PipController -->
|
||||
<activity
|
||||
android:name=".pip.tv.PipMenuActivity"
|
||||
android:permission="com.android.systemui.permission.SELF"
|
||||
|
||||
@@ -115,10 +115,6 @@ Shows UI for keyboard shortcuts (triggered by keyboard shortcut).
|
||||
|
||||
Shows the overlay controls when One handed is triggered.
|
||||
|
||||
### [com.android.systemui.pip.PipUI](/packages/SystemUI/src/com/android/systemui/pip/PipUI.java)
|
||||
|
||||
Shows the overlay controls when Pip is showing.
|
||||
|
||||
### [com.android.systemui.shortcut.ShortcutKeyDispatcher](/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java)
|
||||
|
||||
Dispatches shortcut to System UI components.
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
<item>com.android.systemui.power.PowerUI</item>
|
||||
<item>com.android.systemui.media.RingtonePlayer</item>
|
||||
<item>com.android.systemui.keyboard.KeyboardUI</item>
|
||||
<item>com.android.systemui.pip.PipUI</item>
|
||||
<item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
|
||||
<item>@string/config_systemUIVendorServiceComponent</item>
|
||||
<item>com.android.systemui.SliceBroadcastRelayHandler</item>
|
||||
|
||||
@@ -306,7 +306,6 @@
|
||||
<item>com.android.systemui.power.PowerUI</item>
|
||||
<item>com.android.systemui.media.RingtonePlayer</item>
|
||||
<item>com.android.systemui.keyboard.KeyboardUI</item>
|
||||
<item>com.android.systemui.pip.PipUI</item>
|
||||
<item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
|
||||
<item>@string/config_systemUIVendorServiceComponent</item>
|
||||
<item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.android.systemui.InitController;
|
||||
import com.android.systemui.SystemUIAppComponentFactory;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.keyguard.KeyguardSliceProvider;
|
||||
import com.android.systemui.pip.phone.dagger.PipModule;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.util.InjectionInflationController;
|
||||
|
||||
@@ -36,7 +35,6 @@ import dagger.Subcomponent;
|
||||
@Subcomponent(modules = {
|
||||
DefaultComponentBinder.class,
|
||||
DependencyProvider.class,
|
||||
PipModule.class,
|
||||
SystemUIBinder.class,
|
||||
SystemUIModule.class,
|
||||
SystemUIDefaultModule.class})
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.android.systemui.globalactions.GlobalActionsComponent;
|
||||
import com.android.systemui.keyguard.KeyguardViewMediator;
|
||||
import com.android.systemui.keyguard.dagger.KeyguardModule;
|
||||
import com.android.systemui.onehanded.OneHandedUI;
|
||||
import com.android.systemui.pip.PipUI;
|
||||
import com.android.systemui.power.PowerUI;
|
||||
import com.android.systemui.recents.Recents;
|
||||
import com.android.systemui.recents.RecentsModule;
|
||||
@@ -97,12 +96,6 @@ public abstract class SystemUIBinder {
|
||||
@ClassKey(OneHandedUI.class)
|
||||
public abstract SystemUI bindOneHandedUI(OneHandedUI sysui);
|
||||
|
||||
/** Inject into PipUI. */
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(PipUI.class)
|
||||
public abstract SystemUI bindPipUI(PipUI sysui);
|
||||
|
||||
/** Inject into PowerUI. */
|
||||
@Binds
|
||||
@IntoMap
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.pip;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
|
||||
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
|
||||
public interface BasePipManager {
|
||||
void showPictureInPictureMenu();
|
||||
default void expandPip() {}
|
||||
default void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {}
|
||||
void onConfigurationChanged(Configuration newConfig);
|
||||
default void setShelfHeight(boolean visible, int height) {}
|
||||
default void setPinnedStackAnimationType(int animationType) {}
|
||||
default void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) {}
|
||||
default void dump(PrintWriter pw) {}
|
||||
}
|
||||
170
packages/SystemUI/src/com/android/systemui/pip/Pip.java
Normal file
170
packages/SystemUI/src/com/android/systemui/pip/Pip.java
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.pip;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.media.session.MediaController;
|
||||
|
||||
import com.android.systemui.pip.tv.PipController;
|
||||
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
|
||||
|
||||
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.
|
||||
*/
|
||||
default void addListener(PipController.Listener listener) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link com.android.systemui.pip.tv.PipController.MediaListener} to PipController.
|
||||
*/
|
||||
default void addMediaListener(PipController.MediaListener listener) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes PIP (PIPed activity and PIP system UI).
|
||||
*/
|
||||
default void closePip() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand PIP, it's possible that specific request to activate the window via Alt-tab.
|
||||
*/
|
||||
default void expandPip() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current play back state. (e.g: Used in TV)
|
||||
*
|
||||
* @return The state of defined in PipController.
|
||||
*/
|
||||
default int getPlaybackState() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MediaController.
|
||||
*
|
||||
* @return The MediaController instance.
|
||||
*/
|
||||
default MediaController getMediaController() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the PIP menu.
|
||||
*/
|
||||
void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if PIP is shown.
|
||||
*/
|
||||
default boolean isPipShown() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the PIPed activity to the fullscreen and closes PIP system UI.
|
||||
*/
|
||||
default void movePipToFullscreen() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when configuration change invoked.
|
||||
*/
|
||||
void onConfigurationChanged(Configuration newConfig);
|
||||
|
||||
/**
|
||||
* Removes a {@link PipController.Listener} from PipController.
|
||||
*/
|
||||
default void removeListener(PipController.Listener listener) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a {@link com.android.systemui.pip.tv.PipController.MediaListener} from PipController.
|
||||
*/
|
||||
default void removeMediaListener(PipController.MediaListener listener) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the Pip to the appropriate size for the input state.
|
||||
*
|
||||
* @param state In Pip state also used to determine the new size for the Pip.
|
||||
*/
|
||||
default void resizePinnedStack(int state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes resizing operation on the Pip that was previously suspended.
|
||||
*
|
||||
* @param reason The reason resizing operations on the Pip was suspended.
|
||||
*/
|
||||
default void resumePipResizing(int reason) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets both shelf visibility and its height.
|
||||
*
|
||||
* @param visible visibility of shelf.
|
||||
* @param height to specify the height for shelf.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param listener The listener of pinned stack animation.
|
||||
*/
|
||||
default void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Suspends resizing operation on the Pip until {@link #resumePipResizing} is called.
|
||||
*
|
||||
* @param reason The reason for suspending resizing operations on the 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) {
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.pip;
|
||||
|
||||
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.systemui.SystemUI;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Controls the picture-in-picture window.
|
||||
*/
|
||||
@SysUISingleton
|
||||
public class PipUI extends SystemUI implements CommandQueue.Callbacks {
|
||||
|
||||
private final CommandQueue mCommandQueue;
|
||||
private BasePipManager mPipManager;
|
||||
|
||||
@Inject
|
||||
public PipUI(Context context, CommandQueue commandQueue,
|
||||
BasePipManager pipManager) {
|
||||
super(context);
|
||||
mCommandQueue = commandQueue;
|
||||
mPipManager = pipManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
boolean supportsPip = pm.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
|
||||
if (!supportsPip) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that we are the primary user's SystemUI.
|
||||
final int processUser = UserManager.get(mContext).getUserHandle();
|
||||
if (processUser != UserHandle.USER_SYSTEM) {
|
||||
throw new IllegalStateException("Non-primary Pip component not currently supported.");
|
||||
}
|
||||
|
||||
mCommandQueue.addCallback(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPictureInPictureMenu() {
|
||||
mPipManager.showPictureInPictureMenu();
|
||||
}
|
||||
|
||||
public void expandPip() {
|
||||
mPipManager.expandPip();
|
||||
}
|
||||
|
||||
public void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {
|
||||
mPipManager.hidePipMenu(onStartCallback, onEndCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
if (mPipManager == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPipManager.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
public void setShelfHeight(boolean visible, int height) {
|
||||
if (mPipManager == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPipManager.setShelfHeight(visible, height);
|
||||
}
|
||||
|
||||
public void setPinnedStackAnimationType(int animationType) {
|
||||
if (mPipManager != null) {
|
||||
mPipManager.setPinnedStackAnimationType(animationType);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) {
|
||||
if (mPipManager != null) {
|
||||
mPipManager.setPinnedStackAnimationListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
if (mPipManager == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPipManager.dump(pw);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ 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;
|
||||
|
||||
import static com.android.systemui.pip.PipAnimationController.isOutPipDirection;
|
||||
|
||||
@@ -28,11 +29,14 @@ 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;
|
||||
@@ -44,7 +48,7 @@ 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.BasePipManager;
|
||||
import com.android.systemui.pip.Pip;
|
||||
import com.android.systemui.pip.PipBoundsHandler;
|
||||
import com.android.systemui.pip.PipSurfaceTransactionHelper;
|
||||
import com.android.systemui.pip.PipTaskOrganizer;
|
||||
@@ -55,25 +59,20 @@ 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.stackdivider.SplitScreen;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.util.DeviceConfigProxy;
|
||||
import com.android.systemui.util.FloatingContentCoordinator;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.common.DisplayChangeController;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Manages the picture-in-picture (PIP) UI and states for Phones.
|
||||
*/
|
||||
@SysUISingleton
|
||||
public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitionCallback {
|
||||
private static final String TAG = "PipManager";
|
||||
public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallback {
|
||||
private static final String TAG = "PipController";
|
||||
|
||||
private Context mContext;
|
||||
private IActivityManager mActivityManager;
|
||||
@@ -87,15 +86,15 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
private DisplayController mDisplayController;
|
||||
private InputConsumerController mInputConsumerController;
|
||||
private PipAppOpsListener mAppOpsListener;
|
||||
private PipBoundsHandler mPipBoundsHandler;
|
||||
private PipMediaController mMediaController;
|
||||
private PipTouchHandler mTouchHandler;
|
||||
private PipTaskOrganizer mPipTaskOrganizer;
|
||||
private PipSurfaceTransactionHelper mPipSurfaceTransactionHelper;
|
||||
private IPinnedStackAnimationListener mPinnedStackAnimationRecentsListener;
|
||||
private boolean mIsInFixedRotation;
|
||||
|
||||
protected PipBoundsHandler mPipBoundsHandler;
|
||||
protected PipMenuActivityController mMenuController;
|
||||
protected PipTaskOrganizer mPipTaskOrganizer;
|
||||
|
||||
/**
|
||||
* Handler for display rotation changes.
|
||||
@@ -127,7 +126,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
// not during the fixed rotation. In fixed rotation case, app is about to enter PiP
|
||||
// and we need the offsets preserved to calculate the destination bounds.
|
||||
if (!mIsInFixedRotation) {
|
||||
mPipBoundsHandler.setShelfHeight(false , 0);
|
||||
mPipBoundsHandler.setShelfHeight(false, 0);
|
||||
mPipBoundsHandler.onImeVisibilityChanged(false, 0);
|
||||
mTouchHandler.onShelfVisibilityChanged(false, 0);
|
||||
mTouchHandler.onImeVisibilityChanged(false, 0);
|
||||
@@ -201,7 +200,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
/**
|
||||
* Handler for messages from the PIP controller.
|
||||
*/
|
||||
private class PipManagerPinnedStackListener extends PinnedStackListener {
|
||||
private class PipControllerPinnedStackListener extends PinnedStackListener {
|
||||
@Override
|
||||
public void onListenerRegistered(IPinnedStackController controller) {
|
||||
mHandler.post(() -> mTouchHandler.setPinnedStackController(controller));
|
||||
@@ -253,44 +252,55 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
|
||||
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 */);
|
||||
});
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public void onOverlayChanged() {
|
||||
mHandler.post(() -> {
|
||||
mPipBoundsHandler.onOverlayChanged(mContext, mContext.getDisplay());
|
||||
updateMovementBounds(null /* toBounds */,
|
||||
false /* fromRotation */, false /* fromImeAdjustment */,
|
||||
false /* fromShelfAdjustment */,
|
||||
null /* windowContainerTransaction */);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@Inject
|
||||
public PipManager(Context context, BroadcastDispatcher broadcastDispatcher,
|
||||
public PipController(Context context, BroadcastDispatcher broadcastDispatcher,
|
||||
ConfigurationController configController,
|
||||
DeviceConfigProxy deviceConfig,
|
||||
DisplayController displayController,
|
||||
Optional<SplitScreen> splitScreenOptional,
|
||||
FloatingContentCoordinator floatingContentCoordinator,
|
||||
SysUiState sysUiState,
|
||||
PipUiEventLogger pipUiEventLogger,
|
||||
ShellTaskOrganizer shellTaskOrganizer) {
|
||||
PipBoundsHandler pipBoundsHandler,
|
||||
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
|
||||
PipTaskOrganizer pipTaskOrganizer,
|
||||
PipUiEventLogger pipUiEventLogger) {
|
||||
mContext = context;
|
||||
mActivityManager = ActivityManager.getService();
|
||||
|
||||
PackageManager pm = context.getPackageManager();
|
||||
boolean supportsPip = pm.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
|
||||
if (!supportsPip) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that we are the primary user's SystemUI.
|
||||
final int processUser = UserManager.get(context).getUserHandle();
|
||||
if (processUser != UserHandle.USER_SYSTEM) {
|
||||
throw new IllegalStateException("Non-primary Pip component not currently supported.");
|
||||
}
|
||||
|
||||
try {
|
||||
WindowManagerWrapper.getInstance().addPinnedStackListener(
|
||||
new PipManagerPinnedStackListener());
|
||||
new PipControllerPinnedStackListener());
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to register pinned stack listener", e);
|
||||
}
|
||||
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
|
||||
|
||||
mDisplayController = displayController;
|
||||
mPipBoundsHandler = new PipBoundsHandler(mContext);
|
||||
mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context, configController);
|
||||
mPipTaskOrganizer = new PipTaskOrganizer(mContext, mPipBoundsHandler,
|
||||
mPipSurfaceTransactionHelper, splitScreenOptional, mDisplayController,
|
||||
pipUiEventLogger, shellTaskOrganizer);
|
||||
mPipBoundsHandler = pipBoundsHandler;
|
||||
mPipSurfaceTransactionHelper = pipSurfaceTransactionHelper;
|
||||
mPipTaskOrganizer = pipTaskOrganizer;
|
||||
mPipTaskOrganizer.registerPipTransitionCallback(this);
|
||||
mInputConsumerController = InputConsumerController.getPipInputConsumer();
|
||||
mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher);
|
||||
@@ -450,6 +460,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
mTmpDisplayInfo.rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(PrintWriter pw) {
|
||||
final String innerPrefix = " ";
|
||||
pw.println(TAG);
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.pip.phone.dagger;
|
||||
|
||||
import com.android.systemui.pip.BasePipManager;
|
||||
import com.android.systemui.pip.phone.PipManager;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
|
||||
/**
|
||||
* Dagger Module for Phone PIP.
|
||||
*/
|
||||
@Module
|
||||
public abstract class PipModule {
|
||||
|
||||
/** Binds PipManager as the default BasePipManager. */
|
||||
@Binds
|
||||
public abstract BasePipManager providePipManager(PipManager pipManager);
|
||||
}
|
||||
@@ -20,7 +20,6 @@ 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.annotation.NonNull;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityManager.StackInfo;
|
||||
import android.app.ActivityTaskManager;
|
||||
@@ -51,34 +50,31 @@ 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.BasePipManager;
|
||||
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.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.stackdivider.SplitScreen;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Manages the picture-in-picture (PIP) UI and states.
|
||||
*/
|
||||
@SysUISingleton
|
||||
public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitionCallback {
|
||||
private static final String TAG = "PipManager";
|
||||
public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallback {
|
||||
private static final String TAG = "PipController";
|
||||
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
/**
|
||||
* Unknown or invalid state
|
||||
*/
|
||||
public static final int STATE_UNKNOWN = -1;
|
||||
/**
|
||||
* State when there's no PIP.
|
||||
*/
|
||||
@@ -147,7 +143,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
private boolean mImeVisible;
|
||||
private int mImeHeightAdjustment;
|
||||
|
||||
private final PinnedStackListener mPinnedStackListener = new PipManagerPinnedStackListener();
|
||||
private final PinnedStackListener mPinnedStackListener = new PipControllerPinnedStackListener();
|
||||
|
||||
private final Runnable mResizePinnedStackRunnable = new Runnable() {
|
||||
@Override
|
||||
@@ -189,7 +185,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
/**
|
||||
* Handler for messages from the PIP controller.
|
||||
*/
|
||||
private class PipManagerPinnedStackListener extends PinnedStackListener {
|
||||
private class PipControllerPinnedStackListener extends PinnedStackListener {
|
||||
@Override
|
||||
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
|
||||
mHandler.post(() -> {
|
||||
@@ -231,20 +227,19 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
}
|
||||
}
|
||||
|
||||
@Inject
|
||||
public PipManager(Context context, BroadcastDispatcher broadcastDispatcher,
|
||||
ConfigurationController configController,
|
||||
DisplayController displayController,
|
||||
Optional<SplitScreen> splitScreenOptional,
|
||||
@NonNull PipUiEventLogger pipUiEventLogger,
|
||||
ShellTaskOrganizer shellTaskOrganizer) {
|
||||
public PipController(Context context, BroadcastDispatcher broadcastDispatcher,
|
||||
PipBoundsHandler pipBoundsHandler,
|
||||
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
|
||||
PipTaskOrganizer pipTaskOrganizer) {
|
||||
if (mInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
mContext = context;
|
||||
mPipBoundsHandler = new PipBoundsHandler(mContext);
|
||||
mPipNotification = new PipNotification(context, broadcastDispatcher,
|
||||
Optional.of(this).get());
|
||||
mPipBoundsHandler = pipBoundsHandler;
|
||||
// Ensure that we have the display info in case we get calls to update the bounds before the
|
||||
// listener calls back
|
||||
final DisplayInfo displayInfo = new DisplayInfo();
|
||||
@@ -253,10 +248,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
|
||||
mResizeAnimationDuration = context.getResources()
|
||||
.getInteger(R.integer.config_pipResizeAnimationDuration);
|
||||
mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context, configController);
|
||||
mPipTaskOrganizer = new PipTaskOrganizer(mContext, mPipBoundsHandler,
|
||||
mPipSurfaceTransactionHelper, splitScreenOptional, displayController,
|
||||
pipUiEventLogger, shellTaskOrganizer);
|
||||
mPipSurfaceTransactionHelper = pipSurfaceTransactionHelper;
|
||||
mPipTaskOrganizer = pipTaskOrganizer;
|
||||
mPipTaskOrganizer.registerPipTransitionCallback(this);
|
||||
mActivityTaskManager = ActivityTaskManager.getService();
|
||||
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
|
||||
@@ -278,8 +271,6 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
} catch (RemoteException | UnsupportedOperationException e) {
|
||||
Log.e(TAG, "Failed to register pinned stack listener", e);
|
||||
}
|
||||
|
||||
mPipNotification = new PipNotification(context, broadcastDispatcher, this);
|
||||
}
|
||||
|
||||
private void loadConfigurationsAndApply(Configuration newConfig) {
|
||||
@@ -359,7 +350,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
/**
|
||||
* Moves the PIPed activity to the fullscreen and closes PIP system UI.
|
||||
*/
|
||||
void movePipToFullscreen() {
|
||||
public void movePipToFullscreen() {
|
||||
if (DEBUG) Log.d(TAG, "movePipToFullscreen(), current state=" + getStateDescription());
|
||||
|
||||
mPipTaskId = TASK_ID_NO_PIP;
|
||||
@@ -372,34 +363,41 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
|
||||
/**
|
||||
* Suspends resizing operation on the Pip until {@link #resumePipResizing} is called
|
||||
*
|
||||
* @param reason The reason for suspending resizing operations on the Pip.
|
||||
*/
|
||||
public void suspendPipResizing(int reason) {
|
||||
if (DEBUG) Log.d(TAG,
|
||||
"suspendPipResizing() reason=" + reason + " callers=" + Debug.getCallers(2));
|
||||
if (DEBUG) {
|
||||
Log.d(TAG,
|
||||
"suspendPipResizing() reason=" + reason + " callers=" + Debug.getCallers(2));
|
||||
}
|
||||
|
||||
mSuspendPipResizingReason |= reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes resizing operation on the Pip that was previously suspended.
|
||||
*
|
||||
* @param reason The reason resizing operations on the Pip was suspended.
|
||||
*/
|
||||
public void resumePipResizing(int reason) {
|
||||
if ((mSuspendPipResizingReason & reason) == 0) {
|
||||
return;
|
||||
}
|
||||
if (DEBUG) Log.d(TAG,
|
||||
"resumePipResizing() reason=" + reason + " callers=" + Debug.getCallers(2));
|
||||
if (DEBUG) {
|
||||
Log.d(TAG,
|
||||
"resumePipResizing() reason=" + reason + " callers=" + Debug.getCallers(2));
|
||||
}
|
||||
mSuspendPipResizingReason &= ~reason;
|
||||
mHandler.post(mResizePinnedStackRunnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the Pip to the appropriate size for the input state.
|
||||
*
|
||||
* @param state In Pip state also used to determine the new size for the Pip.
|
||||
*/
|
||||
void resizePinnedStack(int state) {
|
||||
public void resizePinnedStack(int state) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "resizePinnedStack() state=" + stateToName(state) + ", current state="
|
||||
+ getStateDescription(), new Exception());
|
||||
@@ -411,10 +409,12 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
}
|
||||
if (mSuspendPipResizingReason != 0) {
|
||||
mResumeResizePinnedStackRunnableState = state;
|
||||
if (DEBUG) Log.d(TAG, "resizePinnedStack() deferring"
|
||||
+ " mSuspendPipResizingReason=" + mSuspendPipResizingReason
|
||||
+ " mResumeResizePinnedStackRunnableState="
|
||||
+ stateToName(mResumeResizePinnedStackRunnableState));
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "resizePinnedStack() deferring"
|
||||
+ " mSuspendPipResizingReason=" + mSuspendPipResizingReason
|
||||
+ " mResumeResizePinnedStackRunnableState="
|
||||
+ stateToName(mResumeResizePinnedStackRunnableState));
|
||||
}
|
||||
return;
|
||||
}
|
||||
mState = state;
|
||||
@@ -471,28 +471,28 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link Listener} to PipManager.
|
||||
* Adds a {@link Listener} to PipController.
|
||||
*/
|
||||
public void addListener(Listener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a {@link Listener} from PipManager.
|
||||
* Removes a {@link Listener} from PipController.
|
||||
*/
|
||||
public void removeListener(Listener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link MediaListener} to PipManager.
|
||||
* Adds a {@link MediaListener} to PipController.
|
||||
*/
|
||||
public void addMediaListener(MediaListener listener) {
|
||||
mMediaListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a {@link MediaListener} from PipManager.
|
||||
* Removes a {@link MediaListener} from PipController.
|
||||
*/
|
||||
public void removeMediaListener(MediaListener listener) {
|
||||
mMediaListeners.remove(listener);
|
||||
@@ -568,16 +568,21 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
/**
|
||||
* Gets the {@link android.media.session.MediaController} for the PIPed activity.
|
||||
*/
|
||||
MediaController getMediaController() {
|
||||
public MediaController getMediaController() {
|
||||
return mPipMediaController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PIPed activity's playback state.
|
||||
* This returns one of {@link #PLAYBACK_STATE_PLAYING}, {@link #PLAYBACK_STATE_PAUSED},
|
||||
* or {@link #PLAYBACK_STATE_UNAVAILABLE}.
|
||||
*/
|
||||
int getPlaybackState() {
|
||||
public int getPlaybackState() {
|
||||
if (mPipMediaController == null || mPipMediaController.getPlaybackState() == null) {
|
||||
return PLAYBACK_STATE_UNAVAILABLE;
|
||||
}
|
||||
@@ -673,7 +678,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onPipTransitionStarted(ComponentName activity, int direction, Rect pipBounds) { }
|
||||
public void onPipTransitionStarted(ComponentName activity, int direction, Rect pipBounds) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPipTransitionFinished(ComponentName activity, int direction) {
|
||||
@@ -701,7 +707,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
* Invoked when an activity is pinned and PIP manager is set corresponding information.
|
||||
* Classes must use this instead of {@link android.app.ITaskStackListener.onActivityPinned}
|
||||
* because there's no guarantee for the PIP manager be return relavent information
|
||||
* correctly. (e.g. {@link isPipShown}).
|
||||
* correctly. (e.g. {@link Pip.isPipShown}).
|
||||
*/
|
||||
void onPipEntered(String packageName);
|
||||
/** Invoked when a PIPed activity is closed. */
|
||||
@@ -27,12 +27,14 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.pip.Pip;
|
||||
import com.android.wm.shell.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Controller for {@link PipControlsView}.
|
||||
@@ -43,9 +45,9 @@ public class PipControlsViewController {
|
||||
private static final float DISABLED_ACTION_ALPHA = 0.54f;
|
||||
|
||||
private final PipControlsView mView;
|
||||
private final PipManager mPipManager;
|
||||
private final LayoutInflater mLayoutInflater;
|
||||
private final Handler mHandler;
|
||||
private final Optional<Pip> mPipOptional;
|
||||
private final PipControlButtonView mPlayPauseButtonView;
|
||||
private MediaController mMediaController;
|
||||
private PipControlButtonView mFocusedChild;
|
||||
@@ -73,12 +75,14 @@ public class PipControlsViewController {
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View v) {
|
||||
updateMediaController();
|
||||
mPipManager.addMediaListener(mPipMediaListener);
|
||||
mPipOptional.ifPresent(
|
||||
pip -> pip.addMediaListener(mPipMediaListener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View v) {
|
||||
mPipManager.removeMediaListener(mPipMediaListener);
|
||||
mPipOptional.ifPresent(
|
||||
pip -> pip.removeMediaListener(mPipMediaListener));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -89,7 +93,7 @@ public class PipControlsViewController {
|
||||
}
|
||||
};
|
||||
|
||||
private final PipManager.MediaListener mPipMediaListener = this::updateMediaController;
|
||||
private final PipController.MediaListener mPipMediaListener = this::updateMediaController;
|
||||
|
||||
private final View.OnFocusChangeListener
|
||||
mFocusChangeListener =
|
||||
@@ -105,12 +109,11 @@ public class PipControlsViewController {
|
||||
};
|
||||
|
||||
|
||||
@Inject
|
||||
public PipControlsViewController(PipControlsView view, PipManager pipManager,
|
||||
public PipControlsViewController(PipControlsView view, Optional<Pip> pipOptional,
|
||||
LayoutInflater layoutInflater, @Main Handler handler) {
|
||||
super();
|
||||
mView = view;
|
||||
mPipManager = pipManager;
|
||||
mPipOptional = pipOptional;
|
||||
mLayoutInflater = layoutInflater;
|
||||
mHandler = handler;
|
||||
|
||||
@@ -121,12 +124,14 @@ public class PipControlsViewController {
|
||||
|
||||
View fullButtonView = mView.getFullButtonView();
|
||||
fullButtonView.setOnFocusChangeListener(mFocusChangeListener);
|
||||
fullButtonView.setOnClickListener(v -> mPipManager.movePipToFullscreen());
|
||||
fullButtonView.setOnClickListener(
|
||||
v -> mPipOptional.ifPresent(pip -> pip.movePipToFullscreen())
|
||||
);
|
||||
|
||||
View closeButtonView = mView.getCloseButtonView();
|
||||
closeButtonView.setOnFocusChangeListener(mFocusChangeListener);
|
||||
closeButtonView.setOnClickListener(v -> {
|
||||
mPipManager.closePip();
|
||||
mPipOptional.ifPresent(pip -> pip.closePip());
|
||||
if (mListener != null) {
|
||||
mListener.onClosed();
|
||||
}
|
||||
@@ -139,24 +144,29 @@ public class PipControlsViewController {
|
||||
if (mMediaController == null || mMediaController.getPlaybackState() == null) {
|
||||
return;
|
||||
}
|
||||
if (mPipManager.getPlaybackState() == PipManager.PLAYBACK_STATE_PAUSED) {
|
||||
mMediaController.getTransportControls().play();
|
||||
} else if (mPipManager.getPlaybackState() == PipManager.PLAYBACK_STATE_PLAYING) {
|
||||
mMediaController.getTransportControls().pause();
|
||||
}
|
||||
mPipOptional.ifPresent(pip -> {
|
||||
if (pip.getPlaybackState() == PipController.PLAYBACK_STATE_PAUSED) {
|
||||
mMediaController.getTransportControls().play();
|
||||
} else if (pip.getPlaybackState() == PipController.PLAYBACK_STATE_PLAYING) {
|
||||
mMediaController.getTransportControls().pause();
|
||||
}
|
||||
});
|
||||
|
||||
// View will be updated later in {@link mMediaControllerCallback}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateMediaController() {
|
||||
MediaController newController = mPipManager.getMediaController();
|
||||
if (mMediaController == newController) {
|
||||
AtomicReference<MediaController> newController = new AtomicReference<>();
|
||||
mPipOptional.ifPresent(pip -> newController.set(pip.getMediaController()));
|
||||
|
||||
if (newController.get() == null || mMediaController == newController.get()) {
|
||||
return;
|
||||
}
|
||||
if (mMediaController != null) {
|
||||
mMediaController.unregisterCallback(mMediaControllerCallback);
|
||||
}
|
||||
mMediaController = newController;
|
||||
mMediaController = newController.get();
|
||||
if (mMediaController != null) {
|
||||
mMediaController.registerCallback(mMediaControllerCallback);
|
||||
}
|
||||
@@ -210,12 +220,14 @@ public class PipControlsViewController {
|
||||
// Hide the media session buttons
|
||||
mPlayPauseButtonView.setVisibility(View.GONE);
|
||||
} else {
|
||||
int state = mPipManager.getPlaybackState();
|
||||
if (state == PipManager.PLAYBACK_STATE_UNAVAILABLE) {
|
||||
AtomicInteger state = new AtomicInteger(PipController.STATE_UNKNOWN);
|
||||
mPipOptional.ifPresent(pip -> state.set(pip.getPlaybackState()));
|
||||
if (state.get() == PipController.STATE_UNKNOWN
|
||||
|| state.get() == PipController.PLAYBACK_STATE_UNAVAILABLE) {
|
||||
mPlayPauseButtonView.setVisibility(View.GONE);
|
||||
} else {
|
||||
mPlayPauseButtonView.setVisibility(View.VISIBLE);
|
||||
if (state == PipManager.PLAYBACK_STATE_PLAYING) {
|
||||
if (state.get() == PipController.PLAYBACK_STATE_PLAYING) {
|
||||
mPlayPauseButtonView.setImageResource(R.drawable.pip_ic_pause_white);
|
||||
mPlayPauseButtonView.setText(R.string.pip_pause);
|
||||
} else {
|
||||
|
||||
@@ -25,17 +25,20 @@ import android.content.pm.ParceledListSlice;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.systemui.pip.Pip;
|
||||
import com.android.systemui.pip.tv.dagger.TvPipComponent;
|
||||
import com.android.wm.shell.R;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Activity to show the PIP menu to control PIP.
|
||||
*/
|
||||
public class PipMenuActivity extends Activity implements PipManager.Listener {
|
||||
|
||||
public class PipMenuActivity extends Activity implements PipController.Listener {
|
||||
private static final String TAG = "PipMenuActivity";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
@@ -43,7 +46,7 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
|
||||
|
||||
private final TvPipComponent.Builder mPipComponentBuilder;
|
||||
private TvPipComponent mTvPipComponent;
|
||||
private final PipManager mPipManager;
|
||||
private final Optional<Pip> mPipOptional;
|
||||
|
||||
private Animator mFadeInAnimation;
|
||||
private Animator mFadeOutAnimation;
|
||||
@@ -51,10 +54,11 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
|
||||
private PipControlsViewController mPipControlsViewController;
|
||||
|
||||
@Inject
|
||||
public PipMenuActivity(TvPipComponent.Builder pipComponentBuilder, PipManager pipManager) {
|
||||
public PipMenuActivity(TvPipComponent.Builder pipComponentBuilder,
|
||||
Optional<Pip> pipOptional) {
|
||||
super();
|
||||
mPipComponentBuilder = pipComponentBuilder;
|
||||
mPipManager = pipManager;
|
||||
mPipOptional = pipOptional;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,15 +66,17 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
|
||||
if (DEBUG) Log.d(TAG, "onCreate()");
|
||||
|
||||
super.onCreate(bundle);
|
||||
if (!mPipManager.isPipShown()) {
|
||||
finish();
|
||||
}
|
||||
mPipOptional.ifPresent(pip -> {
|
||||
if (!pip.isPipShown()) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
setContentView(R.layout.tv_pip_menu);
|
||||
mTvPipComponent = mPipComponentBuilder.pipControlsView(
|
||||
findViewById(R.id.pip_controls)).build();
|
||||
mPipControlsViewController = mTvPipComponent.getPipControlsViewController();
|
||||
|
||||
mPipManager.addListener(this);
|
||||
mPipOptional.ifPresent(pip -> pip.addListener(this));
|
||||
|
||||
mRestorePipSizeWhenClose = true;
|
||||
mFadeInAnimation = AnimatorInflater.loadAnimator(
|
||||
@@ -98,7 +104,7 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
|
||||
if (DEBUG) Log.d(TAG, " > restoring to the default position");
|
||||
|
||||
// When PIP menu activity is closed, restore to the default position.
|
||||
mPipManager.resizePinnedStack(PipManager.STATE_PIP);
|
||||
mPipOptional.ifPresent(pip -> pip.resizePinnedStack(PipController.STATE_PIP));
|
||||
}
|
||||
finish();
|
||||
}
|
||||
@@ -125,9 +131,9 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
|
||||
if (DEBUG) Log.d(TAG, "onDestroy()");
|
||||
|
||||
super.onDestroy();
|
||||
mPipManager.removeListener(this);
|
||||
mPipManager.resumePipResizing(
|
||||
PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
|
||||
mPipOptional.ifPresent(pip -> pip.removeListener(this));
|
||||
mPipOptional.ifPresent(pip -> pip.resumePipResizing(
|
||||
PipController.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,8 +184,8 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
|
||||
if (DEBUG) Log.d(TAG, "onPipResizeAboutToStart()");
|
||||
|
||||
finish();
|
||||
mPipManager.suspendPipResizing(
|
||||
PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
|
||||
mPipOptional.ifPresent(pip -> pip.suspendPipResizing(
|
||||
PipController.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,14 +48,14 @@ import com.android.wm.shell.R;
|
||||
public class PipNotification {
|
||||
private static final String TAG = "PipNotification";
|
||||
private static final String NOTIFICATION_TAG = PipNotification.class.getSimpleName();
|
||||
private static final boolean DEBUG = PipManager.DEBUG;
|
||||
private static final boolean DEBUG = PipController.DEBUG;
|
||||
|
||||
private static final String ACTION_MENU = "PipNotification.menu";
|
||||
private static final String ACTION_CLOSE = "PipNotification.close";
|
||||
|
||||
private final PackageManager mPackageManager;
|
||||
|
||||
private final PipManager mPipManager;
|
||||
private final PipController mPipController;
|
||||
|
||||
private final NotificationManager mNotificationManager;
|
||||
private final Notification.Builder mNotificationBuilder;
|
||||
@@ -70,7 +70,7 @@ public class PipNotification {
|
||||
private String mMediaTitle;
|
||||
private Bitmap mArt;
|
||||
|
||||
private PipManager.Listener mPipListener = new PipManager.Listener() {
|
||||
private PipController.Listener mPipListener = new PipController.Listener() {
|
||||
@Override
|
||||
public void onPipEntered(String packageName) {
|
||||
mPackageName = packageName;
|
||||
@@ -124,26 +124,27 @@ public class PipNotification {
|
||||
}
|
||||
};
|
||||
|
||||
private final PipManager.MediaListener mPipMediaListener = new PipManager.MediaListener() {
|
||||
@Override
|
||||
public void onMediaControllerChanged() {
|
||||
MediaController newController = mPipManager.getMediaController();
|
||||
if (mMediaController == newController) {
|
||||
return;
|
||||
}
|
||||
if (mMediaController != null) {
|
||||
mMediaController.unregisterCallback(mMediaControllerCallback);
|
||||
}
|
||||
mMediaController = newController;
|
||||
if (mMediaController != null) {
|
||||
mMediaController.registerCallback(mMediaControllerCallback);
|
||||
}
|
||||
if (updateMediaControllerMetadata() && mNotified) {
|
||||
// update notification
|
||||
notifyPipNotification();
|
||||
}
|
||||
}
|
||||
};
|
||||
private final PipController.MediaListener mPipMediaListener =
|
||||
new PipController.MediaListener() {
|
||||
@Override
|
||||
public void onMediaControllerChanged() {
|
||||
MediaController newController = mPipController.getMediaController();
|
||||
if (newController == null || mMediaController == newController) {
|
||||
return;
|
||||
}
|
||||
if (mMediaController != null) {
|
||||
mMediaController.unregisterCallback(mMediaControllerCallback);
|
||||
}
|
||||
mMediaController = newController;
|
||||
if (mMediaController != null) {
|
||||
mMediaController.registerCallback(mMediaControllerCallback);
|
||||
}
|
||||
if (updateMediaControllerMetadata() && mNotified) {
|
||||
// update notification
|
||||
notifyPipNotification();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final BroadcastReceiver mEventReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
@@ -153,17 +154,17 @@ public class PipNotification {
|
||||
}
|
||||
switch (intent.getAction()) {
|
||||
case ACTION_MENU:
|
||||
mPipManager.showPictureInPictureMenu();
|
||||
mPipController.showPictureInPictureMenu();
|
||||
break;
|
||||
case ACTION_CLOSE:
|
||||
mPipManager.closePip();
|
||||
mPipController.closePip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public PipNotification(Context context, BroadcastDispatcher broadcastDispatcher,
|
||||
PipManager pipManager) {
|
||||
PipController pipController) {
|
||||
mPackageManager = context.getPackageManager();
|
||||
|
||||
mNotificationManager = (NotificationManager) context.getSystemService(
|
||||
@@ -177,9 +178,9 @@ public class PipNotification {
|
||||
.setContentIntent(createPendingIntent(context, ACTION_MENU))
|
||||
.setDeleteIntent(createPendingIntent(context, ACTION_CLOSE)));
|
||||
|
||||
mPipManager = pipManager;
|
||||
mPipManager.addListener(mPipListener);
|
||||
mPipManager.addMediaListener(mPipMediaListener);
|
||||
mPipController = pipController;
|
||||
pipController.addListener(mPipListener);
|
||||
pipController.addMediaListener(mPipMediaListener);
|
||||
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(ACTION_MENU);
|
||||
@@ -190,7 +191,7 @@ public class PipNotification {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by {@link PipManager} when the configuration is changed.
|
||||
* Called by {@link PipController} when the configuration is changed.
|
||||
*/
|
||||
void onConfigurationChanged(Context context) {
|
||||
Resources res = context.getResources();
|
||||
@@ -227,8 +228,8 @@ public class PipNotification {
|
||||
private boolean updateMediaControllerMetadata() {
|
||||
String title = null;
|
||||
Bitmap art = null;
|
||||
if (mPipManager.getMediaController() != null) {
|
||||
MediaMetadata metadata = mPipManager.getMediaController().getMetadata();
|
||||
if (mPipController.getMediaController() != null) {
|
||||
MediaMetadata metadata = mPipController.getMediaController().getMetadata();
|
||||
if (metadata != null) {
|
||||
title = metadata.getString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE);
|
||||
if (TextUtils.isEmpty(title)) {
|
||||
@@ -248,6 +249,7 @@ public class PipNotification {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private String getNotificationTitle() {
|
||||
if (!TextUtils.isEmpty(mMediaTitle)) {
|
||||
return mMediaTitle;
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.pip.tv.dagger;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.android.systemui.pip.BasePipManager;
|
||||
import com.android.systemui.pip.tv.PipManager;
|
||||
import com.android.systemui.pip.tv.PipMenuActivity;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.multibindings.ClassKey;
|
||||
import dagger.multibindings.IntoMap;
|
||||
|
||||
/**
|
||||
* Dagger module for TV Pip.
|
||||
*/
|
||||
@Module(subcomponents = {TvPipComponent.class})
|
||||
public abstract class PipModule {
|
||||
|
||||
/** Binds PipManager as the default BasePipManager. */
|
||||
@Binds
|
||||
public abstract BasePipManager providePipManager(PipManager pipManager);
|
||||
|
||||
|
||||
/** Inject into PipMenuActivity. */
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(PipMenuActivity.class)
|
||||
public abstract Activity providePipMenuActivity(PipMenuActivity activity);
|
||||
}
|
||||
@@ -75,8 +75,8 @@ import com.android.systemui.navigationbar.NavigationBarController;
|
||||
import com.android.systemui.navigationbar.NavigationBarView;
|
||||
import com.android.systemui.navigationbar.NavigationModeController;
|
||||
import com.android.systemui.onehanded.OneHandedUI;
|
||||
import com.android.systemui.pip.Pip;
|
||||
import com.android.systemui.pip.PipAnimationController;
|
||||
import com.android.systemui.pip.PipUI;
|
||||
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
|
||||
import com.android.systemui.settings.CurrentUserTracker;
|
||||
import com.android.systemui.shared.recents.IOverviewProxy;
|
||||
@@ -122,7 +122,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
|
||||
private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000;
|
||||
|
||||
private final Context mContext;
|
||||
private final PipUI mPipUI;
|
||||
private final Optional<Pip> mPipOptional;
|
||||
private final Optional<Lazy<StatusBar>> mStatusBarOptionalLazy;
|
||||
private final Optional<SplitScreen> mSplitScreenOptional;
|
||||
private SysUiState mSysUiState;
|
||||
@@ -388,7 +388,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
|
||||
}
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mPipUI.setShelfHeight(visible, shelfHeight);
|
||||
mPipOptional.ifPresent(
|
||||
pip -> pip.setShelfHeight(visible, shelfHeight));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -413,7 +414,9 @@ public class OverviewProxyService extends CurrentUserTracker implements
|
||||
}
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mPipUI.setPinnedStackAnimationType(PipAnimationController.ANIM_TYPE_ALPHA);
|
||||
mPipOptional.ifPresent(
|
||||
pip -> pip.setPinnedStackAnimationType(
|
||||
PipAnimationController.ANIM_TYPE_ALPHA));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -426,7 +429,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
|
||||
}
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mPipUI.setPinnedStackAnimationListener(listener);
|
||||
mPipOptional.ifPresent(
|
||||
pip -> pip.setPinnedStackAnimationListener(listener));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -603,14 +607,16 @@ public class OverviewProxyService extends CurrentUserTracker implements
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
@Inject
|
||||
public OverviewProxyService(Context context, CommandQueue commandQueue,
|
||||
Lazy<NavigationBarController> navBarControllerLazy, NavigationModeController navModeController,
|
||||
Lazy<NavigationBarController> navBarControllerLazy,
|
||||
NavigationModeController navModeController,
|
||||
NotificationShadeWindowController statusBarWinController, SysUiState sysUiState,
|
||||
PipUI pipUI, Optional<SplitScreen> splitScreenOptional,
|
||||
Optional<Pip> pipOptional,
|
||||
Optional<SplitScreen> splitScreenOptional,
|
||||
Optional<Lazy<StatusBar>> statusBarOptionalLazy, OneHandedUI oneHandedUI,
|
||||
BroadcastDispatcher broadcastDispatcher) {
|
||||
super(broadcastDispatcher);
|
||||
mContext = context;
|
||||
mPipUI = pipUI;
|
||||
mPipOptional = pipOptional;
|
||||
mStatusBarOptionalLazy = statusBarOptionalLazy;
|
||||
mHandler = new Handler();
|
||||
mNavBarControllerLazy = navBarControllerLazy;
|
||||
@@ -916,6 +922,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
|
||||
|
||||
/**
|
||||
* Notifies the Launcher of split screen size changes
|
||||
*
|
||||
* @param secondaryWindowBounds Bounds of the secondary window including the insets
|
||||
* @param secondaryWindowInsets stable insets received by the secondary window
|
||||
*/
|
||||
|
||||
@@ -17,12 +17,11 @@
|
||||
package com.android.systemui.tv;
|
||||
|
||||
import com.android.systemui.dagger.GlobalRootComponent;
|
||||
import com.android.systemui.pip.tv.dagger.PipModule;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
|
||||
@Module(includes = {PipModule.class})
|
||||
@Module()
|
||||
interface TvSystemUIBinder {
|
||||
@Binds
|
||||
GlobalRootComponent bindGlobalRootComponent(TvGlobalRootComponent globalRootComponent);
|
||||
|
||||
@@ -62,7 +62,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
||||
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
|
||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||
import com.android.systemui.wmshell.WMShellModule;
|
||||
import com.android.systemui.wmshell.TvWMShellModule;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
@@ -76,7 +76,7 @@ import dagger.Provides;
|
||||
*/
|
||||
@Module(includes = {
|
||||
QSModule.class,
|
||||
WMShellModule.class
|
||||
TvWMShellModule.class,
|
||||
},
|
||||
subcomponents = {
|
||||
})
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 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;
|
||||
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.tv.PipController;
|
||||
import com.android.systemui.pip.tv.PipNotification;
|
||||
import com.android.systemui.pip.tv.dagger.TvPipComponent;
|
||||
import com.android.systemui.stackdivider.SplitScreen;
|
||||
import com.android.systemui.stackdivider.SplitScreenController;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
import com.android.wm.shell.common.SystemWindows;
|
||||
import com.android.wm.shell.common.TransactionPool;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
/**
|
||||
* Provides dependencies from {@link com.android.wm.shell} which could be customized among different
|
||||
* branches of SystemUI.
|
||||
*/
|
||||
// TODO(b/162923491): Move most of these dependencies into WMSingleton scope.
|
||||
@Module(includes = WMShellBaseModule.class, subcomponents = {TvPipComponent.class})
|
||||
public class TvWMShellModule {
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static DisplayImeController provideDisplayImeController(IWindowManager wmService,
|
||||
DisplayController displayController, @Main Handler mainHandler,
|
||||
TransactionPool transactionPool) {
|
||||
return new DisplayImeController(wmService, displayController, mainHandler, transactionPool);
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static Pip providePipController(Context context,
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
PipBoundsHandler pipBoundsHandler,
|
||||
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
|
||||
PipTaskOrganizer pipTaskOrganizer) {
|
||||
return new PipController(context, broadcastDispatcher, pipBoundsHandler,
|
||||
pipSurfaceTransactionHelper, pipTaskOrganizer);
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static SplitScreen provideSplitScreen(Context context,
|
||||
DisplayController displayController, SystemWindows systemWindows,
|
||||
DisplayImeController displayImeController, @Main Handler handler,
|
||||
TransactionPool transactionPool, ShellTaskOrganizer shellTaskOrganizer) {
|
||||
return new SplitScreenController(context, displayController, systemWindows,
|
||||
displayImeController, handler, transactionPool, shellTaskOrganizer);
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static PipNotification providePipNotification(Context context,
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
PipController pipController) {
|
||||
return new PipNotification(context, broadcastDispatcher, pipController);
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static PipBoundsHandler providesPipBoundsHandler(Context context) {
|
||||
return new PipBoundsHandler(context);
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static PipTaskOrganizer providesPipTaskOrganizer(Context context,
|
||||
PipBoundsHandler pipBoundsHandler,
|
||||
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
|
||||
Optional<SplitScreen> splitScreenOptional, DisplayController displayController,
|
||||
PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
|
||||
return new PipTaskOrganizer(context, pipBoundsHandler,
|
||||
pipSurfaceTransactionHelper, splitScreenOptional, displayController,
|
||||
pipUiEventLogger, shellTaskOrganizer);
|
||||
}
|
||||
}
|
||||
@@ -25,10 +25,12 @@ import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.keyguard.KeyguardUpdateMonitorCallback;
|
||||
import com.android.systemui.SystemUI;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.pip.Pip;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
import com.android.systemui.shared.tracing.ProtoTraceable;
|
||||
import com.android.systemui.stackdivider.SplitScreen;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.tracing.ProtoTracer;
|
||||
import com.android.systemui.tracing.nano.SystemUiTraceProto;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
@@ -46,20 +48,27 @@ import javax.inject.Inject;
|
||||
* Proxy in SysUiScope to delegate events to controllers in WM Shell library.
|
||||
*/
|
||||
@SysUISingleton
|
||||
public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTraceProto> {
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTraceProto>,
|
||||
CommandQueue.Callbacks {
|
||||
private final CommandQueue mCommandQueue;
|
||||
private final DisplayImeController mDisplayImeController;
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final Optional<Pip> mPipOptional;
|
||||
private final Optional<SplitScreen> mSplitScreenOptional;
|
||||
private final ProtoTracer mProtoTracer;
|
||||
|
||||
@Inject
|
||||
WMShell(Context context, KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
public WMShell(Context context, CommandQueue commandQueue,
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
DisplayImeController displayImeController,
|
||||
Optional<Pip> pipOptional,
|
||||
Optional<SplitScreen> splitScreenOptional,
|
||||
ProtoTracer protoTracer) {
|
||||
super(context);
|
||||
mCommandQueue = commandQueue;
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mDisplayImeController = displayImeController;
|
||||
mPipOptional = pipOptional;
|
||||
mSplitScreenOptional = splitScreenOptional;
|
||||
mProtoTracer = protoTracer;
|
||||
mProtoTracer.add(this);
|
||||
@@ -70,11 +79,22 @@ public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTr
|
||||
// This is to prevent circular init problem by separating registration step out of its
|
||||
// constructor. And make sure the initialization of DisplayImeController won't depend on
|
||||
// specific feature anymore.
|
||||
mCommandQueue.addCallback(this);
|
||||
mDisplayImeController.startMonitorDisplays();
|
||||
|
||||
mPipOptional.ifPresent(this::initPip);
|
||||
mSplitScreenOptional.ifPresent(this::initSplitScreen);
|
||||
}
|
||||
|
||||
private void initPip(Pip pip) {
|
||||
mCommandQueue.addCallback(new CommandQueue.Callbacks() {
|
||||
@Override
|
||||
public void showPictureInPictureMenu() {
|
||||
pip.showPictureInPictureMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initSplitScreen(SplitScreen splitScreen) {
|
||||
mKeyguardUpdateMonitor.registerCallback(new KeyguardUpdateMonitorCallback() {
|
||||
@Override
|
||||
|
||||
@@ -23,8 +23,11 @@ import android.view.IWindowManager;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
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.stackdivider.SplitScreen;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.util.DeviceConfigProxy;
|
||||
import com.android.systemui.util.FloatingContentCoordinator;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
@@ -74,6 +77,13 @@ public abstract class WMShellBaseModule {
|
||||
return new PipUiEventLogger(uiEventLogger);
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static PipSurfaceTransactionHelper providesPipSurfaceTransactionHelper(Context context,
|
||||
ConfigurationController configController) {
|
||||
return new PipSurfaceTransactionHelper(context, configController);
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static SystemWindows provideSystemWindows(DisplayController displayController,
|
||||
@@ -89,6 +99,9 @@ public abstract class WMShellBaseModule {
|
||||
return organizer;
|
||||
}
|
||||
|
||||
@BindsOptionalOf
|
||||
abstract Pip optionalPip();
|
||||
|
||||
@BindsOptionalOf
|
||||
abstract SplitScreen optionalSplitScreen();
|
||||
}
|
||||
|
||||
@@ -20,16 +20,29 @@ 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.PipController;
|
||||
import com.android.systemui.stackdivider.SplitScreen;
|
||||
import com.android.systemui.stackdivider.SplitScreenController;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.util.DeviceConfigProxy;
|
||||
import com.android.systemui.util.FloatingContentCoordinator;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
import com.android.wm.shell.common.SystemWindows;
|
||||
import com.android.wm.shell.common.TransactionPool;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@@ -48,6 +61,26 @@ public class WMShellModule {
|
||||
return new DisplayImeController(wmService, displayController, mainHandler, transactionPool);
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static Pip providePipController(Context context,
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
ConfigurationController configController,
|
||||
DeviceConfigProxy deviceConfig,
|
||||
DisplayController displayController,
|
||||
FloatingContentCoordinator floatingContentCoordinator,
|
||||
SysUiState sysUiState,
|
||||
PipBoundsHandler pipBoundsHandler,
|
||||
PipSurfaceTransactionHelper surfaceTransactionHelper,
|
||||
PipTaskOrganizer pipTaskOrganizer,
|
||||
PipUiEventLogger pipUiEventLogger) {
|
||||
return new PipController(context, broadcastDispatcher, configController, deviceConfig,
|
||||
displayController, floatingContentCoordinator, sysUiState, pipBoundsHandler,
|
||||
surfaceTransactionHelper,
|
||||
pipTaskOrganizer,
|
||||
pipUiEventLogger);
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static SplitScreen provideSplitScreen(Context context,
|
||||
@@ -57,4 +90,23 @@ public class WMShellModule {
|
||||
return new SplitScreenController(context, displayController, systemWindows,
|
||||
displayImeController, handler, transactionPool, shellTaskOrganizer);
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static PipBoundsHandler providesPipBoundsHandler(Context context) {
|
||||
return new PipBoundsHandler(context);
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static PipTaskOrganizer providesPipTaskOrganizer(Context context,
|
||||
PipBoundsHandler pipBoundsHandler,
|
||||
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
|
||||
Optional<SplitScreen> splitScreenOptional, DisplayController displayController,
|
||||
PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
|
||||
return new PipTaskOrganizer(context, pipBoundsHandler,
|
||||
pipSurfaceTransactionHelper, splitScreenOptional, displayController,
|
||||
pipUiEventLogger, shellTaskOrganizer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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 org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.pip.Pip;
|
||||
import com.android.systemui.pip.tv.PipController;
|
||||
import com.android.systemui.stackdivider.SplitScreen;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.tracing.ProtoTracer;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class WMShellTest extends SysuiTestCase {
|
||||
|
||||
Instrumentation mInstrumentation;
|
||||
WMShell mWMShell;
|
||||
@Mock Context mContext;
|
||||
@Mock CommandQueue mCommandQueue;
|
||||
@Mock KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
@Mock DisplayImeController mDisplayImeController;
|
||||
@Mock Optional<Pip> mPipOptional;
|
||||
@Mock Optional<SplitScreen> mSplitScreenOptional;
|
||||
@Mock PipController mPipController;
|
||||
@Mock ProtoTracer mProtoTracer;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mInstrumentation = InstrumentationRegistry.getInstrumentation();
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mWMShell = new WMShell(mContext, mCommandQueue, mKeyguardUpdateMonitor,
|
||||
mDisplayImeController, mPipOptional, mSplitScreenOptional, mProtoTracer);
|
||||
mWMShell.start();
|
||||
when(mPipOptional.get()).thenReturn(mPipController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWMShellRegisterCommandQueue() {
|
||||
verify(mCommandQueue, times(1)).addCallback(mWMShell);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user