Upgrade to Pro — share decks privately, control downloads, hide ads and more …

droidconfr2013-discover-embedded-linux-with-android

 droidconfr2013-discover-embedded-linux-with-android

Talk given at droidcon fr 2013
http://fr.droidcon.com/2013/sessions/genymobile/

Code sample are available:
https://github.com/CedricCabessa/droidconfr2013

Video:
http://www.youtube.com/watch?v=BgP-QjjWCfA

slide 1 to 37 have speaker notes
slide 38 to the end are the same without speaker notes (download pdf to have correct ratio, speakerdeck do not support slide rotation)

Cédric Cabessa

June 17, 2013
Tweet

More Decks by Cédric Cabessa

Other Decks in Programming

Transcript

  1. Discover embedded Linux
    with Android
    Cédric Cabessa
    [email protected]

    View Slide

  2. Introduction
    Android is for mass market. Ecosystem is oriented toward multimedia content and
    consumer.
    Money is made selling games, music and so on.

    View Slide

  3. Introduction
    On the other hand, embedded linux is used to create everykind of project, you have
    drivers for everything, you can plug any devices you want.
    The "hdtv blueray microwave washing machine" come from the Yocto-project

    View Slide

  4. Introduction
    Can we keep Android with it's UI, its fully integrated API and yet use it to build our
    own embedded system ?

    View Slide

  5. Introduction
    Android IS Linux

    View Slide

  6. The Question
    ● How to modify Android to support a new hardware /
    new features without asking Google.
    ● Android Style
    You have a dev board (like a pandaboard) with Android. You want to plug a new
    device (gpio, i2c, rs232, ...).
    How to use it with an Android like API

    View Slide

  7. Case study

    http://source.android.com

    Nexus

    Pandaboard

    Manufacturer support
    Android is opensource (AOSP), it is fairly easy to grab the source and build your own
    ROM (if you have hardware support: nexus or dev board with manufacturer support).

    View Slide

  8. Case study
    ● Let's play with hardware !

    View Slide

  9. Case study
    ● Character device: /dev/droidcon
    ● Convert upper case to lower case, in kernel land!
    In linux, most of the drivers are exposed through the "/dev" fiilesystem.
    To send data to the driver, you simply open the file and write to it.
    In real life, we assume you already have a driver for your device

    View Slide

  10. Case study
    We assume we have a support for linux (driver) for our new hardware, we want to
    create applications that use it.
    We have to patch every layer from kernel to framework

    View Slide

  11. Kernel / Driver

    Not part of AOSP

    Driver can be built with the kernel

    Or as a seperate module (.ko)

    GPLv2
    Driver is provided by your board manufacturer (kernel) or as a module from your
    device provider.
    Of course you can write your own if you have a custom device.

    View Slide

  12. Kernel / Driver

    init.rc
    on boot
    insmod /system/lib/modules/droidcon.ko
    chown system system /dev/droidcon
    chmod 0600 /dev/droidcon

    device///device.mk
    PRODUCT_COPY_FILES := \
    device///droidcon.ko:system/lib/modules/droidcon.ko

    View Slide

  13. Kernel / Driver

    Try it (connect as root)
    adb shell
    # ls -l /dev/droidcon
    crw------- system system 249, 0 droidcon
    # echo Hello > /dev/droidcon
    # cat /dev/droidcon
    hELLO
    #
    with real world devices, it is hard to check everything works just after loading the
    module

    View Slide

  14. Kernel / Driver

    Our device is only usable by 'system'

    Run our app as system? => NO

    system_server use the device

    App communicate with system_server
    We will have to create permissions

    View Slide

  15. HAL
    We simply load the driver and check permission. It's time to use it.
    Hardware Abstraction Layer

    View Slide

  16. HAL

    C library

    Talk to driver

    Expose hardware feature

    Often closed source :-(
    expose hardware feature:
    driver can only support read / write, HAL should expose more advanced semantics
    that are implemented using read/write/...
    ex: usb missile launcher:
    HAL: missile_launch()
    Driver: write(/dev/foo, 42)

    View Slide

  17. HAL

    hardware/droidcon/lib

    libdroidcon.h
    ssize_t droidcon_getdata(void *buf, size_t count);
    ssize_t droidcon_putdata(const void *buf, size_t count);
    void droidcon_clear(void);

    Do complicated thing here!
    And only here
    The driver only support open / read / write / close.
    We create a "droidcon_clear" function, this semantic make sense from a driver user
    point of view. In fact it is implemented as write(fd, 0, 0)
    ==> intelligent stuff go here

    View Slide

  18. JNI
    Hal is C, System Service is java
    => jni

    View Slide

  19. JNI

    frameworks/base/core/java/android/droidcon/
    LibDroidcon.java
    package android.droidcon;
    public class LibDroidcon {
    public native static void clear();
    public native static String getData() throws DroidconException;
    public native static void putData(String in) throws DroidconException;
    static {
    System.loadLibrary("droidcon_jni");
    }
    }
    Rem: we hack framework! May be we could separate our change from the standard
    android, but we will have to modify SystemServer so can't stay really separated.

    View Slide

  20. JNI

    hardware/droidcon/jni/
    android_droidcon_LibDroidcon.c
    JNIEXPORT void JNICALL Java_android_droidcon_LibDroidcon_putData
    (JNIEnv *env,
    jclass cls, jstring string)
    {
    int ret;
    const char *buff = (*env)->GetStringUTFChars(env, string, NULL);
    int length = (*env)->GetStringLength(env, string);
    ret = droidcon_putdata(buff, length);
    if (ret < 0) {
    ThrowDroidconException(env, "fail to put data");
    }
    (*env)->ReleaseStringUTFChars(env, string, buff);
    }

    View Slide

  21. JNI

    Tip for testing:

    Add a Main.java in android.droidcon
    public class Main {
    public static void main (String[] args) {
    try {
    LibDroidcon.putData("Hello");
    String out = LibDroidcon.getData();
    System.out.println(out);
    LibDroidcon.clear();
    } catch (DroidconException e) {
    Log.d("droidcon", e.toString());
    }
    }
    }

    Run it with the shell
    # dalvikvm android.droidcon.Main
    hELLO

    View Slide

  22. System Service
    Now we can use our HAL from java.
    SystemService run as system.
    When you use context.getSystemService(...) you only get a proxy that send command
    through binder IPC to the SystemService.
    System Service do the real work and check permission.

    View Slide

  23. System Service

    Must implement a Binder interface

    framework/base/droidcon/java/android/droidcon/
    IDroidconManager.aidl
    package android.droidcon;
    /** {@hide} */
    interface IDroidconManager
    {
    void clear();
    String getData();
    void putData(String data);
    }
    Declare every methods the client (framework) can call on the server (System Service)
    Can't throw exception here. Use return code or something else.

    View Slide

  24. System Service

    frameworks/base/services/java/com/android/server/
    DroidconService.java

    View Slide

  25. System Service
    package com.android.server;
    /** @hide */
    class DroidconService extends IDroidconManager.Stub {
    public String getData() {
    enforceAccessPermission();
    try {
    return LibDroidcon.getData();
    } catch(DroidconException e) {
    Slog.d(TAG, "cannot getdata");
    }
    return null;
    }
    private void enforceAccessPermission() {
    mContext.enforceCallingOrSelfPermission(
    android.Manifest.permission.DROIDCON_ACCESS,
    "DroidconService");
    }
    IDroidconManager.Stub is automatically generated from IDroidconManager.aidl
    Check for exception here and return
    Enforce permission (framework/base/core/res/AndroidManifest.xml)

    View Slide

  26. System Service

    Hack SystemServer.java
    public void run() {
    [...]
    try {
    Slog.i(TAG, "Droidcon Service");
    droidconService = new DroidconService(context);
    ServiceManager.addService(Context.DROIDCON_SERVICE,
    droidconService);
    } catch (Throwable e) {
    reportWtf("starting Droidcon Service", e);
    }

    View Slide

  27. Framework
    DroidconService is launched at startup. It listen to a Binder interface.
    We have to write the client side: Framework

    View Slide

  28. Framework

    framework/base/droidcon/java/android/droidcon
    DroidconManager.java
    public class DroidconManager {
    IDroidconManager mService;
    /** @hide */
    public DroidconManager(IDroidconManager service) {
    mService = service;
    }
    public String getData() {
    try {
    return mService.getData();
    } catch (RemoteException e) {
    e.printStackTrace();
    }
    return null;
    }
    Do nothing but calling methods through the binder interface (and checking return
    value)

    View Slide

  29. Framework

    Hack ContextImpl.java
    class ContextImpl extends Context {
    static {
    [...]
    registerService(DROIDCON_SERVICE, new ServiceFetcher() {
    public Object createService(ContextImpl ctx) {
    IBinder b = ServiceManager.getService(DROIDCON_SERVICE);
    IDroidconManager service = IDroidconManager.Stub.asInterface
    (b);
    return new DroidconManager(service);
    }});

    View Slide

  30. Framework

    Create a new SDK

    make update-api

    make sdk

    Configure eclipse

    View Slide

  31. Framework

    package="com.example.droidcon"
    android:versionCode="1"
    android:versionName="1.0" >

    ● AndroidManifest.xml

    View Slide

  32. Framework

    View Slide

  33. Framework

    View Slide

  34. Framework

    View Slide

  35. Conclusion

    Hardware support is not an excuse to not choose
    Android

    Kernel Driver and HAL should be re-usable

    Upper layers are mostly "glue code"

    Fragmentation?

    View Slide

  36. References
    ● Remixing Android
    http://marakana.com/s/post/1044/remixing_android
    ● Adding System Service
    http://processors.wiki.ti.com/index.php/Android-
    Adding_SystemService

    View Slide

  37. Q&A
    Genymobile SAS - 41, rue Meslay 75003 PARIS - 01 83 64 25 40
    www.genymobile.com
    QUESTIONS ?
    Cédric Cabessa
    [email protected]
    https://speakerdeck.com/cedriccabessa/
    droidconfr2013-discover-embedded-linux-with-android
    https://github.com/CedricCabessa/droidconfr2013

    View Slide

  38. Discover embedded Linux
    with Android
    Cédric Cabessa
    [email protected]

    View Slide

  39. Introduction

    View Slide

  40. Introduction

    View Slide

  41. Introduction

    View Slide

  42. Introduction

    View Slide

  43. The Question
    ● How to modify Android to support a new hardware /
    new features without asking Google.
    ● Android Style

    View Slide

  44. Case study

    http://source.android.com

    Nexus

    Pandaboard

    Manufacturer support

    View Slide

  45. Case study
    ● Let's play with hardware !

    View Slide

  46. Case study
    ● Character device: /dev/droidcon
    ● Convert upper case to lower case, in kernel land!

    View Slide

  47. Case study

    View Slide

  48. Kernel / Driver

    Not part of AOSP

    Driver can be built with the kernel

    Or as a seperate module (.ko)

    GPLv2

    View Slide

  49. Kernel / Driver

    init.rc
    on boot
    insmod /system/lib/modules/droidcon.ko
    chown system system /dev/droidcon
    chmod 0600 /dev/droidcon

    device///device.mk
    PRODUCT_COPY_FILES := \
    device///droidcon.ko:system/lib/modules/droidcon.ko

    View Slide

  50. Kernel / Driver

    Try it (connect as root)
    adb shell
    # ls -l /dev/droidcon
    crw------- system system 249, 0 droidcon
    # echo Hello > /dev/droidcon
    # cat /dev/droidcon
    hELLO
    #

    View Slide

  51. Kernel / Driver

    Our device is only usable by 'system'

    Run our app as system? => NO

    system_server use the device

    App communicate with system_server

    View Slide

  52. HAL

    View Slide

  53. HAL

    C library

    Talk to driver

    Expose hardware feature

    Often closed source :-(

    View Slide

  54. HAL

    hardware/droidcon/lib

    libdroidcon.h
    ssize_t droidcon_getdata(void *buf, size_t count);
    ssize_t droidcon_putdata(const void *buf, size_t count);
    void droidcon_clear(void);

    Do complicated thing here!
    And only here

    View Slide

  55. JNI

    View Slide

  56. JNI

    frameworks/base/core/java/android/droidcon/
    LibDroidcon.java
    package android.droidcon;
    public class LibDroidcon {
    public native static void clear();
    public native static String getData() throws DroidconException;
    public native static void putData(String in) throws DroidconException;
    static {
    System.loadLibrary("droidcon_jni");
    }
    }

    View Slide

  57. JNI

    hardware/droidcon/jni/
    android_droidcon_LibDroidcon.c
    JNIEXPORT void JNICALL Java_android_droidcon_LibDroidcon_putData
    (JNIEnv *env,
    jclass cls, jstring string)
    {
    int ret;
    const char *buff = (*env)->GetStringUTFChars(env, string, NULL);
    int length = (*env)->GetStringLength(env, string);
    ret = droidcon_putdata(buff, length);
    if (ret < 0) {
    ThrowDroidconException(env, "fail to put data");
    }
    (*env)->ReleaseStringUTFChars(env, string, buff);
    }

    View Slide

  58. JNI

    Tip for testing:

    Add a Main.java in android.droidcon
    public class Main {
    public static void main (String[] args) {
    try {
    LibDroidcon.putData("Hello");
    String out = LibDroidcon.getData();
    System.out.println(out);
    LibDroidcon.clear();
    } catch (DroidconException e) {
    Log.d("droidcon", e.toString());
    }
    }
    }

    Run it with the shell
    # dalvikvm android.droidcon.Main
    hELLO

    View Slide

  59. System Service

    View Slide

  60. System Service

    Must implement a Binder interface

    framework/base/droidcon/java/android/droidcon/
    IDroidconManager.aidl
    package android.droidcon;
    /** {@hide} */
    interface IDroidconManager
    {
    void clear();
    String getData();
    void putData(String data);
    }

    View Slide

  61. System Service

    frameworks/base/services/java/com/android/server/
    DroidconService.java

    View Slide

  62. System Service
    package com.android.server;
    /** @hide */
    class DroidconService extends IDroidconManager.Stub {
    public String getData() {
    enforceAccessPermission();
    try {
    return LibDroidcon.getData();
    } catch(DroidconException e) {
    Slog.d(TAG, "cannot getdata");
    }
    return null;
    }
    private void enforceAccessPermission() {
    mContext.enforceCallingOrSelfPermission(
    android.Manifest.permission.DROIDCON_ACCESS,
    "DroidconService");
    }

    View Slide

  63. System Service

    Hack SystemServer.java
    public void run() {
    [...]
    try {
    Slog.i(TAG, "Droidcon Service");
    droidconService = new DroidconService(context);
    ServiceManager.addService(Context.DROIDCON_SERVICE,
    droidconService);
    } catch (Throwable e) {
    reportWtf("starting Droidcon Service", e);
    }

    View Slide

  64. Framework

    View Slide

  65. Framework

    framework/base/droidcon/java/android/droidcon
    DroidconManager.java
    public class DroidconManager {
    IDroidconManager mService;
    /** @hide */
    public DroidconManager(IDroidconManager service) {
    mService = service;
    }
    public String getData() {
    try {
    return mService.getData();
    } catch (RemoteException e) {
    e.printStackTrace();
    }
    return null;
    }

    View Slide

  66. Framework

    Hack ContextImpl.java
    class ContextImpl extends Context {
    static {
    [...]
    registerService(DROIDCON_SERVICE, new ServiceFetcher() {
    public Object createService(ContextImpl ctx) {
    IBinder b = ServiceManager.getService(DROIDCON_SERVICE);
    IDroidconManager service = IDroidconManager.Stub.asInterface
    (b);
    return new DroidconManager(service);
    }});

    View Slide

  67. Framework

    Create a new SDK

    make update-api

    make sdk

    Configure eclipse

    View Slide

  68. Framework

    package="com.example.droidcon"
    android:versionCode="1"
    android:versionName="1.0" >

    ● AndroidManifest.xml

    View Slide

  69. Framework

    View Slide

  70. Framework

    View Slide

  71. Framework

    View Slide

  72. Conclusion

    Hardware support is not an excuse to not choose
    Android

    Kernel Driver and HAL should be re-usable

    Upper layers are mostly "glue code"

    Fragmentation?

    View Slide

  73. References
    ● Remixing Android
    http://marakana.com/s/post/1044/remixing_android
    ● Adding System Service
    http://processors.wiki.ti.com/index.php/Android-
    Adding_SystemService

    View Slide

  74. Q&A
    Genymobile SAS - 41, rue Meslay 75003 PARIS - 01 83 64 25 40
    www.genymobile.com
    QUESTIONS ?
    Cédric Cabessa
    [email protected]
    https://speakerdeck.com/cedriccabessa/
    droidconfr2013-discover-embedded-linux-with-android
    https://github.com/CedricCabessa/droidconfr2013

    View Slide