OSDN Git Service

envsetup: Don't tread on my $PROMPT_COMMAND
[android-x86/build.git] / envsetup.sh
1 function hmm() {
2 cat <<EOF
3 Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
4 - lunch:     lunch <product_name>-<build_variant>
5 - tapas:     tapas [<App1> <App2> ...] [arm|x86|mips|armv5|arm64|x86_64|mips64] [eng|userdebug|user]
6 - croot:     Changes directory to the top of the tree.
7 - m:         Makes from the top of the tree.
8 - mm:        Builds all of the modules in the current directory, but not their dependencies.
9 - mmm:       Builds all of the modules in the supplied directories, but not their dependencies.
10              To limit the modules being built use the syntax: mmm dir/:target1,target2.
11 - mma:       Builds all of the modules in the current directory, and their dependencies.
12 - mmma:      Builds all of the modules in the supplied directories, and their dependencies.
13 - mmp:       Builds all of the modules in the current directory and pushes them to the device.
14 - mmmp:      Builds all of the modules in the supplied directories and pushes them to the device.
15 - provision: Flash device with all required partitions. Options will be passed on to fastboot.
16 - cgrep:     Greps on all local C/C++ files.
17 - ggrep:     Greps on all local Gradle files.
18 - jgrep:     Greps on all local Java files.
19 - resgrep:   Greps on all local res/*.xml files.
20 - mangrep:   Greps on all local AndroidManifest.xml files.
21 - mgrep:     Greps on all local Makefiles files.
22 - sepgrep:   Greps on all local sepolicy files.
23 - sgrep:     Greps on all local source files.
24 - godir:     Go to the directory containing a file.
25 - cmremote:  Add git remote for CM Gerrit Review
26 - cmgerrit:  A Git wrapper that fetches/pushes patch from/to CM Gerrit Review
27 - aospremote: Add git remote for matching AOSP repository
28 - cmrebase:  Rebase a Gerrit change and push it again
29 - mka:       Builds using SCHED_BATCH on all processors
30 - reposync:  Parallel repo sync using ionice and SCHED_BATCH
31 - installboot: Installs a boot.img to the connected device.
32 - installrecovery: Installs a recovery.img to the connected device.
33 - repodiff:  Diff 2 different branches or tags within the same repo
34
35 Environment options:
36 - SANITIZE_HOST: Set to 'true' to use ASAN for all host modules. Note that
37                  ASAN_OPTIONS=detect_leaks=0 will be set by default until the
38                  build is leak-check clean.
39
40 Look at the source to view more functions. The complete list is:
41 EOF
42     T=$(gettop)
43     local A
44     A=""
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.
52 function build_build_var_cache()
53 {
54     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=`\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
60                         command make --no-print-directory -f build/core/config.mk \
61                         dump-many-vars \
62                         DUMP_MANY_VARS="$cached_vars" \
63                         DUMP_MANY_ABS_VARS="$cached_abs_vars" \
64                         DUMP_VAR_PREFIX="var_cache_" \
65                         DUMP_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     # Excute 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.
85 function destroy_build_var_cache()
86 {
87     unset BUILD_VAR_CACHE_READY
88     for v in $cached_vars; do
89       unset var_cache_$v
90     done
91     unset cached_vars
92     for v in $cached_abs_vars; do
93       unset abs_var_cache_$v
94     done
95     unset cached_abs_vars
96 }
97
98 # Get the value of a build variable as an absolute path.
99 function get_abs_build_var()
100 {
101     if [ "$BUILD_VAR_CACHE_READY" = "true" ]
102     then
103         eval echo \"\${abs_var_cache_$1}\"
104     return
105     fi
106
107     T=$(gettop)
108     if [ ! "$T" ]; then
109         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
110         return
111     fi
112     (\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
113       command make --no-print-directory -f build/core/config.mk dumpvar-abs-$1)
114 }
115
116 # Get the exact value of a build variable.
117 function get_build_var()
118 {
119     if [ "$BUILD_VAR_CACHE_READY" = "true" ]
120     then
121         eval echo \"\${var_cache_$1}\"
122     return
123     fi
124
125     T=$(gettop)
126     if [ ! "$T" ]; then
127         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
128         return
129     fi
130     (\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
131       command make --no-print-directory -f build/core/config.mk dumpvar-$1)
132 }
133
134 # check to see if the supplied product is one we can build
135 function check_product()
136 {
137     T=$(gettop)
138     if [ ! "$T" ]; then
139         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
140         return
141     fi
142
143     if (echo -n $1 | grep -q -e "^cm_") ; then
144        CM_BUILD=$(echo -n $1 | sed -e 's/^cm_//g')
145     else
146        CM_BUILD=
147     fi
148     export CM_BUILD
149
150         TARGET_PRODUCT=$1 \
151         TARGET_BUILD_VARIANT= \
152         TARGET_BUILD_TYPE= \
153         TARGET_BUILD_APPS= \
154         get_build_var TARGET_DEVICE > /dev/null
155     # hide successful answers, but allow the errors to show
156 }
157
158 VARIANT_CHOICES=(user userdebug eng)
159
160 # check to see if the supplied variant is valid
161 function check_variant()
162 {
163     for v in ${VARIANT_CHOICES[@]}
164     do
165         if [ "$v" = "$1" ]
166         then
167             return 0
168         fi
169     done
170     return 1
171 }
172
173 function setpaths()
174 {
175     T=$(gettop)
176     if [ ! "$T" ]; then
177         echo "Couldn't locate the top of the tree.  Try setting TOP."
178         return
179     fi
180
181     ##################################################################
182     #                                                                #
183     #              Read me before you modify this code               #
184     #                                                                #
185     #   This function sets ANDROID_BUILD_PATHS to what it is adding  #
186     #   to PATH, and the next time it is run, it removes that from   #
187     #   PATH.  This is required so lunch can be run more than once   #
188     #   and still have working paths.                                #
189     #                                                                #
190     ##################################################################
191
192     # Note: on windows/cygwin, ANDROID_BUILD_PATHS will contain spaces
193     # due to "C:\Program Files" being in the path.
194
195     # out with the old
196     if [ -n "$ANDROID_BUILD_PATHS" ] ; then
197         export PATH=${PATH/$ANDROID_BUILD_PATHS/}
198     fi
199     if [ -n "$ANDROID_PRE_BUILD_PATHS" ] ; then
200         export PATH=${PATH/$ANDROID_PRE_BUILD_PATHS/}
201         # strip leading ':', if any
202         export PATH=${PATH/:%/}
203     fi
204
205     # and in with the new
206     prebuiltdir=$(getprebuilt)
207     gccprebuiltdir=$(get_abs_build_var ANDROID_GCC_PREBUILTS)
208
209     # defined in core/config.mk
210     targetgccversion=$(get_build_var TARGET_GCC_VERSION)
211     targetgccversion2=$(get_build_var 2ND_TARGET_GCC_VERSION)
212     export TARGET_GCC_VERSION=$targetgccversion
213
214     # The gcc toolchain does not exists for windows/cygwin. In this case, do not reference it.
215     export ANDROID_TOOLCHAIN=
216     export ANDROID_TOOLCHAIN_2ND_ARCH=
217     local ARCH=$(get_build_var TARGET_ARCH)
218     case $ARCH in
219         x86) toolchaindir=x86/x86_64-linux-android-$targetgccversion/bin
220             ;;
221         x86_64) toolchaindir=x86/x86_64-linux-android-$targetgccversion/bin
222             ;;
223         arm) toolchaindir=arm/arm-linux-androideabi-$targetgccversion/bin
224             ;;
225         arm64) toolchaindir=aarch64/aarch64-linux-android-$targetgccversion/bin;
226                toolchaindir2=arm/arm-linux-androideabi-$targetgccversion2/bin
227             ;;
228         mips|mips64) toolchaindir=mips/mips64el-linux-android-$targetgccversion/bin
229             ;;
230         *)
231             echo "Can't find toolchain for unknown architecture: $ARCH"
232             toolchaindir=xxxxxxxxx
233             ;;
234     esac
235     if [ -d "$gccprebuiltdir/$toolchaindir" ]; then
236         export ANDROID_TOOLCHAIN=$gccprebuiltdir/$toolchaindir
237     fi
238
239     if [ -d "$gccprebuiltdir/$toolchaindir2" ]; then
240         export ANDROID_TOOLCHAIN_2ND_ARCH=$gccprebuiltdir/$toolchaindir2
241     fi
242
243     export ANDROID_DEV_SCRIPTS=$T/development/scripts:$T/prebuilts/devtools/tools:$T/external/selinux/prebuilts/bin
244     export ANDROID_BUILD_PATHS=$(get_build_var ANDROID_BUILD_PATHS):$ANDROID_TOOLCHAIN:$ANDROID_TOOLCHAIN_2ND_ARCH:$ANDROID_DEV_SCRIPTS:
245
246     # If prebuilts/android-emulator/<system>/ exists, prepend it to our PATH
247     # to ensure that the corresponding 'emulator' binaries are used.
248     case $(uname -s) in
249         Darwin)
250             ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/darwin-x86_64
251             ;;
252         Linux)
253             ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/linux-x86_64
254             ;;
255         *)
256             ANDROID_EMULATOR_PREBUILTS=
257             ;;
258     esac
259     if [ -n "$ANDROID_EMULATOR_PREBUILTS" -a -d "$ANDROID_EMULATOR_PREBUILTS" ]; then
260         ANDROID_BUILD_PATHS=$ANDROID_BUILD_PATHS$ANDROID_EMULATOR_PREBUILTS:
261         export ANDROID_EMULATOR_PREBUILTS
262     fi
263
264     export PATH=$ANDROID_BUILD_PATHS$PATH
265     export PYTHONPATH=$T/development/python-packages:$PYTHONPATH
266
267     unset ANDROID_JAVA_TOOLCHAIN
268     unset ANDROID_PRE_BUILD_PATHS
269     if [ -n "$JAVA_HOME" ]; then
270         export ANDROID_JAVA_TOOLCHAIN=$JAVA_HOME/bin
271         export ANDROID_PRE_BUILD_PATHS=$ANDROID_JAVA_TOOLCHAIN:
272         export PATH=$ANDROID_PRE_BUILD_PATHS$PATH
273     fi
274
275     unset ANDROID_PRODUCT_OUT
276     export ANDROID_PRODUCT_OUT=$(get_abs_build_var PRODUCT_OUT)
277     export OUT=$ANDROID_PRODUCT_OUT
278
279     unset ANDROID_HOST_OUT
280     export ANDROID_HOST_OUT=$(get_abs_build_var HOST_OUT)
281
282     # needed for building linux on MacOS
283     # TODO: fix the path
284     #export HOST_EXTRACFLAGS="-I "$T/system/kernel_headers/host_include
285 }
286
287 function printconfig()
288 {
289     T=$(gettop)
290     if [ ! "$T" ]; then
291         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
292         return
293     fi
294     get_build_var report_config
295 }
296
297 function set_stuff_for_environment()
298 {
299     settitle
300     set_java_home
301     setpaths
302     set_sequence_number
303
304     export ANDROID_BUILD_TOP=$(gettop)
305     # With this environment variable new GCC can apply colors to warnings/errors
306     export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
307     export ASAN_OPTIONS=detect_leaks=0
308 }
309
310 function set_sequence_number()
311 {
312     export BUILD_ENV_SEQUENCE_NUMBER=10
313 }
314
315 function settitle()
316 {
317     if [ "$STAY_OFF_MY_LAWN" = "" ]; then
318         local arch=$(gettargetarch)
319         local product=$TARGET_PRODUCT
320         local variant=$TARGET_BUILD_VARIANT
321         local apps=$TARGET_BUILD_APPS
322         if [ -z "$PROMPT_COMMAND"  ]; then
323             # No prompts
324             PROMPT_COMMAND="echo -ne \"\033]0;${USER}@${HOSTNAME}: ${PWD}\007\""
325         elif [ -z "$(echo $PROMPT_COMMAND | grep '033]0;')" ]; then
326             # Prompts exist, but no hardstatus
327             PROMPT_COMMAND="echo -ne \"\033]0;${USER}@${HOSTNAME}: ${PWD}\007\";${PROMPT_COMMAND}"
328         fi
329         if [ ! -z "$ANDROID_PROMPT_PREFIX" ]; then
330             PROMPT_COMMAND=$(echo $PROMPT_COMMAND | sed -e 's/$ANDROID_PROMPT_PREFIX //g')
331         fi
332
333         if [ -z "$apps" ]; then
334             ANDROID_PROMPT_PREFIX="[${arch}-${product}-${variant}]"
335         else
336             ANDROID_PROMPT_PREFIX="[$arch $apps $variant]"
337         fi
338         export ANDROID_PROMPT_PREFIX
339
340         # Inject build data into hardstatus
341         export PROMPT_COMMAND="$(echo $PROMPT_COMMAND | sed -e 's/\\033]0;\(.*\)\\007/\\033]0;$ANDROID_PROMPT_PREFIX \1\\007/g')"
342     fi
343 }
344
345 function addcompletions()
346 {
347     local T dir f
348
349     # Keep us from trying to run in something that isn't bash.
350     if [ -z "${BASH_VERSION}" ]; then
351         return
352     fi
353
354     # Keep us from trying to run in bash that's too old.
355     if [ ${BASH_VERSINFO[0]} -lt 3 ]; then
356         return
357     fi
358
359     dir="sdk/bash_completion"
360     if [ -d ${dir} ]; then
361         for f in `/bin/ls ${dir}/[a-z]*.bash 2> /dev/null`; do
362             echo "including $f"
363             . $f
364         done
365     fi
366 }
367
368 function choosetype()
369 {
370     echo "Build type choices are:"
371     echo "     1. release"
372     echo "     2. debug"
373     echo
374
375     local DEFAULT_NUM DEFAULT_VALUE
376     DEFAULT_NUM=1
377     DEFAULT_VALUE=release
378
379     export TARGET_BUILD_TYPE=
380     local ANSWER
381     while [ -z $TARGET_BUILD_TYPE ]
382     do
383         echo -n "Which would you like? ["$DEFAULT_NUM"] "
384         if [ -z "$1" ] ; then
385             read ANSWER
386         else
387             echo $1
388             ANSWER=$1
389         fi
390         case $ANSWER in
391         "")
392             export TARGET_BUILD_TYPE=$DEFAULT_VALUE
393             ;;
394         1)
395             export TARGET_BUILD_TYPE=release
396             ;;
397         release)
398             export TARGET_BUILD_TYPE=release
399             ;;
400         2)
401             export TARGET_BUILD_TYPE=debug
402             ;;
403         debug)
404             export TARGET_BUILD_TYPE=debug
405             ;;
406         *)
407             echo
408             echo "I didn't understand your response.  Please try again."
409             echo
410             ;;
411         esac
412         if [ -n "$1" ] ; then
413             break
414         fi
415     done
416
417     build_build_var_cache
418     set_stuff_for_environment
419     destroy_build_var_cache
420 }
421
422 #
423 # This function isn't really right:  It chooses a TARGET_PRODUCT
424 # based on the list of boards.  Usually, that gets you something
425 # that kinda works with a generic product, but really, you should
426 # pick a product by name.
427 #
428 function chooseproduct()
429 {
430     if [ "x$TARGET_PRODUCT" != x ] ; then
431         default_value=$TARGET_PRODUCT
432     else
433         default_value=aosp_arm
434     fi
435
436     export TARGET_BUILD_APPS=
437     export TARGET_PRODUCT=
438     local ANSWER
439     while [ -z "$TARGET_PRODUCT" ]
440     do
441         echo -n "Which product would you like? [$default_value] "
442         if [ -z "$1" ] ; then
443             read ANSWER
444         else
445             echo $1
446             ANSWER=$1
447         fi
448
449         if [ -z "$ANSWER" ] ; then
450             export TARGET_PRODUCT=$default_value
451         else
452             if check_product $ANSWER
453             then
454                 export TARGET_PRODUCT=$ANSWER
455             else
456                 echo "** Not a valid product: $ANSWER"
457             fi
458         fi
459         if [ -n "$1" ] ; then
460             break
461         fi
462     done
463
464     build_build_var_cache
465     set_stuff_for_environment
466     destroy_build_var_cache
467 }
468
469 function choosevariant()
470 {
471     echo "Variant choices are:"
472     local index=1
473     local v
474     for v in ${VARIANT_CHOICES[@]}
475     do
476         # The product name is the name of the directory containing
477         # the makefile we found, above.
478         echo "     $index. $v"
479         index=$(($index+1))
480     done
481
482     local default_value=eng
483     local ANSWER
484
485     export TARGET_BUILD_VARIANT=
486     while [ -z "$TARGET_BUILD_VARIANT" ]
487     do
488         echo -n "Which would you like? [$default_value] "
489         if [ -z "$1" ] ; then
490             read ANSWER
491         else
492             echo $1
493             ANSWER=$1
494         fi
495
496         if [ -z "$ANSWER" ] ; then
497             export TARGET_BUILD_VARIANT=$default_value
498         elif (echo -n $ANSWER | grep -q -e "^[0-9][0-9]*$") ; then
499             if [ "$ANSWER" -le "${#VARIANT_CHOICES[@]}" ] ; then
500                 export TARGET_BUILD_VARIANT=${VARIANT_CHOICES[$(($ANSWER-1))]}
501             fi
502         else
503             if check_variant $ANSWER
504             then
505                 export TARGET_BUILD_VARIANT=$ANSWER
506             else
507                 echo "** Not a valid variant: $ANSWER"
508             fi
509         fi
510         if [ -n "$1" ] ; then
511             break
512         fi
513     done
514 }
515
516 function choosecombo()
517 {
518     choosetype $1
519
520     echo
521     echo
522     chooseproduct $2
523
524     echo
525     echo
526     choosevariant $3
527
528     echo
529     build_build_var_cache
530     set_stuff_for_environment
531     printconfig
532     destroy_build_var_cache
533 }
534
535 # Clear this variable.  It will be built up again when the vendorsetup.sh
536 # files are included at the end of this file.
537 unset LUNCH_MENU_CHOICES
538 function add_lunch_combo()
539 {
540     local new_combo=$1
541     local c
542     for c in ${LUNCH_MENU_CHOICES[@]} ; do
543         if [ "$new_combo" = "$c" ] ; then
544             return
545         fi
546     done
547     LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
548 }
549
550 # add the default one here
551 add_lunch_combo aosp_arm-eng
552 add_lunch_combo aosp_arm64-eng
553 add_lunch_combo aosp_mips-eng
554 add_lunch_combo aosp_mips64-eng
555 add_lunch_combo aosp_x86-eng
556 add_lunch_combo aosp_x86_64-eng
557
558 function print_lunch_menu()
559 {
560     local uname=$(uname)
561     echo
562     echo "You're building on" $uname
563     if [ "$(uname)" = "Darwin" ] ; then
564        echo "  (ohai, koush!)"
565     fi
566     echo
567     if [ "z${CM_DEVICES_ONLY}" != "z" ]; then
568        echo "Breakfast menu... pick a combo:"
569     else
570        echo "Lunch menu... pick a combo:"
571     fi
572
573     local i=1
574     local choice
575     for choice in ${LUNCH_MENU_CHOICES[@]}
576     do
577         echo "     $i. $choice"
578         i=$(($i+1))
579     done
580
581     if [ "z${CM_DEVICES_ONLY}" != "z" ]; then
582        echo "... and don't forget the bacon!"
583     fi
584
585     echo
586 }
587
588 function brunch()
589 {
590     breakfast $*
591     if [ $? -eq 0 ]; then
592         mka bacon
593     else
594         echo "No such item in brunch menu. Try 'breakfast'"
595         return 1
596     fi
597     return $?
598 }
599
600 function breakfast()
601 {
602     target=$1
603     CM_DEVICES_ONLY="true"
604     unset LUNCH_MENU_CHOICES
605     add_lunch_combo full-eng
606     for f in `/bin/ls vendor/cm/vendorsetup.sh 2> /dev/null`
607         do
608             echo "including $f"
609             . $f
610         done
611     unset f
612
613     if [ $# -eq 0 ]; then
614         # No arguments, so let's have the full menu
615         lunch
616     else
617         echo "z$target" | grep -q "-"
618         if [ $? -eq 0 ]; then
619             # A buildtype was specified, assume a full device name
620             lunch $target
621         else
622             # This is probably just the CM model name
623             lunch cm_$target-userdebug
624         fi
625     fi
626     return $?
627 }
628
629 alias bib=breakfast
630
631 function lunch()
632 {
633     local answer
634
635     if [ "$1" ] ; then
636         answer=$1
637     else
638         print_lunch_menu
639         echo -n "Which would you like? [aosp_arm-eng] "
640         read answer
641     fi
642
643     local selection=
644
645     if [ -z "$answer" ]
646     then
647         selection=aosp_arm-eng
648     elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
649     then
650         if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
651         then
652             selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}
653         fi
654     elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
655     then
656         selection=$answer
657     fi
658
659     if [ -z "$selection" ]
660     then
661         echo
662         echo "Invalid lunch combo: $answer"
663         return 1
664     fi
665
666     export TARGET_BUILD_APPS=
667
668     local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
669     check_variant $variant
670     if [ $? -ne 0 ]
671     then
672         echo
673         echo "** Invalid variant: '$variant'"
674         echo "** Must be one of ${VARIANT_CHOICES[@]}"
675         variant=
676     fi
677
678     local product=$(echo -n $selection | sed -e "s/-.*$//")
679     TARGET_PRODUCT=$product \
680     TARGET_BUILD_VARIANT=$variant \
681     build_build_var_cache
682     if [ $? -ne 0 ]
683     then
684         # if we can't find a product, try to grab it off the CM github
685         T=$(gettop)
686         pushd $T > /dev/null
687         build/tools/roomservice.py $product
688         popd > /dev/null
689         check_product $product
690     else
691         build/tools/roomservice.py $product true
692     fi
693     if [ $? -ne 0 ]
694     then
695         echo
696         echo "** Don't have a product spec for: '$product'"
697         echo "** Do you have the right repo manifest?"
698         product=
699     fi
700
701     if [ -z "$product" -o -z "$variant" ]
702     then
703         echo
704         return 1
705     fi
706
707     export TARGET_PRODUCT=$product
708     export TARGET_BUILD_VARIANT=$variant
709     export TARGET_BUILD_TYPE=release
710
711     echo
712
713     set_stuff_for_environment
714     printconfig
715     destroy_build_var_cache
716 }
717
718 # Tab completion for lunch.
719 function _lunch()
720 {
721     local cur prev opts
722     COMPREPLY=()
723     cur="${COMP_WORDS[COMP_CWORD]}"
724     prev="${COMP_WORDS[COMP_CWORD-1]}"
725
726     COMPREPLY=( $(compgen -W "${LUNCH_MENU_CHOICES[*]}" -- ${cur}) )
727     return 0
728 }
729 complete -F _lunch lunch
730
731 # Configures the build to build unbundled apps.
732 # Run tapas with one or more app names (from LOCAL_PACKAGE_NAME)
733 function tapas()
734 {
735     local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|mips|armv5|arm64|x86_64|mips64)$' | xargs)"
736     local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)"
737     local density="$(echo $* | xargs -n 1 echo | \grep -E '^(ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi)$' | xargs)"
738     local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|arm|x86|mips|armv5|arm64|x86_64|mips64|ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi)$' | xargs)"
739
740     if [ $(echo $arch | wc -w) -gt 1 ]; then
741         echo "tapas: Error: Multiple build archs supplied: $arch"
742         return
743     fi
744     if [ $(echo $variant | wc -w) -gt 1 ]; then
745         echo "tapas: Error: Multiple build variants supplied: $variant"
746         return
747     fi
748     if [ $(echo $density | wc -w) -gt 1 ]; then
749         echo "tapas: Error: Multiple densities supplied: $density"
750         return
751     fi
752
753     local product=aosp_arm
754     case $arch in
755       x86)    product=aosp_x86;;
756       mips)   product=aosp_mips;;
757       armv5)  product=generic_armv5;;
758       arm64)  product=aosp_arm64;;
759       x86_64) product=aosp_x86_64;;
760       mips64)  product=aosp_mips64;;
761     esac
762     if [ -z "$variant" ]; then
763         variant=eng
764     fi
765     if [ -z "$apps" ]; then
766         apps=all
767     fi
768     if [ -z "$density" ]; then
769         density=alldpi
770     fi
771
772     export TARGET_PRODUCT=$product
773     export TARGET_BUILD_VARIANT=$variant
774     export TARGET_BUILD_DENSITY=$density
775     export TARGET_BUILD_TYPE=release
776     export TARGET_BUILD_APPS=$apps
777
778     build_build_var_cache
779     set_stuff_for_environment
780     printconfig
781     destroy_build_var_cache
782 }
783
784 function eat()
785 {
786     if [ "$OUT" ] ; then
787         MODVERSION=`sed -n -e'/ro\.cm\.version/s/.*=//p' $OUT/system/build.prop`
788         ZIPFILE=cm-$MODVERSION.zip
789         ZIPPATH=$OUT/$ZIPFILE
790         if [ ! -f $ZIPPATH ] ; then
791             echo "Nothing to eat"
792             return 1
793         fi
794         adb start-server # Prevent unexpected starting server message from adb get-state in the next line
795         if [ $(adb get-state) != device -a $(adb shell busybox test -e /sbin/recovery 2> /dev/null; echo $?) != 0 ] ; then
796             echo "No device is online. Waiting for one..."
797             echo "Please connect USB and/or enable USB debugging"
798             until [ $(adb get-state) = device -o $(adb shell busybox test -e /sbin/recovery 2> /dev/null; echo $?) = 0 ];do
799                 sleep 1
800             done
801             echo "Device Found.."
802         fi
803     if (adb shell cat /system/build.prop | grep -q "ro.cm.device=$CM_BUILD");
804     then
805         # if adbd isn't root we can't write to /cache/recovery/
806         adb root
807         sleep 1
808         adb wait-for-device
809         SZ=`stat -c %s $ZIPPATH`
810         CACHESIZE=`adb shell busybox df -PB1 /cache | grep /cache | tr -s ' ' | cut -d ' ' -f 4`
811         if [ $CACHESIZE -gt $SZ ];
812         then
813             PUSHDIR=/cache/
814             DIR=cache
815         else
816             PUSHDIR=/storage/sdcard0/
817              # Optional path for sdcard0 in recovery
818              [ -z "$1" ] && DIR=sdcard/0 || DIR=$1
819         fi
820         echo "Pushing $ZIPFILE to $PUSHDIR"
821         if adb push $ZIPPATH $PUSHDIR ; then
822             cat << EOF > /tmp/command
823 --update_package=/$DIR/$ZIPFILE
824 EOF
825             if adb push /tmp/command /cache/recovery/ ; then
826                 echo "Rebooting into recovery for installation"
827                 adb reboot recovery
828             fi
829             rm /tmp/command
830         fi
831     else
832         echo "Nothing to eat"
833         return 1
834     fi
835     return $?
836     else
837         echo "The connected device does not appear to be $CM_BUILD, run away!"
838     fi
839 }
840
841 function omnom
842 {
843     brunch $*
844     eat
845 }
846
847 function gettop
848 {
849     local TOPFILE=build/core/envsetup.mk
850     if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ] ; then
851         # The following circumlocution ensures we remove symlinks from TOP.
852         (cd $TOP; PWD= /bin/pwd)
853     else
854         if [ -f $TOPFILE ] ; then
855             # The following circumlocution (repeated below as well) ensures
856             # that we record the true directory name and not one that is
857             # faked up with symlink names.
858             PWD= /bin/pwd
859         else
860             local HERE=$PWD
861             T=
862             while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
863                 \cd ..
864                 T=`PWD= /bin/pwd -P`
865             done
866             \cd $HERE
867             if [ -f "$T/$TOPFILE" ]; then
868                 echo $T
869             fi
870         fi
871     fi
872 }
873
874 # Return driver for "make", if any (eg. static analyzer)
875 function getdriver()
876 {
877     local T="$1"
878     test "$WITH_STATIC_ANALYZER" = "0" && unset WITH_STATIC_ANALYZER
879     if [ -n "$WITH_STATIC_ANALYZER" ]; then
880         echo "\
881 $T/prebuilts/misc/linux-x86/analyzer/tools/scan-build/scan-build \
882 --use-analyzer $T/prebuilts/misc/linux-x86/analyzer/bin/analyzer \
883 --status-bugs \
884 --top=$T"
885     fi
886 }
887
888 function m()
889 {
890     local T=$(gettop)
891     local DRV=$(getdriver $T)
892     if [ "$T" ]; then
893         $DRV make -C $T -f build/core/main.mk $@
894     else
895         echo "Couldn't locate the top of the tree.  Try setting TOP."
896         return 1
897     fi
898 }
899
900 function findmakefile()
901 {
902     TOPFILE=build/core/envsetup.mk
903     local HERE=$PWD
904     T=
905     while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
906         T=`PWD= /bin/pwd`
907         if [ -f "$T/Android.mk" ]; then
908             echo $T/Android.mk
909             \cd $HERE
910             return
911         fi
912         \cd ..
913     done
914     \cd $HERE
915 }
916
917 function mm()
918 {
919     local T=$(gettop)
920     local DRV=$(getdriver $T)
921     # If we're sitting in the root of the build tree, just do a
922     # normal make.
923     if [ -f build/core/envsetup.mk -a -f Makefile ]; then
924         $DRV make $@
925     else
926         # Find the closest Android.mk file.
927         local M=$(findmakefile)
928         local MODULES=
929         local GET_INSTALL_PATH=
930         local ARGS=
931         # Remove the path to top as the makefilepath needs to be relative
932         local M=`echo $M|sed 's:'$T'/::'`
933         if [ ! "$T" ]; then
934             echo "Couldn't locate the top of the tree.  Try setting TOP."
935             return 1
936         elif [ ! "$M" ]; then
937             echo "Couldn't locate a makefile from the current directory."
938             return 1
939         else
940             for ARG in $@; do
941                 case $ARG in
942                   GET-INSTALL-PATH) GET_INSTALL_PATH=$ARG;;
943                 esac
944             done
945             if [ -n "$GET_INSTALL_PATH" ]; then
946               MODULES=
947               ARGS=GET-INSTALL-PATH
948             else
949               MODULES=all_modules
950               ARGS=$@
951             fi
952             ONE_SHOT_MAKEFILE=$M $DRV make -C $T -f build/core/main.mk $MODULES $ARGS
953         fi
954     fi
955 }
956
957 function mmm()
958 {
959     local T=$(gettop)
960     local DRV=$(getdriver $T)
961     if [ "$T" ]; then
962         local MAKEFILE=
963         local MODULES=
964         local ARGS=
965         local DIR TO_CHOP
966         local GET_INSTALL_PATH=
967         local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/')
968         local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/')
969         for DIR in $DIRS ; do
970             MODULES=`echo $DIR | sed -n -e 's/.*:\(.*$\)/\1/p' | sed 's/,/ /'`
971             if [ "$MODULES" = "" ]; then
972                 MODULES=all_modules
973             fi
974             DIR=`echo $DIR | sed -e 's/:.*//' -e 's:/$::'`
975             if [ -f $DIR/Android.mk ]; then
976                 local TO_CHOP=`(\cd -P -- $T && pwd -P) | wc -c | tr -d ' '`
977                 local TO_CHOP=`expr $TO_CHOP + 1`
978                 local START=`PWD= /bin/pwd`
979                 local MFILE=`echo $START | cut -c${TO_CHOP}-`
980                 if [ "$MFILE" = "" ] ; then
981                     MFILE=$DIR/Android.mk
982                 else
983                     MFILE=$MFILE/$DIR/Android.mk
984                 fi
985                 MAKEFILE="$MAKEFILE $MFILE"
986             else
987                 case $DIR in
988                   showcommands | snod | dist | *=*) ARGS="$ARGS $DIR";;
989                   GET-INSTALL-PATH) GET_INSTALL_PATH=$DIR;;
990                   *) if [ -d $DIR ]; then
991                          echo "No Android.mk in $DIR.";
992                      else
993                          echo "Couldn't locate the directory $DIR";
994                      fi
995                      return 1;;
996                 esac
997             fi
998         done
999         if [ -n "$GET_INSTALL_PATH" ]; then
1000           ARGS=$GET_INSTALL_PATH
1001           MODULES=
1002         fi
1003         ONE_SHOT_MAKEFILE="$MAKEFILE" $DRV make -C $T -f build/core/main.mk $DASH_ARGS $MODULES $ARGS
1004     else
1005         echo "Couldn't locate the top of the tree.  Try setting TOP."
1006         return 1
1007     fi
1008 }
1009
1010 function mma()
1011 {
1012   local T=$(gettop)
1013   local DRV=$(getdriver $T)
1014   if [ -f build/core/envsetup.mk -a -f Makefile ]; then
1015     $DRV make $@
1016   else
1017     if [ ! "$T" ]; then
1018       echo "Couldn't locate the top of the tree.  Try setting TOP."
1019       return 1
1020     fi
1021     local MY_PWD=`PWD= /bin/pwd|sed 's:'$T'/::'`
1022     local MODULES_IN_PATHS=MODULES-IN-$MY_PWD
1023     # Convert "/" to "-".
1024     MODULES_IN_PATHS=${MODULES_IN_PATHS//\//-}
1025     $DRV make -C $T -f build/core/main.mk $@ $MODULES_IN_PATHS
1026   fi
1027 }
1028
1029 function mmma()
1030 {
1031   local T=$(gettop)
1032   local DRV=$(getdriver $T)
1033   if [ "$T" ]; then
1034     local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/')
1035     local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/')
1036     local MY_PWD=`PWD= /bin/pwd`
1037     if [ "$MY_PWD" = "$T" ]; then
1038       MY_PWD=
1039     else
1040       MY_PWD=`echo $MY_PWD|sed 's:'$T'/::'`
1041     fi
1042     local DIR=
1043     local MODULES_IN_PATHS=
1044     local ARGS=
1045     for DIR in $DIRS ; do
1046       if [ -d $DIR ]; then
1047         # Remove the leading ./ and trailing / if any exists.
1048         DIR=${DIR#./}
1049         DIR=${DIR%/}
1050         if [ "$MY_PWD" != "" ]; then
1051           DIR=$MY_PWD/$DIR
1052         fi
1053         MODULES_IN_PATHS="$MODULES_IN_PATHS MODULES-IN-$DIR"
1054       else
1055         case $DIR in
1056           showcommands | snod | dist | *=*) ARGS="$ARGS $DIR";;
1057           *) echo "Couldn't find directory $DIR"; return 1;;
1058         esac
1059       fi
1060     done
1061     # Convert "/" to "-".
1062     MODULES_IN_PATHS=${MODULES_IN_PATHS//\//-}
1063     $DRV make -C $T -f build/core/main.mk $DASH_ARGS $ARGS $MODULES_IN_PATHS
1064   else
1065     echo "Couldn't locate the top of the tree.  Try setting TOP."
1066     return 1
1067   fi
1068 }
1069
1070 function croot()
1071 {
1072     T=$(gettop)
1073     if [ "$T" ]; then
1074         \cd $(gettop)
1075     else
1076         echo "Couldn't locate the top of the tree.  Try setting TOP."
1077     fi
1078 }
1079
1080 function cproj()
1081 {
1082     TOPFILE=build/core/envsetup.mk
1083     local HERE=$PWD
1084     T=
1085     while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
1086         T=$PWD
1087         if [ -f "$T/Android.mk" ]; then
1088             \cd $T
1089             return
1090         fi
1091         \cd ..
1092     done
1093     \cd $HERE
1094     echo "can't find Android.mk"
1095 }
1096
1097 # simplified version of ps; output in the form
1098 # <pid> <procname>
1099 function qpid() {
1100     local prepend=''
1101     local append=''
1102     if [ "$1" = "--exact" ]; then
1103         prepend=' '
1104         append='$'
1105         shift
1106     elif [ "$1" = "--help" -o "$1" = "-h" ]; then
1107         echo "usage: qpid [[--exact] <process name|pid>"
1108         return 255
1109     fi
1110
1111     local EXE="$1"
1112     if [ "$EXE" ] ; then
1113         qpid | \grep "$prepend$EXE$append"
1114     else
1115         adb shell ps \
1116             | tr -d '\r' \
1117             | sed -e 1d -e 's/^[^ ]* *\([0-9]*\).* \([^ ]*\)$/\1 \2/'
1118     fi
1119 }
1120
1121 function pid()
1122 {
1123     local prepend=''
1124     local append=''
1125     if [ "$1" = "--exact" ]; then
1126         prepend=' '
1127         append='$'
1128         shift
1129     fi
1130     local EXE="$1"
1131     if [ "$EXE" ] ; then
1132         local PID=`adb shell ps \
1133             | tr -d '\r' \
1134             | \grep "$prepend$EXE$append" \
1135             | sed -e 's/^[^ ]* *\([0-9]*\).*$/\1/'`
1136         echo "$PID"
1137     else
1138         echo "usage: pid [--exact] <process name>"
1139         return 255
1140     fi
1141 }
1142
1143 # coredump_setup - enable core dumps globally for any process
1144 #                  that has the core-file-size limit set correctly
1145 #
1146 # NOTE: You must call also coredump_enable for a specific process
1147 #       if its core-file-size limit is not set already.
1148 # NOTE: Core dumps are written to ramdisk; they will not survive a reboot!
1149
1150 function coredump_setup()
1151 {
1152     echo "Getting root...";
1153     adb root;
1154     adb wait-for-device;
1155
1156     echo "Remounting root partition read-write...";
1157     adb shell mount -w -o remount -t rootfs rootfs;
1158     sleep 1;
1159     adb wait-for-device;
1160     adb shell mkdir -p /cores;
1161     adb shell mount -t tmpfs tmpfs /cores;
1162     adb shell chmod 0777 /cores;
1163
1164     echo "Granting SELinux permission to dump in /cores...";
1165     adb shell restorecon -R /cores;
1166
1167     echo "Set core pattern.";
1168     adb shell 'echo /cores/core.%p > /proc/sys/kernel/core_pattern';
1169
1170     echo "Done."
1171 }
1172
1173 # coredump_enable - enable core dumps for the specified process
1174 # $1 = PID of process (e.g., $(pid mediaserver))
1175 #
1176 # NOTE: coredump_setup must have been called as well for a core
1177 #       dump to actually be generated.
1178
1179 function coredump_enable()
1180 {
1181     local PID=$1;
1182     if [ -z "$PID" ]; then
1183         printf "Expecting a PID!\n";
1184         return;
1185     fi;
1186     echo "Setting core limit for $PID to infinite...";
1187     adb shell prlimit $PID 4 -1 -1
1188 }
1189
1190 # core - send SIGV and pull the core for process
1191 # $1 = PID of process (e.g., $(pid mediaserver))
1192 #
1193 # NOTE: coredump_setup must be called once per boot for core dumps to be
1194 #       enabled globally.
1195
1196 function core()
1197 {
1198     local PID=$1;
1199
1200     if [ -z "$PID" ]; then
1201         printf "Expecting a PID!\n";
1202         return;
1203     fi;
1204
1205     local CORENAME=core.$PID;
1206     local COREPATH=/cores/$CORENAME;
1207     local SIG=SEGV;
1208
1209     coredump_enable $1;
1210
1211     local done=0;
1212     while [ $(adb shell "[ -d /proc/$PID ] && echo -n yes") ]; do
1213         printf "\tSending SIG%s to %d...\n" $SIG $PID;
1214         adb shell kill -$SIG $PID;
1215         sleep 1;
1216     done;
1217
1218     adb shell "while [ ! -f $COREPATH ] ; do echo waiting for $COREPATH to be generated; sleep 1; done"
1219     echo "Done: core is under $COREPATH on device.";
1220 }
1221
1222 # systemstack - dump the current stack trace of all threads in the system process
1223 # to the usual ANR traces file
1224 function systemstack()
1225 {
1226     stacks system_server
1227 }
1228
1229 function stacks()
1230 {
1231     if [[ $1 =~ ^[0-9]+$ ]] ; then
1232         local PID="$1"
1233     elif [ "$1" ] ; then
1234         local PIDLIST="$(pid $1)"
1235         if [[ $PIDLIST =~ ^[0-9]+$ ]] ; then
1236             local PID="$PIDLIST"
1237         elif [ "$PIDLIST" ] ; then
1238             echo "more than one process: $1"
1239         else
1240             echo "no such process: $1"
1241         fi
1242     else
1243         echo "usage: stacks [pid|process name]"
1244     fi
1245
1246     if [ "$PID" ] ; then
1247         # Determine whether the process is native
1248         if adb shell ls -l /proc/$PID/exe | grep -q /system/bin/app_process ; then
1249             # Dump stacks of Dalvik process
1250             local TRACES=/data/anr/traces.txt
1251             local ORIG=/data/anr/traces.orig
1252             local TMP=/data/anr/traces.tmp
1253
1254             # Keep original traces to avoid clobbering
1255             adb shell mv $TRACES $ORIG
1256
1257             # Make sure we have a usable file
1258             adb shell touch $TRACES
1259             adb shell chmod 666 $TRACES
1260
1261             # Dump stacks and wait for dump to finish
1262             adb shell kill -3 $PID
1263             adb shell notify $TRACES >/dev/null
1264
1265             # Restore original stacks, and show current output
1266             adb shell mv $TRACES $TMP
1267             adb shell mv $ORIG $TRACES
1268             adb shell cat $TMP
1269         else
1270             # Dump stacks of native process
1271             local USE64BIT="$(is64bit $PID)"
1272             adb shell debuggerd$USE64BIT -b $PID
1273         fi
1274     fi
1275 }
1276
1277 # Read the ELF header from /proc/$PID/exe to determine if the process is
1278 # 64-bit.
1279 function is64bit()
1280 {
1281     local PID="$1"
1282     if [ "$PID" ] ; then
1283         if [[ "$(adb shell cat /proc/$PID/exe | xxd -l 1 -s 4 -ps)" -eq "02" ]] ; then
1284             echo "64"
1285         else
1286             echo ""
1287         fi
1288     else
1289         echo ""
1290     fi
1291 }
1292
1293 case `uname -s` in
1294     Darwin)
1295         function sgrep()
1296         {
1297             find -E . -name .repo -prune -o -name .git -prune -o  -type f -iregex '.*\.(c|h|cc|cpp|S|java|xml|sh|mk|aidl|vts)' \
1298                 -exec grep --color -n "$@" {} +
1299         }
1300
1301         ;;
1302     *)
1303         function sgrep()
1304         {
1305             find . -name .repo -prune -o -name .git -prune -o  -type f -iregex '.*\.\(c\|h\|cc\|cpp\|S\|java\|xml\|sh\|mk\|aidl\|vts\)' \
1306                 -exec grep --color -n "$@" {} +
1307         }
1308         ;;
1309 esac
1310
1311 function gettargetarch
1312 {
1313     get_build_var TARGET_ARCH
1314 }
1315
1316 function ggrep()
1317 {
1318     find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.gradle" \
1319         -exec grep --color -n "$@" {} +
1320 }
1321
1322 function jgrep()
1323 {
1324     find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.java" \
1325         -exec grep --color -n "$@" {} +
1326 }
1327
1328 function cgrep()
1329 {
1330     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' \) \
1331         -exec grep --color -n "$@" {} +
1332 }
1333
1334 function resgrep()
1335 {
1336     for dir in `find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -name res -type d`; do
1337         find $dir -type f -name '*\.xml' -exec grep --color -n "$@" {} +
1338     done
1339 }
1340
1341 function mangrep()
1342 {
1343     find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -type f -name 'AndroidManifest.xml' \
1344         -exec grep --color -n "$@" {} +
1345 }
1346
1347 function sepgrep()
1348 {
1349     find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -name sepolicy -type d \
1350         -exec grep --color -n -r --exclude-dir=\.git "$@" {} +
1351 }
1352
1353 function rcgrep()
1354 {
1355     find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.rc*" \
1356         -exec grep --color -n "$@" {} +
1357 }
1358
1359 case `uname -s` in
1360     Darwin)
1361         function mgrep()
1362         {
1363             find -E . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -type f -iregex '.*/(Makefile|Makefile\..*|.*\.make|.*\.mak|.*\.mk)' \
1364                 -exec grep --color -n "$@" {} +
1365         }
1366
1367         function treegrep()
1368         {
1369             find -E . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*\.(c|h|cpp|S|java|xml)' \
1370                 -exec grep --color -n -i "$@" {} +
1371         }
1372
1373         ;;
1374     *)
1375         function mgrep()
1376         {
1377             find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -regextype posix-egrep -iregex '(.*\/Makefile|.*\/Makefile\..*|.*\.make|.*\.mak|.*\.mk)' -type f \
1378                 -exec grep --color -n "$@" {} +
1379         }
1380
1381         function treegrep()
1382         {
1383             find . -name .repo -prune -o -name .git -prune -o -regextype posix-egrep -iregex '.*\.(c|h|cpp|S|java|xml)' -type f \
1384                 -exec grep --color -n -i "$@" {} +
1385         }
1386
1387         ;;
1388 esac
1389
1390 function getprebuilt
1391 {
1392     get_abs_build_var ANDROID_PREBUILTS
1393 }
1394
1395 function tracedmdump()
1396 {
1397     T=$(gettop)
1398     if [ ! "$T" ]; then
1399         echo "Couldn't locate the top of the tree.  Try setting TOP."
1400         return
1401     fi
1402     local prebuiltdir=$(getprebuilt)
1403     local arch=$(gettargetarch)
1404     local KERNEL=$T/prebuilts/qemu-kernel/$arch/vmlinux-qemu
1405
1406     local TRACE=$1
1407     if [ ! "$TRACE" ] ; then
1408         echo "usage:  tracedmdump  tracename"
1409         return
1410     fi
1411
1412     if [ ! -r "$KERNEL" ] ; then
1413         echo "Error: cannot find kernel: '$KERNEL'"
1414         return
1415     fi
1416
1417     local BASETRACE=$(basename $TRACE)
1418     if [ "$BASETRACE" = "$TRACE" ] ; then
1419         TRACE=$ANDROID_PRODUCT_OUT/traces/$TRACE
1420     fi
1421
1422     echo "post-processing traces..."
1423     rm -f $TRACE/qtrace.dexlist
1424     post_trace $TRACE
1425     if [ $? -ne 0 ]; then
1426         echo "***"
1427         echo "*** Error: malformed trace.  Did you remember to exit the emulator?"
1428         echo "***"
1429         return
1430     fi
1431     echo "generating dexlist output..."
1432     /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
1433     echo "generating dmtrace data..."
1434     q2dm -r $ANDROID_PRODUCT_OUT/symbols $TRACE $KERNEL $TRACE/dmtrace || return
1435     echo "generating html file..."
1436     dmtracedump -h $TRACE/dmtrace >| $TRACE/dmtrace.html || return
1437     echo "done, see $TRACE/dmtrace.html for details"
1438     echo "or run:"
1439     echo "    traceview $TRACE/dmtrace"
1440 }
1441
1442 # communicate with a running device or emulator, set up necessary state,
1443 # and run the hat command.
1444 function runhat()
1445 {
1446     # process standard adb options
1447     local adbTarget=""
1448     if [ "$1" = "-d" -o "$1" = "-e" ]; then
1449         adbTarget=$1
1450         shift 1
1451     elif [ "$1" = "-s" ]; then
1452         adbTarget="$1 $2"
1453         shift 2
1454     fi
1455     local adbOptions=${adbTarget}
1456     #echo adbOptions = ${adbOptions}
1457
1458     # runhat options
1459     local targetPid=$1
1460
1461     if [ "$targetPid" = "" ]; then
1462         echo "Usage: runhat [ -d | -e | -s serial ] target-pid"
1463         return
1464     fi
1465
1466     # confirm hat is available
1467     if [ -z $(which hat) ]; then
1468         echo "hat is not available in this configuration."
1469         return
1470     fi
1471
1472     # issue "am" command to cause the hprof dump
1473     local devFile=/data/local/tmp/hprof-$targetPid
1474     echo "Poking $targetPid and waiting for data..."
1475     echo "Storing data at $devFile"
1476     adb ${adbOptions} shell am dumpheap $targetPid $devFile
1477     echo "Press enter when logcat shows \"hprof: heap dump completed\""
1478     echo -n "> "
1479     read
1480
1481     local localFile=/tmp/$$-hprof
1482
1483     echo "Retrieving file $devFile..."
1484     adb ${adbOptions} pull $devFile $localFile
1485
1486     adb ${adbOptions} shell rm $devFile
1487
1488     echo "Running hat on $localFile"
1489     echo "View the output by pointing your browser at http://localhost:7000/"
1490     echo ""
1491     hat -JXmx512m $localFile
1492 }
1493
1494 function getbugreports()
1495 {
1496     local reports=(`adb shell ls /sdcard/bugreports | tr -d '\r'`)
1497
1498     if [ ! "$reports" ]; then
1499         echo "Could not locate any bugreports."
1500         return
1501     fi
1502
1503     local report
1504     for report in ${reports[@]}
1505     do
1506         echo "/sdcard/bugreports/${report}"
1507         adb pull /sdcard/bugreports/${report} ${report}
1508         gunzip ${report}
1509     done
1510 }
1511
1512 function getsdcardpath()
1513 {
1514     adb ${adbOptions} shell echo -n \$\{EXTERNAL_STORAGE\}
1515 }
1516
1517 function getscreenshotpath()
1518 {
1519     echo "$(getsdcardpath)/Pictures/Screenshots"
1520 }
1521
1522 function getlastscreenshot()
1523 {
1524     local screenshot_path=$(getscreenshotpath)
1525     local screenshot=`adb ${adbOptions} ls ${screenshot_path} | grep Screenshot_[0-9-]*.*\.png | sort -rk 3 | cut -d " " -f 4 | head -n 1`
1526     if [ "$screenshot" = "" ]; then
1527         echo "No screenshots found."
1528         return
1529     fi
1530     echo "${screenshot}"
1531     adb ${adbOptions} pull ${screenshot_path}/${screenshot}
1532 }
1533
1534 function startviewserver()
1535 {
1536     local port=4939
1537     if [ $# -gt 0 ]; then
1538             port=$1
1539     fi
1540     adb shell service call window 1 i32 $port
1541 }
1542
1543 function stopviewserver()
1544 {
1545     adb shell service call window 2
1546 }
1547
1548 function isviewserverstarted()
1549 {
1550     adb shell service call window 3
1551 }
1552
1553 function key_home()
1554 {
1555     adb shell input keyevent 3
1556 }
1557
1558 function key_back()
1559 {
1560     adb shell input keyevent 4
1561 }
1562
1563 function key_menu()
1564 {
1565     adb shell input keyevent 82
1566 }
1567
1568 function smoketest()
1569 {
1570     if [ ! "$ANDROID_PRODUCT_OUT" ]; then
1571         echo "Couldn't locate output files.  Try running 'lunch' first." >&2
1572         return
1573     fi
1574     T=$(gettop)
1575     if [ ! "$T" ]; then
1576         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
1577         return
1578     fi
1579
1580     (\cd "$T" && mmm tests/SmokeTest) &&
1581       adb uninstall com.android.smoketest > /dev/null &&
1582       adb uninstall com.android.smoketest.tests > /dev/null &&
1583       adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTestApp.apk &&
1584       adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTest.apk &&
1585       adb shell am instrument -w com.android.smoketest.tests/android.test.InstrumentationTestRunner
1586 }
1587
1588 # simple shortcut to the runtest command
1589 function runtest()
1590 {
1591     T=$(gettop)
1592     if [ ! "$T" ]; then
1593         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
1594         return
1595     fi
1596     ("$T"/development/testrunner/runtest.py $@)
1597 }
1598
1599 function godir () {
1600     if [[ -z "$1" ]]; then
1601         echo "Usage: godir <regex>"
1602         return
1603     fi
1604     T=$(gettop)
1605     if [ ! "$OUT_DIR" = "" ]; then
1606         mkdir -p $OUT_DIR
1607         FILELIST=$OUT_DIR/filelist
1608     else
1609         FILELIST=$T/filelist
1610     fi
1611     if [[ ! -f $FILELIST ]]; then
1612         echo -n "Creating index..."
1613         (\cd $T; find . -wholename ./out -prune -o -wholename ./.repo -prune -o -type f > $FILELIST)
1614         echo " Done"
1615         echo ""
1616     fi
1617     local lines
1618     lines=($(\grep "$1" $FILELIST | sed -e 's/\/[^/]*$//' | sort | uniq))
1619     if [[ ${#lines[@]} = 0 ]]; then
1620         echo "Not found"
1621         return
1622     fi
1623     local pathname
1624     local choice
1625     if [[ ${#lines[@]} > 1 ]]; then
1626         while [[ -z "$pathname" ]]; do
1627             local index=1
1628             local line
1629             for line in ${lines[@]}; do
1630                 printf "%6s %s\n" "[$index]" $line
1631                 index=$(($index + 1))
1632             done
1633             echo
1634             echo -n "Select one: "
1635             unset choice
1636             read choice
1637             if [[ $choice -gt ${#lines[@]} || $choice -lt 1 ]]; then
1638                 echo "Invalid choice"
1639                 continue
1640             fi
1641             pathname=${lines[$(($choice-1))]}
1642         done
1643     else
1644         pathname=${lines[0]}
1645     fi
1646     \cd $T/$pathname
1647 }
1648
1649 function cmremote()
1650 {
1651     git remote rm cmremote 2> /dev/null
1652     if [ ! -d .git ]
1653     then
1654         echo .git directory not found. Please run this from the root directory of the Android repository you wish to set up.
1655     fi
1656     GERRIT_REMOTE=$(cat .git/config  | grep git://github.com | awk '{ print $NF }' | sed s#git://github.com/##g)
1657     if [ -z "$GERRIT_REMOTE" ]
1658     then
1659         GERRIT_REMOTE=$(cat .git/config  | grep http://github.com | awk '{ print $NF }' | sed s#http://github.com/##g)
1660         if [ -z "$GERRIT_REMOTE" ]
1661         then
1662           echo Unable to set up the git remote, are you in the root of the repo?
1663           return 0
1664         fi
1665     fi
1666     CMUSER=`git config --get review.review.cyanogenmod.org.username`
1667     if [ -z "$CMUSER" ]
1668     then
1669         git remote add cmremote ssh://review.cyanogenmod.org:29418/$GERRIT_REMOTE
1670     else
1671         git remote add cmremote ssh://$CMUSER@review.cyanogenmod.org:29418/$GERRIT_REMOTE
1672     fi
1673     echo You can now push to "cmremote".
1674 }
1675 export -f cmremote
1676
1677 function aospremote()
1678 {
1679     git remote rm aosp 2> /dev/null
1680     if [ ! -d .git ]
1681     then
1682         echo .git directory not found. Please run this from the root directory of the Android repository you wish to set up.
1683     fi
1684     PROJECT=`pwd | sed s#$ANDROID_BUILD_TOP/##g`
1685     if (echo $PROJECT | grep -qv "^device")
1686     then
1687         PFX="platform/"
1688     fi
1689     git remote add aosp https://android.googlesource.com/$PFX$PROJECT
1690     echo "Remote 'aosp' created"
1691 }
1692 export -f aospremote
1693
1694 function installboot()
1695 {
1696     if [ ! -e "$OUT/recovery/root/etc/recovery.fstab" ];
1697     then
1698         echo "No recovery.fstab found. Build recovery first."
1699         return 1
1700     fi
1701     if [ ! -e "$OUT/boot.img" ];
1702     then
1703         echo "No boot.img found. Run make bootimage first."
1704         return 1
1705     fi
1706     PARTITION=`grep "^\/boot" $OUT/recovery/root/etc/recovery.fstab | awk {'print $3'}`
1707     if [ -z "$PARTITION" ];
1708     then
1709         echo "Unable to determine boot partition."
1710         return 1
1711     fi
1712     adb start-server
1713     adb root
1714     sleep 1
1715     adb wait-for-device
1716     adb remount
1717     adb wait-for-device
1718     if (adb shell cat /system/build.prop | grep -q "ro.cm.device=$CM_BUILD");
1719     then
1720         adb push $OUT/boot.img /cache/
1721         for i in $OUT/system/lib/modules/*;
1722         do
1723             adb push $i /system/lib/modules/
1724         done
1725         adb shell dd if=/cache/boot.img of=$PARTITION
1726         adb shell chmod 644 /system/lib/modules/*
1727         echo "Installation complete."
1728     else
1729         echo "The connected device does not appear to be $CM_BUILD, run away!"
1730     fi
1731 }
1732
1733 function installrecovery()
1734 {
1735     if [ ! -e "$OUT/recovery/root/etc/recovery.fstab" ];
1736     then
1737         echo "No recovery.fstab found. Build recovery first."
1738         return 1
1739     fi
1740     if [ ! -e "$OUT/recovery.img" ];
1741     then
1742         echo "No recovery.img found. Run make recoveryimage first."
1743         return 1
1744     fi
1745     PARTITION=`grep "^\/recovery" $OUT/recovery/root/etc/recovery.fstab | awk {'print $3'}`
1746     if [ -z "$PARTITION" ];
1747     then
1748         echo "Unable to determine recovery partition."
1749         return 1
1750     fi
1751     adb start-server
1752     adb root
1753     sleep 1
1754     adb wait-for-device
1755     adb remount
1756     adb wait-for-device
1757     if (adb shell cat /system/build.prop | grep -q "ro.cm.device=$CM_BUILD");
1758     then
1759         adb push $OUT/recovery.img /cache/
1760         adb shell dd if=/cache/recovery.img of=$PARTITION
1761         echo "Installation complete."
1762     else
1763         echo "The connected device does not appear to be $CM_BUILD, run away!"
1764     fi
1765 }
1766
1767 function makerecipe() {
1768   if [ -z "$1" ]
1769   then
1770     echo "No branch name provided."
1771     return 1
1772   fi
1773   cd android
1774   sed -i s/'default revision=.*'/'default revision="refs\/heads\/'$1'"'/ default.xml
1775   git commit -a -m "$1"
1776   cd ..
1777
1778   repo forall -c '
1779
1780   if [ "$REPO_REMOTE" == "github" ]
1781   then
1782     pwd
1783     cmremote
1784     git push cmremote HEAD:refs/heads/'$1'
1785   fi
1786   '
1787 }
1788
1789 function cmgerrit() {
1790     if [ $# -eq 0 ]; then
1791         $FUNCNAME help
1792         return 1
1793     fi
1794     local user=`git config --get review.review.cyanogenmod.org.username`
1795     local review=`git config --get remote.github.review`
1796     local project=`git config --get remote.github.projectname`
1797     local command=$1
1798     shift
1799     case $command in
1800         help)
1801             if [ $# -eq 0 ]; then
1802                 cat <<EOF
1803 Usage:
1804     $FUNCNAME COMMAND [OPTIONS] [CHANGE-ID[/PATCH-SET]][{@|^|~|:}ARG] [-- ARGS]
1805
1806 Commands:
1807     fetch   Just fetch the change as FETCH_HEAD
1808     help    Show this help, or for a specific command
1809     pull    Pull a change into current branch
1810     push    Push HEAD or a local branch to Gerrit for a specific branch
1811
1812 Any other Git commands that support refname would work as:
1813     git fetch URL CHANGE && git COMMAND OPTIONS FETCH_HEAD{@|^|~|:}ARG -- ARGS
1814
1815 See '$FUNCNAME help COMMAND' for more information on a specific command.
1816
1817 Example:
1818     $FUNCNAME checkout -b topic 1234/5
1819 works as:
1820     git fetch http://DOMAIN/p/PROJECT refs/changes/34/1234/5 \\
1821       && git checkout -b topic FETCH_HEAD
1822 will checkout a new branch 'topic' base on patch-set 5 of change 1234.
1823 Patch-set 1 will be fetched if omitted.
1824 EOF
1825                 return
1826             fi
1827             case $1 in
1828                 __cmg_*) echo "For internal use only." ;;
1829                 changes|for)
1830                     if [ "$FUNCNAME" = "cmgerrit" ]; then
1831                         echo "'$FUNCNAME $1' is deprecated."
1832                     fi
1833                     ;;
1834                 help) $FUNCNAME help ;;
1835                 fetch|pull) cat <<EOF
1836 usage: $FUNCNAME $1 [OPTIONS] CHANGE-ID[/PATCH-SET]
1837
1838 works as:
1839     git $1 OPTIONS http://DOMAIN/p/PROJECT \\
1840       refs/changes/HASH/CHANGE-ID/{PATCH-SET|1}
1841
1842 Example:
1843     $FUNCNAME $1 1234
1844 will $1 patch-set 1 of change 1234
1845 EOF
1846                     ;;
1847                 push) cat <<EOF
1848 usage: $FUNCNAME push [OPTIONS] [LOCAL_BRANCH:]REMOTE_BRANCH
1849
1850 works as:
1851     git push OPTIONS ssh://USER@DOMAIN:29418/PROJECT \\
1852       {LOCAL_BRANCH|HEAD}:refs/for/REMOTE_BRANCH
1853
1854 Example:
1855     $FUNCNAME push fix6789:gingerbread
1856 will push local branch 'fix6789' to Gerrit for branch 'gingerbread'.
1857 HEAD will be pushed from local if omitted.
1858 EOF
1859                     ;;
1860                 *)
1861                     $FUNCNAME __cmg_err_not_supported $1 && return
1862                     cat <<EOF
1863 usage: $FUNCNAME $1 [OPTIONS] CHANGE-ID[/PATCH-SET][{@|^|~|:}ARG] [-- ARGS]
1864
1865 works as:
1866     git fetch http://DOMAIN/p/PROJECT \\
1867       refs/changes/HASH/CHANGE-ID/{PATCH-SET|1} \\
1868       && git $1 OPTIONS FETCH_HEAD{@|^|~|:}ARG -- ARGS
1869 EOF
1870                     ;;
1871             esac
1872             ;;
1873         __cmg_get_ref)
1874             $FUNCNAME __cmg_err_no_arg $command $# && return 1
1875             local change_id patchset_id hash
1876             case $1 in
1877                 */*)
1878                     change_id=${1%%/*}
1879                     patchset_id=${1#*/}
1880                     ;;
1881                 *)
1882                     change_id=$1
1883                     patchset_id=1
1884                     ;;
1885             esac
1886             hash=$(($change_id % 100))
1887             case $hash in
1888                 [0-9]) hash="0$hash" ;;
1889             esac
1890             echo "refs/changes/$hash/$change_id/$patchset_id"
1891             ;;
1892         fetch|pull)
1893             $FUNCNAME __cmg_err_no_arg $command $# help && return 1
1894             $FUNCNAME __cmg_err_not_repo && return 1
1895             local change=$1
1896             shift
1897             git $command $@ http://$review/p/$project \
1898                 $($FUNCNAME __cmg_get_ref $change) || return 1
1899             ;;
1900         push)
1901             $FUNCNAME __cmg_err_no_arg $command $# help && return 1
1902             $FUNCNAME __cmg_err_not_repo && return 1
1903             if [ -z "$user" ]; then
1904                 echo >&2 "Gerrit username not found."
1905                 return 1
1906             fi
1907             local local_branch remote_branch
1908             case $1 in
1909                 *:*)
1910                     local_branch=${1%:*}
1911                     remote_branch=${1##*:}
1912                     ;;
1913                 *)
1914                     local_branch=HEAD
1915                     remote_branch=$1
1916                     ;;
1917             esac
1918             shift
1919             git push $@ ssh://$user@$review:29418/$project \
1920                 $local_branch:refs/for/$remote_branch || return 1
1921             ;;
1922         changes|for)
1923             if [ "$FUNCNAME" = "cmgerrit" ]; then
1924                 echo >&2 "'$FUNCNAME $command' is deprecated."
1925             fi
1926             ;;
1927         __cmg_err_no_arg)
1928             if [ $# -lt 2 ]; then
1929                 echo >&2 "'$FUNCNAME $command' missing argument."
1930             elif [ $2 -eq 0 ]; then
1931                 if [ -n "$3" ]; then
1932                     $FUNCNAME help $1
1933                 else
1934                     echo >&2 "'$FUNCNAME $1' missing argument."
1935                 fi
1936             else
1937                 return 1
1938             fi
1939             ;;
1940         __cmg_err_not_repo)
1941             if [ -z "$review" -o -z "$project" ]; then
1942                 echo >&2 "Not currently in any reviewable repository."
1943             else
1944                 return 1
1945             fi
1946             ;;
1947         __cmg_err_not_supported)
1948             $FUNCNAME __cmg_err_no_arg $command $# && return
1949             case $1 in
1950                 #TODO: filter more git commands that don't use refname
1951                 init|add|rm|mv|status|clone|remote|bisect|config|stash)
1952                     echo >&2 "'$FUNCNAME $1' is not supported."
1953                     ;;
1954                 *) return 1 ;;
1955             esac
1956             ;;
1957     #TODO: other special cases?
1958         *)
1959             $FUNCNAME __cmg_err_not_supported $command && return 1
1960             $FUNCNAME __cmg_err_no_arg $command $# help && return 1
1961             $FUNCNAME __cmg_err_not_repo && return 1
1962             local args="$@"
1963             local change pre_args refs_arg post_args
1964             case "$args" in
1965                 *--\ *)
1966                     pre_args=${args%%-- *}
1967                     post_args="-- ${args#*-- }"
1968                     ;;
1969                 *) pre_args="$args" ;;
1970             esac
1971             args=($pre_args)
1972             pre_args=
1973             if [ ${#args[@]} -gt 0 ]; then
1974                 change=${args[${#args[@]}-1]}
1975             fi
1976             if [ ${#args[@]} -gt 1 ]; then
1977                 pre_args=${args[0]}
1978                 for ((i=1; i<${#args[@]}-1; i++)); do
1979                     pre_args="$pre_args ${args[$i]}"
1980                 done
1981             fi
1982             while ((1)); do
1983                 case $change in
1984                     ""|--)
1985                         $FUNCNAME help $command
1986                         return 1
1987                         ;;
1988                     *@*)
1989                         if [ -z "$refs_arg" ]; then
1990                             refs_arg="@${change#*@}"
1991                             change=${change%%@*}
1992                         fi
1993                         ;;
1994                     *~*)
1995                         if [ -z "$refs_arg" ]; then
1996                             refs_arg="~${change#*~}"
1997                             change=${change%%~*}
1998                         fi
1999                         ;;
2000                     *^*)
2001                         if [ -z "$refs_arg" ]; then
2002                             refs_arg="^${change#*^}"
2003                             change=${change%%^*}
2004                         fi
2005                         ;;
2006                     *:*)
2007                         if [ -z "$refs_arg" ]; then
2008                             refs_arg=":${change#*:}"
2009                             change=${change%%:*}
2010                         fi
2011                         ;;
2012                     *) break ;;
2013                 esac
2014             done
2015             $FUNCNAME fetch $change \
2016                 && git $command $pre_args FETCH_HEAD$refs_arg $post_args \
2017                 || return 1
2018             ;;
2019     esac
2020 }
2021
2022 function cmrebase() {
2023     local repo=$1
2024     local refs=$2
2025     local pwd="$(pwd)"
2026     local dir="$(gettop)/$repo"
2027
2028     if [ -z $repo ] || [ -z $refs ]; then
2029         echo "CyanogenMod Gerrit Rebase Usage: "
2030         echo "      cmrebase <path to project> <patch IDs on Gerrit>"
2031         echo "      The patch IDs appear on the Gerrit commands that are offered."
2032         echo "      They consist on a series of numbers and slashes, after the text"
2033         echo "      refs/changes. For example, the ID in the following command is 26/8126/2"
2034         echo ""
2035         echo "      git[...]ges_apps_Camera refs/changes/26/8126/2 && git cherry-pick FETCH_HEAD"
2036         echo ""
2037         return
2038     fi
2039
2040     if [ ! -d $dir ]; then
2041         echo "Directory $dir doesn't exist in tree."
2042         return
2043     fi
2044     cd $dir
2045     repo=$(cat .git/config  | grep git://github.com | awk '{ print $NF }' | sed s#git://github.com/##g)
2046     echo "Starting branch..."
2047     repo start tmprebase .
2048     echo "Bringing it up to date..."
2049     repo sync .
2050     echo "Fetching change..."
2051     git fetch "http://review.cyanogenmod.org/p/$repo" "refs/changes/$refs" && git cherry-pick FETCH_HEAD
2052     if [ "$?" != "0" ]; then
2053         echo "Error cherry-picking. Not uploading!"
2054         return
2055     fi
2056     echo "Uploading..."
2057     repo upload .
2058     echo "Cleaning up..."
2059     repo abandon tmprebase .
2060     cd $pwd
2061 }
2062
2063 function mka() {
2064     case `uname -s` in
2065         Darwin)
2066             make -j `sysctl hw.ncpu|cut -d" " -f2` "$@"
2067             ;;
2068         *)
2069             schedtool -B -n 1 -e ionice -n 1 make -j$(cat /proc/cpuinfo | grep "^processor" | wc -l) "$@"
2070             ;;
2071     esac
2072 }
2073
2074 function reposync() {
2075     case `uname -s` in
2076         Darwin)
2077             repo sync -j 4 "$@"
2078             ;;
2079         *)
2080             schedtool -B -n 1 -e ionice -n 1 `which repo` sync -j 4 "$@"
2081             ;;
2082     esac
2083 }
2084
2085 function repodiff() {
2086     if [ -z "$*" ]; then
2087         echo "Usage: repodiff <ref-from> [[ref-to] [--numstat]]"
2088         return
2089     fi
2090     diffopts=$* repo forall -c \
2091       'echo "$REPO_PATH ($REPO_REMOTE)"; git diff ${diffopts} 2>/dev/null ;'
2092 }
2093
2094 # Credit for color strip sed: http://goo.gl/BoIcm
2095 function dopush()
2096 {
2097     local func=$1
2098     shift
2099
2100     adb start-server # Prevent unexpected starting server message from adb get-state in the next line
2101     if [ $(adb get-state) != device -a $(adb shell busybox test -e /sbin/recovery 2> /dev/null; echo $?) != 0 ] ; then
2102         echo "No device is online. Waiting for one..."
2103         echo "Please connect USB and/or enable USB debugging"
2104         until [ $(adb get-state) = device -o $(adb shell busybox test -e /sbin/recovery 2> /dev/null; echo $?) = 0 ];do
2105             sleep 1
2106         done
2107         echo "Device Found."
2108     fi
2109
2110     if (adb shell cat /system/build.prop | grep -q "ro.cm.device=$CM_BUILD");
2111     then
2112     adb root &> /dev/null
2113     sleep 0.3
2114     adb wait-for-device &> /dev/null
2115     sleep 0.3
2116     adb remount &> /dev/null
2117
2118     $func $* | tee $OUT/.log
2119
2120     # Install: <file>
2121     LOC=$(cat $OUT/.log | sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' | grep 'Install' | cut -d ':' -f 2)
2122
2123     # Copy: <file>
2124     LOC=$LOC $(cat $OUT/.log | sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' | grep 'Copy' | cut -d ':' -f 2)
2125
2126     for FILE in $LOC; do
2127         # Get target file name (i.e. system/bin/adb)
2128         TARGET=$(echo $FILE | sed "s#$OUT/##")
2129
2130         # Don't send files that are not in /system.
2131         if ! echo $TARGET | egrep '^system\/' > /dev/null ; then
2132             continue
2133         else
2134             case $TARGET in
2135             system/app/SystemUI.apk|system/framework/*)
2136                 stop_n_start=true
2137             ;;
2138             *)
2139                 stop_n_start=false
2140             ;;
2141             esac
2142             if $stop_n_start ; then adb shell stop ; fi
2143             echo "Pushing: $TARGET"
2144             adb push $FILE $TARGET
2145             if $stop_n_start ; then adb shell start ; fi
2146         fi
2147     done
2148     rm -f $OUT/.log
2149     return 0
2150     else
2151         echo "The connected device does not appear to be $CM_BUILD, run away!"
2152     fi
2153 }
2154
2155 alias mmp='dopush mm'
2156 alias mmmp='dopush mmm'
2157 alias mkap='dopush mka'
2158 alias cmkap='dopush cmka'
2159
2160 # Force JAVA_HOME to point to java 1.7/1.8 if it isn't already set.
2161 function set_java_home() {
2162     # Clear the existing JAVA_HOME value if we set it ourselves, so that
2163     # we can reset it later, depending on the version of java the build
2164     # system needs.
2165     #
2166     # If we don't do this, the JAVA_HOME value set by the first call to
2167     # build/envsetup.sh will persist forever.
2168     if [ -n "$ANDROID_SET_JAVA_HOME" ]; then
2169       export JAVA_HOME=""
2170     fi
2171
2172     if [ ! "$JAVA_HOME" ]; then
2173       if [ -n "$LEGACY_USE_JAVA7" ]; then
2174         echo Warning: Support for JDK 7 will be dropped. Switch to JDK 8.
2175         case `uname -s` in
2176             Darwin)
2177                 export JAVA_HOME=$(/usr/libexec/java_home -v 1.7)
2178                 ;;
2179             *)
2180                 export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
2181                 ;;
2182         esac
2183       else
2184         case `uname -s` in
2185             Darwin)
2186                 export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
2187                 ;;
2188             *)
2189                 export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
2190                 ;;
2191         esac
2192       fi
2193
2194       # Keep track of the fact that we set JAVA_HOME ourselves, so that
2195       # we can change it on the next envsetup.sh, if required.
2196       export ANDROID_SET_JAVA_HOME=true
2197     fi
2198 }
2199
2200 # Print colored exit condition
2201 function pez {
2202     "$@"
2203     local retval=$?
2204     if [ $retval -ne 0 ]
2205     then
2206         echo $'\E'"[0;31mFAILURE\e[00m"
2207     else
2208         echo $'\E'"[0;32mSUCCESS\e[00m"
2209     fi
2210     return $retval
2211 }
2212
2213 function get_make_command()
2214 {
2215   echo command make
2216 }
2217
2218 function make()
2219 {
2220     local start_time=$(date +"%s")
2221     $(get_make_command) "$@"
2222     local ret=$?
2223     local end_time=$(date +"%s")
2224     local tdiff=$(($end_time-$start_time))
2225     local hours=$(($tdiff / 3600 ))
2226     local mins=$((($tdiff % 3600) / 60))
2227     local secs=$(($tdiff % 60))
2228     local ncolors=$(tput colors 2>/dev/null)
2229     if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then
2230         color_failed=$'\E'"[0;31m"
2231         color_success=$'\E'"[0;32m"
2232         color_reset=$'\E'"[00m"
2233     else
2234         color_failed=""
2235         color_success=""
2236         color_reset=""
2237     fi
2238     echo
2239     if [ $ret -eq 0 ] ; then
2240         echo -n "${color_success}#### make completed successfully "
2241     else
2242         echo -n "${color_failed}#### make failed to build some targets "
2243     fi
2244     if [ $hours -gt 0 ] ; then
2245         printf "(%02g:%02g:%02g (hh:mm:ss))" $hours $mins $secs
2246     elif [ $mins -gt 0 ] ; then
2247         printf "(%02g:%02g (mm:ss))" $mins $secs
2248     elif [ $secs -gt 0 ] ; then
2249         printf "(%s seconds)" $secs
2250     fi
2251     echo " ####${color_reset}"
2252     echo
2253     return $ret
2254 }
2255
2256 function provision()
2257 {
2258     if [ ! "$ANDROID_PRODUCT_OUT" ]; then
2259         echo "Couldn't locate output files.  Try running 'lunch' first." >&2
2260         return 1
2261     fi
2262     if [ ! -e "$ANDROID_PRODUCT_OUT/provision-device" ]; then
2263         echo "There is no provisioning script for the device." >&2
2264         return 1
2265     fi
2266
2267     # Check if user really wants to do this.
2268     if [ "$1" = "--no-confirmation" ]; then
2269         shift 1
2270     else
2271         echo "This action will reflash your device."
2272         echo ""
2273         echo "ALL DATA ON THE DEVICE WILL BE IRREVOCABLY ERASED."
2274         echo ""
2275         echo -n "Are you sure you want to do this (yes/no)? "
2276         read
2277         if [[ "${REPLY}" != "yes" ]] ; then
2278             echo "Not taking any action. Exiting." >&2
2279             return 1
2280         fi
2281     fi
2282     "$ANDROID_PRODUCT_OUT/provision-device" "$@"
2283 }
2284
2285 if [ "x$SHELL" != "x/bin/bash" ]; then
2286     case `ps -o command -p $$` in
2287         *bash*)
2288             ;;
2289         *)
2290             echo "WARNING: Only bash is supported, use of other shell would lead to erroneous results"
2291             ;;
2292     esac
2293 fi
2294
2295 # Execute the contents of any vendorsetup.sh files we can find.
2296 for f in `test -d device && find -L device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
2297          `test -d vendor && find -L vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
2298          `test -d product && find -L product -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort`
2299 do
2300     echo "including $f"
2301     . $f
2302 done
2303 unset f
2304
2305 addcompletions