Import CM build additions

Change-Id: Id1eb902129754e61dfcc2b5d95c3a75172ff0c5e
diff --git a/build/core/mtk_target.mk b/build/core/mtk_target.mk
new file mode 100644
index 0000000..7c3ba1f
--- /dev/null
+++ b/build/core/mtk_target.mk
@@ -0,0 +1,13 @@
+ifeq ($(BOARD_USES_MTK_HARDWARE),true)
+    mtk_flags := -DMTK_HARDWARE
+
+    TARGET_GLOBAL_CFLAGS += $(mtk_flags)
+    TARGET_GLOBAL_CPPFLAGS += $(mtk_flags)
+    CLANG_TARGET_GLOBAL_CFLAGS += $(mtk_flags)
+    CLANG_TARGET_GLOBAL_CPPFLAGS += $(mtk_flags)
+
+    2ND_TARGET_GLOBAL_CFLAGS += $(mtk_flags)
+    2ND_TARGET_GLOBAL_CPPFLAGS += $(mtk_flags)
+    2ND_CLANG_TARGET_GLOBAL_CFLAGS += $(mtk_flags)
+    2ND_CLANG_TARGET_GLOBAL_CPPFLAGS += $(mtk_flags)
+endif
diff --git a/build/core/mtk_utils.mk b/build/core/mtk_utils.mk
new file mode 100755
index 0000000..48fd660
--- /dev/null
+++ b/build/core/mtk_utils.mk
@@ -0,0 +1,5 @@
+# Board platforms lists to be used for
+# TARGET_BOARD_PLATFORM specific featurization
+MTK_BOARD_PLATFORMS := mt6592
+MTK_BOARD_PLATFORMS += mt6582
+MTK_BOARD_PLATFORMS += mt6572
diff --git a/build/core/qcom_target.mk b/build/core/qcom_target.mk
new file mode 100644
index 0000000..29e134a
--- /dev/null
+++ b/build/core/qcom_target.mk
@@ -0,0 +1,133 @@
+# Target-specific configuration
+
+# Populate the qcom hardware variants in the project pathmap.
+define ril-set-path-variant
+$(call project-set-path-variant,ril,TARGET_RIL_VARIANT,hardware/$(1))
+endef
+define wlan-set-path-variant
+$(call project-set-path-variant,wlan,TARGET_WLAN_VARIANT,hardware/qcom/$(1))
+endef
+define bt-vendor-set-path-variant
+$(call project-set-path-variant,bt-vendor,TARGET_BT_VENDOR_VARIANT,hardware/qcom/$(1))
+endef
+
+# Set device-specific HALs into project pathmap
+define set-device-specific-path
+$(if $(USE_DEVICE_SPECIFIC_$(1)), \
+    $(if $(DEVICE_SPECIFIC_$(1)_PATH), \
+        $(eval path := $(DEVICE_SPECIFIC_$(1)_PATH)), \
+        $(eval path := $(TARGET_DEVICE_DIR)/$(2))), \
+    $(eval path := $(3))) \
+$(call project-set-path,qcom-$(2),$(strip $(path)))
+endef
+
+ifeq ($(BOARD_USES_QCOM_HARDWARE),true)
+
+    qcom_flags := -DQCOM_HARDWARE
+    qcom_flags += -DQCOM_BSP
+    qcom_flags += -DQTI_BSP
+
+    TARGET_USES_QCOM_BSP := true
+
+    # Tell HALs that we're compiling an AOSP build with an in-line kernel
+    TARGET_COMPILE_WITH_MSM_KERNEL := true
+
+    ifneq ($(filter msm7x27a msm7x30 msm8660 msm8960,$(TARGET_BOARD_PLATFORM)),)
+        # Enable legacy graphics functions
+        qcom_flags += -DQCOM_BSP_LEGACY
+        # Enable legacy audio functions
+        ifeq ($(BOARD_USES_LEGACY_ALSA_AUDIO),true)
+            USE_CUSTOM_AUDIO_POLICY := 1
+            qcom_flags += -DLEGACY_ALSA_AUDIO
+        endif
+    endif
+
+    # Enable extra offloading for post-805 targets
+    ifneq ($(filter msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),)
+        qcom_flags += -DHAS_EXTRA_FLAC_METADATA
+    endif
+
+    TARGET_GLOBAL_CFLAGS += $(qcom_flags)
+    TARGET_GLOBAL_CPPFLAGS += $(qcom_flags)
+    CLANG_TARGET_GLOBAL_CFLAGS += $(qcom_flags)
+    CLANG_TARGET_GLOBAL_CPPFLAGS += $(qcom_flags)
+
+    # Multiarch needs these too..
+    2ND_TARGET_GLOBAL_CFLAGS += $(qcom_flags)
+    2ND_TARGET_GLOBAL_CPPFLAGS += $(qcom_flags)
+    2ND_CLANG_TARGET_GLOBAL_CFLAGS += $(qcom_flags)
+    2ND_CLANG_TARGET_GLOBAL_CPPFLAGS += $(qcom_flags)
+
+    ifeq ($(QCOM_HARDWARE_VARIANT),)
+        ifneq ($(filter msm8610 msm8226 msm8974,$(TARGET_BOARD_PLATFORM)),)
+            QCOM_HARDWARE_VARIANT := msm8974
+        else
+        ifneq ($(filter msm8909 msm8916,$(TARGET_BOARD_PLATFORM)),)
+            QCOM_HARDWARE_VARIANT := msm8916
+        else
+        ifneq ($(filter msm8953 msm8937,$(TARGET_BOARD_PLATFORM)),)
+            QCOM_HARDWARE_VARIANT := msm8937
+        else
+        ifneq ($(filter msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),)
+            QCOM_HARDWARE_VARIANT := msm8994
+        else
+            QCOM_HARDWARE_VARIANT := $(TARGET_BOARD_PLATFORM)
+        endif
+        endif
+        endif
+        endif
+    endif
+
+# HACK: check to see if build uses standard QC HAL paths by checking for CM path structure
+AOSP_VARIANT_MAKEFILE := $(wildcard hardware/qcom/audio/default/Android.mk)
+ifeq ("$(AOSP_VARIANT_MAKEFILE)","")
+$(call project-set-path,qcom-audio,hardware/qcom/audio)
+$(call project-set-path,qcom-display,hardware/qcom/display)
+$(call project-set-path,qcom-media,hardware/qcom/media)
+$(call set-device-specific-path,CAMERA,camera,hardware/qcom/camera)
+$(call set-device-specific-path,GPS,gps,hardware/qcom/gps)
+$(call set-device-specific-path,SENSORS,sensors,hardware/qcom/sensors)
+$(call set-device-specific-path,LOC_API,loc-api,vendor/qcom/opensource/location)
+$(call set-device-specific-path,DATASERVICES,dataservices,vendor/qcom/opensource/dataservices)
+$(call project-set-path,ril,hardware/ril)
+$(call project-set-path,wlan,hardware/qcom/wlan)
+$(call project-set-path,bt-vendor,hardware/qcom/bt)
+else
+$(call project-set-path,qcom-audio,hardware/qcom/audio-caf/$(QCOM_HARDWARE_VARIANT))
+
+ifeq ($(SONY_BF64_KERNEL_VARIANT),true)
+$(call project-set-path,qcom-display,hardware/qcom/display-caf/sony)
+$(call project-set-path,qcom-media,hardware/qcom/media-caf/sony)
+else
+$(call project-set-path,qcom-display,hardware/qcom/display-caf/$(QCOM_HARDWARE_VARIANT))
+$(call project-set-path,qcom-media,hardware/qcom/media-caf/$(QCOM_HARDWARE_VARIANT))
+endif
+
+$(call set-device-specific-path,CAMERA,camera,hardware/qcom/camera)
+$(call set-device-specific-path,GPS,gps,hardware/qcom/gps)
+$(call set-device-specific-path,SENSORS,sensors,hardware/qcom/sensors)
+$(call set-device-specific-path,LOC_API,loc-api,vendor/qcom/opensource/location)
+$(call set-device-specific-path,DATASERVICES,dataservices,vendor/qcom/opensource/dataservices)
+
+$(call ril-set-path-variant,ril)
+$(call wlan-set-path-variant,wlan-caf)
+$(call bt-vendor-set-path-variant,bt-caf)
+endif # AOSP_VARIANT_MAKEFILE
+
+else
+
+$(call project-set-path,qcom-audio,hardware/qcom/audio/default)
+$(call project-set-path,qcom-display,hardware/qcom/display/$(TARGET_BOARD_PLATFORM))
+$(call project-set-path,qcom-media,hardware/qcom/media)
+
+$(call project-set-path,qcom-camera,hardware/qcom/camera)
+$(call project-set-path,qcom-gps,hardware/qcom/gps)
+$(call project-set-path,qcom-sensors,hardware/qcom/sensors)
+$(call project-set-path,qcom-loc-api,vendor/qcom/opensource/location)
+$(call project-set-path,qcom-dataservices,$(TARGET_DEVICE_DIR)/dataservices)
+
+$(call ril-set-path-variant,ril)
+$(call wlan-set-path-variant,wlan)
+$(call bt-vendor-set-path-variant,bt)
+
+endif
diff --git a/build/core/qcom_utils.mk b/build/core/qcom_utils.mk
new file mode 100755
index 0000000..50e0b4e
--- /dev/null
+++ b/build/core/qcom_utils.mk
@@ -0,0 +1,230 @@
+# Board platforms lists to be used for
+# TARGET_BOARD_PLATFORM specific featurization
+QCOM_BOARD_PLATFORMS += msm7x27a
+QCOM_BOARD_PLATFORMS += msm7x30
+QCOM_BOARD_PLATFORMS += msm8226
+QCOM_BOARD_PLATFORMS += msm8610
+QCOM_BOARD_PLATFORMS += msm8660
+QCOM_BOARD_PLATFORMS += msm8909
+QCOM_BOARD_PLATFORMS += msm8916
+QCOM_BOARD_PLATFORMS += msm8960
+QCOM_BOARD_PLATFORMS += msm8974
+QCOM_BOARD_PLATFORMS += mpq8092
+QCOM_BOARD_PLATFORMS += msm8937
+QCOM_BOARD_PLATFORMS += msm8952
+QCOM_BOARD_PLATFORMS += msm8953
+QCOM_BOARD_PLATFORMS += msm8992
+QCOM_BOARD_PLATFORMS += msm8994
+QCOM_BOARD_PLATFORMS += msm8996
+QCOM_BOARD_PLATFORMS += msm_bronze
+QCOM_BOARD_PLATFORMS += apq8084
+
+MSM7K_BOARD_PLATFORMS := msm7x30
+MSM7K_BOARD_PLATFORMS += msm7x27
+MSM7K_BOARD_PLATFORMS += msm7x27a
+MSM7K_BOARD_PLATFORMS += msm7k
+
+QSD8K_BOARD_PLATFORMS := qsd8k
+
+
+# vars for use by utils
+empty :=
+space := $(empty) $(empty)
+colon := $(empty):$(empty)
+underscore := $(empty)_$(empty)
+
+# $(call match-word,w1,w2)
+# checks if w1 == w2
+# How it works
+#   if (w1-w2 not empty or w2-w1 not empty) then not_match else match
+#
+# returns true or empty
+#$(warning :$(1): :$(2): :$(subst $(1),,$(2)):) \
+#$(warning :$(2): :$(1): :$(subst $(2),,$(1)):) \
+#
+define match-word
+$(strip \
+  $(if $(or $(subst $(1),$(empty),$(2)),$(subst $(2),$(empty),$(1))),,true) \
+)
+endef
+
+# $(call find-word-in-list,w,wlist)
+# finds an exact match of word w in word list wlist
+#
+# How it works
+#   fill wlist spaces with colon
+#   wrap w with colon
+#   search word w in list wl, if found match m, return stripped word w
+#
+# returns stripped word or empty
+define find-word-in-list
+$(strip \
+  $(eval wl:= $(colon)$(subst $(space),$(colon),$(strip $(2)))$(colon)) \
+  $(eval w:= $(colon)$(strip $(1))$(colon)) \
+  $(eval m:= $(findstring $(w),$(wl))) \
+  $(if $(m),$(1),) \
+)
+endef
+
+# $(call match-word-in-list,w,wlist)
+# does an exact match of word w in word list wlist
+# How it works
+#   if the input word is not empty
+#     return output of an exact match of word w in wordlist wlist
+#   else
+#     return empty
+# returns true or empty
+define match-word-in-list
+$(strip \
+  $(if $(strip $(1)), \
+    $(call match-word,$(call find-word-in-list,$(1),$(2)),$(strip $(1))), \
+  ) \
+)
+endef
+
+# $(call match-prefix,p,delim,w/wlist)
+# matches prefix p in wlist using delimiter delim
+#
+# How it works
+#   trim the words in wlist w
+#   if find-word-in-list returns not empty
+#     return true
+#   else
+#     return empty
+#
+define match-prefix
+$(strip \
+  $(eval w := $(strip $(1)$(strip $(2)))) \
+  $(eval text := $(patsubst $(w)%,$(1),$(3))) \
+  $(if $(call match-word-in-list,$(1),$(text)),true,) \
+)
+endef
+
+# ----
+# The following utilities are meant for board platform specific
+# featurisation
+
+# $(call get-vendor-board-platforms,v)
+# returns list of board platforms for vendor v
+define get-vendor-board-platforms
+$(if $(call match-word,$(BOARD_USES_$(1)_HARDWARE),true),$($(1)_BOARD_PLATFORMS))
+endef
+
+# $(call is-board-platform,bp)
+# returns true or empty
+define is-board-platform
+$(call match-word,$(1),$(TARGET_BOARD_PLATFORM))
+endef
+
+# $(call is-not-board-platform,bp)
+# returns true or empty
+define is-not-board-platform
+$(if $(call match-word,$(1),$(TARGET_BOARD_PLATFORM)),,true)
+endef
+
+# $(call is-board-platform-in-list,bpl)
+# returns true or empty
+define is-board-platform-in-list
+$(call match-word-in-list,$(TARGET_BOARD_PLATFORM),$(1))
+endef
+
+# $(call is-vendor-board-platform,vendor)
+# returns true or empty
+define is-vendor-board-platform
+$(strip \
+  $(call match-word-in-list,$(TARGET_BOARD_PLATFORM),\
+    $(call get-vendor-board-platforms,$(1)) \
+  ) \
+)
+endef
+
+# $(call is-chipset-in-board-platform,chipset)
+# does a prefix match of chipset in TARGET_BOARD_PLATFORM
+# uses underscore as a delimiter
+#
+# returns true or empty
+define is-chipset-in-board-platform
+$(call match-prefix,$(1),$(underscore),$(TARGET_BOARD_PLATFORM))
+endef
+
+# $(call is-chipset-prefix-in-board-platform,prefix)
+# does a chipset prefix match in TARGET_BOARD_PLATFORM
+# assumes '_' and 'a' as the delimiter to the chipset prefix
+#
+# How it works
+#   if ($(prefix)_ or $(prefix)a match in board platform)
+#     return true
+#   else
+#     return empty
+#
+define is-chipset-prefix-in-board-platform
+$(strip \
+  $(eval delim_a := $(empty)a$(empty)) \
+  $(if \
+    $(or \
+      $(call match-prefix,$(1),$(delim_a),$(TARGET_BOARD_PLATFORM)), \
+      $(call match-prefix,$(1),$(underscore),$(TARGET_BOARD_PLATFORM)), \
+    ), \
+    true, \
+  ) \
+)
+endef
+
+#----
+# The following utilities are meant for Android Code Name
+# specific featurisation
+#
+# refer http://source.android.com/source/build-numbers.html
+# for code names and associated sdk versions
+CUPCAKE_SDK_VERSIONS := 3
+DONUT_SDK_VERSIONS   := 4
+ECLAIR_SDK_VERSIONS  := 5 6 7
+FROYO_SDK_VERSIONS   := 8
+GINGERBREAD_SDK_VERSIONS := 9 10
+HONEYCOMB_SDK_VERSIONS := 11 12 13
+ICECREAM_SANDWICH_SDK_VERSIONS := 14 15
+JELLY_BEAN_SDK_VERSIONS := 16 17 18
+
+# $(call is-platform-sdk-version-at-least,version)
+# version is a numeric SDK_VERSION defined above
+define is-platform-sdk-version-at-least
+$(strip \
+  $(if $(filter 1,$(shell echo "$$(( $(PLATFORM_SDK_VERSION) >= $(1) ))" )), \
+    true, \
+  ) \
+)
+endef
+
+# $(call is-android-codename,codename)
+# codename is one of cupcake,donut,eclair,froyo,gingerbread,icecream
+# please refer the $(codename)_SDK_VERSIONS declared above
+define is-android-codename
+$(strip \
+  $(if \
+    $(call match-word-in-list,$(PLATFORM_SDK_VERSION),$($(1)_SDK_VERSIONS)), \
+    true, \
+  ) \
+)
+endef
+
+# $(call is-android-codename-in-list,cnlist)
+# cnlist is combination/list of android codenames
+define is-android-codename-in-list
+$(strip \
+  $(eval acn := $(empty)) \
+    $(foreach \
+      i,$(1),\
+      $(eval acn += \
+        $(if \
+          $(call \
+            match-word-in-list,\
+            $(PLATFORM_SDK_VERSION),\
+            $($(i)_SDK_VERSIONS)\
+          ),\
+          true,\
+        )\
+      )\
+    ) \
+  $(if $(strip $(acn)),true,) \
+)
+endef
diff --git a/build/envsetup.sh b/build/envsetup.sh
new file mode 100644
index 0000000..f534eb8
--- /dev/null
+++ b/build/envsetup.sh
@@ -0,0 +1,931 @@
+function __print_cm_functions_help() {
+cat <<EOF
+Additional CyanogenMod functions:
+- cout:            Changes directory to out.
+- mmp:             Builds all of the modules in the current directory and pushes them to the device.
+- mmap:            Builds all of the modules in the current directory and its dependencies, then pushes the package to the device.
+- mmmp:            Builds all of the modules in the supplied directories and pushes them to the device.
+- mms:             Short circuit builder. Quickly re-build the kernel, rootfs, boot and system images
+                   without deep dependencies. Requires the full build to have run before.
+- cmgerrit:        A Git wrapper that fetches/pushes patch from/to CM Gerrit Review.
+- cmrebase:        Rebase a Gerrit change and push it again.
+- cmremote:        Add git remote for CM Gerrit Review.
+- aospremote:      Add git remote for matching AOSP repository.
+- cafremote:       Add git remote for matching CodeAurora repository.
+- mka:             Builds using SCHED_BATCH on all processors.
+- mkap:            Builds the module(s) using mka and pushes them to the device.
+- cmka:            Cleans and builds using mka.
+- repodiff:        Diff 2 different branches or tags within the same repo
+- repolastsync:    Prints date and time of last repo sync.
+- reposync:        Parallel repo sync using ionice and SCHED_BATCH.
+- repopick:        Utility to fetch changes from Gerrit.
+- installboot:     Installs a boot.img to the connected device.
+- installrecovery: Installs a recovery.img to the connected device.
+EOF
+}
+
+function brunch()
+{
+    breakfast $*
+    if [ $? -eq 0 ]; then
+        mka bacon
+    else
+        echo "No such item in brunch menu. Try 'breakfast'"
+        return 1
+    fi
+    return $?
+}
+
+function breakfast()
+{
+    target=$1
+    local variant=$2
+    CM_DEVICES_ONLY="true"
+    unset LUNCH_MENU_CHOICES
+    add_lunch_combo full-eng
+    for f in `/bin/ls vendor/cm/vendorsetup.sh 2> /dev/null`
+        do
+            echo "including $f"
+            . $f
+        done
+    unset f
+
+    if [ $# -eq 0 ]; then
+        # No arguments, so let's have the full menu
+        lunch
+    else
+        echo "z$target" | grep -q "-"
+        if [ $? -eq 0 ]; then
+            # A buildtype was specified, assume a full device name
+            lunch $target
+        else
+            # This is probably just the CM model name
+            if [ -z "$variant" ]; then
+                variant="userdebug"
+            fi
+            lunch cm_$target-$variant
+        fi
+    fi
+    return $?
+}
+
+alias bib=breakfast
+
+function eat()
+{
+    if [ "$OUT" ] ; then
+        MODVERSION=$(get_build_var CM_VERSION)
+        ZIPFILE=cm-$MODVERSION.zip
+        ZIPPATH=$OUT/$ZIPFILE
+        if [ ! -f $ZIPPATH ] ; then
+            echo "Nothing to eat"
+            return 1
+        fi
+        adb start-server # Prevent unexpected starting server message from adb get-state in the next line
+        if [ $(adb get-state) != device -a $(adb shell test -e /sbin/recovery 2> /dev/null; echo $?) != 0 ] ; then
+            echo "No device is online. Waiting for one..."
+            echo "Please connect USB and/or enable USB debugging"
+            until [ $(adb get-state) = device -o $(adb shell test -e /sbin/recovery 2> /dev/null; echo $?) = 0 ];do
+                sleep 1
+            done
+            echo "Device Found.."
+        fi
+    if (adb shell getprop ro.cm.device | grep -q "$CM_BUILD");
+    then
+        # if adbd isn't root we can't write to /cache/recovery/
+        adb root
+        sleep 1
+        adb wait-for-device
+        cat << EOF > /tmp/command
+--sideload_auto_reboot
+EOF
+        if adb push /tmp/command /cache/recovery/ ; then
+            echo "Rebooting into recovery for sideload installation"
+            adb reboot recovery
+            adb wait-for-sideload
+            adb sideload $ZIPPATH
+        fi
+        rm /tmp/command
+    else
+        echo "Nothing to eat"
+        return 1
+    fi
+    return $?
+    else
+        echo "The connected device does not appear to be $CM_BUILD, run away!"
+    fi
+}
+
+function omnom()
+{
+    brunch $*
+    eat
+}
+
+function cout()
+{
+    if [  "$OUT" ]; then
+        cd $OUT
+    else
+        echo "Couldn't locate out directory.  Try setting OUT."
+    fi
+}
+
+function dddclient()
+{
+   local OUT_ROOT=$(get_abs_build_var PRODUCT_OUT)
+   local OUT_SYMBOLS=$(get_abs_build_var TARGET_OUT_UNSTRIPPED)
+   local OUT_SO_SYMBOLS=$(get_abs_build_var TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED)
+   local OUT_VENDOR_SO_SYMBOLS=$(get_abs_build_var TARGET_OUT_VENDOR_SHARED_LIBRARIES_UNSTRIPPED)
+   local OUT_EXE_SYMBOLS=$(get_symbols_directory)
+   local PREBUILTS=$(get_abs_build_var ANDROID_PREBUILTS)
+   local ARCH=$(get_build_var TARGET_ARCH)
+   local GDB
+   case "$ARCH" in
+       arm) GDB=arm-linux-androideabi-gdb;;
+       arm64) GDB=arm-linux-androideabi-gdb; GDB64=aarch64-linux-android-gdb;;
+       mips|mips64) GDB=mips64el-linux-android-gdb;;
+       x86) GDB=x86_64-linux-android-gdb;;
+       x86_64) GDB=x86_64-linux-android-gdb;;
+       *) echo "Unknown arch $ARCH"; return 1;;
+   esac
+
+   if [ "$OUT_ROOT" -a "$PREBUILTS" ]; then
+       local EXE="$1"
+       if [ "$EXE" ] ; then
+           EXE=$1
+           if [[ $EXE =~ ^[^/].* ]] ; then
+               EXE="system/bin/"$EXE
+           fi
+       else
+           EXE="app_process"
+       fi
+
+       local PORT="$2"
+       if [ "$PORT" ] ; then
+           PORT=$2
+       else
+           PORT=":5039"
+       fi
+
+       local PID="$3"
+       if [ "$PID" ] ; then
+           if [[ ! "$PID" =~ ^[0-9]+$ ]] ; then
+               PID=`pid $3`
+               if [[ ! "$PID" =~ ^[0-9]+$ ]] ; then
+                   # that likely didn't work because of returning multiple processes
+                   # try again, filtering by root processes (don't contain colon)
+                   PID=`adb shell ps | \grep $3 | \grep -v ":" | awk '{print $2}'`
+                   if [[ ! "$PID" =~ ^[0-9]+$ ]]
+                   then
+                       echo "Couldn't resolve '$3' to single PID"
+                       return 1
+                   else
+                       echo ""
+                       echo "WARNING: multiple processes matching '$3' observed, using root process"
+                       echo ""
+                   fi
+               fi
+           fi
+           adb forward "tcp$PORT" "tcp$PORT"
+           local USE64BIT="$(is64bit $PID)"
+           adb shell gdbserver$USE64BIT $PORT --attach $PID &
+           sleep 2
+       else
+               echo ""
+               echo "If you haven't done so already, do this first on the device:"
+               echo "    gdbserver $PORT /system/bin/$EXE"
+                   echo " or"
+               echo "    gdbserver $PORT --attach <PID>"
+               echo ""
+       fi
+
+       OUT_SO_SYMBOLS=$OUT_SO_SYMBOLS$USE64BIT
+       OUT_VENDOR_SO_SYMBOLS=$OUT_VENDOR_SO_SYMBOLS$USE64BIT
+
+       echo >|"$OUT_ROOT/gdbclient.cmds" "set solib-absolute-prefix $OUT_SYMBOLS"
+       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"
+       echo >>"$OUT_ROOT/gdbclient.cmds" "source $ANDROID_BUILD_TOP/development/scripts/gdb/dalvik.gdb"
+       echo >>"$OUT_ROOT/gdbclient.cmds" "target remote $PORT"
+       # Enable special debugging for ART processes.
+       if [[ $EXE =~ (^|/)(app_process|dalvikvm)(|32|64)$ ]]; then
+          echo >> "$OUT_ROOT/gdbclient.cmds" "art-on"
+       fi
+       echo >>"$OUT_ROOT/gdbclient.cmds" ""
+
+       local WHICH_GDB=
+       # 64-bit exe found
+       if [ "$USE64BIT" != "" ] ; then
+           WHICH_GDB=$ANDROID_TOOLCHAIN/$GDB64
+       # 32-bit exe / 32-bit platform
+       elif [ "$(get_build_var TARGET_2ND_ARCH)" = "" ]; then
+           WHICH_GDB=$ANDROID_TOOLCHAIN/$GDB
+       # 32-bit exe / 64-bit platform
+       else
+           WHICH_GDB=$ANDROID_TOOLCHAIN_2ND_ARCH/$GDB
+       fi
+
+       ddd --debugger $WHICH_GDB -x "$OUT_ROOT/gdbclient.cmds" "$OUT_EXE_SYMBOLS/$EXE"
+  else
+       echo "Unable to determine build system output dir."
+   fi
+}
+
+function cmremote()
+{
+    if ! git rev-parse --git-dir &> /dev/null
+    then
+        echo ".git directory not found. Please run this from the root directory of the Android repository you wish to set up."
+        return 1
+    fi
+    git remote rm cmremote 2> /dev/null
+    GERRIT_REMOTE=$(git config --get remote.github.projectname)
+    CMUSER=$(git config --get review.review.cyanogenmod.org.username)
+    if [ -z "$CMUSER" ]
+    then
+        git remote add cmremote ssh://review.cyanogenmod.org:29418/$GERRIT_REMOTE
+    else
+        git remote add cmremote ssh://$CMUSER@review.cyanogenmod.org:29418/$GERRIT_REMOTE
+    fi
+    echo "Remote 'cmremote' created"
+}
+
+function aospremote()
+{
+    if ! git rev-parse --git-dir &> /dev/null
+    then
+        echo ".git directory not found. Please run this from the root directory of the Android repository you wish to set up."
+        return 1
+    fi
+    git remote rm aosp 2> /dev/null
+    PROJECT=$(pwd -P | sed "s#$ANDROID_BUILD_TOP\/##")
+    if (echo $PROJECT | grep -qv "^device")
+    then
+        PFX="platform/"
+    fi
+    git remote add aosp https://android.googlesource.com/$PFX$PROJECT
+    echo "Remote 'aosp' created"
+}
+
+function cafremote()
+{
+    if ! git rev-parse --git-dir &> /dev/null
+    then
+        echo ".git directory not found. Please run this from the root directory of the Android repository you wish to set up."
+        return 1
+    fi
+    git remote rm caf 2> /dev/null
+    PROJECT=$(pwd -P | sed "s#$ANDROID_BUILD_TOP\/##")
+    if (echo $PROJECT | grep -qv "^device")
+    then
+        PFX="platform/"
+    fi
+    git remote add caf git://codeaurora.org/$PFX$PROJECT
+    echo "Remote 'caf' created"
+}
+
+function installboot()
+{
+    if [ ! -e "$OUT/recovery/root/etc/recovery.fstab" ];
+    then
+        echo "No recovery.fstab found. Build recovery first."
+        return 1
+    fi
+    if [ ! -e "$OUT/boot.img" ];
+    then
+        echo "No boot.img found. Run make bootimage first."
+        return 1
+    fi
+    PARTITION=`grep "^\/boot" $OUT/recovery/root/etc/recovery.fstab | awk {'print $3'}`
+    if [ -z "$PARTITION" ];
+    then
+        # Try for RECOVERY_FSTAB_VERSION = 2
+        PARTITION=`grep "[[:space:]]\/boot[[:space:]]" $OUT/recovery/root/etc/recovery.fstab | awk {'print $1'}`
+        PARTITION_TYPE=`grep "[[:space:]]\/boot[[:space:]]" $OUT/recovery/root/etc/recovery.fstab | awk {'print $3'}`
+        if [ -z "$PARTITION" ];
+        then
+            echo "Unable to determine boot partition."
+            return 1
+        fi
+    fi
+    adb start-server
+    adb wait-for-online
+    adb root
+    sleep 1
+    adb wait-for-online shell mount /system 2>&1 > /dev/null
+    adb wait-for-online remount
+    if (adb shell getprop ro.cm.device | grep -q "$CM_BUILD");
+    then
+        adb push $OUT/boot.img /cache/
+        for i in $OUT/system/lib/modules/*;
+        do
+            adb push $i /system/lib/modules/
+        done
+        adb shell dd if=/cache/boot.img of=$PARTITION
+        adb shell chmod 644 /system/lib/modules/*
+        echo "Installation complete."
+    else
+        echo "The connected device does not appear to be $CM_BUILD, run away!"
+    fi
+}
+
+function installrecovery()
+{
+    if [ ! -e "$OUT/recovery/root/etc/recovery.fstab" ];
+    then
+        echo "No recovery.fstab found. Build recovery first."
+        return 1
+    fi
+    if [ ! -e "$OUT/recovery.img" ];
+    then
+        echo "No recovery.img found. Run make recoveryimage first."
+        return 1
+    fi
+    PARTITION=`grep "^\/recovery" $OUT/recovery/root/etc/recovery.fstab | awk {'print $3'}`
+    if [ -z "$PARTITION" ];
+    then
+        # Try for RECOVERY_FSTAB_VERSION = 2
+        PARTITION=`grep "[[:space:]]\/recovery[[:space:]]" $OUT/recovery/root/etc/recovery.fstab | awk {'print $1'}`
+        PARTITION_TYPE=`grep "[[:space:]]\/recovery[[:space:]]" $OUT/recovery/root/etc/recovery.fstab | awk {'print $3'}`
+        if [ -z "$PARTITION" ];
+        then
+            echo "Unable to determine recovery partition."
+            return 1
+        fi
+    fi
+    adb start-server
+    adb wait-for-online
+    adb root
+    sleep 1
+    adb wait-for-online shell mount /system 2>&1 >> /dev/null
+    adb wait-for-online remount
+    if (adb shell getprop ro.cm.device | grep -q "$CM_BUILD");
+    then
+        adb push $OUT/recovery.img /cache/
+        adb shell dd if=/cache/recovery.img of=$PARTITION
+        echo "Installation complete."
+    else
+        echo "The connected device does not appear to be $CM_BUILD, run away!"
+    fi
+}
+
+function makerecipe() {
+    if [ -z "$1" ]
+    then
+        echo "No branch name provided."
+        return 1
+    fi
+    cd android
+    sed -i s/'default revision=.*'/'default revision="refs\/heads\/'$1'"'/ default.xml
+    git commit -a -m "$1"
+    cd ..
+
+    repo forall -c '
+
+    if [ "$REPO_REMOTE" = "github" ]
+    then
+        pwd
+        cmremote
+        git push cmremote HEAD:refs/heads/'$1'
+    fi
+    '
+}
+
+function cmgerrit() {
+    if [ "$(__detect_shell)" = "zsh" ]; then
+        # zsh does not define FUNCNAME, derive from funcstack
+        local FUNCNAME=$funcstack[1]
+    fi
+
+    if [ $# -eq 0 ]; then
+        $FUNCNAME help
+        return 1
+    fi
+    local user=`git config --get review.review.cyanogenmod.org.username`
+    local review=`git config --get remote.github.review`
+    local project=`git config --get remote.github.projectname`
+    local command=$1
+    shift
+    case $command in
+        help)
+            if [ $# -eq 0 ]; then
+                cat <<EOF
+Usage:
+    $FUNCNAME COMMAND [OPTIONS] [CHANGE-ID[/PATCH-SET]][{@|^|~|:}ARG] [-- ARGS]
+
+Commands:
+    fetch   Just fetch the change as FETCH_HEAD
+    help    Show this help, or for a specific command
+    pull    Pull a change into current branch
+    push    Push HEAD or a local branch to Gerrit for a specific branch
+
+Any other Git commands that support refname would work as:
+    git fetch URL CHANGE && git COMMAND OPTIONS FETCH_HEAD{@|^|~|:}ARG -- ARGS
+
+See '$FUNCNAME help COMMAND' for more information on a specific command.
+
+Example:
+    $FUNCNAME checkout -b topic 1234/5
+works as:
+    git fetch http://DOMAIN/p/PROJECT refs/changes/34/1234/5 \\
+      && git checkout -b topic FETCH_HEAD
+will checkout a new branch 'topic' base on patch-set 5 of change 1234.
+Patch-set 1 will be fetched if omitted.
+EOF
+                return
+            fi
+            case $1 in
+                __cmg_*) echo "For internal use only." ;;
+                changes|for)
+                    if [ "$FUNCNAME" = "cmgerrit" ]; then
+                        echo "'$FUNCNAME $1' is deprecated."
+                    fi
+                    ;;
+                help) $FUNCNAME help ;;
+                fetch|pull) cat <<EOF
+usage: $FUNCNAME $1 [OPTIONS] CHANGE-ID[/PATCH-SET]
+
+works as:
+    git $1 OPTIONS http://DOMAIN/p/PROJECT \\
+      refs/changes/HASH/CHANGE-ID/{PATCH-SET|1}
+
+Example:
+    $FUNCNAME $1 1234
+will $1 patch-set 1 of change 1234
+EOF
+                    ;;
+                push) cat <<EOF
+usage: $FUNCNAME push [OPTIONS] [LOCAL_BRANCH:]REMOTE_BRANCH
+
+works as:
+    git push OPTIONS ssh://USER@DOMAIN:29418/PROJECT \\
+      {LOCAL_BRANCH|HEAD}:refs/for/REMOTE_BRANCH
+
+Example:
+    $FUNCNAME push fix6789:gingerbread
+will push local branch 'fix6789' to Gerrit for branch 'gingerbread'.
+HEAD will be pushed from local if omitted.
+EOF
+                    ;;
+                *)
+                    $FUNCNAME __cmg_err_not_supported $1 && return
+                    cat <<EOF
+usage: $FUNCNAME $1 [OPTIONS] CHANGE-ID[/PATCH-SET][{@|^|~|:}ARG] [-- ARGS]
+
+works as:
+    git fetch http://DOMAIN/p/PROJECT \\
+      refs/changes/HASH/CHANGE-ID/{PATCH-SET|1} \\
+      && git $1 OPTIONS FETCH_HEAD{@|^|~|:}ARG -- ARGS
+EOF
+                    ;;
+            esac
+            ;;
+        __cmg_get_ref)
+            $FUNCNAME __cmg_err_no_arg $command $# && return 1
+            local change_id patchset_id hash
+            case $1 in
+                */*)
+                    change_id=${1%%/*}
+                    patchset_id=${1#*/}
+                    ;;
+                *)
+                    change_id=$1
+                    patchset_id=1
+                    ;;
+            esac
+            hash=$(($change_id % 100))
+            case $hash in
+                [0-9]) hash="0$hash" ;;
+            esac
+            echo "refs/changes/$hash/$change_id/$patchset_id"
+            ;;
+        fetch|pull)
+            $FUNCNAME __cmg_err_no_arg $command $# help && return 1
+            $FUNCNAME __cmg_err_not_repo && return 1
+            local change=$1
+            shift
+            git $command $@ http://$review/p/$project \
+                $($FUNCNAME __cmg_get_ref $change) || return 1
+            ;;
+        push)
+            $FUNCNAME __cmg_err_no_arg $command $# help && return 1
+            $FUNCNAME __cmg_err_not_repo && return 1
+            if [ -z "$user" ]; then
+                echo >&2 "Gerrit username not found."
+                return 1
+            fi
+            local local_branch remote_branch
+            case $1 in
+                *:*)
+                    local_branch=${1%:*}
+                    remote_branch=${1##*:}
+                    ;;
+                *)
+                    local_branch=HEAD
+                    remote_branch=$1
+                    ;;
+            esac
+            shift
+            git push $@ ssh://$user@$review:29418/$project \
+                $local_branch:refs/for/$remote_branch || return 1
+            ;;
+        changes|for)
+            if [ "$FUNCNAME" = "cmgerrit" ]; then
+                echo >&2 "'$FUNCNAME $command' is deprecated."
+            fi
+            ;;
+        __cmg_err_no_arg)
+            if [ $# -lt 2 ]; then
+                echo >&2 "'$FUNCNAME $command' missing argument."
+            elif [ $2 -eq 0 ]; then
+                if [ -n "$3" ]; then
+                    $FUNCNAME help $1
+                else
+                    echo >&2 "'$FUNCNAME $1' missing argument."
+                fi
+            else
+                return 1
+            fi
+            ;;
+        __cmg_err_not_repo)
+            if [ -z "$review" -o -z "$project" ]; then
+                echo >&2 "Not currently in any reviewable repository."
+            else
+                return 1
+            fi
+            ;;
+        __cmg_err_not_supported)
+            $FUNCNAME __cmg_err_no_arg $command $# && return
+            case $1 in
+                #TODO: filter more git commands that don't use refname
+                init|add|rm|mv|status|clone|remote|bisect|config|stash)
+                    echo >&2 "'$FUNCNAME $1' is not supported."
+                    ;;
+                *) return 1 ;;
+            esac
+            ;;
+    #TODO: other special cases?
+        *)
+            $FUNCNAME __cmg_err_not_supported $command && return 1
+            $FUNCNAME __cmg_err_no_arg $command $# help && return 1
+            $FUNCNAME __cmg_err_not_repo && return 1
+            local args="$@"
+            local change pre_args refs_arg post_args
+            case "$args" in
+                *--\ *)
+                    pre_args=${args%%-- *}
+                    post_args="-- ${args#*-- }"
+                    ;;
+                *) pre_args="$args" ;;
+            esac
+            args=($pre_args)
+            pre_args=
+            if [ ${#args[@]} -gt 0 ]; then
+                change=${args[${#args[@]}-1]}
+            fi
+            if [ ${#args[@]} -gt 1 ]; then
+                pre_args=${args[0]}
+                for ((i=1; i<${#args[@]}-1; i++)); do
+                    pre_args="$pre_args ${args[$i]}"
+                done
+            fi
+            while ((1)); do
+                case $change in
+                    ""|--)
+                        $FUNCNAME help $command
+                        return 1
+                        ;;
+                    *@*)
+                        if [ -z "$refs_arg" ]; then
+                            refs_arg="@${change#*@}"
+                            change=${change%%@*}
+                        fi
+                        ;;
+                    *~*)
+                        if [ -z "$refs_arg" ]; then
+                            refs_arg="~${change#*~}"
+                            change=${change%%~*}
+                        fi
+                        ;;
+                    *^*)
+                        if [ -z "$refs_arg" ]; then
+                            refs_arg="^${change#*^}"
+                            change=${change%%^*}
+                        fi
+                        ;;
+                    *:*)
+                        if [ -z "$refs_arg" ]; then
+                            refs_arg=":${change#*:}"
+                            change=${change%%:*}
+                        fi
+                        ;;
+                    *) break ;;
+                esac
+            done
+            $FUNCNAME fetch $change \
+                && git $command $pre_args FETCH_HEAD$refs_arg $post_args \
+                || return 1
+            ;;
+    esac
+}
+
+function cmrebase() {
+    local repo=$1
+    local refs=$2
+    local pwd="$(pwd)"
+    local dir="$(gettop)/$repo"
+
+    if [ -z $repo ] || [ -z $refs ]; then
+        echo "CyanogenMod Gerrit Rebase Usage: "
+        echo "      cmrebase <path to project> <patch IDs on Gerrit>"
+        echo "      The patch IDs appear on the Gerrit commands that are offered."
+        echo "      They consist on a series of numbers and slashes, after the text"
+        echo "      refs/changes. For example, the ID in the following command is 26/8126/2"
+        echo ""
+        echo "      git[...]ges_apps_Camera refs/changes/26/8126/2 && git cherry-pick FETCH_HEAD"
+        echo ""
+        return
+    fi
+
+    if [ ! -d $dir ]; then
+        echo "Directory $dir doesn't exist in tree."
+        return
+    fi
+    cd $dir
+    repo=$(cat .git/config  | grep git://github.com | awk '{ print $NF }' | sed s#git://github.com/##g)
+    echo "Starting branch..."
+    repo start tmprebase .
+    echo "Bringing it up to date..."
+    repo sync .
+    echo "Fetching change..."
+    git fetch "http://review.cyanogenmod.org/p/$repo" "refs/changes/$refs" && git cherry-pick FETCH_HEAD
+    if [ "$?" != "0" ]; then
+        echo "Error cherry-picking. Not uploading!"
+        return
+    fi
+    echo "Uploading..."
+    repo upload .
+    echo "Cleaning up..."
+    repo abandon tmprebase .
+    cd $pwd
+}
+
+function mka() {
+    local T=$(gettop)
+    if [ "$T" ]; then
+        case `uname -s` in
+            Darwin)
+                make -C $T -j `sysctl hw.ncpu|cut -d" " -f2` "$@"
+                ;;
+            *)
+                mk_timer schedtool -B -n 1 -e ionice -n 1 make -C $T -j$(cat /proc/cpuinfo | grep "^processor" | wc -l) "$@"
+                ;;
+        esac
+
+    else
+        echo "Couldn't locate the top of the tree.  Try setting TOP."
+    fi
+}
+
+function cmka() {
+    if [ ! -z "$1" ]; then
+        for i in "$@"; do
+            case $i in
+                bacon|otapackage|systemimage)
+                    mka installclean
+                    mka $i
+                    ;;
+                *)
+                    mka clean-$i
+                    mka $i
+                    ;;
+            esac
+        done
+    else
+        mka clean
+        mka
+    fi
+}
+
+function mms() {
+    local T=$(gettop)
+    if [ -z "$T" ]
+    then
+        echo "Couldn't locate the top of the tree.  Try setting TOP."
+        return 1
+    fi
+
+    case `uname -s` in
+        Darwin)
+            local NUM_CPUS=$(sysctl hw.ncpu|cut -d" " -f2)
+            ONE_SHOT_MAKEFILE="__none__" \
+                make -C $T -j $NUM_CPUS "$@"
+            ;;
+        *)
+            local NUM_CPUS=$(cat /proc/cpuinfo | grep "^processor" | wc -l)
+            ONE_SHOT_MAKEFILE="__none__" \
+                mk_timer schedtool -B -n 1 -e ionice -n 1 \
+                make -C $T -j $NUM_CPUS "$@"
+            ;;
+    esac
+}
+
+function repolastsync() {
+    RLSPATH="$ANDROID_BUILD_TOP/.repo/.repo_fetchtimes.json"
+    RLSLOCAL=$(date -d "$(stat -c %z $RLSPATH)" +"%e %b %Y, %T %Z")
+    RLSUTC=$(date -d "$(stat -c %z $RLSPATH)" -u +"%e %b %Y, %T %Z")
+    echo "Last repo sync: $RLSLOCAL / $RLSUTC"
+}
+
+function reposync() {
+    case `uname -s` in
+        Darwin)
+            repo sync -j 4 "$@"
+            ;;
+        *)
+            schedtool -B -n 1 -e ionice -n 1 `which repo` sync -j 4 "$@"
+            ;;
+    esac
+}
+
+function repodiff() {
+    if [ -z "$*" ]; then
+        echo "Usage: repodiff <ref-from> [[ref-to] [--numstat]]"
+        return
+    fi
+    diffopts=$* repo forall -c \
+      'echo "$REPO_PATH ($REPO_REMOTE)"; git diff ${diffopts} 2>/dev/null ;'
+}
+
+# Return success if adb is up and not in recovery
+function _adb_connected {
+    {
+        if [[ "$(adb get-state)" == device &&
+              "$(adb shell test -e /sbin/recovery; echo $?)" == 0 ]]
+        then
+            return 0
+        fi
+    } 2>/dev/null
+
+    return 1
+};
+
+# Credit for color strip sed: http://goo.gl/BoIcm
+function dopush()
+{
+    local func=$1
+    shift
+
+    adb start-server # Prevent unexpected starting server message from adb get-state in the next line
+    if ! _adb_connected; then
+        echo "No device is online. Waiting for one..."
+        echo "Please connect USB and/or enable USB debugging"
+        until _adb_connected; do
+            sleep 1
+        done
+        echo "Device Found."
+    fi
+
+    if (adb shell getprop ro.cm.device | grep -q "$CM_BUILD") || [ "$FORCE_PUSH" = "true" ];
+    then
+    # retrieve IP and PORT info if we're using a TCP connection
+    TCPIPPORT=$(adb devices | egrep '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+[^0-9]+' \
+        | head -1 | awk '{print $1}')
+    adb root &> /dev/null
+    sleep 0.3
+    if [ -n "$TCPIPPORT" ]
+    then
+        # adb root just killed our connection
+        # so reconnect...
+        adb connect "$TCPIPPORT"
+    fi
+    adb wait-for-device &> /dev/null
+    sleep 0.3
+    adb remount &> /dev/null
+
+    mkdir -p $OUT
+    ($func $*|tee $OUT/.log;return ${PIPESTATUS[0]})
+    ret=$?;
+    if [ $ret -ne 0 ]; then
+        rm -f $OUT/.log;return $ret
+    fi
+
+    # Install: <file>
+    if [ `uname` = "Linux" ]; then
+        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)"
+    else
+        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)"
+    fi
+
+    # Copy: <file>
+    if [ `uname` = "Linux" ]; then
+        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)"
+    else
+        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)"
+    fi
+
+    # If any files are going to /data, push an octal file permissions reader to device
+    if [ -n "$(echo $LOC | egrep '(^|\s)/data')" ]; then
+        CHKPERM="/data/local/tmp/chkfileperm.sh"
+(
+cat <<'EOF'
+#!/system/xbin/sh
+FILE=$@
+if [ -e $FILE ]; then
+    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
+fi
+EOF
+) > $OUT/.chkfileperm.sh
+        echo "Pushing file permissions checker to device"
+        adb push $OUT/.chkfileperm.sh $CHKPERM
+        adb shell chmod 755 $CHKPERM
+        rm -f $OUT/.chkfileperm.sh
+    fi
+
+    stop_n_start=false
+    for FILE in $(echo $LOC | tr " " "\n"); do
+        # Make sure file is in $OUT/system or $OUT/data
+        case $FILE in
+            $OUT/system/*|$OUT/data/*)
+                # Get target file name (i.e. /system/bin/adb)
+                TARGET=$(echo $FILE | sed "s#$OUT##")
+            ;;
+            *) continue ;;
+        esac
+
+        case $TARGET in
+            /data/*)
+                # fs_config only sets permissions and se labels for files pushed to /system
+                if [ -n "$CHKPERM" ]; then
+                    OLDPERM=$(adb shell $CHKPERM $TARGET)
+                    OLDPERM=$(echo $OLDPERM | tr -d '\r' | tr -d '\n')
+                    OLDOWN=$(adb shell ls -al $TARGET | awk '{print $2}')
+                    OLDGRP=$(adb shell ls -al $TARGET | awk '{print $3}')
+                fi
+                echo "Pushing: $TARGET"
+                adb push $FILE $TARGET
+                if [ -n "$OLDPERM" ]; then
+                    echo "Setting file permissions: $OLDPERM, $OLDOWN":"$OLDGRP"
+                    adb shell chown "$OLDOWN":"$OLDGRP" $TARGET
+                    adb shell chmod "$OLDPERM" $TARGET
+                else
+                    echo "$TARGET did not exist previously, you should set file permissions manually"
+                fi
+                adb shell restorecon "$TARGET"
+            ;;
+            /system/priv-app/SystemUI/SystemUI.apk|/system/framework/*)
+                # Only need to stop services once
+                if ! $stop_n_start; then
+                    adb shell stop
+                    stop_n_start=true
+                fi
+                echo "Pushing: $TARGET"
+                adb push $FILE $TARGET
+            ;;
+            *)
+                echo "Pushing: $TARGET"
+                adb push $FILE $TARGET
+            ;;
+        esac
+    done
+    if [ -n "$CHKPERM" ]; then
+        adb shell rm $CHKPERM
+    fi
+    if $stop_n_start; then
+        adb shell start
+    fi
+    rm -f $OUT/.log
+    return 0
+    else
+        echo "The connected device does not appear to be $CM_BUILD, run away!"
+    fi
+}
+
+alias mmp='dopush mm'
+alias mmmp='dopush mmm'
+alias mmap='dopush mma'
+alias mkap='dopush mka'
+alias cmkap='dopush cmka'
+
+function repopick() {
+    T=$(gettop)
+    $T/vendor/cm/build/tools/repopick.py $@
+}
+
+function fixup_common_out_dir() {
+    common_out_dir=$(get_build_var OUT_DIR)/target/common
+    target_device=$(get_build_var TARGET_DEVICE)
+    if [ ! -z $CM_FIXUP_COMMON_OUT ]; then
+        if [ -d ${common_out_dir} ] && [ ! -L ${common_out_dir} ]; then
+            mv ${common_out_dir} ${common_out_dir}-${target_device}
+            ln -s ${common_out_dir}-${target_device} ${common_out_dir}
+        else
+            [ -L ${common_out_dir} ] && rm ${common_out_dir}
+            mkdir -p ${common_out_dir}-${target_device}
+            ln -s ${common_out_dir}-${target_device} ${common_out_dir}
+        fi
+    else
+        [ -L ${common_out_dir} ] && rm ${common_out_dir}
+        mkdir -p ${common_out_dir}
+    fi
+}
diff --git a/build/target/product/security/cm-devkey.x509.pem b/build/target/product/security/cm-devkey.x509.pem
new file mode 100644
index 0000000..b7a6ae4
--- /dev/null
+++ b/build/target/product/security/cm-devkey.x509.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID1TCCAr2gAwIBAgIJANO67t8hIti6MA0GCSqGSIb3DQEBBQUAMIGAMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEX
+MBUGA1UECgwOQ3lhbm9nZW4sIEluYy4xGzAZBgNVBAsMElJlbGVhc2UgTWFuYWdl
+bWVudDEUMBIGA1UEAwwLRGV2ZWxvcG1lbnQwHhcNMTQwNDI4MjAyODM3WhcNNDEw
+OTEzMjAyODM3WjCBgDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24x
+EDAOBgNVBAcMB1NlYXR0bGUxFzAVBgNVBAoMDkN5YW5vZ2VuLCBJbmMuMRswGQYD
+VQQLDBJSZWxlYXNlIE1hbmFnZW1lbnQxFDASBgNVBAMMC0RldmVsb3BtZW50MIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz/V9RvYnr18fraPWNeQEZNeg
+Kc0A3QskImQyGY22EGBZ63KUxa6zAfAug0OYSjofVJRaTtdvBXjO/C71XZRh4wun
+xhOUAJt8zIJ0lRx8GMC0GHzePEnEVvoiu3zSAPHCNf5lmdhyhccMOtC18J+evPf4
+EVBb3cis+F1m6ZoZKPgSFBR5A9CV5Tai8iiZluGGg15Wt12Rp2vmbmQxiOJZxBs4
+Ps40XR5gjO1q4R3HiGnFyql9qeecwaTUWXAd76lhNiLUr7K8IRs+96i+t5vSKajB
+M8O99BtYyBtf8ItMnHSZJxtsMw+TFXNLmMtaQarpsjp0LLGuHb/vsrjgBPvzsQID
+AQABo1AwTjAdBgNVHQ4EFgQUTpNgXBqV7j+33bi8B80YLQq6EL8wHwYDVR0jBBgw
+FoAUTpNgXBqV7j+33bi8B80YLQq6EL8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B
+AQUFAAOCAQEAVlVBNksK+1C3J8uQ9kVemYMozfbboV9c4PLbtVzNSO8vwZ3X5E4T
+2zfQPcFsfSMIa51a1tETBcDA6k+72xHZ+xEQJQNrX+o1F1RIIrXp0OKAz/k5cXyk
+OS0+nd0EXP/A1EW0m8N/X6E9wpRkIhfqtEsqeCf8GH7O9Ua2qHZ9zkTBpbAVH0oe
+ZWorHBdo3GdMJ5vcjFqnDdRs8F0BnZmjS+NrgXRLhLb6ZARS/bkUQyr5TX82dgG6
+vzvKsdKyX34gsKAsjxwLWo7XXgehFfjY+SGjjilJtardr+y/KlHNEw9s9aLe+Xny
+Qoa9j9Ut6/KwRaC6lSEQ7HZk6SdzFsdugA==
+-----END CERTIFICATE-----
diff --git a/build/target/product/security/cm.x509.pem b/build/target/product/security/cm.x509.pem
new file mode 100644
index 0000000..5ff19db
--- /dev/null
+++ b/build/target/product/security/cm.x509.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDZDCCAkygAwIBAgIEUfbexjANBgkqhkiG9w0BAQUFADB0MQswCQYDVQQGEwJV
+UzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxFjAUBgNVBAoTDUN5YW5v
+Z2VuIEluYy4xFjAUBgNVBAsTDUN5YW5vZ2VuIEluYy4xFjAUBgNVBAMTDUN5YW5v
+Z2VuIEluYy4wHhcNMTMwNzI5MjEyOTQyWhcNNDAxMjE0MjEyOTQyWjB0MQswCQYD
+VQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxFjAUBgNVBAoT
+DUN5YW5vZ2VuIEluYy4xFjAUBgNVBAsTDUN5YW5vZ2VuIEluYy4xFjAUBgNVBAMT
+DUN5YW5vZ2VuIEluYy4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCP
++K2NPqdZ6UmexXQ8tsc2TkLXYhiuEsifO66qlpwsTTw1522HcbKPVoPRr/JBXqOv
+E3K0HuZ/IsYYGsP/wJWWvpaWs+5xC+YkLkittK2uUzTqndpLFiDRAeICKpvDJI57
+Z0DkzVYXBPn+yw+x8ttjT/vWcJ3PEVYuew8MYPUOgKpdZlQtUBeoEBDSL8JPGViq
+e6jWOlSAWekhlgb+wb9RoXhu/v2HYzp89GG0sIrAgj7vZCior5XuFmm8eWhqUhTp
+TUBv/nNI/ORYt3G8IQyI2pJN1GNPAAv1uA5i4y/deX1x4GCWyN9feiD9fOj2oc3z
+Hwf5Frs9BjOb9XMXecbNAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAGudhFe9VnES
+fWynTYO4kWNlMC++yB6qD3pHW6HtBiaANj9wxrLCTFzf+boHNPeZ8HDkW01zAaQK
+fd9/fnGmHf4q/QvxrvGbnb3Fqhw+2hknbbMUoAa+Qp+2ouf9oJaNRquZ+rHEHX8g
+Rx8wGyvjaWYfQrwyZRgXj/Jrc/NXxQCmSJeexHVNXgQD6aOLHJYrJ+s+U/hwVNiM
+5L+psOh89itwt8DGGSLW16HjQKmPPbWbqxgnfRbOlxWrLDq3agcrskYpDP2aGGBA
+5STq/bvh9yZkrNYvMGzrXDhcJ44QRS8e1Jw/ZtfFvJD192e7KKVdy7CJWmOckCNK
+gl0KCQ3MBx4=
+-----END CERTIFICATE-----
diff --git a/build/tasks/dt_image.mk b/build/tasks/dt_image.mk
new file mode 100644
index 0000000..0f84946
--- /dev/null
+++ b/build/tasks/dt_image.mk
@@ -0,0 +1,53 @@
+#----------------------------------------------------------------------
+# Generate device tree image (dt.img)
+#----------------------------------------------------------------------
+ifeq ($(strip $(BOARD_CUSTOM_BOOTIMG_MK)),)
+ifeq ($(strip $(BOARD_KERNEL_SEPARATED_DT)),true)
+ifneq ($(strip $(BOARD_KERNEL_PREBUILT_DT)),true)
+ifeq ($(strip $(BUILD_TINY_ANDROID)),true)
+include device/qcom/common/dtbtool/Android.mk
+endif
+
+ifeq ($(strip $(TARGET_CUSTOM_DTBTOOL)),)
+DTBTOOL_NAME := dtbToolCM
+else
+DTBTOOL_NAME := $(TARGET_CUSTOM_DTBTOOL)
+endif
+
+DTBTOOL := $(HOST_OUT_EXECUTABLES)/$(DTBTOOL_NAME)$(HOST_EXECUTABLE_SUFFIX)
+
+INSTALLED_DTIMAGE_TARGET := $(PRODUCT_OUT)/dt.img
+
+ifeq ($(strip $(TARGET_CUSTOM_DTBTOOL)),)
+# dtbToolCM will search subdirectories
+possible_dtb_dirs = $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/
+else
+# Most specific paths must come first in possible_dtb_dirs
+possible_dtb_dirs = $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/dts/ $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/
+endif
+
+define build-dtimage-target
+    $(call pretty,"Target dt image: $@")
+    $(hide) for dir in $(possible_dtb_dirs); do \
+        if [ -d "$$dir" ]; then \
+            dtb_dir="$$dir"; \
+            break; \
+        fi; \
+    done; \
+    $(DTBTOOL) $(BOARD_DTBTOOL_ARGS) -o $@ -s $(BOARD_KERNEL_PAGESIZE) -p $(KERNEL_OUT)/scripts/dtc/ "$$dtb_dir";
+    $(hide) chmod a+r $@
+endef
+
+$(INSTALLED_DTIMAGE_TARGET): $(DTBTOOL) $(INSTALLED_KERNEL_TARGET)
+	$(build-dtimage-target)
+	@echo "Made DT image: $@"
+
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_DTIMAGE_TARGET)
+ALL_MODULES.$(LOCAL_MODULE).INSTALLED += $(INSTALLED_DTIMAGE_TARGET)
+
+.PHONY: dtimage
+dtimage: $(INSTALLED_DTIMAGE_TARGET)
+
+endif
+endif
+endif
diff --git a/build/tasks/kernel.mk b/build/tasks/kernel.mk
new file mode 100644
index 0000000..527fb54
--- /dev/null
+++ b/build/tasks/kernel.mk
@@ -0,0 +1,373 @@
+# Copyright (C) 2012 The CyanogenMod Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# Android makefile to build kernel as a part of Android Build
+#
+# Configuration
+# =============
+#
+# These config vars are usually set in BoardConfig.mk:
+#
+#   TARGET_KERNEL_SOURCE               = Kernel source dir, optional, defaults
+#                                        to kernel/$(TARGET_DEVICE_DIR)
+#   TARGET_KERNEL_CONFIG               = Kernel defconfig
+#   TARGET_KERNEL_VARIANT_CONFIG       = Variant defconfig, optional
+#   TARGET_KERNEL_SELINUX_CONFIG       = SELinux defconfig, optional
+#   TARGET_KERNEL_ADDITIONAL_CONFIG    = Additional defconfig, optional
+#   TARGET_KERNEL_ARCH                 = Kernel Arch
+#   TARGET_KERNEL_HEADER_ARCH          = Optional Arch for kernel headers if
+#                                          different from TARGET_KERNEL_ARCH
+#   TARGET_USES_UNCOMPRESSED_KERNEL    = 'true' if Kernel is uncompressed,
+#                                          optional, defaults to false
+#   TARGET_KERNEL_CROSS_COMPILE_PREFIX = Compiler prefix (e.g. arm-eabi-)
+#                                          defaults to arm-linux-androideabi- for arm
+#                                                      aarch64-linux-android- for arm64
+#                                                      x86_64-linux-android- for x86
+#
+#   BOARD_KERNEL_IMAGE_NAME            = Built image name, optional,
+#                                          defaults to Image.gz on arm64
+#                                          defaults to Image if TARGET_USES_UNCOMPRESSED_KERNEL
+#                                          defaults to zImage otherwise
+#
+#   KERNEL_TOOLCHAIN_PREFIX            = Overrides TARGET_KERNEL_CROSS_COMPILE_PREFIX,
+#                                          Set this var in shell to override
+#                                          toolchain specified in BoardConfig.mk
+#   KERNEL_TOOLCHAIN                   = Path to toolchain, if unset, assumes
+#                                          TARGET_KERNEL_CROSS_COMPILE_PREFIX
+#                                          is in PATH
+#   USE_CCACHE                         = Enable ccache (global Android flag)
+#
+#   NEED_KERNEL_MODULE_ROOT            = Optional, if true, install kernel
+#                                          modules in root instead of system
+
+
+TARGET_AUTO_KDIR := $(shell echo $(TARGET_DEVICE_DIR) | sed -e 's/^device/kernel/g')
+
+## Externally influenced variables
+# kernel location - optional, defaults to kernel/<vendor>/<device>
+TARGET_KERNEL_SOURCE ?= $(TARGET_AUTO_KDIR)
+KERNEL_SRC := $(TARGET_KERNEL_SOURCE)
+# kernel configuration - mandatory
+KERNEL_DEFCONFIG := $(TARGET_KERNEL_CONFIG)
+VARIANT_DEFCONFIG := $(TARGET_KERNEL_VARIANT_CONFIG)
+SELINUX_DEFCONFIG := $(TARGET_KERNEL_SELINUX_CONFIG)
+
+## Internal variables
+KERNEL_OUT := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ
+KERNEL_CONFIG := $(KERNEL_OUT)/.config
+KERNEL_OUT_STAMP := $(KERNEL_OUT)/.mkdir_stamp
+
+TARGET_KERNEL_ARCH := $(strip $(TARGET_KERNEL_ARCH))
+ifeq ($(TARGET_KERNEL_ARCH),)
+KERNEL_ARCH := $(TARGET_ARCH)
+else
+KERNEL_ARCH := $(TARGET_KERNEL_ARCH)
+endif
+
+ifeq ($(KERNEL_ARCH),x86_64)
+KERNEL_DEFCONFIG_ARCH := x86
+else
+KERNEL_DEFCONFIG_ARCH := $(KERNEL_ARCH)
+endif
+KERNEL_DEFCONFIG_SRC := $(KERNEL_SRC)/arch/$(KERNEL_DEFCONFIG_ARCH)/configs/$(KERNEL_DEFCONFIG)
+
+TARGET_KERNEL_HEADER_ARCH := $(strip $(TARGET_KERNEL_HEADER_ARCH))
+ifeq ($(TARGET_KERNEL_HEADER_ARCH),)
+KERNEL_HEADER_ARCH := $(KERNEL_ARCH)
+else
+KERNEL_HEADER_ARCH := $(TARGET_KERNEL_HEADER_ARCH)
+endif
+
+KERNEL_HEADER_DEFCONFIG := $(strip $(KERNEL_HEADER_DEFCONFIG))
+ifeq ($(KERNEL_HEADER_DEFCONFIG),)
+KERNEL_HEADER_DEFCONFIG := $(KERNEL_DEFCONFIG)
+endif
+
+
+ifneq ($(BOARD_KERNEL_IMAGE_NAME),)
+  TARGET_PREBUILT_INT_KERNEL_TYPE := $(BOARD_KERNEL_IMAGE_NAME)
+else
+  ifeq ($(TARGET_USES_UNCOMPRESSED_KERNEL),true)
+    TARGET_PREBUILT_INT_KERNEL_TYPE := Image
+  else
+    ifeq ($(KERNEL_ARCH),arm64)
+      TARGET_PREBUILT_INT_KERNEL_TYPE := Image.gz
+    else
+      TARGET_PREBUILT_INT_KERNEL_TYPE := zImage
+    endif
+  endif
+endif
+
+TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/$(TARGET_PREBUILT_INT_KERNEL_TYPE)
+
+# Clear this first to prevent accidental poisoning from env
+MAKE_FLAGS :=
+
+ifeq ($(KERNEL_ARCH),arm64)
+  # Avoid "unsupported RELA relocation: 311" errors (R_AARCH64_ADR_GOT_PAGE)
+  MAKE_FLAGS += CFLAGS_MODULE="-fno-pic"
+  ifeq ($(TARGET_ARCH),arm)
+    KERNEL_CONFIG_OVERRIDE := CONFIG_ANDROID_BINDER_IPC_32BIT=y
+  endif
+endif
+
+ifneq ($(TARGET_KERNEL_ADDITIONAL_CONFIG),)
+KERNEL_ADDITIONAL_CONFIG := $(TARGET_KERNEL_ADDITIONAL_CONFIG)
+KERNEL_ADDITIONAL_CONFIG_SRC := $(KERNEL_SRC)/arch/$(KERNEL_ARCH)/configs/$(KERNEL_ADDITIONAL_CONFIG)
+    ifeq ("$(wildcard $(KERNEL_ADDITIONAL_CONFIG_SRC))","")
+        $(warning TARGET_KERNEL_ADDITIONAL_CONFIG '$(TARGET_KERNEL_ADDITIONAL_CONFIG)' doesn't exist)
+        KERNEL_ADDITIONAL_CONFIG_SRC := /dev/null
+    endif
+else
+    KERNEL_ADDITIONAL_CONFIG_SRC := /dev/null
+endif
+
+## Do be discontinued in a future version. Notify builder about target
+## kernel format requirement
+ifeq ($(BOARD_KERNEL_IMAGE_NAME),)
+ifeq ($(BOARD_USES_UBOOT),true)
+        $(error "Please set BOARD_KERNEL_IMAGE_NAME to uImage")
+else ifeq ($(BOARD_USES_UNCOMPRESSED_BOOT),true)
+        $(error "Please set BOARD_KERNEL_IMAGE_NAME to Image")
+endif
+endif
+
+ifeq "$(wildcard $(KERNEL_SRC) )" ""
+    ifneq ($(TARGET_PREBUILT_KERNEL),)
+        HAS_PREBUILT_KERNEL := true
+        NEEDS_KERNEL_COPY := true
+    else
+        $(foreach cf,$(PRODUCT_COPY_FILES), \
+            $(eval _src := $(call word-colon,1,$(cf))) \
+            $(eval _dest := $(call word-colon,2,$(cf))) \
+            $(ifeq kernel,$(_dest), \
+                $(eval HAS_PREBUILT_KERNEL := true)))
+    endif
+
+    ifneq ($(HAS_PREBUILT_KERNEL),)
+        $(warning ***************************************************************)
+        $(warning * Using prebuilt kernel binary instead of source              *)
+        $(warning * THIS IS DEPRECATED, AND WILL BE DISCONTINUED                *)
+        $(warning * Please configure your device to download the kernel         *)
+        $(warning * source repository to $(KERNEL_SRC))
+        $(warning * See http://wiki.cyanogenmod.org/w/Doc:_integrated_kernel_building)
+        $(warning * for more information                                        *)
+        $(warning ***************************************************************)
+        FULL_KERNEL_BUILD := false
+        KERNEL_BIN := $(TARGET_PREBUILT_KERNEL)
+    else
+        $(warning ***************************************************************)
+        $(warning *                                                             *)
+        $(warning * No kernel source found, and no fallback prebuilt defined.   *)
+        $(warning * Please make sure your device is properly configured to      *)
+        $(warning * download the kernel repository to $(KERNEL_SRC))
+        $(warning * and add the TARGET_KERNEL_CONFIG variable to BoardConfig.mk *)
+        $(warning *                                                             *)
+        $(warning * As an alternative, define the TARGET_PREBUILT_KERNEL        *)
+        $(warning * variable with the path to the prebuilt binary kernel image  *)
+        $(warning * in your BoardConfig.mk file                                 *)
+        $(warning *                                                             *)
+        $(warning ***************************************************************)
+        $(error "NO KERNEL")
+    endif
+else
+    NEEDS_KERNEL_COPY := true
+    ifeq ($(TARGET_KERNEL_CONFIG),)
+        $(warning **********************************************************)
+        $(warning * Kernel source found, but no configuration was defined  *)
+        $(warning * Please add the TARGET_KERNEL_CONFIG variable to your   *)
+        $(warning * BoardConfig.mk file                                    *)
+        $(warning **********************************************************)
+        # $(error "NO KERNEL CONFIG")
+    else
+        #$(info Kernel source found, building it)
+        FULL_KERNEL_BUILD := true
+        KERNEL_BIN := $(TARGET_PREBUILT_INT_KERNEL)
+    endif
+endif
+
+ifeq ($(FULL_KERNEL_BUILD),true)
+
+KERNEL_HEADERS_INSTALL := $(KERNEL_OUT)/usr
+KERNEL_HEADERS_INSTALL_STAMP := $(KERNEL_OUT)/.headers_install_stamp
+
+ifeq ($(NEED_KERNEL_MODULE_ROOT),true)
+KERNEL_MODULES_INSTALL := root
+KERNEL_MODULES_OUT := $(TARGET_ROOT_OUT)/lib/modules
+else
+KERNEL_MODULES_INSTALL := system
+KERNEL_MODULES_OUT := $(TARGET_OUT)/lib/modules
+endif
+
+TARGET_KERNEL_CROSS_COMPILE_PREFIX := $(strip $(TARGET_KERNEL_CROSS_COMPILE_PREFIX))
+ifneq ($(TARGET_KERNEL_CROSS_COMPILE_PREFIX),)
+KERNEL_TOOLCHAIN_PREFIX ?= $(TARGET_KERNEL_CROSS_COMPILE_PREFIX)
+else ifeq ($(TARGET_ARCH),arm64)
+KERNEL_TOOLCHAIN_PREFIX ?= aarch64-linux-android-
+else ifeq ($(TARGET_ARCH),arm)
+KERNEL_TOOLCHAIN_PREFIX ?= arm-linux-androideabi-
+else ifeq ($(TARGET_ARCH),x86)
+KERNEL_TOOLCHAIN_PREFIX ?= x86_64-linux-android-
+endif
+
+ifeq ($(KERNEL_TOOLCHAIN),)
+KERNEL_TOOLCHAIN_PATH := $(KERNEL_TOOLCHAIN_PREFIX)
+else
+ifneq ($(KERNEL_TOOLCHAIN_PREFIX),)
+KERNEL_TOOLCHAIN_PATH := $(KERNEL_TOOLCHAIN)/$(KERNEL_TOOLCHAIN_PREFIX)
+endif
+endif
+
+ifneq ($(USE_CCACHE),)
+    ccache := $(ANDROID_BUILD_TOP)/prebuilts/misc/$(HOST_PREBUILT_TAG)/ccache/ccache
+    # Check that the executable is here.
+    ccache := $(strip $(wildcard $(ccache)))
+endif
+
+KERNEL_CROSS_COMPILE := CROSS_COMPILE="$(ccache) $(KERNEL_TOOLCHAIN_PATH)"
+ccache =
+
+define mv-modules
+    mdpath=`find $(KERNEL_MODULES_OUT) -type f -name modules.order`;\
+    if [ "$$mdpath" != "" ];then\
+        mpath=`dirname $$mdpath`;\
+        ko=`find $$mpath/kernel -type f -name *.ko`;\
+        for i in $$ko; do $(KERNEL_TOOLCHAIN_PATH)strip --strip-unneeded $$i;\
+        mv $$i $(KERNEL_MODULES_OUT)/; done;\
+    fi
+endef
+
+define clean-module-folder
+    mdpath=`find $(KERNEL_MODULES_OUT) -type f -name modules.order`;\
+    if [ "$$mdpath" != "" ];then\
+        mpath=`dirname $$mdpath`; rm -rf $$mpath;\
+    fi
+endef
+
+ifeq ($(HOST_OS),darwin)
+  MAKE_FLAGS += C_INCLUDE_PATH=$(ANDROID_BUILD_TOP)/external/elfutils/libelf/
+endif
+
+ifeq ($(TARGET_KERNEL_MODULES),)
+    TARGET_KERNEL_MODULES := no-external-modules
+endif
+
+$(KERNEL_OUT_STAMP):
+	$(hide) mkdir -p $(KERNEL_OUT)
+	$(hide) rm -rf $(KERNEL_MODULES_OUT)
+	$(hide) mkdir -p $(KERNEL_MODULES_OUT)
+	$(hide) touch $@
+
+KERNEL_ADDITIONAL_CONFIG_OUT := $(KERNEL_OUT)/.additional_config
+
+.PHONY: force_additional_config
+$(KERNEL_ADDITIONAL_CONFIG_OUT): force_additional_config
+	$(hide) cmp -s $(KERNEL_ADDITIONAL_CONFIG_SRC) $@ || cp $(KERNEL_ADDITIONAL_CONFIG_SRC) $@;
+
+$(KERNEL_CONFIG): $(KERNEL_OUT_STAMP) $(KERNEL_DEFCONFIG_SRC) $(KERNEL_ADDITIONAL_CONFIG_OUT)
+	@echo "Building Kernel Config"
+	$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) VARIANT_DEFCONFIG=$(VARIANT_DEFCONFIG) SELINUX_DEFCONFIG=$(SELINUX_DEFCONFIG) $(KERNEL_DEFCONFIG)
+	$(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
+			echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
+			echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \
+			$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) oldconfig; fi
+	$(hide) if [ ! -z "$(KERNEL_ADDITIONAL_CONFIG)" ]; then \
+			echo "Using additional config '$(KERNEL_ADDITIONAL_CONFIG)'"; \
+			$(KERNEL_SRC)/scripts/kconfig/merge_config.sh -m -O $(KERNEL_OUT) $(KERNEL_OUT)/.config $(KERNEL_SRC)/arch/$(KERNEL_ARCH)/configs/$(KERNEL_ADDITIONAL_CONFIG); \
+			$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) KCONFIG_ALLCONFIG=$(KERNEL_OUT)/.config alldefconfig; fi
+
+TARGET_KERNEL_BINARIES: $(KERNEL_OUT_STAMP) $(KERNEL_CONFIG) $(KERNEL_HEADERS_INSTALL_STAMP)
+	@echo "Building Kernel"
+	$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(TARGET_PREBUILT_INT_KERNEL_TYPE)
+	$(hide) if grep -q 'CONFIG_OF=y' $(KERNEL_CONFIG) ; \
+			then \
+				echo "Building DTBs" ; \
+				$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) dtbs ; \
+			else \
+				echo "DTBs not enabled" ; \
+			fi ;
+	$(hide) if grep -q 'CONFIG_MODULES=y' $(KERNEL_CONFIG) ; \
+			then \
+				echo "Building Kernel Modules" ; \
+				$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) modules && \
+				$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) INSTALL_MOD_PATH=../../$(KERNEL_MODULES_INSTALL) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) modules_install && \
+				$(mv-modules) && \
+				$(clean-module-folder) ; \
+			else \
+				echo "Kernel Modules not enabled" ; \
+			fi ;
+
+
+$(TARGET_KERNEL_MODULES): TARGET_KERNEL_BINARIES
+
+$(TARGET_PREBUILT_INT_KERNEL): $(TARGET_KERNEL_MODULES)
+	$(mv-modules)
+	$(clean-module-folder)
+
+$(KERNEL_HEADERS_INSTALL_STAMP): $(KERNEL_OUT_STAMP) $(KERNEL_CONFIG)
+	@echo "Building Kernel Headers"
+	$(hide) if [ ! -z "$(KERNEL_HEADER_DEFCONFIG)" ]; then \
+			rm -f ../$(KERNEL_CONFIG); \
+			$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_HEADER_ARCH) $(KERNEL_CROSS_COMPILE) VARIANT_DEFCONFIG=$(VARIANT_DEFCONFIG) SELINUX_DEFCONFIG=$(SELINUX_DEFCONFIG) $(KERNEL_HEADER_DEFCONFIG); \
+			$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_HEADER_ARCH) $(KERNEL_CROSS_COMPILE) headers_install; fi
+	$(hide) if [ "$(KERNEL_HEADER_DEFCONFIG)" != "$(KERNEL_DEFCONFIG)" ]; then \
+			echo "Used a different defconfig for header generation"; \
+			rm -f ../$(KERNEL_CONFIG); \
+			$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) VARIANT_DEFCONFIG=$(VARIANT_DEFCONFIG) SELINUX_DEFCONFIG=$(SELINUX_DEFCONFIG) $(KERNEL_DEFCONFIG); fi
+	$(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
+			echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
+			echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \
+			$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) oldconfig; fi
+	$(hide) if [ ! -z "$(KERNEL_ADDITIONAL_CONFIG)" ]; then \
+			echo "Using additional config '$(KERNEL_ADDITIONAL_CONFIG)'"; \
+			$(KERNEL_SRC)/scripts/kconfig/merge_config.sh -m -O $(KERNEL_OUT) $(KERNEL_OUT)/.config $(KERNEL_SRC)/arch/$(KERNEL_ARCH)/configs/$(KERNEL_ADDITIONAL_CONFIG); \
+			$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) KCONFIG_ALLCONFIG=$(KERNEL_OUT)/.config alldefconfig; fi
+	$(hide) touch $@
+
+# provide this rule because there are dependencies on this throughout the repo
+$(KERNEL_HEADERS_INSTALL): $(KERNEL_HEADERS_INSTALL_STAMP)
+
+kerneltags: $(KERNEL_OUT_STAMP) $(KERNEL_CONFIG)
+	$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) tags
+
+kernelconfig:  KERNELCONFIG_MODE := menuconfig
+kernelxconfig: KERNELCONFIG_MODE := xconfig
+kernelxconfig kernelconfig: $(KERNEL_OUT_STAMP)
+	$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_DEFCONFIG)
+	env KCONFIG_NOTIMESTAMP=true \
+		 $(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNELCONFIG_MODE)
+	env KCONFIG_NOTIMESTAMP=true \
+		 $(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) savedefconfig
+	cp $(KERNEL_OUT)/defconfig $(KERNEL_DEFCONFIG_SRC)
+
+alldefconfig: $(KERNEL_OUT_STAMP)
+	env KCONFIG_NOTIMESTAMP=true \
+		 $(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) alldefconfig
+
+endif # FULL_KERNEL_BUILD
+
+## Install it
+
+ifeq ($(NEEDS_KERNEL_COPY),true)
+file := $(INSTALLED_KERNEL_TARGET)
+ALL_PREBUILT += $(file)
+$(file) : $(KERNEL_BIN) | $(ACP)
+	$(transform-prebuilt-to-target)
+
+ALL_PREBUILT += $(INSTALLED_KERNEL_TARGET)
+endif
+
+.PHONY: kernel
+kernel: $(INSTALLED_KERNEL_TARGET)
diff --git a/build/tools/repopick.py b/build/tools/repopick.py
new file mode 100755
index 0000000..5b0e065
--- /dev/null
+++ b/build/tools/repopick.py
@@ -0,0 +1,407 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2013-15 The CyanogenMod Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# Run repopick.py -h for a description of this utility.
+#
+
+from __future__ import print_function
+
+import sys
+import json
+import os
+import subprocess
+import re
+import argparse
+import textwrap
+from xml.etree import ElementTree
+
+try:
+    # For python3
+    import urllib.error
+    import urllib.request
+except ImportError:
+    # For python2
+    import imp
+    import urllib2
+    urllib = imp.new_module('urllib')
+    urllib.error = urllib2
+    urllib.request = urllib2
+
+
+# Verifies whether pathA is a subdirectory (or the same) as pathB
+def is_subdir(a, b):
+    a = os.path.realpath(a) + '/'
+    b = os.path.realpath(b) + '/'
+    return b == a[:len(b)]
+
+
+def fetch_query_via_ssh(remote_url, query):
+    """Given a remote_url and a query, return the list of changes that fit it
+       This function is slightly messy - the ssh api does not return data in the same structure as the HTTP REST API
+       We have to get the data, then transform it to match what we're expecting from the HTTP RESET API"""
+    if remote_url.count(':') == 2:
+        (uri, userhost, port) = remote_url.split(':')
+        userhost = userhost[2:]
+    elif remote_url.count(':') == 1:
+        (uri, userhost) = remote_url.split(':')
+        userhost = userhost[2:]
+        port = 29418
+    else:
+        raise Exception('Malformed URI: Expecting ssh://[user@]host[:port]')
+
+
+    out = subprocess.check_output(['ssh', '-x', '-p{0}'.format(port), userhost, 'gerrit', 'query', '--format=JSON --patch-sets --current-patch-set', query])
+    if not hasattr(out, 'encode'):
+        out = out.decode()
+    reviews = []
+    for line in out.split('\n'):
+        try:
+            data = json.loads(line)
+            # make our data look like the http rest api data
+            review = {
+                'branch': data['branch'],
+                'change_id': data['id'],
+                'current_revision': data['currentPatchSet']['revision'],
+                'number': int(data['number']),
+                'revisions': {patch_set['revision']: {
+                    'number': int(patch_set['number']),
+                    'fetch': {
+                        'ssh': {
+                            'ref': patch_set['ref'],
+                            'url': 'ssh://{0}:{1}/{2}'.format(userhost, port, data['project'])
+                        }
+                    }
+                } for patch_set in data['patchSets']},
+                'subject': data['subject'],
+                'project': data['project'],
+                'status': data['status']
+            }
+            reviews.append(review)
+        except:
+            pass
+    args.quiet or print('Found {0} reviews'.format(len(reviews)))
+    return reviews
+
+
+def fetch_query_via_http(remote_url, query):
+
+    """Given a query, fetch the change numbers via http"""
+    url = '{0}/changes/?q={1}&o=CURRENT_REVISION&o=ALL_REVISIONS'.format(remote_url, query)
+    data = urllib.request.urlopen(url).read().decode('utf-8')
+    reviews = json.loads(data[5:])
+
+    for review in reviews:
+        review['number'] = review.pop('_number')
+
+    return reviews
+
+
+def fetch_query(remote_url, query):
+    """Wrapper for fetch_query_via_proto functions"""
+    if remote_url[0:3] == 'ssh':
+        return fetch_query_via_ssh(remote_url, query)
+    elif remote_url[0:4] == 'http':
+        return fetch_query_via_http(remote_url, query.replace(' ', '+'))
+    else:
+        raise Exception('Gerrit URL should be in the form http[s]://hostname/ or ssh://[user@]host[:port]')
+
+if __name__ == '__main__':
+    # Default to CyanogenMod Gerrit
+    default_gerrit = 'http://review.cyanogenmod.org'
+
+    parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description=textwrap.dedent('''\
+        repopick.py is a utility to simplify the process of cherry picking
+        patches from CyanogenMod's Gerrit instance (or any gerrit instance of your choosing)
+
+        Given a list of change numbers, repopick will cd into the project path
+        and cherry pick the latest patch available.
+
+        With the --start-branch argument, the user can specify that a branch
+        should be created before cherry picking. This is useful for
+        cherry-picking many patches into a common branch which can be easily
+        abandoned later (good for testing other's changes.)
+
+        The --abandon-first argument, when used in conjunction with the
+        --start-branch option, will cause repopick to abandon the specified
+        branch in all repos first before performing any cherry picks.'''))
+    parser.add_argument('change_number', nargs='*', help='change number to cherry pick.  Use {change number}/{patchset number} to get a specific revision.')
+    parser.add_argument('-i', '--ignore-missing', action='store_true', help='do not error out if a patch applies to a missing directory')
+    parser.add_argument('-s', '--start-branch', nargs=1, help='start the specified branch before cherry picking')
+    parser.add_argument('-a', '--abandon-first', action='store_true', help='before cherry picking, abandon the branch specified in --start-branch')
+    parser.add_argument('-b', '--auto-branch', action='store_true', help='shortcut to "--start-branch auto --abandon-first --ignore-missing"')
+    parser.add_argument('-q', '--quiet', action='store_true', help='print as little as possible')
+    parser.add_argument('-v', '--verbose', action='store_true', help='print extra information to aid in debug')
+    parser.add_argument('-f', '--force', action='store_true', help='force cherry pick even if change is closed')
+    parser.add_argument('-p', '--pull', action='store_true', help='execute pull instead of cherry-pick')
+    parser.add_argument('-P', '--path', help='use the specified path for the change')
+    parser.add_argument('-t', '--topic', help='pick all commits from a specified topic')
+    parser.add_argument('-Q', '--query', help='pick all commits using the specified query')
+    parser.add_argument('-g', '--gerrit', default=default_gerrit, help='Gerrit Instance to use. Form proto://[user@]host[:port]')
+    parser.add_argument('-e', '--exclude', nargs=1, help='exclude a list of commit numbers separated by a ,')
+    args = parser.parse_args()
+    if not args.start_branch and args.abandon_first:
+        parser.error('if --abandon-first is set, you must also give the branch name with --start-branch')
+    if args.auto_branch:
+        args.abandon_first = True
+        args.ignore_missing = True
+        if not args.start_branch:
+            args.start_branch = ['auto']
+    if args.quiet and args.verbose:
+        parser.error('--quiet and --verbose cannot be specified together')
+
+    if (1 << bool(args.change_number) << bool(args.topic) << bool(args.query)) != 2:
+        parser.error('One (and only one) of change_number, topic, and query are allowed')
+
+    # Change current directory to the top of the tree
+    if 'ANDROID_BUILD_TOP' in os.environ:
+        top = os.environ['ANDROID_BUILD_TOP']
+
+        if not is_subdir(os.getcwd(), top):
+            sys.stderr.write('ERROR: You must run this tool from within $ANDROID_BUILD_TOP!\n')
+            sys.exit(1)
+        os.chdir(os.environ['ANDROID_BUILD_TOP'])
+
+    # Sanity check that we are being run from the top level of the tree
+    if not os.path.isdir('.repo'):
+        sys.stderr.write('ERROR: No .repo directory found. Please run this from the top of your tree.\n')
+        sys.exit(1)
+
+    # If --abandon-first is given, abandon the branch before starting
+    if args.abandon_first:
+        # Determine if the branch already exists; skip the abandon if it does not
+        plist = subprocess.check_output(['repo', 'info'])
+        if not hasattr(plist, 'encode'):
+            plist = plist.decode()
+        needs_abandon = False
+        for pline in plist.splitlines():
+            matchObj = re.match(r'Local Branches.*\[(.*)\]', pline)
+            if matchObj:
+                local_branches = re.split('\s*,\s*', matchObj.group(1))
+                if any(args.start_branch[0] in s for s in local_branches):
+                    needs_abandon = True
+
+        if needs_abandon:
+            # Perform the abandon only if the branch already exists
+            if not args.quiet:
+                print('Abandoning branch: %s' % args.start_branch[0])
+            subprocess.check_output(['repo', 'abandon', args.start_branch[0]])
+            if not args.quiet:
+                print('')
+
+    # Get the master manifest from repo
+    #   - convert project name and revision to a path
+    project_name_to_data = {}
+    manifest = subprocess.check_output(['repo', 'manifest'])
+    xml_root = ElementTree.fromstring(manifest)
+    projects = xml_root.findall('project')
+    remotes = xml_root.findall('remote')
+    default_revision = xml_root.findall('default')[0].get('revision')
+
+    #dump project data into the a list of dicts with the following data:
+    #{project: {path, revision}}
+
+    for project in projects:
+        name = project.get('name')
+        path = project.get('path')
+        revision = project.get('revision')
+        if revision is None:
+            for remote in remotes:
+                if remote.get('name') == project.get('remote'):
+                    revision = remote.get('revision')
+            if revision is None:
+            revision = default_revision
+
+        if not name in project_name_to_data:
+            project_name_to_data[name] = {}
+        revision = revision.split('refs/heads/')[-1]
+        project_name_to_data[name][revision] = path
+
+    # get data on requested changes
+    reviews = []
+    change_numbers = []
+    if args.topic:
+        reviews = fetch_query(args.gerrit, 'topic:{0}'.format(args.topic))
+        change_numbers = sorted([str(r['number']) for r in reviews])
+    if args.query:
+        reviews = fetch_query(args.gerrit, args.query)
+        change_numbers = sorted([str(r['number']) for r in reviews])
+    if args.change_number:
+        for c in args.change_number:
+            if '-' in c:
+                templist = c.split('-')
+                for i in range(int(templist[0]), int(templist[1]) + 1):
+                    change_numbers.append(str(i))
+            else:
+                change_numbers.append(c)
+        reviews = fetch_query(args.gerrit, ' OR '.join('change:{0}'.format(x.split('/')[0]) for x in change_numbers))
+
+    # make list of things to actually merge
+    mergables = []
+
+    # If --exclude is given, create the list of commits to ignore
+    exclude = []
+    if args.exclude:
+        exclude = args.exclude[0].split(',')
+
+    for change in change_numbers:
+        patchset = None
+        if '/' in change:
+            (change, patchset) = change.split('/')
+
+        if change in exclude:
+            continue
+
+        change = int(change)
+        review = next((x for x in reviews if x['number'] == change), None)
+        if review is None:
+            print('Change %d not found, skipping' % change)
+            continue
+
+        mergables.append({
+            'subject': review['subject'],
+            'project': review['project'],
+            'branch': review['branch'],
+            'change_id': review['change_id'],
+            'change_number': review['number'],
+            'status': review['status'],
+            'fetch': None
+        })
+        mergables[-1]['fetch'] = review['revisions'][review['current_revision']]['fetch']
+        mergables[-1]['id'] = change
+        if patchset:
+            try:
+                mergables[-1]['fetch'] = [x['fetch'] for x in review['revisions'] if x['_number'] == patchset][0]
+                mergables[-1]['id'] = '{0}/{1}'.format(change, patchset)
+            except (IndexError, ValueError):
+                args.quiet or print('ERROR: The patch set {0}/{1} could not be found, using CURRENT_REVISION instead.'.format(change, patchset))
+
+    for item in mergables:
+        args.quiet or print('Applying change number {0}...'.format(item['id']))
+        # Check if change is open and exit if it's not, unless -f is specified
+        if (item['status'] != 'OPEN' and item['status'] != 'NEW') and not args.query:
+            if args.force:
+                print('!! Force-picking a closed change !!\n')
+            else:
+                print('Change status is ' + item['status'] + '. Skipping the cherry pick.\nUse -f to force this pick.')
+                continue
+
+        # Convert the project name to a project path
+        #   - check that the project path exists
+        project_path = None
+
+        if item['project'] in project_name_to_data and item['branch'] in project_name_to_data[item['project']]:
+            project_path = project_name_to_data[item['project']][item['branch']]
+        elif args.path:
+            project_path = args.path
+        elif args.ignore_missing:
+            print('WARNING: Skipping {0} since there is no project directory for: {1}\n'.format(item['id'], item['project']))
+            continue
+        else:
+            sys.stderr.write('ERROR: For {0}, could not determine the project path for project {1}\n'.format(item['id'], item['project']))
+            sys.exit(1)
+
+        # If --start-branch is given, create the branch (more than once per path is okay; repo ignores gracefully)
+        if args.start_branch:
+            subprocess.check_output(['repo', 'start', args.start_branch[0], project_path])
+
+        # Determine the maximum commits to check already picked changes
+        check_picked_count = 10
+        branch_commits_count = int(subprocess.check_output(['git', 'rev-list', '--count', 'HEAD'], cwd=project_path))
+        if branch_commits_count <= check_picked_count:
+            check_picked_count = branch_commits_count - 1
+
+        # Check if change is already picked to HEAD...HEAD~check_picked_count
+        found_change = False
+        for i in range(0, check_picked_count):
+            output = subprocess.check_output(['git', 'show', '-q', 'HEAD~{0}'.format(i)], cwd=project_path).split()
+            if 'Change-Id:' in output:
+                head_change_id = ''
+                for j,t in enumerate(reversed(output)):
+                    if t == 'Change-Id:':
+                        head_change_id = output[len(output) - j]
+                        break
+                if head_change_id.strip() == item['change_id']:
+                    print('Skipping {0} - already picked in {1} as HEAD~{2}'.format(item['id'], project_path, i))
+                    found_change = True
+                    break
+        if found_change:
+            continue
+
+        # Print out some useful info
+        if not args.quiet:
+            print('--> Subject:       "{0}"'.format(item['subject']))
+            print('--> Project path:  {0}'.format(project_path))
+            print('--> Change number: {0} (Patch Set {0})'.format(item['id']))
+
+        if 'anonymous http' in item['fetch']:
+            method = 'anonymous http'
+        else:
+            method = 'ssh'
+
+        # Try fetching from GitHub first if using default gerrit
+        if args.gerrit == default_gerrit:
+            if args.verbose:
+                print('Trying to fetch the change from GitHub')
+
+            if args.pull:
+                cmd = ['git pull --no-edit github', item['fetch'][method]['ref']]
+            else:
+                cmd = ['git fetch github', item['fetch'][method]['ref']]
+            if args.quiet:
+                cmd.append('--quiet')
+            else:
+                print(cmd)
+            result = subprocess.call([' '.join(cmd)], cwd=project_path, shell=True)
+            FETCH_HEAD = '{0}/.git/FETCH_HEAD'.format(project_path)
+            if result != 0 and os.stat(FETCH_HEAD).st_size != 0:
+                print('ERROR: git command failed')
+                sys.exit(result)
+        # Check if it worked
+        if args.gerrit != default_gerrit or os.stat(FETCH_HEAD).st_size == 0:
+            # If not using the default gerrit or github failed, fetch from gerrit.
+            if args.verbose:
+                if args.gerrit == default_gerrit:
+                    print('Fetching from GitHub didn\'t work, trying to fetch the change from Gerrit')
+                else:
+                    print('Fetching from {0}'.format(args.gerrit))
+
+            if args.pull:
+                cmd = ['git pull --no-edit', item['fetch'][method]['url'], item['fetch'][method]['ref']]
+            else:
+                cmd = ['git fetch', item['fetch'][method]['url'], item['fetch'][method]['ref']]
+            if args.quiet:
+                cmd.append('--quiet')
+            else:
+                print(cmd)
+            result = subprocess.call([' '.join(cmd)], cwd=project_path, shell=True)
+            if result != 0:
+                print('ERROR: git command failed')
+                sys.exit(result)
+        # Perform the cherry-pick
+        if not args.pull:
+            cmd = ['git cherry-pick FETCH_HEAD']
+            if args.quiet:
+                cmd_out = open(os.devnull, 'wb')
+            else:
+                cmd_out = None
+            result = subprocess.call(cmd, cwd=project_path, shell=True, stdout=cmd_out, stderr=cmd_out)
+            if result != 0:
+                print('ERROR: git command failed')
+                sys.exit(result)
+        if not args.quiet:
+            print('')
diff --git a/build/tools/roomservice.py b/build/tools/roomservice.py
new file mode 100755
index 0000000..a1b69cd
--- /dev/null
+++ b/build/tools/roomservice.py
@@ -0,0 +1,297 @@
+#!/usr/bin/env python
+# Copyright (C) 2012-2013, The CyanogenMod Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import print_function
+
+import base64
+import json
+import netrc
+import os
+import re
+import sys
+try:
+  # For python3
+  import urllib.error
+  import urllib.parse
+  import urllib.request
+except ImportError:
+  # For python2
+  import imp
+  import urllib2
+  import urlparse
+  urllib = imp.new_module('urllib')
+  urllib.error = urllib2
+  urllib.parse = urlparse
+  urllib.request = urllib2
+
+from xml.etree import ElementTree
+
+product = sys.argv[1]
+
+if len(sys.argv) > 2:
+    depsonly = sys.argv[2]
+else:
+    depsonly = None
+
+try:
+    device = product[product.index("_") + 1:]
+except:
+    device = product
+
+if not depsonly:
+    print("Device %s not found. Attempting to retrieve device repository from CyanogenMod Github (http://github.com/CyanogenMod)." % device)
+
+repositories = []
+
+try:
+    authtuple = netrc.netrc().authenticators("api.github.com")
+
+    if authtuple:
+        auth_string = ('%s:%s' % (authtuple[0], authtuple[2])).encode()
+        githubauth = base64.encodestring(auth_string).decode().replace('\n', '')
+    else:
+        githubauth = None
+except:
+    githubauth = None
+
+def add_auth(githubreq):
+    if githubauth:
+        githubreq.add_header("Authorization","Basic %s" % githubauth)
+
+if not depsonly:
+    githubreq = urllib.request.Request("https://api.github.com/search/repositories?q=%s+user:CyanogenMod+in:name+fork:true" % device)
+    add_auth(githubreq)
+    try:
+        result = json.loads(urllib.request.urlopen(githubreq).read().decode())
+    except urllib.error.URLError:
+        print("Failed to search GitHub")
+        sys.exit()
+    except ValueError:
+        print("Failed to parse return data from GitHub")
+        sys.exit()
+    for res in result.get('items', []):
+        repositories.append(res)
+
+local_manifests = r'.repo/local_manifests'
+if not os.path.exists(local_manifests): os.makedirs(local_manifests)
+
+def exists_in_tree(lm, path):
+    for child in lm.getchildren():
+        if child.attrib['path'] == path:
+            return True
+    return False
+
+# in-place prettyprint formatter
+def indent(elem, level=0):
+    i = "\n" + level*"  "
+    if len(elem):
+        if not elem.text or not elem.text.strip():
+            elem.text = i + "  "
+        if not elem.tail or not elem.tail.strip():
+            elem.tail = i
+        for elem in elem:
+            indent(elem, level+1)
+        if not elem.tail or not elem.tail.strip():
+            elem.tail = i
+    else:
+        if level and (not elem.tail or not elem.tail.strip()):
+            elem.tail = i
+
+def get_default_revision():
+    m = ElementTree.parse(".repo/manifest.xml")
+    d = m.findall('default')[0]
+    r = d.get('revision')
+    return r.replace('refs/heads/', '').replace('refs/tags/', '')
+
+def get_from_manifest(devicename):
+    try:
+        lm = ElementTree.parse(".repo/local_manifests/roomservice.xml")
+        lm = lm.getroot()
+    except:
+        lm = ElementTree.Element("manifest")
+
+    for localpath in lm.findall("project"):
+        if re.search("android_device_.*_%s$" % device, localpath.get("name")):
+            return localpath.get("path")
+
+    # Devices originally from AOSP are in the main manifest...
+    try:
+        mm = ElementTree.parse(".repo/manifest.xml")
+        mm = mm.getroot()
+    except:
+        mm = ElementTree.Element("manifest")
+
+    for localpath in mm.findall("project"):
+        if re.search("android_device_.*_%s$" % device, localpath.get("name")):
+            return localpath.get("path")
+
+    return None
+
+def is_in_manifest(projectpath):
+    try:
+        lm = ElementTree.parse(".repo/local_manifests/roomservice.xml")
+        lm = lm.getroot()
+    except:
+        lm = ElementTree.Element("manifest")
+
+    for localpath in lm.findall("project"):
+        if localpath.get("path") == projectpath:
+            return True
+
+    ## Search in main manifest, too
+    try:
+        lm = ElementTree.parse(".repo/manifest.xml")
+        lm = lm.getroot()
+    except:
+        lm = ElementTree.Element("manifest")
+
+    for localpath in lm.findall("project"):
+        if localpath.get("path") == projectpath:
+            return True
+
+    return False
+
+def add_to_manifest(repositories, fallback_branch = None):
+    try:
+        lm = ElementTree.parse(".repo/local_manifests/roomservice.xml")
+        lm = lm.getroot()
+    except:
+        lm = ElementTree.Element("manifest")
+
+    for repository in repositories:
+        repo_name = repository['repository']
+        repo_target = repository['target_path']
+        print('Checking if %s is fetched from %s' % (repo_target, repo_name))
+        if is_in_manifest(repo_target):
+            print('CyanogenMod/%s already fetched to %s' % (repo_name, repo_target))
+            continue
+
+        print('Adding dependency: CyanogenMod/%s -> %s' % (repo_name, repo_target))
+        project = ElementTree.Element("project", attrib = { "path": repo_target,
+            "remote": "github", "name": "CyanogenMod/%s" % repo_name })
+
+        if 'branch' in repository:
+            project.set('revision',repository['branch'])
+        elif fallback_branch:
+            print("Using fallback branch %s for %s" % (fallback_branch, repo_name))
+            project.set('revision', fallback_branch)
+        else:
+            print("Using default branch for %s" % repo_name)
+
+        lm.append(project)
+
+    indent(lm, 0)
+    raw_xml = ElementTree.tostring(lm).decode()
+    raw_xml = '<?xml version="1.0" encoding="UTF-8"?>\n' + raw_xml
+
+    f = open('.repo/local_manifests/roomservice.xml', 'w')
+    f.write(raw_xml)
+    f.close()
+
+def fetch_dependencies(repo_path, fallback_branch = None):
+    print('Looking for dependencies')
+    dependencies_path = repo_path + '/cm.dependencies'
+    syncable_repos = []
+
+    if os.path.exists(dependencies_path):
+        dependencies_file = open(dependencies_path, 'r')
+        dependencies = json.loads(dependencies_file.read())
+        fetch_list = []
+
+        for dependency in dependencies:
+            if not is_in_manifest(dependency['target_path']):
+                fetch_list.append(dependency)
+                syncable_repos.append(dependency['target_path'])
+
+        dependencies_file.close()
+
+        if len(fetch_list) > 0:
+            print('Adding dependencies to manifest')
+            add_to_manifest(fetch_list, fallback_branch)
+    else:
+        print('Dependencies file not found, bailing out.')
+
+    if len(syncable_repos) > 0:
+        print('Syncing dependencies')
+        os.system('repo sync --force-sync %s' % ' '.join(syncable_repos))
+
+    for deprepo in syncable_repos:
+        fetch_dependencies(deprepo)
+
+def has_branch(branches, revision):
+    return revision in [branch['name'] for branch in branches]
+
+if depsonly:
+    repo_path = get_from_manifest(device)
+    if repo_path:
+        fetch_dependencies(repo_path)
+    else:
+        print("Trying dependencies-only mode on a non-existing device tree?")
+
+    sys.exit()
+
+else:
+    for repository in repositories:
+        repo_name = repository['name']
+        if repo_name.startswith("android_device_") and repo_name.endswith("_" + device):
+            print("Found repository: %s" % repository['name'])
+            
+            manufacturer = repo_name.replace("android_device_", "").replace("_" + device, "")
+            
+            default_revision = get_default_revision()
+            print("Default revision: %s" % default_revision)
+            print("Checking branch info")
+            githubreq = urllib.request.Request(repository['branches_url'].replace('{/branch}', ''))
+            add_auth(githubreq)
+            result = json.loads(urllib.request.urlopen(githubreq).read().decode())
+
+            ## Try tags, too, since that's what releases use
+            if not has_branch(result, default_revision):
+                githubreq = urllib.request.Request(repository['tags_url'].replace('{/tag}', ''))
+                add_auth(githubreq)
+                result.extend (json.loads(urllib.request.urlopen(githubreq).read().decode()))
+            
+            repo_path = "device/%s/%s" % (manufacturer, device)
+            adding = {'repository':repo_name,'target_path':repo_path}
+            
+            fallback_branch = None
+            if not has_branch(result, default_revision):
+                if os.getenv('ROOMSERVICE_BRANCHES'):
+                    fallbacks = list(filter(bool, os.getenv('ROOMSERVICE_BRANCHES').split(' ')))
+                    for fallback in fallbacks:
+                        if has_branch(result, fallback):
+                            print("Using fallback branch: %s" % fallback)
+                            fallback_branch = fallback
+                            break
+
+                if not fallback_branch:
+                    print("Default revision %s not found in %s. Bailing." % (default_revision, repo_name))
+                    print("Branches found:")
+                    for branch in [branch['name'] for branch in result]:
+                        print(branch)
+                    print("Use the ROOMSERVICE_BRANCHES environment variable to specify a list of fallback branches.")
+                    sys.exit()
+
+            add_to_manifest([adding], fallback_branch)
+
+            print("Syncing repository to retrieve project.")
+            os.system('repo sync --force-sync %s' % repo_path)
+            print("Repository synced!")
+
+            fetch_dependencies(repo_path, fallback_branch)
+            print("Done")
+            sys.exit()
+
+print("Repository for %s not found in the CyanogenMod Github repository list. If this is in error, you may need to manually add it to your local_manifests/roomservice.xml." % device)
diff --git a/config/common.mk b/config/common.mk
index 6c3f7b1..ad2a8d7 100644
--- a/config/common.mk
+++ b/config/common.mk
@@ -351,6 +351,12 @@
   ro.modversion=$(CM_VERSION) \
   ro.cmlegal.url=https://cyngn.com/legal/privacy-policy
 
+ifeq ($(OTA_PACKAGE_SIGNING_KEY),)
+    PRODUCT_EXTRA_RECOVERY_KEYS += \
+        vendor/cm/build/target/product/security/cm \
+        vendor/cm/build/target/product/security/cm-devkey
+endif
+
 -include vendor/cm-priv/keys/keys.mk
 
 CM_DISPLAY_VERSION := $(CM_VERSION)