OSDN Git Service

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