View on GitHub

wiki

Android platform

Building platform

Environment setup

Easiest w/ Ubuntu (14.04 LTS); requires 64-bit

sudo apt-get install git gnupg flex bison gperf build-essential zip curl libc6-dev libncurses5-dev:i386 \
x11proto-core-dev libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-glx:i386 libgl1-mesa-dev \
g++-multilib mingw32 tofrodos  python-markdown libxml2-utils xsltproc zlib1g-dev:i386 lib32ncurses5-dev libssl0.9.8:i386 libqtgui4:i386 libxml2:i386 libswitch-perl

#For android 4.x:
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java6-installer
sudo update-java-alternatives -s java-6-oracle
sudo apt-get install oracle-java6-set-default

#For android 5.x:
sudo apt-get install openjdk-7

Building

Must find android version which has compatible driver binaries before building

Install ‘repo’ program from google (refer to http://source.android.com/source/downloading.html)

repo init -u <manifest URL> -b <proper branch version>

For Mako/Nexus 4:

repo init -u https://android.googlesource.com/platform/manifest -b android-4.4.2_r1
repo sync -j8

Then download binary drivers, run the scripts to extract to vendor/ (refer to https://developers.google.com/android/nexus/drivers)

source build/envsetup.sh
lunch
make -j16
# ~/android_plat/out/target/product/model contains .img files

Boot the device into fastboot mode:

fastboot flash whatever1 whatever1.img
fastboot flash whatever2 whatever2.img
fastboot flash whatever3 whatever3.img

Building kernel

Compiling the kernel

Must build the kernel with the same kernel source version as that being used in the platform build you’re using.

Get the kernel sources (this below repo is just for for N4 and a few other qualcomm-based devices):

git clone https://android.googlesource.com/kernel/msm.git

export ARCH=arm
export SUBARCH=arm
export CROSS_COMPILE=arm-eabi-
export PATH=~/android_plat/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin:$PATH

cd msm
git branch -a to see branches
git checkout proper branch
make mako_defconfig
make menuconfig -> general setup -> local version - append to kernel release (to add an identifier)
make -j16

Adding the kernel to the phone

Two options from here to create the boot.img:

Copy into an old boot.img (couldn’t get to work on Lollipop)

apt-get install abootimg
get the original boot.img (android_platform/out/target/product/mako/boot.img)
get the new zImage (android_kern/arch/arm/boot/zImage)
abootimg --create boot.img -k zImage -r android_plat/out/target/product/mako/ramdisk.img

Build as part of the platform:

cd android_platform
rm device/lge/mako-kernel/kernel
cp zImage device/lge/mako-kernel/kernel
make -j8 bootimage (or just make -j8)

Test with:

adb reboot bootloader
fastboot boot boot.img

Tracing

Overview

ftrace

Function tracing not enabled by default on many production builds. To get working, compile a new kernel:

*disable* CONFIG_STRICT_MEMORY_RWX in .config on msm-based phones
Kernel Hacking -> Tracers -> Kernel FUNCTION_TRACER
Kernel Hacking -> Tracers -> Interrupts-off Latency Tracer
Kernel Hacking -> Tracers -> Preemption-off Latency Tracer
Kernel Hacking -> Tracers -> Trace max stack
Kernel Hacking -> Tracers -> Enable kprobes-based dynamic events
Kernel Hacking -> Tracers -> enable/disable ftrace tracepoints dynamically

For function tracing:

echo function > current_tracer
cat trace

For event tracing:

echo 16384 > /d/tracing/buffer_size_kb && echo "" > /d/tracing/set_event && echo "" > /d/tracing/trace && echo "irq:* sched:* power:cpu_frequency" > /d/tracing/set_event && sleep 60 && cat /d/tracing/trace > /data/local/ftrace.txt &

NDK

The NDK has the option of using a cross-compiler (directly to a Linux binary) instead of compiling to a APK with embedded machine code.

# Download the NDK
./build/tools/make-standalone-toolchain.sh --toolchain=x86-4.6 --install-dir=/home/rayoub1/dkadjox/android/toolchain
# You can now compile a program and load the program into the device
i686-linux-android-gcc -o hello hello.c
adb push hello /data/scl/programs/.

# On the device
cd /data/scl/programs/
chmod 777 hello
./hello

Data sources

Getting battery drain

Current drain given in uA

cat /sys/class/power_supply/battery/current_now

Get FPS data in logcat

setprop debug.gr.calcfps 1
setprop debug.gr.calcfps.period 1
stop
start
adb logcat time -v

TGID information in ftrace

Only new versions of the kernel have TGID info in ftrace. Apply the patch below and recompile the kernel to add this information.

trace: Add an option to show tgids in trace output

The tgids are tracked along side the saved_cmdlines tracking, and can be
included in trace output by enabling the 'print-tgid' trace option. This is
useful when doing post-processing of the trace data, as it allows events to be
grouped by tgid.

Change-Id: I52ed04c3a8ca7fddbb868b792ce5d21ceb76250e
Signed-off-by: Jamie Gennis <jgennis@google.com>
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 66338c4..0308e57 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -479,6 +479,7 @@
    "disable_on_free",
    "irq-info",
    "markers",
+   "print-tgid",
    NULL
 };

@@ -983,6 +984,7 @@
 static unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1];
 static unsigned map_cmdline_to_pid[SAVED_CMDLINES];
 static char saved_cmdlines[SAVED_CMDLINES][TASK_COMM_LEN];
+static unsigned saved_tgids[SAVED_CMDLINES];
 static int cmdline_idx;
 static arch_spinlock_t trace_cmdline_lock = __ARCH_SPIN_LOCK_UNLOCKED;

@@ -1130,6 +1132,7 @@
    }

    memcpy(&saved_cmdlines[idx], tsk->comm, TASK_COMM_LEN);
+   saved_tgids[idx] = tsk->tgid;

    arch_spin_unlock(&trace_cmdline_lock);
 }
@@ -1163,6 +1166,25 @@

    arch_spin_unlock(&trace_cmdline_lock);
    preempt_enable();
+}
+
+int trace_find_tgid(int pid)
+{
+   unsigned map;
+   int tgid;
+
+   preempt_disable();
+   arch_spin_lock(&trace_cmdline_lock);
+   map = map_pid_to_cmdline[pid];
+   if (map != NO_CMDLINE_MAP)
+       tgid = saved_tgids[map];
+   else
+       tgid = -1;
+
+   arch_spin_unlock(&trace_cmdline_lock);
+   preempt_enable();
+
+   return tgid;
 }

 void tracing_record_cmdline(struct task_struct *tsk)
@@ -2082,6 +2104,13 @@
    seq_puts(m, "#              | |       |          |         |\n");
 }

+static void print_func_help_header_tgid(struct trace_array *tr, struct seq_file *m)
+{
+   print_event_info(tr, m);
+   seq_puts(m, "#           TASK-PID    TGID   CPU#      TIMESTAMP  FUNCTION\n");
+   seq_puts(m, "#              | |        |      |          |         |\n");
+}
+
 static void print_func_help_header_irq(struct trace_array *tr, struct seq_file *m)
 {
    print_event_info(tr, m);
@@ -2092,6 +2121,18 @@
    seq_puts(m, "#                            ||| /     delay\n");
    seq_puts(m, "#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION\n");
    seq_puts(m, "#              | |       |   ||||       |         |\n");
+}
+
+static void print_func_help_header_irq_tgid(struct trace_array *tr, struct seq_file *m)
+{
+   print_event_info(tr, m);
+   seq_puts(m, "#                                      _-----=> irqs-off\n");
+   seq_puts(m, "#                                     / _----=> need-resched\n");
+   seq_puts(m, "#                                    | / _---=> hardirq/softirq\n");
+   seq_puts(m, "#                                    || / _--=> preempt-depth\n");
+   seq_puts(m, "#                                    ||| /     delay\n");
+   seq_puts(m, "#           TASK-PID    TGID   CPU#  ||||    TIMESTAMP  FUNCTION\n");
+   seq_puts(m, "#              | |        |      |   ||||       |         |\n");
 }

 void
@@ -2389,9 +2430,15 @@
    } else {
        if (!(trace_flags & TRACE_ITER_VERBOSE)) {
            if (trace_flags & TRACE_ITER_IRQ_INFO)
-             print_func_help_header_irq(iter->tr, m);
+               if (trace_flags & TRACE_ITER_TGID)
+                   print_func_help_header_irq_tgid(iter->tr, m);
+               else
+                   print_func_help_header_irq(iter->tr, m);
            else
-             print_func_help_header(iter->tr, m);
+               if (trace_flags & TRACE_ITER_TGID)
+                   print_func_help_header_tgid(iter->tr, m);
+               else
+                   print_func_help_header(iter->tr, m);
        }
    }
 }
@@ -3074,9 +3121,53 @@
 }

 static const struct file_operations tracing_saved_cmdlines_fops = {
-  .open       = tracing_open_generic,
-  .read       = tracing_saved_cmdlines_read,
-  .llseek    = generic_file_llseek,
+   .open   = tracing_open_generic,
+   .read   = tracing_saved_cmdlines_read,
+   .llseek = generic_file_llseek,
+};
+
+static ssize_t
+tracing_saved_tgids_read(struct file *file, char __user *ubuf,
+               size_t cnt, loff_t *ppos)
+{
+   char *file_buf;
+   char *buf;
+   int len = 0;
+   int pid;
+   int i;
+
+   file_buf = kmalloc(SAVED_CMDLINES*(16+1+16), GFP_KERNEL);
+   if (!file_buf)
+       return -ENOMEM;
+
+   buf = file_buf;
+
+   for (i = 0; i < SAVED_CMDLINES; i++) {
+       int tgid;
+       int r;
+
+       pid = map_cmdline_to_pid[i];
+       if (pid == -1 || pid == NO_CMDLINE_MAP)
+           continue;
+
+       tgid = trace_find_tgid(pid);
+       r = sprintf(buf, "%d %d\n", pid, tgid);
+       buf += r;
+       len += r;
+   }
+
+   len = simple_read_from_buffer(ubuf, cnt, ppos,
+                     file_buf, len);
+
+   kfree(file_buf);
+
+   return len;
+}
+
+static const struct file_operations tracing_saved_tgids_fops = {
+   .open   = tracing_open_generic,
+   .read   = tracing_saved_tgids_read,
+   .llseek = generic_file_llseek,
 };

 static ssize_t
@@ -5073,6 +5164,9 @@
    trace_create_file("saved_cmdlines", 0444, d_tracer,
            NULL, &tracing_saved_cmdlines_fops);

+   trace_create_file("saved_tgids", 0444, d_tracer,
+           NULL, &tracing_saved_tgids_fops);
+
    trace_create_file("trace_clock", 0644, d_tracer, NULL,
              &trace_clock_fops);

diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 2081971..183cfe8 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -574,6 +574,7 @@
 extern cycle_t ftrace_now(int cpu);

 extern void trace_find_cmdline(int pid, char comm[]);
+extern int trace_find_tgid(int pid);

 #ifdef CONFIG_DYNAMIC_FTRACE
 extern unsigned long ftrace_update_tot_cnt;
@@ -786,6 +787,7 @@
    TRACE_ITER_STOP_ON_FREE     = 0x400000,
    TRACE_ITER_IRQ_INFO     = 0x800000,
    TRACE_ITER_MARKERS      = 0x1000000,
+   TRACE_ITER_TGID         = 0x2000000,
 };

 /*
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index 697e88d..249e1e9 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -660,11 +660,25 @@
    unsigned long secs, usec_rem;
    char comm[TASK_COMM_LEN];
    int ret;
+   int tgid;

    trace_find_cmdline(entry->pid, comm);

- ret = trace_seq_printf(s, "%16s-%-5d [%03d] ",
-                comm, entry->pid, iter->cpu);
+   ret = trace_seq_printf(s, "%16s-%-5d ", comm, entry->pid);
+   if (!ret)
+       return 0;
+
+   if (trace_flags & TRACE_ITER_TGID) {
+       tgid = trace_find_tgid(entry->pid);
+       if (tgid < 0)
+           ret = trace_seq_puts(s, "(-----) ");
+       else
+           ret = trace_seq_printf(s, "(%5d) ", tgid);
+       if (!ret)
+           return 0;
+   }
+
+   ret = trace_seq_printf(s, "[%03d] ", iter->cpu);
    if (!ret)
        return 0;