1# /* vim: set ai ts=4 ft=sh: */ 2# 3# Copyright 2011, The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18_adb() { 19 if ! check_type "$1" >/dev/null; then 20 return 21 fi 22 23 if check_type _init_completion >/dev/null; then 24 _init_completion || return 25 fi 26 27 local where i cur serial state transport 28 COMPREPLY=() 29 30 serial="${ANDROID_SERIAL:-none}" 31 where=OPTIONS 32 for ((i=1; i <= COMP_CWORD; i++)); do 33 cur="${COMP_WORDS[i]}" 34 case "${cur}" in 35 -s) 36 where=OPT_SERIAL 37 ;; 38 -p) 39 where=OPT_PATH 40 ;; 41 -*) 42 where=OPTIONS 43 ;; 44 wait-for-*) 45 where=OPTIONS 46 ;; 47 *) 48 if [[ $where == OPT_SERIAL ]]; then 49 where=OPT_SERIAL_ARG 50 serial=${cur} 51 else 52 where=COMMAND 53 break 54 fi 55 ;; 56 esac 57 done 58 59 if [[ $where == COMMAND && $i -ge $COMP_CWORD ]]; then 60 where=OPTIONS 61 fi 62 63 OPTIONS="-d -e -s -p" 64 COMMAND="devices connect disconnect push pull sync shell emu logcat lolcat forward jdwp install uninstall bugreport help version start-server kill-server get-state get-serialno status-window remount reboot reboot-bootloader root usb tcpip disable-verity" 65 66 for state in device recovery rescue sideload bootloader disconnect ; do 67 for transport in -usb -local -any "" ; do 68 WAIT_COMMAND=wait-for${transport}-${state} 69 if [[ -n "${cur}" && $WAIT_COMMAND == "${cur}"* ]] ; then 70 COMMAND+=" $WAIT_COMMAND" 71 fi 72 done 73 done 74 75 case $where in 76 OPTIONS|OPT_SERIAL|OPT_PATH) 77 COMPREPLY=( $(compgen -W "$OPTIONS $COMMAND" -- "$cur") ) 78 ;; 79 OPT_SERIAL_ARG) 80 _adb_devices 81 ;; 82 COMMAND) 83 if [[ $i -eq $COMP_CWORD ]]; then 84 COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") ) 85 else 86 i=$((i+1)) 87 case "${cur}" in 88 disconnect) 89 _adb_devices 90 ;; 91 install) 92 _adb_cmd_install "$serial" $i 93 ;; 94 sideload) 95 _adb_cmd_sideload "$serial" $i 96 ;; 97 pull) 98 _adb_cmd_pull "$serial" $i 99 ;; 100 push) 101 _adb_cmd_push "$serial" $i 102 ;; 103 reboot) 104 if [[ $COMP_CWORD == $i ]]; then 105 args="bootloader recovery" 106 COMPREPLY=( $(compgen -W "${args}" -- "${COMP_WORDS[i]}") ) 107 fi 108 ;; 109 shell) 110 _adb_cmd_shell "$serial" $i 111 ;; 112 uninstall) 113 _adb_cmd_uninstall "$serial" $i 114 ;; 115 esac 116 fi 117 ;; 118 esac 119 120 return 0 121} 122 123_adb_devices() { 124 local devices=$(command adb devices 2> /dev/null | grep -v "List of devices" | awk '{ print $1 }') 125 COMPREPLY=( $(compgen -W "${devices}" -- ${cur}) ) 126 return 127} 128 129_adb_cmd_install() { 130 local serial i cur where 131 132 serial=$1 133 i=$2 134 135 where=OPTIONS 136 for ((; i <= COMP_CWORD; i++)); do 137 cur="${COMP_WORDS[i]}" 138 case "${cur}" in 139 -*) 140 where=OPTIONS 141 ;; 142 *) 143 where=FILE 144 break 145 ;; 146 esac 147 done 148 149 cur="${COMP_WORDS[COMP_CWORD]}" 150 if [[ $where == OPTIONS ]]; then 151 COMPREPLY=( $(compgen -W "-d -l -r -s" -- "${cur}") ) 152 return 153 fi 154 155 _adb_util_complete_local_file "${cur}" '!*.apk' 156} 157 158_adb_cmd_sideload() { 159 local serial i cur 160 161 serial=$1 162 i=$2 163 164 cur="${COMP_WORDS[COMP_CWORD]}" 165 166 _adb_util_complete_local_file "${cur}" '!*.zip' 167} 168 169_adb_cmd_push() { 170 local serial IFS=$'\n' i cur 171 172 serial=$1 173 i=$2 174 175 cur="${COMP_WORDS[COMP_CWORD]}" 176 177 if [[ $COMP_CWORD == $i ]]; then 178 _adb_util_complete_local_file "${cur}" 179 elif [[ $COMP_CWORD == $(($i+1)) ]]; then 180 if [ "${cur}" == "" ]; then 181 cur="/" 182 fi 183 _adb_util_list_files $serial "${cur}" 184 fi 185} 186 187_adb_cmd_pull() { 188 local serial IFS=$'\n' i cur 189 190 serial=$1 191 i=$2 192 193 cur="${COMP_WORDS[COMP_CWORD]}" 194 195 if [[ $COMP_CWORD == $i ]]; then 196 if [ "${cur}" == "" ]; then 197 cur="/" 198 fi 199 _adb_util_list_files $serial "${cur}" 200 elif [[ $COMP_CWORD == $(($i+1)) ]]; then 201 _adb_util_complete_local_file "${cur}" 202 fi 203} 204 205_adb_cmd_shell() { 206 local serial IFS=$'\n' i cur 207 local -a args 208 209 serial=$1 210 i=$2 211 212 cur="${COMP_WORDS[i]}" 213 if [ "$serial" != "none" ]; then 214 args=(-s $serial) 215 fi 216 217 if [[ $i -eq $COMP_CWORD && ${cur:0:1} != "/" ]]; then 218 paths=$(command adb ${args[@]} shell echo '$'PATH 2> /dev/null | tr -d '\r' | tr : '\n') 219 COMMAND=$(command adb ${args[@]} shell ls $paths '2>' /dev/null | tr -d '\r' | { 220 while read -r tmp; do 221 command=${tmp##*/} 222 printf '%s\n' "$command" 223 done 224 }) 225 COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") ) 226 return 0 227 fi 228 229 i=$((i+1)) 230 case "$cur" in 231 ls) 232 _adb_shell_file_command $serial $i "--color -A -C -F -H -L -R -S -Z -a -c -d -f -h -i -k -l -m -n -p -q -r -s -t -u -x -1" 233 ;; 234 cat) 235 _adb_shell_file_command $serial $i "-h -e -t -u -v" 236 ;; 237 dumpsys) 238 _adb_cmd_shell_dumpsys "$serial" $i 239 ;; 240 am) 241 _adb_cmd_shell_am "$serial" $i 242 ;; 243 pm) 244 _adb_cmd_shell_pm "$serial" $i 245 ;; 246 /*) 247 _adb_util_list_files $serial "$cur" 248 ;; 249 *) 250 COMPREPLY=( ) 251 ;; 252 esac 253 254 return 0 255} 256 257_adb_cmd_shell_dumpsys() { 258 local serial i cur 259 local -a args 260 local candidates 261 262 unset IFS 263 264 serial=$1 265 i=$2 266 267 if [ "$serial" != "none" ]; then 268 args=(-s $serial) 269 fi 270 271 if (( $i == $COMP_CWORD )) ; then 272 cur="${COMP_WORDS[COMP_CWORD]}" 273 # First line is a header, so need "1d". 274 candidates=$(command adb ${args[@]} shell dumpsys -l 2> /dev/null | sed -e '1d;s/^ *//' | tr -d '\r') 275 candidates="-l $candidates" 276 COMPREPLY=( $(compgen -W "$candidates" -- "$cur") ) 277 return 0 278 fi 279 280 COMPREPLY=( ) 281 return 0 282} 283 284_adb_cmd_shell_am() { 285 local serial i cur 286 local candidates 287 288 unset IFS 289 290 serial=$1 291 i=$2 292 293 if (( $i == $COMP_CWORD )) ; then 294 cur="${COMP_WORDS[COMP_CWORD]}" 295 candidates="broadcast clear-debug-app clear-watch-heap dumpheap force-stop get-config get-inactive hang idle-maintenance instrument kill kill-all monitor package-importance profile restart screen-compat send-trim-memory set-debug-app set-inactive set-watch-heap stack start startservice start-user stopservice stop-user suppress-resize-config-changes switch-user task to-app-uri to-intent-uri to-uri" 296 COMPREPLY=( $(compgen -W "$candidates" -- "$cur") ) 297 return 0 298 fi 299 300 COMPREPLY=( ) 301 return 0 302} 303 304 305_adb_cmd_shell_pm() { 306 local serial i cur 307 local candidates 308 309 unset IFS 310 311 serial=$1 312 i=$2 313 314 if (( $i == $COMP_CWORD )) ; then 315 cur="${COMP_WORDS[COMP_CWORD]}" 316 candidates="-l -lf -p clear create-user default-state disable" 317 candidates+=" disable-until-used disable-user dump enable" 318 candidates+=" get-app-link get-install-location get-max-users" 319 candidates+=" get-max-running-users grant hide install" 320 candidates+=" install-abandon install-commit install-create" 321 candidates+=" install-write list move-package" 322 candidates+=" move-primary-storage path remove-user" 323 candidates+=" reset-permissions revoke set-app-link" 324 candidates+=" set-installer set-install-location" 325 candidates+=" set-permission-enforced trim-caches unhide" 326 candidates+=" uninstall" 327 COMPREPLY=( $(compgen -W "$candidates" -- "$cur") ) 328 return 0 329 fi 330 331 if (( $i + 1 == $COMP_CWORD )) && [[ "${COMP_WORDS[COMP_CWORD -1]}" == "list" ]] ; then 332 cur="${COMP_WORDS[COMP_CWORD]}" 333 candidates="packages permission-groups permissions instrumentation features libraries users" 334 COMPREPLY=( $(compgen -W "$candidates" -- "$cur") ) 335 return 0 336 fi 337 338 COMPREPLY=( ) 339 return 0 340} 341 342_adb_cmd_uninstall() { 343 local serial i where cur packages 344 345 serial=$1 346 i=$2 347 if [ "$serial" != "none" ]; then 348 args=(-s $serial) 349 fi 350 351 where=OPTIONS 352 for ((; i <= COMP_CWORD; i++)); do 353 cur="${COMP_WORDS[i]}" 354 case "${cur}" in 355 -*) 356 where=OPTIONS 357 ;; 358 *) 359 where=FILE 360 break 361 ;; 362 esac 363 done 364 365 cur="${COMP_WORDS[COMP_CWORD]}" 366 if [[ $where == OPTIONS ]]; then 367 COMPREPLY=( $(compgen -W "-k" -- "${cur}") ) 368 fi 369 370 packages="$( 371 command adb ${args[@]} shell pm list packages '2>' /dev/null 2> /dev/null | tr -d '\r' | { 372 while read -r tmp; do 373 local package=${tmp#package:} 374 echo -n "${package} " 375 done 376 } 377 )" 378 379 COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "${packages}" -- "${cur}") ) 380} 381 382_adb_shell_file_command() { 383 local serial i cur file options 384 local -a args 385 386 serial=$1 387 i=$2 388 if [ "$serial" != "none" ]; then 389 args=(-s $serial) 390 fi 391 options=$3 392 393 where=OPTIONS 394 for ((; i <= COMP_CWORD; i++)); do 395 cur="${COMP_WORDS[i]}" 396 case "${cur}" in 397 -*) 398 where=OPTIONS 399 ;; 400 *) 401 where=FILE 402 break 403 ;; 404 esac 405 done 406 407 file="${COMP_WORDS[COMP_CWORD]}" 408 if [[ ${file} == "" ]]; then 409 file="/" 410 fi 411 412 case $where in 413 OPTIONS) 414 unset IFS 415 COMPREPLY=( $(compgen -W "$options" -- "$cur") ) 416 ;; 417 FILE) 418 _adb_util_list_files $serial "$file" 419 ;; 420 esac 421 422 return 0 423} 424 425_adb_util_list_files() { 426 local serial dir IFS=$'\n' 427 local -a toks 428 local -a args 429 430 serial="$1" 431 file="$2" 432 433 if [ "$serial" != "none" ]; then 434 args=(-s $serial) 435 fi 436 437 if [[ $( command adb ${args[@]} shell ls -dF / '2>/dev/null' | tr -d '\r' ) == "d /" ]] ; then 438 toks=( ${toks[@]-} $( 439 command adb ${args[@]} shell ls -dF ${file}"*" '2>' /dev/null 2> /dev/null | tr -d '\r' | { 440 while read -r tmp; do 441 filetype=${tmp%% *} 442 filename=${tmp:${#filetype}+1} 443 if [[ ${filetype:${#filetype}-1:1} == d ]]; then 444 printf '%s/\n' "$filename" 445 else 446 printf '%s\n' "$filename" 447 fi 448 done 449 } 450 )) 451 else 452 toks=( ${toks[@]-} $( 453 command adb ${args[@]} shell ls -dp ${file}"*" '2>/dev/null' 2> /dev/null | tr -d '\r' 454 )) 455 fi 456 457 # Since we're probably doing file completion here, don't add a space after. 458 if [[ $(check_type compopt) == "builtin" ]]; then 459 compopt -o nospace 460 fi 461 462 COMPREPLY=( ${COMPREPLY[@]:-} "${toks[@]}" ) 463} 464 465_adb_util_complete_local_file() 466{ 467 local file xspec i j IFS=$'\n' 468 local -a dirs files 469 470 file=$1 471 xspec=$2 472 473 # Since we're probably doing file completion here, don't add a space after. 474 if [[ $(check_type compopt) == "builtin" ]]; then 475 compopt -o plusdirs 476 if [[ "${xspec}" == "" ]]; then 477 COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") ) 478 else 479 compopt +o filenames 480 COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") ) 481 fi 482 else 483 # Work-around for shells with no compopt 484 485 dirs=( $(compgen -d -- "${cur}" ) ) 486 487 if [[ "${xspec}" == "" ]]; then 488 files=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") ) 489 else 490 files=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") ) 491 fi 492 493 COMPREPLY=( $( 494 for i in "${files[@]}"; do 495 local skip= 496 for j in "${dirs[@]}"; do 497 if [[ $i == $j ]]; then 498 skip=1 499 break 500 fi 501 done 502 [[ -n $skip ]] || printf "%s\n" "$i" 503 done 504 )) 505 506 COMPREPLY=( ${COMPREPLY[@]:-} $( 507 for i in "${dirs[@]}"; do 508 printf "%s/\n" "$i" 509 done 510 )) 511 fi 512} 513 514 515if [[ $(check_type compopt) == "builtin" ]]; then 516 complete -F _adb adb 517else 518 complete -o nospace -F _adb adb 519fi 520