Snap for 9439764 from 971c479068 to tm-qpr2-release
Change-Id: I932dbef3f918bdbef5aa66a55d56a3979165e5e5
This commit is contained in:
@@ -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}.
|
||||
|
||||
144
core/java/android/service/chooser/ChooserAction.java
Normal file
144
core/java/android/service/chooser/ChooserAction.java
Normal file
@@ -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<ChooserAction> CREATOR =
|
||||
new Creator<ChooserAction>() {
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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> desktopModeController,
|
||||
Optional<DesktopTasksController> desktopTasksController) {
|
||||
return new CaptionWindowDecorViewModel(
|
||||
return new DesktopModeWindowDecorViewModel(
|
||||
context,
|
||||
mainHandler,
|
||||
mainChoreographer,
|
||||
|
||||
@@ -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<EventReceiver> mEventReceiversByDisplay = new SparseArray<>();
|
||||
|
||||
private final SparseArray<CaptionWindowDecoration> mWindowDecorByTaskId = new SparseArray<>();
|
||||
private final SparseArray<DesktopModeWindowDecoration> 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> desktopModeController,
|
||||
Optional<DesktopTasksController> 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,
|
||||
@@ -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<WindowDecorLinearLayout> {
|
||||
public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLinearLayout> {
|
||||
private final Handler mHandler;
|
||||
private final Choreographer mChoreographer;
|
||||
private final SyncTransactionQueue mSyncQueue;
|
||||
@@ -69,7 +69,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
||||
|
||||
private AdditionalWindow mHandleMenu;
|
||||
|
||||
CaptionWindowDecoration(
|
||||
DesktopModeWindowDecoration(
|
||||
Context context,
|
||||
DisplayController displayController,
|
||||
ShellTaskOrganizer taskOrganizer,
|
||||
@@ -424,7 +424,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
||||
|
||||
static class Factory {
|
||||
|
||||
CaptionWindowDecoration create(
|
||||
DesktopModeWindowDecoration create(
|
||||
Context context,
|
||||
DisplayController displayController,
|
||||
ShellTaskOrganizer taskOrganizer,
|
||||
@@ -433,7 +433,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
||||
Handler handler,
|
||||
Choreographer choreographer,
|
||||
SyncTransactionQueue syncQueue) {
|
||||
return new CaptionWindowDecoration(
|
||||
return new DesktopModeWindowDecoration(
|
||||
context,
|
||||
displayController,
|
||||
taskOrganizer,
|
||||
@@ -60,14 +60,14 @@ import java.util.Optional;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/** Tests of {@link CaptionWindowDecorViewModel} */
|
||||
/** Tests of {@link DesktopModeWindowDecorViewModel} */
|
||||
@SmallTest
|
||||
public class CaptionWindowDecorViewModelTests extends ShellTestCase {
|
||||
public class DesktopModeWindowDecorViewModelTests extends ShellTestCase {
|
||||
|
||||
private static final String TAG = "CaptionWindowDecorViewModelTests";
|
||||
private static final String TAG = "DesktopModeWindowDecorViewModelTests";
|
||||
|
||||
@Mock private CaptionWindowDecoration mCaptionWindowDecoration;
|
||||
@Mock private CaptionWindowDecoration.Factory mCaptionWindowDecorFactory;
|
||||
@Mock private DesktopModeWindowDecoration mDesktopModeWindowDecoration;
|
||||
@Mock private DesktopModeWindowDecoration.Factory mDesktopModeWindowDecorFactory;
|
||||
|
||||
@Mock private Handler mMainHandler;
|
||||
@Mock private Choreographer mMainChoreographer;
|
||||
@@ -79,17 +79,17 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase {
|
||||
@Mock private InputMonitor mInputMonitor;
|
||||
@Mock private InputManager mInputManager;
|
||||
|
||||
@Mock private CaptionWindowDecorViewModel.InputMonitorFactory mMockInputMonitorFactory;
|
||||
@Mock private DesktopModeWindowDecorViewModel.InputMonitorFactory mMockInputMonitorFactory;
|
||||
private final List<InputManager> 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();
|
||||
@@ -19,8 +19,8 @@
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||
android:shape="oval">
|
||||
<size
|
||||
android:height="@dimen/media_ttt_chip_size_receiver"
|
||||
android:width="@dimen/media_ttt_chip_size_receiver"
|
||||
android:height="@dimen/media_ttt_icon_size_receiver"
|
||||
android:width="@dimen/media_ttt_icon_size_receiver"
|
||||
/>
|
||||
<solid android:color="?androidprv:attr/colorSurface" />
|
||||
<solid android:color="?androidprv:attr/colorAccentPrimary" />
|
||||
</shape>
|
||||
|
||||
@@ -1073,11 +1073,12 @@
|
||||
<dimen name="media_ttt_last_item_start_margin">12dp</dimen>
|
||||
|
||||
<!-- Media tap-to-transfer chip for receiver device -->
|
||||
<dimen name="media_ttt_chip_size_receiver">100dp</dimen>
|
||||
<dimen name="media_ttt_icon_size_receiver">95dp</dimen>
|
||||
<dimen name="media_ttt_icon_size_receiver">112dp</dimen>
|
||||
<!-- Add some padding for the generic icon so it doesn't go all the way to the border. -->
|
||||
<dimen name="media_ttt_generic_icon_padding">12dp</dimen>
|
||||
<dimen name="media_ttt_receiver_vert_translation">20dp</dimen>
|
||||
<!-- The generic icon should be 40dp, and the full icon is 112dp, so the padding should be
|
||||
(112 - 40) / 2 = 36dp -->
|
||||
<dimen name="media_ttt_generic_icon_padding">36dp</dimen>
|
||||
<dimen name="media_ttt_receiver_vert_translation">40dp</dimen>
|
||||
|
||||
<!-- Window magnification -->
|
||||
<dimen name="magnification_border_drag_size">35dp</dimen>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user