当前位置: 首页 > news >正文

网站备案 假通信地址网站后台上传图片步骤

网站备案 假通信地址,网站后台上传图片步骤,烟台唯佳网络科技有限公司,南通建设公司网站一、资料快车 1、深入了解Android输入系统#xff1a;https://blog.csdn.net/innost/article/details/47660387 2、书籍 - Android系统源代码情景分析 二、Perface 1、参考#xff1a; 2、系统程序分析方法 1#xff09;加入log#xff0c;并跟着log一步步分析 -logc…一、资料快车 1、深入了解Android输入系统https://blog.csdn.net/innost/article/details/47660387 2、书籍 - Android系统源代码情景分析 二、Perface 1、参考 2、系统程序分析方法 1加入log并跟着log一步步分析 -logcat 2利用ChatGPT提供基础概念解析 代码解析 设计原理 3、目标 1提供查阅代码的线索、思路 2能够根据日志进行快读的代码分析 3区分代码层次为定制系统提供思路 4站在前人的肩膀上进一步探究 5熟悉架构后我们应能 如何添加自定义按键、拦截keyevent并添加自己的处理逻辑 6Android源代码兼容多种设备比如一开始Android针对手机设计因此很多代码都有手机的身影后面适应不同的设备不同设备的处理流程不同注意分辨 4、action 务必根据本文提供的线索 去看源代码。 带着疑问去了解 1、kl/kcm作用是什么在哪里会被读取 2、定义CVTE快捷键应该怎么做 3、如何跟中控和TVAPI联合起来 三、代码目录 所在层次名称代码路径Application应用(调用系统库实现用户逻辑)实现android中对应的类及方法进行inputevent处理frameworkandroid (此部分链接到应用)/android/frameworks/base/services/java/com/android/server/SystemServer.java/android/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java/android/frameworks/base/core/java/*/android/frameworks/base/core/java/com/android/internal/policy/DecorView.java/android/frameworks/base/core/java/android/app/Activity.java/android/frameworks/base/core/java/android/view/ViewRootImpl.java/android/frameworks/base/core/java/android/view/View.java/android/frameworks/base/core/java/android/view/KeyEvent.java/android/frameworks/base/core/java/android/view/InputChannel.javaservice (系统服务服务端集中管理)Framework java基础服务/android/frameworks/base/services/java/com/android/server/SystemServer.javaFramework android核心服务/android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.javaJNI(过渡到native)一、libservices.core - 静态库模块/android/frameworks/base/services/core/jni//android/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp二、libandroid_runtime - 静态库模块/android/frameworks/base/core/jni//android/frameworks/base/core/jni/android_view_InputEventReceiver.cppNDK一、libinput - 静态库模块/android/frameworks/native/libs/input//android/frameworks/native/libs/input/InputTransport.cpp二、libinputflinger/libinputflinger_base - 动态库模块/android/frameworks/native/services/inputflinger//android/frameworks/native/services/inputflinger/InputManager.cpp三、lib/android/system/core/libutils/*/android/system/core/libutils/Looper.cppcvte/android/frameworks/base/core/java/com/cvte/key/*kernelinput子系统 四、系统框架流程 1、粗略框图 - 来自深入了解Android 2、代码层级 3、framework部分 4、下面针对各个部分进行拆解分析 五、基础概念 1、APP界面构成关系 1Application 、Activity、Windows 、Decro(ration) 、View 一个Application有多个ActivityActivity中的界面部分为WindowsPhoneWindow是我们所看到的当前整个界面windows界面由Decro(样式) 来描述Decro由各种view组件(TextView、button)组成。 2从代码角度看Decro与View的树状关系 3小结 android里: 1个application, 有1个或多个activity 1个activity, 有1个PhoneWindow 1个window, 有1个decor 1个decor, 有多个viewgroup/layout viewgroup/layout中, 有多个view 2、Activity组件与ViewRoot对象的关系 Android设计思想 - 抽象分工 一个应用程序窗口是由一个Activity来描述描述控件组成、布局等等- 策略者 每一个Activity组件都有一个关联的ViewRoot对象除了绘制具体的窗口还负责分发键盘事件 - 具体实施者 Activity和ViewRoot通过DecorView和PhoneWindow对象来关联起来 需要跟踪代码才能掌握理解以上关系 Android-Activity与Window与View之间的关系https://github.com/jeanboydev/Android-ReadTheFuckingSourceCode/blob/master/article/android/framework/Android-Activity%E4%B8%8EWindow%E4%B8%8EView%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB.md 2、输入事件 输入事件有多种类型触摸、拖动、鼠标、按键等等 3、key相关概念 1*.kl : keylayoutlinux的scancode对应的Android按键映射 2*.kcmkey code mapAndroid按键对应的字符映射 3*.idc : input device configutation 输入设备配置文件 以上文件在板卡都可以找到 4、socketpair 与 binder socketpair 与 binder 为Android的跨进程通信技术模块两者结合可以实现双向的跨进程通信。 5、inotify和epoll inotify模块用于监测某目录下的文件变化 epoll模块用于监测文件内容变化 六、Linux kernel 1、input输入子系统 2、IR驱动 https://blog.csdn.net/STCNXPARM/article/details/134235394 七、Andorid系统部分 1、WMS 2、InputManagerService(java) java层的InputManagerService对native层的InputManager进一步封装很多实现都在native层。 1ReaderCPP 1、Reader角色 Reader主要工作 1从设备里读取输入事件 2根据kcm/kl文件进行按键映射处理 3将RawEvent传递给dispatcher处理 这块代码比较固定也很少去适配了解下即可android\frameworks\native\services\inputflinger\*1、InputReader对象启动线程 android\frameworks\native\services\inputflinger\reader\InputReader.cpp status_t InputReader::start() {if (mThread) {return ALREADY_EXISTS;}mThread std::make_uniqueInputThread(InputReader, [this]() { loopOnce(); }, [this]() { mEventHub-wake(); });return OK; }2、InputThread对提供一个线程模板 android\frameworks\native\services\inputflinger\InputThread.cpp InputThread::InputThread(std::string name, std::functionvoid() loop, std::functionvoid() wake): mName(name), mThreadWake(wake) {mThread spInputThreadImpl::make(loop);mThread-run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY); }3、读取输入事件 //主要使用inotify监测/dev/input使用epoll监测有无数据 void InputReader::loopOnce() { //作为函数参数传给InputThread std::vectorRawEvent events mEventHub-getEvents(timeoutMillis); //读取event设备节点 ... mQueuedListener.flush(); //flush队列通知dispatcher线程 ... }2、InputReader和EventHub的分工 1InputReader(上层角色) 1如果设备刚接入则先addDeviceLocked() 添加设备 2如果设备已存在且有输入事件产生则processEventLocked() 3处理事件对象这里以KeyboardInputMapper为例 2EventHub底层角色 EventHub读取设备节点获取输入事件RawEvent 1读取输入设备驱动信息底层原理是使用inotify/epoll机制进行监测加载idc/kcm/kl文件驱动设备提供路径 2最终转换成RawEvent交给InputReader继续处理 EventHub是linux device交互的功能类 1、openDeviceLocked android\frameworks\native\services\inputflinger\reader\EventHub.cpp void EventHub::openDeviceLocked(const std::string devicePath) {...//打开设备int fd open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);if (fd 0) {ALOGE(could not open %s, %s\n, devicePath.c_str(), strerror(errno));return;}...//ioctl得到信号// Get device name.if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), buffer) 1) {ALOGE(Could not get device name for %s: %s, devicePath.c_str(), strerror(errno));} else {buffer[sizeof(buffer) - 1] \0;identifier.name buffer;}...//加载idc//kl/kcmif (device-classes.any(InputDeviceClass::KEYBOARD | InputDeviceClass::JOYSTICK |InputDeviceClass::SENSOR)) {// Load the keymap for the device.keyMapStatus device-loadKeyMapLocked();} }3InputReader和EventHub的分工介绍分层思想 3、复杂的底层数据结构介绍 1RawEvent/input_event/Device/InputDevice 1、android\frameworks\native\services\inputflinger\reader\include\EventHub.h struct RawEvent { //// Time when the event happenednsecs_t when;// Time when the event was read by EventHub. Only populated for input events.// For other events (device added/removed/etc), this value is undefined and should not be read.nsecs_t readTime;int32_t deviceId;int32_t type;int32_t code;int32_t value; };2、include/linux/input.h struct input_event{struct timeval time;__u16 type;__u16 code;__s32 value; };3、Device //注意不是linux device不要混淆 android\frameworks\native\services\inputflinger\reader\include\EventHub.h struct Device {int fd; // may be -1 if device is closedconst int32_t id;const std::string path;const InputDeviceIdentifier identifier; //输入设备的基本信息...std::string configurationFile; //对应idc配置文件std::unique_ptrPropertyMap configuration;std::unique_ptrVirtualKeyMap virtualKeyMap;KeyMap keyMap; //对应两种配置文件kcm-kl先找kcm映射找不到再找kl映射 } 关于Device信息Android上可以敲dumpsys input查看所有的input设备信息定义 F:\1.code\MTK9256_AN14\android\frameworks\native\services\inputflinger\reader\include\EventHub.h std::unordered_mapint32_t, std::unique_ptrDevice mDevices;4、 F:\1.code\MTK9256_AN14\android\frameworks\native\services\inputflinger\reader\include\InputDevice.hclass InputDevice { //绑定EventHub的Device目的是封装Device的复杂操作给上层提供更方便的操作 private:InputReaderContext* mContext;int32_t mId;int32_t mGeneration;int32_t mControllerNumber;InputDeviceIdentifier mIdentifier;std::unordered_mapint32_t, DevicePair mDevices; } //定义 F:\1.code\MTK9256_AN14\android\frameworks\native\services\inputflinger\reader\include\InputReader.h std::unordered_mapint32_t /*eventHubId*/, std::shared_ptrInputDevice mDevices GUARDED_BY(mLock);5、 /* Types of input device configuration files. */ enum class InputDeviceConfigurationFileType : int32_t {CONFIGURATION 0, /* .idc file */KEY_LAYOUT 1, /* .kl file */KEY_CHARACTER_MAP 2, /* .kcm file */ };2KeyMap-KeyLayoutMap-KeyCharacterMap 1、 F:\1.code\MTK9256_AN14\android\frameworks\native\include\input\Keyboard.h class KeyMap { public:std::string keyLayoutFile;std::shared_ptrKeyLayoutMap keyLayoutMap;std::string keyCharacterMapFile;std::shared_ptrKeyCharacterMap keyCharacterMap; }2、 class KeyLayoutMap { private:struct Key {int32_t keyCode;uint32_t flags;}; } kl文件格式举例 key 305 BUTTON_B // key linux key Android key3、 class KeyCharacterMap { private:struct Behavior {/* The meta key modifiers for this behavior. */int32_t metaState 0;/* The character to insert. */char16_t character 0;/* The fallback keycode if the key is not handled. */int32_t fallbackKeyCode 0;/* The replacement keycode if the key has to be replaced outright. */int32_t replacementKeyCode 0;};struct Key {/* The single character label printed on the key, or 0 if none. */char16_t label 0;/* The number or symbol character generated by the key, or 0 if none. */char16_t number 0;/* The list of key behaviors sorted from most specific to least specific* meta key binding. */std::listBehavior behaviors;};class Parser {} //加载kcm文件时用此class来解析 }kcm文件格式举例 1、 key B {label: B # 印在按键上的文字 base: b # 如果没有其他按键(shift, ctrl等)同时按下此按键对应的字符是b shift, capslock: B # 组合按键如shiftbaseB, capslockbaseB } 2、 key SPACE {label: base: alt, meta: fallback SEARCH #组合按键ctrl: fallback LANGUAGE_SWITCH #组件按键 }解析组合按键构造三个Behavior Behavior.metaStatealt Behavior.fallbackKeyCodeAKEYCODE_SEARCHBehavior.metaStatemeta Behavior.fallbackKeyCodeAKEYCODE_SEARCHBehavior.metaStatectrl Behavior.fallbackKeyCodeAKEYCODE_LANGUAGE_SWITCH放到链表std::listBehavior behaviors3涉及的数据结构总览 2DispatcherCPP 1、Dispatcher的工作 要点解析 1输入事件之按键分类 Global key一键启动 - 快捷键 system key静音、音量、home键 user key普通输入按键 2inboundQueue/outboundQueue双端队列 - 用于储存输入事件 出队mInboundQueue.pop_front(); 入队mInboundQueue.push_front();3mCommandQueue用于储存Command: 出队mCommandQueue.pop_front(); 入队mCommandQueue.push_back(command);2、代码时序图 输入事件有多种类型触摸、拖动、鼠标等等这里以输入按键为例从底层-上层 3、关键点分析 1reader与dispatcher的交互实现 1、总体框图 InputFlinger进程 android\frameworks\native\services\inputflinger\host\main.cpp2、InputManager的构造函数中建立联系通过mQueuedListenerReader获得Dispatcher的指针 android\frameworks\native\services\inputflinger\InputManager.cpp /*** The event flow is via the InputListener interface, as follows:* InputReader - UnwantedInteractionBlocker - InputProcessor - InputDispatcher*/ InputManager::InputManager(const spInputReaderPolicyInterface readerPolicy,InputDispatcherPolicyInterface dispatcherPolicy) {mDispatcher createInputDispatcher(dispatcherPolicy);mProcessor std::make_uniqueInputProcessor(*mDispatcher);mBlocker std::make_uniqueUnwantedInteractionBlocker(*mProcessor);mReader createInputReader(readerPolicy, *mBlocker); }3、处理流 InputReader - UnwantedInteractionBlocker - InputProcessor - InputDispatcher 类图 4、InputListenerInterface android\frameworks\native\services\inputflinger\InputListener.cpp1、根据NotifyArgs的类型执行对应的函数-泛型思想 void InputListenerInterface::notify(const NotifyArgs generalArgs) {Visitor v{[](const NotifyInputDevicesChangedArgs args) { notifyInputDevicesChanged(args); },[](const NotifyConfigurationChangedArgs args) { notifyConfigurationChanged(args); },[](const NotifyKeyArgs args) { notifyKey(args); },[](const NotifyMotionArgs args) { notifyMotion(args); },[](const NotifySwitchArgs args) { notifySwitch(args); },[](const NotifySensorArgs args) { notifySensor(args); },[](const NotifyVibratorStateArgs args) { notifyVibratorState(args); },[](const NotifyDeviceResetArgs args) { notifyDeviceReset(args); },[](const NotifyPointerCaptureChangedArgs args) { notifyPointerCaptureChanged(args); },};std::visit(v, generalArgs); }void QueuedInputListener::notifyKey(const NotifyKeyArgs args) {traceEvent(__func__, args.id);mArgsQueue.emplace_back(args); }2、flush - 逐个将mArgsQueue中的事件通过队列传递给dispatcher处理 - 泛型的简洁 void QueuedInputListener::flush() {for (const NotifyArgs args : mArgsQueue) {mInnerListener.notify(args);}mArgsQueue.clear(); }2高优先级的按键处理介绍 在PhoneWindowManager.java类中会两个地方会对输入按键进行干预处理 为什么这样设计因为需要优先处理高优先级的按键如global/system key 1、mPolicy.interceptKeyBeforeQueueing(); 1分类-global / system /user key 2处理紧急事件-比如来电显示 2、mPolicy.interceptKeyBeforeDispatching() 1响应处理global/system key 2user key则正常传递到app处理 3、在frameworks中进行按键拦截也主要在PhoneWindowManager下面两个函数加逻辑 interceptKeyBeforeDispatching() interceptKeyBeforeQueueing() 3不同事件按键的处理介绍 不同事件按键会走不同的代码分支这里介绍下重点 场景分析1-global key如AKEYCODE_TV - 快捷键 场景分析2-system key如AKEYCODE_VOLUME_DOWM - 音量按键 场景分析3-user key如AKEYCODE_A、上下左右 - 普通按键一、第一次预处理-interceptKeyBeforeQueueing interceptKeyBeforeQueueing的处理结果会储存到事件结构体entry中后续在InputDispatcher.cpp处理会用到 android/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java interceptKeyBeforeQueueingentry-interceptKeyResult KeyEntry::InterceptKeyResult::UNKNOWN //对于没被处理的输入按键事件都是UNKNOWN POLICY_FLAG_PASS_TO_USER entry-policyFlags POLICY_FLAG_PASS_TO_USER二、第二次预处理 android/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java interceptKeyBeforeDispatching1、对于system key直接处理如 switch(keyCode) {case KeyEvent.KEYCODE_HOME:return handleHomeShortcuts(displayId, focusedToken, event);case KeyEvent.KEYCODE_MENU: ... } return key_consumed;2、对于global key会发送广播如 if (isValidGlobalKey(keyCode) mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {return key_consumed;} return key_consumed;3、对于user key, 在此函数内不处理直接返回 return key_not_consumed;三、第二次预处理后的几种返回值 android/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cppvoid InputDispatcher::doInterceptKeyBeforeDispatchingCommand(const spIBinder focusedWindowToken,KeyEntry entry) {const KeyEvent event createKeyEvent(entry);nsecs_t delay 0;{ // release lockscoped_unlock unlock(mLock);android::base::Timer t;delay mPolicy.interceptKeyBeforeDispatching(focusedWindowToken, event, entry.policyFlags);if (t.duration() SLOW_INTERCEPTION_THRESHOLD) {ALOGW(Excessive delay in interceptKeyBeforeDispatching; took %s ms,std::to_string(t.duration().count()).c_str());}} // acquire lockif (delay 0) {entry.interceptKeyResult KeyEntry::InterceptKeyResult::SKIP; //对应system key/global key} else if (delay 0) {entry.interceptKeyResult KeyEntry::InterceptKeyResult::CONTINUE; //对应user key} else {entry.interceptKeyResult KeyEntry::InterceptKeyResult::TRY_AGAIN_LATER;entry.interceptKeyWakeupTime now() delay;} }四、user key的处理 android/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp 对于user key而言dispatchOnce会执行两次其中第一个循环用于处理global/system key因为优先级更高一些第二循环则处理user key发布到app代码设计如此可自行根据代码琢磨。if (runCommandsLockedInterruptable()) {nextWakeupTime LLONG_MIN; } mLooper-pollOnce(timeoutMillis); //下一轮循环将处理user key,最终发布到app4涉及的Server和Service介绍 1、SystemServer 2、 3、WindowManagerService wm WindowManagerService.main(context, inputManager, !mFirstBoot,new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated */ false,DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);4、 public class PhoneWindowManager implements WindowManagerPolicy {static final String TAG WindowManager; }5、LocalServices.addService(WindowManagerPolicy.class, mPolicy);3、Reader和Dispatcher的创建和启动 了解到Reader和Dispatcher的作用再来从宏观上看看创建和启动过程 1流程图 注意dispatcher线程要优先与reader线程启动那样保证消息能第一次时间被处理 3、SystemServer 开机流程Android系统源码开机启动过程 /android/frameworks/base/services/java/com/android/server/SystemServer.java 八、APP与输入系统的联系 1、总体交互框图 1SystemServer通过(connect →inputchannel → socketpair) 将输入事件传递给app 2、inputchannel 1、场景分析 - inputchannel创建过程分析 1流程图 2值得注意的点 1、APP远程调用WM服务 产生远程调用的语句mWindowSession.addToDisplay()细节分析追溯下mWindowSession1、构造函数中又调用自身的构造函数 mWindowSession在构造函数中赋值 public ViewRootImpl(Context context, Display display) {this(context, display, WindowManagerGlobal.getWindowSession(), new WindowLayout()); }public ViewRootImpl(UiContext Context context, Display display, IWindowSession session, WindowLayout windowLayout) {mContext context;mWindowSession session;... }2、获取server端session android\frameworks\base\core\java\android\view\WindowManagerGlobal.javapublic static IWindowSession getWindowSession() {synchronized (WindowManagerGlobal.class) {if (sWindowSession null) {try {// Emulate the legacy behavior. The global instance of InputMethodManager// was instantiated here.// TODO(b/116157766): Remove this hack after cleaning up UnsupportedAppUsageInputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();IWindowManager windowManager getWindowManagerService();sWindowSession windowManager.openSession( //获取session句柄后续使用session访问server接口new IWindowSessionCallback.Stub() {Overridepublic void onAnimatorScaleChanged(float scale) {ValueAnimator.setDurationScale(scale);}});} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}return sWindowSession;}}public static IWindowManager getWindowManagerService() {synchronized (WindowManagerGlobal.class) {if (sWindowManagerService null) {sWindowManagerService IWindowManager.Stub.asInterface( //binder 中 client调用server接口ServiceManager.getService(window));...}return sWindowManagerService;} }3、哪里会new ViewRootImpl实例 android\frameworks\base\core\java\android\view\WindowManagerGlobal.java mGlobal.addView()中会new一个ViewRootImpl实例 root new ViewRootImpl(view.getContext(), display);小结如何找Framework中的远程调用Binder细节很多我们只需要关注以下几点即可找到1、client调用mWindowSession.addToDisplay()2、根据IWindowManager类推断出存在aidl文件IWindowSession.aidl - out目录下找IWindowSession.java3、确定server 函数位置server端必定会extends IWindowSession.Stub并根据函数名来双重确定java/C层的inputChannel java/C层都对应一个 inputChannel类(包含socketpair fd)用于参数传递 1、java层 android\frameworks\base\core\java\android\view\InputChannel.java 2、C层 android\frameworks\native\libs\input\InputTransport.cpp3、JNI中的转换 jobject inputChannelObj android_view_InputChannel_createJavaObject(env, std::move(*inputChannel));C层inputchannel类 声明android\frameworks\native\include\input\InputTransport.h 定义android\frameworks\native\libs\input\InputTransport.cpp 继承于Parcelable即用于进程间通信的类 1、几个变量 std::string mName; android::base::unique_fd mFd; //保存socker文件句柄 spIBinder mToken;2、创建client server 对应的两个inputChannel及对应两个socker static status_t openInputChannelPair(const std::string name,std::unique_ptrInputChannel outServerChannel,std::unique_ptrInputChannel outClientChannel);3、status_t sendMessage(const InputMessage* msg); //service向fd写msg按键信息4、status_t receiveMessage(InputMessage* msg); //client读fd的msg按键信息sockerpair 传递 android\frameworks\native\libs\input\InputTransport.cpp 1、返回给应用程序的fd需要深拷贝否则返回后会被释放 base::unique_fd InputChannel::dupFd() const {android::base::unique_fd newFd(::dup(getFd()));...}return newFd; }3、APP监听输入事件 APP启动时会先获取到connection再设置启动监听输入事件流程如下 4、Looper将输入事件传递给APP 1从底层传递到上层流程图如下 2重点讲解 1、Response、Request结构体struct Response {SequenceNumber seq;int events;Request request;};struct Request {int fd;int ident;int events;spLooperCallback callback;void* data;uint32_t getEpollEvents() const;};2、onInputEvent()是java层处理输入事件的总入口九、APP层的处理 1、stage 在onInputEvent()函数处理中还有一系列的传递用stage来表示各个阶段的处理其中有针对系统输入法InputMethodManager的处理 1术语 1、ime input method可以理解为系统内置输入法实现 android/frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java 经过输入法处理(app)输出的应是一个kcm对应的字符。 2、synthetic - 综合处理 2Android层-ViewrootImpl 当前焦点应用的ViewrootImpl对象会收到该消息并对消息进行分发处理最终将其发送到对应的View对象中进行界面响应。 3注意对于按键类事件 1、我们关注ime之后的即可 2、view处理不了再传递给Activity处理 3、stage主要关注ViewPreImeInputStage/ViewPostImeInputStage; 2、Framework层的类图 1跟踪代码需要理清以上类的关系 3、代码时序图 重点说明 1、mView/mFocused 以TextView为例 2、按下一个按键的过程APP 完成一次按键按下再松开 按下事件onkeypreIme - onkey(setOnKeyListener) - onkeydown(view) → onkeydownactivity 松开事件onkeypreIme - onkey(setOnKeyListener) - onkeyup(view) -onkeyup (activity) 3、mView一般是一个DecorView (extends View) 表示 Activity.java ViewManager wm getWindowManager(); wm.addView(mDecor, getWindow().getAttributes()); 4、A1 没处理交给 A2依次类推A3 A4 十、项目应用 1、系统定制部分-中控-TVAPI 1从整体的输入系统可知可以在PhoneWindowManager 中interceptKeyBeforeQueueing/interceptKeyBeforeDispatching加入截取逻辑 2PhoneWindowManager 加入中控钩子截取处理中控处理不了再调用tvapi接口继续处理 3中控是为了进一步优化系统性能避免过多的按键影响性能从整个输入系统来看流程是相当之多和复杂的代价就是耗时 4在没有中控之前直接在PhoneWindowManager远程调用tvapi 1、 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {...//CVTE Android Patch Beginif(com.cvte.os.CtvManagerInternal.callGeneric(com.cvte.os.ICtvDataDefine.WHAT_COMMON_HOTKEYMANAGER, cvteInterceptKeyBeforeQueueing, false, event)){return 0;}//CVTE Android Patch End }android\vendor\cvte\cvte-central-control\src\com\cvte\server\manager\CvteHotkeyManager.java public boolean cvteInterceptKeyBeforeQueueing(Object... obj) {... //中控能处理的先处理处理不了再转发给tvapiif (mHotkeyService ! null) {if(event.getKeyCode() CtvPerformanceService.CVTE_KEYEVENT_BASE){LLog.i(TAG,TvApi cvteInterceptKeyBeforeQueueing CvtKeyEvent.KEYCODE_UNKNOWN no need process);return true;//skip CvtKeyEvent.KEYCODE_UNKNOWN, no need process}try {long begin SystemClock.uptimeMillis();boolean ret mHotkeyService.handleKeyEventsBefore(event) || (IS_KERNEL_AT isKeyPadEvent(event)); //转到tvapi处理LLog.i(TAG,TvApi cvteInterceptKeyBeforeQueueing KeyEvent.keyCodeToString(event.getKeyCode()) : KeyEvent.actionToString(event.getAction()) , ret: ret , cost: (SystemClock.uptimeMillis() - begin) ms);return ret;} catch (Exception e) {LLog.e(TAG, Unknown Exception, e);}} else {bindService();return isIntercept(event) || (IS_KERNEL_AT isKeyPadEvent(event));} }2、 public long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event, int policyFlags) {//CVTE Android Patch Beginif (com.cvte.os.CtvManagerInternal.callGeneric(com.cvte.os.ICtvDataDefine.WHAT_COMMON_HOTKEYMANAGER,cvteInterceptKeyBeforeDispatching, false, event)) {return -1;} }android\vendor\cvte\cvte-central-control\src\com\cvte\server\manager\CvteHotkeyManager.javapublic boolean cvteInterceptKeyBeforeDispatching(Object... obj) {KeyEvent event (KeyEvent) obj[0];... //中控能处理的先处理处理不了再转发给tvapiif (mHotkeyService ! null) {try {// LLog.d(TAG, enter cvteInterceptKeyBeforeDispatching onGlobalKeyEvent);long begin SystemClock.uptimeMillis();boolean ret mHotkeyService.handleKeyEvents(event); //转到tvapi处理LLog.i(TAG,TvApi KeyBeforeDispatching KeyEvent.keyCodeToString(event.getKeyCode()) : KeyEvent.actionToString(event.getAction()) , ret: ret , cost: (SystemClock.uptimeMillis() - begin) ms);return ret;} catch (Exception e) {LLog.e(TAG, Unknown Exception, e);}} else {bindService();return isIntercept(event);}return false;}2、CVTE - 无焦点应用优化处理 1、android\frameworks\base\core\java\android\view\ViewRootImpl.java private int processKeyEvent(QueuedInputEvent q) {final KeyEvent event (KeyEvent)q.mEvent;//cvte add beginif(FocusAdapterUtil.getInstance().reflectProcessKeyEventMethodCvte(mView, event)){return FINISH_HANDLED;}//cvte add end }2、 android/frameworks/base/core/java/com/cvte/specialapkviewfocus/FocusAdapterUtil.java android/frameworks/base/core/java/com/cvte/specialapkviewfocus/CvteSpecialApkViewFocusHandlerImpl.java这个类的主要功能是处理特定海外主流APK在某些界面上没有焦点的问题。代码中提到了多个特定的应用程序如Amazon PrimeVideo、Netflix、Gaana和Twitter等并为这些应用提供了特定的焦点处理逻辑。 比如处理Netflix的主页和播放界面焦点问题Amazon PrimeVideo的播放和主页焦点问题以及Gaana和Twitter的登录界面焦点问题它通过模拟用户操作和系统事件来解决焦点问题提升用户体验。3、增加按键映射 https://tvgit.gz.cvte.cn/q/message:PT230025-77 4、APP应用编写代码 只需简单两步即可实现input事件处理 1、实现onKey处理逻辑 public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {public interface OnKeyListener {boolean onKey(View v, int keyCode, KeyEvent event);} } 2、setOnKeyListener(new View.OnkeyListener(){....});十一、调试 1、getevent(linux)linux_key 遥控码 /dev/input/event1: 0004 0004 0088908d /dev/input/event1: 0001 0071 00000001getevent -l /dev/input/event1: EV_MSC MSC_SCAN 00889011 /dev/input/event1: EV_KEY KEY_MUTE DOWNIR底层没有配置则为KEY_UNKNOW BT如果缺少hid会设为默认值Linux ( KEY_UNKNOWN )此时需要去配HID2、sendevent (linux) sendevent 目标设备号 码值 sendevent /dev/input/event5 1 42 13、dumpsys (android) dumpsys input //获取当前设备使用的kl和kcm 注意IR和BT吃的kl不一样连接蓝牙设备后 dumpsys input会变4、input (linux) input keyevent num //模拟遥控器、键盘、鼠标各种输入设备操作
http://www.dnsts.com.cn/news/65454.html

相关文章:

  • 山东省住房和城乡建设局网站燕郊网站制作
  • 全屏网站模板网站怎么做微信接口
  • 网站制作营销型域名服务器搭建
  • 怎么做学校子网站在哪里建设网站
  • php开发网站项目心得服装网站设计
  • 安论坛网站建设深圳网站定制建设
  • 网站建设业务员好做吗百度小程序登录
  • 简洁游戏企业网站平面设计速成班
  • win8风格手机网站模板网站域名查企业邮箱
  • 仁怀市城乡建设网站php做网站都需要学什么
  • 公司有网站域名 如何做网站做网站的需求调研
  • 枣庄高端品牌网站建设案例淮北市重点工程建设局网站
  • wordpress 不能发布成品网站seo
  • 徐州专业做网站较好的公司动漫设计自考大专
  • 龙游网站建设承德在线招聘
  • 淮安建设机械网站网站建设渠道员
  • 电子商务网站开发的主要支撑组件静态wordpress ajax
  • 抚顺网站建设技术员招聘阿里云域名注册官网登录
  • 郴州网站网站建设沭阳网站定制
  • 手机版 演示 网站 触摸精品资料网站
  • 医院手机网站源码wordpress会员小图标
  • 网站关键词格式亚马逊网站建设历程
  • 升阳广州做网站公司深圳正规燃气公司一览表
  • 沧州网站建设沧州印鸽定制软件app
  • 想建设个网站卖东西深圳住房和建设局网站登录
  • 家具展示型网站网页设计入门案例
  • 一个简单的动态页面网站需要数据库吗门户网站举例
  • 中间商可以做网站吗黄冈网站建设公司制作网站
  • 电商网站设计文档郑州网站推广公司
  • 五原网站建设关键词优化公司排行