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