欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

IOHIDFamily & SpringBoard

最编程 2024-08-13 15:42:39
...

原英文链接:IOHIDFamily

IOHIDFamily是一个内核扩展,它提供了与人类接口设备(HID)的抽象接口,例如触摸屏、按钮、加速度计等。在用户层级,有两种类型的API与IOHIDFamily相关:
(1).公开的,旨在为HID驱动程序编写者;
(2).私有的, 用于事件处理。此文档仅概述私有API。
公开的API文档可以在这里查看 documentation.

Class structure

IOHID的用户总是首先创建一个与整个HID系统接口的IOHIDEventSystem对象。一个事件系统由多个IHIDServiceIOHIDDisplay组成。

服务(Services)是 IOHIDLibPlugin内核插件的各种接口(位于/System/Library/Extensions/IOHIDFamily.kext/PlugIns/IOHIDLib.plugin/IOHIDLib)。它们接受直接的事件输入(比如触摸事件),并且是所有IOHIDEvent事件输入的来源。

显示 (Displays) 显然是指LCD显示屏,IOHIDDisplay 类只能控制亮度,不能控制单个像素的颜色(绘图是由VRAM负责). 你只能通过改变事件系统的属性来间接地控制显示。
IOHID定义了20种事件类型,其中SpringBoard 只处理4种事件:键盘(用于按钮)、数字化器(即触摸屏)、加速度计和靠近事件(温度事件由IOKit直接处理)。每个事件可能包含子事件。
iOS事件是由SpringBoard负责处理的。

例子

#include <IOKit/hid/IOHIDEventSystem.h>
#include <stdio.h>

void handle_event (void* target, void* refcon, IOHIDServiceRef service, IOHIDEventRef event) {
  // handle the events here.
  printf("Received event of type %2d from service %p.\n", IOHIDEventGetType(event), service);
}

int main () {
  // Create and open an event system.
  //创建和打开一个EventSystem
  IOHIDEventSystemRef system = IOHIDEventSystemCreate(NULL);
  IOHIDEventSystemOpen(system, handle_event, NULL, NULL, NULL);
//HID Event system 正在运行,点击屏幕接收到事件可触发handle_event 方法,
//然后Event system会停止运行并退出main方法。
  printf("HID Event system should now be running. Hit enter to quit any time.\n");
  getchar();

  IOHIDEventSystemClose(system, NULL);
  CFRelease(system);
  return 0;
}

Problems with iOS >= 6.1 (or even earlier)

至少从iOS 6.1开始在IOHIDEventSystemCreate的函数中有一个检查,该检查将bundle identifier与“com.apple.springboard”进行比较。如果该检查失败,函数将返回NULL。因此,除非你绕过这个检查,否则你就不能再在应用程序中使用HID系统了,苹果应该偷偷换成别的方式创建事件系统了。

__text:0001561A loc_1561A                               ; CODE XREF: _IOHIDEventSystemCreate+7E�j
__text:0001561A                 MOV             R0, R4
__text:0001561C                 MOVS            R2, #0xC4 ; ''
__text:0001561E                 MOVS            R3, #0
__text:00015620                 MOVS            R5, #0
__text:00015622                 BLX             __CFRuntimeCreateInstance
__text:00015626                 MOV             R4, R0
__text:00015628                 CMP             R4, #0
__text:0001562A                 BEQ.W           loc_1584A
__text:0001562E                 ADD.W           R5, R4, #8
__text:00015632                 MOVS            R1, #0  ; int
__text:00015634                 MOV             R0, R5  ; void *
__text:00015636                 MOVS            R2, #0xC4 ; '' ; size_t
__text:00015638                 BLX             _memset ; Initialize the struct's variables to zero.
__text:0001563C                 BLX             _CFBundleGetMainBundle ; Get the main bundle
__text:00015640                 CBZ             R0, loc_15660 ; Go to loc_15660 if it returned NULL.
__text:00015642                 BLX             _CFBundleGetIdentifier ; Get the bundle's identifier.
__text:00015646                 CBZ             R0, loc_15660 ; Go to loc_15660 if the identifier is NULL.
__text:00015648                 MOV             R1, #(cfstr_Com_apple_spri - 0x15654) ; "com.apple.springboard"
__text:00015650                 ADD             R1, PC  ; "com.apple.springboard"
__text:00015652                 BLX             _CFEqual ; Check if the main bundle's identifier is equal to com.apple.springboard.
__text:00015656                 CMP             R0, #0 ; If the check returned false, return. 
__text:00015658                 ITT NE
__text:0001565A                 MOVNE           R0, #1
__text:0001565C                 STRNEB.W        R0, [R4,#0xB8]
__text:00015660
__text:00015660 loc_15660                               ; CODE XREF: _IOHIDEventSystemCreate+C0�j
__text:00015660                                         ; _IOHIDEventSystemCreate+C6�j
__text:00015660                 ADD.W           R8, R4, #0x38
__text:00015664                 MOVS            R1, #0  ; attr
__text:00015666                 MOV             R0, R8  ; rwlock
__text:00015668                 BLX             _pthread_rwlock_init
__text:0001566C                 CMP             R0, #0
__text:0001566E                 BNE.W           loc_15792

Services

要访问这些服务,您必须首先使用IOHIDEventSystemCopyMatchingServices匹配它们。这些标准可以使用ioreg -l命令获得。

Service Name match CFBundleIdentifier PrimaryUsagePage PrimaryUsage
AppleLIS302DL (Accelerometer) accelerometer,lis302dl com.apple.driver.AppleEmbeddedAccelerometer 0xff00 3
AppleISL29003 (ALS) als,isl29003 com.apple.driver.AppleEmbeddedLightSensor 0xff00 4
AppleProxShim (ProximitySensor) als,ct700 com.apple.driver.AppleIntegratedProxALSSensor 0xff00 8
AppleM68Buttons (Buttons) buttons com.apple.driver.AppleM68Buttons 11 1
AppleMultitouchZ2SPI (Touchscreen) multi-touch,z2 com.apple.driver.AppleMultitouchSPI - -

Keyboard events键盘事件

iOS按钮事件实际上被视为“键盘”事件,这里的按钮事件并不是指UIButton的点击事件。下面显示有哪些事件是按钮事件。

Usage page Usage Button
1 0x83 Wake up SBUIController wakeUp:] in SpringBoard.)
7 - Hardware keyboard events 硬件键盘事件
11 0x21 Headset button耳机按钮
11 0x23 Obsolete hold 过时的握柄
11 0x2e Ringer套环
12 0x30 Lock手机锁屏按钮
12 0x40, 0x223 Menu菜单
12 0xb3 Fast forward快进按钮
12 0xb4 Rewind快退
12 0xb5 Scan Next Track扫描下一个
12 0xe2 Mute静音按钮
12 0xb8, 0x1ae Media key (to toggle the soft keyboard)切换软键盘
12 0xe9 Volume increase音量加
12 0xea Volume decrease音量减
0xff01 ≤0x20 Apple vender keyboard event苹果供应商键盘事件
0xff07 1 Headset availability changed耳机可用性改变

SpringBoard

SpringBoard是iPhone的应用程序启动器;它提供所有应用程序启动服务、图标管理、状态栏控制,等等,SpringBoard 是一个单例类管理着SpringBoard 应用。

从iOS 6开始,一些SpringBoard的功能现在在backboardd.

Workflow logging

SpringBoard保留UNIX信号31(SIGUSR2)来切换工作流日志记录。它可以记录来自显示堆栈的按下/弹出显示、应用程序启动等。从iOS 6.0开始,这个信号将切换SBWorkspace日志记录;它将输出到/tmp/SBWorkspaceLogs-date.log和syslog。
向SpringBoard发送信号31将在这4种日志类型之间切换:

  1. Stop logging.
  2. Start silent logging.
  3. Start logging to syslog.
  4. Dump workflow log.

HID logging

跳板保留UNIX信号30(SIGUSR1)来切换HID日志记录。它可以记录多点触摸事件、加速度计事件、按钮按下等。
向SpringBoard发送信号30将在这6种日志类型之间切换:

  1. Off.
  2. SpringBoard Events
  3. MultiTouch Gesture Events 多点触摸手势事件
  4. MultiTouch HID Events 多点触摸事件
  5. MultiTouch HID & Gesture Events 多点触摸HID和手势事件
  6. Accelerometer events 加速计事件

Monitoring Orientation of Top App

每当当前应用程序的方向发生改变时,[SpringBoard noteUIOrientationChanged:display:]被调用。因此,可以挂钩(hook)此方法以做事件通知。
你也可以挂钩SpringBoard的方法
-(void)noteInterfaceOrientationChanged:(int)arg1 duration:(float)arg2

Orientation

activeInterfaceOrientation 显示当前应用方向

interfaceOrientationForCurrentDeviceOrientation 显示设备方向

问:什么时候会有所不同?

答:如果你把设备在portrait方向锁定,但是有一个游戏在landscape中运行,这两个值就会不同。activeInterfaceOrientation将处于landscape方向,而interfaceOrientationForCurrentDeviceOrientation仍将处于锁定的portrait方向。

Sending messages to SpringBoard

因为SpringBoard是从UIApplication继承的,所以您可以按照以下方式向它发送消息:
[[SpringBoard sharedApplication] aMethod]

Getting the top SBApplication

可以使用以下方法获得顶部SBApplication的引用:[[SpringBoard sharedApplication] _accessibilityFrontMostApplication].

Monitoring when a new app or the homescreen is displayed

无论app什么时候被显示 frontDisplayDidChange:(id)newDisplay 会被调用,newDisplay 是当前的被切换显示的app的引用(类型是SBApplication指针),如果显示的是桌面屏幕则newDisplaynil;然而,在某些情况下,它可能是一个UIViewController的引用,比如当前进入锁屏状态时,newDisplay会是一个SBLockScreenViewController实例对象的引用。