Merge changes from topics "taskbar-search-back", "taskbar-search-transition" into udc-qpr-dev
* changes:
Support system back in Taskbar search session.
Notify Taskbar search session of All Apps transitions.
diff --git a/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
index 4e67629..69e1574 100644
--- a/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
+++ b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
@@ -23,7 +23,7 @@
android:importantForAccessibility="yes"
android:background="@drawable/keyboard_quick_switch_task_view_background"
android:clipToOutline="true"
- launcher:borderColor="?androidprv:attr/materialColorOutline">
+ launcher:focusBorderColor="?androidprv:attr/materialColorOutline">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/content"
diff --git a/quickstep/res/layout/keyboard_quick_switch_overview.xml b/quickstep/res/layout/keyboard_quick_switch_overview.xml
index e7b1f23..4a9b023 100644
--- a/quickstep/res/layout/keyboard_quick_switch_overview.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_overview.xml
@@ -22,7 +22,7 @@
android:layout_height="@dimen/keyboard_quick_switch_taskview_height"
android:clipToOutline="true"
android:importantForAccessibility="yes"
- launcher:borderColor="?androidprv:attr/materialColorOutline">
+ launcher:focusBorderColor="?androidprv:attr/materialColorOutline">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/content"
diff --git a/quickstep/res/layout/keyboard_quick_switch_taskview.xml b/quickstep/res/layout/keyboard_quick_switch_taskview.xml
index 4d213fa..6ed3c6e 100644
--- a/quickstep/res/layout/keyboard_quick_switch_taskview.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_taskview.xml
@@ -23,7 +23,7 @@
android:importantForAccessibility="yes"
android:background="@drawable/keyboard_quick_switch_task_view_background"
android:clipToOutline="true"
- launcher:borderColor="?androidprv:attr/materialColorOutline">
+ launcher:focusBorderColor="?androidprv:attr/materialColorOutline">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/content"
diff --git a/quickstep/res/layout/split_instructions_view.xml b/quickstep/res/layout/split_instructions_view.xml
index 5f037f8..c663bf4 100644
--- a/quickstep/res/layout/split_instructions_view.xml
+++ b/quickstep/res/layout/split_instructions_view.xml
@@ -32,7 +32,7 @@
android:layout_width="wrap_content"
android:gravity="center"
android:textColor="?androidprv:attr/textColorOnAccent"
- android:drawableEnd="@drawable/ic_split_horizontal"
+ android:drawableEnd="@drawable/ic_split_exit"
android:drawablePadding="@dimen/split_instructions_drawable_padding"
android:text="@string/toast_split_select_app" />
</com.android.quickstep.views.SplitInstructionsView>
\ No newline at end of file
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index 4865aef..29c9992 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -24,7 +24,8 @@
android:clipChildren="false"
android:defaultFocusHighlightEnabled="false"
android:focusable="true"
- launcher:borderColor="?androidprv:attr/materialColorOutline">
+ launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
+ launcher:hoverBorderColor="?androidprv:attr/materialColorPrimary">
<com.android.quickstep.views.TaskThumbnailView
android:id="@+id/snapshot"
diff --git a/quickstep/res/layout/task_desktop.xml b/quickstep/res/layout/task_desktop.xml
index fd82c66..06f4d06 100644
--- a/quickstep/res/layout/task_desktop.xml
+++ b/quickstep/res/layout/task_desktop.xml
@@ -25,7 +25,8 @@
android:clipToOutline="true"
android:defaultFocusHighlightEnabled="false"
android:focusable="true"
- launcher:borderColor="?androidprv:attr/materialColorOutline">
+ launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
+ launcher:hoverBorderColor="?androidprv:attr/materialColorPrimary">
<View
android:id="@+id/background"
diff --git a/quickstep/res/layout/task_grouped.xml b/quickstep/res/layout/task_grouped.xml
index c9fa9c0..75ff626 100644
--- a/quickstep/res/layout/task_grouped.xml
+++ b/quickstep/res/layout/task_grouped.xml
@@ -29,7 +29,8 @@
android:clipChildren="false"
android:defaultFocusHighlightEnabled="false"
android:focusable="true"
- launcher:borderColor="?androidprv:attr/materialColorOutline">
+ launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
+ launcher:hoverBorderColor="?androidprv:attr/materialColorPrimary">
<com.android.quickstep.views.TaskThumbnailView
android:id="@+id/snapshot"
diff --git a/quickstep/res/values/attrs.xml b/quickstep/res/values/attrs.xml
index fb51919..7288774 100644
--- a/quickstep/res/values/attrs.xml
+++ b/quickstep/res/values/attrs.xml
@@ -26,7 +26,8 @@
-->
<declare-styleable name="TaskView">
<!-- Border color for a keyboard quick switch task views -->
- <attr name="borderColor" format="color" />
+ <attr name="focusBorderColor" format="color" />
+ <attr name="hoverBorderColor" format="color" />
</declare-styleable>
<!--
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index e4f6555..b0e91a1 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -38,6 +38,8 @@
<dimen name="task_thumbnail_icon_size">48dp</dimen>
<!-- The icon size for the focused task, placed in center of touch target -->
<dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
+ <!-- The border width shown when task is hovered -->
+ <dimen name="task_hover_border_width">4dp</dimen>
<!-- The space under the focused task icon -->
<dimen name="overview_task_margin">16dp</dimen>
<!-- The horizontal space between tasks -->
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 153c1ac..4489eaf 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -158,6 +158,7 @@
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.wm.shell.startingsurface.IStartingWindowListener;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
@@ -477,6 +478,9 @@
});
}
+ /** Dump debug logs to bug report. */
+ public void dump(@NonNull String prefix, @NonNull PrintWriter printWriter) {}
+
/**
* Content is everything on screen except the background and the floating view (if any).
*
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
index 8a11b57..3e1a6ae 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
@@ -80,7 +80,7 @@
setWillNotDraw(false);
mBorderColor = ta.getColor(
- R.styleable.TaskView_borderColor, DEFAULT_BORDER_COLOR);
+ R.styleable.TaskView_focusBorderColor, DEFAULT_BORDER_COLOR);
ta.recycle();
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 6c73a2d..ffd22b8 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -203,6 +203,8 @@
public static final boolean GO_LOW_RAM_RECENTS_ENABLED = false;
+ protected static final String RING_APPEAR_ANIMATION_PREFIX = "RingAppearAnimation\t";
+
private FixedContainerItems mAllAppsPredictions;
private HotseatPredictionController mHotseatPredictionController;
private DepthController mDepthController;
@@ -1363,5 +1365,8 @@
if (recentsView != null) {
recentsView.getSplitSelectController().dump(prefix, writer);
}
+ if (mAppTransitionManager != null) {
+ mAppTransitionManager.dump(prefix + "\t" + RING_APPEAR_ANIMATION_PREFIX, writer);
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 5301c7c..6b0843c 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -97,7 +97,6 @@
import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.TaskIconCache;
-import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.TaskViewUtils;
@@ -413,7 +412,9 @@
private boolean mIsClickableAsLiveTile = true;
- @Nullable private final BorderAnimator mBorderAnimator;
+ @Nullable private final BorderAnimator mFocusBorderAnimator;
+
+ @Nullable private final BorderAnimator mHoverBorderAnimator;
public TaskView(Context context) {
this(context, null);
@@ -439,23 +440,40 @@
boolean keyboardFocusHighlightEnabled = FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH.get()
|| DesktopTaskView.DESKTOP_MODE_SUPPORTED;
- setWillNotDraw(!keyboardFocusHighlightEnabled);
+ boolean willDrawBorder =
+ keyboardFocusHighlightEnabled || FeatureFlags.ENABLE_CURSOR_HOVER_STATES.get();
+ setWillNotDraw(!willDrawBorder);
- TypedArray ta = context.obtainStyledAttributes(
- attrs, R.styleable.TaskView, defStyleAttr, defStyleRes);
+ if (willDrawBorder) {
+ TypedArray styledAttrs = context.obtainStyledAttributes(
+ attrs, R.styleable.TaskView, defStyleAttr, defStyleRes);
- mBorderAnimator = !keyboardFocusHighlightEnabled
- ? null
- : new BorderAnimator(
- /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
- /* borderColor= */ ta.getColor(
- R.styleable.TaskView_borderColor, DEFAULT_BORDER_COLOR),
- /* borderAnimationParams= */ new BorderAnimator.SimpleParams(
- /* borderWidthPx= */ context.getResources().getDimensionPixelSize(
- R.dimen.keyboard_quick_switch_border_width),
- /* boundsBuilder= */ this::updateBorderBounds,
- /* targetView= */ this));
- ta.recycle();
+ mFocusBorderAnimator = keyboardFocusHighlightEnabled ? new BorderAnimator(
+ /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
+ /* borderColor= */ styledAttrs.getColor(
+ R.styleable.TaskView_focusBorderColor, DEFAULT_BORDER_COLOR),
+ /* borderAnimationParams= */ new BorderAnimator.SimpleParams(
+ /* borderWidthPx= */ context.getResources().getDimensionPixelSize(
+ R.dimen.keyboard_quick_switch_border_width),
+ /* boundsBuilder= */ this::updateBorderBounds,
+ /* targetView= */ this)) : null;
+
+ mHoverBorderAnimator =
+ FeatureFlags.ENABLE_CURSOR_HOVER_STATES.get() ? new BorderAnimator(
+ /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
+ /* borderColor= */ styledAttrs.getColor(
+ R.styleable.TaskView_hoverBorderColor, DEFAULT_BORDER_COLOR),
+ /* borderAnimationParams= */ new BorderAnimator.SimpleParams(
+ /* borderWidthPx= */ context.getResources()
+ .getDimensionPixelSize(R.dimen.task_hover_border_width),
+ /* boundsBuilder= */ this::updateBorderBounds,
+ /* targetView= */ this)) : null;
+
+ styledAttrs.recycle();
+ } else {
+ mFocusBorderAnimator = null;
+ mHoverBorderAnimator = null;
+ }
}
protected void updateBorderBounds(Rect bounds) {
@@ -509,16 +527,48 @@
@Override
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
- if (mBorderAnimator != null) {
- mBorderAnimator.buildAnimator(gainFocus).start();
+ if (mFocusBorderAnimator != null) {
+ mFocusBorderAnimator.buildAnimator(gainFocus).start();
+ }
+ }
+
+ @Override
+ public boolean onHoverEvent(MotionEvent event) {
+ if (FeatureFlags.ENABLE_CURSOR_HOVER_STATES.get()) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ mHoverBorderAnimator.buildAnimator(/* isAppearing= */ true).start();
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ mHoverBorderAnimator.buildAnimator(/* isAppearing= */ false).start();
+ break;
+ default:
+ break;
+ }
+ }
+ return super.onHoverEvent(event);
+ }
+
+ @Override
+ public boolean onInterceptHoverEvent(MotionEvent event) {
+ if (FeatureFlags.ENABLE_CURSOR_HOVER_STATES.get()) {
+ // avoid triggering hover event on child elements which would cause HOVER_EXIT for this
+ // task view
+ return true;
+ } else {
+ return super.onInterceptHoverEvent(event);
}
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
- if (mBorderAnimator != null) {
- mBorderAnimator.drawBorder(canvas);
+ if (mFocusBorderAnimator != null) {
+ mFocusBorderAnimator.drawBorder(canvas);
+ }
+
+ if (mHoverBorderAnimator != null) {
+ mHoverBorderAnimator.drawBorder(canvas);
}
}
diff --git a/res/drawable/ic_split_exit.xml b/res/drawable/ic_split_exit.xml
new file mode 100644
index 0000000..d7e8b03
--- /dev/null
+++ b/res/drawable/ic_split_exit.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="20dp"
+ android:tint="#000000"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="20dp">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
+</vector>
\ No newline at end of file
diff --git a/src/com/android/launcher3/util/EventLogArray.kt b/src/com/android/launcher3/util/EventLogArray.kt
new file mode 100644
index 0000000..a17d650
--- /dev/null
+++ b/src/com/android/launcher3/util/EventLogArray.kt
@@ -0,0 +1,117 @@
+/*
+ * 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.launcher3.util
+
+import java.io.PrintWriter
+import java.text.SimpleDateFormat
+import java.util.Date
+import java.util.Locale
+
+/**
+ * A utility class to record and log events. Events are stored in a fixed size array and old logs
+ * are purged as new events come.
+ */
+class EventLogArray(private val name: String, size: Int) {
+
+ companion object {
+ private const val TYPE_ONE_OFF = 0
+ private const val TYPE_FLOAT = 1
+ private const val TYPE_INTEGER = 2
+ private const val TYPE_BOOL_TRUE = 3
+ private const val TYPE_BOOL_FALSE = 4
+ private fun isEntrySame(entry: EventEntry?, type: Int, event: String): Boolean {
+ return entry != null && entry.type == type && entry.event == event
+ }
+ }
+
+ private val logs: Array<EventEntry?>
+ private var nextIndex = 0
+
+ init {
+ logs = arrayOfNulls(size)
+ }
+
+ fun addLog(event: String) {
+ addLog(TYPE_ONE_OFF, event, 0f)
+ }
+
+ fun addLog(event: String, extras: Int) {
+ addLog(TYPE_INTEGER, event, extras.toFloat())
+ }
+
+ fun addLog(event: String, extras: Float) {
+ addLog(TYPE_FLOAT, event, extras)
+ }
+
+ fun addLog(event: String, extras: Boolean) {
+ addLog(if (extras) TYPE_BOOL_TRUE else TYPE_BOOL_FALSE, event, 0f)
+ }
+
+ private fun addLog(type: Int, event: String, extras: Float) {
+ // Merge the logs if it's a duplicate
+ val last = (nextIndex + logs.size - 1) % logs.size
+ val secondLast = (nextIndex + logs.size - 2) % logs.size
+ if (isEntrySame(logs[last], type, event) && isEntrySame(logs[secondLast], type, event)) {
+ logs[last]!!.update(type, event, extras)
+ logs[secondLast]!!.duplicateCount++
+ return
+ }
+ if (logs[nextIndex] == null) {
+ logs[nextIndex] = EventEntry()
+ }
+ logs[nextIndex]!!.update(type, event, extras)
+ nextIndex = (nextIndex + 1) % logs.size
+ }
+
+ fun dump(prefix: String, writer: PrintWriter) {
+ writer.println("$prefix$name event history:")
+ val sdf = SimpleDateFormat(" HH:mm:ss.SSSZ ", Locale.US)
+ val date = Date()
+ for (i in logs.indices) {
+ val log = logs[(nextIndex + logs.size - i - 1) % logs.size] ?: continue
+ date.time = log.time
+ val msg = StringBuilder(prefix).append(sdf.format(date)).append(log.event)
+ when (log.type) {
+ TYPE_BOOL_FALSE -> msg.append(": false")
+ TYPE_BOOL_TRUE -> msg.append(": true")
+ TYPE_FLOAT -> msg.append(": ").append(log.extras)
+ TYPE_INTEGER -> msg.append(": ").append(log.extras.toInt())
+ else -> {}
+ }
+ if (log.duplicateCount > 0) {
+ msg.append(" & ").append(log.duplicateCount).append(" similar events")
+ }
+ writer.println(msg)
+ }
+ }
+
+ /** A single event entry. */
+ private class EventEntry {
+ var type = 0
+ var event: String? = null
+ var extras = 0f
+ var time: Long = 0
+ var duplicateCount = 0
+ fun update(type: Int, event: String, extras: Float) {
+ this.type = type
+ this.event = event
+ this.extras = extras
+ time = System.currentTimeMillis()
+ duplicateCount = 0
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java b/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
index d3ce67c..81a59b9 100644
--- a/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
+++ b/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
@@ -69,7 +69,10 @@
mView.setBackgroundColor(Color.BLUE);
setContentView(mView);
- registerReceiver(mCommandReceiver, new IntentFilter(mAction + SUFFIX_COMMAND));
+ registerReceiver(
+ mCommandReceiver,
+ new IntentFilter(mAction + SUFFIX_COMMAND),
+ RECEIVER_EXPORTED);
}
protected void addButton(String title, String method) {