Android Device Porting Walkthrough
Android Device Porting Walkthrough
Benjamin Zores
ABS 2012 13th February 2012 Redwood Shores, SF Bay, CA, USA
About Me
ALCATEL LUCENT
SOFTWARE ARCHITECT Expert and Evangelist on Open Source Software. 9y experience on various multimedia/network embedded devices design. From low-level BSP integration to global applicative software architecture.
OPEN SOURCE
Embedded Linux cross-build framework. Embedded multimedia HTPC distribution. EFL Media Center. UPnP A/V and DLNA Media Server. Linux media player application.
GeeXboX Enna: Embedded Media Center. State of Multimedia in 2010 Embedded Linux Devices. Linux Optimization Techniques: How Not to Be Slow ?
My Experience
My Android Bibles
Work Context
Designing an Enterprise Desktop IP Phone. Differs heavily from usual Android devices:
- Always connected, no battery - No GSM/CDMA Phone/Modem - Always docked - No screen rotation - No accelerometer - No GPS - => Not a Smartphone
Key Requirements
- Memory: - Storage: - Display: - Graphics: Minimum of 512 MB. Minimum of 2 GB. Minimum resolution of 460x320. Hardware 2D/3D engine is more than recommended.
- DO NOT modify Google APIs and framework. - Android "Telephony" refers to 3G/CDMA, hence IP-Phones are NOT considered as Android phones.
6 COPYRIGHT 2012 ALCATEL-LUCENT. ALL RIGHTS RESERVED.
Linaro
- Most integrated with wide hardware support. - git://android.git.linaro.org/platform/manifest.git
Cyanogen Mod
- Most features but mostly used for tuning already released commercial products. - https://github.com/cyanogenmod
Vendor BSP
- Potentially outdated but best support for a given platform/SoC.
Well base our example on TI OMAP4 Pandaboard-derived board based on Linaro sources.
7 COPYRIGHT 2012 ALCATEL-LUCENT. ALL RIGHTS RESERVED.
- x264, ffmpeg, powertop, ARM DS-5 Gator Profiler, U-Boot, Linux Kernel, BusyBox
Optimized Packages:
- Dalvik, IPSec, libvpx, libpng, libjpeg-turbo, OpenSSL, GCC Toolchain
PRODUCT_MAKEFILES := $(LOCAL_DIR)/my_device_name.mk
Mandatory my_device_name.mk: $(call inherit-product, $(SRC_TARGET_DIR)/product/full_base.mk) $(call inherit-product, device/my_company/common/common.mk) $(call inherit-product, device/my_company/my_device/device.mk) PRODUCT_BRAND PRODUCT_DEVICE PRODUCT_NAME := my_device_brand := my_device_name := my_device_name
9 COPYRIGHT 2012 ALCATEL-LUCENT. ALL RIGHTS RESERVED.
PRODUCT_COPY_FILES += device/my_company/my_device/init.rc:root/init.rc PRODUCT_PACKAGES += audio.primary.omap4 PRODUCT_PROPERTY_OVERRIDES += hwui.render_dirty_regions=false PRODUCT_CHARACTERISTICS := tablet,nosdcard PRODUCT_TAGS += dalvik.gc.type-precise $(call inherit-product, frameworks/base/build/tablet-dalvik-heap.mk) $(call inherit-product-if-exists, device/ti/proprietary-open/install-binaries.mk)
TARGET_ARCH_VARIANT := armv7-a-neon ARCH_ARM_HAVE_TLS_REGISTER := true TARGET_EXTRA_CFLAGS += $(call cc-option,"-march=armv7-a -mtune=cortex-a9", $(call cc-option,"-march=armv7-a -mtune=cortex-a8")) # Filesystem and partitioning
:= := := := := := :=
:= true := true
:= device/my_company/my_device/overlay
- Create a device/my_company/my_device/overlay directory with same depth and files you want to overwrite. e.g:
- frameworks/base/core/res/res/values/config.xml - frameworks/base/core/res/res/values/dimens.xml - frameworks/base/core/res/res/xml/storage_list.xml
Bootloader
Google provides one in bootable/bootloader/legacy. But usually replaced by U-Boot with Fastboot protocol support. Can be either out of AOSP sources or integrated.
In BoardConfig.mk:
- TARGET_USE_XLOADER XLOADER_CONFIG TARGET_NO_BOOTLOADER TARGET_USE_UBOOT UBOOT_CONFIG := := := := := false omap4430panda_config true # Uses u-boot instead true omap4_panda_config
- Ashmem, shared memory allocator. - Binder IPC and RMI system. - Pmem, process memory allocator. - Logger, system logging facility. - Wakelocks, power management and suspend. - Low Memory Killer, OOM Tuning.
- Alarm Timers.
- Paranoid Network Security. - Timed GPIO. - RAM Console.
Except for proprietary drivers (usually) or those requiring firmware (e.g. WiFi). Can be added to Android FS separately as for firmwares. In BoardConfig.mk: BOARD_KERNEL_BASE BOARD_KERNEL_CMDLINE TARGET_NO_KERNEL KERNEL_CONFIG := 0x80000000 := := false := android_omap4_defconfig
Hint: Develop and debug raw drivers on Linux OS, not Android.
15 COPYRIGHT 2012 ALCATEL-LUCENT. ALL RIGHTS RESERVED.
Bionic C Library
- Non POSIX.
Android Init
Proprietary init language based on rules and conditions. Able to spawn services and restart them on failures through signals and sockets. Initialization Steps:
- Creates basic filesystem (/dev, /proc, /sys) and mounts it.
- Parses /init.rc
- Parses /init.${hw_name}.rc based on kernel command-line or /proc/cpuinfo - Build exec queues - Start triggers and associated actions and services.
- e.g. "early-init", "init", "early-fs", "fs", "post-fs", "early-boot", "boot"
Triggers:
- Strings which can be used to match certain kinds of events and used to cause an action to occur.
Services:
- Programs which init launches and (optionally) restarts when they exit.
Options:
- Modifiers to services. They affect how and when init runs the service.
Commands:
- Android proprietary built-in commands.
Description
This is a device-critical service. If it exits more than four times in four minutes, the device will reboot into recovery mode. This service will not automatically start with its class. It must be explicitly started by name. Set the environment variable <name> to <value> in the launched process. Create a unix domain socket named /dev/socket/<name> and pass its fd to the launched process. Change to groupname before exec'ing this service. Do not restart the service when it exits. Specify a class name for the service. All services in a named class may be started or stopped together Execute a Command when service restarts. Set service priority and scheduling class. Output logs on console. Trigger service through keycode in /dev/keychord
disabled
group <groupname> [ <groupname> ]* oneshot class <name> onrestart ioprio <rt|be|idle> <ioprio 0-7> console capability <keycode>
- This is the first trigger that will occur when init starts (after /init.rc is loaded)
<name>=<value>
- Triggers of this form occur when the property <name> is set to the specific value <value>.
device-added-<path>
device-removed-<path>
- Triggers of these forms occur when a device node is added or removed.
service-exited-<name>
- Triggers of this form occur when the specified service exits.
Description
Fork and execute a program (<path>). This will block until the program completes. Set the environment variable <name> equal to <value> in the global environment. Bring the network interface <interface> online. Set the host name. Change working directory. Change file access permissions. Change file owner and group. Change process root directory. Start all services of the specified class if they are not already running. Stop all services of the specified class if they are currently running. Reset a class. Set the domain name. Install the module at <path> Create a directory at <path>, optionally with the given mode, owner, and group. Attempt to mount the named device at the directory <dir>
Description
Set system property <name> to <value>. Set the rlimit for a resource. Start a service running if it is not already running. Stop a service from running if it is currently running. Restart a service from running if it is currently running. Create a symbolic link at <path> with the value <target> Set the system clock base (0 if system clock ticks in GMT) Trigger an event. Used to queue an action from another action. Open the file at <path> and write one or more strings to it. Removes a file. Removes a directory. Wait for file to exist or timeout to be reached. Copy from source to dest. Set kernel log level. Load properties from files in /data/property
23 COPYRIGHT 2012 ALCATEL-LUCENT. ALL RIGHTS RESERVED.
uEventd
Somehow replaces udevd from desktop Linux. Used to set user/group/permissions on /dev nodes. Steps:
- Parses /ueventd.rc - Parses /ueventd.${hw_name}.rc based on kernel command-line or /proc/cpuinfo. - Set nodes permissions.
LCD Display
LCD Display
- LCD 800x480 WVGA 7 (1.667 aspect ratio) => 133 dpi => Phone Mode. - In BoardConfig.mk:
PRODUCT_PROPERTY_OVERRIDES PRODUCT_CHARACTERISTICS += ro.sf.lcd_density=120 := tablet
2D/3D GPU
Input Subsystem
Maps Linux key and axis codes to Android key and axis codes.
Required for all internal (built-in) input devices that have keys, including special keys such as volume, power and headset media keys. Location:
- Located by USB vendor, product (and optionally version) id or by input device name. - The following paths are consulted in order: /system/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl /system/usr/keylayout/Vendor_XXXX_Product_XXXX.kl /system/usr/keylayout/DEVICE_NAME.kl /system/usr/keylayout/Generic.kl /data/system/devices/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl /data/system/devices/keylayout/Vendor_XXXX_Product_XXXX.kl /data/system/devices/keylayout/DEVICE_NAME.kl /data/system/devices/keylayout/Generic.kl
- key - Linux scan code number - Android key code name - [policy flags]
ESCAPE VOLUME_DOWN Q
WAKE VIRTUAL
WAKE
Policy flags:
- WAKE|WAKE_DROPPED:
The key should wake the device when it is asleep.
The key should be interpreted as if the SHIFT key were also pressed. The key should be interpreted as if the CAPS LOCK key were also pressed. The key should be interpreted as if the ALT key were also pressed. The key should be interpreted as if the RIGHT ALT key were also pressed. The key should be interpreted as if the FUNCTION key were also pressed. The key is a virtual soft key that is adjacent to the main touch screen.
Contains device-specific configuration properties that affect the behavior of input devices. Optional for standard peripherals such as HID keyboard and mouse. Mandatory for built-in embedded devices such as touch screens. Location:
- Located by USB vendor, product (and optionally version) id or by input device name.
I2C Touchscreen
input_set_abs_params(input_dev, ABS_X, min_x, max_x, 0, 0); input_set_abs_params(input_dev, ABS_Y, min_y, max_y, 0, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0);
Example of cy8ctmg110.idc:
- # Basic Parameters touch.deviceType = touchScreen touch.orientationAware = 0 # Size touch.size.calibration = none # Orientation touch.pressure.calibration = none
37 COPYRIGHT 2012 ALCATEL-LUCENT. ALL RIGHTS RESERVED.
Storage Subsystem
Audio Subsystem
In BoardConfig.mk:
Low-level kernel drivers work just like a charm up to Linux user-space. For Java apps connectivity, each connection type must register a specific ConnectivityManager and associated ConnectivityService that handles device configuration, packet routing and HTTP(S) proxy settings.
40 COPYRIGHT 2012 ALCATEL-LUCENT. ALL RIGHTS RESERVED.
Ethernet Connectivity
Ethernet connection type exists in ICS API. But with no ConnectivityManager or ConnectivityService implementation.
- => Can't be configured nor used easily through regular Java apps (with exception to the Web Browser). - Experimental ECM patch has been integrated in Linaro ICS.
- Allow low-level device configuration and settings. - Uses Persistent Secure Settings SQLite database. - Doesn't register with ConnectivityManager (i.e "No Internet Connection" symptom). - Doesn't provide HTTP(S) proxy support.
- => To be implemented !! :-(
WiFi Connectivity
WiFi Connectivity
Bluetooth
May requires support in audio HAL for BT A2DP support. libbluedroid implements enables/disables BT interface and creates HCI socket through rfkill (see system/bluetooth/bluedroid).
45 COPYRIGHT 2012 ALCATEL-LUCENT. ALL RIGHTS RESERVED.
Multimedia Subsystem
In media_profiles.xml:
No-Battery Trick
Partial trick for Android to believe its running on power supply (at least on main UI).
- Add new system setting in device.mk:
- PRODUCT_PROPERTY_OVERRIDES += hw.nobattery=true
- Hack on frameworks/base/services/java/com/android/server/BatteryService.java
- String hwNoBatteryStr = SystemProperties.get("hw.nobattery"); boolean hwNoBattery = Boolean.parseBoolean(hwNoBatteryStr); if (!hwNoBattery) mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); private void stubUpdate() { // Hardcode values. We could read them from properties mAcOnline = true; mUsbOnline = false; mBatteryPresent = true; mBatteryLevel = 100; mBatteryVoltage = 4700; mBatteryTemperature = 80; mBatteryStatus = BatteryManager.BATTERY_STATUS_FULL; mPlugType = BatteryManager.BATTERY_PLUGGED_AC; } private synchronized final void update() { if (hwNoBattery) stubUpdate(); else { native_update(); processValues(); } }
47 COPYRIGHT 2012 ALCATEL-LUCENT. ALL RIGHTS RESERVED.
Phone
What's More ?
But that's really another story ... for another day ;-)
Thanks
Thank You