1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.wm.shell.desktopmode 18 19 import android.app.ActivityTaskManager.INVALID_TASK_ID 20 import android.window.DesktopExperienceFlags 21 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UnminimizeReason 22 import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource.UNKNOWN 23 import com.android.wm.shell.sysui.ShellCommandHandler 24 import com.android.wm.shell.transition.FocusTransitionObserver 25 import java.io.PrintWriter 26 27 /** Handles the shell commands for the DesktopTasksController. */ 28 class DesktopModeShellCommandHandler( 29 private val controller: DesktopTasksController, 30 private val focusTransitionObserver: FocusTransitionObserver, 31 ) : ShellCommandHandler.ShellCommandActionHandler { 32 onShellCommandnull33 override fun onShellCommand(args: Array<String>, pw: PrintWriter): Boolean = 34 when (args[0]) { 35 "moveTaskToDesk" -> runMoveTaskToDesk(args, pw) 36 "moveToNextDisplay" -> runMoveToNextDisplay(args, pw) 37 "createDesk" -> runCreateDesk(args, pw) 38 "activateDesk" -> runActivateDesk(args, pw) 39 "removeDesk" -> runRemoveDesk(args, pw) 40 "removeAllDesks" -> runRemoveAllDesks(args, pw) 41 "moveTaskToFront" -> runMoveTaskToFront(args, pw) 42 "moveTaskOutOfDesk" -> runMoveTaskOutOfDesk(args, pw) 43 "canCreateDesk" -> runCanCreateDesk(args, pw) 44 "getActiveDeskId" -> runGetActiveDeskId(args, pw) 45 else -> { 46 pw.println("Invalid command: ${args[0]}") 47 false 48 } 49 } 50 runMoveTaskToDesknull51 private fun runMoveTaskToDesk(args: Array<String>, pw: PrintWriter): Boolean { 52 if (args.size < 2) { 53 // First argument is the action name. 54 pw.println("Error: task id should be provided as arguments") 55 return false 56 } 57 val taskId = 58 try { 59 args[1].toInt() 60 } catch (e: NumberFormatException) { 61 pw.println("Error: task id should be an integer") 62 return false 63 } 64 if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { 65 return controller.moveTaskToDefaultDeskAndActivate(taskId, transitionSource = UNKNOWN) 66 } 67 if (args.size < 3) { 68 pw.println("Error: desk id should be provided as arguments") 69 return false 70 } 71 val deskId = 72 try { 73 args[2].toInt() 74 } catch (e: NumberFormatException) { 75 pw.println("Error: desk id should be an integer") 76 return false 77 } 78 controller.moveTaskToDesk(taskId = taskId, deskId = deskId, transitionSource = UNKNOWN) 79 pw.println("Not implemented.") 80 return true 81 } 82 runMoveToNextDisplaynull83 private fun runMoveToNextDisplay(args: Array<String>, pw: PrintWriter): Boolean { 84 var taskId = INVALID_TASK_ID 85 if (args.size < 2) { 86 taskId = focusTransitionObserver.globallyFocusedTaskId 87 } else { 88 try { 89 taskId = args[1].toInt() 90 } catch (e: NumberFormatException) { 91 pw.println("Error: task id should be an integer") 92 return false 93 } 94 } 95 if (taskId == INVALID_TASK_ID) { 96 pw.println("Error: no appropriate task found") 97 return false 98 } 99 controller.moveToNextDisplay(taskId) 100 return true 101 } 102 runCreateDesknull103 private fun runCreateDesk(args: Array<String>, pw: PrintWriter): Boolean { 104 if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { 105 pw.println("Not supported.") 106 return false 107 } 108 if (args.size < 2) { 109 // First argument is the action name. 110 pw.println("Error: desk id should be provided as arguments") 111 return false 112 } 113 val displayId = 114 try { 115 args[1].toInt() 116 } catch (e: NumberFormatException) { 117 pw.println("Error: display id should be an integer") 118 return false 119 } 120 controller.createDesk(displayId) 121 return true 122 } 123 runActivateDesknull124 private fun runActivateDesk(args: Array<String>, pw: PrintWriter): Boolean { 125 if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { 126 pw.println("Not supported.") 127 return false 128 } 129 if (args.size < 2) { 130 // First argument is the action name. 131 pw.println("Error: desk id should be provided as arguments") 132 return false 133 } 134 val deskId = 135 try { 136 args[1].toInt() 137 } catch (e: NumberFormatException) { 138 pw.println("Error: desk id should be an integer") 139 return false 140 } 141 controller.activateDesk(deskId) 142 return true 143 } 144 runRemoveDesknull145 private fun runRemoveDesk(args: Array<String>, pw: PrintWriter): Boolean { 146 if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { 147 pw.println("Not supported.") 148 return false 149 } 150 if (args.size < 2) { 151 // First argument is the action name. 152 pw.println("Error: desk id should be provided as arguments") 153 return false 154 } 155 val deskId = 156 try { 157 args[1].toInt() 158 } catch (e: NumberFormatException) { 159 pw.println("Error: desk id should be an integer") 160 return false 161 } 162 controller.removeDesk(deskId) 163 return true 164 } 165 runRemoveAllDesksnull166 private fun runRemoveAllDesks(args: Array<String>, pw: PrintWriter): Boolean { 167 if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { 168 pw.println("Not supported.") 169 return false 170 } 171 pw.println("Not implemented.") 172 return false 173 } 174 runMoveTaskToFrontnull175 private fun runMoveTaskToFront(args: Array<String>, pw: PrintWriter): Boolean { 176 if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { 177 pw.println("Not supported.") 178 return false 179 } 180 if (args.size < 2) { 181 // First argument is the action name. 182 pw.println("Error: task id should be provided as arguments") 183 return false 184 } 185 val taskId = 186 try { 187 args[1].toInt() 188 } catch (e: NumberFormatException) { 189 pw.println("Error: task id should be an integer") 190 return false 191 } 192 controller.moveTaskToFront( 193 /* taskId= */ taskId, 194 /* remoteTransition= */ null, 195 /* unminimizeReason= */ UnminimizeReason.UNKNOWN, 196 ) 197 return true 198 } 199 runMoveTaskOutOfDesknull200 private fun runMoveTaskOutOfDesk(args: Array<String>, pw: PrintWriter): Boolean { 201 if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { 202 pw.println("Not supported.") 203 return false 204 } 205 if (args.size < 2) { 206 // First argument is the action name. 207 pw.println("Error: task id should be provided as arguments") 208 return false 209 } 210 val taskId = 211 try { 212 args[1].toInt() 213 } catch (e: NumberFormatException) { 214 pw.println("Error: task id should be an integer") 215 return false 216 } 217 controller.moveToFullscreen(taskId, transitionSource = UNKNOWN) 218 return true 219 } 220 runCanCreateDesknull221 private fun runCanCreateDesk(args: Array<String>, pw: PrintWriter): Boolean { 222 if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { 223 pw.println("Not supported.") 224 return false 225 } 226 val displayId = 227 try { 228 args[1].toInt() 229 } catch (e: NumberFormatException) { 230 pw.println("Error: display id should be an integer") 231 return false 232 } 233 pw.println("Not implemented.") 234 return false 235 } 236 runGetActiveDeskIdnull237 private fun runGetActiveDeskId(args: Array<String>, pw: PrintWriter): Boolean { 238 if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { 239 pw.println("Not supported.") 240 return false 241 } 242 if (args.size < 2) { 243 // First argument is the action name. 244 pw.println("Error: task id should be provided as arguments") 245 return false 246 } 247 val displayId = 248 try { 249 args[1].toInt() 250 } catch (e: NumberFormatException) { 251 pw.println("Error: display id should be an integer") 252 return false 253 } 254 pw.println("Not implemented.") 255 return false 256 } 257 printShellCommandHelpnull258 override fun printShellCommandHelp(pw: PrintWriter, prefix: String) { 259 if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { 260 pw.println("$prefix moveTaskToDesk <taskId> ") 261 pw.println("$prefix Move a task with given id to desktop mode.") 262 pw.println("$prefix moveToNextDisplay <taskId> ") 263 pw.println("$prefix Move a task with given id to next display.") 264 return 265 } 266 pw.println("$prefix moveTaskToDesk <taskId> <deskId>") 267 pw.println("$prefix Move a task with given id to the given desk and activate it.") 268 pw.println("$prefix moveToNextDisplay <taskId>") 269 pw.println("$prefix Move a task with given id to next display.") 270 pw.println("$prefix createDesk <displayId>") 271 pw.println("$prefix Creates a desk on the given display.") 272 pw.println("$prefix activateDesk <deskId>") 273 pw.println("$prefix Activates the given desk.") 274 pw.println("$prefix removeDesk <deskId> ") 275 pw.println("$prefix Removes the given desk and all of its windows.") 276 pw.println("$prefix removeAllDesks") 277 pw.println("$prefix Removes all the desks and their windows across all displays") 278 pw.println("$prefix moveTaskToFront <taskId>") 279 pw.println("$prefix Moves a task in front of its siblings.") 280 pw.println("$prefix moveTaskOutOfDesk <taskId>") 281 pw.println("$prefix Moves the given desktop task out of the desk into fullscreen mode.") 282 pw.println("$prefix canCreateDesk <displayId>") 283 pw.println("$prefix Whether creating a new desk in the given display is allowed.") 284 pw.println("$prefix getActivateDeskId <displayId>") 285 pw.println("$prefix Print the id of the active desk in the given display.") 286 } 287 } 288