1function hmm() {
2cat <<EOF
3
4Run "m help" for help with the build system itself.
5
6Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
7- lunch:      lunch <product_name>-<build_variant>
8              Selects <product_name> as the product to build, and <build_variant> as the variant to
9              build, and stores those selections in the environment to be read by subsequent
10              invocations of 'm' etc.
11- tapas:      tapas [<App1> <App2> ...] [arm|x86|arm64|x86_64] [eng|userdebug|user]
12- croot:      Changes directory to the top of the tree, or a subdirectory thereof.
13- m:          Makes from the top of the tree.
14- mm:         Builds and installs all of the modules in the current directory, and their
15              dependencies.
16- mmm:        Builds and installs all of the modules in the supplied directories, and their
17              dependencies.
18              To limit the modules being built use the syntax: mmm dir/:target1,target2.
19- mma:        Same as 'mm'
20- mmma:       Same as 'mmm'
21- provision:  Flash device with all required partitions. Options will be passed on to fastboot.
22- cgrep:      Greps on all local C/C++ files.
23- ggrep:      Greps on all local Gradle files.
24- gogrep:     Greps on all local Go files.
25- jgrep:      Greps on all local Java files.
26- resgrep:    Greps on all local res/*.xml files.
27- mangrep:    Greps on all local AndroidManifest.xml files.
28- mgrep:      Greps on all local Makefiles and *.bp files.
29- owngrep:    Greps on all local OWNERS files.
30- sepgrep:    Greps on all local sepolicy files.
31- sgrep:      Greps on all local source files.
32- godir:      Go to the directory containing a file.
33- allmod:     List all modules.
34- gomod:      Go to the directory containing a module.
35- pathmod:    Get the directory containing a module.
36- refreshmod: Refresh list of modules for allmod/gomod/pathmod.
37
38Environment options:
39- SANITIZE_HOST: Set to 'address' to use ASAN for all host modules.
40- ANDROID_QUIET_BUILD: set to 'true' to display only the essential messages.
41
42Look at the source to view more functions. The complete list is:
43EOF
44    local T=$(gettop)
45    local A=""
46    local i
47    for i in `cat $T/build/envsetup.sh | sed -n "/^[[:blank:]]*function /s/function \([a-z_]*\).*/\1/p" | sort | uniq`; do
48      A="$A $i"
49    done
50    echo $A
51}
52
53# Get all the build variables needed by this script in a single call to the build system.
54function build_build_var_cache()
55{
56    local T=$(gettop)
57    # Grep out the variable names from the script.
58    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' ' '`)
59    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' ' '`)
60    # Call the build system to dump the "<val>=<value>" pairs as a shell script.
61    build_dicts_script=`\builtin cd $T; build/soong/soong_ui.bash --dumpvars-mode \
62                        --vars="${cached_vars[*]}" \
63                        --abs-vars="${cached_abs_vars[*]}" \
64                        --var-prefix=var_cache_ \
65                        --abs-var-prefix=abs_var_cache_`
66    local ret=$?
67    if [ $ret -ne 0 ]
68    then
69        unset build_dicts_script
70        return $ret
71    fi
72    # Execute the script to store the "<val>=<value>" pairs as shell variables.
73    eval "$build_dicts_script"
74    ret=$?
75    unset build_dicts_script
76    if [ $ret -ne 0 ]
77    then
78        return $ret
79    fi
80    BUILD_VAR_CACHE_READY="true"
81}
82
83# Delete the build var cache, so that we can still call into the build system
84# to get build variables not listed in this script.
85function destroy_build_var_cache()
86{
87    unset BUILD_VAR_CACHE_READY
88    local v
89    for v in $cached_vars; do
90      unset var_cache_$v
91    done
92    unset cached_vars
93    for v in $cached_abs_vars; do
94      unset abs_var_cache_$v
95    done
96    unset cached_abs_vars
97}
98
99# Get the value of a build variable as an absolute path.
100function get_abs_build_var()
101{
102    if [ "$BUILD_VAR_CACHE_READY" = "true" ]
103    then
104        eval "echo \"\${abs_var_cache_$1}\""
105    return
106    fi
107
108    local T=$(gettop)
109    if [ ! "$T" ]; then
110        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
111        return
112    fi
113    (\cd $T; build/soong/soong_ui.bash --dumpvar-mode --abs $1)
114}
115
116# Get the exact value of a build variable.
117function get_build_var()
118{
119    if [ "$BUILD_VAR_CACHE_READY" = "true" ]
120    then
121        eval "echo \"\${var_cache_$1}\""
122        return 0
123    fi
124
125    local T=$(gettop)
126    if [ ! "$T" ]; then
127        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
128        return 1
129    fi
130    (\cd $T; build/soong/soong_ui.bash --dumpvar-mode $1)
131}
132
133# check to see if the supplied product is one we can build
134function check_product()
135{
136    local T=$(gettop)
137    if [ ! "$T" ]; then
138        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
139        return
140    fi
141        TARGET_PRODUCT=$1 \
142        TARGET_BUILD_VARIANT= \
143        TARGET_BUILD_TYPE= \
144        TARGET_BUILD_APPS= \
145        get_build_var TARGET_DEVICE > /dev/null
146    # hide successful answers, but allow the errors to show
147}
148
149VARIANT_CHOICES=(user userdebug eng)
150
151# check to see if the supplied variant is valid
152function check_variant()
153{
154    local v
155    for v in ${VARIANT_CHOICES[@]}
156    do
157        if [ "$v" = "$1" ]
158        then
159            return 0
160        fi
161    done
162    return 1
163}
164
165function setpaths()
166{
167    local T=$(gettop)
168    if [ ! "$T" ]; then
169        echo "Couldn't locate the top of the tree.  Try setting TOP."
170        return
171    fi
172
173    ##################################################################
174    #                                                                #
175    #              Read me before you modify this code               #
176    #                                                                #
177    #   This function sets ANDROID_BUILD_PATHS to what it is adding  #
178    #   to PATH, and the next time it is run, it removes that from   #
179    #   PATH.  This is required so lunch can be run more than once   #
180    #   and still have working paths.                                #
181    #                                                                #
182    ##################################################################
183
184    # Note: on windows/cygwin, ANDROID_BUILD_PATHS will contain spaces
185    # due to "C:\Program Files" being in the path.
186
187    # out with the old
188    if [ -n "$ANDROID_BUILD_PATHS" ] ; then
189        export PATH=${PATH/$ANDROID_BUILD_PATHS/}
190    fi
191    if [ -n "$ANDROID_PRE_BUILD_PATHS" ] ; then
192        export PATH=${PATH/$ANDROID_PRE_BUILD_PATHS/}
193        # strip leading ':', if any
194        export PATH=${PATH/:%/}
195    fi
196
197    # and in with the new
198    local prebuiltdir=$(getprebuilt)
199    local gccprebuiltdir=$(get_abs_build_var ANDROID_GCC_PREBUILTS)
200
201    # defined in core/config.mk
202    local targetgccversion=$(get_build_var TARGET_GCC_VERSION)
203    local targetgccversion2=$(get_build_var 2ND_TARGET_GCC_VERSION)
204    export TARGET_GCC_VERSION=$targetgccversion
205
206    # The gcc toolchain does not exists for windows/cygwin. In this case, do not reference it.
207    export ANDROID_TOOLCHAIN=
208    export ANDROID_TOOLCHAIN_2ND_ARCH=
209    local ARCH=$(get_build_var TARGET_ARCH)
210    local toolchaindir toolchaindir2=
211    case $ARCH in
212        x86) toolchaindir=x86/x86_64-linux-android-$targetgccversion/bin
213            ;;
214        x86_64) toolchaindir=x86/x86_64-linux-android-$targetgccversion/bin
215            ;;
216        arm) toolchaindir=arm/arm-linux-androideabi-$targetgccversion/bin
217            ;;
218        arm64) toolchaindir=aarch64/aarch64-linux-android-$targetgccversion/bin;
219               toolchaindir2=arm/arm-linux-androideabi-$targetgccversion2/bin
220            ;;
221        *)
222            echo "Can't find toolchain for unknown architecture: $ARCH"
223            toolchaindir=xxxxxxxxx
224            ;;
225    esac
226    if [ -d "$gccprebuiltdir/$toolchaindir" ]; then
227        export ANDROID_TOOLCHAIN=$gccprebuiltdir/$toolchaindir
228    fi
229
230    if [ "$toolchaindir2" -a -d "$gccprebuiltdir/$toolchaindir2" ]; then
231        export ANDROID_TOOLCHAIN_2ND_ARCH=$gccprebuiltdir/$toolchaindir2
232    fi
233
234    export ANDROID_DEV_SCRIPTS=$T/development/scripts:$T/prebuilts/devtools/tools:$T/external/selinux/prebuilts/bin
235
236    # add kernel specific binaries
237    case $(uname -s) in
238        Linux)
239            export ANDROID_DEV_SCRIPTS=$ANDROID_DEV_SCRIPTS:$T/prebuilts/misc/linux-x86/dtc:$T/prebuilts/misc/linux-x86/libufdt
240            ;;
241        *)
242            ;;
243    esac
244
245    ANDROID_BUILD_PATHS=$(get_build_var ANDROID_BUILD_PATHS):$ANDROID_TOOLCHAIN
246    if [ -n "$ANDROID_TOOLCHAIN_2ND_ARCH" ]; then
247        ANDROID_BUILD_PATHS=$ANDROID_BUILD_PATHS:$ANDROID_TOOLCHAIN_2ND_ARCH
248    fi
249    ANDROID_BUILD_PATHS=$ANDROID_BUILD_PATHS:$ANDROID_DEV_SCRIPTS
250
251    # Append llvm binutils prebuilts path to ANDROID_BUILD_PATHS.
252    local ANDROID_LLVM_BINUTILS=$(get_abs_build_var ANDROID_CLANG_PREBUILTS)/llvm-binutils-stable
253    ANDROID_BUILD_PATHS=$ANDROID_BUILD_PATHS:$ANDROID_LLVM_BINUTILS
254
255    # Set up ASAN_SYMBOLIZER_PATH for SANITIZE_HOST=address builds.
256    export ASAN_SYMBOLIZER_PATH=$ANDROID_LLVM_BINUTILS/llvm-symbolizer
257
258    # If prebuilts/android-emulator/<system>/ exists, prepend it to our PATH
259    # to ensure that the corresponding 'emulator' binaries are used.
260    case $(uname -s) in
261        Darwin)
262            ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/darwin-x86_64
263            ;;
264        Linux)
265            ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/linux-x86_64
266            ;;
267        *)
268            ANDROID_EMULATOR_PREBUILTS=
269            ;;
270    esac
271    if [ -n "$ANDROID_EMULATOR_PREBUILTS" -a -d "$ANDROID_EMULATOR_PREBUILTS" ]; then
272        ANDROID_BUILD_PATHS=$ANDROID_BUILD_PATHS:$ANDROID_EMULATOR_PREBUILTS
273        export ANDROID_EMULATOR_PREBUILTS
274    fi
275
276    # Append asuite prebuilts path to ANDROID_BUILD_PATHS.
277    local os_arch=$(get_build_var HOST_PREBUILT_TAG)
278    local ACLOUD_PATH="$T/prebuilts/asuite/acloud/$os_arch"
279    local AIDEGEN_PATH="$T/prebuilts/asuite/aidegen/$os_arch"
280    local ATEST_PATH="$T/prebuilts/asuite/atest/$os_arch"
281    export ANDROID_BUILD_PATHS=$ANDROID_BUILD_PATHS:$ACLOUD_PATH:$AIDEGEN_PATH:$ATEST_PATH:
282
283    export PATH=$ANDROID_BUILD_PATHS$PATH
284
285    # out with the duplicate old
286    if [ -n $ANDROID_PYTHONPATH ]; then
287        export PYTHONPATH=${PYTHONPATH//$ANDROID_PYTHONPATH/}
288    fi
289    # and in with the new
290    export ANDROID_PYTHONPATH=$T/development/python-packages:
291    if [ -n $VENDOR_PYTHONPATH  ]; then
292        ANDROID_PYTHONPATH=$ANDROID_PYTHONPATH$VENDOR_PYTHONPATH
293    fi
294    export PYTHONPATH=$ANDROID_PYTHONPATH$PYTHONPATH
295
296    export ANDROID_JAVA_HOME=$(get_abs_build_var ANDROID_JAVA_HOME)
297    export JAVA_HOME=$ANDROID_JAVA_HOME
298    export ANDROID_JAVA_TOOLCHAIN=$(get_abs_build_var ANDROID_JAVA_TOOLCHAIN)
299    export ANDROID_PRE_BUILD_PATHS=$ANDROID_JAVA_TOOLCHAIN:
300    export PATH=$ANDROID_PRE_BUILD_PATHS$PATH
301
302    unset ANDROID_PRODUCT_OUT
303    export ANDROID_PRODUCT_OUT=$(get_abs_build_var PRODUCT_OUT)
304    export OUT=$ANDROID_PRODUCT_OUT
305
306    unset ANDROID_HOST_OUT
307    export ANDROID_HOST_OUT=$(get_abs_build_var HOST_OUT)
308
309    unset ANDROID_HOST_OUT_TESTCASES
310    export ANDROID_HOST_OUT_TESTCASES=$(get_abs_build_var HOST_OUT_TESTCASES)
311
312    unset ANDROID_TARGET_OUT_TESTCASES
313    export ANDROID_TARGET_OUT_TESTCASES=$(get_abs_build_var TARGET_OUT_TESTCASES)
314
315    # needed for building linux on MacOS
316    # TODO: fix the path
317    #export HOST_EXTRACFLAGS="-I "$T/system/kernel_headers/host_include
318}
319
320function printconfig()
321{
322    local T=$(gettop)
323    if [ ! "$T" ]; then
324        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
325        return
326    fi
327    get_build_var report_config
328}
329
330function set_stuff_for_environment()
331{
332    setpaths
333    set_sequence_number
334
335    export ANDROID_BUILD_TOP=$(gettop)
336    # With this environment variable new GCC can apply colors to warnings/errors
337    export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
338}
339
340function set_sequence_number()
341{
342    export BUILD_ENV_SEQUENCE_NUMBER=13
343}
344
345# Takes a command name, and check if it's in ENVSETUP_NO_COMPLETION or not.
346function should_add_completion() {
347    local cmd="$(basename $1| sed 's/_completion//' |sed 's/\.\(.*\)*sh$//')"
348    case :"$ENVSETUP_NO_COMPLETION": in
349        *:"$cmd":*)
350            return 1
351            ;;
352    esac
353    return 0
354}
355
356function addcompletions()
357{
358    local T dir f
359
360    # Keep us from trying to run in something that's neither bash nor zsh.
361    if [ -z "$BASH_VERSION" -a -z "$ZSH_VERSION" ]; then
362        return
363    fi
364
365    # Keep us from trying to run in bash that's too old.
366    if [ -n "$BASH_VERSION" -a ${BASH_VERSINFO[0]} -lt 3 ]; then
367        return
368    fi
369
370    local completion_files=(
371      system/core/adb/adb.bash
372      system/core/fastboot/fastboot.bash
373      tools/asuite/asuite.sh
374    )
375    # Completion can be disabled selectively to allow users to use non-standard completion.
376    # e.g.
377    # ENVSETUP_NO_COMPLETION=adb # -> disable adb completion
378    # ENVSETUP_NO_COMPLETION=adb:bit # -> disable adb and bit completion
379    for f in ${completion_files[*]}; do
380        if [ -f "$f" ] && should_add_completion "$f"; then
381            . $f
382        fi
383    done
384
385    if should_add_completion bit ; then
386        complete -C "bit --tab" bit
387    fi
388    if [ -z "$ZSH_VERSION" ]; then
389        # Doesn't work in zsh.
390        complete -o nospace -F _croot croot
391    fi
392    complete -F _lunch lunch
393
394    complete -F _complete_android_module_names gomod
395    complete -F _complete_android_module_names m
396}
397
398function choosetype()
399{
400    echo "Build type choices are:"
401    echo "     1. release"
402    echo "     2. debug"
403    echo
404
405    local DEFAULT_NUM DEFAULT_VALUE
406    DEFAULT_NUM=1
407    DEFAULT_VALUE=release
408
409    export TARGET_BUILD_TYPE=
410    local ANSWER
411    while [ -z $TARGET_BUILD_TYPE ]
412    do
413        echo -n "Which would you like? ["$DEFAULT_NUM"] "
414        if [ -z "$1" ] ; then
415            read ANSWER
416        else
417            echo $1
418            ANSWER=$1
419        fi
420        case $ANSWER in
421        "")
422            export TARGET_BUILD_TYPE=$DEFAULT_VALUE
423            ;;
424        1)
425            export TARGET_BUILD_TYPE=release
426            ;;
427        release)
428            export TARGET_BUILD_TYPE=release
429            ;;
430        2)
431            export TARGET_BUILD_TYPE=debug
432            ;;
433        debug)
434            export TARGET_BUILD_TYPE=debug
435            ;;
436        *)
437            echo
438            echo "I didn't understand your response.  Please try again."
439            echo
440            ;;
441        esac
442        if [ -n "$1" ] ; then
443            break
444        fi
445    done
446
447    build_build_var_cache
448    set_stuff_for_environment
449    destroy_build_var_cache
450}
451
452#
453# This function isn't really right:  It chooses a TARGET_PRODUCT
454# based on the list of boards.  Usually, that gets you something
455# that kinda works with a generic product, but really, you should
456# pick a product by name.
457#
458function chooseproduct()
459{
460    local default_value
461    if [ "x$TARGET_PRODUCT" != x ] ; then
462        default_value=$TARGET_PRODUCT
463    else
464        default_value=aosp_arm
465    fi
466
467    export TARGET_BUILD_APPS=
468    export TARGET_PRODUCT=
469    local ANSWER
470    while [ -z "$TARGET_PRODUCT" ]
471    do
472        echo -n "Which product would you like? [$default_value] "
473        if [ -z "$1" ] ; then
474            read ANSWER
475        else
476            echo $1
477            ANSWER=$1
478        fi
479
480        if [ -z "$ANSWER" ] ; then
481            export TARGET_PRODUCT=$default_value
482        else
483            if check_product $ANSWER
484            then
485                export TARGET_PRODUCT=$ANSWER
486            else
487                echo "** Not a valid product: $ANSWER"
488            fi
489        fi
490        if [ -n "$1" ] ; then
491            break
492        fi
493    done
494
495    build_build_var_cache
496    set_stuff_for_environment
497    destroy_build_var_cache
498}
499
500function choosevariant()
501{
502    echo "Variant choices are:"
503    local index=1
504    local v
505    for v in ${VARIANT_CHOICES[@]}
506    do
507        # The product name is the name of the directory containing
508        # the makefile we found, above.
509        echo "     $index. $v"
510        index=$(($index+1))
511    done
512
513    local default_value=eng
514    local ANSWER
515
516    export TARGET_BUILD_VARIANT=
517    while [ -z "$TARGET_BUILD_VARIANT" ]
518    do
519        echo -n "Which would you like? [$default_value] "
520        if [ -z "$1" ] ; then
521            read ANSWER
522        else
523            echo $1
524            ANSWER=$1
525        fi
526
527        if [ -z "$ANSWER" ] ; then
528            export TARGET_BUILD_VARIANT=$default_value
529        elif (echo -n $ANSWER | grep -q -e "^[0-9][0-9]*$") ; then
530            if [ "$ANSWER" -le "${#VARIANT_CHOICES[@]}" ] ; then
531                export TARGET_BUILD_VARIANT=${VARIANT_CHOICES[@]:$(($ANSWER-1)):1}
532            fi
533        else
534            if check_variant $ANSWER
535            then
536                export TARGET_BUILD_VARIANT=$ANSWER
537            else
538                echo "** Not a valid variant: $ANSWER"
539            fi
540        fi
541        if [ -n "$1" ] ; then
542            break
543        fi
544    done
545}
546
547function choosecombo()
548{
549    choosetype $1
550
551    echo
552    echo
553    chooseproduct $2
554
555    echo
556    echo
557    choosevariant $3
558
559    echo
560    build_build_var_cache
561    set_stuff_for_environment
562    printconfig
563    destroy_build_var_cache
564}
565
566function add_lunch_combo()
567{
568    if [ -n "$ZSH_VERSION" ]; then
569        echo -n "${funcfiletrace[1]}: "
570    else
571        echo -n "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: "
572    fi
573    echo "add_lunch_combo is obsolete. Use COMMON_LUNCH_CHOICES in your AndroidProducts.mk instead."
574}
575
576function print_lunch_menu()
577{
578    local uname=$(uname)
579    local choices
580    choices=$(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES 2>/dev/null)
581    local ret=$?
582
583    echo
584    echo "You're building on" $uname
585    echo
586
587    if [ $ret -ne 0 ]
588    then
589        echo "Warning: Cannot display lunch menu."
590        echo
591        echo "Note: You can invoke lunch with an explicit target:"
592        echo
593        echo "  usage: lunch [target]" >&2
594        echo
595        return
596    fi
597
598    echo "Lunch menu... pick a combo:"
599
600    local i=1
601    local choice
602    for choice in $(echo $choices)
603    do
604        echo "     $i. $choice"
605        i=$(($i+1))
606    done
607
608    echo
609}
610
611function lunch()
612{
613    local answer
614
615    if [[ $# -gt 1 ]]; then
616        echo "usage: lunch [target]" >&2
617        return 1
618    fi
619
620    if [ "$1" ]; then
621        answer=$1
622    else
623        print_lunch_menu
624        echo -n "Which would you like? [aosp_arm-eng] "
625        read answer
626    fi
627
628    local selection=
629
630    if [ -z "$answer" ]
631    then
632        selection=aosp_arm-eng
633    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
634    then
635        local choices=($(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES))
636        if [ $answer -le ${#choices[@]} ]
637        then
638            # array in zsh starts from 1 instead of 0.
639            if [ -n "$ZSH_VERSION" ]
640            then
641                selection=${choices[$(($answer))]}
642            else
643                selection=${choices[$(($answer-1))]}
644            fi
645        fi
646    else
647        selection=$answer
648    fi
649
650    export TARGET_BUILD_APPS=
651
652    local product variant_and_version variant version
653    product=${selection%%-*} # Trim everything after first dash
654    variant_and_version=${selection#*-} # Trim everything up to first dash
655    if [ "$variant_and_version" != "$selection" ]; then
656        variant=${variant_and_version%%-*}
657        if [ "$variant" != "$variant_and_version" ]; then
658            version=${variant_and_version#*-}
659        fi
660    fi
661
662    if [ -z "$product" ]
663    then
664        echo
665        echo "Invalid lunch combo: $selection"
666        return 1
667    fi
668
669    TARGET_PRODUCT=$product \
670    TARGET_BUILD_VARIANT=$variant \
671    TARGET_PLATFORM_VERSION=$version \
672    build_build_var_cache
673    if [ $? -ne 0 ]
674    then
675        return 1
676    fi
677    export TARGET_PRODUCT=$(get_build_var TARGET_PRODUCT)
678    export TARGET_BUILD_VARIANT=$(get_build_var TARGET_BUILD_VARIANT)
679    if [ -n "$version" ]; then
680      export TARGET_PLATFORM_VERSION=$(get_build_var TARGET_PLATFORM_VERSION)
681    else
682      unset TARGET_PLATFORM_VERSION
683    fi
684    export TARGET_BUILD_TYPE=release
685
686    [[ -n "${ANDROID_QUIET_BUILD:-}" ]] || echo
687
688    set_stuff_for_environment
689    [[ -n "${ANDROID_QUIET_BUILD:-}" ]] || printconfig
690    destroy_build_var_cache
691}
692
693unset COMMON_LUNCH_CHOICES_CACHE
694# Tab completion for lunch.
695function _lunch()
696{
697    local cur prev opts
698    COMPREPLY=()
699    cur="${COMP_WORDS[COMP_CWORD]}"
700    prev="${COMP_WORDS[COMP_CWORD-1]}"
701
702    if [ -z "$COMMON_LUNCH_CHOICES_CACHE" ]; then
703        COMMON_LUNCH_CHOICES_CACHE=$(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES)
704    fi
705
706    COMPREPLY=( $(compgen -W "${COMMON_LUNCH_CHOICES_CACHE}" -- ${cur}) )
707    return 0
708}
709
710# Configures the build to build unbundled apps.
711# Run tapas with one or more app names (from LOCAL_PACKAGE_NAME)
712function tapas()
713{
714    local showHelp="$(echo $* | xargs -n 1 echo | \grep -E '^(help)$' | xargs)"
715    local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|arm64|x86_64)$' | xargs)"
716    local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)"
717    local density="$(echo $* | xargs -n 1 echo | \grep -E '^(ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi)$' | xargs)"
718    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)$' | xargs)"
719
720    if [ "$showHelp" != "" ]; then
721      $(gettop)/build/make/tapasHelp.sh
722      return
723    fi
724
725    if [ $(echo $arch | wc -w) -gt 1 ]; then
726        echo "tapas: Error: Multiple build archs supplied: $arch"
727        return
728    fi
729    if [ $(echo $variant | wc -w) -gt 1 ]; then
730        echo "tapas: Error: Multiple build variants supplied: $variant"
731        return
732    fi
733    if [ $(echo $density | wc -w) -gt 1 ]; then
734        echo "tapas: Error: Multiple densities supplied: $density"
735        return
736    fi
737
738    local product=aosp_arm
739    case $arch in
740      x86)    product=aosp_x86;;
741      arm64)  product=aosp_arm64;;
742      x86_64) product=aosp_x86_64;;
743    esac
744    if [ -z "$variant" ]; then
745        variant=eng
746    fi
747    if [ -z "$apps" ]; then
748        apps=all
749    fi
750    if [ -z "$density" ]; then
751        density=alldpi
752    fi
753
754    export TARGET_PRODUCT=$product
755    export TARGET_BUILD_VARIANT=$variant
756    export TARGET_BUILD_DENSITY=$density
757    export TARGET_BUILD_TYPE=release
758    export TARGET_BUILD_APPS=$apps
759
760    build_build_var_cache
761    set_stuff_for_environment
762    printconfig
763    destroy_build_var_cache
764}
765
766function gettop
767{
768    local TOPFILE=build/make/core/envsetup.mk
769    if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ] ; then
770        # The following circumlocution ensures we remove symlinks from TOP.
771        (cd $TOP; PWD= /bin/pwd)
772    else
773        if [ -f $TOPFILE ] ; then
774            # The following circumlocution (repeated below as well) ensures
775            # that we record the true directory name and not one that is
776            # faked up with symlink names.
777            PWD= /bin/pwd
778        else
779            local HERE=$PWD
780            local T=
781            while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
782                \cd ..
783                T=`PWD= /bin/pwd -P`
784            done
785            \cd $HERE
786            if [ -f "$T/$TOPFILE" ]; then
787                echo $T
788            fi
789        fi
790    fi
791}
792
793function croot()
794{
795    local T=$(gettop)
796    if [ "$T" ]; then
797        if [ "$1" ]; then
798            \cd $(gettop)/$1
799        else
800            \cd $(gettop)
801        fi
802    else
803        echo "Couldn't locate the top of the tree.  Try setting TOP."
804    fi
805}
806
807function _croot()
808{
809    local T=$(gettop)
810    if [ "$T" ]; then
811        local cur="${COMP_WORDS[COMP_CWORD]}"
812        k=0
813        for c in $(compgen -d ${T}/${cur}); do
814            COMPREPLY[k++]=${c#${T}/}/
815        done
816    fi
817}
818
819function cproj()
820{
821    local TOPFILE=build/make/core/envsetup.mk
822    local HERE=$PWD
823    local T=
824    while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
825        T=$PWD
826        if [ -f "$T/Android.mk" ]; then
827            \cd $T
828            return
829        fi
830        \cd ..
831    done
832    \cd $HERE
833    echo "can't find Android.mk"
834}
835
836# simplified version of ps; output in the form
837# <pid> <procname>
838function qpid() {
839    local prepend=''
840    local append=''
841    if [ "$1" = "--exact" ]; then
842        prepend=' '
843        append='$'
844        shift
845    elif [ "$1" = "--help" -o "$1" = "-h" ]; then
846        echo "usage: qpid [[--exact] <process name|pid>"
847        return 255
848    fi
849
850    local EXE="$1"
851    if [ "$EXE" ] ; then
852        qpid | \grep "$prepend$EXE$append"
853    else
854        adb shell ps \
855            | tr -d '\r' \
856            | sed -e 1d -e 's/^[^ ]* *\([0-9]*\).* \([^ ]*\)$/\1 \2/'
857    fi
858}
859
860# coredump_setup - enable core dumps globally for any process
861#                  that has the core-file-size limit set correctly
862#
863# NOTE: You must call also coredump_enable for a specific process
864#       if its core-file-size limit is not set already.
865# NOTE: Core dumps are written to ramdisk; they will not survive a reboot!
866
867function coredump_setup()
868{
869    echo "Getting root...";
870    adb root;
871    adb wait-for-device;
872
873    echo "Remounting root partition read-write...";
874    adb shell mount -w -o remount -t rootfs rootfs;
875    sleep 1;
876    adb wait-for-device;
877    adb shell mkdir -p /cores;
878    adb shell mount -t tmpfs tmpfs /cores;
879    adb shell chmod 0777 /cores;
880
881    echo "Granting SELinux permission to dump in /cores...";
882    adb shell restorecon -R /cores;
883
884    echo "Set core pattern.";
885    adb shell 'echo /cores/core.%p > /proc/sys/kernel/core_pattern';
886
887    echo "Done."
888}
889
890# coredump_enable - enable core dumps for the specified process
891# $1 = PID of process (e.g., $(pid mediaserver))
892#
893# NOTE: coredump_setup must have been called as well for a core
894#       dump to actually be generated.
895
896function coredump_enable()
897{
898    local PID=$1;
899    if [ -z "$PID" ]; then
900        printf "Expecting a PID!\n";
901        return;
902    fi;
903    echo "Setting core limit for $PID to infinite...";
904    adb shell /system/bin/ulimit -p $PID -c unlimited
905}
906
907# core - send SIGV and pull the core for process
908# $1 = PID of process (e.g., $(pid mediaserver))
909#
910# NOTE: coredump_setup must be called once per boot for core dumps to be
911#       enabled globally.
912
913function core()
914{
915    local PID=$1;
916
917    if [ -z "$PID" ]; then
918        printf "Expecting a PID!\n";
919        return;
920    fi;
921
922    local CORENAME=core.$PID;
923    local COREPATH=/cores/$CORENAME;
924    local SIG=SEGV;
925
926    coredump_enable $1;
927
928    local done=0;
929    while [ $(adb shell "[ -d /proc/$PID ] && echo -n yes") ]; do
930        printf "\tSending SIG%s to %d...\n" $SIG $PID;
931        adb shell kill -$SIG $PID;
932        sleep 1;
933    done;
934
935    adb shell "while [ ! -f $COREPATH ] ; do echo waiting for $COREPATH to be generated; sleep 1; done"
936    echo "Done: core is under $COREPATH on device.";
937}
938
939# systemstack - dump the current stack trace of all threads in the system process
940# to the usual ANR traces file
941function systemstack()
942{
943    stacks system_server
944}
945
946# Read the ELF header from /proc/$PID/exe to determine if the process is
947# 64-bit.
948function is64bit()
949{
950    local PID="$1"
951    if [ "$PID" ] ; then
952        if [[ "$(adb shell cat /proc/$PID/exe | xxd -l 1 -s 4 -p)" -eq "02" ]] ; then
953            echo "64"
954        else
955            echo ""
956        fi
957    else
958        echo ""
959    fi
960}
961
962case `uname -s` in
963    Darwin)
964        function sgrep()
965        {
966            find -E . -name .repo -prune -o -name .git -prune -o  -type f -iregex '.*\.(c|h|cc|cpp|hpp|S|java|xml|sh|mk|aidl|vts|proto)' \
967                -exec grep --color -n "$@" {} +
968        }
969
970        ;;
971    *)
972        function sgrep()
973        {
974            find . -name .repo -prune -o -name .git -prune -o  -type f -iregex '.*\.\(c\|h\|cc\|cpp\|hpp\|S\|java\|xml\|sh\|mk\|aidl\|vts\|proto\)' \
975                -exec grep --color -n "$@" {} +
976        }
977        ;;
978esac
979
980function gettargetarch
981{
982    get_build_var TARGET_ARCH
983}
984
985function ggrep()
986{
987    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.gradle" \
988        -exec grep --color -n "$@" {} +
989}
990
991function gogrep()
992{
993    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.go" \
994        -exec grep --color -n "$@" {} +
995}
996
997function jgrep()
998{
999    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.java" \
1000        -exec grep --color -n "$@" {} +
1001}
1002
1003function cgrep()
1004{
1005    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' \) \
1006        -exec grep --color -n "$@" {} +
1007}
1008
1009function resgrep()
1010{
1011    local dir
1012    for dir in `find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -name res -type d`; do
1013        find $dir -type f -name '*\.xml' -exec grep --color -n "$@" {} +
1014    done
1015}
1016
1017function mangrep()
1018{
1019    find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -type f -name 'AndroidManifest.xml' \
1020        -exec grep --color -n "$@" {} +
1021}
1022
1023function owngrep()
1024{
1025    find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -type f -name 'OWNERS' \
1026        -exec grep --color -n "$@" {} +
1027}
1028
1029function sepgrep()
1030{
1031    find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -name sepolicy -type d \
1032        -exec grep --color -n -r --exclude-dir=\.git "$@" {} +
1033}
1034
1035function rcgrep()
1036{
1037    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.rc*" \
1038        -exec grep --color -n "$@" {} +
1039}
1040
1041case `uname -s` in
1042    Darwin)
1043        function mgrep()
1044        {
1045            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 \
1046                -exec grep --color -n "$@" {} +
1047        }
1048
1049        function treegrep()
1050        {
1051            find -E . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*\.(c|h|cpp|hpp|S|java|xml)' \
1052                -exec grep --color -n -i "$@" {} +
1053        }
1054
1055        ;;
1056    *)
1057        function mgrep()
1058        {
1059            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 \
1060                -exec grep --color -n "$@" {} +
1061        }
1062
1063        function treegrep()
1064        {
1065            find . -name .repo -prune -o -name .git -prune -o -regextype posix-egrep -iregex '.*\.(c|h|cpp|hpp|S|java|xml)' -type f \
1066                -exec grep --color -n -i "$@" {} +
1067        }
1068
1069        ;;
1070esac
1071
1072function getprebuilt
1073{
1074    get_abs_build_var ANDROID_PREBUILTS
1075}
1076
1077function tracedmdump()
1078{
1079    local T=$(gettop)
1080    if [ ! "$T" ]; then
1081        echo "Couldn't locate the top of the tree.  Try setting TOP."
1082        return
1083    fi
1084    local prebuiltdir=$(getprebuilt)
1085    local arch=$(gettargetarch)
1086    local KERNEL=$T/prebuilts/qemu-kernel/$arch/vmlinux-qemu
1087
1088    local TRACE=$1
1089    if [ ! "$TRACE" ] ; then
1090        echo "usage:  tracedmdump  tracename"
1091        return
1092    fi
1093
1094    if [ ! -r "$KERNEL" ] ; then
1095        echo "Error: cannot find kernel: '$KERNEL'"
1096        return
1097    fi
1098
1099    local BASETRACE=$(basename $TRACE)
1100    if [ "$BASETRACE" = "$TRACE" ] ; then
1101        TRACE=$ANDROID_PRODUCT_OUT/traces/$TRACE
1102    fi
1103
1104    echo "post-processing traces..."
1105    rm -f $TRACE/qtrace.dexlist
1106    post_trace $TRACE
1107    if [ $? -ne 0 ]; then
1108        echo "***"
1109        echo "*** Error: malformed trace.  Did you remember to exit the emulator?"
1110        echo "***"
1111        return
1112    fi
1113    echo "generating dexlist output..."
1114    /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
1115    echo "generating dmtrace data..."
1116    q2dm -r $ANDROID_PRODUCT_OUT/symbols $TRACE $KERNEL $TRACE/dmtrace || return
1117    echo "generating html file..."
1118    dmtracedump -h $TRACE/dmtrace >| $TRACE/dmtrace.html || return
1119    echo "done, see $TRACE/dmtrace.html for details"
1120    echo "or run:"
1121    echo "    traceview $TRACE/dmtrace"
1122}
1123
1124# communicate with a running device or emulator, set up necessary state,
1125# and run the hat command.
1126function runhat()
1127{
1128    # process standard adb options
1129    local adbTarget=""
1130    if [ "$1" = "-d" -o "$1" = "-e" ]; then
1131        adbTarget=$1
1132        shift 1
1133    elif [ "$1" = "-s" ]; then
1134        adbTarget="$1 $2"
1135        shift 2
1136    fi
1137    local adbOptions=${adbTarget}
1138    #echo adbOptions = ${adbOptions}
1139
1140    # runhat options
1141    local targetPid=$1
1142
1143    if [ "$targetPid" = "" ]; then
1144        echo "Usage: runhat [ -d | -e | -s serial ] target-pid"
1145        return
1146    fi
1147
1148    # confirm hat is available
1149    if [ -z $(which hat) ]; then
1150        echo "hat is not available in this configuration."
1151        return
1152    fi
1153
1154    # issue "am" command to cause the hprof dump
1155    local devFile=/data/local/tmp/hprof-$targetPid
1156    echo "Poking $targetPid and waiting for data..."
1157    echo "Storing data at $devFile"
1158    adb ${adbOptions} shell am dumpheap $targetPid $devFile
1159    echo "Press enter when logcat shows \"hprof: heap dump completed\""
1160    echo -n "> "
1161    read
1162
1163    local localFile=/tmp/$$-hprof
1164
1165    echo "Retrieving file $devFile..."
1166    adb ${adbOptions} pull $devFile $localFile
1167
1168    adb ${adbOptions} shell rm $devFile
1169
1170    echo "Running hat on $localFile"
1171    echo "View the output by pointing your browser at http://localhost:7000/"
1172    echo ""
1173    hat -JXmx512m $localFile
1174}
1175
1176function getbugreports()
1177{
1178    local reports=(`adb shell ls /sdcard/bugreports | tr -d '\r'`)
1179
1180    if [ ! "$reports" ]; then
1181        echo "Could not locate any bugreports."
1182        return
1183    fi
1184
1185    local report
1186    for report in ${reports[@]}
1187    do
1188        echo "/sdcard/bugreports/${report}"
1189        adb pull /sdcard/bugreports/${report} ${report}
1190        gunzip ${report}
1191    done
1192}
1193
1194function getsdcardpath()
1195{
1196    adb ${adbOptions} shell echo -n \$\{EXTERNAL_STORAGE\}
1197}
1198
1199function getscreenshotpath()
1200{
1201    echo "$(getsdcardpath)/Pictures/Screenshots"
1202}
1203
1204function getlastscreenshot()
1205{
1206    local screenshot_path=$(getscreenshotpath)
1207    local screenshot=`adb ${adbOptions} ls ${screenshot_path} | grep Screenshot_[0-9-]*.*\.png | sort -rk 3 | cut -d " " -f 4 | head -n 1`
1208    if [ "$screenshot" = "" ]; then
1209        echo "No screenshots found."
1210        return
1211    fi
1212    echo "${screenshot}"
1213    adb ${adbOptions} pull ${screenshot_path}/${screenshot}
1214}
1215
1216function startviewserver()
1217{
1218    local port=4939
1219    if [ $# -gt 0 ]; then
1220            port=$1
1221    fi
1222    adb shell service call window 1 i32 $port
1223}
1224
1225function stopviewserver()
1226{
1227    adb shell service call window 2
1228}
1229
1230function isviewserverstarted()
1231{
1232    adb shell service call window 3
1233}
1234
1235function key_home()
1236{
1237    adb shell input keyevent 3
1238}
1239
1240function key_back()
1241{
1242    adb shell input keyevent 4
1243}
1244
1245function key_menu()
1246{
1247    adb shell input keyevent 82
1248}
1249
1250function smoketest()
1251{
1252    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
1253        echo "Couldn't locate output files.  Try running 'lunch' first." >&2
1254        return
1255    fi
1256    local T=$(gettop)
1257    if [ ! "$T" ]; then
1258        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
1259        return
1260    fi
1261
1262    (\cd "$T" && mmm tests/SmokeTest) &&
1263      adb uninstall com.android.smoketest > /dev/null &&
1264      adb uninstall com.android.smoketest.tests > /dev/null &&
1265      adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTestApp.apk &&
1266      adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTest.apk &&
1267      adb shell am instrument -w com.android.smoketest.tests/android.test.InstrumentationTestRunner
1268}
1269
1270# simple shortcut to the runtest command
1271function runtest()
1272{
1273    local T=$(gettop)
1274    if [ ! "$T" ]; then
1275        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
1276        return
1277    fi
1278    ("$T"/development/testrunner/runtest.py $@)
1279}
1280
1281function godir () {
1282    if [[ -z "$1" ]]; then
1283        echo "Usage: godir <regex>"
1284        return
1285    fi
1286    local T=$(gettop)
1287    local FILELIST
1288    if [ ! "$OUT_DIR" = "" ]; then
1289        mkdir -p $OUT_DIR
1290        FILELIST=$OUT_DIR/filelist
1291    else
1292        FILELIST=$T/filelist
1293    fi
1294    if [[ ! -f $FILELIST ]]; then
1295        echo -n "Creating index..."
1296        (\cd $T; find . -wholename ./out -prune -o -wholename ./.repo -prune -o -type f > $FILELIST)
1297        echo " Done"
1298        echo ""
1299    fi
1300    local lines
1301    lines=($(\grep "$1" $FILELIST | sed -e 's/\/[^/]*$//' | sort | uniq))
1302    if [[ ${#lines[@]} = 0 ]]; then
1303        echo "Not found"
1304        return
1305    fi
1306    local pathname
1307    local choice
1308    if [[ ${#lines[@]} > 1 ]]; then
1309        while [[ -z "$pathname" ]]; do
1310            local index=1
1311            local line
1312            for line in ${lines[@]}; do
1313                printf "%6s %s\n" "[$index]" $line
1314                index=$(($index + 1))
1315            done
1316            echo
1317            echo -n "Select one: "
1318            unset choice
1319            read choice
1320            if [[ $choice -gt ${#lines[@]} || $choice -lt 1 ]]; then
1321                echo "Invalid choice"
1322                continue
1323            fi
1324            pathname=${lines[@]:$(($choice-1)):1}
1325        done
1326    else
1327        pathname=${lines[@]:0:1}
1328    fi
1329    \cd $T/$pathname
1330}
1331
1332# Update module-info.json in out.
1333function refreshmod() {
1334    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
1335        echo "No ANDROID_PRODUCT_OUT. Try running 'lunch' first." >&2
1336        return 1
1337    fi
1338
1339    echo "Refreshing modules (building module-info.json). Log at $ANDROID_PRODUCT_OUT/module-info.json.build.log." >&2
1340
1341    # for the output of the next command
1342    mkdir -p $ANDROID_PRODUCT_OUT || return 1
1343
1344    # Note, can't use absolute path because of the way make works.
1345    m out/target/product/$(get_build_var TARGET_DEVICE)/module-info.json \
1346        > $ANDROID_PRODUCT_OUT/module-info.json.build.log 2>&1
1347}
1348
1349# List all modules for the current device, as cached in module-info.json. If any build change is
1350# made and it should be reflected in the output, you should run 'refreshmod' first.
1351function allmod() {
1352    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
1353        echo "No ANDROID_PRODUCT_OUT. Try running 'lunch' first." >&2
1354        return 1
1355    fi
1356
1357    if [ ! -f "$ANDROID_PRODUCT_OUT/module-info.json" ]; then
1358        echo "Could not find module-info.json. It will only be built once, and it can be updated with 'refreshmod'" >&2
1359        refreshmod || return 1
1360    fi
1361
1362    python -c "import json; print('\n'.join(sorted(json.load(open('$ANDROID_PRODUCT_OUT/module-info.json')).keys())))"
1363}
1364
1365# Get the path of a specific module in the android tree, as cached in module-info.json. If any build change
1366# is made, and it should be reflected in the output, you should run 'refreshmod' first.
1367function pathmod() {
1368    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
1369        echo "No ANDROID_PRODUCT_OUT. Try running 'lunch' first." >&2
1370        return 1
1371    fi
1372
1373    if [[ $# -ne 1 ]]; then
1374        echo "usage: pathmod <module>" >&2
1375        return 1
1376    fi
1377
1378    if [ ! -f "$ANDROID_PRODUCT_OUT/module-info.json" ]; then
1379        echo "Could not find module-info.json. It will only be built once, and it can be updated with 'refreshmod'" >&2
1380        refreshmod || return 1
1381    fi
1382
1383    local relpath=$(python -c "import json, os
1384module = '$1'
1385module_info = json.load(open('$ANDROID_PRODUCT_OUT/module-info.json'))
1386if module not in module_info:
1387    exit(1)
1388print(module_info[module]['path'][0])" 2>/dev/null)
1389
1390    if [ -z "$relpath" ]; then
1391        echo "Could not find module '$1' (try 'refreshmod' if there have been build changes?)." >&2
1392        return 1
1393    else
1394        echo "$ANDROID_BUILD_TOP/$relpath"
1395    fi
1396}
1397
1398# Go to a specific module in the android tree, as cached in module-info.json. If any build change
1399# is made, and it should be reflected in the output, you should run 'refreshmod' first.
1400function gomod() {
1401    if [[ $# -ne 1 ]]; then
1402        echo "usage: gomod <module>" >&2
1403        return 1
1404    fi
1405
1406    local path="$(pathmod $@)"
1407    if [ -z "$path" ]; then
1408        return 1
1409    fi
1410    cd $path
1411}
1412
1413function _complete_android_module_names() {
1414    local word=${COMP_WORDS[COMP_CWORD]}
1415    COMPREPLY=( $(allmod | grep -E "^$word") )
1416}
1417
1418# Print colored exit condition
1419function pez {
1420    "$@"
1421    local retval=$?
1422    if [ $retval -ne 0 ]
1423    then
1424        echo $'\E'"[0;31mFAILURE\e[00m"
1425    else
1426        echo $'\E'"[0;32mSUCCESS\e[00m"
1427    fi
1428    return $retval
1429}
1430
1431function get_make_command()
1432{
1433    # If we're in the top of an Android tree, use soong_ui.bash instead of make
1434    if [ -f build/soong/soong_ui.bash ]; then
1435        # Always use the real make if -C is passed in
1436        for arg in "$@"; do
1437            if [[ $arg == -C* ]]; then
1438                echo command make
1439                return
1440            fi
1441        done
1442        echo build/soong/soong_ui.bash --make-mode
1443    else
1444        echo command make
1445    fi
1446}
1447
1448function _wrap_build()
1449{
1450    if [[ "${ANDROID_QUIET_BUILD:-}" == true ]]; then
1451      "$@"
1452      return $?
1453    fi
1454    local start_time=$(date +"%s")
1455    "$@"
1456    local ret=$?
1457    local end_time=$(date +"%s")
1458    local tdiff=$(($end_time-$start_time))
1459    local hours=$(($tdiff / 3600 ))
1460    local mins=$((($tdiff % 3600) / 60))
1461    local secs=$(($tdiff % 60))
1462    local ncolors=$(tput colors 2>/dev/null)
1463    if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then
1464        color_failed=$'\E'"[0;31m"
1465        color_success=$'\E'"[0;32m"
1466        color_reset=$'\E'"[00m"
1467    else
1468        color_failed=""
1469        color_success=""
1470        color_reset=""
1471    fi
1472    echo
1473    if [ $ret -eq 0 ] ; then
1474        echo -n "${color_success}#### build completed successfully "
1475    else
1476        echo -n "${color_failed}#### failed to build some targets "
1477    fi
1478    if [ $hours -gt 0 ] ; then
1479        printf "(%02g:%02g:%02g (hh:mm:ss))" $hours $mins $secs
1480    elif [ $mins -gt 0 ] ; then
1481        printf "(%02g:%02g (mm:ss))" $mins $secs
1482    elif [ $secs -gt 0 ] ; then
1483        printf "(%s seconds)" $secs
1484    fi
1485    echo " ####${color_reset}"
1486    echo
1487    return $ret
1488}
1489
1490function _trigger_build()
1491(
1492    local -r bc="$1"; shift
1493    if T="$(gettop)"; then
1494      _wrap_build "$T/build/soong/soong_ui.bash" --build-mode --${bc} --dir="$(pwd)" "$@"
1495    else
1496      echo "Couldn't locate the top of the tree. Try setting TOP."
1497    fi
1498)
1499
1500function m()
1501(
1502    _trigger_build "all-modules" "$@"
1503)
1504
1505function mm()
1506(
1507    _trigger_build "modules-in-a-dir-no-deps" "$@"
1508)
1509
1510function mmm()
1511(
1512    _trigger_build "modules-in-dirs-no-deps" "$@"
1513)
1514
1515function mma()
1516(
1517    _trigger_build "modules-in-a-dir" "$@"
1518)
1519
1520function mmma()
1521(
1522    _trigger_build "modules-in-dirs" "$@"
1523)
1524
1525function make()
1526{
1527    _wrap_build $(get_make_command "$@") "$@"
1528}
1529
1530function provision()
1531{
1532    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
1533        echo "Couldn't locate output files.  Try running 'lunch' first." >&2
1534        return 1
1535    fi
1536    if [ ! -e "$ANDROID_PRODUCT_OUT/provision-device" ]; then
1537        echo "There is no provisioning script for the device." >&2
1538        return 1
1539    fi
1540
1541    # Check if user really wants to do this.
1542    if [ "$1" = "--no-confirmation" ]; then
1543        shift 1
1544    else
1545        echo "This action will reflash your device."
1546        echo ""
1547        echo "ALL DATA ON THE DEVICE WILL BE IRREVOCABLY ERASED."
1548        echo ""
1549        echo -n "Are you sure you want to do this (yes/no)? "
1550        read
1551        if [[ "${REPLY}" != "yes" ]] ; then
1552            echo "Not taking any action. Exiting." >&2
1553            return 1
1554        fi
1555    fi
1556    "$ANDROID_PRODUCT_OUT/provision-device" "$@"
1557}
1558
1559# Zsh needs bashcompinit called to support bash-style completion.
1560function enable_zsh_completion() {
1561    # Don't override user's options if bash-style completion is already enabled.
1562    if ! declare -f complete >/dev/null; then
1563        autoload -U compinit && compinit
1564        autoload -U bashcompinit && bashcompinit
1565    fi
1566}
1567
1568function validate_current_shell() {
1569    local current_sh="$(ps -o command -p $$)"
1570    case "$current_sh" in
1571        *bash*)
1572            function check_type() { type -t "$1"; }
1573            ;;
1574        *zsh*)
1575            function check_type() { type "$1"; }
1576            enable_zsh_completion ;;
1577        *)
1578            echo -e "WARNING: Only bash and zsh are supported.\nUse of other shell would lead to erroneous results."
1579            ;;
1580    esac
1581}
1582
1583# Execute the contents of any vendorsetup.sh files we can find.
1584# Unless we find an allowed-vendorsetup_sh-files file, in which case we'll only
1585# load those.
1586#
1587# This allows loading only approved vendorsetup.sh files
1588function source_vendorsetup() {
1589    unset VENDOR_PYTHONPATH
1590    allowed=
1591    for f in $(find -L device vendor product -maxdepth 4 -name 'allowed-vendorsetup_sh-files' 2>/dev/null | sort); do
1592        if [ -n "$allowed" ]; then
1593            echo "More than one 'allowed_vendorsetup_sh-files' file found, not including any vendorsetup.sh files:"
1594            echo "  $allowed"
1595            echo "  $f"
1596            return
1597        fi
1598        allowed="$f"
1599    done
1600
1601    allowed_files=
1602    [ -n "$allowed" ] && allowed_files=$(cat "$allowed")
1603    for dir in device vendor product; do
1604        for f in $(test -d $dir && \
1605            find -L $dir -maxdepth 4 -name 'vendorsetup.sh' 2>/dev/null | sort); do
1606
1607            if [[ -z "$allowed" || "$allowed_files" =~ $f ]]; then
1608                echo "including $f"; . "$f"
1609            else
1610                echo "ignoring $f, not in $allowed"
1611            fi
1612        done
1613    done
1614}
1615
1616validate_current_shell
1617source_vendorsetup
1618addcompletions
1619