From 91d99268048b657e1dfabed4f1dd3d484d606592 Mon Sep 17 00:00:00 2001 From: Luca Zuccarini Date: Wed, 23 Nov 2022 16:09:46 +0000 Subject: [PATCH 1/5] Add CUJs for closing All Apps. CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME is meant to be the CUJ for closing All Apps through the home gesture/home button, which has different animations from closing apps in the same way. By contrast, CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE is the finger-tracking transition that dismisses All Apps by swiping down. Bug: 260218332 Test: recorded prefetto trace while closing All Apps, see bug Change-Id: Ie0403471d61eea9dd251fe214ce7bd8f78f3bfdc --- .../internal/jank/InteractionJankMonitor.java | 14 +++++++++++++- .../system/InteractionJankMonitorWrapper.java | 9 ++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java index 39b9e217fce70..d8afe50d3af3f 100644 --- a/core/java/com/android/internal/jank/InteractionJankMonitor.java +++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java @@ -28,6 +28,8 @@ import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_IN import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_RECENTS; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_WIDGET; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_SWIPE_TO_RECENTS; +import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE; +import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNLOCK_ENTRANCE_ANIMATION; @@ -227,6 +229,8 @@ public class InteractionJankMonitor { public static final int CUJ_LOCKSCREEN_OCCLUSION = 64; public static final int CUJ_RECENTS_SCROLLING = 65; public static final int CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS = 66; + public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE = 67; + public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME = 68; private static final int NO_STATSD_LOGGING = -1; @@ -302,6 +306,8 @@ public class InteractionJankMonitor { UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_OCCLUSION, UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__RECENTS_SCROLLING, UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_SWIPE_TO_RECENTS, + UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE, + UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME, }; private static volatile InteractionJankMonitor sInstance; @@ -388,7 +394,9 @@ public class InteractionJankMonitor { CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION, CUJ_LOCKSCREEN_OCCLUSION, CUJ_RECENTS_SCROLLING, - CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS + CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS, + CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE, + CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME }) @Retention(RetentionPolicy.SOURCE) public @interface CujType { @@ -905,6 +913,10 @@ public class InteractionJankMonitor { return "RECENTS_SCROLLING"; case CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS: return "LAUNCHER_APP_SWIPE_TO_RECENTS"; + case CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE: + return "LAUNCHER_CLOSE_ALL_APPS_SWIPE"; + case CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME: + return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME"; } return "UNKNOWN"; } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java index 82d70116bbffb..e08a604338d2c 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java @@ -43,6 +43,10 @@ public final class InteractionJankMonitorWrapper { InteractionJankMonitor.CUJ_LAUNCHER_QUICK_SWITCH; public static final int CUJ_OPEN_ALL_APPS = InteractionJankMonitor.CUJ_LAUNCHER_OPEN_ALL_APPS; + public static final int CUJ_CLOSE_ALL_APPS_SWIPE = + InteractionJankMonitor.CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE; + public static final int CUJ_CLOSE_ALL_APPS_TO_HOME = + InteractionJankMonitor.CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME; public static final int CUJ_ALL_APPS_SCROLL = InteractionJankMonitor.CUJ_LAUNCHER_ALL_APPS_SCROLL; public static final int CUJ_APP_LAUNCH_FROM_WIDGET = @@ -65,7 +69,10 @@ public final class InteractionJankMonitorWrapper { CUJ_APP_LAUNCH_FROM_WIDGET, CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION, CUJ_RECENTS_SCROLLING, - CUJ_APP_SWIPE_TO_RECENTS + CUJ_APP_SWIPE_TO_RECENTS, + CUJ_OPEN_ALL_APPS, + CUJ_CLOSE_ALL_APPS_SWIPE, + CUJ_CLOSE_ALL_APPS_TO_HOME }) @Retention(RetentionPolicy.SOURCE) public @interface CujType { From 7d26b6795394907458d4f6e561fcaed6c92a0ad5 Mon Sep 17 00:00:00 2001 From: Andrey Epin Date: Tue, 6 Dec 2022 20:44:14 -0800 Subject: [PATCH 2/5] Chooser custom actions API. A proposal for the new API for custom Chooser actions. A new extra flags for Intent, EXTRA_CHOOSER_CUSTOM_ACTIONS and EXTRA_CHOOSER_PAYLOAD_RESELECTION_ACTION. EXTRA_CHOOSER_CUSTOM_ACTIONS can be used with intent action ACTION_CHOOSER to provide a collection of application custom that would be present to the user in the sharesheet. ChooserAction class is a new data for carrying app-specified actions. EXTRA_CHOOSER_PAYLOAD_RESELECTION_ACTION extra flag for content reselection custom action. Bug: 258838272 Test: smoke build test, the API is not used at the moment. Change-Id: Id6748c01ad84cc8ec4a1bc7010e2b82812def9ad --- core/java/android/content/Intent.java | 20 +++ .../service/chooser/ChooserAction.java | 144 ++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 core/java/android/service/chooser/ChooserAction.java diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 5ca8b0535dced..2ea0d82355484 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -65,6 +65,7 @@ import android.provider.DocumentsContract; import android.provider.DocumentsProvider; import android.provider.MediaStore; import android.provider.OpenableColumns; +import android.service.chooser.ChooserAction; import android.telecom.PhoneAccount; import android.telecom.TelecomManager; import android.text.TextUtils; @@ -5730,6 +5731,25 @@ public class Intent implements Parcelable, Cloneable { public static final String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER"; + /** + * A Parcelable[] of {@link ChooserAction} objects to provide the Android Sharesheet with + * app-specific actions to be presented to the user when invoking {@link #ACTION_CHOOSER}. + * @hide + */ + public static final String EXTRA_CHOOSER_CUSTOM_ACTIONS = + "android.intent.extra.EXTRA_CHOOSER_CUSTOM_ACTIONS"; + + /** + * Optional argument to be used with {@link #ACTION_CHOOSER}. + * A {@link android.app.PendingIntent} to be sent when the user wants to do payload reselection + * in the sharesheet. + * A reselection action allows the user to return to the source app to change the content being + * shared. + * @hide + */ + public static final String EXTRA_CHOOSER_PAYLOAD_RESELECTION_ACTION = + "android.intent.extra.EXTRA_CHOOSER_PAYLOAD_RESELECTION_ACTION"; + /** * An {@code ArrayList} of {@code String} annotations describing content for * {@link #ACTION_CHOOSER}. diff --git a/core/java/android/service/chooser/ChooserAction.java b/core/java/android/service/chooser/ChooserAction.java new file mode 100644 index 0000000000000..3010049633d41 --- /dev/null +++ b/core/java/android/service/chooser/ChooserAction.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2022 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 android.service.chooser; + +import android.annotation.NonNull; +import android.app.PendingIntent; +import android.graphics.drawable.Icon; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import java.util.Objects; + +/** + * A ChooserAction is an app-defined action that can be provided to the Android Sharesheet to + * be shown to the user when {@link android.content.Intent.ACTION_CHOOSER} is invoked. + * + * @see android.content.Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS + * @see android.content.Intent.EXTRA_CHOOSER_PAYLOAD_RESELECTION_ACTION + * @hide + */ +public final class ChooserAction implements Parcelable { + private final Icon mIcon; + private final CharSequence mLabel; + private final PendingIntent mAction; + + private ChooserAction( + Icon icon, + CharSequence label, + PendingIntent action) { + mIcon = icon; + mLabel = label; + mAction = action; + } + + /** + * Return a user-readable label for this action. + */ + @NonNull + public CharSequence getLabel() { + return mLabel; + } + + /** + * Return an {@link Icon} representing this action. + */ + @NonNull + public Icon getIcon() { + return mIcon; + } + + /** + * Return the action intent. + */ + @NonNull + public PendingIntent getAction() { + return mAction; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + mIcon.writeToParcel(dest, flags); + TextUtils.writeToParcel(mLabel, dest, flags); + mAction.writeToParcel(dest, flags); + } + + @Override + public String toString() { + return "ChooserAction {" + "label=" + mLabel + ", intent=" + mAction + "}"; + } + + public static final Parcelable.Creator CREATOR = + new Creator() { + @Override + public ChooserAction createFromParcel(Parcel source) { + return new ChooserAction( + Icon.CREATOR.createFromParcel(source), + TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source), + PendingIntent.CREATOR.createFromParcel(source)); + } + + @Override + public ChooserAction[] newArray(int size) { + return new ChooserAction[size]; + } + }; + + /** + * Builder class for {@link ChooserAction} objects + */ + public static final class Builder { + private final Icon mIcon; + private final CharSequence mLabel; + private final PendingIntent mAction; + + /** + * Construct a new builder for {@link ChooserAction} object. + * + * @param icon an {@link Icon} representing this action, consisting of a white foreground + * atop a transparent background. + * @param label label the user-readable label for this action. + * @param action {@link PendingIntent} to be invoked when the action is selected. + */ + public Builder( + @NonNull Icon icon, + @NonNull CharSequence label, + @NonNull PendingIntent action) { + Objects.requireNonNull(icon, "icon can not be null"); + Objects.requireNonNull(label, "label can not be null"); + Objects.requireNonNull(action, "pending intent can not be null"); + mIcon = icon; + mLabel = label; + mAction = action; + } + + /** + * Combine all of the options that have been set and return a new {@link ChooserAction} + * object. + * @return the built action + */ + public ChooserAction build() { + return new ChooserAction(mIcon, mLabel, mAction); + } + } +} From 209156b953e5e3533b7902b0afb7f8b8da8ec03e Mon Sep 17 00:00:00 2001 From: Caitlin Shkuratov Date: Thu, 22 Dec 2022 20:52:28 +0000 Subject: [PATCH 3/5] [Media TTT] Tweak the coloring and sizing of the receiver icon. Fixes: 263478641 Test: manual -- see screenshots in bug Change-Id: I135fae722cb981888a8aa61cec07a6cb4caedaae --- .../res/drawable/media_ttt_chip_background_receiver.xml | 6 +++--- packages/SystemUI/res/values/dimens.xml | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/res/drawable/media_ttt_chip_background_receiver.xml b/packages/SystemUI/res/drawable/media_ttt_chip_background_receiver.xml index 708bc1ac7e8a7..8aae276789d68 100644 --- a/packages/SystemUI/res/drawable/media_ttt_chip_background_receiver.xml +++ b/packages/SystemUI/res/drawable/media_ttt_chip_background_receiver.xml @@ -19,8 +19,8 @@ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:shape="oval"> - + diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 584823746662c..ecb6560914785 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1073,11 +1073,12 @@ 12dp - 100dp - 95dp + 112dp - 12dp - 20dp + + 36dp + 40dp 35dp From 492e3399d252113aa24f26e8164f536e08759cd7 Mon Sep 17 00:00:00 2001 From: Merissa Mitchell Date: Wed, 21 Dec 2022 12:00:48 -0800 Subject: [PATCH 4/5] Rename WindowDecor classes for Desktop Mode. Bug: 260276028 Test: atest DesktopModeWindowDecorViewModelTests Change-Id: I5c6fbf8efd7d00a7f0fd6bb0d1339d31a66d53b7 --- .../wm/shell/dagger/WMShellModule.java | 4 +- ...a => DesktopModeWindowDecorViewModel.java} | 53 ++++++++--------- ....java => DesktopModeWindowDecoration.java} | 12 ++-- ...DesktopModeWindowDecorViewModelTests.java} | 58 ++++++++++--------- 4 files changed, 67 insertions(+), 60 deletions(-) rename libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/{CaptionWindowDecorViewModel.java => DesktopModeWindowDecorViewModel.java} (92%) rename libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/{CaptionWindowDecoration.java => DesktopModeWindowDecoration.java} (98%) rename libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/{CaptionWindowDecorViewModelTests.java => DesktopModeWindowDecorViewModelTests.java} (81%) 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 701a3a42fadd3..d3b9fa5e628d6 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 @@ -93,7 +93,7 @@ import com.android.wm.shell.unfold.animation.SplitTaskUnfoldAnimator; import com.android.wm.shell.unfold.animation.UnfoldTaskAnimator; import com.android.wm.shell.unfold.qualifier.UnfoldShellTransition; import com.android.wm.shell.unfold.qualifier.UnfoldTransition; -import com.android.wm.shell.windowdecor.CaptionWindowDecorViewModel; +import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel; import com.android.wm.shell.windowdecor.WindowDecorViewModel; import java.util.ArrayList; @@ -192,7 +192,7 @@ public abstract class WMShellModule { SyncTransactionQueue syncQueue, Optional desktopModeController, Optional desktopTasksController) { - return new CaptionWindowDecorViewModel( + return new DesktopModeWindowDecorViewModel( context, mainHandler, mainChoreographer, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java similarity index 92% rename from libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java rename to libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index 299284f5bda6e..b500f5fb01550 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -61,12 +61,12 @@ import java.util.Optional; /** * View model for the window decoration with a caption and shadows. Works with - * {@link CaptionWindowDecoration}. + * {@link DesktopModeWindowDecoration}. */ -public class CaptionWindowDecorViewModel implements WindowDecorViewModel { - private static final String TAG = "CaptionViewModel"; - private final CaptionWindowDecoration.Factory mCaptionWindowDecorFactory; +public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { + private static final String TAG = "DesktopModeWindowDecorViewModel"; + private final DesktopModeWindowDecoration.Factory mDesktopModeWindowDecorFactory; private final ActivityTaskManager mActivityTaskManager; private final ShellTaskOrganizer mTaskOrganizer; private final Context mContext; @@ -81,11 +81,12 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { private SparseArray mEventReceiversByDisplay = new SparseArray<>(); - private final SparseArray mWindowDecorByTaskId = new SparseArray<>(); + private final SparseArray mWindowDecorByTaskId = + new SparseArray<>(); private final DragStartListenerImpl mDragStartListener = new DragStartListenerImpl(); private InputMonitorFactory mInputMonitorFactory; - public CaptionWindowDecorViewModel( + public DesktopModeWindowDecorViewModel( Context context, Handler mainHandler, Choreographer mainChoreographer, @@ -103,12 +104,12 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { syncQueue, desktopModeController, desktopTasksController, - new CaptionWindowDecoration.Factory(), + new DesktopModeWindowDecoration.Factory(), new InputMonitorFactory()); } @VisibleForTesting - CaptionWindowDecorViewModel( + DesktopModeWindowDecorViewModel( Context context, Handler mainHandler, Choreographer mainChoreographer, @@ -117,7 +118,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { SyncTransactionQueue syncQueue, Optional desktopModeController, Optional desktopTasksController, - CaptionWindowDecoration.Factory captionWindowDecorFactory, + DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory, InputMonitorFactory inputMonitorFactory) { mContext = context; mMainHandler = mainHandler; @@ -129,7 +130,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { mDesktopModeController = desktopModeController; mDesktopTasksController = desktopTasksController; - mCaptionWindowDecorFactory = captionWindowDecorFactory; + mDesktopModeWindowDecorFactory = desktopModeWindowDecorFactory; mInputMonitorFactory = inputMonitorFactory; } @@ -151,7 +152,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { @Override public void onTaskInfoChanged(RunningTaskInfo taskInfo) { - final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId); + final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId); if (decoration == null) return; @@ -170,7 +171,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { SurfaceControl taskSurface, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { - final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId); + final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId); if (!shouldShowWindowDecor(taskInfo)) { if (decoration != null) { @@ -191,7 +192,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { RunningTaskInfo taskInfo, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { - final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId); + final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId); if (decoration == null) return; decoration.relayout(taskInfo, startT, finishT); @@ -199,7 +200,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { @Override public void destroyWindowDecoration(RunningTaskInfo taskInfo) { - final CaptionWindowDecoration decoration = + final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.removeReturnOld(taskInfo.taskId); if (decoration == null) return; @@ -232,7 +233,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { @Override public void onClick(View v) { - CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId); + DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId); final int id = v.getId(); if (id == R.id.close_window) { WindowContainerTransaction wct = new WindowContainerTransaction(); @@ -373,7 +374,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { boolean handled = false; if (event instanceof MotionEvent) { handled = true; - CaptionWindowDecorViewModel.this + DesktopModeWindowDecorViewModel.this .handleReceivedMotionEvent((MotionEvent) event, mInputMonitor); } finishInputEvent(event, handled); @@ -433,7 +434,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { */ private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) { if (DesktopModeStatus.isProto2Enabled()) { - CaptionWindowDecoration focusedDecor = getFocusedDecor(); + DesktopModeWindowDecoration focusedDecor = getFocusedDecor(); if (focusedDecor == null || focusedDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) { handleCaptionThroughStatusBar(ev); @@ -460,7 +461,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { private void handleEventOutsideFocusedCaption(MotionEvent ev) { int action = ev.getActionMasked(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { - CaptionWindowDecoration focusedDecor = getFocusedDecor(); + DesktopModeWindowDecoration focusedDecor = getFocusedDecor(); if (focusedDecor == null) { return; } @@ -480,7 +481,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: { // Begin drag through status bar if applicable. - CaptionWindowDecoration focusedDecor = getFocusedDecor(); + DesktopModeWindowDecoration focusedDecor = getFocusedDecor(); if (focusedDecor != null) { boolean dragFromStatusBarAllowed = false; if (DesktopModeStatus.isProto2Enabled()) { @@ -499,7 +500,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { break; } case MotionEvent.ACTION_UP: { - CaptionWindowDecoration focusedDecor = getFocusedDecor(); + DesktopModeWindowDecoration focusedDecor = getFocusedDecor(); if (focusedDecor == null) { mTransitionDragActive = false; return; @@ -529,11 +530,11 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { } @Nullable - private CaptionWindowDecoration getFocusedDecor() { + private DesktopModeWindowDecoration getFocusedDecor() { int size = mWindowDecorByTaskId.size(); - CaptionWindowDecoration focusedDecor = null; + DesktopModeWindowDecoration focusedDecor = null; for (int i = 0; i < size; i++) { - CaptionWindowDecoration decor = mWindowDecorByTaskId.valueAt(i); + DesktopModeWindowDecoration decor = mWindowDecorByTaskId.valueAt(i); if (decor != null && decor.isFocused()) { focusedDecor = decor; break; @@ -571,13 +572,13 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { SurfaceControl taskSurface, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { - CaptionWindowDecoration oldDecoration = mWindowDecorByTaskId.get(taskInfo.taskId); + DesktopModeWindowDecoration oldDecoration = mWindowDecorByTaskId.get(taskInfo.taskId); if (oldDecoration != null) { // close the old decoration if it exists to avoid two window decorations being added oldDecoration.close(); } - final CaptionWindowDecoration windowDecoration = - mCaptionWindowDecorFactory.create( + final DesktopModeWindowDecoration windowDecoration = + mDesktopModeWindowDecorFactory.create( mContext, mDisplayController, mTaskOrganizer, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java similarity index 98% rename from libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java rename to libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java index f7c7a87e66596..467f374f2110f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java @@ -43,12 +43,12 @@ import com.android.wm.shell.desktopmode.DesktopModeStatus; /** * Defines visuals and behaviors of a window decoration of a caption bar and shadows. It works with - * {@link CaptionWindowDecorViewModel}. The caption bar contains a handle, back button, and close - * button. + * {@link DesktopModeWindowDecorViewModel}. The caption bar contains a handle, back button, and + * close button. * * The shadow's thickness is 20dp when the window is in focus and 5dp when the window isn't. */ -public class CaptionWindowDecoration extends WindowDecoration { +public class DesktopModeWindowDecoration extends WindowDecoration { private final Handler mHandler; private final Choreographer mChoreographer; private final SyncTransactionQueue mSyncQueue; @@ -69,7 +69,7 @@ public class CaptionWindowDecoration extends WindowDecoration mMockInputManagers = new ArrayList<>(); - private CaptionWindowDecorViewModel mCaptionWindowDecorViewModel; + private DesktopModeWindowDecorViewModel mDesktopModeWindowDecorViewModel; @Before public void setUp() { mMockInputManagers.add(mInputManager); - mCaptionWindowDecorViewModel = - new CaptionWindowDecorViewModel( + mDesktopModeWindowDecorViewModel = + new DesktopModeWindowDecorViewModel( mContext, mMainHandler, mMainChoreographer, @@ -98,12 +98,12 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase { mSyncQueue, Optional.of(mDesktopModeController), Optional.of(mDesktopTasksController), - mCaptionWindowDecorFactory, + mDesktopModeWindowDecorFactory, mMockInputMonitorFactory ); - doReturn(mCaptionWindowDecoration) - .when(mCaptionWindowDecorFactory) + doReturn(mDesktopModeWindowDecoration) + .when(mDesktopModeWindowDecorFactory) .create(any(), any(), any(), any(), any(), any(), any(), any()); when(mMockInputMonitorFactory.create(any(), any())).thenReturn(mInputMonitor); @@ -123,13 +123,15 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase { final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); - mCaptionWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, finishT); + mDesktopModeWindowDecorViewModel.onTaskOpening( + taskInfo, surfaceControl, startT, finishT); taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_UNDEFINED); taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED); - mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT); + mDesktopModeWindowDecorViewModel.onTaskChanging( + taskInfo, surfaceControl, startT, finishT); }); - verify(mCaptionWindowDecorFactory) + verify(mDesktopModeWindowDecorFactory) .create( mContext, mDisplayController, @@ -139,7 +141,7 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase { mMainHandler, mMainChoreographer, mSyncQueue); - verify(mCaptionWindowDecoration).close(); + verify(mDesktopModeWindowDecoration).close(); } @Test @@ -153,14 +155,16 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase { final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED); - mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT); + mDesktopModeWindowDecorViewModel.onTaskChanging( + taskInfo, surfaceControl, startT, finishT); taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM); taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD); - mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT); + mDesktopModeWindowDecorViewModel.onTaskChanging( + taskInfo, surfaceControl, startT, finishT); }); - verify(mCaptionWindowDecorFactory, times(1)) + verify(mDesktopModeWindowDecorFactory, times(1)) .create( mContext, mDisplayController, @@ -183,9 +187,10 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase { final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); - mCaptionWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, finishT); + mDesktopModeWindowDecorViewModel.onTaskOpening( + taskInfo, surfaceControl, startT, finishT); - mCaptionWindowDecorViewModel.destroyWindowDecoration(taskInfo); + mDesktopModeWindowDecorViewModel.destroyWindowDecoration(taskInfo); }); verify(mMockInputMonitorFactory).create(any(), any()); verify(mInputMonitor).dispose(); @@ -214,13 +219,14 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase { final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); - mCaptionWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, finishT); - mCaptionWindowDecorViewModel.onTaskOpening(secondTaskInfo, surfaceControl, + mDesktopModeWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, + finishT); + mDesktopModeWindowDecorViewModel.onTaskOpening(secondTaskInfo, surfaceControl, startT, finishT); - mCaptionWindowDecorViewModel.onTaskOpening(thirdTaskInfo, surfaceControl, + mDesktopModeWindowDecorViewModel.onTaskOpening(thirdTaskInfo, surfaceControl, startT, finishT); - mCaptionWindowDecorViewModel.destroyWindowDecoration(thirdTaskInfo); - mCaptionWindowDecorViewModel.destroyWindowDecoration(taskInfo); + mDesktopModeWindowDecorViewModel.destroyWindowDecoration(thirdTaskInfo); + mDesktopModeWindowDecorViewModel.destroyWindowDecoration(taskInfo); }); verify(mMockInputMonitorFactory, times(2)).create(any(), any()); verify(mInputMonitor, times(1)).dispose(); From 07cb36926ef0a6767e464241c5a94bc54648d694 Mon Sep 17 00:00:00 2001 From: Jeff Nainaparampil Date: Tue, 27 Dec 2022 14:37:13 +0000 Subject: [PATCH 5/5] [People Service] Fix issue in AOSP people service where `setupUser` in the People DataManager is stuck Due to a missing `break` statement, People DataManager `setupUser` gets stuck at `userData.loadUserData()`, which prevents important listeners from registering properly. Among other things, this prevents the conversation widget from showing recent conversations. This CL fixes and adds tests for the proto conversion flow. Bug: 246928516 Change-Id: I929e1989761c8234c252b935afbe63712e93e124 --- .../server/people/data/ConversationInfo.java | 1 + .../people/data/ConversationInfoTest.java | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/services/people/java/com/android/server/people/data/ConversationInfo.java b/services/people/java/com/android/server/people/data/ConversationInfo.java index 6ead44a8cd1b8..a539fddc93814 100644 --- a/services/people/java/com/android/server/people/data/ConversationInfo.java +++ b/services/people/java/com/android/server/people/data/ConversationInfo.java @@ -424,6 +424,7 @@ public class ConversationInfo { case (int) ConversationInfoProto.CREATION_TIMESTAMP: builder.setCreationTimestamp(protoInputStream.readLong( ConversationInfoProto.CREATION_TIMESTAMP)); + break; case (int) ConversationInfoProto.SHORTCUT_FLAGS: builder.setShortcutFlags(protoInputStream.readInt( ConversationInfoProto.SHORTCUT_FLAGS)); diff --git a/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java b/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java index c90064eaa8107..9f914a1332b3f 100644 --- a/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java +++ b/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java @@ -30,6 +30,8 @@ import android.app.people.ConversationStatus; import android.content.LocusId; import android.content.pm.ShortcutInfo; import android.net.Uri; +import android.util.proto.ProtoInputStream; +import android.util.proto.ProtoOutputStream; import org.junit.Test; import org.junit.runner.RunWith; @@ -270,4 +272,58 @@ public final class ConversationInfoTest { assertTrue(conversationInfoFromBackup.isContactStarred()); // ConversationStatus is a transient object and not persisted } + + @Test + public void testBuildFromProtoPayload() throws Exception { + ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build(); + ConversationStatus cs2 = new ConversationStatus.Builder("id2", ACTIVITY_GAME).build(); + + ConversationInfo conversationInfo = new ConversationInfo.Builder() + .setShortcutId(SHORTCUT_ID) + .setLocusId(LOCUS_ID) + .setContactUri(CONTACT_URI) + .setContactPhoneNumber(PHONE_NUMBER) + .setNotificationChannelId(NOTIFICATION_CHANNEL_ID) + .setParentNotificationChannelId(PARENT_NOTIFICATION_CHANNEL_ID) + .setLastEventTimestamp(100L) + .setCreationTimestamp(200L) + .setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED + | ShortcutInfo.FLAG_CACHED_NOTIFICATIONS) + .setImportant(true) + .setNotificationSilenced(true) + .setBubbled(true) + .setDemoted(true) + .setPersonImportant(true) + .setPersonBot(true) + .setContactStarred(true) + .addOrUpdateStatus(cs) + .addOrUpdateStatus(cs2) + .build(); + + final ProtoOutputStream protoOutputStream = new ProtoOutputStream(); + conversationInfo.writeToProto(protoOutputStream); + ConversationInfo conversationInfoFromBackup = + ConversationInfo.readFromProto(new ProtoInputStream(protoOutputStream.getBytes())); + + assertEquals(SHORTCUT_ID, conversationInfoFromBackup.getShortcutId()); + assertEquals(LOCUS_ID, conversationInfoFromBackup.getLocusId()); + assertEquals(CONTACT_URI, conversationInfoFromBackup.getContactUri()); + assertEquals(PHONE_NUMBER, conversationInfoFromBackup.getContactPhoneNumber()); + assertEquals( + NOTIFICATION_CHANNEL_ID, conversationInfoFromBackup.getNotificationChannelId()); + assertEquals(PARENT_NOTIFICATION_CHANNEL_ID, + conversationInfoFromBackup.getParentNotificationChannelId()); + assertEquals(100L, conversationInfoFromBackup.getLastEventTimestamp()); + assertEquals(200L, conversationInfoFromBackup.getCreationTimestamp()); + assertTrue(conversationInfoFromBackup.isShortcutLongLived()); + assertTrue(conversationInfoFromBackup.isShortcutCachedForNotification()); + assertTrue(conversationInfoFromBackup.isImportant()); + assertTrue(conversationInfoFromBackup.isNotificationSilenced()); + assertTrue(conversationInfoFromBackup.isBubbled()); + assertTrue(conversationInfoFromBackup.isDemoted()); + assertTrue(conversationInfoFromBackup.isPersonImportant()); + assertTrue(conversationInfoFromBackup.isPersonBot()); + assertTrue(conversationInfoFromBackup.isContactStarred()); + // ConversationStatus is a transient object and not persisted + } }