summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java90
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java34
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java19
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java209
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java48
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java15
10 files changed, 327 insertions, 118 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java
index f2f09820639a..e380426b9ca2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java
@@ -19,41 +19,58 @@ package com.android.wm.shell.apppairs;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
import android.app.ActivityManager;
+import android.util.Slog;
import android.util.SparseArray;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import java.io.PrintWriter;
+import java.util.concurrent.TimeUnit;
/**
* Class manages app-pairs multitasking mode and implements the main interface {@link AppPairs}.
*/
-public class AppPairsController implements AppPairs {
+public class AppPairsController {
private static final String TAG = AppPairsController.class.getSimpleName();
private final ShellTaskOrganizer mTaskOrganizer;
private final SyncTransactionQueue mSyncQueue;
+ private final ShellExecutor mMainExecutor;
+ private final AppPairsImpl mImpl = new AppPairsImpl();
private AppPairsPool mPairsPool;
// Active app-pairs mapped by root task id key.
private final SparseArray<AppPair> mActiveAppPairs = new SparseArray<>();
private final DisplayController mDisplayController;
- public AppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
- DisplayController displayController) {
+ /**
+ * Creates {@link AppPairs}, returns {@code null} if the feature is not supported.
+ */
+ @Nullable
+ public static AppPairs create(ShellTaskOrganizer organizer,
+ SyncTransactionQueue syncQueue, DisplayController displayController,
+ ShellExecutor mainExecutor) {
+ return new AppPairsController(organizer, syncQueue, displayController,
+ mainExecutor).mImpl;
+ }
+
+ AppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
+ DisplayController displayController, ShellExecutor mainExecutor) {
mTaskOrganizer = organizer;
mSyncQueue = syncQueue;
mDisplayController = displayController;
+ mMainExecutor = mainExecutor;
}
- @Override
- public void onOrganizerRegistered() {
+ void onOrganizerRegistered() {
if (mPairsPool == null) {
setPairsPool(new AppPairsPool(this));
}
@@ -64,8 +81,7 @@ public class AppPairsController implements AppPairs {
mPairsPool = pool;
}
- @Override
- public boolean pair(int taskId1, int taskId2) {
+ boolean pair(int taskId1, int taskId2) {
final ActivityManager.RunningTaskInfo task1 = mTaskOrganizer.getRunningTaskInfo(taskId1);
final ActivityManager.RunningTaskInfo task2 = mTaskOrganizer.getRunningTaskInfo(taskId2);
if (task1 == null || task2 == null) {
@@ -74,8 +90,7 @@ public class AppPairsController implements AppPairs {
return pair(task1, task2);
}
- @Override
- public boolean pair(ActivityManager.RunningTaskInfo task1,
+ boolean pair(ActivityManager.RunningTaskInfo task1,
ActivityManager.RunningTaskInfo task2) {
return pairInner(task1, task2) != null;
}
@@ -94,8 +109,7 @@ public class AppPairsController implements AppPairs {
return pair;
}
- @Override
- public void unpair(int taskId) {
+ void unpair(int taskId) {
unpair(taskId, true /* releaseToPool */);
}
@@ -135,8 +149,7 @@ public class AppPairsController implements AppPairs {
return mDisplayController;
}
- @Override
- public void dump(@NonNull PrintWriter pw, String prefix) {
+ private void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
final String childPrefix = innerPrefix + " ";
pw.println(prefix + this);
@@ -155,4 +168,55 @@ public class AppPairsController implements AppPairs {
return TAG + "#" + mActiveAppPairs.size();
}
+ private class AppPairsImpl implements AppPairs {
+ @Override
+ public boolean pair(int task1, int task2) {
+ boolean[] result = new boolean[1];
+ try {
+ mMainExecutor.executeBlocking(() -> {
+ result[0] = AppPairsController.this.pair(task1, task2);
+ });
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to pair tasks: " + task1 + ", " + task2);
+ }
+ return result[0];
+ }
+
+ @Override
+ public boolean pair(ActivityManager.RunningTaskInfo task1,
+ ActivityManager.RunningTaskInfo task2) {
+ boolean[] result = new boolean[1];
+ try {
+ mMainExecutor.executeBlocking(() -> {
+ result[0] = AppPairsController.this.pair(task1, task2);
+ });
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to pair tasks: " + task1 + ", " + task2);
+ }
+ return result[0];
+ }
+
+ @Override
+ public void unpair(int taskId) {
+ mMainExecutor.execute(() -> {
+ AppPairsController.this.unpair(taskId);
+ });
+ }
+
+ @Override
+ public void onOrganizerRegistered() {
+ mMainExecutor.execute(() -> {
+ AppPairsController.this.onOrganizerRegistered();
+ });
+ }
+
+ @Override
+ public void dump(@NonNull PrintWriter pw, String prefix) {
+ try {
+ mMainExecutor.executeBlocking(() -> AppPairsController.this.dump(pw, prefix));
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to dump AppPairsController in 2s");
+ }
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java
index a89100526b8b..12b8b87f1285 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java
@@ -19,6 +19,7 @@ package com.android.wm.shell.hidedisplaycutout;
import android.content.Context;
import android.content.res.Configuration;
import android.os.SystemProperties;
+import android.util.Slog;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -28,17 +29,18 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import java.io.PrintWriter;
-import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
/**
* Manages the hide display cutout status.
*/
-public class HideDisplayCutoutController implements HideDisplayCutout {
+public class HideDisplayCutoutController {
private static final String TAG = "HideDisplayCutoutController";
private final Context mContext;
private final HideDisplayCutoutOrganizer mOrganizer;
private final ShellExecutor mMainExecutor;
+ private final HideDisplayCutoutImpl mImpl = new HideDisplayCutoutImpl();
@VisibleForTesting
boolean mEnabled;
@@ -55,7 +57,7 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
* supported.
*/
@Nullable
- public static HideDisplayCutoutController create(
+ public static HideDisplayCutout create(
Context context, DisplayController displayController, ShellExecutor mainExecutor) {
// The SystemProperty is set for devices that support this feature and is used to control
// whether to create the HideDisplayCutout instance.
@@ -66,7 +68,7 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
HideDisplayCutoutOrganizer organizer =
new HideDisplayCutoutOrganizer(context, displayController, mainExecutor);
- return new HideDisplayCutoutController(context, organizer, mainExecutor);
+ return new HideDisplayCutoutController(context, organizer, mainExecutor).mImpl;
}
@VisibleForTesting
@@ -88,13 +90,11 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
}
}
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
+ private void onConfigurationChanged(Configuration newConfig) {
updateStatus();
}
- @Override
- public void dump(@NonNull PrintWriter pw) {
+ private void dump(@NonNull PrintWriter pw) {
final String prefix = " ";
pw.print(TAG);
pw.println(" states: ");
@@ -103,4 +103,22 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
pw.println(mEnabled);
mOrganizer.dump(pw);
}
+
+ private class HideDisplayCutoutImpl implements HideDisplayCutout {
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ mMainExecutor.execute(() -> {
+ HideDisplayCutoutController.this.onConfigurationChanged(newConfig);
+ });
+ }
+
+ @Override
+ public void dump(@NonNull PrintWriter pw) {
+ try {
+ mMainExecutor.executeBlocking(() -> HideDisplayCutoutController.this.dump(pw));
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to dump HideDisplayCutoutController in 2s");
+ }
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
index c1b6c4fec792..e13a1dbe22d6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
@@ -36,7 +36,6 @@ import android.graphics.Region;
import android.graphics.Region.Op;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
-import android.os.Handler;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Slog;
@@ -60,7 +59,6 @@ import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
-import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.policy.DividerSnapAlgorithm;
@@ -146,8 +144,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,
private LegacySplitDisplayLayout mSplitLayout;
private DividerImeController mImeController;
private DividerCallbacks mCallback;
- private final AnimationHandler mAnimationHandler = new AnimationHandler();
+ private AnimationHandler mSfVsyncAnimationHandler;
private ValueAnimator mCurrentAnimator;
private boolean mEntranceAnimationRunning;
private boolean mExitAnimationRunning;
@@ -172,8 +170,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
// used interact with keyguard.
private boolean mSurfaceHidden = false;
- private final Handler mHandler = new Handler();
-
private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
@@ -284,7 +280,10 @@ public class DividerView extends FrameLayout implements OnTouchListener,
final DisplayManager displayManager =
(DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
- mAnimationHandler.setProvider(new SfVsyncFrameCallbackProvider());
+ }
+
+ public void setAnimationHandler(AnimationHandler sfVsyncAnimationHandler) {
+ mSfVsyncAnimationHandler = sfVsyncAnimationHandler;
}
@Override
@@ -669,12 +668,12 @@ public class DividerView extends FrameLayout implements OnTouchListener,
} else {
final Boolean cancelled = mCancelled;
if (DEBUG) Slog.d(TAG, "Posting endFling " + cancelled + " d:" + delay + "ms");
- mHandler.postDelayed(() -> endAction.accept(cancelled), delay);
+ getHandler().postDelayed(() -> endAction.accept(cancelled), delay);
}
}
});
- anim.setAnimationHandler(mAnimationHandler);
mCurrentAnimator = anim;
+ mCurrentAnimator.setAnimationHandler(mSfVsyncAnimationHandler);
return anim;
}
@@ -1061,8 +1060,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,
}
}
if (getViewRootImpl() != null) {
- mHandler.removeCallbacks(mUpdateEmbeddedMatrix);
- mHandler.post(mUpdateEmbeddedMatrix);
+ getHandler().removeCallbacks(mUpdateEmbeddedMatrix);
+ getHandler().post(mUpdateEmbeddedMatrix);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
index abff69c9ecbb..4fe28e630114 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
@@ -34,6 +34,8 @@ import com.android.wm.shell.R;
/**
* Translucent activity that gets started on top of a task in multi-window to inform the user that
* we forced the activity below to be resizable.
+ *
+ * Note: This activity runs on the main thread of the process hosting the Shell lib.
*/
public class ForcedResizableInfoActivity extends Activity implements OnTouchListener {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
index a785cffb3df0..bca6deb451c9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
@@ -24,6 +24,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.Display.DEFAULT_DISPLAY;
+import android.animation.AnimationHandler;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
@@ -40,6 +41,8 @@ import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
+import androidx.annotation.Nullable;
+
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -60,14 +63,14 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
/**
* Controls split screen feature.
*/
-public class LegacySplitScreenController implements LegacySplitScreen,
- DisplayController.OnDisplaysChangedListener {
+public class LegacySplitScreenController implements DisplayController.OnDisplaysChangedListener {
static final boolean DEBUG = false;
private static final String TAG = "SplitScreenCtrl";
@@ -81,11 +84,13 @@ public class LegacySplitScreenController implements LegacySplitScreen,
private final DividerState mDividerState = new DividerState();
private final ForcedResizableInfoActivityController mForcedResizableController;
private final ShellExecutor mMainExecutor;
+ private final AnimationHandler mSfVsyncAnimationHandler;
private final LegacySplitScreenTaskListener mSplits;
private final SystemWindows mSystemWindows;
final TransactionPool mTransactionPool;
private final WindowManagerProxy mWindowManagerProxy;
private final TaskOrganizer mTaskOrganizer;
+ private final SplitScreenImpl mImpl = new SplitScreenImpl();
private final CopyOnWriteArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners
= new CopyOnWriteArrayList<>();
@@ -106,21 +111,37 @@ public class LegacySplitScreenController implements LegacySplitScreen,
private boolean mIsKeyguardShowing;
private boolean mVisible = false;
- private boolean mMinimized = false;
- private boolean mAdjustedForIme = false;
+ private volatile boolean mMinimized = false;
+ private volatile boolean mAdjustedForIme = false;
private boolean mHomeStackResizable = false;
+ /**
+ * Creates {@link SplitScreen}, returns {@code null} if the feature is not supported.
+ */
+ @Nullable
+ public static LegacySplitScreen create(Context context,
+ DisplayController displayController, SystemWindows systemWindows,
+ DisplayImeController imeController, TransactionPool transactionPool,
+ ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
+ TaskStackListenerImpl taskStackListener, Transitions transitions,
+ ShellExecutor mainExecutor, AnimationHandler sfVsyncAnimationHandler) {
+ return new LegacySplitScreenController(context, displayController, systemWindows,
+ imeController, transactionPool, shellTaskOrganizer, syncQueue, taskStackListener,
+ transitions, mainExecutor, sfVsyncAnimationHandler).mImpl;
+ }
+
public LegacySplitScreenController(Context context,
DisplayController displayController, SystemWindows systemWindows,
DisplayImeController imeController, TransactionPool transactionPool,
ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
TaskStackListenerImpl taskStackListener, Transitions transitions,
- ShellExecutor mainExecutor) {
+ ShellExecutor mainExecutor, AnimationHandler sfVsyncAnimationHandler) {
mContext = context;
mDisplayController = displayController;
mSystemWindows = systemWindows;
mImeController = imeController;
mMainExecutor = mainExecutor;
+ mSfVsyncAnimationHandler = sfVsyncAnimationHandler;
mForcedResizableController = new ForcedResizableInfoActivityController(context, this,
mainExecutor);
mTransactionPool = transactionPool;
@@ -216,8 +237,7 @@ public class LegacySplitScreenController implements LegacySplitScreen,
mTaskOrganizer.applyTransaction(tct);
}
- @Override
- public void onKeyguardVisibilityChanged(boolean showing) {
+ private void onKeyguardVisibilityChanged(boolean showing) {
if (!isSplitActive() || mView == null) {
return;
}
@@ -273,23 +293,19 @@ public class LegacySplitScreenController implements LegacySplitScreen,
}
}
- @Override
- public DividerView getDividerView() {
- return mView;
- }
-
- @Override
- public boolean isMinimized() {
+ boolean isMinimized() {
return mMinimized;
}
- @Override
- public boolean isHomeStackResizable() {
+ boolean isHomeStackResizable() {
return mHomeStackResizable;
}
- @Override
- public boolean isDividerVisible() {
+ DividerView getDividerView() {
+ return mView;
+ }
+
+ boolean isDividerVisible() {
return mView != null && mView.getVisibility() == View.VISIBLE;
}
@@ -308,6 +324,7 @@ public class LegacySplitScreenController implements LegacySplitScreen,
Context dctx = mDisplayController.getDisplayContext(mContext.getDisplayId());
mView = (DividerView)
LayoutInflater.from(dctx).inflate(R.layout.docked_stack_divider, null);
+ mView.setAnimationHandler(mSfVsyncAnimationHandler);
DisplayLayout displayLayout = mDisplayController.getDisplayLayout(mContext.getDisplayId());
mView.injectDependencies(this, mWindowManager, mDividerState, mForcedResizableController,
mSplits, mSplitLayout, mImePositionProcessor, mWindowManagerProxy);
@@ -373,8 +390,7 @@ public class LegacySplitScreenController implements LegacySplitScreen,
}
}
- @Override
- public void setMinimized(final boolean minimized) {
+ private void setMinimized(final boolean minimized) {
if (DEBUG) Slog.d(TAG, "posting ext setMinimized " + minimized + " vis:" + mVisible);
mMainExecutor.execute(() -> {
if (DEBUG) Slog.d(TAG, "run posted ext setMinimized " + minimized + " vis:" + mVisible);
@@ -437,23 +453,20 @@ public class LegacySplitScreenController implements LegacySplitScreen,
mWindowManager.setTouchable(!mAdjustedForIme);
}
- @Override
- public void onUndockingTask() {
+ private void onUndockingTask() {
if (mView != null) {
mView.onUndockingTask();
}
}
- @Override
- public void onAppTransitionFinished() {
+ private void onAppTransitionFinished() {
if (mView == null) {
return;
}
mForcedResizableController.onAppTransitionFinished();
}
- @Override
- public void dump(PrintWriter pw) {
+ private void dump(PrintWriter pw) {
pw.print(" mVisible="); pw.println(mVisible);
pw.print(" mMinimized="); pw.println(mMinimized);
pw.print(" mAdjustedForIme="); pw.println(mAdjustedForIme);
@@ -469,16 +482,14 @@ public class LegacySplitScreenController implements LegacySplitScreen,
return (long) (transitionDuration * transitionScale);
}
- @Override
- public void registerInSplitScreenListener(Consumer<Boolean> listener) {
+ void registerInSplitScreenListener(Consumer<Boolean> listener) {
listener.accept(isDividerVisible());
synchronized (mDockedStackExistsListeners) {
mDockedStackExistsListeners.add(new WeakReference<>(listener));
}
}
- @Override
- public void unregisterInSplitScreenListener(Consumer<Boolean> listener) {
+ void unregisterInSplitScreenListener(Consumer<Boolean> listener) {
synchronized (mDockedStackExistsListeners) {
for (int i = mDockedStackExistsListeners.size() - 1; i >= 0; i--) {
if (mDockedStackExistsListeners.get(i) == listener) {
@@ -488,15 +499,13 @@ public class LegacySplitScreenController implements LegacySplitScreen,
}
}
- @Override
- public void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener) {
+ private void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener) {
synchronized (mBoundsChangedListeners) {
mBoundsChangedListeners.add(new WeakReference<>(listener));
}
}
- @Override
- public boolean splitPrimaryTask() {
+ private boolean splitPrimaryTask() {
try {
if (ActivityTaskManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_PINNED
|| isSplitActive()) {
@@ -529,8 +538,7 @@ public class LegacySplitScreenController implements LegacySplitScreen,
topRunningTask.taskId, true /* onTop */);
}
- @Override
- public void dismissSplitToPrimaryTask() {
+ private void dismissSplitToPrimaryTask() {
startDismissSplit(true /* toPrimaryTask */);
}
@@ -621,11 +629,136 @@ public class LegacySplitScreenController implements LegacySplitScreen,
return mWindowManagerProxy;
}
- @Override
- public WindowContainerToken getSecondaryRoot() {
+ WindowContainerToken getSecondaryRoot() {
if (mSplits == null || mSplits.mSecondary == null) {
return null;
}
return mSplits.mSecondary.token;
}
+
+ private class SplitScreenImpl implements LegacySplitScreen {
+ @Override
+ public boolean isMinimized() {
+ return mMinimized;
+ }
+
+ @Override
+ public boolean isHomeStackResizable() {
+ return mHomeStackResizable;
+ }
+
+ /**
+ * TODO: Remove usage from outside the shell.
+ */
+ @Override
+ public DividerView getDividerView() {
+ return LegacySplitScreenController.this.getDividerView();
+ }
+
+ @Override
+ public boolean isDividerVisible() {
+ boolean[] result = new boolean[1];
+ try {
+ mMainExecutor.executeBlocking(() -> {
+ result[0] = LegacySplitScreenController.this.isDividerVisible();
+ });
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to get divider visible");
+ }
+ return result[0];
+ }
+
+ @Override
+ public void onKeyguardVisibilityChanged(boolean isShowing) {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.onKeyguardVisibilityChanged(isShowing);
+ });
+ }
+
+ @Override
+ public void setMinimized(boolean minimized) {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.setMinimized(minimized);
+ });
+ }
+
+ @Override
+ public void onUndockingTask() {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.onUndockingTask();
+ });
+ }
+
+ @Override
+ public void onAppTransitionFinished() {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.onAppTransitionFinished();
+ });
+ }
+
+ @Override
+ public void registerInSplitScreenListener(Consumer<Boolean> listener) {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.registerInSplitScreenListener(listener);
+ });
+ }
+
+ @Override
+ public void unregisterInSplitScreenListener(Consumer<Boolean> listener) {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.unregisterInSplitScreenListener(listener);
+ });
+ }
+
+ @Override
+ public void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener) {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.registerBoundsChangeListener(listener);
+ });
+ }
+
+ @Override
+ public WindowContainerToken getSecondaryRoot() {
+ WindowContainerToken[] result = new WindowContainerToken[1];
+ try {
+ mMainExecutor.executeBlocking(() -> {
+ result[0] = LegacySplitScreenController.this.getSecondaryRoot();
+ });
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to get secondary root");
+ }
+ return result[0];
+ }
+
+ @Override
+ public boolean splitPrimaryTask() {
+ boolean[] result = new boolean[1];
+ try {
+ mMainExecutor.executeBlocking(() -> {
+ result[0] = LegacySplitScreenController.this.splitPrimaryTask();
+ });
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to split primary task");
+ }
+ return result[0];
+ }
+
+ @Override
+ public void dismissSplitToPrimaryTask() {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.dismissSplitToPrimaryTask();
+ });
+ }
+
+ @Override
+ public void dump(PrintWriter pw) {
+ try {
+ mMainExecutor.executeBlocking(() -> {
+ LegacySplitScreenController.this.dump(pw);
+ });
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to dump LegacySplitScreenController in 2s");
+ }
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
index a8cd1dd4fbde..94c6f018b6ac 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
@@ -47,8 +47,6 @@ import com.android.wm.shell.transition.Transitions;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
/**
* Proxy to simplify calls into window manager/activity manager
@@ -77,25 +75,7 @@ class WindowManagerProxy {
@GuardedBy("mDockedRect")
private final Rect mTouchableRegion = new Rect();
- private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
-
private final SyncTransactionQueue mSyncTransactionQueue;
-
- private final Runnable mSetTouchableRegionRunnable = new Runnable() {
- @Override
- public void run() {
- try {
- synchronized (mDockedRect) {
- mTmpRect1.set(mTouchableRegion);
- }
- WindowManagerGlobal.getWindowManagerService().setDockedStackDividerTouchRegion(
- mTmpRect1);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to set touchable region: " + e);
- }
- }
- };
-
private final TaskOrganizer mTaskOrganizer;
WindowManagerProxy(SyncTransactionQueue syncQueue, TaskOrganizer taskOrganizer) {
@@ -108,29 +88,29 @@ class WindowManagerProxy {
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
tiles.mSplitScreenController.startDismissSplit(!dismissOrMaximize, true /* snapped */);
} else {
- mExecutor.execute(() -> applyDismissSplit(tiles, layout, dismissOrMaximize));
+ applyDismissSplit(tiles, layout, dismissOrMaximize);
}
}
public void setResizing(final boolean resizing) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- try {
- ActivityTaskManager.getService().setSplitScreenResizing(resizing);
- } catch (RemoteException e) {
- Log.w(TAG, "Error calling setDockedStackResizing: " + e);
- }
- }
- });
+ try {
+ ActivityTaskManager.getService().setSplitScreenResizing(resizing);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error calling setDockedStackResizing: " + e);
+ }
}
/** Sets a touch region */
public void setTouchRegion(Rect region) {
- synchronized (mDockedRect) {
- mTouchableRegion.set(region);
+ try {
+ synchronized (mDockedRect) {
+ mTouchableRegion.set(region);
+ }
+ WindowManagerGlobal.getWindowManagerService().setDockedStackDividerTouchRegion(
+ mTouchableRegion);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to set touchable region: " + e);
}
- mExecutor.execute(mSetTouchableRegionRunnable);
}
void applyResizeSplits(int position, LegacySplitDisplayLayout splitLayout) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java
index be0963628933..e094158e1144 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java
@@ -16,16 +16,21 @@
package com.android.wm.shell.apppairs;
+import static org.mockito.Mockito.mock;
+
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
+import org.mockito.Mock;
+
public class TestAppPairsController extends AppPairsController {
- TestAppPairsPool mPool;
+ private TestAppPairsPool mPool;
public TestAppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
DisplayController displayController) {
- super(organizer, syncQueue, displayController);
+ super(organizer, syncQueue, displayController, mock(ShellExecutor.class));
mPool = new TestAppPairsPool(this);
setPairsPool(mPool);
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
index f0ccc6d15661..f23367b4d65b 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
@@ -16,6 +16,7 @@
package com.android.systemui.wmshell;
+import android.animation.AnimationHandler;
import android.content.Context;
import android.view.IWindowManager;
@@ -28,6 +29,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.ChoreographerSfVsync;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
@@ -58,9 +60,10 @@ public class TvWMShellModule {
DisplayImeController displayImeController, TransactionPool transactionPool,
ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
TaskStackListenerImpl taskStackListener, Transitions transitions,
- @ShellMainThread ShellExecutor mainExecutor) {
- return new LegacySplitScreenController(context, displayController, systemWindows,
+ @ShellMainThread ShellExecutor mainExecutor,
+ @ChoreographerSfVsync AnimationHandler sfVsyncAnimationHandler) {
+ return LegacySplitScreenController.create(context, displayController, systemWindows,
displayImeController, transactionPool, shellTaskOrganizer, syncQueue,
- taskStackListener, transitions, mainExecutor);
+ taskStackListener, transitions, mainExecutor, sfVsyncAnimationHandler);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index 02eb26d19343..a44fcec69e6a 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -146,18 +146,18 @@ public abstract class WMShellBaseModule {
}
/**
- * Provide a Shell animation-thread AnimationHandler. The AnimationHandler can be set on
+ * Provide a Shell main-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.
+ * the Shell main-thread with the SF vsync.
*/
@WMSingleton
@Provides
@ChoreographerSfVsync
- public static AnimationHandler provideShellAnimationExecutorSfVsyncAnimationHandler(
- @ShellAnimationThread ShellExecutor shellAnimationExecutor) {
+ public static AnimationHandler provideShellMainExecutorSfVsyncAnimationHandler(
+ @ShellMainThread ShellExecutor mainExecutor) {
try {
AnimationHandler handler = new AnimationHandler();
- shellAnimationExecutor.executeBlocking(() -> {
+ mainExecutor.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
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 4351c4f0b9ce..ee761691a97d 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -16,6 +16,7 @@
package com.android.systemui.wmshell;
+import android.animation.AnimationHandler;
import android.content.Context;
import android.view.IWindowManager;
@@ -33,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.ChoreographerSfVsync;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
@@ -78,10 +80,11 @@ public class WMShellModule {
DisplayImeController displayImeController, TransactionPool transactionPool,
ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
TaskStackListenerImpl taskStackListener, Transitions transitions,
- @ShellMainThread ShellExecutor mainExecutor) {
- return new LegacySplitScreenController(context, displayController, systemWindows,
+ @ShellMainThread ShellExecutor mainExecutor,
+ @ChoreographerSfVsync AnimationHandler sfVsyncAnimationHandler) {
+ return LegacySplitScreenController.create(context, displayController, systemWindows,
displayImeController, transactionPool, shellTaskOrganizer, syncQueue,
- taskStackListener, transitions, mainExecutor);
+ taskStackListener, transitions, mainExecutor, sfVsyncAnimationHandler);
}
@WMSingleton
@@ -96,8 +99,10 @@ public class WMShellModule {
@WMSingleton
@Provides
static AppPairs provideAppPairs(ShellTaskOrganizer shellTaskOrganizer,
- SyncTransactionQueue syncQueue, DisplayController displayController) {
- return new AppPairsController(shellTaskOrganizer, syncQueue, displayController);
+ SyncTransactionQueue syncQueue, DisplayController displayController,
+ @ShellMainThread ShellExecutor mainExecutor) {
+ return AppPairsController.create(shellTaskOrganizer, syncQueue, displayController,
+ mainExecutor);
}
@WMSingleton