= Android OS Development =
This page provides details about the Gateworks Android BSP which is used to produce
the various components of the Android OS on a Gateworks Ventana board.
[=#hardware-integration]
== Hardware Integration ==
[=#gpio]
[=#led]
=== LEDs and GPIOs ===
If you wish to manipulate hardware resources such as LED's and GPIO's you can do so
with the Linux sysfs APIs:
* [wiki:gpio#gpiolib_sysfs GPIO class]
* [wiki:gpio#led LED class]
[=#button]
=== Physical Buttons (including Capacitive) ===
Physical buttons are handled by Linux device drivers that generate Linux input
events and get mapped to Android key codes via
[https://source.android.com/devices/input/key-layout-files.html Key Layout Files].
Therefore, you can map (or disable) these to Android Key codes in the various .kl
files in use on your device.
[=#gsc-pushbutton]
==== GSC User Pushbutton ====
The [wiki:gsc Gateworks System Controller] functions as a pushbutton controller for
the front-panel user pushbutton available on most Ventana boards. This particular
button is available as gpio-240 on Ventana boards however there is a
[wiki:gsc#inputdriver gsc-input driver] that converts GSC related interrupts, such
as push-button press-and-release to Linux Input events.
By default note that the GSC is configured such that the user pushbutton is a hard
reset. To configure it instead to be software controlled you need to set GSC CTRL_0
accordingly depending on the actions you wish to catch. For example:
* Configure the pushbutton controller to just catch quick press-and-release
events:
{{{#!bash
i2cset -f -y 0 0x20 0 0x00 # disable hard reset function
i2cset -f -y 0 0x20 11 0x01 # enable pushbutton interrupt
}}}
The [wiki:gsc#inputdriver gsc-input driver] will catch all enabled GSC interrupts
and emit a Linux Input event with a key-code cooresponding to a button (defined in
Linux input.h). For example the GSC_IRQ_PB (pushbutton press-and-release) interrupt
is mapped to BTN_0 which is defined as 0x100 (decimal 256) in
[https://lxr.missinglinkelectronics.com/linux/include/uapi/linux/input.h#L481
input.h].
There exists a key layout file that maps the Linux input event keycodes to Android
key events in /system/usr/keylayout/gsc_input.kl:
{{{#!bash
130|root@ventana:/ # cat /system/usr/keylayout/gsc_input.kl
# quick press-and-release (held <700ms) of front-panel pushbutton
key 256 POWER WAKE
# tamper event
key 259 POWER WAKE
}}}
* Note that BTN_0 is hex 0x100 which is decimal 256
If for some reason you wish to use the pushbutton to capture events that the GSC
does not automatically capture and report as interrupts (for example a button
'press' event instead of a quick press-and-release event, a 'button held for x
seconds' event, or a 'button pressed-and-released x times in quick succession'
event, you can choose to monitor gpio-240 manually with a simple application which
uses the poll(2) stdlib function to block waiting for an interrupt.
[=#gpio-pushbutton]
==== GPIO as a Button ====
Any GPIO can be used as a pushbutton by using the gpio-keys or gpio-keys-polled
driver. This driver will monitor a gpio's interrupt (or poll it if it has none),
debounce it, and emit a Linux input event with a keycode of your choosing.
}}}
* The gpio node needs to be at the top level and its placement is arbitrary
however its customary to put it in alphabetical order (thus between the
'''chosen''' node and the '''leds''' node)
A keylayout file (.kl) is added to the live Android system. The keylayout files are
matched by device name and in this case, the device-name is taken from the device-
tree node name ('''gpio-button''' above) with a unique kernel-defined number
appended. To determine the device name you can ls /sys/bus/platform/drivers/gpio-
keys/gpio-button*:
{{{#!bash
root@ventana:/ # ls /sys/bus/platform/drivers/gpio-keys/gpio-button*
/sys/bus/platform/drivers/gpio-keys/gpio-button.19
}}}
Therefore in the example above where the gpio node was named 'gpio-button' the
device name is 'gpio-button.19'. This name is used as the input device name and you
can see all names of input devices with:
{{{#!bash
root@ventana:/ # cat /sys/class/input/input*/name
gsc_input
gpio-button.19
root@ventana:/ #
}}}
References:
* [https://lxr.missinglinkelectronics.com/linux/include/uapi/linux/input.h Linux
keycodes]
*
[https://lxr.missinglinkelectronics.com/linux/Documentation/devicetree/bindings/inp
ut/gpio-keys.txt Linux gpio-keys device-tree bindings]
* [https://source.android.com/devices/input/key-layout-files.html Android key-
layout files]
[=#filesystem-permissions]
== Filesystem Permissions ==
You can read/write files in /sys from your Android app, but only if the Linux
filesystem has the correct permissions to do so. Android uses Linux filesystem
permissions in the following way:
* root user/group used only by init process (as far as we can tell)
* system user/group used for core Android OS
* user applications get their own unique user/group added at APK install time
which will remain constant until uninstalled but will not match the same APK's
user/group on another device
If you want a user application to be able to control something (for instance a GPIO
direction/value) you need to ensure that all user/group's have access to the
resource (because each Android app has a unique user/group) you need to make sure
the resource has the permissions set for 'others' (ie 666 for read/write or 444 for
read-only).
Permissions and ownership of devices and files are set by the following:
* Android init - when processing *.rc files with the {{{chown}}} and {{{chmod}}}
directives
* Android ueventd - when devices appear dynamically based on configuration in
{{{/ueventd.rc}}} and {{{/ueventd.freescale.rc}}}
* /system/bin/init.sh (Gateworks Added) via {{{chmod}}} and {{{chown}}} shell
commands
[=#networking]
== Android Networking Support ==
[=#netd]
=== Network Daemon (netd) ===
Most networking operations are performed by the network daemon
([http://androidxref.com/4.4.3_r1.1/xref/system/netd/ netd]) via a socket
interface.
[=#dhcp]
=== DHCP ===
When netlink (kernel) shows a device obtaining a link (NETDEV_CHANGE) the
EthernetDataTracker detects the change and dhcpcd is launched. There is a single
EthernetDataTracker object
(frameworks/base/core/java/android/net/EthernetDataTracker.java) that tracks
'Ethernet' device state changes but by design it only tracks a single device which
is controlled by the '''config_ethernet_iface_regex''' string property
(frameworks/base/core/res/res/values/config.xml). While this is defaulted to
'eth\d' to keep it generic this does not mean it will catch interface up/down
events on 'any' ethernet as expected. Instead it only monitors the last interface
from /sys/class/net that matches the setting.
References:
* https://community.freescale.com/docs/DOC-93626 - How to Add Ethernet UI Support
in ICS
[=#wifi]
=== !WiFi ===
See [wiki:Android/wireless]
[=#properties]
== Android Properties ==
You may want to use Android properties to abstract resources such as GPIO's,
backlights, uart devices etc that may vary per board so that you can use a single
firmware image that works across multiple boards.
The Gateworks Android BSP init script sets the following properties that can be
used in an app:
* gpio.dio0 - the numeric gpio assigned to DIO0 (/sys/class/gpio/gpio<n>)
* gpio.dio1 - the numeric gpio assigned to DIO1 (/sys/class/gpio/gpio<n>)
* gpio.dio2 - the numeric gpio assigned to DIO2 (/sys/class/gpio/gpio<n>)
* gpio.dio3 - the numeric gpio assigned to DIO3 (/sys/class/gpio/gpio<n>)
* gpio.can_stby
Your android app can use properties to obtain the actual gpio number used to access
that function via sysfs:
* Android Application Java API:
[http://developer.android.com/reference/java/lang/System.html#getProperty(java.lang
.String) getProperty]
* Native C Code: use property_get from system/core/include/cutils/properties.h
Here is a simple example C application showing how to use get_property to find the
gpio value for a digital-io (assuming the init script above set this up) and
reading the value from /sys/class/gpio:
* external/gpio/Android.mk
{{{
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := gpio.c
LOCAL_MODULE := gpio
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_STATIC_LIBRARIES := libcutils libc
include $(BUILD_EXECUTABLE)
}}}
* external/gpio/gpio.c
{{{#!c
/*
* gpio.c - Tim Harvey <tharvey@gateworks.com>
*
* Simple example of how to get/set GPIO from a property
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <cutils/properties.h>
if (argc < 1) {
fprintf(stderr, "Usage: %s <dionum>\n", argv[0]);
exit(1);
}
return 0;
}
}}}
[=#boot]
== Android Boot Process and Components ==
[=#bootscript]
=== Android Bootloader Script ===
Because the Android kernel needs some additional parameters which are not required
by a standard Linux kernel, the default Ventana u-boot scripts are not sufficient
for booting Android directly. The default bootscripts however anticipate this
requirement and therefore always look for a /boot/6x_bootscript-ventana file on the
first partition (ext fs for non-mtd block storage). If this file is present the
bootloader will load it and source it (thus executing the script it contains).
There are some U-Boot env variables that the bootscript can use for various
overrides (mainly because there isn't a foolproof way of detecting display devices
and boot devices):
* console - device to use as kernel console (you can unset this to disable kernel
console which increases boot time)
* baudrate - baudrate to use for kernel console device
* panel - display (or displays in prioritized order) which can a list of the
following:
* '''Hannstar-XGA''' (for 10" 1024x768 Freescale MXC-LVDS1 display with a egalax
touch controller at i2c 0x04)
* '''AUO-G070VW01''' (for 7" 800x480 display with a tsc2007 touch controller at
i2c 0x49)
* '''HDMI''' (for HDMI display where linux framebuffer mode can be specified in
the 'hdmi' env var but defaults to 1080x720M@60. Other options for 'hdmi' var
include 1920x1080M@60, 640x480M60 and others your monitor may support from
/sys/class/graphics/fb0/modes)
* If not specified, the above displays will attempt to be detected by simply
seeing if an i2c device responds on their touchscreens slave address. Note that
some HDMI monitors may have slave devices that match these
* Please see [wiki:ventana/bootloader#Displaysupport setting display in
bootloader at this link].
* fs - the filesystem used on the storage device (defaults to ext2)
* disk - the device number for the disk type (defaults to 0)
* dtype - the storage type which can be one of usb, mmc,
sata
* this is set by the latest Gateworks U-Boot default scripts to avoid detection
* if not specified will be the first device that has a boot/uImage file
* bootdev - the boot device passed to Android which can be one of: fsl-ehci.0 (USB
OTG), fsl-ehci.1 (USB EHCI), sdhci-esdhc-imx.2, ahci.0
For the best understanding of how the boot script works you can view
[https://github.com/Gateworks/android_device_gateworks/blob/imx_kk4.4.3_2.0.0-
beta/ventana/6x_bootscript.txt the source here]
Because the kernel, bootscript, device-tree files, and initial ramdisk are stored
in the BOOT partition you can update the bootscriptmanually as follows via [#adb
adb]:
{{{#!bash
bootable/bootloader/uboot-imx/tools/mkimage -A arm -O linux -T script -C none -a 0
-e 0 -n "boot script" -d \
device/gateworks/ventana/6x_bootscript.txt 6x_bootscript-ventana
adb remount
adb push 6x_bootscript-ventana /boot/boot/
adb reboot
}}}
[=#init.sh]
=== Android Init Script ===
Android has its own init system that differs from the init systems used across
various Unix and Linux distributions. The Android init.rc script syntax allows some
simple primitives for launching applications (either one-shot or persistent),
setting ownership and permissions, and setting properties. This is useful for
things that are common to all devices your firmware will run on and things that
should be setup once (or defaulted) at boot.
For example, if you want your application to be able to control LED brightness you
can do either of the following:
* init.rc: add the following to device/gateworks/ventana/init.rc 'on boot'
section:
{{{#!bash
# set permissions for user leds (using Android init syntax)
chown system system /sys/class/leds/user1/brightness
chown system system /sys/class/leds/user2/brightness
chown system system /sys/class/leds/user3/brightness
chmod 0660 /sys/class/leds/user1/brightness
chmod 0660 /sys/class/leds/user2/brightness
chmod 0660 /sys/class/leds/user3/brightness
}}}
The init.rc file for the Gateworks Ventana Android BSP can be found
[https://github.com/Gateworks/Android/blob/imx_kk4.4.3_2.0.0-beta/ventana/init.rc
here].
Because the Android init application runs from a Linux inital ramdisk (initrd), if
you modify init.rc you need to do a toplevel 'make' to rebuild the ramdisk.img,
apply a U-Boot header to it with 'mkimage' and update it on your BOOT partition.
References:
* [https://android.googlesource.com/platform/system/core/+/master/init/readme.txt
Android init syntax]
[=#init.rc]
=== Android Init Shell Script ===
Because the Android init system does not allow for complex syntax supporting
decision making logic (ie if/then/else clauses) we configured
[https://github.com/Gateworks/android_device_gateworks/blob/imx_kk4.4.3_2.0.0-
beta/ventana/init.rc init.rc] to run a shell script during late boot to handle more
complex board-specific tasks.
Our init script sets some android properties to describe the hardware in a non
board-specific way so that you can use properties in your app to allow it to run on
a variety of Gateworks boards. See [#properties here] for more details on
properties.
[=#kernel]
=== Android Kernel ===
The Android kernel is a Linux kernel with a few additional patches which have not
made it into mainline Linux yet.
Because there is no userspace daemon such as udev which monitors Linux hotplug
events and loads kernel modules on demand typically the kernel has no modules. This
is not a hard rule however and if you want to prune down the kernel to reduce boot
time you can remove support that is not required for your application and/or load
kernel driver modules from [#init.rc init.rc] [#init.sh init.sh] or some other
mechanism after the OS is fully booted.
Because the kernel, bootscript, device-tree files, and initial ramdisk are stored
in the BOOT partition you can update the kernel and dtbs manually as follows via
[#adb adb]:
{{{#!bash
adb remount
adb push kernel_imx/arch/arm/boot/uImage /boot/boot/uImage
for i in `ls kernel_imx/arch/arm/boot/dts/imx6*gw*.dtb`; do adb push $i /boot/boot;
done
adb reboot
}}}
[=#external_storage]
== External Storage ==
The Gateworks Android BSP supports a number of storage mediums that can be
classified as internal or external storage. External storage can be provided by
physical media, like an SD card or USB, that is for temporary file storage and data
transfer. The physical media may remain with the device for an extended period of
time, but is not tied to the device and may be removed.
Depending on whether your boot device was passed as a flash or block device from
the bootloader to the kernel command line, either the {{{fstab_nand}}} or
{{{fstab_block}}} file will be parsed by Vold to handle how the external storage
will be mounted. Adding a new device will require an additional line of the format:
* {{{src}}} - The kernel sysfs path where the device node exists (usually
mounted at /sys). The path must start with {{{/}}}.
* {{{mnt_point}}} - Filesystem path where the volume should be mounted (usually
{{{auto}}}).
* {{{type}}} - The type of the filesystem on the volume. For external cards,
this is usually {{{vfat}}}.
* {{{mnt_flags}}} - Vold ignores this field and it should be set to
{{{defaults}}}
* {{{fs_mgr_flags}}} - Vold ignores any lines in the unified fstab that do not
include the {{{voldmanaged=}}} flag in this field. This flag must be followed by a
label describing the card, and a partition number or the word {{{auto}}}. Other
possible flags are {{{nonremovable}}}, {{{encryptable=sdcard}}},
{{{noemulatedsd}}}, and {{{encryptable=userdata}}}.
An example {{{<storage>}}} element to accompany the fstab line above would be:
{{{#!xml
<storage android:mountPoint="/storage/extsd"
android:storageDescription="@string/storage_sd_card"
android:primary="false"
android:removable="true" />
}}}
[=#selinux]
== Security-Enhanced Linux (SELinux) ==
SELinux is a mandatory access control (MAC) system for the Linux OS. Sockets,
Files, and Processes all have labels in SELinux. A label takes the form of
{{{user:role:type:mls_level}}}. Rules are applied to labels and take the form
{{{allow domains types:classes permissions}}}. The {{{file_contexts}}} file assigns
labels to files via regular expression matches. Filesystems must be built to
include SELinux filesystem attributes. The {{{restorecon}}} userspace application
applies policies to a running kernel, which is usually done as one of the first
things in system init.
Android has been phasing in more robust security measures with each release.
[https://en.wikipedia.org/wiki/Security-Enhanced_Linux SELinux] is a Linux kernel
security module that provides a mechanism for supporting access control security
policies, including the United States Department of Defense-style mandatory access
controls (MAC). SELinux started being used for Android 3.x (Jellybean) in a
permissive mode, and in enforcing mode for Android 4.x (Kitkat).
While troubleshooting it may be useful to disable SELiux which you can do in the
following ways:
* add {{{selinux=0}}} to the kernel cmdline (requires
CONFIG_SECURITY_SELINUX_BOOTPARAM=y in kernel config)
* {{{setenforce 0}}} on cmdline
SELinux policy files are compiled into the {{{sepolicy}}} which exists in the root
of the ramdisk on the BOOT partition. This is created from rules defined in files
in paths from BOARD_SEPOLICY_DIRS defined in !BoardConfig.mk. The ventana specific
policies are located in
[https://github.com/Gateworks/android_device_gateworks/tree/imx_kk4.4.3_2.0.0-
ga/ventana/sepolicy device/gateworks/ventana/sepolicy].
SELinux denials errors output as kernel error messages prefixed with "avc: ". For
example:
{{{#!bash
$ adb shell su -c dmesg | grep "avc: "
[ 62.658290] type=1400 audit(1443478068.109:5): avc: denied { setgid } for
pid=1155 comm="hostapd" capability=6 scontext=u:r:netd:s0 tcontext=u:r:netd:s0
tclass=capability permissive=0
[ 62.675542] type=1400 audit(1443478068.129:6): avc: denied { setgid } for
pid=1155 comm="hostapd" capability=6 scontext=u:r:netd:s0 tcontext=u:r:netd:s0
tclass=capability permissive=0
[ 62.692514] type=1400 audit(1443478068.149:7): avc: denied { add_name } for
pid=1155 comm="hostapd" name="1010" scontext=u:r:netd:s0
tcontext=u:object_r:cgroup:s0 tclass=dir permissive=0
[ 62.709701] type=1400 audit(1443478068.169:8): avc: denied { setuid } for
pid=1155 comm="hostapd" capability=7 scontext=u:r:netd:s0 tcontext=u:r:netd:s0
tclass=capability permissive=0
}}}
* above the 'hostapd' process exec'd by netd is trying to setgid/setuid and failed
The {{{audit2allow}}} tool from the {{{policycoreutils}}} package can take these
denials and converts them into corresponding SELinux policy statements:
{{{#!bash
sudo apt-get install policycoreutils
adb shell su -c dmesg | grep "avc: " | audit2allow # show rules
adb shell su -c dmesg | grep "avc: " | audit2allow -p
out/target/product/ventana/root/sepolicy # analyze against current policy
}}}
For example when the above netd/hostapd violations are run through audit2allow this
shows the following additions could be made to fix the violations:
{{{
#============= netd ==============
allow netd cgroup:dir add_name;
allow netd self:capability { setuid setgid };
}}}
The {{{ls -Z}}} command will show you file contexts and similarly the {{{ps -Z}}}
command will show you process contexts.
You can find the processed policies with comments detailing their source in
$OUTDIR/obj/ETC/sepolicy_intermediates/policy.conf which is built from the
{{{external/sepolicy}}} project.
During development you can rebuild the {{{sepolicy}}} (which verifies your rules
and configuration) via {{{mmm external/sepolicy}}}. You can rebuild and update your
ramdisk with a something like:
{{{
mmm external/sepolicy && mkbootfs out/target/product/ventana/root | minigzip >
out/target/product/ventana/ramdisk.img && \
mkimage -A arm -O linux -T ramdisk -n "RAM Disk" -d
out/target/product/ventana/ramdisk.img \
out/target/product/ventana/boot/boot/uramdisk.img && \
adb remount && \
adb push out/target/product/ventana/boot/boot/uramdisk.img /boot/boot/uramdisk.img
&& \
adb reboot
}}}
Be aware, that because this does not rebuild the system filesystem, any rule
changes will not take effect without a manual {{{restorecon <file>}}}.
References:
* [https://source.android.com/security/selinux/index.html Security-Enhanced Linux
in Android]
[=#partitions]
== Partitions ==
The flash storage space on an Android device typically contains the following
partitions.
* BOOT: /boot - contains bootscript/kernel/ramdisk that boots Android init
* RECOVERY: /recovery - contains bootscript/kernel/ramdisk that boots an
'''Android recovery image''' who's function is very device/vendor specific
* SYSTEM: /system ro - the system '''ROM'''
* DATA: /data - user data - this is where your apps and app data are stored and
where you want the most space
* CACHE: /cache - used for various (unclear) OS caching (including downloading
apps from play store)
* MISC: /misc - a tiny partition used by recovery to stash some information away
about what its doing in case the device is restarted while the OTA package is being
applied
* VENDOR: /device - for vendor specific files
The storage device partitioning is taken care of with whatever script you use to
image android onto a specific device:
* device/gateworks/ventana/mksdcard.sh - for block storage devices such as
USB/mSATA/MMC. The partition sizes are baked into the script
* device/gateworks/ventana/ubi/ubinize.ini - for NAND ubi volume creation of ubi
image
References:
- [https://source.android.com/devices/tech/ota/index.html#android-device-layout
Android device layout]
[=#bootpartition]
=== BOOT partition ===
The BOOT partition is very device specific and typically contains a kernel and
ramdisk containing the Android init system (/sbin/init, init.rc and its includes)
and processes early init until the mounting of the other filesystems. When
filesystems are mounted this may be mounted to /boot
It is built from $(OUTPUT_DIR)/boot and deps are setup on all files in that dir
other than prebuilt files, copied headers, generated sources, and default installed
modules.
To install files onto the ramdisk make sure they get copied to the root/ directory
of the product output folder:
* from ventana.mk or imx6.mk add a file to PRODUCT_COPY_FILES destined for root/:
{{{
PRODUCT_COPY_FILES += device/gateworks/ventana/foo:root/foo
}}}
* from a module Android.mk you can set LOCAL_MODULE_PATH to TARGET_ROOT_OUT to put
it in root/:
{{{
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
}}}
If changes are made you may need to remove the images to force dependency checks
prior to rebuilding:
{{{#!bash
rm -rf out/target/product/ventana/boot/boot/uramdisk.img \
out/target/product/ventana/ramdisk.img
make
}}}
To extract a ramdisk.img from a uramdisk.img you need to take off the 64-byte U-
Boot header:
{{{#!bash
dd if=uramdisk.img of=ramdisk.img bs=1 skip=64
}}}
A recovery.img is a bootable image with the same layout/format as the boot image
(see above).
Typically the ramdisk will have a few more files such as graphics resources and a
different init script/app.
[=#systempartition]
=== SYSTEM partition ===
The SYSTEM partition (ext4 for block devs, ubifs for NAND devs) is mounted to
/system read-only and contains the base Android OS minus installed apps and data
(which go to the DATA partition mounted read-write to /data). This is what is
considered the Android '''ROM'''.
The system partition uses an ext4 filesystem image system.img, created using a
helper script 'out/host/linux-x86/bin/mkuserimg.sh <sourcedir> <output-file> ext4
<mountpoint> <size> <fc>' which does the following:
{{{#!bash
make_ext4fs -S out/target/product/ventana/root/file_contexts -l 398458880 -a
system
out/target/product/ventana/obj/PACKAGING/systemimage_intermediates/system.img
out/target/product/ventana/system
}}}
[=#datapartition]
=== DATA partition ===
The DATA partition (ext4 for block devs, ubifs for NAND devs) is where all user
apps/data/settings are stored and is mounted read/write to /data. Initially its
empty and formatting it is the equivalent of a 'factory wipe' on an Android device.
If you wanted to pre-install apps but allow them to be removable, you would do that
here.
[=#cachepartition]
=== CACHE partition ===
The CACHE partition is a read/write partition (ext4 for block devs, or ubifs for
NAND devs) and is a general purpose storage area. I'm not clear how usable this is
by apps, or if it is only usable by the base OS and Google Apps (I have to think
its usable by anything that wants it). I do know that the Play Store uses this area
for temporary downloads thus if you severely limit the size you cripple the ability
to download large apps. I also am not clear on the size requirements or
recomendations for partitioning schemes. We size this to 512MB which I got from
other IMX6 Android BSP's.
[=#vendorpartition]
=== VENDOR partition ===
The VENDOR partition (ext4 for block devs, or ubifs for NAND devs) is mounted to
/device as readonly and is apparently where vendors should put their add-on
apps/drivers(kernel-modules)/etc. I'm not sure I understand the point of this vs
the vendors adding them into the SYSTEM partition. This is unused by Freescale but
still created with 10MB of space
[=#miscpartition]
=== MISC partition ===
The VENDOR partition (ext4 for block devs, or ubifs for NAND devs) is mounted to
/misc as read/write and is used by recovery to stash some information away about
what it's doing in case the device is restarted while the OTA package is being
applied.
[=#androidui]
== Android System UI Info ==
Some common questions and answers regarding the Android OS UI:
1. how do I disable the 'Navigation Bar'?
* The Navigation bar is the bar at the bottom of the screen reserved for soft
buttons for back, home, and recent apps
* You can disable it at build time for the entire OS by setting
'config_showNavigationBar' property to false in
device/gateworks/ventana/overlay/frameworks/base/core/res/res/values/config.xml
* You can disable within an application at runtime as well - see
[https://developer.android.com/training/system-ui/navigation.html here]
1. Why is the Android Launch showing the dock bar on the right and the Google
Search bar on the left instead of a typical top and bottom layout?
* This has to do with the Launcher application layout configuration. By default
its configured to use this layout if the smallest width is not at least 720dp
(Device Independent Pixels) which is a function of your resolution (which Android
obtains from the Linux framebuffer info) and the defined dpi (declared in
ro.sf_lcd_density in the init script)
[=#touchscreen]
== Android Touchscreen calibration ==
The Android AOSP code does not have any built-in support for x/y point calibration
which is often needed for touchscreen hardware. This means that touchscreen
controller drivers must calibrate the points before sending them to the Linux input
subsystem.
References:
* https://source.android.com/devices/tech/input/input-device-configuration-
files.html
* https://source.android.com/devices/tech/input/touch-devices.html (info on
calibration etc)
* http://www.ti.com/lit/an/slyt277/slyt277.pdf
[=#shell]
== Android shell ==
Handy commands you can enter via the shell over adb or serial console (Note you can
use 'adb shell <command>' to execute shell commands over the Android Debug Bridge):
- input:
- send power button event:
{{{#!bash
input keyevent 26
}}}
- unlock screen
{{{#!bash
input keyevent 82
}}}
- pm (package management):
- display installed packages
{{{#!bash
pm list packages -f
}}}
- clear app data
{{{#!bash
pm clear <packagename>
}}}
[=#build-system]
== Using the Android build system ==
The Android build system consists of a set of makefiles and scripts that can build
the entire OS image or build specific directories at a time.
See also:
- https://source.android.com/source/building.html
- http://elinux.org/Android_Build_System
[=#build-setup]
=== Build environment setup ===
In order to use the build system you must source the scripts into your shell
environment (commonly referred to as 'activating the shell'). This must be done for
each and every shell you wish to build with:
{{{
# activate shell for building Android OS
. ./build/env_setup.sh
}}}
Secondly, you must select a target device and BUILDTYPE (one of eng, user, or
userdebug). For the Gateworks ventana you would use 'ventana-eng', or 'ventana-
user' for example:
{{{
# configure for building User build for Ventana
lunch ventana-user
}}}
[=#build-commands]
=== Build shell commands ===
Once in an activated shell (see [#build-setup above]) you can use the following
common aliases to build:
Make Targets - Here is a list of different make targets you can use to build
different parts of the system:
- {{{make}}} - build OS
- {{{make clean}}} - clean everything
- {{{make dist}}} - build OTA and dist files in DIST_OUT directory (defaults to
out/dist)
- {{{make modules}}} - show a list of submodules that can be built by themselves
- {{{make <local_module>}}} - make a specific module by name (not the directory of
the module but the name assigned by LOCAL_MODULE - use 'make modules' to show a
list)
- {{{make clean-<local_module>}}} - clean a specific module
Helper macros and functions - There are some helper macros and functions that are
installed when you source envsetup.sh. They are documented at the top of
envesetup.sh, but here is information about a few of them:
- {{{croot}}} - change directory to the top of the tree
- {{{m}}} - execute 'make' from the top of the tree (even if your current directory
is somewhere else)
- {{{mm}}} - builds all of the modules in the current directory
- {{{mmm <dir1> ...}}} - build all of the modules in the supplied directories
- {{{cgrep <pattern>}}} - grep on all local C/C++ files
- {{{jgrep <pattern>}}} - grep on all local Java files
- {{{resgrep <pattern>}}} - grep on all local res/*.xml files
- {{{godir <filename>}}} - go to the directory containing a file
[=#android.mk]
=== Modules and Android.mk ===
Android modules are projects in the build tree that contain an Android.mk file.
These are scanned by the build system. Each Android.mk file declares one or more
'''modules''' by defining a few vars:
* LOCAL_MODULE: module name
* LOCAL_MODULE_TAGS: defines which build variants this module should be installed
in. (see [http://www.kandroid.org/online-pdk/guide/build_system.html here]). Use
'user' for final build only, 'eng' for eng build only, 'optional' for all
(technically only if the module is listed in the PRODUCT_PACKAGES). You can remove
this completely to make it not built at all.
* LOCAL_MODULE_PATH: the directory where to install compiled objects
(TARGET_OUT_SHARED_LIBARIES would be the 'lib' subdir in the system folder)
* LOCAL-SRC_FILES: the *.c files
* LOCAL_C_INCLUDES: additional include dirs (relative to topdir)
* LOCAL_SHARED_LIBARIES: names of libs to include (like liblog, libcutils,
libtinyalsa, libdl, etc)
* if building a *.so 'include $(BUILD_SHARED_LIBARY)'
see also:
- http://android.mk/
include $(CLEAR_VARS)
LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SRC_FILES := tinyalsa_hal.c
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
system/media/audio_utils/include \
system/media/audio_effects/include
LOCAL_SHARED_LIBRARIES := liblog libcutils libtinyalsa libaudioutils libdl
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
endif
}}}
include $(CLEAR_VARS)
LOCAL_MODULE := wpa_supplicant_overlay.conf
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_SRC_FILES := $(LOCAL_MODULE)
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/wifi
include $(BUILD_PREBUILT)
}}}
* example from device/fsl/common/wifi/Android.mk
Reference:
* http://www.kandroid.org/online-pdk/guide/build_system.html
If you have APK's that you wish to pre-install you can do so by creating an
Android.mk file that installs the apk to the system partition by including the $
(BUILD_PREBUILT) make file.
Example Android.mk:
{{{
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := MyApp
LOCAL_SRC_FILES := myapp.apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
# tell dexopt not to try resigning the apks
LOCAL_CERTIFICATE := PRESIGNED
include $(BUILD_PREBUILT)
}}}
[=#buildmodule]
=== Building a stand-alone-app within the Android build system ===
If you are developing your own Android application, you can built it easily in the
android BSP directory and use adb to quickly update it on the target.
For example, on your development host in the Gateworks Android BSP directory:
{{{#!bash
# activate your shell
source build/envsetup.sh
# configure build type
lunch ventana-eng
# rebuild your app (replace external/can-test with the directory to your app
containing an Android.mk)
mmm external/can-test/
}}}
Note that if your application is fairly self-contained and not tightly coupled with
the OS, you may wish to use Android Studio to develop it outside of the Android OS
build system. See [wiki:Android/AppDevelopment] for more info.
[=#helloworld]
=== Android Hello World Executable C File ===
As a full example consider a simple 'helloworld' application.
}}}
include $(CLEAR_VARS)
LOCAL_SRC_FILES := helloworld.c
LOCAL_MODULE := helloworld
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_STATIC_LIBRARIES := libcutils libc
include $(BUILD_EXECUTABLE)
}}}
3. Compile the file (using an activated shell - Note: A full build must have been
compiled prior to this...)
* compile by directory (or you could compile by module via 'make helloworld'
however this takes longer as it needs to scan the directories for module names)
{{{
$ mmm external/helloworld
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.4.3
TARGET_PRODUCT=ventana
TARGET_BUILD_VARIANT=user
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a-neon
TARGET_CPU_VARIANT=cortex-a9
HOST_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-3.13.0-43-generic-x86_64-with-Ubuntu-14.04-trusty
HOST_BUILD_TYPE=release
BUILD_ID=2.0.0
OUT_DIR=out
============================================
.....
4. Copy exectuable file over to running Android system and run it. For example, the
executable was put in the location as defined by the output of the log above:
out/target/product/ventana/obj/EXECUTABLES/helloworld_intermediates/LINKED/hellowor
ld. An example location to put the file on a running Android system on the
Gateworks SBC would be /data/system. Use wget or use adb push
[wiki:Android/OSDevelopment#adb-push ADB Push Example]
* use wget on target
{{{#!bash
root@ventana:/data/system # busybox wget http://xxx.xx.xx.11/helloworld
root@ventana:/data/system # ./helloworld
Hello World
}}}
[=#overlay]
=== Customizing your target device using overlays ===
The Android build system uses an overlay system that allows files to be replaced on
a per-target device basis. This is commonly done to do things like adjust layout
specific resources or background wallpapers for a specific device.
If your product's .mk file defines one of these, any resource file present there
will override the resource from the original directory.
[=#adb]
== Android Debug Bridge (ADB) ==
Android uses a client/server application for remote debugging referred to as the
Android Debug Bridge or adb. This can run over a variety of interconnects including
serial, USB, and TCP/IP.
[=#adb-security]
=== ADB security ===
The ADB Daemon (adbd) typically operates with security in place (ro.adb.secure=1)
such that the android target device must grant permissions for devices to operate
over ADB.
Notes:
- ro.adb.secure=1 # enables security"
- ~/.android/adbkey.pub is your public key on your Linux development host
- /data/misc/adb/adb_keys is where they are stored on android target
Reference:
* http://nelenkov.blogspot.com/2013/02/secure-usb-debugging-in-android-422.html
[=#adb-install]
=== Installing adb on PC ===
You have several options for installing adb on a Linux / Mac / Windows PC:
* install from a downloadable package
* Ubuntu 13.10 and above:
{{{#!bash
sudo apt-get install android-tools-adb
}}}
* Ubuntu 12.04, 11.10, 11.04 - the latest android tools package is 4.1.1 which
has adb v1.0.29 which will does not support the per device authentication mechanism
added in Jellybean 4.2+. You can update to the v4.2.2 package containing adb
v1.0.31 using a community ppa from https://launchpad.net/~nilarimogard/
+archive/webupd8:
{{{#!bash
sudo add-apt-repository ppa:nilarimogard/webupd8
sudo apt-get update
sudo apt-get install android-tools-adb android-tools-fastboot
}}}
* if you have updated be sure to restart the adb server
* install the Android SDK
* build from source
Common issues:
* adb devices shows device as 'offline': you have not authenticated the device -
go to the target device, unlock it and select 'ok' to the authentication dialog
* adb devices shows device as 'unauthorized': you need to enable Settings-
>Developer options->USB debugging
* adb devices shows device as '???????????? no permissions: this is a usb device
permissions issue - restart server as root: adb kill-server; sudo adb start-server
[=#adb-otg]
=== adb over USB OTG ===
Probably the most common use of adb is to use it over a USB OTG connection. For
example, you can connect a PC Host USB port to the USB OTG (microUSB) connector on
a Ventana board.
Note that to use adb over USB OTG to communicate with an Android Jellybean (4.2+)
target device you must:
* enable USB debugging: Developer options -> USB debugging
* Authenticate the host device (your PC): When you connect and are not on the
lockscreen, you will be presented with a USB Debugging Authentication dialog. You
must select 'OK' to allow debugging and you can optionally check the box to
remember this device so you don't have to authenticate it every time (in the
Developer options -> USB debugging menu you can also revoke prior remembered
authentications)
[=#adb-net]
=== adb over TCP/IP network ===
To use adb over TCP/IP networking you need to configure the port on the target
device either via a serial console, or by using an adb shell from another method
such as usb.
On host PC:
{{{#!bash
adb connect <ip>
# authenticate the request on the target device
adb logcat ...
}}}
Note that an authentication dialog will appear on the Android target device (as
long as it not on the lockscreen) after the {{{adb connect}}} - be sure to
authenticate or the device will be offline.
References:
- http://stackoverflow.com/questions/2604727/how-can-i-connect-to-android-with-
adb-over-tcp
[=#adb-push]
=== Using adb to push your code to your target ===
To push a newly built file to target (ie the cantest app):
{{{#!bash
# push the newly built exe to the target (make sure you push it somewhere you have
write permissions for)
adb push out/target/product/ventana/system/bin/cantest /data
adb reboot
}}}
* Note that adb push pushes the file contents AND '''the file permissions''' from
the development host to the target. Therefore, bue sure to check the file
permissions once onto the target.
Note that filesystem permissions apply, so you need to make sure you are pushing to
a filesystem that is writable. The /data partition for example is writable, but by
default /system is not. If you wish to remount /system read/write you can use adb
remount before pushing:
{{{#!bash
adb remount
}}}
Note that adb can also sync your development output directory with your target
which is very handy if you want to push all changes (providing your using the
android build system to properly build and install files into the output
directory):
{{{#!bash
adb remount
adb sync
adb reboot
}}}
Note that {{adb sync}}} only works for the system and data partition. If you wish
to sync udpdates to the boot partition (kernel, bootscript, dtbs, ramdisk) you can
do that with the following command:
{{{#!bash
adb remount
for i in `ls out/target/product/ventana/boot/boot`; do \
adb push out/target/product/ventana/boot/boot/$i /boot/boot; \
done
adb reboot
}}}