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 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 *) 45 if [[ $where == OPT_SERIAL ]]; then 46 where=OPT_SERIAL_ARG 47 serial=${cur} 48 else 49 where=COMMAND 50 break 51 fi 52 ;; 53 esac 54 done 55 56 if [[ $where == COMMAND && $i -ge $COMP_CWORD ]]; then 57 where=OPTIONS 58 fi 59 60 OPTIONS="-d -e -s -p" 61 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" 62 63 case $where in 64 OPTIONS|OPT_SERIAL|OPT_PATH) 65 COMPREPLY=( $(compgen -W "$OPTIONS $COMMAND" -- "$cur") ) 66 ;; 67 OPT_SERIAL_ARG) 68 local devices=$(command adb devices 2> /dev/null | grep -v "List of devices" | awk '{ print $1 }') 69 COMPREPLY=( $(compgen -W "${devices}" -- ${cur}) ) 70 ;; 71 COMMAND) 72 if [[ $i -eq $COMP_CWORD ]]; then 73 COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") ) 74 else 75 i=$((i+1)) 76 case "${cur}" in 77 install) 78 _adb_cmd_install "$serial" $i 79 ;; 80 sideload) 81 _adb_cmd_sideload "$serial" $i 82 ;; 83 pull) 84 _adb_cmd_pull "$serial" $i 85 ;; 86 push) 87 _adb_cmd_push "$serial" $i 88 ;; 89 reboot) 90 if [[ $COMP_CWORD == $i ]]; then 91 args="bootloader recovery" 92 COMPREPLY=( $(compgen -W "${args}" -- "${COMP_WORDS[i]}") ) 93 fi 94 ;; 95 shell) 96 _adb_cmd_shell "$serial" $i 97 ;; 98 uninstall) 99 _adb_cmd_uninstall "$serial" $i 100 ;; 101 esac 102 fi 103 ;; 104 esac 105 106 return 0 107} 108 109_adb_cmd_install() { 110 local serial i cur where 111 112 serial=$1 113 i=$2 114 115 where=OPTIONS 116 for ((; i <= COMP_CWORD; i++)); do 117 cur="${COMP_WORDS[i]}" 118 case "${cur}" in 119 -*) 120 where=OPTIONS 121 ;; 122 *) 123 where=FILE 124 break 125 ;; 126 esac 127 done 128 129 cur="${COMP_WORDS[COMP_CWORD]}" 130 if [[ $where == OPTIONS ]]; then 131 COMPREPLY=( $(compgen -W "-d -l -r -s" -- "${cur}") ) 132 return 133 fi 134 135 _adb_util_complete_local_file "${cur}" '!*.apk' 136} 137 138_adb_cmd_sideload() { 139 local serial i cur 140 141 serial=$1 142 i=$2 143 144 cur="${COMP_WORDS[COMP_CWORD]}" 145 146 _adb_util_complete_local_file "${cur}" '!*.zip' 147} 148 149_adb_cmd_push() { 150 local serial IFS=$'\n' i cur 151 152 serial=$1 153 i=$2 154 155 cur="${COMP_WORDS[COMP_CWORD]}" 156 157 if [[ $COMP_CWORD == $i ]]; then 158 _adb_util_complete_local_file "${cur}" 159 elif [[ $COMP_CWORD == $(($i+1)) ]]; then 160 if [ "${cur}" == "" ]; then 161 cur="/" 162 fi 163 _adb_util_list_files $serial "${cur}" 164 fi 165} 166 167_adb_cmd_pull() { 168 local serial IFS=$'\n' i cur 169 170 serial=$1 171 i=$2 172 173 cur="${COMP_WORDS[COMP_CWORD]}" 174 175 if [[ $COMP_CWORD == $i ]]; then 176 if [ "${cur}" == "" ]; then 177 cur="/" 178 fi 179 _adb_util_list_files $serial "${cur}" 180 elif [[ $COMP_CWORD == $(($i+1)) ]]; then 181 _adb_util_complete_local_file "${cur}" 182 fi 183} 184 185_adb_cmd_shell() { 186 local serial IFS=$'\n' i cur 187 local -a args 188 189 serial=$1 190 i=$2 191 192 cur="${COMP_WORDS[i]}" 193 if [ "$serial" != "none" ]; then 194 args=(-s $serial) 195 fi 196 197 if [[ $i -eq $COMP_CWORD && ${cur:0:1} != "/" ]]; then 198 paths=$(command adb ${args[@]} shell echo '$'PATH 2> /dev/null | tr -d '\r' | tr : '\n') 199 COMMAND=$(command adb ${args[@]} shell ls $paths '2>' /dev/null | tr -d '\r' | { 200 while read -r tmp; do 201 command=${tmp##*/} 202 printf '%s\n' "$command" 203 done 204 }) 205 COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") ) 206 return 0 207 fi 208 209 i=$((i+1)) 210 case "$cur" in 211 ls) 212 _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" 213 ;; 214 cat) 215 _adb_shell_file_command $serial $i "-h -e -t -u -v" 216 ;; 217 dumpsys) 218 _adb_cmd_shell_dumpsys "$serial" $i 219 ;; 220 am) 221 _adb_cmd_shell_am "$serial" $i 222 ;; 223 pm) 224 _adb_cmd_shell_pm "$serial" $i 225 ;; 226 /*) 227 _adb_util_list_files $serial "$cur" 228 ;; 229 *) 230 COMPREPLY=( ) 231 ;; 232 esac 233 234 return 0 235} 236 237_adb_cmd_shell_dumpsys() { 238 local serial i cur 239 local -a args 240 local candidates 241 242 unset IFS 243 244 serial=$1 245 i=$2 246 247 if [ "$serial" != "none" ]; then 248 args=(-s $serial) 249 fi 250 251 if (( $i == $COMP_CWORD )) ; then 252 cur="${COMP_WORDS[COMP_CWORD]}" 253 # First line is a header, so need "1d". 254 candidates=$(command adb ${args[@]} shell dumpsys -l 2> /dev/null | sed -e '1d;s/^ *//' | tr -d '\r') 255 candidates="-l $candidates" 256 COMPREPLY=( $(compgen -W "$candidates" -- "$cur") ) 257 return 0 258 fi 259 260 COMPREPLY=( ) 261 return 0 262} 263 264_adb_cmd_shell_am() { 265 local serial i cur 266 local candidates 267 268 unset IFS 269 270 serial=$1 271 i=$2 272 273 if (( $i == $COMP_CWORD )) ; then 274 cur="${COMP_WORDS[COMP_CWORD]}" 275 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" 276 COMPREPLY=( $(compgen -W "$candidates" -- "$cur") ) 277 return 0 278 fi 279 280 COMPREPLY=( ) 281 return 0 282} 283 284 285_adb_cmd_shell_pm() { 286 local serial i cur 287 local candidates 288 289 unset IFS 290 291 serial=$1 292 i=$2 293 294 if (( $i == $COMP_CWORD )) ; then 295 cur="${COMP_WORDS[COMP_CWORD]}" 296 candidates="-l -lf -p clear create-user default-state disable" 297 candidates+=" disable-until-used disable-user dump enable" 298 candidates+=" get-app-link get-install-location get-max-users" 299 candidates+=" get-max-running-users grant hide install" 300 candidates+=" install-abandon install-commit install-create" 301 candidates+=" install-write list move-package" 302 candidates+=" move-primary-storage path remove-user" 303 candidates+=" reset-permissions revoke set-app-link" 304 candidates+=" set-installer set-install-location" 305 candidates+=" set-permission-enforced trim-caches unhide" 306 candidates+=" uninstall" 307 COMPREPLY=( $(compgen -W "$candidates" -- "$cur") ) 308 return 0 309 fi 310 311 if (( $i + 1 == $COMP_CWORD )) && [[ "${COMP_WORDS[COMP_CWORD -1]}" == "list" ]] ; then 312 cur="${COMP_WORDS[COMP_CWORD]}" 313 candidates="packages permission-groups permissions instrumentation features libraries users" 314 COMPREPLY=( $(compgen -W "$candidates" -- "$cur") ) 315 return 0 316 fi 317 318 COMPREPLY=( ) 319 return 0 320} 321 322_adb_cmd_uninstall() { 323 local serial i where cur packages 324 325 serial=$1 326 i=$2 327 if [ "$serial" != "none" ]; then 328 args=(-s $serial) 329 fi 330 331 where=OPTIONS 332 for ((; i <= COMP_CWORD; i++)); do 333 cur="${COMP_WORDS[i]}" 334 case "${cur}" in 335 -*) 336 where=OPTIONS 337 ;; 338 *) 339 where=FILE 340 break 341 ;; 342 esac 343 done 344 345 cur="${COMP_WORDS[COMP_CWORD]}" 346 if [[ $where == OPTIONS ]]; then 347 COMPREPLY=( $(compgen -W "-k" -- "${cur}") ) 348 fi 349 350 packages="$( 351 command adb ${args[@]} shell pm list packages '2>' /dev/null 2> /dev/null | tr -d '\r' | { 352 while read -r tmp; do 353 local package=${tmp#package:} 354 echo -n "${package} " 355 done 356 } 357 )" 358 359 COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "${packages}" -- "${cur}") ) 360} 361 362_adb_shell_file_command() { 363 local serial i cur file options 364 local -a args 365 366 serial=$1 367 i=$2 368 if [ "$serial" != "none" ]; then 369 args=(-s $serial) 370 fi 371 options=$3 372 373 where=OPTIONS 374 for ((; i <= COMP_CWORD; i++)); do 375 cur="${COMP_WORDS[i]}" 376 case "${cur}" in 377 -*) 378 where=OPTIONS 379 ;; 380 *) 381 where=FILE 382 break 383 ;; 384 esac 385 done 386 387 file="${COMP_WORDS[COMP_CWORD]}" 388 if [[ ${file} == "" ]]; then 389 file="/" 390 fi 391 392 case $where in 393 OPTIONS) 394 unset IFS 395 COMPREPLY=( $(compgen -W "$options" -- "$cur") ) 396 ;; 397 FILE) 398 _adb_util_list_files $serial "$file" 399 ;; 400 esac 401 402 return 0 403} 404 405_adb_util_list_files() { 406 local serial dir IFS=$'\n' 407 local -a toks 408 local -a args 409 410 serial="$1" 411 file="$2" 412 413 if [ "$serial" != "none" ]; then 414 args=(-s $serial) 415 fi 416 417 if [[ $( command adb ${args[@]} shell ls -dF / '2>/dev/null' | tr -d '\r' ) == "d /" ]] ; then 418 toks=( ${toks[@]-} $( 419 command adb ${args[@]} shell ls -dF ${file}"*" '2>' /dev/null 2> /dev/null | tr -d '\r' | { 420 while read -r tmp; do 421 filetype=${tmp%% *} 422 filename=${tmp:${#filetype}+1} 423 if [[ ${filetype:${#filetype}-1:1} == d ]]; then 424 printf '%s/\n' "$filename" 425 else 426 printf '%s\n' "$filename" 427 fi 428 done 429 } 430 )) 431 else 432 toks=( ${toks[@]-} $( 433 command adb ${args[@]} shell ls -dp ${file}"*" '2>/dev/null' 2> /dev/null | tr -d '\r' 434 )) 435 fi 436 437 # Since we're probably doing file completion here, don't add a space after. 438 if [[ $(check_type compopt) == "builtin" ]]; then 439 compopt -o nospace 440 fi 441 442 COMPREPLY=( ${COMPREPLY[@]:-} "${toks[@]}" ) 443} 444 445_adb_util_complete_local_file() 446{ 447 local file xspec i j IFS=$'\n' 448 local -a dirs files 449 450 file=$1 451 xspec=$2 452 453 # Since we're probably doing file completion here, don't add a space after. 454 if [[ $(check_type compopt) == "builtin" ]]; then 455 compopt -o plusdirs 456 if [[ "${xspec}" == "" ]]; then 457 COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") ) 458 else 459 compopt +o filenames 460 COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") ) 461 fi 462 else 463 # Work-around for shells with no compopt 464 465 dirs=( $(compgen -d -- "${cur}" ) ) 466 467 if [[ "${xspec}" == "" ]]; then 468 files=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") ) 469 else 470 files=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") ) 471 fi 472 473 COMPREPLY=( $( 474 for i in "${files[@]}"; do 475 local skip= 476 for j in "${dirs[@]}"; do 477 if [[ $i == $j ]]; then 478 skip=1 479 break 480 fi 481 done 482 [[ -n $skip ]] || printf "%s\n" "$i" 483 done 484 )) 485 486 COMPREPLY=( ${COMPREPLY[@]:-} $( 487 for i in "${dirs[@]}"; do 488 printf "%s/\n" "$i" 489 done 490 )) 491 fi 492} 493 494 495if [[ $(check_type compopt) == "builtin" ]]; then 496 complete -F _adb adb 497else 498 complete -o nospace -F _adb adb 499fi 500