blob: b1b3957c0e8432eb5e3032ca6925c90d3e2fbeff [file] [log] [blame]
Elliott Hughes476b36e2018-04-03 13:42:18 -07001# /* 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() {
Jim Tang5e60e6d2018-06-19 19:11:48 +080019 if ! check_type "$1" >/dev/null; then
Elliott Hughes476b36e2018-04-03 13:42:18 -070020 return
21 fi
22
Jim Tang5e60e6d2018-06-19 19:11:48 +080023 if check_type _init_completion >/dev/null; then
Elliott Hughes476b36e2018-04-03 13:42:18 -070024 _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.
Jim Tang5e60e6d2018-06-19 19:11:48 +0800438 if [[ $(check_type compopt) == "builtin" ]]; then
Elliott Hughes476b36e2018-04-03 13:42:18 -0700439 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.
Jim Tang5e60e6d2018-06-19 19:11:48 +0800454 if [[ $(check_type compopt) == "builtin" ]]; then
Elliott Hughes476b36e2018-04-03 13:42:18 -0700455 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
Jim Tang5e60e6d2018-06-19 19:11:48 +0800495if [[ $(check_type compopt) == "builtin" ]]; then
Elliott Hughes476b36e2018-04-03 13:42:18 -0700496 complete -F _adb adb
497else
498 complete -o nospace -F _adb adb
499fi