1/ Initial preparation for separate shell main thread
- Add @BinderThread/@ShellMainThread/@SysUIMainThread annotations for some common shell classes and callbacks - Add mechanism to inject shell-anim/shell-main/sysui-main/etc executors (removed AnimationThread static instance) (Note: The shell main thread will still be the sysui main thread) Bug: 161979899 Test: atest WMShellUnitTests Change-Id: I4adfeaebe5b79fab7c9451eef7b54fcdf4d8d40a
This commit is contained in:
@@ -213,12 +213,12 @@ public class TaskOrganizer extends WindowOrganizer {
|
||||
private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() {
|
||||
@Override
|
||||
public void addStartingWindow(ActivityManager.RunningTaskInfo taskInfo, IBinder appToken) {
|
||||
TaskOrganizer.this.addStartingWindow(taskInfo, appToken);
|
||||
mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(taskInfo, appToken));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStartingWindow(ActivityManager.RunningTaskInfo taskInfo) {
|
||||
TaskOrganizer.this.removeStartingWindow(taskInfo);
|
||||
mExecutor.execute(() -> TaskOrganizer.this.removeStartingWindow(taskInfo));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -122,6 +122,7 @@ android_library {
|
||||
"kotlinx-coroutines-android",
|
||||
"kotlinx-coroutines-core",
|
||||
"iconloader_base",
|
||||
"jsr330",
|
||||
"protolog-lib",
|
||||
"SettingsLib",
|
||||
"WindowManager-Shell-proto",
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.wm.shell;
|
||||
import android.view.Gravity;
|
||||
|
||||
import com.android.wm.shell.apppairs.AppPairs;
|
||||
import com.android.wm.shell.common.annotations.ExternalThread;
|
||||
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
|
||||
import com.android.wm.shell.letterbox.LetterboxConfigController;
|
||||
import com.android.wm.shell.onehanded.OneHanded;
|
||||
@@ -61,6 +62,7 @@ public final class ShellCommandHandler {
|
||||
}
|
||||
|
||||
/** Dumps WM Shell internal state. */
|
||||
@ExternalThread
|
||||
public void dump(PrintWriter pw) {
|
||||
mShellTaskOrganizer.dump(pw, "");
|
||||
pw.println();
|
||||
@@ -76,6 +78,7 @@ public final class ShellCommandHandler {
|
||||
|
||||
|
||||
/** Returns {@code true} if command was found and executed. */
|
||||
@ExternalThread
|
||||
public boolean handleCommand(String[] args, PrintWriter pw) {
|
||||
if (args.length < 2) {
|
||||
// Argument at position 0 is "WMShell".
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_LETTERB
|
||||
|
||||
import com.android.wm.shell.apppairs.AppPairs;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
import com.android.wm.shell.common.annotations.ExternalThread;
|
||||
import com.android.wm.shell.draganddrop.DragAndDropController;
|
||||
import com.android.wm.shell.letterbox.LetterboxTaskListener;
|
||||
import com.android.wm.shell.splitscreen.SplitScreen;
|
||||
@@ -56,6 +57,7 @@ public class ShellInit {
|
||||
mFullscreenTaskListener = fullscreenTaskListener;
|
||||
}
|
||||
|
||||
@ExternalThread
|
||||
public void init() {
|
||||
// Start listening for display changes
|
||||
mDisplayImeController.startMonitorDisplays();
|
||||
|
||||
@@ -31,12 +31,14 @@ import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.ITaskOrganizerController;
|
||||
import android.window.TaskAppearedInfo;
|
||||
import android.window.TaskOrganizer;
|
||||
|
||||
import androidx.annotation.BinderThread;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@@ -45,6 +47,7 @@ import com.android.internal.protolog.common.ProtoLog;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
||||
import com.android.wm.shell.common.TransactionPool;
|
||||
import com.android.wm.shell.common.annotations.ShellMainThread;
|
||||
import com.android.wm.shell.startingsurface.StartingSurfaceDrawer;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -119,7 +122,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
|
||||
ShellExecutor mainExecutor, ShellExecutor animExecutor, Context context) {
|
||||
super(taskOrganizerController, mainExecutor);
|
||||
mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor);
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions);
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) mTransitions.register(this);
|
||||
// TODO(b/131727939) temporarily live here, the starting surface drawer should be controlled
|
||||
// by a controller, that class should be create while porting
|
||||
// ActivityRecord#addStartingWindow to WMShell.
|
||||
|
||||
@@ -23,9 +23,9 @@ import static android.window.TransitionInfo.TRANSIT_SHOW;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.MainThread;
|
||||
import android.annotation.NonNull;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Slog;
|
||||
@@ -35,15 +35,18 @@ import android.window.ITransitionPlayer;
|
||||
import android.window.TransitionInfo;
|
||||
import android.window.WindowOrganizer;
|
||||
|
||||
import androidx.annotation.BinderThread;
|
||||
|
||||
import com.android.internal.protolog.common.ProtoLog;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.common.TransactionPool;
|
||||
import com.android.wm.shell.common.annotations.ShellMainThread;
|
||||
import com.android.wm.shell.protolog.ShellProtoLogGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/** Plays transition animations */
|
||||
public class Transitions extends ITransitionPlayer.Stub {
|
||||
public class Transitions {
|
||||
private static final String TAG = "ShellTransitions";
|
||||
|
||||
/** Set to {@code true} to enable shell transitions. */
|
||||
@@ -54,6 +57,7 @@ public class Transitions extends ITransitionPlayer.Stub {
|
||||
private final TransactionPool mTransactionPool;
|
||||
private final ShellExecutor mMainExecutor;
|
||||
private final ShellExecutor mAnimExecutor;
|
||||
private final TransitionPlayerImpl mPlayerImpl;
|
||||
|
||||
/** Keeps track of currently tracked transitions and all the animations associated with each */
|
||||
private final ArrayMap<IBinder, ArrayList<Animator>> mActiveTransitions = new ArrayMap<>();
|
||||
@@ -64,6 +68,11 @@ public class Transitions extends ITransitionPlayer.Stub {
|
||||
mTransactionPool = pool;
|
||||
mMainExecutor = mainExecutor;
|
||||
mAnimExecutor = animExecutor;
|
||||
mPlayerImpl = new TransitionPlayerImpl();
|
||||
}
|
||||
|
||||
public void register(ShellTaskOrganizer taskOrganizer) {
|
||||
taskOrganizer.registerTransitionPlayer(mPlayerImpl);
|
||||
}
|
||||
|
||||
// TODO(shell-transitions): real animations
|
||||
@@ -115,77 +124,73 @@ public class Transitions extends ITransitionPlayer.Stub {
|
||||
|| type == WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionReady(@NonNull IBinder transitionToken, @NonNull TransitionInfo info,
|
||||
private void onTransitionReady(@NonNull IBinder transitionToken, @NonNull TransitionInfo info,
|
||||
@NonNull SurfaceControl.Transaction t) {
|
||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "onTransitionReady %s: %s",
|
||||
transitionToken, info);
|
||||
// start task
|
||||
mMainExecutor.execute(() -> {
|
||||
if (!mActiveTransitions.containsKey(transitionToken)) {
|
||||
Slog.e(TAG, "Got transitionReady for non-active transition " + transitionToken
|
||||
+ " expecting one of " + mActiveTransitions.keySet());
|
||||
}
|
||||
if (mActiveTransitions.get(transitionToken) != null) {
|
||||
throw new IllegalStateException("Got a duplicate onTransitionReady call for "
|
||||
+ transitionToken);
|
||||
}
|
||||
mActiveTransitions.put(transitionToken, new ArrayList<>());
|
||||
boolean isOpening = isOpeningType(info.getType());
|
||||
if (info.getRootLeash().isValid()) {
|
||||
t.show(info.getRootLeash());
|
||||
}
|
||||
// changes should be ordered top-to-bottom in z
|
||||
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(i);
|
||||
final SurfaceControl leash = change.getLeash();
|
||||
final int mode = info.getChanges().get(i).getMode();
|
||||
if (!mActiveTransitions.containsKey(transitionToken)) {
|
||||
Slog.e(TAG, "Got transitionReady for non-active transition " + transitionToken
|
||||
+ " expecting one of " + mActiveTransitions.keySet());
|
||||
}
|
||||
if (mActiveTransitions.get(transitionToken) != null) {
|
||||
throw new IllegalStateException("Got a duplicate onTransitionReady call for "
|
||||
+ transitionToken);
|
||||
}
|
||||
mActiveTransitions.put(transitionToken, new ArrayList<>());
|
||||
boolean isOpening = isOpeningType(info.getType());
|
||||
if (info.getRootLeash().isValid()) {
|
||||
t.show(info.getRootLeash());
|
||||
}
|
||||
// changes should be ordered top-to-bottom in z
|
||||
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(i);
|
||||
final SurfaceControl leash = change.getLeash();
|
||||
final int mode = info.getChanges().get(i).getMode();
|
||||
|
||||
// Don't animate anything with an animating parent
|
||||
if (change.getParent() != null) {
|
||||
if (mode == TRANSIT_OPEN || mode == TRANSIT_SHOW) {
|
||||
t.show(leash);
|
||||
t.setMatrix(leash, 1, 0, 0, 1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
t.reparent(leash, info.getRootLeash());
|
||||
t.setPosition(leash, change.getEndAbsBounds().left - info.getRootOffset().x,
|
||||
change.getEndAbsBounds().top - info.getRootOffset().y);
|
||||
// Put all the OPEN/SHOW on top
|
||||
// Don't animate anything with an animating parent
|
||||
if (change.getParent() != null) {
|
||||
if (mode == TRANSIT_OPEN || mode == TRANSIT_SHOW) {
|
||||
t.show(leash);
|
||||
t.setMatrix(leash, 1, 0, 0, 1);
|
||||
if (isOpening) {
|
||||
// put on top and fade in
|
||||
t.setLayer(leash, info.getChanges().size() - i);
|
||||
t.setAlpha(leash, 0.f);
|
||||
startExampleAnimation(transitionToken, leash, true /* show */);
|
||||
} else {
|
||||
// put on bottom and leave it visible without fade
|
||||
t.setLayer(leash, -i);
|
||||
t.setAlpha(leash, 1.f);
|
||||
}
|
||||
} else if (mode == TRANSIT_CLOSE || mode == TRANSIT_HIDE) {
|
||||
if (isOpening) {
|
||||
// put on bottom and leave visible without fade
|
||||
t.setLayer(leash, -i);
|
||||
} else {
|
||||
// put on top and fade out
|
||||
t.setLayer(leash, info.getChanges().size() - i);
|
||||
startExampleAnimation(transitionToken, leash, false /* show */);
|
||||
}
|
||||
} else {
|
||||
t.setLayer(leash, info.getChanges().size() - i);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
t.apply();
|
||||
onFinish(transitionToken);
|
||||
});
|
||||
|
||||
t.reparent(leash, info.getRootLeash());
|
||||
t.setPosition(leash, change.getEndAbsBounds().left - info.getRootOffset().x,
|
||||
change.getEndAbsBounds().top - info.getRootOffset().y);
|
||||
// Put all the OPEN/SHOW on top
|
||||
if (mode == TRANSIT_OPEN || mode == TRANSIT_SHOW) {
|
||||
t.show(leash);
|
||||
t.setMatrix(leash, 1, 0, 0, 1);
|
||||
if (isOpening) {
|
||||
// put on top and fade in
|
||||
t.setLayer(leash, info.getChanges().size() - i);
|
||||
t.setAlpha(leash, 0.f);
|
||||
startExampleAnimation(transitionToken, leash, true /* show */);
|
||||
} else {
|
||||
// put on bottom and leave it visible without fade
|
||||
t.setLayer(leash, -i);
|
||||
t.setAlpha(leash, 1.f);
|
||||
}
|
||||
} else if (mode == TRANSIT_CLOSE || mode == TRANSIT_HIDE) {
|
||||
if (isOpening) {
|
||||
// put on bottom and leave visible without fade
|
||||
t.setLayer(leash, -i);
|
||||
} else {
|
||||
// put on top and fade out
|
||||
t.setLayer(leash, info.getChanges().size() - i);
|
||||
startExampleAnimation(transitionToken, leash, false /* show */);
|
||||
}
|
||||
} else {
|
||||
t.setLayer(leash, info.getChanges().size() - i);
|
||||
}
|
||||
}
|
||||
t.apply();
|
||||
onFinish(transitionToken);
|
||||
}
|
||||
|
||||
@MainThread
|
||||
private void onFinish(IBinder transition) {
|
||||
if (!mActiveTransitions.get(transition).isEmpty()) return;
|
||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
|
||||
@@ -194,16 +199,32 @@ public class Transitions extends ITransitionPlayer.Stub {
|
||||
mOrganizer.finishTransition(transition, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestStartTransition(int type, @NonNull IBinder transitionToken) {
|
||||
private void requestStartTransition(int type, @NonNull IBinder transitionToken) {
|
||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition requested: type=%d %s",
|
||||
type, transitionToken);
|
||||
mMainExecutor.execute(() -> {
|
||||
if (mActiveTransitions.containsKey(transitionToken)) {
|
||||
throw new RuntimeException("Transition already started " + transitionToken);
|
||||
}
|
||||
IBinder transition = mOrganizer.startTransition(type, transitionToken, null /* wct */);
|
||||
mActiveTransitions.put(transition, null);
|
||||
});
|
||||
|
||||
if (mActiveTransitions.containsKey(transitionToken)) {
|
||||
throw new RuntimeException("Transition already started " + transitionToken);
|
||||
}
|
||||
IBinder transition = mOrganizer.startTransition(type, transitionToken, null /* wct */);
|
||||
mActiveTransitions.put(transition, null);
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
private class TransitionPlayerImpl extends ITransitionPlayer.Stub {
|
||||
@Override
|
||||
public void onTransitionReady(IBinder iBinder, TransitionInfo transitionInfo,
|
||||
SurfaceControl.Transaction transaction) throws RemoteException {
|
||||
mMainExecutor.execute(() -> {
|
||||
Transitions.this.onTransitionReady(iBinder, transitionInfo, transaction);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestStartTransition(int i, IBinder iBinder) throws RemoteException {
|
||||
mMainExecutor.execute(() -> {
|
||||
Transitions.this.requestStartTransition(i, iBinder);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ package com.android.wm.shell;
|
||||
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
|
||||
import android.app.WindowConfiguration;
|
||||
import android.os.RemoteException;
|
||||
import android.view.WindowManagerGlobal;
|
||||
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.pip.PinnedStackListenerForwarder;
|
||||
import com.android.wm.shell.pip.PinnedStackListenerForwarder.PinnedStackListener;
|
||||
|
||||
/**
|
||||
* The singleton wrapper to communicate between WindowManagerService and WMShell features
|
||||
@@ -31,32 +31,30 @@ import com.android.wm.shell.pip.PinnedStackListenerForwarder;
|
||||
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();
|
||||
private final PinnedStackListenerForwarder mPinnedStackListenerForwarder;
|
||||
|
||||
public WindowManagerShellWrapper(ShellExecutor shellMainExecutor) {
|
||||
mPinnedStackListenerForwarder = new PinnedStackListenerForwarder(shellMainExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
public void addPinnedStackListener(PinnedStackListener listener)
|
||||
throws RemoteException {
|
||||
mPinnedStackListenerForwarder.addListener(listener);
|
||||
WindowManagerGlobal.getWindowManagerService().registerPinnedStackListener(
|
||||
DEFAULT_DISPLAY, mPinnedStackListenerForwarder);
|
||||
mPinnedStackListenerForwarder.register(DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a pinned stack listener.
|
||||
*/
|
||||
public void removePinnedStackListener(
|
||||
PinnedStackListenerForwarder.PinnedStackListener listener) {
|
||||
public void removePinnedStackListener(PinnedStackListener listener) {
|
||||
mPinnedStackListenerForwarder.removeListener(listener);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,14 @@ import android.app.ActivityManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.wm.shell.common.annotations.ExternalThread;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Interface to engage app pairs feature.
|
||||
*/
|
||||
@ExternalThread
|
||||
public interface AppPairs {
|
||||
/** Pairs indicated tasks. */
|
||||
boolean pair(int task1, int task2);
|
||||
|
||||
@@ -1213,7 +1213,7 @@ public class BubbleController implements Bubbles {
|
||||
@Override
|
||||
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
|
||||
if (mStackView != null) {
|
||||
mStackView.post(() -> mStackView.onImeVisibilityChanged(imeVisible, imeHeight));
|
||||
mStackView.onImeVisibilityChanged(imeVisible, imeHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import android.view.View;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.wm.shell.common.annotations.ExternalThread;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -40,6 +42,7 @@ import java.util.function.IntConsumer;
|
||||
/**
|
||||
* Interface to engage bubbles feature.
|
||||
*/
|
||||
@ExternalThread
|
||||
public interface Bubbles {
|
||||
|
||||
@Retention(SOURCE)
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* 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.wm.shell.common;
|
||||
|
||||
import static android.os.Process.THREAD_PRIORITY_DISPLAY;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.os.HandlerThread;
|
||||
import android.util.Singleton;
|
||||
|
||||
/**
|
||||
* A singleton thread for Shell to run animations on.
|
||||
*/
|
||||
public class AnimationThread extends HandlerThread {
|
||||
private ShellExecutor mExecutor;
|
||||
|
||||
private AnimationThread() {
|
||||
super("wmshell.anim", THREAD_PRIORITY_DISPLAY);
|
||||
}
|
||||
|
||||
/** Get the singleton instance of this thread */
|
||||
public static AnimationThread instance() {
|
||||
return sAnimationThreadSingleton.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a shared {@link ShellExecutor} associated with this thread
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public ShellExecutor getExecutor() {
|
||||
if (mExecutor == null) {
|
||||
mExecutor = new HandlerExecutor(getThreadHandler());
|
||||
}
|
||||
return mExecutor;
|
||||
}
|
||||
|
||||
private static final Singleton<AnimationThread> sAnimationThreadSingleton =
|
||||
new Singleton<AnimationThread>() {
|
||||
@Override
|
||||
protected AnimationThread create() {
|
||||
final AnimationThread animThread = new AnimationThread();
|
||||
animThread.start();
|
||||
return animThread;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -23,6 +23,10 @@ import android.view.IDisplayWindowRotationController;
|
||||
import android.view.IWindowManager;
|
||||
import android.window.WindowContainerTransaction;
|
||||
|
||||
import androidx.annotation.BinderThread;
|
||||
|
||||
import com.android.wm.shell.common.annotations.ShellMainThread;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
@@ -35,39 +39,18 @@ public class DisplayChangeController {
|
||||
|
||||
private final Handler mHandler;
|
||||
private final IWindowManager mWmService;
|
||||
private final IDisplayWindowRotationController mControllerImpl;
|
||||
|
||||
private final ArrayList<OnDisplayChangingListener> mRotationListener =
|
||||
new ArrayList<>();
|
||||
private final ArrayList<OnDisplayChangingListener> mTmpListeners = new ArrayList<>();
|
||||
|
||||
private final IDisplayWindowRotationController mDisplayRotationController =
|
||||
new IDisplayWindowRotationController.Stub() {
|
||||
@Override
|
||||
public void onRotateDisplay(int displayId, final int fromRotation,
|
||||
final int toRotation, IDisplayWindowRotationCallback callback) {
|
||||
mHandler.post(() -> {
|
||||
WindowContainerTransaction t = new WindowContainerTransaction();
|
||||
synchronized (mRotationListener) {
|
||||
mTmpListeners.clear();
|
||||
// Make a local copy in case the handlers add/remove themselves.
|
||||
mTmpListeners.addAll(mRotationListener);
|
||||
}
|
||||
for (OnDisplayChangingListener c : mTmpListeners) {
|
||||
c.onRotateDisplay(displayId, fromRotation, toRotation, t);
|
||||
}
|
||||
try {
|
||||
callback.continueRotateDisplay(toRotation, t);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
public DisplayChangeController(Handler mainHandler, IWindowManager wmService) {
|
||||
mHandler = mainHandler;
|
||||
mWmService = wmService;
|
||||
mControllerImpl = new DisplayWindowRotationControllerImpl();
|
||||
try {
|
||||
mWmService.setDisplayWindowRotationController(mDisplayRotationController);
|
||||
mWmService.setDisplayWindowRotationController(mControllerImpl);
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException("Unable to register rotation controller");
|
||||
}
|
||||
@@ -91,10 +74,41 @@ public class DisplayChangeController {
|
||||
}
|
||||
}
|
||||
|
||||
private void onRotateDisplay(int displayId, final int fromRotation, final int toRotation,
|
||||
IDisplayWindowRotationCallback callback) {
|
||||
WindowContainerTransaction t = new WindowContainerTransaction();
|
||||
synchronized (mRotationListener) {
|
||||
mTmpListeners.clear();
|
||||
// Make a local copy in case the handlers add/remove themselves.
|
||||
mTmpListeners.addAll(mRotationListener);
|
||||
}
|
||||
for (OnDisplayChangingListener c : mTmpListeners) {
|
||||
c.onRotateDisplay(displayId, fromRotation, toRotation, t);
|
||||
}
|
||||
try {
|
||||
callback.continueRotateDisplay(toRotation, t);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
private class DisplayWindowRotationControllerImpl
|
||||
extends IDisplayWindowRotationController.Stub {
|
||||
@Override
|
||||
public void onRotateDisplay(int displayId, final int fromRotation,
|
||||
final int toRotation, IDisplayWindowRotationCallback callback) {
|
||||
mHandler.post(() -> {
|
||||
DisplayChangeController.this.onRotateDisplay(displayId, fromRotation, toRotation,
|
||||
callback);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Give a listener a chance to queue up configuration changes to execute as part of a
|
||||
* display rotation. The contents of {@link #onRotateDisplay} must run synchronously.
|
||||
*/
|
||||
@ShellMainThread
|
||||
public interface OnDisplayChangingListener {
|
||||
/**
|
||||
* Called before the display is rotated. Contents of this method must run synchronously.
|
||||
|
||||
@@ -28,7 +28,10 @@ import android.view.Display;
|
||||
import android.view.IDisplayWindowListener;
|
||||
import android.view.IWindowManager;
|
||||
|
||||
import androidx.annotation.BinderThread;
|
||||
|
||||
import com.android.wm.shell.common.DisplayChangeController.OnDisplayChangingListener;
|
||||
import com.android.wm.shell.common.annotations.ShellMainThread;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -45,6 +48,7 @@ public class DisplayController {
|
||||
private final Context mContext;
|
||||
private final IWindowManager mWmService;
|
||||
private final DisplayChangeController mChangeController;
|
||||
private final IDisplayWindowListener mDisplayContainerListener;
|
||||
|
||||
private final SparseArray<DisplayRecord> mDisplays = new SparseArray<>();
|
||||
private final ArrayList<OnDisplaysChangedListener> mDisplayChangedListeners = new ArrayList<>();
|
||||
@@ -57,119 +61,13 @@ public class DisplayController {
|
||||
return displayManager.getDisplay(displayId);
|
||||
}
|
||||
|
||||
private final IDisplayWindowListener mDisplayContainerListener =
|
||||
new IDisplayWindowListener.Stub() {
|
||||
@Override
|
||||
public void onDisplayAdded(int displayId) {
|
||||
mHandler.post(() -> {
|
||||
synchronized (mDisplays) {
|
||||
if (mDisplays.get(displayId) != null) {
|
||||
return;
|
||||
}
|
||||
Display display = getDisplay(displayId);
|
||||
if (display == null) {
|
||||
// It's likely that the display is private to some app and thus not
|
||||
// accessible by system-ui.
|
||||
return;
|
||||
}
|
||||
DisplayRecord record = new DisplayRecord();
|
||||
record.mDisplayId = displayId;
|
||||
record.mContext = (displayId == Display.DEFAULT_DISPLAY) ? mContext
|
||||
: mContext.createDisplayContext(display);
|
||||
record.mDisplayLayout = new DisplayLayout(record.mContext, display);
|
||||
mDisplays.put(displayId, record);
|
||||
for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
|
||||
mDisplayChangedListeners.get(i).onDisplayAdded(displayId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
|
||||
mHandler.post(() -> {
|
||||
synchronized (mDisplays) {
|
||||
DisplayRecord dr = mDisplays.get(displayId);
|
||||
if (dr == null) {
|
||||
Slog.w(TAG, "Skipping Display Configuration change on non-added"
|
||||
+ " display.");
|
||||
return;
|
||||
}
|
||||
Display display = getDisplay(displayId);
|
||||
if (display == null) {
|
||||
Slog.w(TAG, "Skipping Display Configuration change on invalid"
|
||||
+ " display. It may have been removed.");
|
||||
return;
|
||||
}
|
||||
Context perDisplayContext = mContext;
|
||||
if (displayId != Display.DEFAULT_DISPLAY) {
|
||||
perDisplayContext = mContext.createDisplayContext(display);
|
||||
}
|
||||
dr.mContext = perDisplayContext.createConfigurationContext(newConfig);
|
||||
dr.mDisplayLayout = new DisplayLayout(dr.mContext, display);
|
||||
for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
|
||||
mDisplayChangedListeners.get(i).onDisplayConfigurationChanged(
|
||||
displayId, newConfig);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayRemoved(int displayId) {
|
||||
mHandler.post(() -> {
|
||||
synchronized (mDisplays) {
|
||||
if (mDisplays.get(displayId) == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = mDisplayChangedListeners.size() - 1; i >= 0; --i) {
|
||||
mDisplayChangedListeners.get(i).onDisplayRemoved(displayId);
|
||||
}
|
||||
mDisplays.remove(displayId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFixedRotationStarted(int displayId, int newRotation) {
|
||||
mHandler.post(() -> {
|
||||
synchronized (mDisplays) {
|
||||
if (mDisplays.get(displayId) == null || getDisplay(displayId) == null) {
|
||||
Slog.w(TAG, "Skipping onFixedRotationStarted on unknown"
|
||||
+ " display, displayId=" + displayId);
|
||||
return;
|
||||
}
|
||||
for (int i = mDisplayChangedListeners.size() - 1; i >= 0; --i) {
|
||||
mDisplayChangedListeners.get(i).onFixedRotationStarted(
|
||||
displayId, newRotation);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFixedRotationFinished(int displayId) {
|
||||
mHandler.post(() -> {
|
||||
synchronized (mDisplays) {
|
||||
if (mDisplays.get(displayId) == null || getDisplay(displayId) == null) {
|
||||
Slog.w(TAG, "Skipping onFixedRotationFinished on unknown"
|
||||
+ " display, displayId=" + displayId);
|
||||
return;
|
||||
}
|
||||
for (int i = mDisplayChangedListeners.size() - 1; i >= 0; --i) {
|
||||
mDisplayChangedListeners.get(i).onFixedRotationFinished(displayId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
public DisplayController(Context context, Handler handler,
|
||||
IWindowManager wmService) {
|
||||
mHandler = handler;
|
||||
mContext = context;
|
||||
mWmService = wmService;
|
||||
mChangeController = new DisplayChangeController(mHandler, mWmService);
|
||||
mDisplayContainerListener = new DisplayWindowListenerImpl();
|
||||
try {
|
||||
mWmService.registerDisplayWindowListener(mDisplayContainerListener);
|
||||
} catch (RemoteException e) {
|
||||
@@ -232,18 +130,146 @@ public class DisplayController {
|
||||
mChangeController.removeRotationListener(controller);
|
||||
}
|
||||
|
||||
private void onDisplayAdded(int displayId) {
|
||||
synchronized (mDisplays) {
|
||||
if (mDisplays.get(displayId) != null) {
|
||||
return;
|
||||
}
|
||||
Display display = getDisplay(displayId);
|
||||
if (display == null) {
|
||||
// It's likely that the display is private to some app and thus not
|
||||
// accessible by system-ui.
|
||||
return;
|
||||
}
|
||||
DisplayRecord record = new DisplayRecord();
|
||||
record.mDisplayId = displayId;
|
||||
record.mContext = (displayId == Display.DEFAULT_DISPLAY) ? mContext
|
||||
: mContext.createDisplayContext(display);
|
||||
record.mDisplayLayout = new DisplayLayout(record.mContext, display);
|
||||
mDisplays.put(displayId, record);
|
||||
for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
|
||||
mDisplayChangedListeners.get(i).onDisplayAdded(displayId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
|
||||
synchronized (mDisplays) {
|
||||
DisplayRecord dr = mDisplays.get(displayId);
|
||||
if (dr == null) {
|
||||
Slog.w(TAG, "Skipping Display Configuration change on non-added"
|
||||
+ " display.");
|
||||
return;
|
||||
}
|
||||
Display display = getDisplay(displayId);
|
||||
if (display == null) {
|
||||
Slog.w(TAG, "Skipping Display Configuration change on invalid"
|
||||
+ " display. It may have been removed.");
|
||||
return;
|
||||
}
|
||||
Context perDisplayContext = mContext;
|
||||
if (displayId != Display.DEFAULT_DISPLAY) {
|
||||
perDisplayContext = mContext.createDisplayContext(display);
|
||||
}
|
||||
dr.mContext = perDisplayContext.createConfigurationContext(newConfig);
|
||||
dr.mDisplayLayout = new DisplayLayout(dr.mContext, display);
|
||||
for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
|
||||
mDisplayChangedListeners.get(i).onDisplayConfigurationChanged(
|
||||
displayId, newConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onDisplayRemoved(int displayId) {
|
||||
synchronized (mDisplays) {
|
||||
if (mDisplays.get(displayId) == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = mDisplayChangedListeners.size() - 1; i >= 0; --i) {
|
||||
mDisplayChangedListeners.get(i).onDisplayRemoved(displayId);
|
||||
}
|
||||
mDisplays.remove(displayId);
|
||||
}
|
||||
}
|
||||
|
||||
private void onFixedRotationStarted(int displayId, int newRotation) {
|
||||
synchronized (mDisplays) {
|
||||
if (mDisplays.get(displayId) == null || getDisplay(displayId) == null) {
|
||||
Slog.w(TAG, "Skipping onFixedRotationStarted on unknown"
|
||||
+ " display, displayId=" + displayId);
|
||||
return;
|
||||
}
|
||||
for (int i = mDisplayChangedListeners.size() - 1; i >= 0; --i) {
|
||||
mDisplayChangedListeners.get(i).onFixedRotationStarted(
|
||||
displayId, newRotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onFixedRotationFinished(int displayId) {
|
||||
synchronized (mDisplays) {
|
||||
if (mDisplays.get(displayId) == null || getDisplay(displayId) == null) {
|
||||
Slog.w(TAG, "Skipping onFixedRotationFinished on unknown"
|
||||
+ " display, displayId=" + displayId);
|
||||
return;
|
||||
}
|
||||
for (int i = mDisplayChangedListeners.size() - 1; i >= 0; --i) {
|
||||
mDisplayChangedListeners.get(i).onFixedRotationFinished(displayId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class DisplayRecord {
|
||||
int mDisplayId;
|
||||
Context mContext;
|
||||
DisplayLayout mDisplayLayout;
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
private class DisplayWindowListenerImpl extends IDisplayWindowListener.Stub {
|
||||
@Override
|
||||
public void onDisplayAdded(int displayId) {
|
||||
mHandler.post(() -> {
|
||||
DisplayController.this.onDisplayAdded(displayId);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
|
||||
mHandler.post(() -> {
|
||||
DisplayController.this.onDisplayConfigurationChanged(displayId, newConfig);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayRemoved(int displayId) {
|
||||
mHandler.post(() -> {
|
||||
DisplayController.this.onDisplayRemoved(displayId);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFixedRotationStarted(int displayId, int newRotation) {
|
||||
mHandler.post(() -> {
|
||||
DisplayController.this.onFixedRotationStarted(displayId, newRotation);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFixedRotationFinished(int displayId) {
|
||||
mHandler.post(() -> {
|
||||
DisplayController.this.onFixedRotationFinished(displayId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets notified when a display is added/removed to the WM hierarchy and when a display's
|
||||
* window-configuration changes.
|
||||
*
|
||||
* @see IDisplayWindowListener
|
||||
*/
|
||||
@ShellMainThread
|
||||
public interface OnDisplaysChangedListener {
|
||||
/**
|
||||
* Called when a display has been added to the WM hierarchy.
|
||||
|
||||
@@ -39,6 +39,8 @@ import android.view.WindowInsets;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
import androidx.annotation.BinderThread;
|
||||
|
||||
import com.android.internal.view.IInputMethodManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -196,6 +198,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
|
||||
mRotation = initialRotation;
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
@Override
|
||||
public void insetsChanged(InsetsState insetsState) {
|
||||
mExecutor.execute(() -> {
|
||||
@@ -217,6 +220,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
|
||||
});
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
@Override
|
||||
public void insetsControlChanged(InsetsState insetsState,
|
||||
InsetsSourceControl[] activeControls) {
|
||||
@@ -267,6 +271,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
|
||||
}
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
@Override
|
||||
public void showInsets(int types, boolean fromIme) {
|
||||
if ((types & WindowInsets.Type.ime()) == 0) {
|
||||
@@ -276,6 +281,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
|
||||
mExecutor.execute(() -> startAnimation(true /* show */, false /* forceRestart */));
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
@Override
|
||||
public void hideInsets(int types, boolean fromIme) {
|
||||
if ((types & WindowInsets.Type.ime()) == 0) {
|
||||
@@ -285,6 +291,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
|
||||
mExecutor.execute(() -> startAnimation(false /* show */, false /* forceRestart */));
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
@Override
|
||||
public void topFocusedWindowChanged(String packageName) {
|
||||
// no-op
|
||||
|
||||
@@ -27,6 +27,17 @@ public class HandlerExecutor implements ShellExecutor {
|
||||
mHandler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NonNull Runnable command) {
|
||||
if (mHandler.getLooper().isCurrentThread()) {
|
||||
command.run();
|
||||
return;
|
||||
}
|
||||
if (!mHandler.post(command)) {
|
||||
throw new RuntimeException(mHandler + " is probably exiting");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeDelayed(@NonNull Runnable r, long delayMillis) {
|
||||
if (!mHandler.postDelayed(r, delayMillis)) {
|
||||
@@ -38,11 +49,4 @@ public class HandlerExecutor implements ShellExecutor {
|
||||
public void removeCallbacks(@NonNull Runnable r) {
|
||||
mHandler.removeCallbacks(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NonNull Runnable command) {
|
||||
if (!mHandler.post(command)) {
|
||||
throw new RuntimeException(mHandler + " is probably exiting");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,40 @@
|
||||
|
||||
package com.android.wm.shell.common;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Super basic Executor interface that adds support for delayed execution and removing callbacks.
|
||||
* Intended to wrap Handler while better-supporting testing.
|
||||
*/
|
||||
public interface ShellExecutor extends Executor {
|
||||
|
||||
/**
|
||||
* Executes the given runnable. If the caller is running on the same looper as this executor,
|
||||
* the runnable must be executed immediately.
|
||||
*/
|
||||
@Override
|
||||
void execute(Runnable runnable);
|
||||
|
||||
/**
|
||||
* Executes the given runnable in a blocking call. If the caller is running on the same looper
|
||||
* as this executor, the runnable must be executed immediately.
|
||||
*
|
||||
* @throws InterruptedException if runnable does not return in the time specified by
|
||||
* {@param waitTimeout}
|
||||
*/
|
||||
default void executeBlocking(Runnable runnable, int waitTimeout, TimeUnit waitTimeUnit)
|
||||
throws InterruptedException {
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
execute(() -> {
|
||||
runnable.run();
|
||||
latch.countDown();
|
||||
});
|
||||
latch.await(waitTimeout, waitTimeUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link android.os.Handler#postDelayed(Runnable, long)}.
|
||||
*/
|
||||
|
||||
@@ -24,6 +24,10 @@ import android.window.WindowContainerTransaction;
|
||||
import android.window.WindowContainerTransactionCallback;
|
||||
import android.window.WindowOrganizer;
|
||||
|
||||
import androidx.annotation.BinderThread;
|
||||
|
||||
import com.android.wm.shell.common.annotations.ShellMainThread;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
@@ -151,6 +155,7 @@ public final class SyncTransactionQueue {
|
||||
mHandler.postDelayed(mOnReplyTimeout, REPLY_TIMEOUT);
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
@Override
|
||||
public void onTransactionReady(int id,
|
||||
@NonNull SurfaceControl.Transaction t) {
|
||||
|
||||
@@ -19,12 +19,10 @@ package com.android.wm.shell.common;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ITaskStackListener;
|
||||
import android.app.TaskInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.annotation.BinderThread;
|
||||
import androidx.annotation.MainThread;
|
||||
|
||||
/**
|
||||
* An interface to track task stack changes. Classes should implement this instead of
|
||||
@@ -32,85 +30,61 @@ import androidx.annotation.MainThread;
|
||||
*/
|
||||
public interface TaskStackListenerCallback {
|
||||
|
||||
@MainThread
|
||||
default void onRecentTaskListUpdated() { }
|
||||
|
||||
@MainThread
|
||||
default void onRecentTaskListFrozenChanged(boolean frozen) { }
|
||||
|
||||
@BinderThread
|
||||
default void onTaskStackChangedBackground() { }
|
||||
|
||||
@MainThread
|
||||
default void onTaskStackChanged() { }
|
||||
|
||||
@MainThread
|
||||
default void onTaskProfileLocked(int taskId, int userId) { }
|
||||
|
||||
@MainThread
|
||||
default void onTaskDisplayChanged(int taskId, int newDisplayId) { }
|
||||
|
||||
@MainThread
|
||||
default void onTaskCreated(int taskId, ComponentName componentName) { }
|
||||
|
||||
@MainThread
|
||||
default void onTaskRemoved(int taskId) { }
|
||||
|
||||
@MainThread
|
||||
default void onTaskMovedToFront(int taskId) { }
|
||||
|
||||
@MainThread
|
||||
default void onTaskMovedToFront(RunningTaskInfo taskInfo) {
|
||||
onTaskMovedToFront(taskInfo.taskId);
|
||||
}
|
||||
|
||||
@MainThread
|
||||
default void onTaskDescriptionChanged(RunningTaskInfo taskInfo) { }
|
||||
|
||||
@MainThread
|
||||
default void onTaskSnapshotChanged(int taskId, ActivityManager.TaskSnapshot snapshot) { }
|
||||
|
||||
@MainThread
|
||||
default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { }
|
||||
|
||||
@MainThread
|
||||
default void onActivityRestartAttempt(RunningTaskInfo task, boolean homeTaskVisible,
|
||||
boolean clearedTask, boolean wasVisible) { }
|
||||
|
||||
@MainThread
|
||||
default void onActivityPinned(String packageName, int userId, int taskId, int stackId) { }
|
||||
|
||||
@MainThread
|
||||
default void onActivityUnpinned() { }
|
||||
|
||||
@MainThread
|
||||
default void onActivityForcedResizable(String packageName, int taskId, int reason) { }
|
||||
|
||||
@MainThread
|
||||
default void onActivityDismissingDockedStack() { }
|
||||
|
||||
@MainThread
|
||||
default void onActivityLaunchOnSecondaryDisplayFailed() { }
|
||||
|
||||
@MainThread
|
||||
default void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo) {
|
||||
onActivityLaunchOnSecondaryDisplayFailed();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
default void onActivityLaunchOnSecondaryDisplayRerouted() { }
|
||||
|
||||
@MainThread
|
||||
default void onActivityLaunchOnSecondaryDisplayRerouted(RunningTaskInfo taskInfo) {
|
||||
onActivityLaunchOnSecondaryDisplayRerouted();
|
||||
}
|
||||
|
||||
@MainThread
|
||||
default void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { }
|
||||
|
||||
@MainThread
|
||||
default void onActivityRotation(int displayId) { }
|
||||
|
||||
@MainThread
|
||||
default void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken) { }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.android.wm.shell.common.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
/**
|
||||
* Annotates a method that or qualifies a provider runs aligned to the Choreographer SF vsync
|
||||
* instead of the app vsync.
|
||||
*/
|
||||
@Documented
|
||||
@Inherited
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ChoreographerSfVsync {}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.android.wm.shell.common.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
/** Annotates a method or class that is called from an external thread to the Shell threads. */
|
||||
@Documented
|
||||
@Inherited
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ExternalThread {}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.android.wm.shell.common.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
/** Annotates a method or qualifies a provider that runs on the Shell animation-thread */
|
||||
@Documented
|
||||
@Inherited
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ShellAnimationThread {}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.android.wm.shell.common.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
/** Annotates a method or qualifies a provider that runs on the Shell main-thread */
|
||||
@Documented
|
||||
@Inherited
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ShellMainThread {}
|
||||
@@ -20,11 +20,14 @@ import android.content.res.Configuration;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.wm.shell.common.annotations.ExternalThread;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Interface to engage hide display cutout feature.
|
||||
*/
|
||||
@ExternalThread
|
||||
public interface HideDisplayCutout {
|
||||
/**
|
||||
* Notifies {@link Configuration} changed.
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.wm.shell.onehanded;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.wm.shell.common.annotations.ExternalThread;
|
||||
import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -25,6 +26,7 @@ import java.io.PrintWriter;
|
||||
/**
|
||||
* Interface to engage one handed feature.
|
||||
*/
|
||||
@ExternalThread
|
||||
public interface OneHanded {
|
||||
/**
|
||||
* Return one handed settings enabled or not.
|
||||
|
||||
@@ -19,12 +19,17 @@ package com.android.wm.shell.pip;
|
||||
import android.app.RemoteAction;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.os.RemoteException;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.IPinnedStackController;
|
||||
import android.view.IPinnedStackListener;
|
||||
import android.view.WindowManagerGlobal;
|
||||
|
||||
import androidx.annotation.BinderThread;
|
||||
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* PinnedStackListener that simply forwards all calls to each listener added via
|
||||
@@ -32,8 +37,15 @@ import java.util.List;
|
||||
* {@link com.android.server.wm.WindowManagerService#registerPinnedStackListener} replaces any
|
||||
* previously set listener.
|
||||
*/
|
||||
public class PinnedStackListenerForwarder extends IPinnedStackListener.Stub {
|
||||
private List<PinnedStackListener> mListeners = new ArrayList<>();
|
||||
public class PinnedStackListenerForwarder {
|
||||
|
||||
private final IPinnedStackListener mListenerImpl = new PinnedStackListenerImpl();
|
||||
private final ShellExecutor mShellMainExecutor;
|
||||
private final ArrayList<PinnedStackListener> mListeners = new ArrayList<>();
|
||||
|
||||
public PinnedStackListenerForwarder(ShellExecutor shellMainExecutor) {
|
||||
mShellMainExecutor = shellMainExecutor;
|
||||
}
|
||||
|
||||
/** Adds a listener to receive updates from the WindowManagerService. */
|
||||
public void addListener(PinnedStackListener listener) {
|
||||
@@ -45,62 +57,118 @@ public class PinnedStackListenerForwarder extends IPinnedStackListener.Stub {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListenerRegistered(IPinnedStackController controller) {
|
||||
public void register(int displayId) throws RemoteException {
|
||||
WindowManagerGlobal.getWindowManagerService().registerPinnedStackListener(
|
||||
displayId, mListenerImpl);
|
||||
}
|
||||
|
||||
private void onListenerRegistered(IPinnedStackController controller) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onListenerRegistered(controller);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMovementBoundsChanged(boolean fromImeAdjustment) {
|
||||
private void onMovementBoundsChanged(boolean fromImeAdjustment) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onMovementBoundsChanged(fromImeAdjustment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
|
||||
private void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onImeVisibilityChanged(imeVisible, imeHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionsChanged(ParceledListSlice<RemoteAction> actions) {
|
||||
private void onActionsChanged(ParceledListSlice<RemoteAction> actions) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onActionsChanged(actions);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityHidden(ComponentName componentName) {
|
||||
private void onActivityHidden(ComponentName componentName) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onActivityHidden(componentName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayInfoChanged(DisplayInfo displayInfo) {
|
||||
private void onDisplayInfoChanged(DisplayInfo displayInfo) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onDisplayInfoChanged(displayInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged() {
|
||||
private void onConfigurationChanged() {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onConfigurationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAspectRatioChanged(float aspectRatio) {
|
||||
private void onAspectRatioChanged(float aspectRatio) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onAspectRatioChanged(aspectRatio);
|
||||
}
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
private class PinnedStackListenerImpl extends IPinnedStackListener.Stub {
|
||||
@Override
|
||||
public void onListenerRegistered(IPinnedStackController controller) {
|
||||
mShellMainExecutor.execute(() -> {
|
||||
PinnedStackListenerForwarder.this.onListenerRegistered(controller);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMovementBoundsChanged(boolean fromImeAdjustment) {
|
||||
mShellMainExecutor.execute(() -> {
|
||||
PinnedStackListenerForwarder.this.onMovementBoundsChanged(fromImeAdjustment);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
|
||||
mShellMainExecutor.execute(() -> {
|
||||
PinnedStackListenerForwarder.this.onImeVisibilityChanged(imeVisible, imeHeight);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionsChanged(ParceledListSlice<RemoteAction> actions) {
|
||||
mShellMainExecutor.execute(() -> {
|
||||
PinnedStackListenerForwarder.this.onActionsChanged(actions);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityHidden(ComponentName componentName) {
|
||||
mShellMainExecutor.execute(() -> {
|
||||
PinnedStackListenerForwarder.this.onActivityHidden(componentName);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayInfoChanged(DisplayInfo displayInfo) {
|
||||
mShellMainExecutor.execute(() -> {
|
||||
PinnedStackListenerForwarder.this.onDisplayInfoChanged(displayInfo);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged() {
|
||||
mShellMainExecutor.execute(() -> {
|
||||
PinnedStackListenerForwarder.this.onConfigurationChanged();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAspectRatioChanged(float aspectRatio) {
|
||||
mShellMainExecutor.execute(() -> {
|
||||
PinnedStackListenerForwarder.this.onAspectRatioChanged(aspectRatio);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A counterpart of {@link IPinnedStackListener} with empty implementations.
|
||||
* Subclasses can ignore those methods they do not intend to take action upon.
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
package com.android.wm.shell.pip;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.PictureInPictureParams;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.Rect;
|
||||
|
||||
import com.android.wm.shell.common.annotations.ExternalThread;
|
||||
import com.android.wm.shell.pip.phone.PipTouchHandler;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -31,6 +31,7 @@ import java.util.function.Consumer;
|
||||
/**
|
||||
* Interface to engage picture in picture feature.
|
||||
*/
|
||||
@ExternalThread
|
||||
public interface Pip {
|
||||
/**
|
||||
* Closes PIP (PIPed activity and PIP system UI).
|
||||
|
||||
@@ -20,15 +20,18 @@ import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.view.MagnificationSpec;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.accessibility.AccessibilityWindowInfo;
|
||||
import android.view.accessibility.IAccessibilityInteractionConnection;
|
||||
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
|
||||
|
||||
import androidx.annotation.BinderThread;
|
||||
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.pip.PipBoundsState;
|
||||
import com.android.wm.shell.pip.PipSnapAlgorithm;
|
||||
import com.android.wm.shell.pip.PipTaskOrganizer;
|
||||
@@ -40,8 +43,7 @@ import java.util.List;
|
||||
* Expose the touch actions to accessibility as if this object were a window with a single view.
|
||||
* That pseudo-view exposes all of the actions this object can perform.
|
||||
*/
|
||||
public class PipAccessibilityInteractionConnection
|
||||
extends IAccessibilityInteractionConnection.Stub {
|
||||
public class PipAccessibilityInteractionConnection {
|
||||
|
||||
public interface AccessibilityCallbacks {
|
||||
void onAccessibilityShowMenu();
|
||||
@@ -50,14 +52,15 @@ public class PipAccessibilityInteractionConnection
|
||||
private static final long ACCESSIBILITY_NODE_ID = 1;
|
||||
private List<AccessibilityNodeInfo> mAccessibilityNodeInfoList;
|
||||
|
||||
private Context mContext;
|
||||
private Handler mHandler;
|
||||
private final Context mContext;
|
||||
private final ShellExecutor mShellMainExcutor;
|
||||
private final @NonNull PipBoundsState mPipBoundsState;
|
||||
private PipMotionHelper mMotionHelper;
|
||||
private PipTaskOrganizer mTaskOrganizer;
|
||||
private PipSnapAlgorithm mSnapAlgorithm;
|
||||
private Runnable mUpdateMovementBoundCallback;
|
||||
private AccessibilityCallbacks mCallbacks;
|
||||
private final PipMotionHelper mMotionHelper;
|
||||
private final PipTaskOrganizer mTaskOrganizer;
|
||||
private final PipSnapAlgorithm mSnapAlgorithm;
|
||||
private final Runnable mUpdateMovementBoundCallback;
|
||||
private final AccessibilityCallbacks mCallbacks;
|
||||
private final IAccessibilityInteractionConnection mConnectionImpl;
|
||||
|
||||
private final Rect mNormalBounds = new Rect();
|
||||
private final Rect mExpandedBounds = new Rect();
|
||||
@@ -69,19 +72,23 @@ public class PipAccessibilityInteractionConnection
|
||||
@NonNull PipBoundsState pipBoundsState, PipMotionHelper motionHelper,
|
||||
PipTaskOrganizer taskOrganizer, PipSnapAlgorithm snapAlgorithm,
|
||||
AccessibilityCallbacks callbacks, Runnable updateMovementBoundCallback,
|
||||
Handler handler) {
|
||||
ShellExecutor shellMainExcutor) {
|
||||
mContext = context;
|
||||
mHandler = handler;
|
||||
mShellMainExcutor = shellMainExcutor;
|
||||
mPipBoundsState = pipBoundsState;
|
||||
mMotionHelper = motionHelper;
|
||||
mTaskOrganizer = taskOrganizer;
|
||||
mSnapAlgorithm = snapAlgorithm;
|
||||
mUpdateMovementBoundCallback = updateMovementBoundCallback;
|
||||
mCallbacks = callbacks;
|
||||
mConnectionImpl = new PipAccessibilityInteractionConnectionImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
|
||||
public void register(AccessibilityManager am) {
|
||||
am.setPictureInPictureActionReplacingConnection(mConnectionImpl);
|
||||
}
|
||||
|
||||
private void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
|
||||
Region interactiveRegion, int interactionId,
|
||||
IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec, Bundle args) {
|
||||
@@ -94,8 +101,7 @@ public class PipAccessibilityInteractionConnection
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAccessibilityAction(long accessibilityNodeId, int action,
|
||||
private void performAccessibilityAction(long accessibilityNodeId, int action,
|
||||
Bundle arguments, int interactionId,
|
||||
IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid) {
|
||||
@@ -115,9 +121,7 @@ public class PipAccessibilityInteractionConnection
|
||||
} else {
|
||||
switch (action) {
|
||||
case AccessibilityNodeInfo.ACTION_CLICK:
|
||||
mHandler.post(() -> {
|
||||
mCallbacks.onAccessibilityShowMenu();
|
||||
});
|
||||
mCallbacks.onAccessibilityShowMenu();
|
||||
result = true;
|
||||
break;
|
||||
case AccessibilityNodeInfo.ACTION_DISMISS:
|
||||
@@ -172,8 +176,7 @@ public class PipAccessibilityInteractionConnection
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
|
||||
private void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
|
||||
String viewId, Region interactiveRegion, int interactionId,
|
||||
IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
|
||||
@@ -185,8 +188,7 @@ public class PipAccessibilityInteractionConnection
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text,
|
||||
private void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text,
|
||||
Region interactiveRegion, int interactionId,
|
||||
IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
|
||||
@@ -198,8 +200,7 @@ public class PipAccessibilityInteractionConnection
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findFocus(long accessibilityNodeId, int focusType, Region interactiveRegion,
|
||||
private void findFocus(long accessibilityNodeId, int focusType, Region interactiveRegion,
|
||||
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
|
||||
// We have no view that can take focus
|
||||
@@ -210,8 +211,7 @@ public class PipAccessibilityInteractionConnection
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusSearch(long accessibilityNodeId, int direction, Region interactiveRegion,
|
||||
private void focusSearch(long accessibilityNodeId, int direction, Region interactiveRegion,
|
||||
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
|
||||
// We have no view that can take focus
|
||||
@@ -222,16 +222,6 @@ public class PipAccessibilityInteractionConnection
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAccessibilityFocus() {
|
||||
// We should not be here.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyOutsideTouch() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the normal and expanded bounds so they can be used for Resize.
|
||||
*/
|
||||
@@ -271,4 +261,95 @@ public class PipAccessibilityInteractionConnection
|
||||
mAccessibilityNodeInfoList.add(info);
|
||||
return mAccessibilityNodeInfoList;
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
private class PipAccessibilityInteractionConnectionImpl
|
||||
extends IAccessibilityInteractionConnection.Stub {
|
||||
@Override
|
||||
public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
|
||||
Region bounds, int interactionId,
|
||||
IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec,
|
||||
Bundle arguments) throws RemoteException {
|
||||
mShellMainExcutor.execute(() -> {
|
||||
PipAccessibilityInteractionConnection.this
|
||||
.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, bounds,
|
||||
interactionId, callback, flags, interrogatingPid, interrogatingTid,
|
||||
spec, arguments);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId, String viewId,
|
||||
Region bounds, int interactionId,
|
||||
IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec)
|
||||
throws RemoteException {
|
||||
mShellMainExcutor.execute(() -> {
|
||||
PipAccessibilityInteractionConnection.this.findAccessibilityNodeInfosByViewId(
|
||||
accessibilityNodeId, viewId, bounds, interactionId, callback, flags,
|
||||
interrogatingPid, interrogatingTid, spec);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text,
|
||||
Region bounds, int interactionId,
|
||||
IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec)
|
||||
throws RemoteException {
|
||||
mShellMainExcutor.execute(() -> {
|
||||
PipAccessibilityInteractionConnection.this.findAccessibilityNodeInfosByText(
|
||||
accessibilityNodeId, text, bounds, interactionId, callback, flags,
|
||||
interrogatingPid, interrogatingTid, spec);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findFocus(long accessibilityNodeId, int focusType, Region bounds,
|
||||
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec)
|
||||
throws RemoteException {
|
||||
mShellMainExcutor.execute(() -> {
|
||||
PipAccessibilityInteractionConnection.this.findFocus(accessibilityNodeId, focusType,
|
||||
bounds, interactionId, callback, flags, interrogatingPid, interrogatingTid,
|
||||
spec);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusSearch(long accessibilityNodeId, int direction, Region bounds,
|
||||
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec)
|
||||
throws RemoteException {
|
||||
mShellMainExcutor.execute(() -> {
|
||||
PipAccessibilityInteractionConnection.this.focusSearch(accessibilityNodeId,
|
||||
direction,
|
||||
bounds, interactionId, callback, flags, interrogatingPid, interrogatingTid,
|
||||
spec);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAccessibilityAction(long accessibilityNodeId, int action,
|
||||
Bundle arguments, int interactionId,
|
||||
IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid) throws RemoteException {
|
||||
mShellMainExcutor.execute(() -> {
|
||||
PipAccessibilityInteractionConnection.this.performAccessibilityAction(
|
||||
accessibilityNodeId, action, arguments, interactionId, callback, flags,
|
||||
interrogatingPid, interrogatingTid);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAccessibilityFocus() throws RemoteException {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyOutsideTouch() throws RemoteException {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,6 @@ import com.android.wm.shell.WindowManagerShellWrapper;
|
||||
import com.android.wm.shell.common.DisplayChangeController;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.DisplayLayout;
|
||||
import com.android.wm.shell.common.PipInputConsumer;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.common.TaskStackListenerCallback;
|
||||
import com.android.wm.shell.common.TaskStackListenerImpl;
|
||||
@@ -164,62 +163,54 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
PinnedStackListenerForwarder.PinnedStackListener {
|
||||
@Override
|
||||
public void onListenerRegistered(IPinnedStackController controller) {
|
||||
mMainExecutor.execute(() -> mTouchHandler.setPinnedStackController(controller));
|
||||
mTouchHandler.setPinnedStackController(controller);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
|
||||
mMainExecutor.execute(() -> {
|
||||
mPipBoundsState.setImeVisibility(imeVisible, imeHeight);
|
||||
mTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight);
|
||||
});
|
||||
mPipBoundsState.setImeVisibility(imeVisible, imeHeight);
|
||||
mTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMovementBoundsChanged(boolean fromImeAdjustment) {
|
||||
mMainExecutor.execute(() -> updateMovementBounds(null /* toBounds */,
|
||||
updateMovementBounds(null /* toBounds */,
|
||||
false /* fromRotation */, fromImeAdjustment, false /* fromShelfAdjustment */,
|
||||
null /* windowContainerTransaction */));
|
||||
null /* windowContainerTransaction */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionsChanged(ParceledListSlice<RemoteAction> actions) {
|
||||
mMainExecutor.execute(() -> mMenuController.setAppActions(actions));
|
||||
mMenuController.setAppActions(actions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityHidden(ComponentName componentName) {
|
||||
mMainExecutor.execute(() -> {
|
||||
if (componentName.equals(mPipBoundsState.getLastPipComponentName())) {
|
||||
// The activity was removed, we don't want to restore to the reentry state
|
||||
// saved for this component anymore.
|
||||
mPipBoundsState.setLastPipComponentName(null);
|
||||
}
|
||||
});
|
||||
if (componentName.equals(mPipBoundsState.getLastPipComponentName())) {
|
||||
// The activity was removed, we don't want to restore to the reentry state
|
||||
// saved for this component anymore.
|
||||
mPipBoundsState.setLastPipComponentName(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayInfoChanged(DisplayInfo displayInfo) {
|
||||
mMainExecutor.execute(() -> mPipBoundsState.setDisplayInfo(displayInfo));
|
||||
mPipBoundsState.setDisplayInfo(displayInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged() {
|
||||
mMainExecutor.execute(() -> {
|
||||
mPipBoundsAlgorithm.onConfigurationChanged(mContext);
|
||||
mTouchHandler.onConfigurationChanged();
|
||||
mPipBoundsState.onConfigurationChanged();
|
||||
});
|
||||
mPipBoundsAlgorithm.onConfigurationChanged(mContext);
|
||||
mTouchHandler.onConfigurationChanged();
|
||||
mPipBoundsState.onConfigurationChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAspectRatioChanged(float aspectRatio) {
|
||||
// TODO(b/169373982): Remove this callback as it is redundant with PipTaskOrg params
|
||||
// change.
|
||||
mMainExecutor.execute(() -> {
|
||||
mPipBoundsState.setAspectRatio(aspectRatio);
|
||||
mTouchHandler.onAspectRatioChanged();
|
||||
});
|
||||
mPipBoundsState.setAspectRatio(aspectRatio);
|
||||
mTouchHandler.onAspectRatioChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,11 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.wm.shell.common;
|
||||
package com.android.wm.shell.pip.phone;
|
||||
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
|
||||
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
|
||||
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
@@ -30,7 +28,6 @@ import android.view.Choreographer;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.InputChannel;
|
||||
import android.view.InputEvent;
|
||||
import android.view.WindowManagerGlobal;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@@ -47,6 +47,7 @@ import android.view.accessibility.AccessibilityWindowInfo;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.common.FloatingContentCoordinator;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.pip.PipAnimationController;
|
||||
import com.android.wm.shell.pip.PipBoundsAlgorithm;
|
||||
import com.android.wm.shell.pip.PipBoundsState;
|
||||
@@ -157,7 +158,8 @@ public class PipTouchHandler {
|
||||
@NonNull PipBoundsState pipBoundsState,
|
||||
PipTaskOrganizer pipTaskOrganizer,
|
||||
FloatingContentCoordinator floatingContentCoordinator,
|
||||
PipUiEventLogger pipUiEventLogger) {
|
||||
PipUiEventLogger pipUiEventLogger,
|
||||
ShellExecutor shellMainExecutor) {
|
||||
// Initialize the Pip input consumer
|
||||
mContext = context;
|
||||
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
|
||||
@@ -188,7 +190,7 @@ public class PipTouchHandler {
|
||||
mFloatingContentCoordinator = floatingContentCoordinator;
|
||||
mConnection = new PipAccessibilityInteractionConnection(mContext, pipBoundsState,
|
||||
mMotionHelper, pipTaskOrganizer, mPipBoundsAlgorithm.getSnapAlgorithm(),
|
||||
this::onAccessibilityShowMenu, this::updateMovementBounds, mHandler);
|
||||
this::onAccessibilityShowMenu, this::updateMovementBounds, shellMainExecutor);
|
||||
|
||||
mPipUiEventLogger = pipUiEventLogger;
|
||||
|
||||
@@ -436,8 +438,11 @@ public class PipTouchHandler {
|
||||
* TODO Add appropriate description
|
||||
*/
|
||||
public void onRegistrationChanged(boolean isRegistered) {
|
||||
mAccessibilityManager.setPictureInPictureActionReplacingConnection(isRegistered
|
||||
? mConnection : null);
|
||||
if (isRegistered) {
|
||||
mConnection.register(mAccessibilityManager);
|
||||
} else {
|
||||
mAccessibilityManager.setPictureInPictureActionReplacingConnection(null);
|
||||
}
|
||||
if (!isRegistered && mTouchState.isUserInteracting()) {
|
||||
// If the input consumer is unregistered while the user is interacting, then we may not
|
||||
// get the final TOUCH_UP event, so clean up the dismiss target as well
|
||||
|
||||
@@ -179,40 +179,33 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
PinnedStackListenerForwarder.PinnedStackListener {
|
||||
@Override
|
||||
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
|
||||
mHandler.post(() -> {
|
||||
mPipBoundsState.setImeVisibility(imeVisible, imeHeight);
|
||||
if (mState == STATE_PIP) {
|
||||
if (mImeVisible != imeVisible) {
|
||||
if (imeVisible) {
|
||||
// Save the IME height adjustment, and offset to not occlude the IME
|
||||
mPipBoundsState.getNormalBounds().offset(0, -imeHeight);
|
||||
mImeHeightAdjustment = imeHeight;
|
||||
} else {
|
||||
// Apply the inverse adjustment when the IME is hidden
|
||||
mPipBoundsState.getNormalBounds().offset(0, mImeHeightAdjustment);
|
||||
}
|
||||
mImeVisible = imeVisible;
|
||||
resizePinnedStack(STATE_PIP);
|
||||
mPipBoundsState.setImeVisibility(imeVisible, imeHeight);
|
||||
if (mState == STATE_PIP) {
|
||||
if (mImeVisible != imeVisible) {
|
||||
if (imeVisible) {
|
||||
// Save the IME height adjustment, and offset to not occlude the IME
|
||||
mPipBoundsState.getNormalBounds().offset(0, -imeHeight);
|
||||
mImeHeightAdjustment = imeHeight;
|
||||
} else {
|
||||
// Apply the inverse adjustment when the IME is hidden
|
||||
mPipBoundsState.getNormalBounds().offset(0, mImeHeightAdjustment);
|
||||
}
|
||||
mImeVisible = imeVisible;
|
||||
resizePinnedStack(STATE_PIP);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMovementBoundsChanged(boolean fromImeAdjustment) {
|
||||
mHandler.post(() -> {
|
||||
mTmpDisplayInfo.copyFrom(mPipBoundsState.getDisplayInfo());
|
||||
|
||||
mPipBoundsAlgorithm.getInsetBounds(mTmpInsetBounds);
|
||||
});
|
||||
mTmpDisplayInfo.copyFrom(mPipBoundsState.getDisplayInfo());
|
||||
mPipBoundsAlgorithm.getInsetBounds(mTmpInsetBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionsChanged(ParceledListSlice<RemoteAction> actions) {
|
||||
mCustomActions = actions;
|
||||
mHandler.post(() -> {
|
||||
mTvPipMenuController.setAppActions(mCustomActions);
|
||||
});
|
||||
mTvPipMenuController.setAppActions(mCustomActions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.android.wm.shell.splitscreen;
|
||||
import android.graphics.Rect;
|
||||
import android.window.WindowContainerToken;
|
||||
|
||||
import com.android.wm.shell.common.annotations.ExternalThread;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
@@ -26,6 +28,7 @@ import java.util.function.Consumer;
|
||||
/**
|
||||
* Interface to engage split screen feature.
|
||||
*/
|
||||
@ExternalThread
|
||||
public interface SplitScreen {
|
||||
/** Called when keyguard showing state changed. */
|
||||
void onKeyguardVisibilityChanged(boolean isShowing);
|
||||
|
||||
@@ -33,6 +33,7 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.ShellTestCase;
|
||||
import com.android.wm.shell.common.FloatingContentCoordinator;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.pip.PipBoundsAlgorithm;
|
||||
import com.android.wm.shell.pip.PipBoundsState;
|
||||
import com.android.wm.shell.pip.PipSnapAlgorithm;
|
||||
@@ -71,6 +72,9 @@ public class PipTouchHandlerTest extends ShellTestCase {
|
||||
@Mock
|
||||
private PipUiEventLogger mPipUiEventLogger;
|
||||
|
||||
@Mock
|
||||
private ShellExecutor mShellMainExecutor;
|
||||
|
||||
private PipBoundsState mPipBoundsState;
|
||||
private PipBoundsAlgorithm mPipBoundsAlgorithm;
|
||||
private PipSnapAlgorithm mPipSnapAlgorithm;
|
||||
@@ -94,7 +98,7 @@ public class PipTouchHandlerTest extends ShellTestCase {
|
||||
mPipSnapAlgorithm = new PipSnapAlgorithm();
|
||||
mPipTouchHandler = new PipTouchHandler(mContext, mPhonePipMenuController,
|
||||
mPipBoundsAlgorithm, mPipBoundsState, mPipTaskOrganizer,
|
||||
mFloatingContentCoordinator, mPipUiEventLogger);
|
||||
mFloatingContentCoordinator, mPipUiEventLogger, mShellMainExecutor);
|
||||
mMotionHelper = Mockito.spy(mPipTouchHandler.getMotionHelper());
|
||||
mPipResizeGestureHandler = Mockito.spy(mPipTouchHandler.getPipResizeGestureHandler());
|
||||
mPipTouchHandler.setPipMotionHelper(mMotionHelper);
|
||||
|
||||
@@ -16,14 +16,19 @@
|
||||
|
||||
package com.android.systemui.wmshell;
|
||||
|
||||
import static android.os.Process.THREAD_PRIORITY_DISPLAY;
|
||||
|
||||
import android.animation.AnimationHandler;
|
||||
import android.app.IActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.systemui.dagger.WMSingleton;
|
||||
@@ -36,7 +41,6 @@ import com.android.wm.shell.WindowManagerShellWrapper;
|
||||
import com.android.wm.shell.apppairs.AppPairs;
|
||||
import com.android.wm.shell.bubbles.BubbleController;
|
||||
import com.android.wm.shell.bubbles.Bubbles;
|
||||
import com.android.wm.shell.common.AnimationThread;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
import com.android.wm.shell.common.FloatingContentCoordinator;
|
||||
@@ -46,6 +50,9 @@ import com.android.wm.shell.common.SyncTransactionQueue;
|
||||
import com.android.wm.shell.common.SystemWindows;
|
||||
import com.android.wm.shell.common.TaskStackListenerImpl;
|
||||
import com.android.wm.shell.common.TransactionPool;
|
||||
import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
|
||||
import com.android.wm.shell.common.annotations.ShellAnimationThread;
|
||||
import com.android.wm.shell.common.annotations.ShellMainThread;
|
||||
import com.android.wm.shell.draganddrop.DragAndDropController;
|
||||
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
|
||||
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
|
||||
@@ -62,6 +69,7 @@ import com.android.wm.shell.pip.phone.PipTouchHandler;
|
||||
import com.android.wm.shell.splitscreen.SplitScreen;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import dagger.BindsOptionalOf;
|
||||
import dagger.Module;
|
||||
@@ -74,6 +82,89 @@ import dagger.Provides;
|
||||
@Module
|
||||
public abstract class WMShellBaseModule {
|
||||
|
||||
private static final boolean ENABLE_SHELL_MAIN_THREAD = false;
|
||||
|
||||
//
|
||||
// Shell Concurrency - Components used for managing threading in the Shell and SysUI
|
||||
//
|
||||
|
||||
/**
|
||||
* Provide a SysUI main-thread Executor.
|
||||
*/
|
||||
@WMSingleton
|
||||
@Provides
|
||||
@Main
|
||||
public static ShellExecutor provideSysUIMainExecutor(@Main Handler sysuiMainHandler) {
|
||||
return new HandlerExecutor(sysuiMainHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shell main-thread Handler, don't use this unless really necessary (ie. need to dedupe
|
||||
* multiple types of messages, etc.)
|
||||
*/
|
||||
@WMSingleton
|
||||
@Provides
|
||||
@ShellMainThread
|
||||
public static Handler provideShellMainHandler(@Main Handler sysuiMainHandler) {
|
||||
if (ENABLE_SHELL_MAIN_THREAD) {
|
||||
HandlerThread shellMainThread = new HandlerThread("wmshell.main");
|
||||
shellMainThread.start();
|
||||
return shellMainThread.getThreadHandler();
|
||||
}
|
||||
return sysuiMainHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a Shell main-thread Executor.
|
||||
*/
|
||||
@WMSingleton
|
||||
@Provides
|
||||
@ShellMainThread
|
||||
public static ShellExecutor provideShellMainExecutor(@ShellMainThread Handler shellMainHandler,
|
||||
@Main ShellExecutor sysuiMainExecutor) {
|
||||
if (ENABLE_SHELL_MAIN_THREAD) {
|
||||
return new HandlerExecutor(shellMainHandler);
|
||||
}
|
||||
return sysuiMainExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a Shell animation-thread Executor.
|
||||
*/
|
||||
@WMSingleton
|
||||
@Provides
|
||||
@ShellAnimationThread
|
||||
public static ShellExecutor provideShellAnimationExecutor() {
|
||||
HandlerThread shellAnimationThread = new HandlerThread("wmshell.anim",
|
||||
THREAD_PRIORITY_DISPLAY);
|
||||
shellAnimationThread.start();
|
||||
return new HandlerExecutor(shellAnimationThread.getThreadHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a Shell animation-thread AnimationHandler. The AnimationHandler can be set on
|
||||
* {@link android.animation.ValueAnimator}s and will ensure that the animation will run on
|
||||
* the Shell animation-thread.
|
||||
*/
|
||||
@WMSingleton
|
||||
@Provides
|
||||
@ChoreographerSfVsync
|
||||
public static AnimationHandler provideShellAnimationExecutorSfVsyncAnimationHandler(
|
||||
@ShellAnimationThread ShellExecutor shellAnimationExecutor) {
|
||||
try {
|
||||
AnimationHandler handler = new AnimationHandler();
|
||||
shellAnimationExecutor.executeBlocking(() -> {
|
||||
// This is called on the animation thread since it calls
|
||||
// Choreographer.getSfInstance() which returns a thread-local Choreographer instance
|
||||
// that uses the SF vsync
|
||||
handler.setProvider(new SfVsyncFrameCallbackProvider());
|
||||
}, 1, TimeUnit.SECONDS);
|
||||
return handler;
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Failed to initialize SfVsync animation handler in 1s", e);
|
||||
}
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static ShellInit provideShellInit(DisplayImeController displayImeController,
|
||||
@@ -139,8 +230,9 @@ public abstract class WMShellBaseModule {
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static WindowManagerShellWrapper provideWindowManagerShellWrapper() {
|
||||
return new WindowManagerShellWrapper();
|
||||
static WindowManagerShellWrapper provideWindowManagerShellWrapper(
|
||||
@ShellMainThread ShellExecutor shellMainExecutor) {
|
||||
return new WindowManagerShellWrapper(shellMainExecutor);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@@ -187,9 +279,11 @@ public abstract class WMShellBaseModule {
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static ShellTaskOrganizer provideShellTaskOrganizer(SyncTransactionQueue syncQueue,
|
||||
ShellExecutor mainExecutor, TransactionPool transactionPool, Context context) {
|
||||
return new ShellTaskOrganizer(syncQueue, transactionPool, mainExecutor,
|
||||
AnimationThread.instance().getExecutor(), context);
|
||||
@ShellMainThread ShellExecutor shellMainExecutor,
|
||||
@ShellAnimationThread ShellExecutor shellAnimationExecutor,
|
||||
TransactionPool transactionPool, Context context) {
|
||||
return new ShellTaskOrganizer(syncQueue, transactionPool, shellMainExecutor,
|
||||
shellAnimationExecutor, context);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@@ -228,12 +322,6 @@ public abstract class WMShellBaseModule {
|
||||
taskStackListener));
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static ShellExecutor provideMainShellExecutor(@Main Handler handler) {
|
||||
return new HandlerExecutor(handler);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static Optional<HideDisplayCutout> provideHideDisplayCutoutController(Context context,
|
||||
@@ -262,5 +350,4 @@ public abstract class WMShellBaseModule {
|
||||
static LetterboxConfigController provideLetterboxConfigController(Context context) {
|
||||
return new LetterboxConfigController(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.android.wm.shell.common.SyncTransactionQueue;
|
||||
import com.android.wm.shell.common.SystemWindows;
|
||||
import com.android.wm.shell.common.TaskStackListenerImpl;
|
||||
import com.android.wm.shell.common.TransactionPool;
|
||||
import com.android.wm.shell.common.annotations.ShellMainThread;
|
||||
import com.android.wm.shell.pip.Pip;
|
||||
import com.android.wm.shell.pip.PipBoundsAlgorithm;
|
||||
import com.android.wm.shell.pip.PipBoundsState;
|
||||
@@ -95,11 +96,12 @@ public class WMShellModule {
|
||||
PipBoundsState pipBoundsState, PipMediaController pipMediaController,
|
||||
PhonePipMenuController phonePipMenuController, PipTaskOrganizer pipTaskOrganizer,
|
||||
PipTouchHandler pipTouchHandler, WindowManagerShellWrapper windowManagerShellWrapper,
|
||||
TaskStackListenerImpl taskStackListener, ShellExecutor mainExecutor) {
|
||||
TaskStackListenerImpl taskStackListener,
|
||||
@ShellMainThread ShellExecutor shellMainExecutor) {
|
||||
return Optional.ofNullable(PipController.create(context, displayController,
|
||||
pipAppOpsListener, pipBoundsAlgorithm, pipBoundsState, pipMediaController,
|
||||
phonePipMenuController, pipTaskOrganizer, pipTouchHandler,
|
||||
windowManagerShellWrapper, taskStackListener, mainExecutor));
|
||||
windowManagerShellWrapper, taskStackListener, shellMainExecutor));
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@@ -129,9 +131,11 @@ public class WMShellModule {
|
||||
PipBoundsState pipBoundsState,
|
||||
PipTaskOrganizer pipTaskOrganizer,
|
||||
FloatingContentCoordinator floatingContentCoordinator,
|
||||
PipUiEventLogger pipUiEventLogger) {
|
||||
PipUiEventLogger pipUiEventLogger,
|
||||
@ShellMainThread ShellExecutor shellMainExecutor) {
|
||||
return new PipTouchHandler(context, menuPhoneController, pipBoundsAlgorithm,
|
||||
pipBoundsState, pipTaskOrganizer, floatingContentCoordinator, pipUiEventLogger);
|
||||
pipBoundsState, pipTaskOrganizer, floatingContentCoordinator, pipUiEventLogger,
|
||||
shellMainExecutor);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
|
||||
Reference in New Issue
Block a user