2021-04-27 Android 理解frameworks services jni hardware kernel 整个控制过程实例包括回调
Android 理解frameworks services jni hardware kernel 整个控制过程实例包括回调
一、这个例子的实现的功能是,app控制power pin和control pin,可以read feedback pin的电平,如果feedback pin的电平有变化,会触发中断,底层把这个中断信息通过一系列回调和侦听发送到app。
通过这个简单的实例可以了解frameworks services jni hardware kernel整个流程,里面涉及到回调和侦听还是需要花费很多精力去理解和调试。
二、kernel 驱动\kernel\drivers\char\moneybox.c,获取中断,控制gpio,提供杂项设备节点 /dev/moneybox以及下面3个控制节点
/sys/devices/platform/moneybox/enpower
/sys/devices/platform/moneybox/control
/sys/devices/platform/moneybox/feedback
三、hardware 主要代码下面的代码
hardware/libhardware/include/hardware/moneybox.hhardware/libhardware/modules/Android.mkhardware/libhardware/modules/moneybox/Android.mkhardware/libhardware/modules/moneybox/moneybox.cpp
3.1 moneybox.cpp代码
3.2 moneybox.h代码
#ifndef ANDROID_FREG_INTERFACE_H
#define ANDROID_FREG_INTERFACE_H#include <hardware/hardware.h>__BEGIN_DECLS/*** The id of this module*/
#define MONEYBOX_HARDWARE_MODULE_ID "moneybox"/*** The id of this device*/
#define MONEYBOX_HARDWARE_DEVICE_ID "moneybox"struct moneybox_module_t {struct hw_module_t common;
};/* Callback function type */
typedef void (*moneybox_notify_t)(int m,int n);struct moneybox_device_t {struct hw_device_t common;int fd;moneybox_notify_t notify;int (*set_val)(struct moneybox_device_t* dev, int val);int (*set_enable_power)(struct moneybox_device_t* dev, int val);int (*set_control_val)(struct moneybox_device_t* dev, int val);int (*get_feedback_val)(struct moneybox_device_t* dev, int* val);int (*set_notify)(struct moneybox_device_t *dev, moneybox_notify_t notify);
};__END_DECLS#endif
四、JNI代码frameworks/base/services/core/jni/com_android_server_MoneyboxService.cpp
#define LOG_TAG "MoneyboxServiceJNI"#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/moneybox.h>
#include <utils/Looper.h>
#include <android_os_MessageQueue.h>#include <stdio.h>static jobject mCallbacksObj = NULL;
static jmethodID javaCallback;JNIEnv* m_env;
jobject mobj;
jclass jSdkClass;jobject g_jobj; //全局对象namespace android
{static void moneybox_setVal(JNIEnv* env, jobject clazz, jint ptr, jint value) {moneybox_device_t* device = (moneybox_device_t*)ptr;if(!device) {ALOGE("Device moneybox is not open.");return;} int val = value;ALOGI("Set value %d to device moneybox.", val);device->set_val(device, val);}
static void moneybox_set_enable_power(JNIEnv* env, jobject clazz, jint ptr, jint value) {moneybox_device_t* device = (moneybox_device_t*)ptr;if(!device) {ALOGE("Device moneybox is not open.");return;} int val = value;device->set_enable_power(device, val);ALOGI("Set value %d to device moneybox.", val);}static void moneybox_set_control_val(JNIEnv* env, jobject clazz, jint ptr, jint value) {int val = value;moneybox_device_t* device = (moneybox_device_t*)ptr;if(!device) {ALOGE("Device moneybox is not open.");return;} device->set_control_val(device, val);ALOGI("Set value %d to device moneybox.", val);}static inline int moneybox_device_open(const hw_module_t* module, struct moneybox_device_t** device) {return module->methods->open(module, MONEYBOX_HARDWARE_DEVICE_ID, (struct hw_device_t**)device);}
// Called by the HAL to notify us of moneybox eventsstatic void hal_notify_callback(int m,int n) {JNIEnv* env = AndroidRuntime::getJNIEnv();if (!mCallbacksObj)return;jclass clz = env->GetObjectClass(mCallbacksObj);jint ret = env->CallStaticIntMethod(clz, javaCallback,(jint)m,(jint)n);ALOGI("hal_notify_callback ,m=%d,n=%d,ret=%d.",m,n,ret);}static jint moneybox_get_feedback_val(JNIEnv* env, jobject clazz, jint ptr) {int val = 0;moneybox_device_t* device = (moneybox_device_t*)ptr;if(!device) {ALOGE("Device moneybox is not open.");return 0;}device->get_feedback_val(device, &val);ALOGI("Get Value %d from device moneybox....", val);#if 0 if (!mCallbacksObj)mCallbacksObj = env->NewGlobalRef(clazz);jclass clz = env->GetObjectClass(mCallbacksObj);//jint ret = env->CallIntMethod(mCallbacksObj, javaCallback,(jint)val,(jint)val);jint ret = env->CallStaticIntMethod(clz, javaCallback,(jint)val,(jint)val);if (env->ExceptionCheck()) {ALOGE("An exception was thrown by callback");env->ExceptionClear();}ALOGI(" CallIntMethod mCallbacksObj env ret=%d",ret);#endif return val;}static jint moneybox_init(JNIEnv* env, jobject clazz) {int err;moneybox_module_t* module;moneybox_device_t* device;ALOGI("Initializing HAL stub moneybox......");if(hw_get_module(MONEYBOX_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {ALOGI("Device moneybox found.");if(moneybox_device_open(&(module->common), &device) == 0) {ALOGI("Device moneybox is Opened.");err=device->set_notify(device, hal_notify_callback);if (err < 0) {ALOGE("Failed in call to set_notify(), err=%d", err);}elseALOGI("Call to set_notify successfully!");if (!mCallbacksObj)mCallbacksObj = env->NewGlobalRef(clazz);ALOGI("moneybox_device_open successfully!");return (jint)device;}ALOGE("Failed to open device moneybox.");return 0;}ALOGE("Failed to get HAL stub moneybox.");return 0; }
static void moneybox_class_init_native(JNIEnv* env, jclass clazz) {ALOGE("moneybox_class_init_native GetMethodID moneybox_callback");//javaCallback = env->GetMethodID(clazz, "moneybox_callback", "(II)I");javaCallback = env->GetStaticMethodID(clazz, "moneybox_callback", "(II)I");
}static const JNINativeMethod method_table[] = {{"class_init_native", "()V", (void *)moneybox_class_init_native},{"init_native", "()I", (void*)moneybox_init},{"setVal_native", "(II)V", (void*)moneybox_setVal},{"set_enable_power_native", "(II)V", (void*)moneybox_set_enable_power},{"set_control_val_native", "(II)V", (void*)moneybox_set_control_val},{"get_feedback_val_native", "(I)I", (void*)moneybox_get_feedback_val},
};int register_android_server_MoneyboxService(JNIEnv *env) {int res = jniRegisterNativeMethods(env, "com/android/server/MoneyboxService", method_table, NELEM(method_table));/*jclass clazz;clazz=env->FindClass("com/android/server/MoneyboxService");javaCallback = env->GetMethodID(clazz, "moneybox_callback", "(II)I");*/ALOGI("register_android_server_MoneyboxService");return res;
}};
五、frameworks/base/services/core/jni/onload.cpp注册jni
int register_android_server_MoneyboxService(JNIEnv* env);
六、添加服务文件frameworks/base/services/core/java/com/android/server/MoneyboxService.java
七,添加manager文件, frameworks/base/core/java/android/os/SystemMoneybox.java ,提供api个app
八、添加服务frameworks/base/services/java/com/android/server/SystemServer.java
try {traceBeginAndSlog("Moneybox Service");ServiceManager.addService("moneybox", new MoneyboxService(context));} catch (Throwable e) {Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);}
九、注册服务 frameworks/base/core/java/android/app/SystemServiceRegistry.java
registerService(Context.MONEYBOX_SERVICE, SystemMoneybox.class,new CachedServiceFetcher<SystemMoneybox>() {@Overridepublic SystemMoneybox createService(ContextImpl ctx) {//return new SystemMoneybox(ctx);//ctx.mMainThread.getHandler().getLooper()return new SystemMoneybox(ctx,ctx.mMainThread.getHandler().getLooper());}});
十、添加frameworks/base/core/java/android/os/IMoneyboxService.aidl进行跨进行binder通信
package android.os;import android.os.IMoneyboxTListener;interface IMoneyboxService {void setVal(int val);void set_enable_power(int val);void set_control_val(int val);int get_feedback_val();void registerListener(IMoneyboxTListener listener);
}
十一、添加frameworks/base/core/java/android/os/IMoneyboxTListener.aidl用于回调binder通信
package android.os;import android.os.Bundle;oneway interface IMoneyboxTListener
{void onMoneyboxChanged(int i);
}
十二、添加frameworks/base/location/java/android/location/MoneyboxListener.java 用于侦听
/** Copyright (C) 2008 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package android.location;import android.os.Bundle;/*** Used for receiving notifications from the LocationManager when* the location has changed. These methods are called if the* LocationListener has been registered with the location manager service* using the {@link LocationManager#requestLocationUpdates(String, long, float, LocationListener)}* method.** <div class="special reference">* <h3>Developer Guides</h3>* <p>For more information about identifying user location, read the* <a href="{@docRoot}guide/topics/location/obtaining-user-location.html">Obtaining User* Location</a> developer guide.</p>* </div>*/
public interface MoneyboxListener {void onMoneyboxChanged(int i);
}
十三、frameworks/base/Android.mk添加下面内容
core/java/android/os/IMoneyboxService.aidl \
core/java/android/os/IMoneyboxTListener.aidl \
十四、APP demo,app通过下面两种方法调用系统服务。
IMoneyboxService.Stub.asInterface( ServiceManager.getService("moneybox"));
或者
(SystemMoneybox) getSystemService("moneybox");
十五、make update-api更新api,mmm frameworks/base/services/、mmm frameworks/base/编译出framework.jar、services.jar和libandroid_servers.so(jni),push到机器运行测试
15.1、执行service list查看该服务是否已经start。
15.2、确认是否已经生成杂项设备节点和平台总线控制node。
xxx:/ # ls -l /dev/moneybox
crwxrwxrwx 1 root root 10, 60 2021-04-27 00:26 /dev/moneybox
xxx:/ # ls /sys/devices/platform/moneybox/
control driver driver_override enpower feedback modalias of_node power subsystem uevent
xxx:/ #
15.3、运行demo app
15.3、点击demo里面的button调用framework接口,然后通过servies,jni、hardware、kernel控制gpio,然后feedback gpio电平有变化的时候会通过一系列回调传数据到app,看下面的log,
所有的通路都是测试ok。
十六、整个过程涉及到下面的文件。
DEMO APP代码在Moneyboxapp目录下,用mmm进行编译
A packages/apps/Moneyboxapp/Android.mk
A packages/apps/Moneyboxapp/AndroidManifest.xml
A packages/apps/Moneyboxapp/res/drawable/icon.png
A packages/apps/Moneyboxapp/res/layout/main.xml
A packages/apps/Moneyboxapp/res/values/strings.xml
A packages/apps/Moneyboxapp/src/giada/ibc/moneybox/Moneybox.javaFramework涉及到的代码:
M device/rockchip/rk3288/device.mk
M frameworks/base/Android.mk
M frameworks/base/core/java/android/app/SystemServiceRegistry.java
M frameworks/base/core/java/android/content/Context.java
A frameworks/base/core/java/android/os/IMoneyboxService.aidl
A frameworks/base/core/java/android/os/IMoneyboxTListener.aidl
A frameworks/base/core/java/android/os/SystemMoneybox.java
A frameworks/base/location/java/android/location/MoneyboxListener.java
A frameworks/base/services/core/java/com/android/server/MoneyboxService.java
M frameworks/base/services/core/jni/Android.mk
A frameworks/base/services/core/jni/com_android_server_MoneyboxService.cpp
M frameworks/base/services/core/jni/onload.cpp
M frameworks/base/services/java/com/android/server/SystemServer.javahardware的代码:
A hardware/libhardware/include/hardware/moneybox.h
M hardware/libhardware/modules/Android.mk
A hardware/libhardware/modules/moneybox/Android.mk
A hardware/libhardware/modules/moneybox/moneybox.cpp底层驱动涉及到的代码:
M device/rockchip/common/init.connectivity.rc
M kernel/arch/arm/boot/dts/rk3288-giada-jhs66l-act8846.dts
M kernel/drivers/char/Makefile
A kernel/drivers/char/moneybox.c
十七、源码下载路径 frameworks_services_jni_hardware_kernel.zip-Linux文档类资源-CSDN下载 包含所有的文件。
十八、饮水思源,参考文章:
1、android 创建一个实时监听的系统Service
android 创建一个实时监听的系统Service_lz强的博客-CSDN博客_android 监听service
2、安卓硬件服务实例:手把手教你如何从驱动到应用添加硬件服务
安卓硬件服务实例:手把手教你如何从驱动到应用添加硬件服务_kavin.zhu的博客-CSDN博客_安卓硬件驱动
3、Android Hal层回调APP应用接口
Android Hal层回调APP应用接口_yujd的博客-CSDN博客
4、Android硬件服务框架实例之Vibrator(驱动到应用)
Android硬件服务框架实例之Vibrator(驱动到应用)_kavin.zhu的博客-CSDN博客_android振动代码
5、https://www.jianshu.com/p/0f46a95d576f (Android 添加一个系统服务的完整流程(SystemService))
2021-04-27 Android 理解frameworks services jni hardware kernel 整个控制过程实例包括回调相关推荐
- Russ Cox:这不是Go项目的标准布局 | Gopher Daily (2021.04.28) ʕ◔ϖ◔ʔ
每日一谚:Profile before you decide something is performance critical. Go技术生态 Go web开发的当前状态 - https://tno ...
- I.MX6 Android frameworks services 文件架构
/******************************************************************************** I.MX6 Android fram ...
- ubuntu-18.04.4 Android系统源码TP1A(Android 13)下载及编译
继上一篇博客介绍了VMware Workstation15 配置ubuntu-18.04.4,这篇主要介绍安装后环境搭建,Android源码的下载与编译.小编当前下载的是当前最新的代码,是主干分支代码 ...
- [2021.8.18]深入理解PackageManagerService
原文链接:https://blog.csdn.net/Innost/article/details/47253179 本章主要内容: 详细分析PackageManagerService 1 概述 P ...
- android studio 单步调试jni,android studio实现Jni单步调试-标准配置教程
本文主要介绍在android studio下实现jni单步调试时,所需要的配置及其步骤,这些也是本人经过几天折腾慢慢实现的,先提供给大家做参考: 1,配置是在mac下android studio实现的 ...
- android 中 Proguard 和JNI 相关
在Android项目中用到JNI,当用了proguard后,发现native方法找不到很多变量,原来是被produard优化掉了.所以,在JNI应用中该慎用progurad啊. 解决办法: 1.在An ...
- [2021.1.27多校省选模拟10]染色(min-max容斥/二项式反演)
[2021.1.27多校省选模拟10]染色 突然发现我对概率期望的理解不是很好... 部分分1:可以直接进行状压dp,然后按照题意模拟即可. 部分分2:首先可以发现这个问题是min_max容斥形式,然 ...
- Android Studio1.4.x JNI开发基础-基本环境配置
从Eclipse时代到Android Studio普及,开发工具越来越好用.早些时候还需要安装Cygwin工具,从Android Studio1.3以后,在Android 环境开发JNI程序搭建开发环 ...
- WSL Ubuntu 20.04下Android源码编译与导入Android Studio
源码下载见前文:WSL Ubuntu 20.04下Android源码下载 idegen 模块编译 在development/tools/idegen/README下可以看到关于 idegen 工具的相 ...
最新文章
- AI检测制造“零缺陷”
- linux命令之创建符号连接-ln
- 3d点击_gooood合辑:3D打印 | 精选全部3D打印案例
- JavaScript学习笔记04【高级——DOM和事件的简单学习、BOM对象】
- set 与 map 的第一次尝试
- .Net Core应用框架Util介绍(二)
- python3.8安装xlwings出错_Python xlwings模块简单使用
- java注释 param_@Param注解的用法解析
- (转)Spring Boot 2 (五):Docker Compose + Spring Boot + Nginx + Mysql 实践
- github 手机号码归属地信息库、手机号归属地查询
- ApiPost测试接口获取不到session
- 【Unity】ET框架学习笔记
- python fundamental structure_Data Structures and Algorithms in Python
- Lambda表达式----“进化论”
- c语言字母字符参与运算,c语言字符串可以参加运算吗?
- 主动提交sitemap让谷歌、雅虎、MSN统统收录你的网站、博客
- 华为云服务器 共享文件夹在哪个文件夹,用户数据安全存储 华为云空间这些功能大显身手...
- Linux 网络驱动 phy 读写寄存器调试方法
- Python :18Python计算器
- 这样一首歌,让人泪流满面