赞
踩
前面文章讲述了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
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。