• 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
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