我在实际开发中,遇到一个问题,在电容屏驱动中没有发送input_sync 给上层,导致电容屏有的数据缓存在inputreader 中,会导致系统一系列奇怪问题发生,

至于为什么驱动不发送input_sync ,是因为项目某个功能的框架没有搭好导致的,总之这次不能从驱动中解决这个问题,这次为了弥补这个过失,

就需要在特定的情况下强制把电容屏在inputreader 的缓存清除,好了,这次binder 又要闪亮登场了!

1. 熟悉Inputreader 源码获取清除缓存接口

说实话,没有具体跟踪调试过这部分源码,直接从0开始生硬的看代码确实费力,我尽量简洁地说这块源码,以及我是如何找到清除缓存的接口的。

a. 首先把 frameworks\native\services\inputflinger 这部分代码添加到sourceinsight 中。

b. 只需要大致明白,EventHub.cpp 是直接获取驱动报上来的原始数据,然后InputReader.cpp 对这份数据进行处理保存在一段缓存队列中,InputDispatcher.cpp

从队列中取数据,再发送给上层窗口等等。

所以,只需要阅读InputReader.cpp 代码即可,因为要清空的缓存就在其中。

怎么办,这个cpp 有7千多行代码,不同android 版本说不定有8千多行呢?

别慌!粗略的看一下,发现有个类叫做 MultiTouchInputMapper ,电容屏不就是多点触控么,直接添加相关调试log, 可以清楚这块调用流程。总之,MultiTouchInputMapper

里面有个重要的实现叫做 void MultiTouchInputMapper::reset(nsecs_t when) ,就是它会清空缓存。

c. 熟悉代码后发现 MultiTouchInputMapper 与 InputMapper 有密切的关系,如果实在觉得看代码嫌烦,直接搜出所有的reset ,可以发现void InputDevice::reset(nsecs_t when) 最终会掉进

MultiTouchInputMapper 里面,感觉这就是唯一的通路了,虽然会误伤到SingleTouchInputMapper ,但是对项目没有影响就无所谓了,毕竟SingleTouchInputMapper 中也没有什么数据好清空,如果对我的设计思想有异议请大胆说出来吧!

误伤SingleTouchInputMapper 的InputDevice::reset 代码如下,如果不想误伤可以把下面实现进行修改,或者只调用MultiTouchInputMapper 的reset 接口也行,我这么做主要是害怕只清空一部分不能解决问题,所以后续调试决定统一清空。

void InputDevice::reset(nsecs_t when) {size_t numMappers = mMappers.size();for (size_t i = 0; i < numMappers; i++) {InputMapper* mapper = mMappers[i];mapper->reset(when);}mContext->updateGlobalMetaState();notifyReset(when);
}

  

d. 下一步就是搜寻InputDevice 这个类了,可以很快找到调用的方式。

首先声明获取device: InputDevice* device = mDevices.valueAt(deviceIndex);

然后清空数据:device->reset(when);

e. 添加处理代码

void InputReader::clearCTPData(nsecs_t when, int32_t deviceId) {ssize_t deviceIndex = mDevices.indexOfKey(deviceId);if (deviceIndex < 0) {ALOGW("Discarding event for unknown deviceId %d.", deviceId);return;}InputDevice* device = mDevices.valueAt(deviceIndex);if (device->isIgnored()) {//ALOGD("Discarding event for ignored deviceId %d.", deviceId);return;}device->reset(when);
}

  

发现里面有个参数比较陌生,deviceId, 调试过input 设备的朋友应该清楚,在adb shell 下输入getevent 就会冒出好多挂载的input 设备信息,其中就包括了deviceId,当然要用代码获取也是可以的,这部分下一节讨论。

2. 添加binder 服务

由上面添加的clearCTPData 这个接口可知,这个处理是在InputReader 类里面新加的一个方法。调用它就需要有一个指针指向当前的InputReader ,好的,有了这个想法就开始写代码吧。

首先在InputReader.cpp 中InputReader::InputReader 的构造函数中添加咱们的binder 指针,binder 调用ontransct的类服务也需要重写一下,就命名为MyInputreaderService 吧。

分三步走,

第一部:

把clearCTPData的代码添加到InputReader.cpp 和 InputReader.h 中,代码刚才有贴过,声明直接放在class InputReader 里面即可。

第二部 :

InputReader.cpp 中在构造函数里面添加binder 的服务,代码如下:

InputReader::InputReader(const sp<EventHubInterface>& eventHub,const sp<InputReaderPolicyInterface>& policy,const sp<InputListenerInterface>& listener) :mContext(this), mEventHub(eventHub), mPolicy(policy),mGlobalMetaState(0), mGeneration(1),mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),mConfigurationChangesToRefresh(0) {mQueuedListener = new QueuedInputListener(listener);{ // acquire lockAutoMutex _l(mLock);sp<IBinder> sendBinder = new ByInputreaderService(this);defaultServiceManager()->addService(String16("my.inputreader"), sendBinder);refreshConfigurationLocked(0);updateGlobalMetaStateLocked();} // release lock
}

  

第三部:

完成ByInputreaderService 的功能,我主要借鉴getevent的源码做了一个简单的获取deviceID的功能,同时用InputReader 构造函数中传入的this 来搞事情(调用clearCTPData)

class ByInputreaderService : public BBinder {
public:InputReader *parent;int mCTPDeviceId;nsecs_t mWhen;ByInputreaderService(InputReader *p) : parent(p){mCTPDeviceId = 1;getCtpFd();}~ByInputreaderService(){}int scan_input_device(int fd){char name[80];name[sizeof(name) - 1] = '\0';if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {ALOGI("could not get device name for %s\n", strerror(errno));name[0] = '\0';}ALOGI("getCtpFd device name is %s\n", name);if(strcmp("cyttsp5_mt", name) == 0){ALOGI("getCtpFd cyttsp5_mt !!!\n");return 0;}return -1;}int getCtpFd(void){int fd = 0;int device_type = 0;char devname[50];char *filename;DIR *dir;struct dirent *de;dir = opendir("/dev/input");if(dir == NULL)return -1;strcpy(devname, "/dev/input");filename = devname + strlen(devname);*filename++ = '/';while((de = readdir(dir))) {if(de->d_name[0] == '.' && (de->d_name[1] == '\0' ||(de->d_name[1] == '.' && de->d_name[2] == '\0')))continue;strcpy(filename, de->d_name);fd = open(devname, O_RDWR);if (fd < 0) {ALOGI("[getCtpFd] open device failed! path: %s\n",devname);continue;}device_type = scan_input_device(fd);if(device_type != 0){mCTPDeviceId ++;close(fd);ALOGI("[getCtpFd] scan device failed! path: %s -- %d\n",devname, device_type);continue;}else{ALOGI("[getCtpFd] scan device success! path: %s -- %d\n",devname, device_type);break;}}closedir(dir);close(fd);return fd;    }status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ALOGI("ByInputreaderService %d \n", code);if(CLEARINPUTDATA == code){mWhen = systemTime(SYSTEM_TIME_MONOTONIC);parent->clearCTPData(mWhen, mCTPDeviceId);          }return NO_ERROR;}};

  

CLEARINPUTDATA 这个宏随便定义,总之客户端要和这个code 值保持一致即可。

如果觉得代码或者实现的方式有什么不妥的地方请多多指教,谢谢。

希望大家多多吐槽,大家一起共同进步!!

转载于:https://www.cnblogs.com/songsongman/p/11101353.html

Android native进程间通信实例-binder篇之——解决实际问题inputreader内建类清楚缓存...相关推荐

  1. java 通信层_Android native进程间通信实例-binder篇之——HAL层访问JAVA层的服务

    有一天在群里聊天的时候,有人提出一个问题,怎样才能做到HAL层访问JAVA层的接口?刚好我不会,所以做了一点研究. 之前的文章末尾部分说过了service call 可以用来调试系统的binder服务 ...

  2. android 进程间的通信,Android native进程间通信实例-binder结合共享内存

    在android源码的驱动目录下,一般会有共享内存的相关实现源码,目录是:kerneldriversstagingandroidashmem.c.但是本篇文章不是讲解android共享内存的功能实现原 ...

  3. 黑苹果 装SVN工具 cornerstone无法打开解决办法——网卡内建

    黑苹果 装SVN工具 cornerstone无法打开解决办法--网卡内建 具体内容,请参照远景帖子:http://bbs.pcbeta.com/viewthread-900017-1-1.html 转 ...

  4. IDEA中导入之前的web项目.完整篇.并解决了导入后项目的类全是橙色的J的角标的问题

    1.在IDEA中点击file 然后再点击project Structure... 之后找到modules,再点击右侧的加号 点了加号后再点import module 之后在右侧文件列表中,找到要导入的 ...

  5. vue支付宝html,vue 解决在微信内置浏览器中调用支付宝支付的情况

    我的思路大概是这样的 1. 验证是否是在微信内置浏览器中调用支付宝 2.给支付页面的url加上调用接口所需的参数(因为在微信里是不能直接调用支付宝的需要调用外部浏览器) 3.在外部浏览器中完成支付跳转 ...

  6. Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析

    原文地址: http://blog.csdn.net/luoshengyang/article/details/6629298 在前面一篇文章浅谈Android系统进程间通信(IPC)机制Binder ...

  7. 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路

    原文地址: http://blog.csdn.net/luoshengyang/article/details/6627260 在前面一篇文章浅谈Service Manager成为Android进程间 ...

  8. Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析(1)

    在前面一篇文章浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路中,介绍了在Android系统中Binder进程间通信机 ...

  9. Android跨进程通信Binder机制与AIDL实例

    文章目录 进程通信 1.1 进程空间划分 1.2 跨进程通信IPC 1.3 Linux跨进程通信 1.4 Android进程通信 Binder跨进程通信 2.1 Binder简介 2.2 Binder ...

最新文章

  1. dicom文件_图像识别 | 使用Python对医学Dicom文件的预处理(含代码)
  2. 零基础学python爬虫-我是如何零基础开始能写Python爬虫的
  3. mysql重置auto_increment字段
  4. java 局部性原理_程序局部性原理
  5. 【9603】最大整数
  6. LeetCode 892. 三维形体的表面积
  7. SQL将A表的现有数据添加到B表,通过A表现有数据更新B表
  8. webSocket 干货分享 附带项目源码
  9. 写软件详细设计方案总结
  10. 计算机累论文的数据字典怎么写,毕业论文中数据字典应该这样写
  11. 基于matlab的直流调速仿真系统代码,基于Matlab的双闭环直流调速系统仿真研究毕业设计论文...
  12. IOCP完成端口模拟线程池
  13. 音视频基础:H264、H265、MPEG-4、VP8、VP9编码基础知识
  14. python3 数独解法 深度遍历
  15. pada aws configuration
  16. 4年亏损超6亿,摩贝化学赴美上市能否输血成功?
  17. nbiot教学实箱_lora-NBiot窄带物联网通信试验箱--5g通信技术教学篇
  18. 数据结构实验八 图及其应用
  19. 虚拟信用卡最大的发行商有哪些?
  20. Codevs P1814 最长链

热门文章

  1. 小米折叠手机高清渲染图曝光:双外折叠形态美如画
  2. DTMF采用RFC2833进行带内传输的实现[ZT]
  3. 基于Linux和MiniGUI的嵌入式系统软件开发指南(五)
  4. [python]json.loads 几种错误 解决方案
  5. 死锁发生的条件和预防
  6. 线性表:2.线性表的顺序存储结构--顺序表及C语言实现
  7. 函数调用中的参数太多_函数调用
  8. [置顶文章]打豆豆的一些小问题、不小心会忘记的知识点
  9. Python:int,float,str之间的转换
  10. 【clickhouse】clickhouse UTC 时间带有时区 如何写入