blob: ad62eba390d78e033fc1853b35ca4617a889312a [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
Woody Lin3ae3cec2022-08-26 13:29:05 +080027 local where i cur serial state transport
Elliott Hughes476b36e2018-04-03 13:42:18 -070028 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 ;;
Woody Lin3ae3cec2022-08-26 13:29:05 +080044 wait-for-*)
45 where=OPTIONS
46 ;;
Elliott Hughes476b36e2018-04-03 13:42:18 -070047 *)
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
Woody Lin3ae3cec2022-08-26 13:29:05 +080066 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
Elliott Hughes476b36e2018-04-03 13:42:18 -070075 case $where in
76 OPTIONS|OPT_SERIAL|OPT_PATH)
77 COMPREPLY=( $(compgen -W "$OPTIONS $COMMAND" -- "$cur") )
78 ;;
79 OPT_SERIAL_ARG)
Inseob Kim0e048452023-01-31 14:03:10 +090080 _adb_devices
Elliott Hughes476b36e2018-04-03 13:42:18 -070081 ;;
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
Inseob Kim0e048452023-01-31 14:03:10 +090088 disconnect)
89 _adb_devices
90 ;;
Elliott Hughes476b36e2018-04-03 13:42:18 -070091 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
Inseob Kim0e048452023-01-31 14:03:10 +0900123_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
Elliott Hughes476b36e2018-04-03 13:42:18 -0700129_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.
Jim Tang5e60e6d2018-06-19 19:11:48 +0800458 if [[ $(check_type compopt) == "builtin" ]]; then
Elliott Hughes476b36e2018-04-03 13:42:18 -0700459 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.
Jim Tang5e60e6d2018-06-19 19:11:48 +0800474 if [[ $(check_type compopt) == "builtin" ]]; then
Elliott Hughes476b36e2018-04-03 13:42:18 -0700475 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
Jim Tang5e60e6d2018-06-19 19:11:48 +0800515if [[ $(check_type compopt) == "builtin" ]]; then
Elliott Hughes476b36e2018-04-03 13:42:18 -0700516 complete -F _adb adb
517else
518 complete -o nospace -F _adb adb
519fi