diff options
Diffstat (limited to 'libs')
57 files changed, 670 insertions, 358 deletions
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java index a663f9fafb50..ed99501b867d 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java @@ -20,6 +20,7 @@ import android.app.ActivityTaskManager; import android.app.ActivityThread; import android.app.Application; import android.content.Context; +import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -40,12 +41,17 @@ import java.util.Objects; */ public class WindowExtensionsImpl implements WindowExtensions { + private static final String TAG = "WindowExtensionsImpl"; private final Object mLock = new Object(); private volatile DeviceStateManagerFoldingFeatureProducer mFoldingFeatureProducer; private volatile WindowLayoutComponentImpl mWindowLayoutComponent; private volatile SplitController mSplitController; private volatile WindowAreaComponent mWindowAreaComponent; + public WindowExtensionsImpl() { + Log.i(TAG, "Initializing Window Extensions."); + } + // TODO(b/241126279) Introduce constants to better version functionality @Override public int getVendorApiLevel() { diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index 76f0b6769855..4973a4d85af7 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -156,6 +156,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen public SplitController(@NonNull WindowLayoutComponentImpl windowLayoutComponent, @NonNull DeviceStateManagerFoldingFeatureProducer foldingFeatureProducer) { + Log.i(TAG, "Initializing Activity Embedding Controller."); final MainThreadExecutor executor = new MainThreadExecutor(); mHandler = executor.mHandler; mPresenter = new SplitPresenter(executor, windowLayoutComponent, this); @@ -208,6 +209,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @Override public void setEmbeddingRules(@NonNull Set<EmbeddingRule> rules) { synchronized (mLock) { + Log.i(TAG, "Setting embedding rules. Size: " + rules.size()); mSplitRules.clear(); mSplitRules.addAll(rules); } @@ -216,6 +218,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @Override public boolean pinTopActivityStack(int taskId, @NonNull SplitPinRule splitPinRule) { synchronized (mLock) { + Log.i(TAG, "Request to pin top activity stack."); final TaskContainer task = getTaskContainer(taskId); if (task == null) { Log.e(TAG, "Cannot find the task for id: " + taskId); @@ -272,6 +275,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @Override public void unpinTopActivityStack(int taskId){ synchronized (mLock) { + Log.i(TAG, "Request to unpin top activity stack."); final TaskContainer task = getTaskContainer(taskId); if (task == null) { Log.e(TAG, "Cannot find the task to unpin, id: " + taskId); diff --git a/libs/WindowManager/Shell/res/values-television/config.xml b/libs/WindowManager/Shell/res/values-television/config.xml index 8d2e28b9492f..464e13225506 100644 --- a/libs/WindowManager/Shell/res/values-television/config.xml +++ b/libs/WindowManager/Shell/res/values-television/config.xml @@ -57,4 +57,9 @@ - 0 for radial vanish + slide up - 1 for fade out --> <integer name="starting_window_exit_animation_type">1</integer> + + <!-- Whether this device allows to use the appIcon as a fallback icon for the splash screen + window. If false, the splash screen will be a solid color splash screen whenever the + app has not provided a windowSplashScreenAnimatedIcon. --> + <bool name="config_canUseAppIconForSplashScreen">false</bool> </resources> diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml index 74364001b6c5..6a6f2b02766d 100644 --- a/libs/WindowManager/Shell/res/values/config.xml +++ b/libs/WindowManager/Shell/res/values/config.xml @@ -136,4 +136,9 @@ <!-- Whether DragAndDrop capability is enabled --> <bool name="config_enableShellDragDrop">true</bool> + + <!-- Whether this device allows to use the appIcon as a fallback icon for the splash screen + window. If false, the splash screen will be a solid color splash screen whenever the + app has not provided a windowSplashScreenAnimatedIcon. --> + <bool name="config_canUseAppIconForSplashScreen">true</bool> </resources> diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml index c4be384f48b3..55a91323295a 100644 --- a/libs/WindowManager/Shell/res/values/dimen.xml +++ b/libs/WindowManager/Shell/res/values/dimen.xml @@ -476,4 +476,11 @@ <item type="dimen" format="float" name="splash_icon_enlarge_foreground_threshold">0.44</item> <!-- Scaling factor applied to splash icons without provided background i.e. (192 / 160) --> <item type="dimen" format="float" name="splash_icon_no_background_scale_factor">1.2</item> + + <!-- The margin between the entering window and the exiting window during cross task back --> + <dimen name="cross_task_back_inter_window_margin">14dp</dimen> + <!-- The vertical margin that needs to be preserved between the scaled window bounds and the + original window bounds (once the surface is scaled enough to do so) --> + <dimen name="cross_task_back_vertical_margin">8dp</dimen> + </resources> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index 04795768aefc..b1b196d40357 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -29,6 +29,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager.RunningTaskInfo; +import android.app.AppCompatTaskInfo; import android.app.TaskInfo; import android.app.WindowConfiguration; import android.content.LocusId; @@ -700,7 +701,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements @Override public void onCameraControlStateUpdated( - int taskId, @TaskInfo.CameraCompatControlState int state) { + int taskId, @AppCompatTaskInfo.CameraCompatControlState int state) { final TaskAppearedInfo info; synchronized (mLock) { info = mTasks.get(taskId); @@ -754,7 +755,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements // The task is vanished or doesn't support compat UI, notify to remove compat UI // on this Task if there is any. if (taskListener == null || !taskListener.supportCompatUI() - || !taskInfo.hasCompatUI() || !taskInfo.isVisible) { + || !taskInfo.appCompatTaskInfo.hasCompatUI() || !taskInfo.isVisible) { mCompatUI.onCompatInfoChanged(taskInfo, null /* taskListener */); return; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java index 2ec9e8b12fc6..880579d6a772 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java @@ -88,6 +88,8 @@ public class Interpolators { public static final PathInterpolator DIM_INTERPOLATOR = new PathInterpolator(.23f, .87f, .52f, -0.11f); + public static final Interpolator DECELERATE = new PathInterpolator(0f, 0f, 0.5f, 1f); + // Create the default emphasized interpolator private static PathInterpolator createEmphasizedInterpolator() { Path path = new Path(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java index fc5ff017ebe5..8ec297e1e79c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java @@ -18,7 +18,6 @@ package com.android.wm.shell.back; import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.RemoteAnimationTarget.MODE_OPENING; -import static android.window.BackEvent.EDGE_RIGHT; import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BACK_CROSS_TASK; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW; @@ -37,7 +36,7 @@ import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; -import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.window.BackEvent; import android.window.BackMotionEvent; @@ -46,6 +45,8 @@ import android.window.IOnBackInvokedCallback; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.protolog.common.ProtoLog; +import com.android.wm.shell.R; +import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.common.annotations.ShellMainThread; import javax.inject.Inject; @@ -68,32 +69,18 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private static final int BACKGROUNDCOLOR = 0x43433A; /** - * Minimum scale of the entering window. + * Minimum scale of the entering and closing window. */ - private static final float ENTERING_MIN_WINDOW_SCALE = 0.85f; + private static final float MIN_WINDOW_SCALE = 0.8f; - /** - * Minimum scale of the closing window. - */ - private static final float CLOSING_MIN_WINDOW_SCALE = 0.75f; - - /** - * Minimum color scale of the closing window. - */ - private static final float CLOSING_MIN_WINDOW_COLOR_SCALE = 0.1f; - - /** - * The margin between the entering window and the closing window - */ - private static final int WINDOW_MARGIN = 35; - - /** Max window translation in the Y axis. */ - private static final int WINDOW_MAX_DELTA_Y = 160; + /** Duration of post animation after gesture committed. */ + private static final int POST_ANIMATION_DURATION_MS = 500; private final Rect mStartTaskRect = new Rect(); private final float mCornerRadius; // The closing window properties. + private final Rect mClosingStartRect = new Rect(); private final RectF mClosingCurrentRect = new RectF(); // The entering window properties. @@ -101,44 +88,32 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private final RectF mEnteringCurrentRect = new RectF(); private final PointF mInitialTouchPos = new PointF(); - private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator(); - + private final Interpolator mPostAnimationInterpolator = Interpolators.EMPHASIZED; + private final Interpolator mYMovementInterpolator = Interpolators.DECELERATE; + private final Interpolator mProgressInterpolator = new DecelerateInterpolator(); private final Matrix mTransformMatrix = new Matrix(); private final float[] mTmpFloat9 = new float[9]; - private final float[] mTmpTranslate = {0, 0, 0}; private final BackAnimationRunner mBackAnimationRunner; private final BackAnimationBackground mBackground; private final Context mContext; private RemoteAnimationTarget mEnteringTarget; private RemoteAnimationTarget mClosingTarget; - private SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction(); + private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction(); private boolean mBackInProgress = false; - private boolean mIsRightEdge; - private float mProgress = 0; - private PointF mTouchPos = new PointF(); + private final PointF mTouchPos = new PointF(); private IRemoteAnimationFinishedCallback mFinishCallback; - private BackProgressAnimator mProgressAnimator = new BackProgressAnimator(); + private final BackProgressAnimator mProgressAnimator = new BackProgressAnimator(); + private float mInterWindowMargin; + private float mVerticalMargin; @Inject public CrossTaskBackAnimation(Context context, BackAnimationBackground background) { - mContext = context; mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context); mBackAnimationRunner = new BackAnimationRunner( new Callback(), new Runner(), context, CUJ_PREDICTIVE_BACK_CROSS_TASK); mBackground = background; - } - - private static void computeScaleTransformMatrix(float scale, float[] matrix) { - matrix[0] = scale; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = scale; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = scale; + mContext = context; } private static float mapRange(float value, float min, float max) { @@ -146,7 +121,7 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { } private float getInterpolatedProgress(float backProgress) { - return 1 - (1 - backProgress) * (1 - backProgress) * (1 - backProgress); + return mProgressInterpolator.getInterpolation(backProgress); } private void startBackAnimation() { @@ -162,6 +137,10 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { // Draw background. mBackground.ensureBackground(mClosingTarget.windowConfiguration.getBounds(), BACKGROUNDCOLOR, mTransaction); + mInterWindowMargin = mContext.getResources() + .getDimension(R.dimen.cross_task_back_inter_window_margin); + mVerticalMargin = mContext.getResources() + .getDimension(R.dimen.cross_task_back_vertical_margin); } private void updateGestureBackProgress(float progress, BackEvent event) { @@ -169,44 +148,38 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { return; } - float touchX = event.getTouchX(); float touchY = event.getTouchY(); - float dX = Math.abs(touchX - mInitialTouchPos.x); // The 'follow width' is the width of the window if it completely matches // the gesture displacement. final int width = mStartTaskRect.width(); final int height = mStartTaskRect.height(); - // The 'progress width' is the width of the window if it strictly linearly interpolates - // to minimum scale base on progress. - float enteringScale = mapRange(progress, 1, ENTERING_MIN_WINDOW_SCALE); - float closingScale = mapRange(progress, 1, CLOSING_MIN_WINDOW_SCALE); - float closingColorScale = mapRange(progress, 1, CLOSING_MIN_WINDOW_COLOR_SCALE); - - // The final width is derived from interpolating between the follow with and progress width - // using gesture progress. - float enteringWidth = enteringScale * width; - float closingWidth = closingScale * width; - float enteringHeight = (float) height / width * enteringWidth; - float closingHeight = (float) height / width * closingWidth; + float scale = mapRange(progress, 1, MIN_WINDOW_SCALE); + float scaledWidth = scale * width; + float scaledHeight = scale * height; - float deltaYRatio = (touchY - mInitialTouchPos.y) / height; // Base the window movement in the Y axis on the touch movement in the Y axis. - float deltaY = (float) Math.sin(deltaYRatio * Math.PI * 0.5f) * WINDOW_MAX_DELTA_Y; + float rawYDelta = touchY - mInitialTouchPos.y; + float yDirection = rawYDelta < 0 ? -1 : 1; + // limit yDelta interpretation to 1/2 of screen height in either direction + float deltaYRatio = Math.min(height / 2f, Math.abs(rawYDelta)) / (height / 2f); + float interpolatedYRatio = mYMovementInterpolator.getInterpolation(deltaYRatio); + // limit y-shift so surface never passes 8dp screen margin + float deltaY = yDirection * interpolatedYRatio * Math.max(0f, + (height - scaledHeight) / 2f - mVerticalMargin); + // Move the window along the Y axis. - float closingTop = (height - closingHeight) * 0.5f + deltaY; - float enteringTop = (height - enteringHeight) * 0.5f + deltaY; + float scaledTop = (height - scaledHeight) * 0.5f + deltaY; // Move the window along the X axis. - float right = width - (progress * WINDOW_MARGIN); - float left = right - closingWidth; + float right = width - (progress * mVerticalMargin); + float left = right - scaledWidth; - mClosingCurrentRect.set(left, closingTop, right, closingTop + closingHeight); - mEnteringCurrentRect.set(left - enteringWidth - WINDOW_MARGIN, enteringTop, - left - WINDOW_MARGIN, enteringTop + enteringHeight); + mClosingCurrentRect.set(left, scaledTop, right, scaledTop + scaledHeight); + mEnteringCurrentRect.set(left - scaledWidth - mInterWindowMargin, scaledTop, + left - mInterWindowMargin, scaledTop + scaledHeight); applyTransform(mClosingTarget.leash, mClosingCurrentRect, mCornerRadius); - applyColorTransform(mClosingTarget.leash, closingColorScale); applyTransform(mEnteringTarget.leash, mEnteringCurrentRect, mCornerRadius); mTransaction.apply(); @@ -214,9 +187,21 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { } private void updatePostCommitClosingAnimation(float progress) { + float targetLeft = + mStartTaskRect.left + (1 - MIN_WINDOW_SCALE) * mStartTaskRect.width() / 2; + float targetTop = + mStartTaskRect.top + (1 - MIN_WINDOW_SCALE) * mStartTaskRect.height() / 2; + float targetWidth = mStartTaskRect.width() * MIN_WINDOW_SCALE; + float targetHeight = mStartTaskRect.height() * MIN_WINDOW_SCALE; + + float left = mapRange(progress, mClosingStartRect.left, targetLeft); + float top = mapRange(progress, mClosingStartRect.top, targetTop); + float width = mapRange(progress, mClosingStartRect.width(), targetWidth); + float height = mapRange(progress, mClosingStartRect.height(), targetHeight); mTransaction.setLayer(mClosingTarget.leash, 0); - float alpha = mapRange(progress, 1, 0); - mTransaction.setAlpha(mClosingTarget.leash, alpha); + + mClosingCurrentRect.set(left, top, left + width, top + height); + applyTransform(mClosingTarget.leash, mClosingCurrentRect, mCornerRadius); } private void updatePostCommitEnteringAnimation(float progress) { @@ -244,14 +229,6 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { .setCornerRadius(leash, cornerRadius); } - private void applyColorTransform(SurfaceControl leash, float colorScale) { - if (leash == null) { - return; - } - computeScaleTransformMatrix(colorScale, mTmpFloat9); - mTransaction.setColorTransform(leash, mTmpFloat9, mTmpTranslate); - } - private void finishAnimation() { if (mEnteringTarget != null) { mEnteringTarget.leash.release(); @@ -276,7 +253,8 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { try { mFinishCallback.onAnimationFinished(); } catch (RemoteException e) { - e.printStackTrace(); + ProtoLog.e(WM_SHELL_BACK_PREVIEW, + "RemoteException when invoking onAnimationFinished callback"); } mFinishCallback = null; } @@ -285,12 +263,11 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private void onGestureProgress(@NonNull BackEvent backEvent) { if (!mBackInProgress) { mInitialTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY()); - mIsRightEdge = backEvent.getSwipeEdge() == EDGE_RIGHT; mBackInProgress = true; } - mProgress = backEvent.getProgress(); + float progress = backEvent.getProgress(); mTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY()); - updateGestureBackProgress(getInterpolatedProgress(mProgress), backEvent); + updateGestureBackProgress(getInterpolatedProgress(progress), backEvent); } private void onGestureCommitted() { @@ -302,9 +279,11 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { // We enter phase 2 of the animation, the starting coordinates for phase 2 are the current // coordinate of the gesture driven phase. mEnteringCurrentRect.round(mEnteringStartRect); + mClosingCurrentRect.round(mClosingStartRect); - ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f, 0f).setDuration(300); - valueAnimator.setInterpolator(mInterpolator); + ValueAnimator valueAnimator = + ValueAnimator.ofFloat(1f, 0f).setDuration(POST_ANIMATION_DURATION_MS); + valueAnimator.setInterpolator(mPostAnimationInterpolator); valueAnimator.addUpdateListener(animation -> { float progress = animation.getAnimatedFraction(); updatePostCommitEnteringAnimation(progress); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimation.java index 312e88db863e..dc659197848e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimation.java @@ -34,6 +34,9 @@ public abstract class ShellBackAnimation { @Qualifier public @interface ReturnToHome {} + @Qualifier + public @interface DialogClose {} + /** Retrieve the {@link BackAnimationRunner} associated with this animation. */ public abstract BackAnimationRunner getRunner(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java index 62b18f342995..26d20972c751 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java @@ -33,17 +33,22 @@ public class ShellBackAnimationRegistry { public ShellBackAnimationRegistry( @ShellBackAnimation.CrossActivity @Nullable ShellBackAnimation crossActivityAnimation, @ShellBackAnimation.CrossTask @Nullable ShellBackAnimation crossTaskAnimation, + @ShellBackAnimation.DialogClose @Nullable ShellBackAnimation dialogCloseAnimation, @ShellBackAnimation.CustomizeActivity @Nullable ShellBackAnimation customizeActivityAnimation, @ShellBackAnimation.ReturnToHome @Nullable ShellBackAnimation defaultBackToHomeAnimation) { if (crossActivityAnimation != null) { mAnimationDefinition.set( + BackNavigationInfo.TYPE_CROSS_ACTIVITY, crossActivityAnimation.getRunner()); + } + if (crossTaskAnimation != null) { + mAnimationDefinition.set( BackNavigationInfo.TYPE_CROSS_TASK, crossTaskAnimation.getRunner()); } - if (crossActivityAnimation != null) { + if (dialogCloseAnimation != null) { mAnimationDefinition.set( - BackNavigationInfo.TYPE_CROSS_ACTIVITY, crossActivityAnimation.getRunner()); + BackNavigationInfo.TYPE_DIALOG_CLOSE, dialogCloseAnimation.getRunner()); } if (defaultBackToHomeAnimation != null) { mAnimationDefinition.set( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt index 84feb03e6a40..108aa8275009 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt @@ -129,9 +129,7 @@ object PipUtils { @JvmStatic fun getTaskSnapshot(taskId: Int, isLowResolution: Boolean): TaskSnapshot? { return if (taskId <= 0) null else try { - ActivityTaskManager.getService().getTaskSnapshot( - taskId, isLowResolution, false /* takeSnapshotIfNeeded */ - ) + ActivityTaskManager.getService().getTaskSnapshot(taskId, isLowResolution) } catch (e: RemoteException) { Log.e(TAG, "Failed to get task snapshot, taskId=$taskId", e) null diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java index 953efa78326c..86571cf9c622 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java @@ -20,8 +20,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.AppCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; -import android.app.TaskInfo.CameraCompatControlState; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -239,7 +239,7 @@ public class CompatUIController implements OnDisplaysChangedListener, */ public void onCompatInfoChanged(@NonNull TaskInfo taskInfo, @Nullable ShellTaskOrganizer.TaskListener taskListener) { - if (taskInfo != null && !taskInfo.topActivityInSizeCompat) { + if (taskInfo != null && !taskInfo.appCompatTaskInfo.topActivityInSizeCompat) { mSetOfTaskIdsShowingRestartDialog.remove(taskInfo.taskId); } @@ -267,7 +267,7 @@ public class CompatUIController implements OnDisplaysChangedListener, } return; } - if (!taskInfo.isFromLetterboxDoubleTap) { + if (!taskInfo.appCompatTaskInfo.isFromLetterboxDoubleTap) { createOrUpdateUserAspectRatioSettingsLayout(taskInfo, taskListener); } } @@ -348,7 +348,8 @@ public class CompatUIController implements OnDisplaysChangedListener, // as they are still relevant. Else, if the activity is visible and focused (the one the // user can see and is using), the user aspect ratio button can potentially be displayed so // start tracking the buttons visibility for this task. - if (mTopActivityTaskId != taskInfo.taskId && !taskInfo.isTopActivityTransparent + if (mTopActivityTaskId != taskInfo.taskId + && !taskInfo.isTopActivityTransparent && taskInfo.isVisible && taskInfo.isFocused) { mTopActivityTaskId = taskInfo.taskId; setHasShownUserAspectRatioSettingsButton(false); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java index d44b4d8f63b6..a0986fa601f2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java @@ -16,9 +16,10 @@ package com.android.wm.shell.compatui; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; + import android.annotation.IdRes; -import android.app.TaskInfo; -import android.app.TaskInfo.CameraCompatControlState; +import android.app.AppCompatTaskInfo.CameraCompatControlState; import android.content.Context; import android.util.AttributeSet; import android.view.View; @@ -57,10 +58,10 @@ class CompatUILayout extends LinearLayout { } void updateCameraTreatmentButton(@CameraCompatControlState int newState) { - int buttonBkgId = newState == TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED + int buttonBkgId = newState == CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED ? R.drawable.camera_compat_treatment_suggested_ripple : R.drawable.camera_compat_treatment_applied_ripple; - int hintStringId = newState == TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED + int hintStringId = newState == CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED ? R.string.camera_compat_treatment_suggested_button_description : R.string.camera_compat_treatment_applied_button_description; final ImageButton button = findViewById(R.id.camera_compat_treatment_button); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java index ce3c5093fdd4..00e0cdb034b6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java @@ -16,15 +16,15 @@ package com.android.wm.shell.compatui; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI; import android.annotation.Nullable; +import android.app.AppCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; -import android.app.TaskInfo.CameraCompatControlState; import android.content.Context; import android.graphics.Rect; import android.util.Log; @@ -75,8 +75,8 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> onRestartButtonClicked) { super(context, taskInfo, syncQueue, taskListener, displayLayout); mCallback = callback; - mHasSizeCompat = taskInfo.topActivityInSizeCompat; - mCameraCompatControlState = taskInfo.cameraCompatControlState; + mHasSizeCompat = taskInfo.appCompatTaskInfo.topActivityInSizeCompat; + mCameraCompatControlState = taskInfo.appCompatTaskInfo.cameraCompatControlState; mCompatUIHintsState = compatUIHintsState; mCompatUIConfiguration = compatUIConfiguration; mOnRestartButtonClicked = onRestartButtonClicked; @@ -127,8 +127,8 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { boolean canShow) { final boolean prevHasSizeCompat = mHasSizeCompat; final int prevCameraCompatControlState = mCameraCompatControlState; - mHasSizeCompat = taskInfo.topActivityInSizeCompat; - mCameraCompatControlState = taskInfo.cameraCompatControlState; + mHasSizeCompat = taskInfo.appCompatTaskInfo.topActivityInSizeCompat; + mCameraCompatControlState = taskInfo.appCompatTaskInfo.cameraCompatControlState; if (!super.updateCompatInfo(taskInfo, taskListener, canShow)) { return false; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java index fce1a39399d0..623feada0172 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java @@ -103,7 +103,8 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract { R.dimen.letterbox_education_dialog_margin); mDockStateReader = dockStateReader; mCompatUIConfiguration = compatUIConfiguration; - mEligibleForLetterboxEducation = taskInfo.topActivityEligibleForLetterboxEducation; + mEligibleForLetterboxEducation = + taskInfo.appCompatTaskInfo.topActivityEligibleForLetterboxEducation; } @Override @@ -204,7 +205,8 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract { @Override public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, boolean canShow) { - mEligibleForLetterboxEducation = taskInfo.topActivityEligibleForLetterboxEducation; + mEligibleForLetterboxEducation = + taskInfo.appCompatTaskInfo.topActivityEligibleForLetterboxEducation; return super.updateCompatInfo(taskInfo, taskListener, canShow); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java index 5612bc8ef226..835f1af85c51 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java @@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI; import android.annotation.Nullable; +import android.app.AppCompatTaskInfo; import android.app.TaskInfo; import android.content.Context; import android.graphics.Rect; @@ -89,11 +90,12 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract { BiConsumer<TaskInfo, ShellTaskOrganizer.TaskListener> onDismissCallback, Function<Integer, Integer> disappearTimeSupplier) { super(context, taskInfo, syncQueue, taskListener, displayLayout); - mIsActivityLetterboxed = taskInfo.isLetterboxDoubleTapEnabled; - mLetterboxVerticalPosition = taskInfo.topActivityLetterboxVerticalPosition; - mLetterboxHorizontalPosition = taskInfo.topActivityLetterboxHorizontalPosition; - mTopActivityLetterboxWidth = taskInfo.topActivityLetterboxWidth; - mTopActivityLetterboxHeight = taskInfo.topActivityLetterboxHeight; + final AppCompatTaskInfo appCompatTaskInfo = taskInfo.appCompatTaskInfo; + mIsActivityLetterboxed = appCompatTaskInfo.isLetterboxDoubleTapEnabled; + mLetterboxVerticalPosition = appCompatTaskInfo.topActivityLetterboxVerticalPosition; + mLetterboxHorizontalPosition = appCompatTaskInfo.topActivityLetterboxHorizontalPosition; + mTopActivityLetterboxWidth = appCompatTaskInfo.topActivityLetterboxWidth; + mTopActivityLetterboxHeight = appCompatTaskInfo.topActivityLetterboxHeight; mCompatUIConfiguration = compatUIConfiguration; mMainExecutor = mainExecutor; mOnDismissCallback = onDismissCallback; @@ -145,12 +147,13 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract { final int prevLetterboxHorizontalPosition = mLetterboxHorizontalPosition; final int prevTopActivityLetterboxWidth = mTopActivityLetterboxWidth; final int prevTopActivityLetterboxHeight = mTopActivityLetterboxHeight; - mIsActivityLetterboxed = taskInfo.isLetterboxDoubleTapEnabled; - mLetterboxVerticalPosition = taskInfo.topActivityLetterboxVerticalPosition; - mLetterboxHorizontalPosition = taskInfo.topActivityLetterboxHorizontalPosition; - mTopActivityLetterboxWidth = taskInfo.topActivityLetterboxWidth; - mTopActivityLetterboxHeight = taskInfo.topActivityLetterboxHeight; - mHasUserDoubleTapped = taskInfo.isFromLetterboxDoubleTap; + final AppCompatTaskInfo appCompatTaskInfo = taskInfo.appCompatTaskInfo; + mIsActivityLetterboxed = appCompatTaskInfo.isLetterboxDoubleTapEnabled; + mLetterboxVerticalPosition = appCompatTaskInfo.topActivityLetterboxVerticalPosition; + mLetterboxHorizontalPosition = appCompatTaskInfo.topActivityLetterboxHorizontalPosition; + mTopActivityLetterboxWidth = appCompatTaskInfo.topActivityLetterboxWidth; + mTopActivityLetterboxHeight = appCompatTaskInfo.topActivityLetterboxHeight; + mHasUserDoubleTapped = appCompatTaskInfo.isFromLetterboxDoubleTap; if (!super.updateCompatInfo(taskInfo, taskListener, canShow)) { return false; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java index c2dec623416b..ef763ec45994 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java @@ -227,9 +227,9 @@ class UserAspectRatioSettingsWindowManager extends CompatUIWindowManagerAbstract } private boolean getHasUserAspectRatioSettingsButton(@NonNull TaskInfo taskInfo) { - return taskInfo.topActivityEligibleForUserAspectRatioButton - && (taskInfo.topActivityBoundsLetterboxed - || taskInfo.isUserFullscreenOverrideEnabled) + return taskInfo.appCompatTaskInfo.topActivityEligibleForUserAspectRatioButton + && (taskInfo.appCompatTaskInfo.topActivityBoundsLetterboxed + || taskInfo.appCompatTaskInfo.isUserFullscreenOverrideEnabled) && (!mUserAspectRatioButtonShownChecker.get() || isShowingButton()); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java index ea7b2e92fefb..64294c9dbdc6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java @@ -103,6 +103,7 @@ import com.android.wm.shell.sysui.ShellInterface; import com.android.wm.shell.taskview.TaskViewFactory; import com.android.wm.shell.taskview.TaskViewFactoryController; import com.android.wm.shell.taskview.TaskViewTransitions; +import com.android.wm.shell.transition.HomeTransitionObserver; import com.android.wm.shell.transition.ShellTransitions; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.unfold.ShellUnfoldProgressProvider; @@ -613,14 +614,22 @@ public abstract class WMShellBaseModule { @ShellMainThread ShellExecutor mainExecutor, @ShellMainThread Handler mainHandler, @ShellAnimationThread ShellExecutor animExecutor, - RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) { + RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, + HomeTransitionObserver homeTransitionObserver) { if (!context.getResources().getBoolean(R.bool.config_registerShellTransitionsOnInit)) { // TODO(b/238217847): Force override shell init if registration is disabled shellInit = new ShellInit(mainExecutor); } return new Transitions(context, shellInit, shellCommandHandler, shellController, organizer, pool, displayController, mainExecutor, mainHandler, animExecutor, - rootTaskDisplayAreaOrganizer); + rootTaskDisplayAreaOrganizer, homeTransitionObserver); + } + + @WMSingleton + @Provides + static HomeTransitionObserver provideHomeTransitionObserver(Context context, + @ShellMainThread ShellExecutor mainExecutor) { + return new HomeTransitionObserver(context, mainExecutor); } @WMSingleton diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index a533ca5fa8fb..47769a8eeb11 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -78,6 +78,7 @@ import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.taskview.TaskViewTransitions; import com.android.wm.shell.transition.DefaultMixedHandler; +import com.android.wm.shell.transition.HomeTransitionObserver; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.unfold.ShellUnfoldProgressProvider; import com.android.wm.shell.unfold.UnfoldAnimationController; @@ -380,9 +381,10 @@ public abstract class WMShellModule { static RecentsTransitionHandler provideRecentsTransitionHandler( ShellInit shellInit, Transitions transitions, - Optional<RecentTasksController> recentTasksController) { + Optional<RecentTasksController> recentTasksController, + HomeTransitionObserver homeTransitionObserver) { return new RecentsTransitionHandler(shellInit, transitions, - recentTasksController.orElse(null)); + recentTasksController.orElse(null), homeTransitionObserver); } // diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/back/ShellBackAnimationModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/back/ShellBackAnimationModule.java index b34c6b213df4..3be7d970e922 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/back/ShellBackAnimationModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/back/ShellBackAnimationModule.java @@ -38,6 +38,7 @@ public interface ShellBackAnimationModule { return new ShellBackAnimationRegistry( crossActivity, crossTask, + /* dialogCloseAnimation */ null, customizeActivity, /* defaultBackToHomeAnimation= */ null); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java index 1898ea737729..3b48c67a5bbd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java @@ -22,6 +22,8 @@ import android.content.Context; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayInsetsController; +import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.common.pip.PipBoundsAlgorithm; import com.android.wm.shell.common.pip.PipBoundsState; import com.android.wm.shell.common.pip.PipDisplayLayoutState; @@ -29,6 +31,7 @@ import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.dagger.WMShellBaseModule; import com.android.wm.shell.dagger.WMSingleton; import com.android.wm.shell.pip2.phone.PipController; +import com.android.wm.shell.pip2.phone.PipScheduler; import com.android.wm.shell.pip2.phone.PipTransition; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; @@ -52,9 +55,10 @@ public abstract class Pip2Module { @NonNull Transitions transitions, PipBoundsState pipBoundsState, PipBoundsAlgorithm pipBoundsAlgorithm, - Optional<PipController> pipController) { + Optional<PipController> pipController, + @NonNull PipScheduler pipScheduler) { return new PipTransition(shellInit, shellTaskOrganizer, transitions, pipBoundsState, null, - pipBoundsAlgorithm); + pipBoundsAlgorithm, pipScheduler); } @WMSingleton @@ -73,4 +77,12 @@ public abstract class Pip2Module { pipDisplayLayoutState)); } } + + @WMSingleton + @Provides + static PipScheduler providePipScheduler(Context context, + PipBoundsState pipBoundsState, + @ShellMainThread ShellExecutor mainExecutor) { + return new PipScheduler(context, pipBoundsState, mainExecutor); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index 412a5b5a6997..8e12991080ed 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -343,9 +343,8 @@ class DesktopTasksController( task.taskId ) val wct = WindowContainerTransaction() - wct.setWindowingMode(task.token, WINDOWING_MODE_MULTI_WINDOW) wct.setBounds(task.token, Rect()) - wct.setDensityDpi(task.token, getDefaultDensityDpi()) + addMoveToSplitChanges(wct, task) if (Transitions.ENABLE_SHELL_TRANSITIONS) { transitions.startTransition(TRANSIT_CHANGE, wct, null /* handler */) } else { @@ -827,7 +826,9 @@ class DesktopTasksController( wct: WindowContainerTransaction, taskInfo: RunningTaskInfo ) { - wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_MULTI_WINDOW) + // Explicitly setting multi-window at task level interferes with animations. + // Let task inherit windowing mode once transition is complete instead. + wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED) // The task's density may have been overridden in freeform; revert it here as we don't // want it overridden in multi-window. wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java index 53b5bd7ceb94..dba7f4bdd78d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java @@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_OCCLUDING; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_UNOCCLUDING; import static android.view.WindowManager.TRANSIT_SLEEP; @@ -134,24 +135,28 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler "going-away", transition, info, startTransaction, finishTransaction, finishCallback); } - if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_OCCLUDING) != 0) { - if (hasOpeningDream(info)) { - return startAnimation(mOccludeByDreamTransition, - "occlude-by-dream", - transition, info, startTransaction, finishTransaction, finishCallback); - } else { - return startAnimation(mOccludeTransition, - "occlude", + + // Occlude/unocclude animations are only played if the keyguard is locked. + if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0) { + if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_OCCLUDING) != 0) { + if (hasOpeningDream(info)) { + return startAnimation(mOccludeByDreamTransition, + "occlude-by-dream", + transition, info, startTransaction, finishTransaction, finishCallback); + } else { + return startAnimation(mOccludeTransition, + "occlude", + transition, info, startTransaction, finishTransaction, finishCallback); + } + } else if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_UNOCCLUDING) != 0) { + return startAnimation(mUnoccludeTransition, + "unocclude", transition, info, startTransaction, finishTransaction, finishCallback); } - } else if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_UNOCCLUDING) != 0) { - return startAnimation(mUnoccludeTransition, - "unocclude", - transition, info, startTransaction, finishTransaction, finishCallback); - } else { - Log.i(TAG, "Refused to play keyguard transition: " + info); - return false; } + + Log.i(TAG, "Refused to play keyguard transition: " + info); + return false; } private boolean startAnimation(IRemoteTransition remoteHandler, String description, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java new file mode 100644 index 000000000000..9bb383f0b61a --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2023 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.pip2.phone; + +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; + +import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.view.SurfaceControl; +import android.window.WindowContainerToken; +import android.window.WindowContainerTransaction; + +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; + +import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.common.pip.PipBoundsState; +import com.android.wm.shell.common.pip.PipUtils; +import com.android.wm.shell.pip.PipTransitionController; + +/** + * Scheduler for Shell initiated PiP transitions and animations. + */ +public class PipScheduler { + private static final String TAG = PipScheduler.class.getSimpleName(); + private static final String BROADCAST_FILTER = PipScheduler.class.getCanonicalName(); + + private final Context mContext; + private final PipBoundsState mPipBoundsState; + private final ShellExecutor mMainExecutor; + private PipSchedulerReceiver mSchedulerReceiver; + private PipTransitionController mPipTransitionController; + + // pinned PiP task's WC token + @Nullable + private WindowContainerToken mPipTaskToken; + + // pinned PiP task's leash + @Nullable + private SurfaceControl mPinnedTaskLeash; + + // the leash of the original task of the PiP activity; + // used to synchronize app drawings in the multi-activity case + @Nullable + private SurfaceControl mOriginalTaskLeash; + + /** + * A temporary broadcast receiver to initiate exit PiP via expand. + * This will later be modified to be triggered by the PiP menu. + */ + private class PipSchedulerReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + scheduleExitPipViaExpand(); + } + } + + public PipScheduler(Context context, PipBoundsState pipBoundsState, + ShellExecutor mainExecutor) { + mContext = context; + mPipBoundsState = pipBoundsState; + mMainExecutor = mainExecutor; + + if (PipUtils.isPip2ExperimentEnabled()) { + // temporary broadcast receiver to initiate exit PiP via expand + mSchedulerReceiver = new PipSchedulerReceiver(); + ContextCompat.registerReceiver(mContext, mSchedulerReceiver, + new IntentFilter(BROADCAST_FILTER), ContextCompat.RECEIVER_EXPORTED); + } + } + + void setPipTransitionController(PipTransitionController pipTransitionController) { + mPipTransitionController = pipTransitionController; + } + + void setPinnedTaskLeash(SurfaceControl pinnedTaskLeash) { + mPinnedTaskLeash = pinnedTaskLeash; + } + + void setOriginalTaskLeash(SurfaceControl originalTaskLeash) { + mOriginalTaskLeash = originalTaskLeash; + } + + void setPipTaskToken(@Nullable WindowContainerToken pipTaskToken) { + mPipTaskToken = pipTaskToken; + } + + @Nullable + private WindowContainerTransaction getExitPipViaExpandTransaction() { + if (mPipTaskToken == null || mPinnedTaskLeash == null) { + return null; + } + WindowContainerTransaction wct = new WindowContainerTransaction(); + // final expanded bounds to be inherited from the parent + wct.setBounds(mPipTaskToken, null); + // if we are hitting a multi-activity case + // windowing mode change will reparent to original host task + wct.setWindowingMode(mPipTaskToken, WINDOWING_MODE_UNDEFINED); + return wct; + } + + /** + * Schedules exit PiP via expand transition. + */ + public void scheduleExitPipViaExpand() { + WindowContainerTransaction wct = getExitPipViaExpandTransaction(); + if (wct != null) { + mMainExecutor.execute(() -> { + mPipTransitionController.startExitTransition(TRANSIT_EXIT_PIP, wct, + null /* destinationBounds */); + }); + } + } + + void onExitPip() { + mPipTaskToken = null; + mPinnedTaskLeash = null; + mOriginalTaskLeash = null; + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java index d704b091754f..7d3bd658d126 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java @@ -16,8 +16,12 @@ package com.android.wm.shell.pip2.phone; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.view.WindowManager.TRANSIT_OPEN; +import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP; + import android.annotation.NonNull; import android.app.ActivityManager; import android.app.PictureInPictureParams; @@ -26,6 +30,7 @@ import android.os.IBinder; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; +import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import androidx.annotation.Nullable; @@ -43,8 +48,15 @@ import com.android.wm.shell.transition.Transitions; * Implementation of transitions for PiP on phone. */ public class PipTransition extends PipTransitionController { + private static final String TAG = PipTransition.class.getSimpleName(); + + private PipScheduler mPipScheduler; + @Nullable + private WindowContainerToken mPipTaskToken; @Nullable private IBinder mAutoEnterButtonNavTransition; + @Nullable + private IBinder mExitViaExpandTransition; public PipTransition( @NonNull ShellInit shellInit, @@ -52,9 +64,13 @@ public class PipTransition extends PipTransitionController { @NonNull Transitions transitions, PipBoundsState pipBoundsState, PipMenuController pipMenuController, - PipBoundsAlgorithm pipBoundsAlgorithm) { + PipBoundsAlgorithm pipBoundsAlgorithm, + PipScheduler pipScheduler) { super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController, pipBoundsAlgorithm); + + mPipScheduler = pipScheduler; + mPipScheduler.setPipTransitionController(this); } @Override @@ -64,6 +80,18 @@ public class PipTransition extends PipTransitionController { } } + @Override + public void startExitTransition(int type, WindowContainerTransaction out, + @android.annotation.Nullable Rect destinationBounds) { + if (out == null) { + return; + } + IBinder transition = mTransitions.startTransition(type, out, this); + if (type == TRANSIT_EXIT_PIP) { + mExitViaExpandTransition = transition; + } + } + @Nullable @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, @@ -84,8 +112,18 @@ public class PipTransition extends PipTransitionController { } } + @Override + public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, + @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, + @NonNull Transitions.TransitionFinishCallback finishCallback) {} + + @Override + public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted, + @Nullable SurfaceControl.Transaction finishT) {} + private WindowContainerTransaction getEnterPipTransaction(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { + // cache the original task token to check for multi-activity case later final ActivityManager.RunningTaskInfo pipTask = request.getPipTask(); PictureInPictureParams pipParams = pipTask.pictureInPictureParams; mPipBoundsState.setBoundsStateForEntry(pipTask.topActivity, pipTask.topActivityInfo, @@ -93,6 +131,8 @@ public class PipTransition extends PipTransitionController { // calculate the entry bounds and notify core to move task to pinned with final bounds final Rect entryBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); + mPipBoundsState.setBounds(entryBounds); + WindowContainerTransaction wct = new WindowContainerTransaction(); wct.movePipActivityToPinnedRootTask(pipTask.token, entryBounds); return wct; @@ -121,19 +161,59 @@ public class PipTransition extends PipTransitionController { @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { if (transition == mAutoEnterButtonNavTransition) { + mAutoEnterButtonNavTransition = null; + TransitionInfo.Change pipChange = getPipChange(info); + if (pipChange == null) { + return false; + } + mPipTaskToken = pipChange.getContainer(); + + // cache the PiP task token and the relevant leashes + mPipScheduler.setPipTaskToken(mPipTaskToken); + mPipScheduler.setPinnedTaskLeash(pipChange.getLeash()); + // check if we entered PiP from a multi-activity task and set the original task leash + final int lastParentTaskId = pipChange.getTaskInfo().lastParentTaskIdBeforePip; + final boolean isSingleActivity = lastParentTaskId == INVALID_TASK_ID; + mPipScheduler.setOriginalTaskLeash(isSingleActivity ? null : + findChangeByTaskId(info, lastParentTaskId).getLeash()); + startTransaction.apply(); finishCallback.onTransitionFinished(null); return true; + } else if (transition == mExitViaExpandTransition) { + mExitViaExpandTransition = null; + startTransaction.apply(); + finishCallback.onTransitionFinished(null); + onExitPip(); + return true; } return false; } - @Override - public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, - @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, - @NonNull Transitions.TransitionFinishCallback finishCallback) {} + @Nullable + private TransitionInfo.Change getPipChange(TransitionInfo info) { + for (TransitionInfo.Change change : info.getChanges()) { + if (change.getTaskInfo() != null + && change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_PINNED) { + return change; + } + } + return null; + } - @Override - public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted, - @Nullable SurfaceControl.Transaction finishT) {} + @Nullable + private TransitionInfo.Change findChangeByTaskId(TransitionInfo info, int taskId) { + for (TransitionInfo.Change change : info.getChanges()) { + if (change.getTaskInfo() != null + && change.getTaskInfo().taskId == taskId) { + return change; + } + } + return null; + } + + private void onExitPip() { + mPipTaskToken = null; + mPipScheduler.onExitPip(); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java index d277eef761e9..c20d23e4374e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java @@ -59,6 +59,7 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.transition.HomeTransitionObserver; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.util.TransitionUtil; @@ -85,11 +86,15 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { */ private final ArrayList<RecentsMixedHandler> mMixers = new ArrayList<>(); + private final HomeTransitionObserver mHomeTransitionObserver; + public RecentsTransitionHandler(ShellInit shellInit, Transitions transitions, - @Nullable RecentTasksController recentTasksController) { + @Nullable RecentTasksController recentTasksController, + HomeTransitionObserver homeTransitionObserver) { mTransitions = transitions; mExecutor = transitions.getMainExecutor(); mRecentTasksController = recentTasksController; + mHomeTransitionObserver = homeTransitionObserver; if (!Transitions.ENABLE_SHELL_TRANSITIONS) return; if (recentTasksController == null) return; shellInit.addInitCallback(() -> { @@ -911,6 +916,11 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { Slog.e(TAG, "Duplicate call to finish"); return; } + if (!toHome) { + // For some transitions, we may have notified home activity that it became visible. + // We need to notify the observer that we are no longer going home. + mHomeTransitionObserver.notifyHomeVisibilityChanged(false); + } ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "[%d] RecentsController.finishInner: toHome=%b userLeave=%b " + "willFinishToHome=%b state=%d", diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java index 0c6adc942385..43ae5f47c92f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java @@ -23,6 +23,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN; import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN; import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN; +import static android.window.StartingWindowInfo.TYPE_PARAMETER_APP_PREFERS_ICON; import android.annotation.ColorInt; import android.annotation.IntDef; @@ -125,6 +126,7 @@ public class SplashscreenContentDrawer { private final TransactionPool mTransactionPool; private final SplashScreenWindowAttrs mTmpAttrs = new SplashScreenWindowAttrs(); private final Handler mSplashscreenWorkerHandler; + private final boolean mCanUseAppIconForSplashScreen; @VisibleForTesting final ColorCache mColorCache; @@ -141,6 +143,8 @@ public class SplashscreenContentDrawer { shellSplashscreenWorkerThread.start(); mSplashscreenWorkerHandler = shellSplashscreenWorkerThread.getThreadHandler(); mColorCache = new ColorCache(mContext, mSplashscreenWorkerHandler); + mCanUseAppIconForSplashScreen = context.getResources().getBoolean( + com.android.wm.shell.R.bool.config_canUseAppIconForSplashScreen); } /** @@ -427,7 +431,10 @@ public class SplashscreenContentDrawer { getWindowAttrs(context, mTmpAttrs); mLastPackageContextConfigHash = context.getResources().getConfiguration().hashCode(); - final Drawable legacyDrawable = suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN + final @StartingWindowType int splashType = + suggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN && !canUseIcon(info) + ? STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN : suggestType; + final Drawable legacyDrawable = splashType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN ? peekLegacySplashscreenContent(context, mTmpAttrs) : null; final ActivityInfo ai = info.targetActivityInfo != null ? info.targetActivityInfo @@ -439,12 +446,17 @@ public class SplashscreenContentDrawer { return new SplashViewBuilder(context, ai) .setWindowBGColor(themeBGColor) .overlayDrawable(legacyDrawable) - .chooseStyle(suggestType) + .chooseStyle(splashType) .setUiThreadInitConsumer(uiThreadInitConsumer) .setAllowHandleSolidColor(info.allowHandleSolidColorSplashScreen()) .build(); } + private boolean canUseIcon(StartingWindowInfo info) { + return mCanUseAppIconForSplashScreen || mTmpAttrs.mSplashScreenIcon != null + || (info.startingWindowTypeParameter & TYPE_PARAMETER_APP_PREFERS_ICON) != 0; + } + private int getBGColorFromCache(ActivityInfo ai, IntSupplier windowBgColorSupplier) { return mColorCache.getWindowColor(ai.packageName, mLastPackageContextConfigHash, mTmpAttrs.mWindowBgColor, mTmpAttrs.mWindowBgResId, windowBgColorSupplier).mBgColor; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java index f561aa5568be..b528089d153e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java @@ -38,24 +38,15 @@ import com.android.wm.shell.util.TransitionUtil; */ public class HomeTransitionObserver implements TransitionObserver, RemoteCallable<HomeTransitionObserver> { - private final SingleInstanceRemoteListener<HomeTransitionObserver, IHomeTransitionListener> + private SingleInstanceRemoteListener<HomeTransitionObserver, IHomeTransitionListener> mListener; private @NonNull final Context mContext; private @NonNull final ShellExecutor mMainExecutor; - private @NonNull final Transitions mTransitions; - public HomeTransitionObserver(@NonNull Context context, - @NonNull ShellExecutor mainExecutor, - @NonNull Transitions transitions) { + @NonNull ShellExecutor mainExecutor) { mContext = context; mMainExecutor = mainExecutor; - mTransitions = transitions; - - mListener = new SingleInstanceRemoteListener<>(this, - c -> mTransitions.registerObserver(this), - c -> mTransitions.unregisterObserver(this)); - } @Override @@ -72,7 +63,7 @@ public class HomeTransitionObserver implements TransitionObserver, final int mode = change.getMode(); if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME && TransitionUtil.isOpenOrCloseMode(mode)) { - mListener.call(l -> l.onHomeVisibilityChanged(TransitionUtil.isOpeningType(mode))); + notifyHomeVisibilityChanged(TransitionUtil.isOpeningType(mode)); } } } @@ -92,7 +83,14 @@ public class HomeTransitionObserver implements TransitionObserver, * Sets the home transition listener that receives any transitions resulting in a change of * */ - public void setHomeTransitionListener(IHomeTransitionListener listener) { + public void setHomeTransitionListener(Transitions transitions, + IHomeTransitionListener listener) { + if (mListener == null) { + mListener = new SingleInstanceRemoteListener<>(this, + c -> transitions.registerObserver(this), + c -> transitions.unregisterObserver(this)); + } + if (listener != null) { mListener.register(listener); } else { @@ -100,6 +98,16 @@ public class HomeTransitionObserver implements TransitionObserver, } } + /** + * Notifies the listener that the home visibility has changed. + * @param isVisible true when home activity is visible, false otherwise. + */ + public void notifyHomeVisibilityChanged(boolean isVisible) { + if (mListener != null) { + mListener.call(l -> l.onHomeVisibilityChanged(isVisible)); + } + } + @Override public Context getContext() { return mContext; @@ -113,7 +121,7 @@ public class HomeTransitionObserver implements TransitionObserver, /** * Invalidates this controller, preventing future calls to send updates. */ - public void invalidate() { - mTransitions.unregisterObserver(this); + public void invalidate(Transitions transitions) { + transitions.unregisterObserver(this); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java index 030f601a7b60..4355ed2bd3bf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java @@ -83,7 +83,6 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { mMainExecutor.execute(() -> { finishCallback.onTransitionFinished(wct); }); - Log.d("b/302551868", "OneShotRemoteHandler#start remote anim null"); mRemote = null; } }; @@ -107,7 +106,6 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { mRemote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */); } finishCallback.onTransitionFinished(null /* wct */); - Log.d("b/302551868", "OneShotRemoteHandler#exception remote anim null"); mRemote = null; } return true; @@ -127,7 +125,6 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { // so just assume the worst-case and clear the local transaction. t.clear(); mMainExecutor.execute(() -> finishCallback.onTransitionFinished(wct)); - Log.d("b/302551868", "OneShotRemoteHandler#merge remote anim null"); mRemote = null; } }; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java index 718c704f2c65..ab5c0636f2b5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java @@ -192,6 +192,8 @@ public class Transitions implements RemoteCallable<Transitions>, private final ArrayList<TransitionObserver> mObservers = new ArrayList<>(); + private HomeTransitionObserver mHomeTransitionObserver; + /** List of {@link Runnable} instances to run when the last active transition has finished. */ private final ArrayList<Runnable> mRunWhenIdleQueue = new ArrayList<>(); @@ -267,10 +269,11 @@ public class Transitions implements RemoteCallable<Transitions>, @NonNull DisplayController displayController, @NonNull ShellExecutor mainExecutor, @NonNull Handler mainHandler, - @NonNull ShellExecutor animExecutor) { + @NonNull ShellExecutor animExecutor, + @NonNull HomeTransitionObserver observer) { this(context, shellInit, new ShellCommandHandler(), shellController, organizer, pool, displayController, mainExecutor, mainHandler, animExecutor, - new RootTaskDisplayAreaOrganizer(mainExecutor, context, shellInit)); + new RootTaskDisplayAreaOrganizer(mainExecutor, context, shellInit), observer); } public Transitions(@NonNull Context context, @@ -283,7 +286,8 @@ public class Transitions implements RemoteCallable<Transitions>, @NonNull ShellExecutor mainExecutor, @NonNull Handler mainHandler, @NonNull ShellExecutor animExecutor, - @NonNull RootTaskDisplayAreaOrganizer rootTDAOrganizer) { + @NonNull RootTaskDisplayAreaOrganizer rootTDAOrganizer, + @NonNull HomeTransitionObserver observer) { mOrganizer = organizer; mContext = context; mMainExecutor = mainExecutor; @@ -302,6 +306,7 @@ public class Transitions implements RemoteCallable<Transitions>, mHandlers.add(mRemoteTransitionHandler); ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: Remote"); shellInit.addInitCallback(this::onInit, this); + mHomeTransitionObserver = observer; } private void onInit() { @@ -351,7 +356,7 @@ public class Transitions implements RemoteCallable<Transitions>, } private ExternalInterfaceBinder createExternalInterface() { - return new IShellTransitionsImpl(mContext, getMainExecutor(), this); + return new IShellTransitionsImpl(this); } @Override @@ -1397,12 +1402,9 @@ public class Transitions implements RemoteCallable<Transitions>, private static class IShellTransitionsImpl extends IShellTransitions.Stub implements ExternalInterfaceBinder { private Transitions mTransitions; - private final HomeTransitionObserver mHomeTransitionObserver; - IShellTransitionsImpl(Context context, ShellExecutor executor, Transitions transitions) { + IShellTransitionsImpl(Transitions transitions) { mTransitions = transitions; - mHomeTransitionObserver = new HomeTransitionObserver(context, executor, - mTransitions); } /** @@ -1410,7 +1412,7 @@ public class Transitions implements RemoteCallable<Transitions>, */ @Override public void invalidate() { - mHomeTransitionObserver.invalidate(); + mTransitions.mHomeTransitionObserver.invalidate(mTransitions); mTransitions = null; } @@ -1440,7 +1442,8 @@ public class Transitions implements RemoteCallable<Transitions>, public void setHomeTransitionListener(IHomeTransitionListener listener) { executeRemoteCallWithTaskPermission(mTransitions, "setHomeTransitionListener", (transitions) -> { - mHomeTransitionObserver.setHomeTransitionListener(listener); + transitions.mHomeTransitionObserver.setHomeTransitionListener(mTransitions, + listener); }); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index 716f8b81f158..e206039aa6bf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -82,6 +82,7 @@ import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; import com.android.wm.shell.recents.RecentsTransitionHandler; import com.android.wm.shell.recents.RecentsTransitionStateListener; import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.splitscreen.SplitScreen.StageType; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.sysui.KeyguardChangeListener; import com.android.wm.shell.sysui.ShellCommandHandler; @@ -238,7 +239,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mSplitScreenController = splitScreenController; mSplitScreenController.registerSplitScreenListener(new SplitScreen.SplitScreenListener() { @Override - public void onTaskStageChanged(int taskId, int stage, boolean visible) { + public void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) { if (visible) { DesktopModeWindowDecoration decor = mWindowDecorByTaskId.get(taskId); if (decor != null && DesktopModeStatus.isEnabled() @@ -391,10 +392,10 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId); final int id = v.getId(); if (id == R.id.close_window) { - mTaskOperations.closeTask(mTaskToken); if (isTaskInSplitScreen(mTaskId)) { - RunningTaskInfo remainingTask = getOtherSplitTask(mTaskId); - mSplitScreenController.moveTaskToFullscreen(remainingTask.taskId); + mSplitScreenController.moveTaskToFullscreen(getOtherSplitTask(mTaskId).taskId); + } else { + mTaskOperations.closeTask(mTaskToken); } } else if (id == R.id.back_button) { mTaskOperations.injectBackKey(); @@ -417,8 +418,12 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { } decoration.closeHandleMenu(); } else if (id == R.id.fullscreen_button) { - mDesktopTasksController.ifPresent(c -> c.moveToFullscreen(mTaskId)); decoration.closeHandleMenu(); + if (isTaskInSplitScreen(mTaskId)) { + mSplitScreenController.moveTaskToFullscreen(mTaskId); + } else { + mDesktopTasksController.ifPresent(c -> c.moveToFullscreen(mTaskId)); + } } else if (id == R.id.split_screen_button) { decoration.closeHandleMenu(); mDesktopTasksController.ifPresent(c -> { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt index 9dc86db4f59b..b1fb0f184bff 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt @@ -42,11 +42,11 @@ internal class DesktopModeFocusedWindowDecorationViewHolder( } override fun onHandleMenuOpened() { - animateCaptionHandleAlpha(startValue = 0f, endValue = 1f) + animateCaptionHandleAlpha(startValue = 1f, endValue = 0f) } override fun onHandleMenuClosed() { - animateCaptionHandleAlpha(startValue = 1f, endValue = 0f) + animateCaptionHandleAlpha(startValue = 0f, endValue = 1f) } private fun getCaptionHandleBarColor(taskInfo: RunningTaskInfo): Int { diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml index 1df11369a049..5b2ffec67e93 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml @@ -95,14 +95,6 @@ <option name="pull-pattern-keys" value="perfetto_file_path"/> <option name="directory-keys" value="/data/user/0/com.android.wm.shell.flicker/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.pip/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.splitscreen/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.service/files"/> <option name="collect-on-run-ended-only" value="true"/> <option name="clean-up" value="true"/> </metrics_collector> diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml index 1df11369a049..9f7d9fcf1326 100644 --- a/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml +++ b/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml @@ -94,15 +94,7 @@ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> <option name="pull-pattern-keys" value="perfetto_file_path"/> <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker/files"/> - <option name="directory-keys" value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.pip/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.splitscreen/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.service/files"/> <option name="collect-on-run-ended-only" value="true"/> <option name="clean-up" value="true"/> </metrics_collector> diff --git a/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml index 1df11369a049..882b200da3a2 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml +++ b/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml @@ -94,15 +94,9 @@ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> <option name="pull-pattern-keys" value="perfetto_file_path"/> <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/> - <option name="directory-keys" value="/data/user/0/com.android.wm.shell.flicker.pip/files"/> <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.splitscreen/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.service/files"/> + value="/data/user/0/com.android.wm.shell.flicker.pip.apps/files"/> <option name="collect-on-run-ended-only" value="true"/> <option name="clean-up" value="true"/> </metrics_collector> diff --git a/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml b/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml index ca182fa5a266..6df65391ea61 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml +++ b/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml @@ -57,6 +57,17 @@ <option name="test-file-name" value="WMShellFlickerTestsPipAppsCSuite.apk"/> <option name="test-file-name" value="FlickerTestApp.apk"/> </target_preparer> + + <!-- Needed for installing apk's from Play Store --> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="aapt-version" value="AAPT2"/> + <option name="throw-if-not-found" value="false"/> + <option name="install-arg" value="-d"/> + <option name="install-arg" value="-g"/> + <option name="install-arg" value="-r"/> + <option name="test-file-name" value="pstash://com.netflix.mediaclient"/> + </target_preparer> + <!-- Enable mocking GPS location by the test app --> <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> <option name="run-command" @@ -94,28 +105,8 @@ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> <option name="pull-pattern-keys" value="perfetto_file_path"/> <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.pip/files"/> - <option name="directory-keys" value="/data/user/0/com.android.wm.shell.flicker.pip.apps/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.splitscreen/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.service/files"/> <option name="collect-on-run-ended-only" value="true"/> <option name="clean-up" value="true"/> </metrics_collector> - - <!-- Needed for installing apk's from Play Store --> - <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> - <option name="aapt-version" value="AAPT2"/> - <option name="throw-if-not-found" value="false"/> - <option name="install-arg" value="-d"/> - <option name="install-arg" value="-g"/> - <option name="install-arg" value="-r"/> - <option name="test-file-name" value="pstash://com.netflix.mediaclient"/> - </target_preparer> </configuration> diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt index be5a27ac7dcc..bd8b0056a6a3 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt @@ -20,6 +20,8 @@ import android.platform.test.annotations.Postsubmit import android.tools.common.Rotation import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper +import android.tools.device.flicker.junit.FlickerBuilderProvider +import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.LegacyFlickerTest import android.tools.device.flicker.legacy.LegacyFlickerTestFactory import com.android.wm.shell.flicker.pip.common.EnterPipTransition @@ -29,6 +31,15 @@ import org.junit.runners.Parameterized abstract class AppsEnterPipTransition(flicker: LegacyFlickerTest) : EnterPipTransition(flicker) { protected abstract val standardAppHelper: StandardAppHelper + @FlickerBuilderProvider + override fun buildFlicker(): FlickerBuilder { + return FlickerBuilder(instrumentation).apply { + withoutScreenRecorder() + setup { flicker.scenario.setIsTablet(tapl.isTablet) } + transition() + } + } + /** Checks [standardAppHelper] window remains visible throughout the animation */ @Postsubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml index 1df11369a049..51a55e359acf 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml +++ b/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml @@ -94,14 +94,6 @@ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> <option name="pull-pattern-keys" value="perfetto_file_path"/> <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.pip/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.splitscreen/files"/> - <option name="directory-keys" value="/data/user/0/com.android.wm.shell.flicker.service/files"/> <option name="collect-on-run-ended-only" value="true"/> <option name="clean-up" value="true"/> diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml index 1df11369a049..fdda5974d1f9 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml @@ -94,15 +94,7 @@ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> <option name="pull-pattern-keys" value="perfetto_file_path"/> <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.pip/files"/> - <option name="directory-keys" value="/data/user/0/com.android.wm.shell.flicker.splitscreen/files"/> - <option name="directory-keys" - value="/data/user/0/com.android.wm.shell.flicker.service/files"/> <option name="collect-on-run-ended-only" value="true"/> <option name="clean-up" value="true"/> </metrics_collector> diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseBenchmarkTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseBenchmarkTest.kt index 0f3e0f5ef043..e9363f725fd8 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseBenchmarkTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseBenchmarkTest.kt @@ -38,7 +38,7 @@ constructor( * executions */ @FlickerBuilderProvider - fun buildFlicker(): FlickerBuilder { + open fun buildFlicker(): FlickerBuilder { return FlickerBuilder(instrumentation).apply { setup { flicker.scenario.setIsTablet(tapl.isTablet) } transition() diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt index c31b9e2c22c7..3244ebc9ef32 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt @@ -135,19 +135,29 @@ object SplitScreenUtils { // second task to split. val home = tapl.workspace.switchToOverview() ChangeDisplayOrientationRule.setRotation(rotation) - home.overviewActions.clickSplit() + val isGridOnlyOverviewEnabled = tapl.isGridOnlyOverviewEnabled + if (isGridOnlyOverviewEnabled) { + home.currentTask.tapMenu().tapSplitMenuItem() + } else { + home.overviewActions.clickSplit() + } val snapshots = device.wait(Until.findObjects(overviewSnapshotSelector), TIMEOUT_MS) if (snapshots == null || snapshots.size < 1) { error("Fail to find a overview snapshot to split.") } - // Find the second task in the upper right corner in split select mode by sorting - // 'left' in descending order and 'top' in ascending order. + // Find the second task in the upper (or bottom for grid only Overview) right corner in + // split select mode by sorting 'left' in descending order and 'top' in ascending (or + // descending for grid only Overview) order. snapshots.sortWith { t1: UiObject2, t2: UiObject2 -> t2.getVisibleBounds().left - t1.getVisibleBounds().left } snapshots.sortWith { t1: UiObject2, t2: UiObject2 -> - t1.getVisibleBounds().top - t2.getVisibleBounds().top + if (isGridOnlyOverviewEnabled) { + t2.getVisibleBounds().top - t1.getVisibleBounds().top + } else { + t1.getVisibleBounds().top - t2.getVisibleBounds().top + } } snapshots[0].click() } else { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java index 081c8ae91bdb..9c1a88e1caa0 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java @@ -16,6 +16,10 @@ package com.android.wm.shell; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; @@ -40,7 +44,6 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.app.ActivityManager.RunningTaskInfo; -import android.app.TaskInfo; import android.content.LocusId; import android.content.pm.ParceledListSlice; import android.os.Binder; @@ -356,7 +359,7 @@ public class ShellTaskOrganizerTests extends ShellTestCase { public void testOnSizeCompatActivityChanged() { final RunningTaskInfo taskInfo1 = createTaskInfo(12, WINDOWING_MODE_FULLSCREEN); taskInfo1.displayId = DEFAULT_DISPLAY; - taskInfo1.topActivityInSizeCompat = false; + taskInfo1.appCompatTaskInfo.topActivityInSizeCompat = false; final TrackingTaskListener taskListener = new TrackingTaskListener(); mOrganizer.addListenerForType(taskListener, TASK_LISTENER_TYPE_FULLSCREEN); mOrganizer.onTaskAppeared(taskInfo1, null); @@ -369,7 +372,7 @@ public class ShellTaskOrganizerTests extends ShellTestCase { final RunningTaskInfo taskInfo2 = createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); taskInfo2.displayId = taskInfo1.displayId; - taskInfo2.topActivityInSizeCompat = true; + taskInfo2.appCompatTaskInfo.topActivityInSizeCompat = true; taskInfo2.isVisible = true; mOrganizer.onTaskInfoChanged(taskInfo2); verify(mCompatUI).onCompatInfoChanged(taskInfo2, taskListener); @@ -379,7 +382,7 @@ public class ShellTaskOrganizerTests extends ShellTestCase { final RunningTaskInfo taskInfo3 = createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); taskInfo3.displayId = taskInfo1.displayId; - taskInfo3.topActivityInSizeCompat = true; + taskInfo3.appCompatTaskInfo.topActivityInSizeCompat = true; taskInfo3.isVisible = false; mOrganizer.onTaskInfoChanged(taskInfo3); verify(mCompatUI).onCompatInfoChanged(taskInfo3, null /* taskListener */); @@ -393,7 +396,7 @@ public class ShellTaskOrganizerTests extends ShellTestCase { public void testOnEligibleForLetterboxEducationActivityChanged() { final RunningTaskInfo taskInfo1 = createTaskInfo(12, WINDOWING_MODE_FULLSCREEN); taskInfo1.displayId = DEFAULT_DISPLAY; - taskInfo1.topActivityEligibleForLetterboxEducation = false; + taskInfo1.appCompatTaskInfo.topActivityEligibleForLetterboxEducation = false; final TrackingTaskListener taskListener = new TrackingTaskListener(); mOrganizer.addListenerForType(taskListener, TASK_LISTENER_TYPE_FULLSCREEN); mOrganizer.onTaskAppeared(taskInfo1, null); @@ -408,7 +411,7 @@ public class ShellTaskOrganizerTests extends ShellTestCase { final RunningTaskInfo taskInfo2 = createTaskInfo(taskInfo1.taskId, WINDOWING_MODE_FULLSCREEN); taskInfo2.displayId = taskInfo1.displayId; - taskInfo2.topActivityEligibleForLetterboxEducation = true; + taskInfo2.appCompatTaskInfo.topActivityEligibleForLetterboxEducation = true; taskInfo2.isVisible = true; mOrganizer.onTaskInfoChanged(taskInfo2); verify(mCompatUI).onCompatInfoChanged(taskInfo2, taskListener); @@ -418,7 +421,7 @@ public class ShellTaskOrganizerTests extends ShellTestCase { final RunningTaskInfo taskInfo3 = createTaskInfo(taskInfo1.taskId, WINDOWING_MODE_FULLSCREEN); taskInfo3.displayId = taskInfo1.displayId; - taskInfo3.topActivityEligibleForLetterboxEducation = true; + taskInfo3.appCompatTaskInfo.topActivityEligibleForLetterboxEducation = true; taskInfo3.isVisible = false; mOrganizer.onTaskInfoChanged(taskInfo3); verify(mCompatUI).onCompatInfoChanged(taskInfo3, null /* taskListener */); @@ -432,7 +435,7 @@ public class ShellTaskOrganizerTests extends ShellTestCase { public void testOnCameraCompatActivityChanged() { final RunningTaskInfo taskInfo1 = createTaskInfo(1, WINDOWING_MODE_FULLSCREEN); taskInfo1.displayId = DEFAULT_DISPLAY; - taskInfo1.cameraCompatControlState = TaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; + taskInfo1.appCompatTaskInfo.cameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; final TrackingTaskListener taskListener = new TrackingTaskListener(); mOrganizer.addListenerForType(taskListener, TASK_LISTENER_TYPE_FULLSCREEN); mOrganizer.onTaskAppeared(taskInfo1, null); @@ -446,7 +449,8 @@ public class ShellTaskOrganizerTests extends ShellTestCase { final RunningTaskInfo taskInfo2 = createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); taskInfo2.displayId = taskInfo1.displayId; - taskInfo2.cameraCompatControlState = TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; + taskInfo2.appCompatTaskInfo.cameraCompatControlState = + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; taskInfo2.isVisible = true; mOrganizer.onTaskInfoChanged(taskInfo2); verify(mCompatUI).onCompatInfoChanged(taskInfo2, taskListener); @@ -457,7 +461,8 @@ public class ShellTaskOrganizerTests extends ShellTestCase { final RunningTaskInfo taskInfo3 = createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); taskInfo3.displayId = taskInfo1.displayId; - taskInfo3.cameraCompatControlState = TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; + taskInfo3.appCompatTaskInfo.cameraCompatControlState = + CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; taskInfo3.isVisible = true; mOrganizer.onTaskInfoChanged(taskInfo3); verify(mCompatUI).onCompatInfoChanged(taskInfo3, taskListener); @@ -468,8 +473,9 @@ public class ShellTaskOrganizerTests extends ShellTestCase { final RunningTaskInfo taskInfo4 = createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); taskInfo4.displayId = taskInfo1.displayId; - taskInfo4.topActivityInSizeCompat = true; - taskInfo4.cameraCompatControlState = TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; + taskInfo4.appCompatTaskInfo.topActivityInSizeCompat = true; + taskInfo4.appCompatTaskInfo.cameraCompatControlState = + CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; taskInfo4.isVisible = true; mOrganizer.onTaskInfoChanged(taskInfo4); verify(mCompatUI).onCompatInfoChanged(taskInfo4, taskListener); @@ -479,7 +485,8 @@ public class ShellTaskOrganizerTests extends ShellTestCase { final RunningTaskInfo taskInfo5 = createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); taskInfo5.displayId = taskInfo1.displayId; - taskInfo5.cameraCompatControlState = TaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; + taskInfo5.appCompatTaskInfo.cameraCompatControlState = + CAMERA_COMPAT_CONTROL_DISMISSED; taskInfo5.isVisible = true; mOrganizer.onTaskInfoChanged(taskInfo5); verify(mCompatUI).onCompatInfoChanged(taskInfo5, null /* taskListener */); @@ -489,7 +496,8 @@ public class ShellTaskOrganizerTests extends ShellTestCase { final RunningTaskInfo taskInfo6 = createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); taskInfo6.displayId = taskInfo1.displayId; - taskInfo6.cameraCompatControlState = TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; + taskInfo6.appCompatTaskInfo.cameraCompatControlState = + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; taskInfo6.isVisible = false; mOrganizer.onTaskInfoChanged(taskInfo6); verify(mCompatUI).onCompatInfoChanged(taskInfo6, null /* taskListener */); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java index 6cf5450db9ea..a67fd377db93 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java @@ -132,8 +132,9 @@ public class BackAnimationControllerTest extends ShellTestCase { new ShellBackAnimationRegistry( new CrossActivityAnimation(mContext, mAnimationBackground), new CrossTaskBackAnimation(mContext, mAnimationBackground), + /* dialogCloseAnimation= */ null, new CustomizeActivityAnimation(mContext, mAnimationBackground), - null); + /* defaultBackToHomeAnimation= */ null); mController = new BackAnimationController( mShellInit, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java index f85d707d55f9..fef81af8946b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java @@ -16,8 +16,8 @@ package com.android.wm.shell.compatui; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; import static android.view.WindowInsets.Type.navigationBars; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -34,8 +34,8 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.app.ActivityManager.RunningTaskInfo; +import android.app.AppCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; -import android.app.TaskInfo.CameraCompatControlState; import android.content.Context; import android.content.res.Configuration; import android.testing.AndroidTestingRunner; @@ -688,8 +688,8 @@ public class CompatUIControllerTest extends ShellTestCase { RunningTaskInfo taskInfo = new RunningTaskInfo(); taskInfo.taskId = taskId; taskInfo.displayId = displayId; - taskInfo.topActivityInSizeCompat = hasSizeCompat; - taskInfo.cameraCompatControlState = cameraCompatControlState; + taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat; + taskInfo.appCompatTaskInfo.cameraCompatControlState = cameraCompatControlState; taskInfo.isVisible = isVisible; taskInfo.isFocused = isFocused; taskInfo.isTopActivityTransparent = isTopActivityTransparent; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java index 3bce2b824e28..23a4e3956289 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java @@ -16,10 +16,10 @@ package com.android.wm.shell.compatui; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -28,8 +28,8 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import android.app.ActivityManager; +import android.app.AppCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; -import android.app.TaskInfo.CameraCompatControlState; import android.testing.AndroidTestingRunner; import android.util.Pair; import android.view.LayoutInflater; @@ -219,8 +219,8 @@ public class CompatUILayoutTest extends ShellTestCase { @CameraCompatControlState int cameraCompatControlState) { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = TASK_ID; - taskInfo.topActivityInSizeCompat = hasSizeCompat; - taskInfo.cameraCompatControlState = cameraCompatControlState; + taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat; + taskInfo.appCompatTaskInfo.cameraCompatControlState = cameraCompatControlState; return taskInfo; } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java index 4c837e635939..d4b97ed55192 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java @@ -16,10 +16,10 @@ package com.android.wm.shell.compatui; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; import static android.view.WindowInsets.Type.navigationBars; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -35,6 +35,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.app.ActivityManager; +import android.app.AppCompatTaskInfo; import android.app.TaskInfo; import android.content.res.Configuration; import android.graphics.Rect; @@ -464,11 +465,11 @@ public class CompatUIWindowManagerTest extends ShellTestCase { } private static TaskInfo createTaskInfo(boolean hasSizeCompat, - @TaskInfo.CameraCompatControlState int cameraCompatControlState) { + @AppCompatTaskInfo.CameraCompatControlState int cameraCompatControlState) { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = TASK_ID; - taskInfo.topActivityInSizeCompat = hasSizeCompat; - taskInfo.cameraCompatControlState = cameraCompatControlState; + taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat; + taskInfo.appCompatTaskInfo.cameraCompatControlState = cameraCompatControlState; taskInfo.configuration.uiMode &= ~Configuration.UI_MODE_TYPE_DESK; return taskInfo; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/LetterboxEduWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/LetterboxEduWindowManagerTest.java index 9200b3c90f0d..a60a1cbb435f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/LetterboxEduWindowManagerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/LetterboxEduWindowManagerTest.java @@ -477,7 +477,7 @@ public class LetterboxEduWindowManagerTest extends ShellTestCase { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.userId = userId; taskInfo.taskId = TASK_ID; - taskInfo.topActivityEligibleForLetterboxEducation = eligible; + taskInfo.appCompatTaskInfo.topActivityEligibleForLetterboxEducation = eligible; taskInfo.configuration.windowConfiguration.setBounds(bounds); return taskInfo; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java index f460d1b09e34..38d6ea1839c4 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java @@ -16,7 +16,7 @@ package com.android.wm.shell.compatui; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; +import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -25,8 +25,8 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import android.app.ActivityManager; +import android.app.AppCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; -import android.app.TaskInfo.CameraCompatControlState; import android.content.ComponentName; import android.testing.AndroidTestingRunner; import android.util.Pair; @@ -147,8 +147,8 @@ public class UserAspectRatioSettingsLayoutTest extends ShellTestCase { @CameraCompatControlState int cameraCompatControlState) { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = TASK_ID; - taskInfo.topActivityInSizeCompat = hasSizeCompat; - taskInfo.cameraCompatControlState = cameraCompatControlState; + taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat; + taskInfo.appCompatTaskInfo.cameraCompatControlState = cameraCompatControlState; taskInfo.realActivity = new ComponentName("com.mypackage.test", "TestActivity"); return taskInfo; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManagerTest.java index 5a4d6c812c17..065293960da7 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManagerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManagerTest.java @@ -381,8 +381,9 @@ public class UserAspectRatioSettingsWindowManagerTest extends ShellTestCase { boolean topActivityBoundsLetterboxed) { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = TASK_ID; - taskInfo.topActivityEligibleForUserAspectRatioButton = eligibleForUserAspectRatioButton; - taskInfo.topActivityBoundsLetterboxed = topActivityBoundsLetterboxed; + taskInfo.appCompatTaskInfo.topActivityEligibleForUserAspectRatioButton = + eligibleForUserAspectRatioButton; + taskInfo.appCompatTaskInfo.topActivityBoundsLetterboxed = topActivityBoundsLetterboxed; taskInfo.configuration.uiMode &= ~Configuration.UI_MODE_TYPE_DESK; taskInfo.realActivity = new ComponentName("com.mypackage.test", "TestActivity"); return taskInfo; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java index cc4db22e772c..fff65f364121 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java @@ -74,6 +74,7 @@ import com.android.wm.shell.common.split.SplitLayout; import com.android.wm.shell.splitscreen.SplitScreen.SplitScreenListener; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.transition.HomeTransitionObserver; import com.android.wm.shell.transition.Transitions; import org.junit.Before; @@ -373,7 +374,7 @@ public class StageCoordinatorTests extends ShellTestCase { ShellInit shellInit = new ShellInit(mMainExecutor); final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class), mTaskOrganizer, mTransactionPool, mock(DisplayController.class), mMainExecutor, - mMainHandler, mAnimExecutor); + mMainHandler, mAnimExecutor, mock(HomeTransitionObserver.class)); shellInit.init(); return t; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java index a9082a6e2585..012c40811811 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java @@ -80,6 +80,7 @@ public class StartingWindowControllerTests extends ShellTestCase { MockitoAnnotations.initMocks(this); doReturn(mock(Display.class)).when(mDisplayManager).getDisplay(anyInt()); doReturn(mDisplayManager).when(mContext).getSystemService(eq(DisplayManager.class)); + doReturn(super.mContext.getResources()).when(mContext).getResources(); mShellInit = spy(new ShellInit(mMainExecutor)); mShellController = spy(new ShellController(mContext, mShellInit, mShellCommandHandler, mMainExecutor)); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java index 7a8a2a93e0e1..ea7c0d9c264e 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java @@ -75,24 +75,24 @@ public class HomeTransitionObserverTest extends ShellTestCase { private final Handler mMainHandler = new Handler(Looper.getMainLooper()); private final DisplayController mDisplayController = mock(DisplayController.class); + private IHomeTransitionListener mListener; private Transitions mTransition; + private HomeTransitionObserver mHomeTransitionObserver; @Before public void setUp() { + mListener = mock(IHomeTransitionListener.class); + when(mListener.asBinder()).thenReturn(mock(IBinder.class)); + + mHomeTransitionObserver = new HomeTransitionObserver(mContext, mMainExecutor); mTransition = new Transitions(mContext, mock(ShellInit.class), mock(ShellController.class), mOrganizer, mTransactionPool, mDisplayController, mMainExecutor, - mMainHandler, mAnimExecutor); + mMainHandler, mAnimExecutor, mHomeTransitionObserver); + mHomeTransitionObserver.setHomeTransitionListener(mTransition, mListener); } @Test public void testHomeActivityWithOpenModeNotifiesHomeIsVisible() throws RemoteException { - IHomeTransitionListener listener = mock(IHomeTransitionListener.class); - when(listener.asBinder()).thenReturn(mock(IBinder.class)); - - HomeTransitionObserver observer = new HomeTransitionObserver(mContext, mMainExecutor, - mTransition); - observer.setHomeTransitionListener(listener); - TransitionInfo info = mock(TransitionInfo.class); TransitionInfo.Change change = mock(TransitionInfo.Change.class); ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class); @@ -101,23 +101,16 @@ public class HomeTransitionObserverTest extends ShellTestCase { setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_OPEN); - observer.onTransitionReady(mock(IBinder.class), + mHomeTransitionObserver.onTransitionReady(mock(IBinder.class), info, mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class)); - verify(listener, times(1)).onHomeVisibilityChanged(true); + verify(mListener, times(1)).onHomeVisibilityChanged(true); } @Test public void testHomeActivityWithCloseModeNotifiesHomeIsNotVisible() throws RemoteException { - IHomeTransitionListener listener = mock(IHomeTransitionListener.class); - when(listener.asBinder()).thenReturn(mock(IBinder.class)); - - HomeTransitionObserver observer = new HomeTransitionObserver(mContext, mMainExecutor, - mTransition); - observer.setHomeTransitionListener(listener); - TransitionInfo info = mock(TransitionInfo.class); TransitionInfo.Change change = mock(TransitionInfo.Change.class); ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class); @@ -126,38 +119,30 @@ public class HomeTransitionObserverTest extends ShellTestCase { setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_TO_BACK); - observer.onTransitionReady(mock(IBinder.class), + mHomeTransitionObserver.onTransitionReady(mock(IBinder.class), info, mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class)); - verify(listener, times(1)).onHomeVisibilityChanged(false); + verify(mListener, times(1)).onHomeVisibilityChanged(false); } @Test public void testNonHomeActivityDoesNotTriggerCallback() throws RemoteException { - IHomeTransitionListener listener = mock(IHomeTransitionListener.class); - when(listener.asBinder()).thenReturn(mock(IBinder.class)); - - HomeTransitionObserver observer = new HomeTransitionObserver(mContext, mMainExecutor, - mTransition); - observer.setHomeTransitionListener(listener); - TransitionInfo info = mock(TransitionInfo.class); TransitionInfo.Change change = mock(TransitionInfo.Change.class); ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class); when(change.getTaskInfo()).thenReturn(taskInfo); when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change))); - setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_UNDEFINED, TRANSIT_TO_BACK); - observer.onTransitionReady(mock(IBinder.class), + mHomeTransitionObserver.onTransitionReady(mock(IBinder.class), info, mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class)); - verify(listener, times(0)).onHomeVisibilityChanged(anyBoolean()); + verify(mListener, times(0)).onHomeVisibilityChanged(anyBoolean()); } /** diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java index da83d4c0a122..4e300d9a7e69 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java @@ -146,7 +146,7 @@ public class ShellTransitionTests extends ShellTestCase { ShellInit shellInit = mock(ShellInit.class); final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class), mOrganizer, mTransactionPool, createTestDisplayController(), mMainExecutor, - mMainHandler, mAnimExecutor); + mMainHandler, mAnimExecutor, mock(HomeTransitionObserver.class)); // One from Transitions, one from RootTaskDisplayAreaOrganizer verify(shellInit).addInitCallback(any(), eq(t)); verify(shellInit).addInitCallback(any(), isA(RootTaskDisplayAreaOrganizer.class)); @@ -158,7 +158,7 @@ public class ShellTransitionTests extends ShellTestCase { ShellController shellController = mock(ShellController.class); final Transitions t = new Transitions(mContext, shellInit, shellController, mOrganizer, mTransactionPool, createTestDisplayController(), mMainExecutor, - mMainHandler, mAnimExecutor); + mMainHandler, mAnimExecutor, mock(HomeTransitionObserver.class)); shellInit.init(); verify(shellController, times(1)).addExternalInterface( eq(ShellSharedConstants.KEY_EXTRA_SHELL_SHELL_TRANSITIONS), any(), any()); @@ -1075,10 +1075,10 @@ public class ShellTransitionTests extends ShellTestCase { final Transitions transitions = new Transitions(mContext, shellInit, mock(ShellController.class), mOrganizer, mTransactionPool, createTestDisplayController(), mMainExecutor, - mMainHandler, mAnimExecutor); + mMainHandler, mAnimExecutor, mock(HomeTransitionObserver.class)); final RecentsTransitionHandler recentsHandler = new RecentsTransitionHandler(shellInit, transitions, - mock(RecentTasksController.class)); + mock(RecentTasksController.class), mock(HomeTransitionObserver.class)); transitions.replaceDefaultHandlerForTest(mDefaultHandler); shellInit.init(); @@ -1623,7 +1623,7 @@ public class ShellTransitionTests extends ShellTestCase { ShellInit shellInit = new ShellInit(mMainExecutor); final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class), mOrganizer, mTransactionPool, createTestDisplayController(), mMainExecutor, - mMainHandler, mAnimExecutor); + mMainHandler, mAnimExecutor, mock(HomeTransitionObserver.class)); shellInit.init(); return t; } diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h index ef4dce57bf46..caffdfc907f7 100644 --- a/libs/hwui/hwui/Paint.h +++ b/libs/hwui/hwui/Paint.h @@ -17,18 +17,18 @@ #ifndef ANDROID_GRAPHICS_PAINT_H_ #define ANDROID_GRAPHICS_PAINT_H_ +#include "Typeface.h" + +#include <cutils/compiler.h> + #include <SkFont.h> #include <SkPaint.h> #include <SkSamplingOptions.h> -#include <cutils/compiler.h> -#include <minikin/FamilyVariant.h> -#include <minikin/FontFamily.h> -#include <minikin/FontFeature.h> -#include <minikin/Hyphenator.h> - #include <string> -#include "Typeface.h" +#include <minikin/FontFamily.h> +#include <minikin/FamilyVariant.h> +#include <minikin/Hyphenator.h> namespace android { @@ -82,15 +82,11 @@ public: float getWordSpacing() const { return mWordSpacing; } - void setFontFeatureSettings(std::string_view fontFeatures) { - mFontFeatureSettings = minikin::FontFeature::parse(fontFeatures); + void setFontFeatureSettings(const std::string& fontFeatureSettings) { + mFontFeatureSettings = fontFeatureSettings; } - void resetFontFeatures() { mFontFeatureSettings.clear(); } - - const std::vector<minikin::FontFeature>& getFontFeatureSettings() const { - return mFontFeatureSettings; - } + std::string getFontFeatureSettings() const { return mFontFeatureSettings; } void setMinikinLocaleListId(uint32_t minikinLocaleListId) { mMinikinLocaleListId = minikinLocaleListId; @@ -174,7 +170,7 @@ private: float mLetterSpacing = 0; float mWordSpacing = 0; - std::vector<minikin::FontFeature> mFontFeatureSettings; + std::string mFontFeatureSettings; uint32_t mMinikinLocaleListId; std::optional<minikin::FamilyVariant> mFamilyVariant; uint32_t mHyphenEdit = 0; diff --git a/libs/hwui/jni/Paint.cpp b/libs/hwui/jni/Paint.cpp index d84b73d1a1ca..8c71d6fc7860 100644 --- a/libs/hwui/jni/Paint.cpp +++ b/libs/hwui/jni/Paint.cpp @@ -33,7 +33,6 @@ #include <cassert> #include <cstring> #include <memory> -#include <string_view> #include <vector> #include "ColorFilter.h" @@ -691,11 +690,10 @@ namespace PaintGlue { jstring settings) { Paint* paint = reinterpret_cast<Paint*>(paintHandle); if (!settings) { - paint->resetFontFeatures(); + paint->setFontFeatureSettings(std::string()); } else { ScopedUtfChars settingsChars(env, settings); - paint->setFontFeatureSettings( - std::string_view(settingsChars.c_str(), settingsChars.size())); + paint->setFontFeatureSettings(std::string(settingsChars.c_str(), settingsChars.size())); } } diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index abd928486607..576ebc1579ef 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -24,6 +24,7 @@ #include <SkColor.h> #include <android-base/stringprintf.h> #include <android-base/thread_annotations.h> +#include <com_android_input_flags.h> #include <ftl/enum.h> #include <mutex> @@ -34,6 +35,8 @@ #define INDENT2 " " #define INDENT3 " " +namespace input_flags = com::android::input::flags; + namespace android { namespace { @@ -63,10 +66,20 @@ void PointerController::DisplayInfoListener::onPointerControllerDestroyed() { std::shared_ptr<PointerController> PointerController::create( const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper, - SpriteController& spriteController, bool enabled) { + SpriteController& spriteController, bool enabled, ControllerType type) { // using 'new' to access non-public constructor - std::shared_ptr<PointerController> controller = std::shared_ptr<PointerController>( - new PointerController(policy, looper, spriteController, enabled)); + std::shared_ptr<PointerController> controller; + switch (type) { + case ControllerType::MOUSE: + controller = std::shared_ptr<PointerController>( + new MousePointerController(policy, looper, spriteController, enabled)); + break; + case ControllerType::LEGACY: + default: + controller = std::shared_ptr<PointerController>( + new PointerController(policy, looper, spriteController, enabled)); + break; + } /* * Now we need to hook up the constructed PointerController object to its callbacks. @@ -375,4 +388,13 @@ std::string PointerController::dump() { return dump; } +// --- MousePointerController --- + +MousePointerController::MousePointerController(const sp<PointerControllerPolicyInterface>& policy, + const sp<Looper>& looper, + SpriteController& spriteController, bool enabled) + : PointerController(policy, looper, spriteController, enabled) { + PointerController::setPresentation(Presentation::POINTER); +} + } // namespace android diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index aa7ca3c52ecf..08e19a096d87 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -47,7 +47,8 @@ class PointerController : public PointerControllerInterface { public: static std::shared_ptr<PointerController> create( const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper, - SpriteController& spriteController, bool enabled); + SpriteController& spriteController, bool enabled, + ControllerType type = ControllerType::LEGACY); ~PointerController() override; @@ -75,7 +76,7 @@ public: void onDisplayInfosChangedLocked(const std::vector<gui::DisplayInfo>& displayInfos) REQUIRES(getLock()); - std::string dump(); + std::string dump() override; protected: using WindowListenerConsumer = @@ -87,10 +88,10 @@ protected: WindowListenerConsumer registerListener, WindowListenerConsumer unregisterListener); -private: PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper, SpriteController& spriteController, bool enabled); +private: friend PointerControllerContext::LooperCallback; friend PointerControllerContext::MessageHandler; @@ -135,6 +136,24 @@ private: void clearSpotsLocked() REQUIRES(getLock()); }; +class MousePointerController : public PointerController { +public: + /** A version of PointerController that controls one mouse pointer. */ + MousePointerController(const sp<PointerControllerPolicyInterface>& policy, + const sp<Looper>& looper, SpriteController& spriteController, + bool enabled); + + void setPresentation(Presentation) override { + LOG_ALWAYS_FATAL("Should not be called"); + } + void setSpots(const PointerCoords*, const uint32_t*, BitSet32, int32_t) override { + LOG_ALWAYS_FATAL("Should not be called"); + } + void clearSpots() override { + LOG_ALWAYS_FATAL("Should not be called"); + } +}; + } // namespace android #endif // _UI_POINTER_CONTROLLER_H |