Android Hal层回调APP应用接口

前面文章讲述了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

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值