Refactoring OverviewCommandHelper (2/3)

This CL should not affect the behavior of OverviewCommandHelper.
- It splits executeCommand into smaller functions
- Rearrange public/private functions
- Adds extra logs.

Bug: 352046797
Bug: 351122926
Flag: EXEMPT bugfix.
Test: Manual.
Change-Id: I283f179794af812973a559db6291febe19e3c6d7
This commit is contained in:
Jordan Silva
2024-08-28 15:20:05 +01:00
parent e7ae4e31ae
commit ebfae18529

View File

@@ -73,48 +73,6 @@ class OverviewCommandHelper(
private val visibleRecentsView: RecentsView<*, *>?
get() = activityInterface.getVisibleRecentsView<RecentsView<*, *>>()
/** Called when the command finishes execution. */
private fun onCommandFinished(command: CommandInfo) {
command.status = CommandStatus.COMPLETED
if (commandQueue.first() !== command) {
Log.d(
TAG,
"next task not scheduled. First pending command type " +
"is ${commandQueue.first()} - command type is: $command"
)
return
}
Log.d(TAG, "command executed successfully! $command")
commandQueue.remove(command)
executeNext()
}
/**
* Executes the next command from the queue. If the command finishes immediately (returns true),
* it continues to execute the next command, until the queue is empty of a command defer's its
* completion (returns false).
*/
@UiThread
private fun executeNext() {
val command: CommandInfo =
commandQueue.firstOrNull()
?: run {
Log.d(TAG, "no pending commands to be executed.")
return
}
Log.d(TAG, "executing command: $command")
val result = executeCommand(command)
Log.d(TAG, "command executed: $command with result: $result")
if (result) {
onCommandFinished(command)
} else {
Log.d(TAG, "waiting for command callback: $command")
}
}
/**
* Adds a command to be executed next, after all pending tasks are completed. Max commands that
* can be queued is [.MAX_QUEUE_SIZE]. Requests after reaching that limit will be silently
@@ -138,23 +96,89 @@ class OverviewCommandHelper(
fun canStartHomeSafely(): Boolean = commandQueue.isEmpty() || commandQueue.first().type == HOME
/** Clear commands from the queue */
/** Clear pending commands from the queue */
fun clearPendingCommands() {
Log.d(TAG, "clearing pending commands: $commandQueue")
commandQueue.clear()
}
private fun getNextTask(view: RecentsView<*, *>): TaskView? {
val runningTaskView = view.runningTaskView
/**
* Executes the next command from the queue. If the command finishes immediately (returns true),
* it continues to execute the next command, until the queue is empty of a command defer's its
* completion (returns false).
*/
@UiThread
private fun executeNext() {
val command: CommandInfo =
commandQueue.firstOrNull()
?: run {
Log.d(TAG, "no pending commands to be executed.")
return
}
return if (runningTaskView == null) {
view.getTaskViewAt(0)
command.status = CommandStatus.PROCESSING
Log.d(TAG, "executing command: $command")
val result = executeCommand(command)
Log.d(TAG, "command executed: $command with result: $result")
if (result) {
onCommandFinished(command)
} else {
val nextTask = view.nextTaskView
nextTask ?: runningTaskView
Log.d(TAG, "waiting for command callback: $command")
}
}
/**
* Executes the task and returns true if next task can be executed. If false, then the next task
* is deferred until [.scheduleNextTask] is called
*/
private fun executeCommand(command: CommandInfo): Boolean {
if (waitForToggleCommandComplete && command.type == TOGGLE) {
Log.d(TAG, "executeCommand: $command - waiting for toggle command complete")
return true
}
val recentsView = visibleRecentsView
Log.d(TAG, "executeCommand: $command - visibleRecentsView: $recentsView")
return if (recentsView != null) {
executeWhenRecentsIsVisible(command, recentsView)
} else {
executeWhenRecentsIsNotVisible(command)
}
}
private fun executeWhenRecentsIsVisible(
command: CommandInfo,
recentsView: RecentsView<*, *>,
): Boolean =
when (command.type) {
SHOW -> true // already visible
KEYBOARD_INPUT,
HIDE -> {
if (recentsView.isHandlingTouch) {
true
} else {
keyboardTaskFocusIndex = PagedView.INVALID_PAGE
val currentPage = recentsView.nextPage
val taskView = recentsView.getTaskViewAt(currentPage)
launchTask(recentsView, taskView, command)
}
}
TOGGLE -> {
val taskView =
if (recentsView.runningTaskView == null) {
recentsView.getTaskViewAt(0)
} else {
recentsView.nextTaskView ?: recentsView.runningTaskView
}
launchTask(recentsView, taskView, command)
}
HOME -> {
recentsView.startHome()
true
}
}
private fun launchTask(
recents: RecentsView<*, *>,
taskView: TaskView?,
@@ -182,81 +206,46 @@ class OverviewCommandHelper(
}
}
/**
* Executes the task and returns true if next task can be executed. If false, then the next task
* is deferred until [.scheduleNextTask] is called
*/
private fun executeCommand(command: CommandInfo): Boolean {
command.status = CommandStatus.PROCESSING
private fun executeWhenRecentsIsNotVisible(command: CommandInfo): Boolean {
val recentsViewContainer = activityInterface.getCreatedContainer() as? RecentsViewContainer
val recentsView: RecentsView<*, *>? = recentsViewContainer?.getOverviewPanel()
val deviceProfile = recentsViewContainer?.getDeviceProfile()
val uiController = activityInterface.getTaskbarController()
val allowQuickSwitch =
FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH.get() &&
uiController != null &&
deviceProfile != null &&
(deviceProfile.isTablet || deviceProfile.isTwoPanels)
if (waitForToggleCommandComplete && command.type == TOGGLE) {
Log.d(TAG, "executeCommand: $command - waiting for toggle command complete")
return true
}
var recentsView = visibleRecentsView
Log.d(TAG, "executeCommand: $command - visibleRecentsView: $recentsView")
if (recentsView == null) {
val activity = activityInterface.getCreatedContainer() as? RecentsViewContainer
recentsView = activity?.getOverviewPanel()
val deviceProfile = activity?.getDeviceProfile()
val uiController = activityInterface.getTaskbarController()
val allowQuickSwitch =
FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH.get() &&
uiController != null &&
deviceProfile != null &&
(deviceProfile.isTablet || deviceProfile.isTwoPanels)
when (command.type) {
HIDE -> {
if (!allowQuickSwitch) return true
keyboardTaskFocusIndex = uiController!!.launchFocusedTask()
if (keyboardTaskFocusIndex == -1) return true
}
KEYBOARD_INPUT ->
if (allowQuickSwitch) {
uiController!!.openQuickSwitchView()
return true
} else {
keyboardTaskFocusIndex = 0
}
HOME -> {
ActiveGestureLog.INSTANCE.addLog("OverviewCommandHelper.executeCommand(HOME)")
// Although IActivityTaskManager$Stub$Proxy.startActivity is a slow binder call,
// we should still call it on main thread because launcher is waiting for
// ActivityTaskManager to resume it. Also calling startActivity() on bg thread
// could potentially delay resuming launcher. See b/348668521 for more details.
touchInteractionService.startActivity(overviewComponentObserver.homeIntent)
when (command.type) {
HIDE -> {
if (!allowQuickSwitch) return true
keyboardTaskFocusIndex = uiController!!.launchFocusedTask()
if (keyboardTaskFocusIndex == -1) return true
}
KEYBOARD_INPUT ->
if (allowQuickSwitch) {
uiController!!.openQuickSwitchView()
return true
}
SHOW ->
// When Recents is not currently visible, the command's type is SHOW
// when overview is triggered via the keyboard overview button or Action+Tab
// keys (Not Alt+Tab which is KQS). The overview button on-screen in 3-button
// nav is TYPE_TOGGLE.
} else {
keyboardTaskFocusIndex = 0
TOGGLE -> {}
}
} else {
return when (command.type) {
SHOW -> true // already visible
KEYBOARD_INPUT,
HIDE -> {
if (recentsView.isHandlingTouch) {
true
} else {
keyboardTaskFocusIndex = PagedView.INVALID_PAGE
val currentPage = recentsView.nextPage
val taskView = recentsView.getTaskViewAt(currentPage)
launchTask(recentsView, taskView, command)
}
}
TOGGLE -> launchTask(recentsView, getNextTask(recentsView), command)
HOME -> {
recentsView.startHome()
true
}
HOME -> {
ActiveGestureLog.INSTANCE.addLog("OverviewCommandHelper.executeCommand(HOME)")
// Although IActivityTaskManager$Stub$Proxy.startActivity is a slow binder call,
// we should still call it on main thread because launcher is waiting for
// ActivityTaskManager to resume it. Also calling startActivity() on bg thread
// could potentially delay resuming launcher. See b/348668521 for more details.
touchInteractionService.startActivity(overviewComponentObserver.homeIntent)
return true
}
SHOW ->
// When Recents is not currently visible, the command's type is SHOW
// when overview is triggered via the keyboard overview button or Action+Tab
// keys (Not Alt+Tab which is KQS). The overview button on-screen in 3-button
// nav is TYPE_TOGGLE.
keyboardTaskFocusIndex = 0
TOGGLE -> {}
}
recentsView?.setKeyboardTaskFocusIndex(keyboardTaskFocusIndex)
@@ -264,6 +253,7 @@ class OverviewCommandHelper(
val animatorListener: Animator.AnimatorListener =
object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator) {
Log.d(TAG, "switching to Overview state - onAnimationStart: $command")
super.onAnimationStart(animation)
updateRecentsViewFocus(command)
logShowOverviewFrom(command.type)
@@ -309,9 +299,11 @@ class OverviewCommandHelper(
controller: RecentsAnimationController,
targets: RecentsAnimationTargets
) {
Log.d(TAG, "recents animation started: $command")
updateRecentsViewFocus(command)
logShowOverviewFrom(command.type)
activityInterface.runOnInitBackgroundStateUI {
Log.d(TAG, "recents animation started - onInitBackgroundStateUI: $command")
interactionHandler.onGestureEnded(0f, PointF())
}
command.removeListener(this)
@@ -320,6 +312,7 @@ class OverviewCommandHelper(
override fun onRecentsAnimationCanceled(
thumbnailDatas: HashMap<Int, ThumbnailData>
) {
Log.d(TAG, "recents animation canceled: $command")
interactionHandler.onGestureCancelled()
command.removeListener(this)
@@ -366,6 +359,23 @@ class OverviewCommandHelper(
onCommandFinished(command)
}
/** Called when the command finishes execution. */
private fun onCommandFinished(command: CommandInfo) {
command.status = CommandStatus.COMPLETED
if (commandQueue.first() !== command) {
Log.d(
TAG,
"next task not scheduled. First pending command type " +
"is ${commandQueue.first()} - command type is: $command"
)
return
}
Log.d(TAG, "command executed successfully! $command")
commandQueue.remove(command)
executeNext()
}
private fun updateRecentsViewFocus(command: CommandInfo) {
val recentsView: RecentsView<*, *> = visibleRecentsView ?: return
if (command.type != KEYBOARD_INPUT && command.type != HIDE && command.type != SHOW) {
@@ -380,10 +390,11 @@ class OverviewCommandHelper(
// here we launch overview with live tile.
recentsView.viewRootImpl.touchModeChanged(false)
// Ensure that recents view has focus so that it receives the followup key inputs
if (requestFocus(recentsView.getTaskViewAt(keyboardTaskFocusIndex))) return
if (requestFocus(recentsView.nextTaskView)) return
if (requestFocus(recentsView.getTaskViewAt(0))) return
requestFocus(recentsView)
// Stops requesting focused after first view gets focused.
recentsView.getTaskViewAt(keyboardTaskFocusIndex).requestFocus() ||
recentsView.nextTaskView.requestFocus() ||
recentsView.getTaskViewAt(0).requestFocus() ||
recentsView.requestFocus()
}
private fun onRecentsViewFocusUpdated(command: CommandInfo) {
@@ -396,11 +407,11 @@ class OverviewCommandHelper(
keyboardTaskFocusIndex = PagedView.INVALID_PAGE
}
private fun requestFocus(taskView: View?): Boolean {
if (taskView == null) return false
taskView.post {
taskView.requestFocus()
taskView.requestAccessibilityFocus()
private fun View?.requestFocus(): Boolean {
if (this == null) return false
post {
requestFocus()
requestAccessibilityFocus()
}
return true
}