• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2022 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15# gettop is duplicated here and in shell_utils.mk, because it's difficult
16# to find shell_utils.make without it for all the novel ways this file can be
17# sourced.  Other common functions should only be in one place or the other.
18function _gettop_once
19{
20    local TOPFILE=build/make/core/envsetup.mk
21    if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ] ; then
22        # The following circumlocution ensures we remove symlinks from TOP.
23        (cd "$TOP"; PWD= /bin/pwd)
24    else
25        if [ -f $TOPFILE ] ; then
26            # The following circumlocution (repeated below as well) ensures
27            # that we record the true directory name and not one that is
28            # faked up with symlink names.
29            PWD= /bin/pwd
30        else
31            local HERE=$PWD
32            local T=
33            while [ \( ! \( -f $TOPFILE \) \) -a \( "$PWD" != "/" \) ]; do
34                \cd ..
35                T=`PWD= /bin/pwd -P`
36            done
37            \cd "$HERE"
38            if [ -f "$T/$TOPFILE" ]; then
39                echo "$T"
40            fi
41        fi
42    fi
43}
44T=$(_gettop_once)
45if [ ! "$T" ]; then
46    echo "Couldn't locate the top of the tree. Always source build/envsetup.sh from the root of the tree." >&2
47    return 1
48fi
49IMPORTING_ENVSETUP=true source $T/build/make/shell_utils.sh
50
51
52# Help
53function hmm() {
54cat <<EOF
55
56Run "m help" for help with the build system itself.
57
58Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
59- lunch:      lunch <product_name>-<build_variant>
60              Selects <product_name> as the product to build, and <build_variant> as the variant to
61              build, and stores those selections in the environment to be read by subsequent
62              invocations of 'm' etc.
63- tapas:      tapas [<App1> <App2> ...] [arm|x86|arm64|x86_64] [eng|userdebug|user]
64              Sets up the build environment for building unbundled apps (APKs).
65- banchan:    banchan <module1> [<module2> ...] [arm|x86|arm64|x86_64|arm64_only|x86_64only] \
66                      [eng|userdebug|user]
67              Sets up the build environment for building unbundled modules (APEXes).
68- croot:      Changes directory to the top of the tree, or a subdirectory thereof.
69- m:          Makes from the top of the tree.
70- mm:         Builds and installs all of the modules in the current directory, and their
71              dependencies.
72- mmm:        Builds and installs all of the modules in the supplied directories, and their
73              dependencies.
74              To limit the modules being built use the syntax: mmm dir/:target1,target2.
75- mma:        Same as 'mm'
76- mmma:       Same as 'mmm'
77- provision:  Flash device with all required partitions. Options will be passed on to fastboot.
78- cgrep:      Greps on all local C/C++ files.
79- ggrep:      Greps on all local Gradle files.
80- gogrep:     Greps on all local Go files.
81- jgrep:      Greps on all local Java files.
82- jsongrep:   Greps on all local Json files.
83- ktgrep:     Greps on all local Kotlin files.
84- resgrep:    Greps on all local res/*.xml files.
85- mangrep:    Greps on all local AndroidManifest.xml files.
86- mgrep:      Greps on all local Makefiles and *.bp files.
87- owngrep:    Greps on all local OWNERS files.
88- rsgrep:     Greps on all local Rust files.
89- sepgrep:    Greps on all local sepolicy files.
90- sgrep:      Greps on all local source files.
91- tomlgrep:   Greps on all local Toml files.
92- pygrep:     Greps on all local Python files.
93- godir:      Go to the directory containing a file.
94- allmod:     List all modules.
95- gomod:      Go to the directory containing a module.
96- bmod:       Get the Bazel label of a Soong module if it is converted with bp2build.
97- pathmod:    Get the directory containing a module.
98- outmod:     Gets the location of a module's installed outputs with a certain extension.
99- dirmods:    Gets the modules defined in a given directory.
100- installmod: Adb installs a module's built APK.
101- refreshmod: Refresh list of modules for allmod/gomod/pathmod/outmod/installmod.
102- syswrite:   Remount partitions (e.g. system.img) as writable, rebooting if necessary.
103
104Environment options:
105- SANITIZE_HOST: Set to 'address' to use ASAN for all host modules.
106- ANDROID_QUIET_BUILD: set to 'true' to display only the essential messages.
107
108Look at the source to view more functions. The complete list is:
109EOF
110    local T=$(gettop)
111    local A=""
112    local i
113    for i in `cat $T/build/envsetup.sh | sed -n "/^[[:blank:]]*function /s/function \([a-z_]*\).*/\1/p" | sort | uniq`; do
114      A="$A $i"
115    done
116    echo $A
117}
118
119# Get all the build variables needed by this script in a single call to the build system.
120function build_build_var_cache()
121{
122    local T=$(gettop)
123    # Grep out the variable names from the script.
124    cached_vars=(`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/get_build_var/) print $(i+1)}' | sort -u | tr '\n' ' '`)
125    cached_abs_vars=(`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/get_abs_build_var/) print $(i+1)}' | sort -u | tr '\n' ' '`)
126    # Call the build system to dump the "<val>=<value>" pairs as a shell script.
127    build_dicts_script=`\builtin cd $T; build/soong/soong_ui.bash --dumpvars-mode \
128                        --vars="${cached_vars[*]}" \
129                        --abs-vars="${cached_abs_vars[*]}" \
130                        --var-prefix=var_cache_ \
131                        --abs-var-prefix=abs_var_cache_`
132    local ret=$?
133    if [ $ret -ne 0 ]
134    then
135        unset build_dicts_script
136        return $ret
137    fi
138    # Execute the script to store the "<val>=<value>" pairs as shell variables.
139    eval "$build_dicts_script"
140    ret=$?
141    unset build_dicts_script
142    if [ $ret -ne 0 ]
143    then
144        return $ret
145    fi
146    BUILD_VAR_CACHE_READY="true"
147}
148
149# Delete the build var cache, so that we can still call into the build system
150# to get build variables not listed in this script.
151function destroy_build_var_cache()
152{
153    unset BUILD_VAR_CACHE_READY
154    local v
155    for v in $cached_vars; do
156      unset var_cache_$v
157    done
158    unset cached_vars
159    for v in $cached_abs_vars; do
160      unset abs_var_cache_$v
161    done
162    unset cached_abs_vars
163}
164
165# Get the value of a build variable as an absolute path.
166function get_abs_build_var()
167{
168    if [ "$BUILD_VAR_CACHE_READY" = "true" ]
169    then
170        eval "echo \"\${abs_var_cache_$1}\""
171        return
172    fi
173
174    local T=$(gettop)
175    if [ ! "$T" ]; then
176        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
177        return
178    fi
179    (\cd $T; build/soong/soong_ui.bash --dumpvar-mode --abs $1)
180}
181
182# Get the exact value of a build variable.
183function get_build_var()
184{
185    if [ "$BUILD_VAR_CACHE_READY" = "true" ]
186    then
187        eval "echo \"\${var_cache_$1}\""
188        return 0
189    fi
190
191    local T=$(gettop)
192    if [ ! "$T" ]; then
193        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
194        return 1
195    fi
196    (\cd $T; build/soong/soong_ui.bash --dumpvar-mode $1)
197}
198
199# check to see if the supplied product is one we can build
200function check_product()
201{
202    local T=$(gettop)
203    if [ ! "$T" ]; then
204        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
205        return
206    fi
207        TARGET_PRODUCT=$1 \
208        TARGET_BUILD_VARIANT= \
209        TARGET_BUILD_TYPE= \
210        TARGET_BUILD_APPS= \
211        get_build_var TARGET_DEVICE > /dev/null
212    # hide successful answers, but allow the errors to show
213}
214
215VARIANT_CHOICES=(user userdebug eng)
216
217# check to see if the supplied variant is valid
218function check_variant()
219{
220    local v
221    for v in ${VARIANT_CHOICES[@]}
222    do
223        if [ "$v" = "$1" ]
224        then
225            return 0
226        fi
227    done
228    return 1
229}
230
231
232# Add directories to PATH that are dependent on the lunch target.
233# For directories that are not lunch-specific, add them in set_global_paths
234function set_lunch_paths()
235{
236    local T=$(gettop)
237    if [ ! "$T" ]; then
238        echo "Couldn't locate the top of the tree.  Try setting TOP."
239        return
240    fi
241
242    ##################################################################
243    #                                                                #
244    #              Read me before you modify this code               #
245    #                                                                #
246    #   This function sets ANDROID_LUNCH_BUILD_PATHS to what it is   #
247    #   adding to PATH, and the next time it is run, it removes that #
248    #   from PATH.  This is required so lunch can be run more than   #
249    #   once and still have working paths.                           #
250    #                                                                #
251    ##################################################################
252
253    # Note: on windows/cygwin, ANDROID_LUNCH_BUILD_PATHS will contain spaces
254    # due to "C:\Program Files" being in the path.
255
256    # Handle compat with the old ANDROID_BUILD_PATHS variable.
257    # TODO: Remove this after we think everyone has lunched again.
258    if [ -z "$ANDROID_LUNCH_BUILD_PATHS" -a -n "$ANDROID_BUILD_PATHS" ] ; then
259      ANDROID_LUNCH_BUILD_PATHS="$ANDROID_BUILD_PATHS"
260      ANDROID_BUILD_PATHS=
261    fi
262    if [ -n "$ANDROID_PRE_BUILD_PATHS" ] ; then
263        export PATH=${PATH/$ANDROID_PRE_BUILD_PATHS/}
264        # strip leading ':', if any
265        export PATH=${PATH/:%/}
266        ANDROID_PRE_BUILD_PATHS=
267    fi
268
269    # Out with the old...
270    if [ -n "$ANDROID_LUNCH_BUILD_PATHS" ] ; then
271        export PATH=${PATH/$ANDROID_LUNCH_BUILD_PATHS/}
272    fi
273
274    # And in with the new...
275    ANDROID_LUNCH_BUILD_PATHS=$(get_abs_build_var SOONG_HOST_OUT_EXECUTABLES)
276    ANDROID_LUNCH_BUILD_PATHS+=:$(get_abs_build_var HOST_OUT_EXECUTABLES)
277
278    # Append llvm binutils prebuilts path to ANDROID_LUNCH_BUILD_PATHS.
279    local ANDROID_LLVM_BINUTILS=$(get_abs_build_var ANDROID_CLANG_PREBUILTS)/llvm-binutils-stable
280    ANDROID_LUNCH_BUILD_PATHS+=:$ANDROID_LLVM_BINUTILS
281
282    # Set up ASAN_SYMBOLIZER_PATH for SANITIZE_HOST=address builds.
283    export ASAN_SYMBOLIZER_PATH=$ANDROID_LLVM_BINUTILS/llvm-symbolizer
284
285    # Append asuite prebuilts path to ANDROID_LUNCH_BUILD_PATHS.
286    local os_arch=$(get_build_var HOST_PREBUILT_TAG)
287    ANDROID_LUNCH_BUILD_PATHS+=:$T/prebuilts/asuite/acloud/$os_arch
288    ANDROID_LUNCH_BUILD_PATHS+=:$T/prebuilts/asuite/aidegen/$os_arch
289    ANDROID_LUNCH_BUILD_PATHS+=:$T/prebuilts/asuite/atest/$os_arch
290
291    export ANDROID_JAVA_HOME=$(get_abs_build_var ANDROID_JAVA_HOME)
292    export JAVA_HOME=$ANDROID_JAVA_HOME
293    export ANDROID_JAVA_TOOLCHAIN=$(get_abs_build_var ANDROID_JAVA_TOOLCHAIN)
294    ANDROID_LUNCH_BUILD_PATHS+=:$ANDROID_JAVA_TOOLCHAIN
295
296    # Fix up PYTHONPATH
297    if [ -n $ANDROID_PYTHONPATH ]; then
298        export PYTHONPATH=${PYTHONPATH//$ANDROID_PYTHONPATH/}
299    fi
300    # //development/python-packages contains both a pseudo-PYTHONPATH which
301    # mimics an already assembled venv, but also contains real Python packages
302    # that are not in that layout until they are installed. We can fake it for
303    # the latter type by adding the package source directories to the PYTHONPATH
304    # directly. For the former group, we only need to add the python-packages
305    # directory itself.
306    #
307    # This could be cleaned up by converting the remaining packages that are in
308    # the first category into a typical python source layout (that is, another
309    # layer of directory nesting) and automatically adding all subdirectories of
310    # python-packages to the PYTHONPATH instead of manually curating this. We
311    # can't convert the packages like adb to the other style because doing so
312    # would prevent exporting type info from those packages.
313    #
314    # http://b/266688086
315    export ANDROID_PYTHONPATH=$T/development/python-packages/adb:$T/development/python-packages:
316    if [ -n $VENDOR_PYTHONPATH ]; then
317        ANDROID_PYTHONPATH=$ANDROID_PYTHONPATH$VENDOR_PYTHONPATH
318    fi
319    export PYTHONPATH=$ANDROID_PYTHONPATH$PYTHONPATH
320
321    unset ANDROID_PRODUCT_OUT
322    export ANDROID_PRODUCT_OUT=$(get_abs_build_var PRODUCT_OUT)
323    export OUT=$ANDROID_PRODUCT_OUT
324
325    unset ANDROID_HOST_OUT
326    export ANDROID_HOST_OUT=$(get_abs_build_var HOST_OUT)
327
328    unset ANDROID_SOONG_HOST_OUT
329    export ANDROID_SOONG_HOST_OUT=$(get_abs_build_var SOONG_HOST_OUT)
330
331    unset ANDROID_HOST_OUT_TESTCASES
332    export ANDROID_HOST_OUT_TESTCASES=$(get_abs_build_var HOST_OUT_TESTCASES)
333
334    unset ANDROID_TARGET_OUT_TESTCASES
335    export ANDROID_TARGET_OUT_TESTCASES=$(get_abs_build_var TARGET_OUT_TESTCASES)
336
337    # Finally, set PATH
338    export PATH=$ANDROID_LUNCH_BUILD_PATHS:$PATH
339}
340
341# Add directories to PATH that are NOT dependent on the lunch target.
342# For directories that are lunch-specific, add them in set_lunch_paths
343function set_global_paths()
344{
345    local T=$(gettop)
346    if [ ! "$T" ]; then
347        echo "Couldn't locate the top of the tree.  Try setting TOP."
348        return
349    fi
350
351    ##################################################################
352    #                                                                #
353    #              Read me before you modify this code               #
354    #                                                                #
355    #   This function sets ANDROID_GLOBAL_BUILD_PATHS to what it is  #
356    #   adding to PATH, and the next time it is run, it removes that #
357    #   from PATH.  This is required so envsetup.sh can be sourced   #
358    #   more than once and still have working paths.                 #
359    #                                                                #
360    ##################################################################
361
362    # Out with the old...
363    if [ -n "$ANDROID_GLOBAL_BUILD_PATHS" ] ; then
364        export PATH=${PATH/$ANDROID_GLOBAL_BUILD_PATHS/}
365    fi
366
367    # And in with the new...
368    ANDROID_GLOBAL_BUILD_PATHS=$T/build/bazel/bin
369    ANDROID_GLOBAL_BUILD_PATHS+=:$T/development/scripts
370    ANDROID_GLOBAL_BUILD_PATHS+=:$T/prebuilts/devtools/tools
371
372    # add kernel specific binaries
373    if [ $(uname -s) = Linux ] ; then
374        ANDROID_GLOBAL_BUILD_PATHS+=:$T/prebuilts/misc/linux-x86/dtc
375        ANDROID_GLOBAL_BUILD_PATHS+=:$T/prebuilts/misc/linux-x86/libufdt
376    fi
377
378    # If prebuilts/android-emulator/<system>/ exists, prepend it to our PATH
379    # to ensure that the corresponding 'emulator' binaries are used.
380    case $(uname -s) in
381        Darwin)
382            ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/darwin-x86_64
383            ;;
384        Linux)
385            ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/linux-x86_64
386            ;;
387        *)
388            ANDROID_EMULATOR_PREBUILTS=
389            ;;
390    esac
391    if [ -n "$ANDROID_EMULATOR_PREBUILTS" -a -d "$ANDROID_EMULATOR_PREBUILTS" ]; then
392        ANDROID_GLOBAL_BUILD_PATHS+=:$ANDROID_EMULATOR_PREBUILTS
393        export ANDROID_EMULATOR_PREBUILTS
394    fi
395
396    # Finally, set PATH
397    export PATH=$ANDROID_GLOBAL_BUILD_PATHS:$PATH
398}
399
400function printconfig()
401{
402    local T=$(gettop)
403    if [ ! "$T" ]; then
404        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
405        return
406    fi
407    get_build_var report_config
408}
409
410function set_stuff_for_environment()
411{
412    set_lunch_paths
413    set_sequence_number
414
415    export ANDROID_BUILD_TOP=$(gettop)
416}
417
418function set_sequence_number()
419{
420    export BUILD_ENV_SEQUENCE_NUMBER=13
421}
422
423# Takes a command name, and check if it's in ENVSETUP_NO_COMPLETION or not.
424function should_add_completion() {
425    local cmd="$(basename $1| sed 's/_completion//' |sed 's/\.\(.*\)*sh$//')"
426    case :"$ENVSETUP_NO_COMPLETION": in
427        *:"$cmd":*)
428            return 1
429            ;;
430    esac
431    return 0
432}
433
434function addcompletions()
435{
436    local f=
437
438    # Keep us from trying to run in something that's neither bash nor zsh.
439    if [ -z "$BASH_VERSION" -a -z "$ZSH_VERSION" ]; then
440        return
441    fi
442
443    # Keep us from trying to run in bash that's too old.
444    if [ -n "$BASH_VERSION" -a ${BASH_VERSINFO[0]} -lt 3 ]; then
445        return
446    fi
447
448    local completion_files=(
449      packages/modules/adb/adb.bash
450      system/core/fastboot/fastboot.bash
451      tools/asuite/asuite.sh
452      prebuilts/bazel/common/bazel-complete.bash
453    )
454    # Completion can be disabled selectively to allow users to use non-standard completion.
455    # e.g.
456    # ENVSETUP_NO_COMPLETION=adb # -> disable adb completion
457    # ENVSETUP_NO_COMPLETION=adb:bit # -> disable adb and bit completion
458    local T=$(gettop)
459    for f in ${completion_files[*]}; do
460        f="$T/$f"
461        if [ ! -f "$f" ]; then
462          echo "Warning: completion file $f not found"
463        elif should_add_completion "$f"; then
464            . $f
465        fi
466    done
467
468    if should_add_completion bit ; then
469        complete -C "bit --tab" bit
470    fi
471    if [ -z "$ZSH_VERSION" ]; then
472        # Doesn't work in zsh.
473        complete -o nospace -F _croot croot
474        # TODO(b/244559459): Support b autocompletion for zsh
475        complete -F _bazel__complete -o nospace b
476    fi
477    complete -F _lunch lunch
478
479    complete -F _complete_android_module_names pathmod
480    complete -F _complete_android_module_names gomod
481    complete -F _complete_android_module_names outmod
482    complete -F _complete_android_module_names installmod
483    complete -F _complete_android_module_names bmod
484    complete -F _complete_android_module_names m
485}
486
487function multitree_lunch_help()
488{
489    echo "usage: lunch PRODUCT-VARIANT" 1>&2
490    echo "    Set up android build environment based on a product short name and variant" 1>&2
491    echo 1>&2
492    echo "lunch COMBO_FILE VARIANT" 1>&2
493    echo "    Set up android build environment based on a specific lunch combo file" 1>&2
494    echo "    and variant." 1>&2
495    echo 1>&2
496    echo "lunch --print [CONFIG]" 1>&2
497    echo "    Print the contents of a configuration.  If CONFIG is supplied, that config" 1>&2
498    echo "    will be flattened and printed.  If CONFIG is not supplied, the currently" 1>&2
499    echo "    selected config will be printed.  Returns 0 on success or nonzero on error." 1>&2
500    echo 1>&2
501    echo "lunch --list" 1>&2
502    echo "    List all possible combo files available in the current tree" 1>&2
503    echo 1>&2
504    echo "lunch --help" 1>&2
505    echo "lunch -h" 1>&2
506    echo "    Prints this message." 1>&2
507}
508
509function multitree_lunch()
510{
511    local code
512    local results
513    # Lunch must be run in the topdir, but this way we get a clear error
514    # message, instead of FileNotFound.
515    local T=$(multitree_gettop)
516    if [ -z "$T" ]; then
517      _multitree_lunch_error
518      return 1
519    fi
520    if $(echo "$1" | grep -q '^-') ; then
521        # Calls starting with a -- argument are passed directly and the function
522        # returns with the lunch.py exit code.
523        "${T}/orchestrator/build/orchestrator/core/lunch.py" "$@"
524        code=$?
525        if [[ $code -eq 2 ]] ; then
526          echo 1>&2
527          multitree_lunch_help
528          return $code
529        elif [[ $code -ne 0 ]] ; then
530          return $code
531        fi
532    else
533        # All other calls go through the --lunch variant of lunch.py
534        results=($(${T}/orchestrator/build/orchestrator/core/lunch.py --lunch "$@"))
535        code=$?
536        if [[ $code -eq 2 ]] ; then
537          echo 1>&2
538          multitree_lunch_help
539          return $code
540        elif [[ $code -ne 0 ]] ; then
541          return $code
542        fi
543
544        export TARGET_BUILD_COMBO=${results[0]}
545        export TARGET_BUILD_VARIANT=${results[1]}
546    fi
547}
548
549function choosetype()
550{
551    echo "Build type choices are:"
552    echo "     1. release"
553    echo "     2. debug"
554    echo
555
556    local DEFAULT_NUM DEFAULT_VALUE
557    DEFAULT_NUM=1
558    DEFAULT_VALUE=release
559
560    export TARGET_BUILD_TYPE=
561    local ANSWER
562    while [ -z $TARGET_BUILD_TYPE ]
563    do
564        echo -n "Which would you like? ["$DEFAULT_NUM"] "
565        if [ -z "$1" ] ; then
566            read ANSWER
567        else
568            echo $1
569            ANSWER=$1
570        fi
571        case $ANSWER in
572        "")
573            export TARGET_BUILD_TYPE=$DEFAULT_VALUE
574            ;;
575        1)
576            export TARGET_BUILD_TYPE=release
577            ;;
578        release)
579            export TARGET_BUILD_TYPE=release
580            ;;
581        2)
582            export TARGET_BUILD_TYPE=debug
583            ;;
584        debug)
585            export TARGET_BUILD_TYPE=debug
586            ;;
587        *)
588            echo
589            echo "I didn't understand your response.  Please try again."
590            echo
591            ;;
592        esac
593        if [ -n "$1" ] ; then
594            break
595        fi
596    done
597
598    build_build_var_cache
599    set_stuff_for_environment
600    destroy_build_var_cache
601}
602
603#
604# This function isn't really right:  It chooses a TARGET_PRODUCT
605# based on the list of boards.  Usually, that gets you something
606# that kinda works with a generic product, but really, you should
607# pick a product by name.
608#
609function chooseproduct()
610{
611    local default_value
612    if [ "x$TARGET_PRODUCT" != x ] ; then
613        default_value=$TARGET_PRODUCT
614    else
615        default_value=aosp_arm
616    fi
617
618    export TARGET_BUILD_APPS=
619    export TARGET_PRODUCT=
620    local ANSWER
621    while [ -z "$TARGET_PRODUCT" ]
622    do
623        echo -n "Which product would you like? [$default_value] "
624        if [ -z "$1" ] ; then
625            read ANSWER
626        else
627            echo $1
628            ANSWER=$1
629        fi
630
631        if [ -z "$ANSWER" ] ; then
632            export TARGET_PRODUCT=$default_value
633        else
634            if check_product $ANSWER
635            then
636                export TARGET_PRODUCT=$ANSWER
637            else
638                echo "** Not a valid product: $ANSWER"
639            fi
640        fi
641        if [ -n "$1" ] ; then
642            break
643        fi
644    done
645
646    build_build_var_cache
647    set_stuff_for_environment
648    destroy_build_var_cache
649}
650
651function choosevariant()
652{
653    echo "Variant choices are:"
654    local index=1
655    local v
656    for v in ${VARIANT_CHOICES[@]}
657    do
658        # The product name is the name of the directory containing
659        # the makefile we found, above.
660        echo "     $index. $v"
661        index=$(($index+1))
662    done
663
664    local default_value=eng
665    local ANSWER
666
667    export TARGET_BUILD_VARIANT=
668    while [ -z "$TARGET_BUILD_VARIANT" ]
669    do
670        echo -n "Which would you like? [$default_value] "
671        if [ -z "$1" ] ; then
672            read ANSWER
673        else
674            echo $1
675            ANSWER=$1
676        fi
677
678        if [ -z "$ANSWER" ] ; then
679            export TARGET_BUILD_VARIANT=$default_value
680        elif (echo -n $ANSWER | grep -q -e "^[0-9][0-9]*$") ; then
681            if [ "$ANSWER" -le "${#VARIANT_CHOICES[@]}" ] ; then
682                export TARGET_BUILD_VARIANT=${VARIANT_CHOICES[@]:$(($ANSWER-1)):1}
683            fi
684        else
685            if check_variant $ANSWER
686            then
687                export TARGET_BUILD_VARIANT=$ANSWER
688            else
689                echo "** Not a valid variant: $ANSWER"
690            fi
691        fi
692        if [ -n "$1" ] ; then
693            break
694        fi
695    done
696}
697
698function choosecombo()
699{
700    choosetype $1
701
702    echo
703    echo
704    chooseproduct $2
705
706    echo
707    echo
708    choosevariant $3
709
710    echo
711    build_build_var_cache
712    set_stuff_for_environment
713    printconfig
714    destroy_build_var_cache
715}
716
717function add_lunch_combo()
718{
719    if [ -n "$ZSH_VERSION" ]; then
720        echo -n "${funcfiletrace[1]}: "
721    else
722        echo -n "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: "
723    fi
724    echo "add_lunch_combo is obsolete. Use COMMON_LUNCH_CHOICES in your AndroidProducts.mk instead."
725}
726
727function print_lunch_menu()
728{
729    local uname=$(uname)
730    local choices
731    choices=$(TARGET_BUILD_APPS= TARGET_PRODUCT= TARGET_BUILD_VARIANT= get_build_var COMMON_LUNCH_CHOICES 2>/dev/null)
732    local ret=$?
733
734    echo
735    echo "You're building on" $uname
736    echo
737
738    if [ $ret -ne 0 ]
739    then
740        echo "Warning: Cannot display lunch menu."
741        echo
742        echo "Note: You can invoke lunch with an explicit target:"
743        echo
744        echo "  usage: lunch [target]" >&2
745        echo
746        return
747    fi
748
749    echo "Lunch menu .. Here are the common combinations:"
750
751    local i=1
752    local choice
753    for choice in $(echo $choices)
754    do
755        echo "     $i. $choice"
756        i=$(($i+1))
757    done
758
759    echo
760}
761
762function lunch()
763{
764    local answer
765
766    if [[ $# -gt 1 ]]; then
767        echo "usage: lunch [target]" >&2
768        return 1
769    fi
770
771    local used_lunch_menu=0
772
773    if [ "$1" ]; then
774        answer=$1
775    else
776        print_lunch_menu
777        echo "Which would you like? [aosp_arm-eng]"
778        echo -n "Pick from common choices above (e.g. 13) or specify your own (e.g. aosp_barbet-eng): "
779        read answer
780        used_lunch_menu=1
781    fi
782
783    local selection=
784
785    if [ -z "$answer" ]
786    then
787        selection=aosp_arm-eng
788    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
789    then
790        local choices=($(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES))
791        if [ $answer -le ${#choices[@]} ]
792        then
793            # array in zsh starts from 1 instead of 0.
794            if [ -n "$ZSH_VERSION" ]
795            then
796                selection=${choices[$(($answer))]}
797            else
798                selection=${choices[$(($answer-1))]}
799            fi
800        fi
801    else
802        selection=$answer
803    fi
804
805    export TARGET_BUILD_APPS=
806
807    local product variant_and_version variant version
808    product=${selection%%-*} # Trim everything after first dash
809    variant_and_version=${selection#*-} # Trim everything up to first dash
810    if [ "$variant_and_version" != "$selection" ]; then
811        variant=${variant_and_version%%-*}
812        if [ "$variant" != "$variant_and_version" ]; then
813            version=${variant_and_version#*-}
814        fi
815    fi
816
817    if [ -z "$product" ]
818    then
819        echo
820        echo "Invalid lunch combo: $selection"
821        return 1
822    fi
823
824    TARGET_PRODUCT=$product \
825    TARGET_BUILD_VARIANT=$variant \
826    TARGET_PLATFORM_VERSION=$version \
827    build_build_var_cache
828    if [ $? -ne 0 ]
829    then
830        if [[ "$product" =~ .*_(eng|user|userdebug) ]]
831        then
832            echo "Did you mean -${product/*_/}? (dash instead of underscore)"
833        fi
834        return 1
835    fi
836    export TARGET_PRODUCT=$(get_build_var TARGET_PRODUCT)
837    export TARGET_BUILD_VARIANT=$(get_build_var TARGET_BUILD_VARIANT)
838    if [ -n "$version" ]; then
839      export TARGET_PLATFORM_VERSION=$(get_build_var TARGET_PLATFORM_VERSION)
840    else
841      unset TARGET_PLATFORM_VERSION
842    fi
843    export TARGET_BUILD_TYPE=release
844
845    if [ $used_lunch_menu -eq 1 ]; then
846      echo
847      echo "Hint: next time you can simply run 'lunch $selection'"
848    fi
849
850    [[ -n "${ANDROID_QUIET_BUILD:-}" ]] || echo
851
852    set_stuff_for_environment
853    [[ -n "${ANDROID_QUIET_BUILD:-}" ]] || printconfig
854    destroy_build_var_cache
855
856    if [[ -n "${CHECK_MU_CONFIG:-}" ]]; then
857      check_mu_config
858    fi
859}
860
861unset COMMON_LUNCH_CHOICES_CACHE
862# Tab completion for lunch.
863function _lunch()
864{
865    local cur prev opts
866    COMPREPLY=()
867    cur="${COMP_WORDS[COMP_CWORD]}"
868    prev="${COMP_WORDS[COMP_CWORD-1]}"
869
870    if [ -z "$COMMON_LUNCH_CHOICES_CACHE" ]; then
871        COMMON_LUNCH_CHOICES_CACHE=$(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES)
872    fi
873
874    COMPREPLY=( $(compgen -W "${COMMON_LUNCH_CHOICES_CACHE}" -- ${cur}) )
875    return 0
876}
877
878# Configures the build to build unbundled apps.
879# Run tapas with one or more app names (from LOCAL_PACKAGE_NAME)
880function tapas()
881{
882    local showHelp="$(echo $* | xargs -n 1 echo | \grep -E '^(help)$' | xargs)"
883    local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|arm64|x86_64)$' | xargs)"
884    local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)"
885    local density="$(echo $* | xargs -n 1 echo | \grep -E '^(ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi)$' | xargs)"
886    local keys="$(echo $* | xargs -n 1 echo | \grep -E '^(devkeys)$' | xargs)"
887    local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|arm|x86|arm64|x86_64|ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi|devkeys)$' | xargs)"
888
889
890    if [ "$showHelp" != "" ]; then
891      $(gettop)/build/make/tapasHelp.sh
892      return
893    fi
894
895    if [ $(echo $arch | wc -w) -gt 1 ]; then
896        echo "tapas: Error: Multiple build archs supplied: $arch"
897        return
898    fi
899    if [ $(echo $variant | wc -w) -gt 1 ]; then
900        echo "tapas: Error: Multiple build variants supplied: $variant"
901        return
902    fi
903    if [ $(echo $density | wc -w) -gt 1 ]; then
904        echo "tapas: Error: Multiple densities supplied: $density"
905        return
906    fi
907    if [ $(echo $keys | wc -w) -gt 1 ]; then
908        echo "tapas: Error: Multiple keys supplied: $keys"
909        return
910    fi
911
912    local product=aosp_arm
913    case $arch in
914      x86)    product=aosp_x86;;
915      arm64)  product=aosp_arm64;;
916      x86_64) product=aosp_x86_64;;
917    esac
918    if [ -n "$keys" ]; then
919        product=${product/aosp_/aosp_${keys}_}
920    fi;
921
922    if [ -z "$variant" ]; then
923        variant=eng
924    fi
925    if [ -z "$apps" ]; then
926        apps=all
927    fi
928    if [ -z "$density" ]; then
929        density=alldpi
930    fi
931
932    export TARGET_PRODUCT=$product
933    export TARGET_BUILD_VARIANT=$variant
934    export TARGET_BUILD_DENSITY=$density
935    export TARGET_BUILD_TYPE=release
936    export TARGET_BUILD_APPS=$apps
937
938    build_build_var_cache
939    set_stuff_for_environment
940    printconfig
941    destroy_build_var_cache
942}
943
944# Configures the build to build unbundled Android modules (APEXes).
945# Run banchan with one or more module names (from apex{} modules).
946function banchan()
947{
948    local showHelp="$(echo $* | xargs -n 1 echo | \grep -E '^(help)$' | xargs)"
949    local product="$(echo $* | xargs -n 1 echo | \grep -E '^(.*_)?(arm|x86|arm64|x86_64|arm64only|x86_64only)$' | xargs)"
950    local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)"
951    local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|(.*_)?(arm|x86|arm64|x86_64))$' | xargs)"
952
953    if [ "$showHelp" != "" ]; then
954      $(gettop)/build/make/banchanHelp.sh
955      return
956    fi
957
958    if [ -z "$product" ]; then
959        product=arm64
960    elif [ $(echo $product | wc -w) -gt 1 ]; then
961        echo "banchan: Error: Multiple build archs or products supplied: $products"
962        return
963    fi
964    if [ $(echo $variant | wc -w) -gt 1 ]; then
965        echo "banchan: Error: Multiple build variants supplied: $variant"
966        return
967    fi
968    if [ -z "$apps" ]; then
969        echo "banchan: Error: No modules supplied"
970        return
971    fi
972
973    case $product in
974      arm)    product=module_arm;;
975      x86)    product=module_x86;;
976      arm64)  product=module_arm64;;
977      x86_64) product=module_x86_64;;
978      arm64only)  product=module_arm64only;;
979      x86_64only) product=module_x86_64only;;
980    esac
981    if [ -z "$variant" ]; then
982        variant=eng
983    fi
984
985    export TARGET_PRODUCT=$product
986    export TARGET_BUILD_VARIANT=$variant
987    export TARGET_BUILD_DENSITY=alldpi
988    export TARGET_BUILD_TYPE=release
989
990    # This setup currently uses TARGET_BUILD_APPS just like tapas, but the use
991    # case is different and it may diverge in the future.
992    export TARGET_BUILD_APPS=$apps
993
994    build_build_var_cache
995    set_stuff_for_environment
996    printconfig
997    destroy_build_var_cache
998}
999
1000# TODO: Merge into gettop as part of launching multitree
1001function multitree_gettop
1002{
1003    local TOPFILE=orchestrator/build/make/core/envsetup.mk
1004    if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ] ; then
1005        # The following circumlocution ensures we remove symlinks from TOP.
1006        (cd "$TOP"; PWD= /bin/pwd)
1007    else
1008        if [ -f $TOPFILE ] ; then
1009            # The following circumlocution (repeated below as well) ensures
1010            # that we record the true directory name and not one that is
1011            # faked up with symlink names.
1012            PWD= /bin/pwd
1013        else
1014            local HERE=$PWD
1015            local T=
1016            while [ \( ! \( -f $TOPFILE \) \) -a \( "$PWD" != "/" \) ]; do
1017                \cd ..
1018                T=`PWD= /bin/pwd -P`
1019            done
1020            \cd "$HERE"
1021            if [ -f "$T/$TOPFILE" ]; then
1022                echo "$T"
1023            fi
1024        fi
1025    fi
1026}
1027
1028function croot()
1029{
1030    local T=$(gettop)
1031    if [ "$T" ]; then
1032        if [ "$1" ]; then
1033            \cd $(gettop)/$1
1034        else
1035            \cd $(gettop)
1036        fi
1037    else
1038        echo "Couldn't locate the top of the tree.  Try setting TOP."
1039    fi
1040}
1041
1042function _croot()
1043{
1044    local T=$(gettop)
1045    if [ "$T" ]; then
1046        local cur="${COMP_WORDS[COMP_CWORD]}"
1047        k=0
1048        for c in $(compgen -d ${T}/${cur}); do
1049            COMPREPLY[k++]=${c#${T}/}/
1050        done
1051    fi
1052}
1053
1054function cproj()
1055{
1056    local TOPFILE=build/make/core/envsetup.mk
1057    local HERE=$PWD
1058    local T=
1059    while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
1060        T=$PWD
1061        if [ -f "$T/Android.mk" ]; then
1062            \cd $T
1063            return
1064        fi
1065        \cd ..
1066    done
1067    \cd $HERE
1068    echo "can't find Android.mk"
1069}
1070
1071# simplified version of ps; output in the form
1072# <pid> <procname>
1073function qpid() {
1074    local prepend=''
1075    local append=''
1076    if [ "$1" = "--exact" ]; then
1077        prepend=' '
1078        append='$'
1079        shift
1080    elif [ "$1" = "--help" -o "$1" = "-h" ]; then
1081        echo "usage: qpid [[--exact] <process name|pid>"
1082        return 255
1083    fi
1084
1085    local EXE="$1"
1086    if [ "$EXE" ] ; then
1087        qpid | \grep "$prepend$EXE$append"
1088    else
1089        adb shell ps \
1090            | tr -d '\r' \
1091            | sed -e 1d -e 's/^[^ ]* *\([0-9]*\).* \([^ ]*\)$/\1 \2/'
1092    fi
1093}
1094
1095# syswrite - disable verity, reboot if needed, and remount image
1096#
1097# Easy way to make system.img/etc writable
1098function syswrite() {
1099  adb wait-for-device && adb root || return 1
1100  if [[ $(adb disable-verity | grep -i "reboot") ]]; then
1101      echo "rebooting"
1102      adb reboot && adb wait-for-device && adb root || return 1
1103  fi
1104  adb wait-for-device && adb remount || return 1
1105}
1106
1107# coredump_setup - enable core dumps globally for any process
1108#                  that has the core-file-size limit set correctly
1109#
1110# NOTE: You must call also coredump_enable for a specific process
1111#       if its core-file-size limit is not set already.
1112# NOTE: Core dumps are written to ramdisk; they will not survive a reboot!
1113
1114function coredump_setup()
1115{
1116    echo "Getting root...";
1117    adb root;
1118    adb wait-for-device;
1119
1120    echo "Remounting root partition read-write...";
1121    adb shell mount -w -o remount -t rootfs rootfs;
1122    sleep 1;
1123    adb wait-for-device;
1124    adb shell mkdir -p /cores;
1125    adb shell mount -t tmpfs tmpfs /cores;
1126    adb shell chmod 0777 /cores;
1127
1128    echo "Granting SELinux permission to dump in /cores...";
1129    adb shell restorecon -R /cores;
1130
1131    echo "Set core pattern.";
1132    adb shell 'echo /cores/core.%p > /proc/sys/kernel/core_pattern';
1133
1134    echo "Done."
1135}
1136
1137# coredump_enable - enable core dumps for the specified process
1138# $1 = PID of process (e.g., $(pid mediaserver))
1139#
1140# NOTE: coredump_setup must have been called as well for a core
1141#       dump to actually be generated.
1142
1143function coredump_enable()
1144{
1145    local PID=$1;
1146    if [ -z "$PID" ]; then
1147        printf "Expecting a PID!\n";
1148        return;
1149    fi;
1150    echo "Setting core limit for $PID to infinite...";
1151    adb shell /system/bin/ulimit -P $PID -c unlimited
1152}
1153
1154# core - send SIGV and pull the core for process
1155# $1 = PID of process (e.g., $(pid mediaserver))
1156#
1157# NOTE: coredump_setup must be called once per boot for core dumps to be
1158#       enabled globally.
1159
1160function core()
1161{
1162    local PID=$1;
1163
1164    if [ -z "$PID" ]; then
1165        printf "Expecting a PID!\n";
1166        return;
1167    fi;
1168
1169    local CORENAME=core.$PID;
1170    local COREPATH=/cores/$CORENAME;
1171    local SIG=SEGV;
1172
1173    coredump_enable $1;
1174
1175    local done=0;
1176    while [ $(adb shell "[ -d /proc/$PID ] && echo -n yes") ]; do
1177        printf "\tSending SIG%s to %d...\n" $SIG $PID;
1178        adb shell kill -$SIG $PID;
1179        sleep 1;
1180    done;
1181
1182    adb shell "while [ ! -f $COREPATH ] ; do echo waiting for $COREPATH to be generated; sleep 1; done"
1183    echo "Done: core is under $COREPATH on device.";
1184}
1185
1186# systemstack - dump the current stack trace of all threads in the system process
1187# to the usual ANR traces file
1188function systemstack()
1189{
1190    stacks system_server
1191}
1192
1193# Read the ELF header from /proc/$PID/exe to determine if the process is
1194# 64-bit.
1195function is64bit()
1196{
1197    local PID="$1"
1198    if [ "$PID" ] ; then
1199        if [[ "$(adb shell cat /proc/$PID/exe | xxd -l 1 -s 4 -p)" -eq "02" ]] ; then
1200            echo "64"
1201        else
1202            echo ""
1203        fi
1204    else
1205        echo ""
1206    fi
1207}
1208
1209case `uname -s` in
1210    Darwin)
1211        function sgrep()
1212        {
1213            find -E . -name .repo -prune -o -name .git -prune -o  -type f -iregex '.*\.(c|h|cc|cpp|hpp|S|java|kt|xml|sh|mk|aidl|vts|proto|rs|go)' \
1214                -exec grep --color -n "$@" {} +
1215        }
1216
1217        ;;
1218    *)
1219        function sgrep()
1220        {
1221            find . -name .repo -prune -o -name .git -prune -o  -type f -iregex '.*\.\(c\|h\|cc\|cpp\|hpp\|S\|java\|kt\|xml\|sh\|mk\|aidl\|vts\|proto\|rs\|go\)' \
1222                -exec grep --color -n "$@" {} +
1223        }
1224        ;;
1225esac
1226
1227function gettargetarch
1228{
1229    get_build_var TARGET_ARCH
1230}
1231
1232function ggrep()
1233{
1234    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.gradle" \
1235        -exec grep --color -n "$@" {} +
1236}
1237
1238function gogrep()
1239{
1240    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.go" \
1241        -exec grep --color -n "$@" {} +
1242}
1243
1244function jgrep()
1245{
1246    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.java" \
1247        -exec grep --color -n "$@" {} +
1248}
1249
1250function rsgrep()
1251{
1252    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.rs" \
1253        -exec grep --color -n "$@" {} +
1254}
1255
1256function jsongrep()
1257{
1258    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.json" \
1259        -exec grep --color -n "$@" {} +
1260}
1261
1262function tomlgrep()
1263{
1264    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.toml" \
1265        -exec grep --color -n "$@" {} +
1266}
1267
1268function ktgrep()
1269{
1270    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.kt" \
1271        -exec grep --color -n "$@" {} +
1272}
1273
1274function cgrep()
1275{
1276    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f \( -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) \
1277        -exec grep --color -n "$@" {} +
1278}
1279
1280function resgrep()
1281{
1282    local dir
1283    for dir in `find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -name res -type d`; do
1284        find $dir -type f -name '*\.xml' -exec grep --color -n "$@" {} +
1285    done
1286}
1287
1288function mangrep()
1289{
1290    find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -type f -name 'AndroidManifest.xml' \
1291        -exec grep --color -n "$@" {} +
1292}
1293
1294function owngrep()
1295{
1296    find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -type f -name 'OWNERS' \
1297        -exec grep --color -n "$@" {} +
1298}
1299
1300function sepgrep()
1301{
1302    find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -name sepolicy -type d \
1303        -exec grep --color -n -r --exclude-dir=\.git "$@" {} +
1304}
1305
1306function rcgrep()
1307{
1308    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.rc*" \
1309        -exec grep --color -n "$@" {} +
1310}
1311
1312function pygrep()
1313{
1314    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.py" \
1315        -exec grep --color -n "$@" {} +
1316}
1317
1318case `uname -s` in
1319    Darwin)
1320        function mgrep()
1321        {
1322            find -E . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o \( -iregex '.*/(Makefile|Makefile\..*|.*\.make|.*\.mak|.*\.mk|.*\.bp)' -o -regex '(.*/)?(build|soong)/.*[^/]*\.go' \) -type f \
1323                -exec grep --color -n "$@" {} +
1324        }
1325
1326        function treegrep()
1327        {
1328            find -E . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*\.(c|h|cpp|hpp|S|java|kt|xml)' \
1329                -exec grep --color -n -i "$@" {} +
1330        }
1331
1332        ;;
1333    *)
1334        function mgrep()
1335        {
1336            find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o \( -regextype posix-egrep -iregex '(.*\/Makefile|.*\/Makefile\..*|.*\.make|.*\.mak|.*\.mk|.*\.bp)' -o -regextype posix-extended -regex '(.*/)?(build|soong)/.*[^/]*\.go' \) -type f \
1337                -exec grep --color -n "$@" {} +
1338        }
1339
1340        function treegrep()
1341        {
1342            find . -name .repo -prune -o -name .git -prune -o -regextype posix-egrep -iregex '.*\.(c|h|cpp|hpp|S|java|kt|xml)' -type f \
1343                -exec grep --color -n -i "$@" {} +
1344        }
1345
1346        ;;
1347esac
1348
1349function getprebuilt
1350{
1351    get_abs_build_var ANDROID_PREBUILTS
1352}
1353
1354function tracedmdump()
1355{
1356    local T=$(gettop)
1357    if [ ! "$T" ]; then
1358        echo "Couldn't locate the top of the tree.  Try setting TOP."
1359        return
1360    fi
1361    local prebuiltdir=$(getprebuilt)
1362    local arch=$(gettargetarch)
1363    local KERNEL=$T/prebuilts/qemu-kernel/$arch/vmlinux-qemu
1364
1365    local TRACE=$1
1366    if [ ! "$TRACE" ] ; then
1367        echo "usage:  tracedmdump  tracename"
1368        return
1369    fi
1370
1371    if [ ! -r "$KERNEL" ] ; then
1372        echo "Error: cannot find kernel: '$KERNEL'"
1373        return
1374    fi
1375
1376    local BASETRACE=$(basename $TRACE)
1377    if [ "$BASETRACE" = "$TRACE" ] ; then
1378        TRACE=$ANDROID_PRODUCT_OUT/traces/$TRACE
1379    fi
1380
1381    echo "post-processing traces..."
1382    rm -f $TRACE/qtrace.dexlist
1383    post_trace $TRACE
1384    if [ $? -ne 0 ]; then
1385        echo "***"
1386        echo "*** Error: malformed trace.  Did you remember to exit the emulator?"
1387        echo "***"
1388        return
1389    fi
1390    echo "generating dexlist output..."
1391    /bin/ls $ANDROID_PRODUCT_OUT/system/framework/*.jar $ANDROID_PRODUCT_OUT/system/app/*.apk $ANDROID_PRODUCT_OUT/data/app/*.apk 2>/dev/null | xargs dexlist > $TRACE/qtrace.dexlist
1392    echo "generating dmtrace data..."
1393    q2dm -r $ANDROID_PRODUCT_OUT/symbols $TRACE $KERNEL $TRACE/dmtrace || return
1394    echo "generating html file..."
1395    dmtracedump -h $TRACE/dmtrace >| $TRACE/dmtrace.html || return
1396    echo "done, see $TRACE/dmtrace.html for details"
1397    echo "or run:"
1398    echo "    traceview $TRACE/dmtrace"
1399}
1400
1401# communicate with a running device or emulator, set up necessary state,
1402# and run the hat command.
1403function runhat()
1404{
1405    # process standard adb options
1406    local adbTarget=""
1407    if [ "$1" = "-d" -o "$1" = "-e" ]; then
1408        adbTarget=$1
1409        shift 1
1410    elif [ "$1" = "-s" ]; then
1411        adbTarget="$1 $2"
1412        shift 2
1413    fi
1414    local adbOptions=${adbTarget}
1415    #echo adbOptions = ${adbOptions}
1416
1417    # runhat options
1418    local targetPid=$1
1419
1420    if [ "$targetPid" = "" ]; then
1421        echo "Usage: runhat [ -d | -e | -s serial ] target-pid"
1422        return
1423    fi
1424
1425    # confirm hat is available
1426    if [ -z $(which hat) ]; then
1427        echo "hat is not available in this configuration."
1428        return
1429    fi
1430
1431    # issue "am" command to cause the hprof dump
1432    local devFile=/data/local/tmp/hprof-$targetPid
1433    echo "Poking $targetPid and waiting for data..."
1434    echo "Storing data at $devFile"
1435    adb ${adbOptions} shell am dumpheap $targetPid $devFile
1436    echo "Press enter when logcat shows \"hprof: heap dump completed\""
1437    echo -n "> "
1438    read
1439
1440    local localFile=/tmp/$$-hprof
1441
1442    echo "Retrieving file $devFile..."
1443    adb ${adbOptions} pull $devFile $localFile
1444
1445    adb ${adbOptions} shell rm $devFile
1446
1447    echo "Running hat on $localFile"
1448    echo "View the output by pointing your browser at http://localhost:7000/"
1449    echo ""
1450    hat -JXmx512m $localFile
1451}
1452
1453function getbugreports()
1454{
1455    local reports=(`adb shell ls /sdcard/bugreports | tr -d '\r'`)
1456
1457    if [ ! "$reports" ]; then
1458        echo "Could not locate any bugreports."
1459        return
1460    fi
1461
1462    local report
1463    for report in ${reports[@]}
1464    do
1465        echo "/sdcard/bugreports/${report}"
1466        adb pull /sdcard/bugreports/${report} ${report}
1467        gunzip ${report}
1468    done
1469}
1470
1471function getsdcardpath()
1472{
1473    adb ${adbOptions} shell echo -n \$\{EXTERNAL_STORAGE\}
1474}
1475
1476function getscreenshotpath()
1477{
1478    echo "$(getsdcardpath)/Pictures/Screenshots"
1479}
1480
1481function getlastscreenshot()
1482{
1483    local screenshot_path=$(getscreenshotpath)
1484    local screenshot=`adb ${adbOptions} ls ${screenshot_path} | grep Screenshot_[0-9-]*.*\.png | sort -rk 3 | cut -d " " -f 4 | head -n 1`
1485    if [ "$screenshot" = "" ]; then
1486        echo "No screenshots found."
1487        return
1488    fi
1489    echo "${screenshot}"
1490    adb ${adbOptions} pull ${screenshot_path}/${screenshot}
1491}
1492
1493function startviewserver()
1494{
1495    local port=4939
1496    if [ $# -gt 0 ]; then
1497            port=$1
1498    fi
1499    adb shell service call window 1 i32 $port
1500}
1501
1502function stopviewserver()
1503{
1504    adb shell service call window 2
1505}
1506
1507function isviewserverstarted()
1508{
1509    adb shell service call window 3
1510}
1511
1512function key_home()
1513{
1514    adb shell input keyevent 3
1515}
1516
1517function key_back()
1518{
1519    adb shell input keyevent 4
1520}
1521
1522function key_menu()
1523{
1524    adb shell input keyevent 82
1525}
1526
1527function smoketest()
1528{
1529    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
1530        echo "Couldn't locate output files.  Try running 'lunch' first." >&2
1531        return
1532    fi
1533    local T=$(gettop)
1534    if [ ! "$T" ]; then
1535        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
1536        return
1537    fi
1538
1539    (\cd "$T" && mmm tests/SmokeTest) &&
1540      adb uninstall com.android.smoketest > /dev/null &&
1541      adb uninstall com.android.smoketest.tests > /dev/null &&
1542      adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTestApp.apk &&
1543      adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTest.apk &&
1544      adb shell am instrument -w com.android.smoketest.tests/android.test.InstrumentationTestRunner
1545}
1546
1547# simple shortcut to the runtest command
1548function runtest()
1549{
1550    local T=$(gettop)
1551    if [ ! "$T" ]; then
1552        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
1553        return
1554    fi
1555    ("$T"/development/testrunner/runtest.py $@)
1556}
1557
1558function godir () {
1559    if [[ -z "$1" ]]; then
1560        echo "Usage: godir <regex>"
1561        return
1562    fi
1563    local T=$(gettop)
1564    local FILELIST
1565    if [ ! "$OUT_DIR" = "" ]; then
1566        mkdir -p $OUT_DIR
1567        FILELIST=$OUT_DIR/filelist
1568    else
1569        FILELIST=$T/filelist
1570    fi
1571    if [[ ! -f $FILELIST ]]; then
1572        echo -n "Creating index..."
1573        (\cd $T; find . -wholename ./out -prune -o -wholename ./.repo -prune -o -type f > $FILELIST)
1574        echo " Done"
1575        echo ""
1576    fi
1577    local lines
1578    lines=($(\grep "$1" $FILELIST | sed -e 's/\/[^/]*$//' | sort | uniq))
1579    if [[ ${#lines[@]} = 0 ]]; then
1580        echo "Not found"
1581        return
1582    fi
1583    local pathname
1584    local choice
1585    if [[ ${#lines[@]} > 1 ]]; then
1586        while [[ -z "$pathname" ]]; do
1587            local index=1
1588            local line
1589            for line in ${lines[@]}; do
1590                printf "%6s %s\n" "[$index]" $line
1591                index=$(($index + 1))
1592            done
1593            echo
1594            echo -n "Select one: "
1595            unset choice
1596            read choice
1597            if [[ $choice -gt ${#lines[@]} || $choice -lt 1 ]]; then
1598                echo "Invalid choice"
1599                continue
1600            fi
1601            pathname=${lines[@]:$(($choice-1)):1}
1602        done
1603    else
1604        pathname=${lines[@]:0:1}
1605    fi
1606    \cd $T/$pathname
1607}
1608
1609# Update module-info.json in out.
1610function refreshmod() {
1611    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
1612        echo "No ANDROID_PRODUCT_OUT. Try running 'lunch' first." >&2
1613        return 1
1614    fi
1615
1616    echo "Refreshing modules (building module-info.json). Log at $ANDROID_PRODUCT_OUT/module-info.json.build.log." >&2
1617
1618    # for the output of the next command
1619    mkdir -p $ANDROID_PRODUCT_OUT || return 1
1620
1621    # Note, can't use absolute path because of the way make works.
1622    m $(get_build_var PRODUCT_OUT)/module-info.json \
1623        > $ANDROID_PRODUCT_OUT/module-info.json.build.log 2>&1
1624}
1625
1626# Verifies that module-info.txt exists, returning nonzero if it doesn't.
1627function verifymodinfo() {
1628    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
1629        if [ "$QUIET_VERIFYMODINFO" != "true" ] ; then
1630            echo "No ANDROID_PRODUCT_OUT. Try running 'lunch' first." >&2
1631        fi
1632        return 1
1633    fi
1634
1635    if [ ! -f "$ANDROID_PRODUCT_OUT/module-info.json" ]; then
1636        if [ "$QUIET_VERIFYMODINFO" != "true" ] ; then
1637            echo "Could not find module-info.json. Please run 'refreshmod' first." >&2
1638        fi
1639        return 1
1640    fi
1641}
1642
1643# List all modules for the current device, as cached in all_modules.txt. If any build change is
1644# made and it should be reflected in the output, you should run `m nothing` first.
1645function allmod() {
1646    cat $ANDROID_PRODUCT_OUT/all_modules.txt 2>/dev/null
1647}
1648
1649# Return the Bazel label of a Soong module if it is converted with bp2build.
1650function bmod()
1651(
1652    if [ $# -ne 1 ]; then
1653        echo "usage: bmod <module>" >&2
1654        return 1
1655    fi
1656
1657    # We could run bp2build here, but it might trigger bp2build invalidation
1658    # when used with `b` (e.g. --run_soong_tests) and/or add unnecessary waiting
1659    # time overhead.
1660    #
1661    # For a snappy result, use the latest generated version in soong_injection,
1662    # and ask users to run m bp2build if it doesn't exist.
1663    converted_json="$(get_abs_build_var OUT_DIR)/soong/soong_injection/metrics/converted_modules_path_map.json"
1664
1665    if [ ! -f ${converted_json} ]; then
1666      echo "bp2build files not found. Have you ran 'm bp2build'?" >&2
1667      return 1
1668    fi
1669
1670    local target_label=$(python3 -c "import json
1671module = '$1'
1672converted_json='$converted_json'
1673bp2build_converted_map = json.load(open(converted_json))
1674if module not in bp2build_converted_map:
1675    exit(1)
1676print(bp2build_converted_map[module] + ':' + module)")
1677
1678    if [ -z "${target_label}" ]; then
1679      echo "$1 is not converted to Bazel." >&2
1680      return 1
1681    else
1682      echo "${target_label}"
1683    fi
1684)
1685
1686# Get the path of a specific module in the android tree, as cached in module-info.json.
1687# If any build change is made, and it should be reflected in the output, you should run
1688# 'refreshmod' first.  Note: This is the inverse of dirmods.
1689function pathmod() {
1690    if [[ $# -ne 1 ]]; then
1691        echo "usage: pathmod <module>" >&2
1692        return 1
1693    fi
1694
1695    verifymodinfo || return 1
1696
1697    local relpath=$(python3 -c "import json, os
1698module = '$1'
1699module_info = json.load(open('$ANDROID_PRODUCT_OUT/module-info.json'))
1700if module not in module_info:
1701    exit(1)
1702print(module_info[module]['path'][0])" 2>/dev/null)
1703
1704    if [ -z "$relpath" ]; then
1705        echo "Could not find module '$1' (try 'refreshmod' if there have been build changes?)." >&2
1706        return 1
1707    else
1708        echo "$ANDROID_BUILD_TOP/$relpath"
1709    fi
1710}
1711
1712# Get the path of a specific module in the android tree, as cached in module-info.json.
1713# If any build change is made, and it should be reflected in the output, you should run
1714# 'refreshmod' first.  Note: This is the inverse of pathmod.
1715function dirmods() {
1716    if [[ $# -ne 1 ]]; then
1717        echo "usage: dirmods <path>" >&2
1718        return 1
1719    fi
1720
1721    verifymodinfo || return 1
1722
1723    python3 -c "import json, os
1724dir = '$1'
1725while dir.endswith('/'):
1726    dir = dir[:-1]
1727prefix = dir + '/'
1728module_info = json.load(open('$ANDROID_PRODUCT_OUT/module-info.json'))
1729results = set()
1730for m in module_info.values():
1731    for path in m.get(u'path', []):
1732        if path == dir or path.startswith(prefix):
1733            name = m.get(u'module_name')
1734            if name:
1735                results.add(name)
1736for name in sorted(results):
1737    print(name)
1738"
1739}
1740
1741
1742# Go to a specific module in the android tree, as cached in module-info.json. If any build change
1743# is made, and it should be reflected in the output, you should run 'refreshmod' first.
1744function gomod() {
1745    if [[ $# -ne 1 ]]; then
1746        echo "usage: gomod <module>" >&2
1747        return 1
1748    fi
1749
1750    local path="$(pathmod $@)"
1751    if [ -z "$path" ]; then
1752        return 1
1753    fi
1754    cd $path
1755}
1756
1757# Gets the list of a module's installed outputs, as cached in module-info.json.
1758# If any build change is made, and it should be reflected in the output, you should run 'refreshmod' first.
1759function outmod() {
1760    if [[ $# -ne 1 ]]; then
1761        echo "usage: outmod <module>" >&2
1762        return 1
1763    fi
1764
1765    verifymodinfo || return 1
1766
1767    local relpath
1768    relpath=$(python3 -c "import json, os
1769module = '$1'
1770module_info = json.load(open('$ANDROID_PRODUCT_OUT/module-info.json'))
1771if module not in module_info:
1772    exit(1)
1773for output in module_info[module]['installed']:
1774    print(os.path.join('$ANDROID_BUILD_TOP', output))" 2>/dev/null)
1775
1776    if [ $? -ne 0 ]; then
1777        echo "Could not find module '$1' (try 'refreshmod' if there have been build changes?)" >&2
1778        return 1
1779    elif [ ! -z "$relpath" ]; then
1780        echo "$relpath"
1781    fi
1782}
1783
1784# adb install a module's apk, as cached in module-info.json. If any build change
1785# is made, and it should be reflected in the output, you should run 'refreshmod' first.
1786# Usage: installmod [adb install arguments] <module>
1787# For example: installmod -r Dialer -> adb install -r /path/to/Dialer.apk
1788function installmod() {
1789    if [[ $# -eq 0 ]]; then
1790        echo "usage: installmod [adb install arguments] <module>" >&2
1791        echo "" >&2
1792        echo "Only flags to be passed after the \"install\" in adb install are supported," >&2
1793        echo "with the exception of -s. If -s is passed it will be placed before the \"install\"." >&2
1794        echo "-s must be the first flag passed if it exists." >&2
1795        return 1
1796    fi
1797
1798    local _path
1799    _path=$(outmod ${@:$#:1})
1800    if [ $? -ne 0 ]; then
1801        return 1
1802    fi
1803
1804    _path=$(echo "$_path" | grep -E \\.apk$ | head -n 1)
1805    if [ -z "$_path" ]; then
1806        echo "Module '$1' does not produce a file ending with .apk (try 'refreshmod' if there have been build changes?)" >&2
1807        return 1
1808    fi
1809    local serial_device=""
1810    if [[ "$1" == "-s" ]]; then
1811        if [[ $# -le 2 ]]; then
1812            echo "-s requires an argument" >&2
1813            return 1
1814        fi
1815        serial_device="-s $2"
1816        shift 2
1817    fi
1818    local length=$(( $# - 1 ))
1819    echo adb $serial_device install ${@:1:$length} $_path
1820    adb $serial_device install ${@:1:$length} $_path
1821}
1822
1823function _complete_android_module_names() {
1824    local word=${COMP_WORDS[COMP_CWORD]}
1825    COMPREPLY=( $(allmod | grep -E "^$word") )
1826}
1827
1828# Print colored exit condition
1829function pez {
1830    "$@"
1831    local retval=$?
1832    if [ $retval -ne 0 ]
1833    then
1834        echo $'\E'"[0;31mFAILURE\e[00m"
1835    else
1836        echo $'\E'"[0;32mSUCCESS\e[00m"
1837    fi
1838    return $retval
1839}
1840
1841function get_make_command()
1842{
1843    # If we're in the top of an Android tree, use soong_ui.bash instead of make
1844    if [ -f build/soong/soong_ui.bash ]; then
1845        # Always use the real make if -C is passed in
1846        for arg in "$@"; do
1847            if [[ $arg == -C* ]]; then
1848                echo command make
1849                return
1850            fi
1851        done
1852        echo build/soong/soong_ui.bash --make-mode
1853    else
1854        echo command make
1855    fi
1856}
1857
1858function _wrap_build()
1859{
1860    if [[ "${ANDROID_QUIET_BUILD:-}" == true ]]; then
1861      "$@"
1862      return $?
1863    fi
1864    local start_time=$(date +"%s")
1865    "$@"
1866    local ret=$?
1867    local end_time=$(date +"%s")
1868    local tdiff=$(($end_time-$start_time))
1869    local hours=$(($tdiff / 3600 ))
1870    local mins=$((($tdiff % 3600) / 60))
1871    local secs=$(($tdiff % 60))
1872    local ncolors=$(tput colors 2>/dev/null)
1873    if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then
1874        color_failed=$'\E'"[0;31m"
1875        color_success=$'\E'"[0;32m"
1876        color_warning=$'\E'"[0;33m"
1877        color_reset=$'\E'"[00m"
1878    else
1879        color_failed=""
1880        color_success=""
1881        color_reset=""
1882    fi
1883
1884    echo
1885    if [ $ret -eq 0 ] ; then
1886        echo -n "${color_success}#### build completed successfully "
1887    else
1888        echo -n "${color_failed}#### failed to build some targets "
1889    fi
1890    if [ $hours -gt 0 ] ; then
1891        printf "(%02g:%02g:%02g (hh:mm:ss))" $hours $mins $secs
1892    elif [ $mins -gt 0 ] ; then
1893        printf "(%02g:%02g (mm:ss))" $mins $secs
1894    elif [ $secs -gt 0 ] ; then
1895        printf "(%s seconds)" $secs
1896    fi
1897    echo " ####${color_reset}"
1898    echo
1899    return $ret
1900}
1901
1902function _trigger_build()
1903(
1904    local -r bc="$1"; shift
1905    local T=$(gettop)
1906    if [ -n "$T" ]; then
1907      _wrap_build "$T/build/soong/soong_ui.bash" --build-mode --${bc} --dir="$(pwd)" "$@"
1908    else
1909      >&2 echo "Couldn't locate the top of the tree. Try setting TOP."
1910      return 1
1911    fi
1912)
1913
1914function m()
1915(
1916    _trigger_build "all-modules" "$@"
1917)
1918
1919function mm()
1920(
1921    _trigger_build "modules-in-a-dir-no-deps" "$@"
1922)
1923
1924function mmm()
1925(
1926    _trigger_build "modules-in-dirs-no-deps" "$@"
1927)
1928
1929function mma()
1930(
1931    _trigger_build "modules-in-a-dir" "$@"
1932)
1933
1934function mmma()
1935(
1936    _trigger_build "modules-in-dirs" "$@"
1937)
1938
1939function make()
1940{
1941    _wrap_build $(get_make_command "$@") "$@"
1942}
1943
1944function _multitree_lunch_error()
1945{
1946      >&2 echo "Couldn't locate the top of the tree. Please run \'source build/envsetup.sh\' and multitree_lunch from the root of your workspace."
1947}
1948
1949function multitree_build()
1950{
1951    local T=$(multitree_gettop)
1952    if [ -n "$T" ]; then
1953      "$T/orchestrator/build/orchestrator/core/orchestrator.py" "$@"
1954    else
1955      _multitree_lunch_error
1956      return 1
1957    fi
1958}
1959
1960function provision()
1961{
1962    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
1963        echo "Couldn't locate output files.  Try running 'lunch' first." >&2
1964        return 1
1965    fi
1966    if [ ! -e "$ANDROID_PRODUCT_OUT/provision-device" ]; then
1967        echo "There is no provisioning script for the device." >&2
1968        return 1
1969    fi
1970
1971    # Check if user really wants to do this.
1972    if [ "$1" = "--no-confirmation" ]; then
1973        shift 1
1974    else
1975        echo "This action will reflash your device."
1976        echo ""
1977        echo "ALL DATA ON THE DEVICE WILL BE IRREVOCABLY ERASED."
1978        echo ""
1979        echo -n "Are you sure you want to do this (yes/no)? "
1980        read
1981        if [[ "${REPLY}" != "yes" ]] ; then
1982            echo "Not taking any action. Exiting." >&2
1983            return 1
1984        fi
1985    fi
1986    "$ANDROID_PRODUCT_OUT/provision-device" "$@"
1987}
1988
1989# Zsh needs bashcompinit called to support bash-style completion.
1990function enable_zsh_completion() {
1991    # Don't override user's options if bash-style completion is already enabled.
1992    if ! declare -f complete >/dev/null; then
1993        autoload -U compinit && compinit
1994        autoload -U bashcompinit && bashcompinit
1995    fi
1996}
1997
1998function validate_current_shell() {
1999    local current_sh="$(ps -o command -p $$)"
2000    case "$current_sh" in
2001        *bash*)
2002            function check_type() { type -t "$1"; }
2003            ;;
2004        *zsh*)
2005            function check_type() { type "$1"; }
2006            enable_zsh_completion ;;
2007        *)
2008            echo -e "WARNING: Only bash and zsh are supported.\nUse of other shell would lead to erroneous results."
2009            ;;
2010    esac
2011}
2012
2013# Execute the contents of any vendorsetup.sh files we can find.
2014# Unless we find an allowed-vendorsetup_sh-files file, in which case we'll only
2015# load those.
2016#
2017# This allows loading only approved vendorsetup.sh files
2018function source_vendorsetup() {
2019    unset VENDOR_PYTHONPATH
2020    local T="$(gettop)"
2021    allowed=
2022    for f in $(cd "$T" && find -L device vendor product -maxdepth 4 -name 'allowed-vendorsetup_sh-files' 2>/dev/null | sort); do
2023        if [ -n "$allowed" ]; then
2024            echo "More than one 'allowed_vendorsetup_sh-files' file found, not including any vendorsetup.sh files:"
2025            echo "  $allowed"
2026            echo "  $f"
2027            return
2028        fi
2029        allowed="$T/$f"
2030    done
2031
2032    allowed_files=
2033    [ -n "$allowed" ] && allowed_files=$(cat "$allowed")
2034    for dir in device vendor product; do
2035        for f in $(cd "$T" && test -d $dir && \
2036            find -L $dir -maxdepth 4 -name 'vendorsetup.sh' 2>/dev/null | sort); do
2037
2038            if [[ -z "$allowed" || "$allowed_files" =~ $f ]]; then
2039                echo "including $f"; . "$T/$f"
2040            else
2041                echo "ignoring $f, not in $allowed"
2042            fi
2043        done
2044    done
2045}
2046
2047function showcommands() {
2048    local T=$(gettop)
2049    if [[ -z "$TARGET_PRODUCT" ]]; then
2050        >&2 echo "TARGET_PRODUCT not set. Run lunch."
2051        return
2052    fi
2053    case $(uname -s) in
2054        Darwin)
2055            PREBUILT_NAME=darwin-x86
2056            ;;
2057        Linux)
2058            PREBUILT_NAME=linux-x86
2059            ;;
2060        *)
2061            >&2 echo Unknown host $(uname -s)
2062            return
2063            ;;
2064    esac
2065    OUT_DIR="$(get_abs_build_var OUT_DIR)"
2066    if [[ "$1" == "--regenerate" ]]; then
2067      shift 1
2068      NINJA_ARGS="-t commands $@" m
2069    else
2070      (cd $T && prebuilts/build-tools/$PREBUILT_NAME/bin/ninja \
2071          -f $OUT_DIR/combined-${TARGET_PRODUCT}.ninja \
2072          -t commands "$@")
2073    fi
2074}
2075
2076function avbtool() {
2077    if [[ ! -f "$ANDROID_SOONG_HOST_OUT"/bin/avbtool ]]; then
2078        m avbtool
2079    fi
2080    "$ANDROID_SOONG_HOST_OUT"/bin/avbtool $@
2081}
2082
2083validate_current_shell
2084set_global_paths
2085source_vendorsetup
2086addcompletions
2087
2088