[Android] Warped420:
This tree has broken branches

STEP 8​

​

Creating a basic new device tree

First step to this is to search Github for a device tree for your specific device.

This is where I got lucky.

PG and his associates lol, had already put together a working device tree for our device.

Chances are ,if your device didn't just hit the stores this week, somebody may have started work on a device tree for it.

Although if you do not have anything to start with, You must first open your device folder in the "repo" you "sync'd" to your PC, look at the supported devices

This will be a tool only for reference.

As I open my folder I notice the following

1. A "bluetooth" folder, with a config file
2. An "include" folder
3. An "overlay" folder
4. A "prebuilts" folder
5. A "recovery" folder
6. A "releasetools" folder
7. AndroidBoard.mk
8. AndroidProducts.mk
9. Boardconfig.mk
10. CM.mk
11. device_warp2.mk
12. extract-files.sh (this is to pull prop blobs)
13. full_warp2.mk
14. Proprietary-files.txt( a list of the prop files you will pull from your stock phone)
15. recovery.fstab
16. setup-makefiles.sh
17. system.prop
18. USBcontroller.cpp

With this group of files, i was able to get a built, but not bootable copy of Jellybeer 10.1.

Now some devices have less and some have alot more files in the device folder.

If you are really serious about becoming a developer, you have to search out others on Github, forums, etc

This step will take teamwork.

Below are two explanations of the files that go into making a device tree...

The directions below describe how to configure make files for new mobile devices and products.

Create a company directory in //device/partner.

mkdir device/partner/<company_name>

Create a products directory beneath the company directory you created in step 1.

mkdir device/partner/<company_name>/products/

Create a product-specific make file, called device/partner/<company_name>/products/<first_product_name>.mk, that includes the following code:

$(call inherit-product, target/product/generic.mk)
#
# Overrides
PRODUCT_NAME := <first_product_name>
PRODUCT_DEVICE := <board_name>

In the products directory, create an AndroidProducts.mk file that point to (and is responsible for finding) the individual product make files.

#
# This file should set PRODUCT_MAKEFILES to a list of product makefiles
# to expose to the build system. LOCAL_DIR will already be set to
# the directory containing this file.
#
# This file may not rely on the value of any variable other than
# LOCAL_DIR; do not use any conditionals, and do not look up the
# value of any variable that isn't set in this file or in a file that
# it includes.
#

PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/first_product_name.mk \

Create a board-specific directory beneath your company directory that matches the PRODUCT_DEVICE variable <board_name> referenced in the product-specific make file above. This will include a make file that gets accessed by any product using this board.

mkdir device/partner/<company_name>/<board_name>

Create a product_config.mk file in the directory created in the previous step (device/partner/<company_name>/<board_name>). If this directory does not include a product_config.mk file, the build will fail.

# These definitions override the defaults in config/config.make for <board_name>
#
# TARGET_NO_BOOTLOADER := false
# TARGET_HARDWARE_3D := false
#
TARGET_USE_GENERIC_AUDIO := true

If you wish to modify system properties, create a system.prop file in your <board_name> directory(device/partner/<company_name>/<board_name>).

# system.prop for
# This overrides settings in the products/generic/system.prop file
#
# rild.libpath=/system/lib/libreference-ril.so
# rild.libargs=-d /dev/ttyS0

Add a pointer to <second_product_name>.mk within products/AndroidProducts.mk.

PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/first_product_name.mk \
$(LOCAL_DIR)/second_product_name.mk

device/partner/<company_name>/<board_name> must include an Android.mk file with at least the following code:

# make file for new hardware from
#
LOCAL_PATH := $(call my-dir)
#
# this is here to use the pre-built kernel
ifeq ($(TARGET_PREBUILT_KERNEL),)
TARGET_PREBUILT_KERNEL := $(LOCAL_PATH)/kernel
endif
#
file := $(INSTALLED_KERNEL_TARGET)
ALL_PREBUILT += $(file)
$(file): $(TARGET_PREBUILT_KERNEL) | $(ACP)
$(transform-prebuilt-to-target)
#
# no boot loader, so we don't need any of that stuff..
#
LOCAL_PATH := partner/<company_name>/<board_name>
#
include $(CLEAR_VARS)
#
# include more board specific stuff here? Such as Audio parameters.
#

To create a second product for the same board, create a second product-specific make file called device/partner/company_name/products/<second_product_name>.mk that includes:

$(call inherit-product, partner/google/products/generic.mk)
#
# Overrides
PRODUCT_NAME := <second_product_name>
PRODUCT_DEVICE := <board_name>

By now, you should have two new products, called <first_product_name> and <second_product_name> associated with <company_name>. To verify that a product is properly configured (<first_product_name>, for example), execute the following:

cd device
. ./envsetup.sh
partner_setup <first_product_name>
make PRODUCT-<first_product_name>-user

You should find new build binaries located in device/out/target/product/<board_name>.
New Product File Tree

The file tree below illustrates what your own system should look like after completing the steps above.

<company_name>
<board_name>
Android.mk
product_config.mk
system.prop
products
AndroidProducts.mk
<first_product_name>.mk
<second_product_name>.mk

Part 2

Right... So you want to build your own device tree, read on.

Disclaimer: this is by no means complete, and there will be omissions as have explained all this top of my head and copied pasted certain bits that I have here on my own device tree.

The device tree, for example, /device/lg/gt540would consist of the following make files:

Android.mk - this will tell the build system to include and to build sources specifically for your device. See below, for an example. This is dependant on the device and hardware, you could have libsensors, liblights, libcamera subdirectories under the example device tree, i.e. /device/lg/gt540/libsensors, /device/lg/gt540/liblights, /device/lg/gt540/libcamera etc.
AndroidBoard.mk - this is for the kernel, the build system uses that to drop the kernel image in place (more about this in a few minutes)
AndroidProducts.mk - specifies the appropriate device's make file, to use for building. i.e. /device/lg/gt540/device_gt540.mk, this is specific also.
device_xxxxx.mk - specifies the properties and extras to copy over into the final output, in this case, it could be for example, device_gt540.mk
BoardConfig.mk - This is the meat of it all, this is where compiler conditional flags are set, partition layouts, boot addresses, ramdisk size, and so on.

Lets peek into each of those to give a glance as to where it all fits in.

Android.mk:

ifeq ($(TARGET_BOOTLOADER_BOARD_NAME),xxxxx)
include $(call all-named-subdir-makefiles, recovery libsensors liblights libcamera ....)
endif

This is how the build will use that to build recovery, sensors, lights and camera (of course there will be more), its saying 'Yo Builder, go into each of the directories specified, and build the respective sources plskthxbai'

AndroidBoard.mk:

LOCAL_PATH := device/lg/gt540/

#
# Boot files
#
TARGET_PREBUILT_KERNEL := $(LOCAL_PATH)/kernel

file := $(INSTALLED_KERNEL_TARGET)
ALL_PREBUILT += $(file)
$(file): $(TARGET_PREBUILT_KERNEL) | $(ACP)
$(transform-prebuilt-to-target)

Now this, is telling the build system, to be able to drop this kernel into the out/target/product/lg/gt540 (notice the correlation with the device tree directory?)

AndroidProducts.mk:

PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/device_gt540.mk

Its telling the build as in 'Yo Builder, read that device make file please and process it upon completion of build.'

*device_xxxxx.mk: (for this example, device_gt540.mk) *

PRODUCT_NAME := lg_gt540
PRODUCT_DEVICE := gt540
PRODUCT_MODEL := LG GT 540

PRODUCT_COPY_FILES += \
... specific ...

PRODUCT_PROPERTY_OVERRIDES := \
ro.com.android.dateformat=dd-MM-yyyy \
... more stuff ...

This is where all the specifics for the device such as drivers, proprietary libraries, supporting scripts specifically for the device, gets copied over to out/target/product/lg/gt540/system/ in this case. Notice how the overrides for the properties, these end up in the build.prop found in the root of the /system of the Android ROM.

BoardConfig.mk:

LOCAL_PATH:= $(call my-dir)

TARGET_NO_BOOTLOADER := true
TARGET_PREBUILT_KERNEL := device/lg/gt540/kernel
TARGET_PREBUILT_RECOVERY_KERNEL := device/lg/gt540/recovery_kernel

# This will vary from device!
TARGET_BOARD_PLATFORM := msm7k
TARGET_ARCH_VARIANT := armv6-vfp
TARGET_CPU_ABI := armeabi
TARGET_CPU_ABI := armeabi-v6l
TARGET_CPU_ABI2 := armeabi

# OpenGL drivers config file path
BOARD_EGL_CFG := device/lg/gt540/egl.cfg

# Dependant, not to be taken literally!
BOARD_GLOBAL_CFLAGS += -DHAVE_FM_RADIO

# Dependant, not to be taken literally!
BOARD_KERNEL_BASE := 0x02600000

# this will be device specific, and by doing cat /proc/mtd will give you the correct sizes
BOARD_BOOTIMAGE_PARTITION_SIZE := 0x00480000
BOARD_RECOVERYIMAGE_PARTITION_SIZE := 0x00480000
BOARD_SYSTEMIMAGE_PARTITION_SIZE := 0x0cf80000
BOARD_USERDATAIMAGE_PARTITION_SIZE := 0x0d020000
BOARD_FLASH_BLOCK_SIZE := 131072

That is an excerpt, notice how we specify kernel's base address, this is how the boot.img gets generated after compilation is done and yet again, gets dropped into out/target/product/lg/gt540/boot.img. Also, more importantly, we're telling the build system to use the target platform for cross-compiling the sources (*TARGET_BOARD_PLATFORM*/*TARGET_CPU_ABI*) There will be more information in there such as conditional flags to pass to the compiler, for an example. we specified the directive HAVE_FM_RADIO to tell it, when it comes to handling the source for the FM radio system, to conditionally compile parts of the source. Again, this is hardware specific and mileage will vary, also this applies to the address for boot. In a nutshell, this is saying 'Yo Builder, read the damn variables and remember them and apply them when cross-compiling those source files!'

Now that the internals of each of those Android build make-files are shown.

Now, onto the vendor/ part of it, in AOSP, simply, once again, correlation and corresponds with the device/ tree, as in continuing with this example, vendor/lg/gt540/ which gets picked up by the lunch. There's more make files in there but the general consensus is there's a directory called proprietary which contains the proprietary libs (due to close-source etc) that gets copied over. The copying over of the libraries gets specified in the file device-vendor-blobs.mk, in this case, gt540-vendor-blobs.mk.

When the magic happens by doing the following:

. build/envsetup.sh

This is reading in the entire entries found in each of the device/ subdirectories and "remembers them", so the build system knows what type of target is used etc.

When the . lunch gets invoked, a menu appears prompting to pick the device that is required to build. Now the last and final step to do the build...

make -j5 > buildlog.log 2>&1

I run multitail on another terminal and monitor the buildlog.log file to check and make sure its building.

This last step will depend on how many cores you have (n cores + 1 as a rule) and it takes a while to build, GB build takes 40mins on my laptop running Arch Linux 64bit, ICS build takes about 2hrs 30 mins. So mileage will vary on what type of horsepower your machine has.

When the build is done, a little bell goes off and at the bottom of the said log file, I see this:

Combining NOTICE files: out/target/product/xxxxx/obj/NOTICE.html

Target system fs image: out/target/product/xxxxx/obj/PACKAGING/systemimage_intermediates/system.img

Install system fs image: out/target/product/xxxxx/system.img

out/target/product/xxxx/system.img+ total size is 108776448

As matter of interest JBQ (Jean Baptiste Queru - the 'boss' for managing/distributing the source from Google), his build step is this...

Extra code to use the ICS Repository

Now enter the following to initialize the repository:

cd ~/android/system/
repo init -u git://github.com/CyanogenMod/android.git -b ics

Extra codes to use the JB Repository

Now enter the following to initialize the repository:

cd ~/android/system/
repo init -u git://github.com/CyanogenMod/android.git -b jellybean

This is not everything, because a device tree for every device is different, To start from scratch will take alot of time.

You will add, then remove, and then add again.

ASSEMBLE A TEAM...THIS IS A ADVANCED STEP