android HIDL HAL控制LED demo(二)之JAVA作客户端

目录

    • 基本环境
    • 演示场景
    • 一、JAVA实现HAL客户端
    • 二、系统配置
    • 参考文献

基本环境

  • 开发板:hikey960 (4G+32G版本)
  • 代码:aosp,android-10.0.0_r33
  • 开发环境:64bit ubuntu 16.04

演示场景

  在app中使用JAVA实现HIDL HAL客户端,从而控制LED的亮灭。HIDL HAL本身的实现以及关键sepolicy的配置,请参考我的上一篇文章《android HIDL HAL控制LED demo(一)之C++作客户端》。
  本文涉及到的关键源码我已释放到github上面:android_drviver_demo/apps/LedCtrlHidlJava/。

一、JAVA实现HAL客户端

① 创建主程序LedCtrlHidlJava/app/src/main/java/com/example/ledctrlhidljava/MainActivity.java代码如下所示。
  第8、9行所示的android.os.RemoteExceptionmy_demo.hardware.led.V1_0.ILed是必须导入的软件包,以使用相应的HIDL HAL接口。第23行调用ILed.getService(true);以在hwservicemanager中索引并获取到我们开发的HIDL HAL接口。第41行led_server.control(1)实际调用了自己实现的HIDL HAL接口。
  如第21、37行所示,在调用HIDL HAL接口时必须要捕捉或抛出RemoteException异常,可选地捕捉或抛出NoSuchElementException异常,否则编译时会报错。

package com.example.ledctrlhidljava;                                                                                                                                                                        [2/1808]

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.os.RemoteException;
import my_demo.hardware.led.V1_0.ILed;

public class MainActivity extends Activity {
    private final String TAG = "LedCtrlHidlJava";
    private Button btn_led = null;
    private ILed led_server;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        try {
            Log.d(TAG, "get led hidl service:");
            led_server = ILed.getService(true);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        Log.d(TAG, "done");
    }

    public void initView() {
        btn_led = (Button) findViewById(R.id.btn_led);
    }

    public void onClickLed(View v) {
        int ret;

        try {
            if (btn_led.getText().equals("开灯") ) {
                Log.d(TAG, "turn on led");
                btn_led.setText("关灯");
                if ( led_server.control(1) < 0 ) {
                    Log.e(TAG, "led_server.control(0) failed");
                }

            } else {
                Log.d(TAG, "turn off led");
                btn_led.setText("开灯");
                if ( led_server.control(0) < 0 ) {
                    Log.e(TAG, "led_server.control(1) failed");
                }
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Exception in led_server.control() " + e);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}

② 创建app布局文件LedCtrlHidlJava/app/src/main/res/layout/activity_main.xml,界面较为简单,只有一个用来控制LED亮灭的按钮。


<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn_led"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="开灯"
        android:textSize="@android:dimen/app_icon_size"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:onClick="onClickLed"/>

androidx.constraintlayout.widget.ConstraintLayout>

③ 创建控制编译的LedCtrlHidlJava/Android.bp文件内容如下。
  第13行的"my_demo.hardware.led-V1.0-java"是HIDL HAL生成用于实现HIDL JAVA客户的静态库,注意其格式。

android_app {
    name: "LedCtrlHidlJava",
    certificate: "platform",
    //product_specific: true,
    srcs: ["app/src/main/java/**/*.java"],

    resource_dirs: ["app/src/main/res"],
    manifest: "app/src/main/AndroidManifest.xml",

    static_libs: [
        "androidx-constraintlayout_constraintlayout",
        "androidx-constraintlayout_constraintlayout-solver",
        "my_demo.hardware.led-V1.0-java",
    ],

    optimize: {
        enabled: false,
    },
    //sdk_version: "current",
    dex_preopt: {
        enabled: false,
    },
}

注意:第19行的sdk_version: "current"要注释掉,否则在编译时会报如下错误。原因在于当执行sdk_version: "current"或者LOCAL_SDK_VERSION := current项编译时,编译系统会忽略源码隐藏的API,故在源码中引用带@hide api标注的接口会导致编译失败。

my_demo/apps/LedCtrlHidlJava/app/src/main/java/com/example/ledctrlhidljava/MainActivity.java:23: error: cannot access IHwInterface
            led_server = ILed.getService(true);
                             ^
  class file for android.os.IHwInterface not found
1 error
[ 96% 460/475] Generating out/target/product/hikey960/module-info.json
ninja: build stopped: subcommand failed.
19:43:49 ninja failed with: exit status 1

二、系统配置

① selinux权限的配置
  APP关于selinux权限的配置我已经在文章《android HIDL HAL控制LED demo(一)之C++作客户端》的“系统配置”章节已提到;在这里再说明一遍:上面的Android.bp中已经将app用签名成platfrom_app,所以需要修改文件device/linaro/hikey/sepolicy/platform_app.te附加如下代码,该APP才能调用HIDL HAL接口。

allow platform_app hal_led_hwservice:hwservice_manager { find };
allow platform_app hal_led_default:binder { call };

② 把APP添加到板级项目配置的PRODUCT_PACKAGES中,它才真正被编进system镜像。配置文件device/linaro/hikey/hikey960/device-hikey960.mk加入如下内容:

PRODUCT_PACKAGES += LedCtrlHidlJava

参考文献

  1. 《Android.mk文件LOCAL_SDK_VERSION选项》
  2. aosp的HIDL JAVA的介绍

你可能感兴趣的:(github,Android)