前面文章讲述了Android APP怎么调用hal层的方法,和Android系统自带的灯光子系统类似;本文将讲述hal层如何回调APP应用接口,和android系统振动传感器数据上报类似,同时本文也会将App如何调用hal层接口进行再一次回顾,硬件环境基于amlogic的A311D,android系统9.0
一、首先定义frameworks/base/core/java/android/os/IXxxxListener.aidl回调函数接口,修改了该文件增加或者减少函数接口,需要先执行make update-api,再编译系统
package android.os;
/** {@hide} */
interface IXxxxListener
{
boolean xxxxReport(int param);
}
二、定义frameworks/base/core/java/android/os/IXxxxManager.aidl文件,定义APP控制hal层函数接口,同理增加或者减少函数接口,需要先执行make update-api,再编译系统,注视里面@hide关键字不能少(Android 框架的开发人员需要可见性为 public 或 protected 的类或成员,但又不希望这些方法成为开发者可用的 API,这就是 @hide 的用处了)
package android.os;
import android.os.IXxxxListener;
/** {@hide} */
interface IXxxxManager
{
void setOnListener(IPovodoListener iPovodoListener);
boolean xxxxOpen(); //打开操作
boolean setDevStatus(int status); //设置设备状态
}
在framework/base/Android.mk中添加aidl文件
core/java/android/os/IVibratorService.aidl \
core/java/android/os/IPovodoManager.aidl \
core/java/android/os/IPovodoListener.aidl \
三、定义frameworks/base/services/core/java/com/android/server/XxxxService.java文件,实现Java层服务定义以及函数回调定义实现
import android.os.IXxxxManager;
import android.os.IXxxxListener;
import android.os.XxxxListener;
package com.android.server;
import android.util.Slog;
import android.os.IXxxxManager;
import android.os.IXxxxListener;
import android.os.XxxxListener;
import android.os.Process;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.content.Context;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import android.os.RemoteException;
public class XxxxService extends IXxxxManager.Stub {
private static final String TAG = "XXXX_Service";
static IXxxxListener mIXxxxListener;
public XxxxService () {
Slog.d(TAG, "--XxxxService--");
}
// --回调函数设置
public static boolean xxxxReport(int param) {
try {
mIXxxxListener.xxxxReport(param);
} catch (RemoteException e) {
e.printStackTrace();
}
if (DEBUG_MODE) {
Slog.d(TAG, "--xxxxReport-- end");
}
return true;
}
//控制函数设置
// 打开设备
public boolean xxxxOpen() throws android.os.RemoteException {
return nativeXxxxOpen();
}
@Override //该函数在APP中调用设置回调对象
public void setOnListener(IXxxxListener iXxxxListener) {
/*
* 将注册的回调通过集合来管理,可以实现多客户端 同时监听的功能。
*/
mIXxxxListener = iXxxxListener;
}
public boolean setDevStatus(int status); //设置设备状态
{
return nativeSetDevStatus(status);
}
public static native boolean nativeXxxxOpen();
public static native boolean nativeSetDevStatus(int status);
}
四、定义frameworks/base/core/java/android/os/XxxxListener.java文件,定义回调函数接口
package android.os;
import android.util.Slog;
import android.os.IXxxxListener;
import android.os.Process;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.content.Context;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public interface XxxxListener {
public xxxxReport(int param);
}
五、定义frameworks/base/core/java/android/os/XxxxListenerCallBack.java文件,实现Java层回调调用
package android.os;
import android.os.XxxxListener;
import android.os.XxxxListener;
import android.util.Slog;
import android.os.Process;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.content.Context;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class XxxxListenerCallBack extends IXxxxListener.Stub {
private XxxxListener mXxxxListener;
public XxxxListenerCallBack(XxxxListener xxxxListener) {
mXxxxListener = xxxxListener;
}
@Override
public boolean xxxxReport(int armId) throws RemoteException {
return mXxxxListener.xxxxReport(int param) ;
}
}
六、在frameworks/base/services/java/com/android/server/SystemServer.java文件中,定义XxxxService
private void startOtherServices() {
...
final Context context = mSystemContext;
VibratorService vibrator = null;
XxxxService xxxxService = null;
....
traceBeginAndSlog("StartXxxxService");
xxxxService = new XxxxService();
ServiceManager.addService("xxxx_service", xxxxService);
traceEnd();
.......
}
在frameworks/base/core/java/android/content/Context.java文件中定义服务名
…
public static final String VIBRATOR_SERVICE = "vibrator";
public static final String XXXX_SERVICE = "xxxx_
service";
在frameworks/base/core/java/android/app/SystemServiceRegistry.java文件中添加添加注册服务
.....
import android.os.IXxxxManager;
import android.os.XxxxManager;
.....
registerService(Context.XXXX_SERVICE, XxxxManager.class,
new CachedServiceFetcher<XxxxManager>() {
@Override
public XxxxManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
IXxxxManager service = IXxxxManager.Stub.asInterface(
ServiceManager.getServiceOrThrow(
Context.XXXX_SERVICE));
return new XxxxxManager(service);
}});
七,至此Java层的工作完成,剩下的就是jni和hal层的工作,在frameworks/base/services/core/jni/onload.cpp文件中定义jvm并初始化
...
JavaVM* g_jvm;
....
namespace android {
int register_android_server_XxxxService(JNIEnv* env);
};
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
JNIEnv* env = NULL;
jint result = -1;
g_jvm = vm;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
ALOGE("GetEnv failed!");
return result;
}
ALOG_ASSERT(env, "Could not retrieve the env!");
....
register_android_server_XxxxService(env);
....
}
修改frameworks/base/services/core/jni/Android.mk
$(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp \
$(LOCAL_REL_DIR)/com_android_server_PovodoService.cpp \
创建frameworks/base/services/core/jni/com_android_server_XxxxService.cpp
#include <jni.h>
#include <nativehelper/JNIHelp.h>
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/xxxx_hal.h>
#include <hardware/xxxx_callback.h>
#include <pthread.h>
#include <stdio.h>
#include <hardware/xxxx_common.h>
struct xxxx_device_t *xxxx_dev;
struct xxxx_callback_t xxxx_callBack;
_JNIEnv *g_jenv; //native线程env对象
jobject g_jobj; //全局对象
extern JavaVM *g_jvm;
using namespace FrameWork;
namespace android
{
jmethodID xxxxReport_jmd; //java方法id,可以根据实际情况创建多个
bool xxxxReportCallBack(int armId); //回调函数定义
//定义结构体
class WlListener
{
public:
WlListener(JavaVM *vm, _JNIEnv *jenv, jobject obj);
~WlListener();
};
WlListener *wlListener;
//定义构造函数
WlListener::WlListener(JavaVM *vm, _JNIEnv *env, jobject obj)
{
//初始化回调函数
xxxx_callBack.xxxxReport = xxxxReportCallBack;
//获取类class
jclass clz = env->FindClass("com/android/server/XxxxService");
if (clz == NULL)
{
ALOG(LOG_DEBUG, LOG_TAG, "get jclass wrong");
}
//获取方法ID
xxxxReport_jmd= env->GetStaticMethodID(clz, "xxxxReport ", "(I)Z");
if (!xxxxReport_jmd)
{
ALOG(LOG_DEBUG, LOG_TAG, "get xxxxReport_jmdwrong");
}
}
bool xxxxReport (int param) //回调函数定义
{
//实现函数
return true;
}
pthread_t callBackThreadPid;
//线程执行函数
void *threadFunc(void *data)
{
//在子线程中调用回调方法
JNIEnv *env;
ALOG(LOG_DEBUG, LOG_TAG, "threadFunc start....");
g_jvm->AttachCurrentThread(&env, 0);
jclass clz = env->GetObjectClass(g_jobj);
if (clz == 0)
{
ALOG(LOG_DEBUG, LOG_TAG, "get jclass wrong2");
return NULL;
}
ALOG(LOG_DEBUG, LOG_TAG, "threadFunc start listen....");
while (1)
{
env->CallStaticBooleanMethod(clz, xxxxReport_jmd, 11); //11表示回调函数参数,这里任意写的
}
}
//jni和hal层接口初始化,该函数一般只调用一次
static jboolean xxxxOpen(JNIEnv *env, jobject thiz)
{
hw_module_t *module;
hw_device_t *device;
jint err;
static int sFirstInitFlag = 0;
if (sFirstInitFlag == 0)
{
//JavaVM是虚拟机在JNI中的表示,其他线程回调java层需要用到
env->GetJavaVM(&g_jvm);
// 生成一个全局引用保留下来,以便回调
g_jobj = env->NewGlobalRef(thiz);
err = hw_get_module(XXXX_HARDWARE_MODULE_ID, (hw_module_t const **)&module); //获取到对应的hal中的modules对象,第一个参数为hal层中的id
if (err == 0)
{
ALOG(LOG_DEBUG, LOG_TAG, "--xxxxOpen successful--");
module->methods->open(module, NULL, &device); //获取到hal中的device信息
xxxx_dev = (struct xxxx_device_t *)device;
xxxx_dev->setCallBackFunc(&xxxx_callBack); //设置回调参数
wlListener = new WlListener(g_jvm, env, env->NewGlobalRef(thiz));
}
pthread_create(&callBackThreadPid, NULL, threadFunc, NULL);
ALOG(LOG_DEBUG, LOG_TAG, "--xxxxOpen succeed--");
sFirstInitFlag = 1;
return true;
}
else
{
ALOG(LOG_DEBUG, LOG_TAG, "--xxxxOpen error--");
return false;
}
ALOG(LOG_DEBUG, LOG_TAG, "--xxxxOpen alread open--");
return true;
}
//APP调用hal层函数定义
static jboolean setDevStatus(JNIEnv *env, jobject thiz, int status)
{
if (DEBUG_MODE)
ALOG(LOG_DEBUG, LOG_TAG, "--setDevStatus--");
return xxxx_dev->setDevStatus(status);
}
static JNINativeMethod method_table[] = {
{"nativeXxxxOpen", "()Z", (void *)xxxxOpen}, //第二个参数()参数个数,I-返回值类型
{"nativeSetDevStatus", "(I)Z", (void *)setDevStatus},
}
int register_android_server_XxxxService(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/android/server/XxxxService",
method_table, NELEM(method_table));
}
} ;
八、创建hardware/libhardware/include/hardware/xxxx_callback.h
//自定义一个对外的结构体
struct xxxx_callback_t
{
bool (*xxxxReport)(int param);
};
创建hardware/libhardware/include/hardware/xxxx_hal.h
#include "xxxx_callback.h"
#define XXXX_HARDWARE_MODULE_ID "xxxx"
//自定义一个对外的结构体
struct xxxx_device_t
{
struct hw_device_t xxxx_device;
bool (*setCallBackFunc)(struct xxxx_callback_t *pCallBack);
bool (*setDevStatus)(int status);
};
boolean setDevStatus(int status); //设置设备状态
创建hardware/libhardware/modules/xxxx/xxxx_hal.c
#include <hardware/xxxx_hal.h>
#include <hardware/xxxx_callback.h>
struct xxxx_callback_t *g_xxxxCallBack = NULL;
static struct xxxx_device_t xxxx_dev =
{
.xxxx_device =
{
.tag = HARDWARE_DEVICE_TAG,
},
.setCallBackFunc = setCallBackFunc,
.setDevStatus = setDevStatus,
};
//设置回调函数
bool setCallBackFunc(struct xxxx_callback_t *pCallBack)
{
g_xxxxCallBack = pCallBack;
return true;
}
static int xxxxHalOpen(const struct hw_module_t *module, char const *id, struct hw_device_t **device)
{
(void)module;
(void)id;
static sFirstInitflag
if (sFirstInitflag== 0)
{
*device = (struct hw_device_t *)(&xxxx_dev);
//执行一系列hal层的初始化工作,比如初始化串口,保存日志初始化等等
}
else
{
sFirstInitflag == 1;
}
}
//APP调用hal层接口
bool setDevStatus(int status)
{
return true;
}
//hal层回调APP接口
bool xxxxReport(int param)
{
g_xxxxCallBack->xxxxReport(11); //是参数,根据需要设置
}
//定义HAL_MODULE_INFO_SYM,并对其进行初始化
static hw_module_methods_t xxxx_methods =
{
.open = xxxxHalOpen,
};
struct hw_module_t HAL_MODULE_INFO_SYM =
{
.tag = HARDWARE_MODULE_TAG,
.id = XXXX_HARDWARE_MODULE_ID, //该id起到了承上启下的作用,硬件服务层会匹配该id,一般这里使用宏定义(VIBRATOR_HARDWARE_MODULE_ID),不然可能会出错
.author = "yujd",
.methods = &xxxx_methods,
};
添加hal模块编译信息
hardware/libhardware/modules/Android.mk
build/target/product/generic_no_telephony.mk(不添加的话,默认不会编译生成so库)
做到这步,系统层的工作完成,接下来写测试APP进行测试,测试之前需要先编译系统,生成class.jar包导入到APP工程,编译过程和导入方法在上篇文章有详细介绍,文件路径(out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
out/target/common/obj/JAVA_LIBRARIES/services_intermediates/classes.jar)
九、编写测试APP
package com.xxxx.yujd;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Context;
import android.os.XxxxListener; //导入自定义服务类
import android.os.XxxxManager;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.util.Log;
import java.text.DecimalFormat;
import java.util.List;
import java.util.ArrayList;
import android.app.Dialog;
import android.app.Person;
import android.app.AlertDialog;
public class MainActivity extends AppCompatActivity implements View.OnClickListener, XxxxListener{
private XxxxManager mXxxxManager = null;
//初始化服务对象
mXxxxManager = (XxxxManager)getSystemService(Context.XXXX_SERVICE);//IXxxxManager.Stub.asInterface(ServiceManager.getService("xxxx_service"));
if (mXxxxManager == null) {
Log.i("Xxxx_APP--", "get servcie error");
}else
{
Log.i("Xxxx_APP--", "get servcie success");
}
mXxxxManager.setOnListener(this); //设置回调监听对象
//打开初始化设备
if(mXxxxManager.xxxxOpen() == true){
Log.i("Xxxx_APP", "open successful");
}
else{
Log.i("Xxxx_APP", "open error");
}
//调用hal层方法
if(mXxxxManager.setDevStatus(1) == true){
Log.i("Xxxx_APP", "setDevStatus successful");
}
else{
Log.i("Xxxx_APP", "setDevStatus error");
}
//回调函数-当hal层调用xxxxReport函数调用时,APP层函数xxxxReport就会被调用
public boolean xxxxReport(int param )
{
Log.i("Xxxx_APP","xxxxReport:" + param);
return true;
}
}
到此整个回调流程完成了,如果不准确的地方,欢迎指点,交流QQ:1308418494