Merge changes I0ea9aae2,I369e83cb

* changes:
  5/ Update splitscreen to use shell main thread
  4/ Update HideDisplayCutout and AppPairs to use shell main thread
This commit is contained in:
Winson Chung
2021-01-14 03:38:50 +00:00
committed by Android (Google) Code Review
10 changed files with 327 additions and 118 deletions

View File

@@ -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");
}
}
}
}

View File

@@ -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");
}
}
}
}

View File

@@ -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);
}
}

View File

@@ -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 {

View File

@@ -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");
}
}
}
}

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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