【干货】Android系统定制基础篇:第十六部分(双屏异触、定时开关机与看门狗)

news2024/11/15 19:55:19

一、Android双屏异触-指定触摸为副屏触摸

在双屏异显产品中,有时候主副屏都带有触摸屏,并且要求主副屏触摸各自操作互不干扰。

Android 现有框架中已经支持副输入设备的逻辑,只是默认将所有的外部热插拔设备统一指定为副输入设备,这种逻辑我们如果是一个 I2C 加上一个 USB 触摸那么默认就可以支持,USB 触摸就是副 TP。

但,有时候我们是双 I2C 或双 USB 的搭配,我们就需要改造现有逻辑,方案如下:

通过属性配置副屏 TP 的: 设备名、PID&VID、USB 端口,在 EventHub 中获取输入设备的设备名、PID&VID、USB 端口与属性值进行对比,如果是配置中的设备就将其标记为副输入设备。

实现

diff --git a/frameworks/native/services/inputflinger/EventHub.cpp b/frameworks/native/services/inputflinger/EventHub.cpp
old mode 100644
new mode 100755
index 2bcc5c7..1542a7b
--- a/frameworks/native/services/inputflinger/EventHub.cpp
+++ b/frameworks/native/services/inputflinger/EventHub.cpp
@@ -64,6 +64,11 @@
 #define INDENT2 "    "
 #define INDENT3 "      "
 
+// for multi touch panel
+#define DEVICE_MATCH_METHOD_MAX 10
+#define USB_LOCATION_MATCH_START 13 //"usb-ff540000."
+#define USB_LOCATION_MATCH_LEN 7 //"usb-1.1"
+
 namespace android {
 
 static const char *WAKE_LOCK_ID = "KeyEvents";
@@ -1184,17 +1189,17 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
     int32_t deviceId = mNextDeviceId++;
     Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
 
-    ALOGV("add device %d: %s\n", deviceId, devicePath);
-    ALOGV("  bus:        %04x\n"
+    ALOGI("add device %d: %s\n", deviceId, devicePath);
+    ALOGI("  bus:        %04x\n"
          "  vendor      %04x\n"
          "  product     %04x\n"
          "  version     %04x\n",
         identifier.bus, identifier.vendor, identifier.product, identifier.version);
-    ALOGV("  name:       \"%s\"\n", identifier.name.string());
-    ALOGV("  location:   \"%s\"\n", identifier.location.string());
-    ALOGV("  unique id:  \"%s\"\n", identifier.uniqueId.string());
-    ALOGV("  descriptor: \"%s\"\n", identifier.descriptor.string());
-    ALOGV("  driver:     v%d.%d.%d\n",
+    ALOGI("  name:       \"%s\"\n", identifier.name.string());
+    ALOGI("  location:   \"%s\"\n", identifier.location.string());
+    ALOGI("  unique id:  \"%s\"\n", identifier.uniqueId.string());
+    ALOGI("  descriptor: \"%s\"\n", identifier.descriptor.string());
+    ALOGI("  driver:     v%d.%d.%d\n",
         driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
 
     // Load the configuration file for the device.
@@ -1357,10 +1362,35 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
     }
 
     // Determine whether the device is external or internal.
-    if (isExternalDeviceLocked(device)) {
+    if((device->classes & 0x04) == INPUT_DEVICE_CLASS_TOUCH) {
+        int count = 0;
+        char flag[DEVICE_MATCH_METHOD_MAX][PROPERTY_VALUE_MAX];
+        char value[PROPERTY_VALUE_MAX] = {0};
+    
+        property_get("ro.input.external", value, "");
+
+        if (isExternalDeviceLocked(device)) {
+            sprintf(flag[count++], "%04x:%04x", identifier.vendor, identifier.product);
+            if (identifier.location.length() >= USB_LOCATION_MATCH_START+USB_LOCATION_MATCH_LEN) {
+                strncpy(flag[count++], identifier.location.string()+USB_LOCATION_MATCH_START, USB_LOCATION_MATCH_LEN);
+            }
+        } else {
+            sprintf(flag[count++], "%s", device->identifier.name.string());
+        }
+
+        for (int i=0; i<count; i++) {
+            ALOGI("openDeviceLocked:%d, value=%s flag=%s\n", __LINE__, value, flag[i]);
+            if (strstr(value, flag[i])) {
+                device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
+                ALOGI("openDeviceLocked:%d, name:\"%s\" id:%d device_class:%x vid:%04x pid:%04x is external input device\n",
+                    __LINE__, device->identifier.name.string(), device->id, device->classes, identifier.vendor, identifier.product);
+                break;
+            }
+        }
+    } else {
         device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
     }
-
+    
     if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_DPAD)
             && device->classes & INPUT_DEVICE_CLASS_GAMEPAD) {
         device->controllerNumber = getNextControllerNumberLocked(device);

属性配置格式说明
属性名:ro.input.external
在这里插入图片描述也可以同时配置多个设备,各属性值之间用“,”隔开。
例如

ro.input.external=222a:0001,Hanvon electromagnetic pen,usb-1.4

以上属性配置“vid=222a,pid=0001”的 USB TP 和设备名为“Hanvon electromagnetic pen”的 I2C TP 以及 USB 端口为 1.4 的 TP 为副屏 TP,其它未配置的都默认为主屏 TP。

源码:https://github.com/aystshen/Android-MultiTouchPanel

二、Android定时开关机与看门狗
此方案用于实现 Android 主板的定时开机与看门狗功能,应用于一些特殊产品,如:广告机、自动售货机等。
在这里插入图片描述在这里插入图片描述看门狗

看门狗功能默认关闭,直到 Android 发送命令打开看门狗功能。如果看门狗功能处于打开状态,Android 系统会在小于看门狗超时时长内定时发送心跳数据给 MCU,如果看门狗超时时长到,仍未收到心跳数据,则拉低 RESET 引脚10ms,使 CPU 复位重启。

定时开机
当 MCU 收到数据后启动计时,时间到拉低 POWER 引脚10ms,使 CPU 开机,同时清除本次定时任务,直到下次 CPU 重新下发新的定时任务。

协议
通信接口为 I2C,从机地址:0x61。
在这里插入图片描述在这里插入图片描述源码 https://github.com/aystshen/Android-TimedBootDriver

API

heartbeat
发送看门狗(Watchdog)心跳,至少在每个看门狗超时周期内发送一次心跳,否则超时复位。
定义:

int heartbeat();
返回值 <0:失败,>=0:成功。

setUptime 设置定时开机倒计时,当倒计时结束则开机。
定义:

int setUptime(int time);//time 开机倒计时(单位:秒)。
返回 <0:失败,>=0:成功。

getUptime 获取定时开机剩余时间。

int getUptime(); // <0:失败,>=0:剩余时间(单位:秒)。

openWatchdog 打开看门狗。

int openWatchdog(); // 返回 <0:失败,>=0:成功。

closeWatchdog 关闭看门狗。

int closeWatchdog(); //<0:失败,>=0:成功。

setWatchdogDuration 设置看门狗超时时长。

int setWatchdogDuration(int duration);//duration 看门狗超时时长(单位:秒)
返回值 <0:失败,>=0:成功。

getWatchdogDuration 获取看门狗超时时长。

int getWatchdogDuration();//<0:失败,>=0:看门狗超时时长(单位:秒)

watchdogIsOpen 判断看门狗是否开启。

boolean watchdogIsOpen();//true:看门狗打开,false:看门狗关闭。

使用

  1. 在 APP 源码 src/main 目录下新建 aidl/android/os/ 这样的目录结构。
  2. 在 aidl/android/os/ 目录下新建 IMcuService.aidl 文件,内容如下:
package android.os;
 
/** {@hide} */
interface IMcuService
{
    int heartbeat();
    int setUptime(int time);
    int getUptime();
    int openWatchdog();
    int closeWatchdog();
    int setWatchdogDuration(int duration);
    int getWatchdogDuration();
    boolean watchdogIsOpen();
}

3.参考源码 Mcu.java

package com.ayst.androidx.supply;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.IBinder;
import android.os.IMcuService;
import android.os.RemoteException;

import java.lang.reflect.Method;

/**
 * Created by Administrator on 2018/11/6.
 */
public class Mcu {
    private IMcuService mMcuService;

    @SuppressLint("WrongConstant")
    public Mcu(Context context) {
        Method method = null;
        try {
            method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
            IBinder binder = (IBinder) method.invoke(null, new Object[]{"mcu"});
            mMcuService = IMcuService.Stub.asInterface(binder);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Heartbeat
     */
    public void heartbeat() {
        if (null != mMcuService) {
            try {
                mMcuService.heartbeat();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Set the boot countdown
     * @param time (unit: second)
     * @return <0:error
     */
    public int setUptime(int time) {
        if (null != mMcuService) {
            try {
                return mMcuService.setUptime(time);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return -1;
    }

    /**
     * Get the boot countdown
     * @return time
     */
    public int getUptime() {
        if (null != mMcuService) {
            try {
                return mMcuService.getUptime();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    /**
     * Enable watchdog
     * @return <0:error
     */
    public int openWatchdog() {
        if (null != mMcuService) {
            try {
                return mMcuService.openWatchdog();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return -1;
    }

    /**
     * Disable watchdog
     * @return <0:error
     */
    public int closeWatchdog() {
        if (null != mMcuService) {
            try {
                return mMcuService.closeWatchdog();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return -1;
    }

    /**
     * Watchdog is open
     * @return
     */
    public boolean watchdogIsOpen() {
        if (null != mMcuService) {
            try {
                return mMcuService.watchdogIsOpen();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    /**
     * Set watchdog over time duration
     * @param duration (unit: second)
     * @return <0:error
     */
    public int setWatchdogDuration(int duration) {
        if (null != mMcuService) {
            try {
                return mMcuService.setWatchdogDuration(duration);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return -1;
    }

    /**
     * Get watchdog over time duration
     * @return
     */
    public int getWatchdogDuration() {
        if (null != mMcuService) {
            try {
                return mMcuService.getWatchdogDuration();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/671345.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

XILINX 7系列FPGA封装之芯片常见封装技术详解

&#x1f3e1;《Xilinx FPGA开发指南》 目录 1&#xff0c;概述2&#xff0c;常用封装技术2.1&#xff0c;Wire-bond chip-scale2.2&#xff0c;Wire-bond fine-pitch2.3&#xff0c;Flip-chip lidless2.4&#xff0c;Ruggedized flip-chip2.5&#xff0c; Flip-chip fine-pitc…

【算法设计与分析】期末复习

文章目录 复习大纲第一章算法概述1.1算法与程序1.2 算法复杂性分析 第二章递归与分治策略分治法的基本思想递归与分治的关系&#xff1a;用分治法解决的问题的几个特征&#xff1a;例题&#xff1a; 第三章动态规划动态规划的基本思想&#xff1a;分治与动态规划算法的异同&…

mine vpn

client remote ‘whvpn.deepin.com’ 1194 auth-user-pass dev tun proto tcp nobind auth-nocache script-security 2 persist-key persist-tun user nm-openvpn group nm-openvpn -----BEGIN CERTIFICATE----- MIIDPDCCAiSgAwIBAgIUUTvTCz6BndUDTIVTBxpKL19mEMkwDQYJKoZIhvcN…

JAVA开发(spring RestFull风格Feign使用总结)

现在大多数的springboot都是使用RestFull风格的接口&#xff0c;是Feign进行远程调用。 一、Feign介绍&#xff1a; Feign是Spring Cloud Netflix组件中的一个轻量级RESTFULL的http服务客户端&#xff0c;实现了负载均衡和Rest调用的开源框架&#xff0c;封装了Ribbon和RestTe…

使用谷歌 Chrome 浏览器禁用网页 JavaScript

使用谷歌 Chrome 浏览器禁用网页 JavaScript 文章目录 使用谷歌 Chrome 浏览器禁用网页 JavaScriptI - 概述1.1 - JavaScript 的功能1.2 - 为何要禁用 JavaScript II - 禁用 JavaScript 的方式2.1 - Chrome 调试工具2.2 - Chrome 黑名单 I - 概述 1.1 - JavaScript 的功能 Web…

Fegin 中统一处理调用的结果

背景 项目中&#xff0c;微服务环境下&#xff0c;有很多时候&#xff0c;都需要调用其他服务&#xff0c;而且其他服务基本上都有一个骨架类(如下图)&#xff0c;为了不用每次调用都去判断是否成功&#xff0c;所以需要统一处理接口返回的结果 思考 跟踪代码发现&#xff0c;…

Seata Saga 模式理论学习、生产级使用示例搭建及注意事项(二) | Spring Cloud58

一、前言 通过以下系列章节&#xff1a; docker-compose 实现Seata Server高可用部署 | Spring Cloud 51 Seata AT 模式理论学习、事务隔离及部分源码解析 | Spring Cloud 52 Spring Boot集成Seata利用AT模式分布式事务示例 | Spring Cloud 53 Seata XA 模式理论学习、使用…

Dubbo服务发现原理

一、Dubbo服务发现设计 Dubbo提供的是一种Client-Based的服务发现机制&#xff0c;依赖第三方注册中心组件来协调服务发现过程&#xff0c;支持常用的注册中心如Nacos、Connsul、Zookeeper等 Dubbo服务发现机制的基本工作原理图&#xff1a; 服务发现包含提供者、消费者和注册…

MySQL 被 PG 干翻了。。

出品 | OSC开源社区&#xff08;ID&#xff1a;oschina2013) Stack Overflow 发布了 2023 年开发者调查报告&#xff0c;据称共计超过 9 万名开发者参与了此次调查。 完整报告包含了受访开发者画像&#xff0c;以及关于开发技术、AI、职业、社区等方面的内容。本文主要介绍关于…

ICC2: 工具是如何控制局部利用率的?

分析congestion map时不难发现,route congestion高的地方局部利用率往往要比周围低,这时疑问就来了,既然standard cell的分布不是均匀的,那局部再降一降彻底解决congestion问题不好嘛?工具是如何控制这种congestion driven的行为的呢? 在place_opt以及clock_opt的log里都…

Apache Atlas高级搜索语法示例

from hive_table;hive_table from hive_table where name xxx or name yyy from hive_table where name ["xxx", "yyy"] from hive_table where name LIKE *_xxx hive_db where name like "???dm?*" hive_column where table.name …

Dcat Admin 2 集成富文本编辑器 wangEditor 5

由于默认的 TinyMCE 个人不是很喜欢&#xff0c;所以替换成国产的富文本编辑器 wangEditor Dcat Admin 文档示例&#xff1a;集成富文本编辑器 wangEditor 但是官方的示例是针对 wangEditor 4 编写的&#xff0c;这里仅指出对版本 5 的差异部分 获取文件 将以下三个文件保存…

快码住! 结构体内存对齐(计算结构体大小) 干货满满!

文章目录 结构体内存对齐规则结构体大小计算为什么存在内存对齐&#xff1f;设计结构体的技巧如何修改默认对齐数&#xff1f; 结构体内存对齐规则 我们知道&#xff0c;整型变量有自己的大小&#xff0c;浮点型变量有自己的大小&#xff0c;数组也有自己的大小&#xff0c;那…

血流动力学与血压(一)--平均动脉压

平均动脉压 在血管血流动力学研究中&#xff0c;心血管系统通常被认为是一个简单的液压回路&#xff0c;由泵&#xff08;心脏&#xff09;组成&#xff0c;泵&#xff08;心脏&#xff09;有节奏地活动&#xff08;收缩 --> 舒张 --> 收缩 --> 舒张 --> 收缩…&am…

中国一重集中采购平台的建设经历和亮点

中国一重前身为第一重型机器厂&#xff0c;是“一五”期间建设156项重点工程项目之一&#xff0c;始建于1954年&#xff0c;是中央管理的涉及国家安全和国民经济命脉的国有重要骨干企业之一&#xff0c;是国家创新型试点企业、国家高新技术企业&#xff0c;拥有国家级企业技术中…

java 校园管理系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 JSP 校园管理系统 是一套完善的系统源码&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;以及相应配套的设计文档&#xff0c;系统主要采用B/S模式开发。 研究的基本内容是基于Web的校园管理系统&…

访问不到阿里云服务器端口

这里前台在主机上 然后访问服务器上的node后台 一直访问不到 不能连入阿里云服务器后台 连不上公网ip端口 解决方案 登录阿里云 进入云服务器 2、管理控制台 3、网络与安全——>安全组 4、安全组里面点击配置规则 5、手动添加 即可

《项目实战》构建SpringCloud alibaba项目(三、构建服务方子工程store-user-service)

系列文章目录 构建SpringCloud alibaba项目&#xff08;一、构建父工程、公共库、网关&#xff09; 构建SpringCloud alibaba项目&#xff08;二、构建微服务鉴权子工程store-authority-service&#xff09; 构建SpringCloud alibaba项目&#xff08;三、构建服务方子工程stor…

python学习——NumPy数值计算基础

目录 NumPy数值计算基础1.array创建数组及其属性2.其他创建方式3.数据类型及其转换4.生成随机数5.数组的索引和切片6.改变数组形态【案例】两个国家的数据方法一起来研究分析&#xff0c;同时保留国家的信息&#xff08;每条数据的国家来源&#xff09;&#xff0c;应该怎么办 …

《网络安全0-100》单钥加密体制

单钥加密体制 DES算法 DES属于对称密码算法中的分组加密(块加密)&#xff0c;和流密码相对应。DES算法将明文分为若干个64位块(不足补充)&#xff0c;秘钥为56位(8位校验位)。DES算法流程图如下 接下来&#xff0c;进行DES算法关键步骤的逐步解析&#xff1a; IP置换 IP置换…