• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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