How to add a custom service for Android

Revision as of 14:41, 30 July 2019 by Registered User (Created page with "{{UnderConstruction}} == Article purpose == This article is intended for distribution-creator profile end users (see Which Package better suits your needs for more informa...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Under construction.png Coming soon

1. Article purpose[edit source]

This article is intended for distribution-creator profile end users (see Which Package better suits your needs for more information).

When you develop a new hardware for the device that is not yet supported you need to create your own service to be able to use it.

2. Prerequisites[edit source]

The environment used must have been installed using the right distribution creator Package for your selected microprocessor device. See the list of Android distribution Packages here.

3. Hardware interface[edit source]

First of all you need to create your HIDL files to be able to interact with your hardware. They are interfaces between your hardware and the AOSP. You can refer to the HIDL manual [1].

3.1. Creation[edit source]

To create your interface you need to make a folder "myinterface" into "hardware/interfaces". Then create a version folder for your interface like "hardware/interfaces/myinterface/1.0/".

3.2. HAL[edit source]

Define as many classes and types you need to be able to interact with your hardware. Those functions will need to be implemented on your device HAL folder. (See Implement the vendor HAL)

IClass1.hal

package android.hardware.myinterface@1.0;

interface IClass1 {
    myFunct1() generates (bool ret);
    myFunct2(string name) generates (bool ret, MyType val);
};

types.hal

package android.hardware.myinterface@1.0;

struct MyType {
    uint32_t id;
    bool state;
};

3.3. Generation[edit source]

Android.bp[2]:

hidl_interface {
    name: "android.hardware.myinterface@1.0",
    root: "android.hardware",
    vndk: {
        enabled: true,
    },
    srcs: [
        "types.hal",
        "IClass1.hal",
    ],
    interfaces: [
        "android.hidl.base@1.0",
    ],
    types: [
        "MyType",
    ],
    gen_java: true,
}

3.4. Hash creation[edit source]

This step is not require to make it work but it must be done at least at the end of the developpment. When your interface is done you must execute

hidl-gen -L hash android.hardware.myinterface@1.0 >> hardware/interfaces/current.txt

This will add specific hash matching your hardware interface. It is usede to ensure you use the appropriate one. Don't forget to update the hash as soon as you make changes.

4. AIDL[edit source]

In order to interact with your hardware from an application you need to add to the Android API your own functions.

4.1. Creation[edit source]

To create your API you need to make a folder "myinterface" into "frameworks/base/core/java/android/".

4.2. AIDL[edit source]

Create as many classes you need to define your API. All files need to have aidl extension. For more information on how to create aidl files see[3].

frameworks/base/core/java/android/myinterface/IClass1.aidl

package android.myinterface;

interface IClass1 {
    void myAidlFunct1();
}

Then you need to generate java classes matching your AIDL files. Those functions will be the one expose to the application developer.

frameworks/base/core/java/android/myinterface/Class1.java

package android.myinterface;

import android.util.AndroidException;
import android.util.Log;
import android.util.Slog;
import android.content.Context;
import android.os.RemoteException;

public class Class1 {
    private final Context mContext;
    private final IClass1 mService;

    public Class1(Context ctx, IClass1 service) {
        mContext = ctx;
        mService = service;
    }

    public void myAidlFunct1() {
        try{
            mService.myAidlFunct1();
        } catch (RemoteException ex){
            Slog.e("Class1", "Unable to contact the remote Class1");
        }
    }
}


4.3. Generation[edit source]

To integrate your change you need to adapt Android.bp file in "frameworke/base". Add as many line as you have aidl files.

java_library {
	.
	.
	.
    "core/java/android/copro/IClass1.aidl",
}

4.4. Update API[edit source]

When your interface is well define you need to execute the command:

make update-api

This command will update necessary files to integrate you API inside the AOSP.


5. Implement the vendor HAL[edit source]

Under construction.png Coming soon

?

6. Custom Service[edit source]

To be able to connect everythong together you need to create an independant service that will run in background and reply to request.


6.1. Package apps[edit source]

Create a folder in "packages/apps" witht the name of your service "MyInterfaceService"

prepare the folder structure as follow:

  • AndroidManifest.xml
  • Android.mk
  • src
    • com
      • android
        • myinterfaceservice
          • MyInterfaceServiceApp.java
          • IClass1Impl.java


6.2. Implement service[edit source]

MyInterfaceServiceApp.java

package com.android.myinterfaceservice;

import android.util.Log;
import android.util.Slog;
import android.os.IBinder;

import android.app.Application;
import android.os.ServiceManager;

import android.myinterface.IClass1;

public class MyInterfaceServiceApp extends Application { 
    private static final String REMOTE_SERVICE_NAME = IClass1.class.getName();
    private static final String TAG = "MyInterfaceServiceApp";
    private IBinder mClass1 = null; 

    public void onCreate() {
        super.onCreate();
        Slog.d(TAG, "Build service");
        mClass1 = new IClass1Impl();
        ServiceManager.addService(REMOTE_SERVICE_NAME, mClass1);
    }

    public void onTerminate() {
        super.onTerminate();
    }

}

IClass1Impl.java

package com.android.myinterfaceservice;

import android.util.Log;
import android.util.Slog;

import java.util.ArrayList;
import android.os.RemoteException;

import android.myinterface.IClass1;

import android.hardware.myinterface.V1_0.IClass1;

class IClass1Impl extends IClass1.Stub {
    private static final String TAG = "IClass1Impl";
    private IClass1 mIClass1Hal = null;

    public IClass1Impl() {
        Slog.d(TAG, "Build service");
        try {
            mIClass1Hal = IClass1.getService();
        } catch (Exception e)
        {
            mIClass1Hal = null;
        }
    }

    @Override
    public void myAidlFunct1() throws RemoteException {
        if (mIClass1Hal != null) {
            mIClass1Hal.myFunct1(new IClass1.myFunct1Callback() {

                @Override
                public void onValues(bool ret) {
                    //Do something with ret
                }
            });
        }
    }

6.3. Makefile and manifest[edit source]

Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under,src)
LOCAL_REQUIRED_MODULES := android.hardware.myinterface
LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.myinterface-V1.0-java
LOCAL_PACKAGE_NAME := MyInterfaceService
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PRIVATE_PLATFORM_APIS := true
include $(BUILD_PACKAGE)

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.android.myinterfaceservice"
  android:sharedUserId="android.uid.system">
<application android:name=".MyInterfaceServiceApp"
             android:persistent="true">
 </application>
</manifest>

7. Add to the board[edit source]

To include your new service into the board you need to customize your device.mk.

PRODUCT_PACKAGES += \
        android.hardware.myinterface@1.0-service.stm32mp1 \ #The HAL
        MyInterfaceService #The packages apps service

8. SDK integration[edit source]

When you have finish creating your service you need to reference to How to build and install an SDK in order to rebuild it to include your custom API.

9. References[edit source]