Android 支持各種觸摸屏和触摸板,包括基於手寫筆的數字化板。
觸摸屏是與顯示器相關聯的觸摸設備,使得用戶具有直接操縱屏幕上的項目的印象。
觸摸板是與顯示器無關的觸摸設備,例如數字化板。觸摸板通常用於指向或用於絕對間接定位或用戶界面的基於手勢的控制。
觸摸設備可能具有功能類似於鼠標按鈕的按鈕。
觸摸設備有時可以使用各種不同的工具(例如手指或手寫筆)進行操作,具體取決於底層觸摸傳感器技術。
觸摸設備有時用於實現虛擬鍵。例如,在某些 Android 設備上,觸摸屏傳感器區域延伸到顯示屏邊緣之外,並作為觸摸感應鍵盤的一部分起到雙重作用。
由於觸摸設備種類繁多,Android 依賴大量的配置屬性來描述每個設備的特性和期望的行為。
觸控設備分類
如果滿足以下兩個條件,則輸入設備被歸類為多點觸控設備:
輸入設備報告存在
ABS_MT_POSITION_X
和ABS_MT_POSITION_Y
絕對軸。輸入設備沒有任何遊戲手柄按鈕。此條件解決了某些遊戲手柄的歧義,這些遊戲手柄報告軸的代碼與 MT 軸的代碼重疊。
如果滿足以下兩個條件,則輸入設備被歸類為單點觸摸設備:
輸入設備不屬於多點觸控設備。輸入設備要么被歸類為單點觸控設備,要么被歸類為多點觸控設備,而不能同時歸為兩者。
輸入設備報告
ABS_X
和ABS_Y
絕對軸的存在,以及BTN_TOUCH
鍵碼的存在。
一旦輸入設備被歸類為觸摸設備,就可以通過嘗試加載設備的虛擬鍵映射文件來確定虛擬鍵的存在。如果虛擬鍵映射可用,則還會加載設備的鍵佈局文件。
請參閱以下有關虛擬鍵映射文件的位置和格式的部分。
接下來,系統加載觸摸設備的輸入設備配置文件。
所有內置觸摸設備都應該有輸入設備配置文件。如果不存在輸入設備配置文件,系統將選擇適用於典型通用觸摸外圍設備(例如外部 USB 或藍牙 HID 觸摸屏或觸摸板)的默認配置。這些默認值不是為內置觸摸屏設計的,很可能會導致不正確的行為。
加載輸入設備配置後,系統會將輸入設備分類為觸摸屏、觸摸板或指針設備。
觸摸屏設備用於直接操作屏幕上的對象。由於用戶直接觸摸屏幕,系統不需要任何額外的提示來指示正在操作的對象。
觸摸板設備用於向應用程序提供關於給定傳感器區域上的觸摸的絕對定位信息。它可能對數字化板有用。
指針設備用於使用光標間接操作屏幕上的對象。手指被解釋為多點觸控指針手勢。其他工具(例如手寫筆)使用絕對位置進行解釋。
有關詳細信息,請參閱間接多點觸控指針手勢。
以下規則用於將輸入設備分類為觸摸屏、觸摸板或指針設備。
如果設置了
touch.deviceType
屬性,則設備類型將按指示設置。如果輸入設備報告存在
INPUT_PROP_DIRECT
輸入屬性(通過EVIOCGPROP
ioctl),則設備類型將設置為touch screen 。此條件假定直接輸入觸摸設備連接到也已連接的顯示器。如果輸入設備報告存在
INPUT_PROP_POINTER
輸入屬性(通過EVIOCGPROP
ioctl),則設備類型將設置為pointer 。如果輸入設備報告存在
REL_X
或REL_Y
相對軸,則設備類型將設置為touch pad 。此條件解決了由鼠標和触摸板組成的輸入設備的歧義。在這種情況下,觸摸板將不會用於控制指針,因為鼠標已經控制了它。否則,設備類型將被設置為pointer 。此默認設置確保未指定任何其他特殊用途的觸摸板將用於控制指針。
鈕扣
按鈕是可選的控件,應用程序可以使用它們來執行附加功能。觸摸設備上的按鈕與鼠標按鈕的行為類似,主要用於指針式觸摸設備或手寫筆。
支持以下按鈕:
BTN_LEFT
:映射到MotionEvent.BUTTON_PRIMARY
。BTN_RIGHT
:映射到MotionEvent.BUTTON_SECONDARY
。BTN_MIDDLE
:映射到MotionEvent.BUTTON_MIDDLE
。BTN_BACK
和BTN_SIDE
:映射到MotionEvent.BUTTON_BACK
。按下此按鈕還會合成按鍵代碼為KeyEvent.KEYCODE_BACK
的按鍵。BTN_FORWARD
和BTN_EXTRA
:映射到MotionEvent.BUTTON_FORWARD
。按下此按鈕還會合成按鍵代碼為KeyEvent.KEYCODE_FORWARD
的按鍵。BTN_STYLUS
:映射到MotionEvent.BUTTON_SECONDARY
。BTN_STYLUS2
:映射到MotionEvent.BUTTON_TERTIARY
。
工具和工具類型
工具是手指、手寫筆或其他用於與觸摸設備交互的裝置。一些觸摸設備可以區分不同類型的工具。
在 Android 的其他地方,如在MotionEvent
API 中,工具通常稱為指針。
支持以下工具類型:
BTN_TOOL_FINGER
和MT_TOOL_FINGER
:映射到MotionEvent.TOOL_TYPE_FINGER
。BTN_TOOL_PEN
和MT_TOOL_PEN
:映射到MotionEvent.TOOL_TYPE_STYLUS
。BTN_TOOL_RUBBER
:映射到MotionEvent.TOOL_TYPE_ERASER
。BTN_TOOL_BRUSH
:映射到MotionEvent.TOOL_TYPE_STYLUS
。BTN_TOOL_PENCIL
:映射到MotionEvent.TOOL_TYPE_STYLUS
。BTN_TOOL_AIRBRUSH
:映射到MotionEvent.TOOL_TYPE_STYLUS
。BTN_TOOL_MOUSE
:映射到MotionEvent.TOOL_TYPE_MOUSE
。BTN_TOOL_LENS
:映射到MotionEvent.TOOL_TYPE_MOUSE
。BTN_TOOL_DOUBLETAP
、BTN_TOOL_TRIPLETAP
和BTN_TOOL_QUADTAP
:映射到MotionEvent.TOOL_TYPE_FINGER
。
懸停與觸摸工具
工具可以與觸摸設備接觸,也可以在其範圍內並懸停在其上方。並非所有觸摸設備都能夠感測到懸停在觸摸設備上方的工具的存在。那些這樣做的,例如基於 RF 的手寫筆數字化儀,通常可以檢測工具何時在數字化儀的有限範圍內。
InputReader
組件負責區分觸摸工具和懸停工具。同樣,觸摸工具和懸停工具以不同的方式報告給應用程序。
使用MotionEvent.ACTION_DOWN
、 MotionEvent.ACTION_MOVE
、 MotionEvent.ACTION_DOWN
、 MotionEvent.ACTION_POINTER_DOWN
和MotionEvent.ACTION_POINTER_UP
將觸摸工具作為觸摸事件報告給應用程序。
使用MotionEvent.ACTION_HOVER_ENTER
、 MotionEvent.ACTION_HOVER_MOVE
和MotionEvent.ACTION_HOVER_EXIT
將懸停工具作為通用運動事件報告給應用程序。
觸摸設備驅動程序要求
觸摸設備驅動程序應該只為它們實際支持的軸和按鈕註冊軸和鍵代碼。註冊過多的軸或鍵代碼可能會混淆設備分類算法或導致系統錯誤地檢測設備的功能。
例如,如果設備報告
BTN_TOUCH
鍵碼,系統將假定BTN_TOUCH
將始終用於指示工具是否實際觸摸屏幕。因此,不應使用BTN_TOUCH
來指示工具僅在範圍內和懸停。單點觸控設備使用以下 Linux 輸入事件:
ABS_X
:(必需)報告工具的 X 坐標。ABS_Y
:(必需)報告工具的 Y 坐標。ABS_PRESSURE
:(可選)報告施加到工具尖端的物理壓力或觸摸觸點的信號強度。ABS_TOOL_WIDTH
:(可選)報告觸摸觸點或工具本身的橫截面積或寬度。ABS_DISTANCE
:(可選)報告工具與觸摸設備表面的距離。ABS_TILT_X
:(可選)報告工具從觸摸設備表面沿 X 軸的傾斜度。ABS_TILT_Y
:(可選)報告工具從觸摸設備表面沿 Y 軸的傾斜度。BTN_TOUCH
:(必需)指示工具是否正在接觸設備。BTN_LEFT
、BTN_RIGHT
、BTN_MIDDLE
、BTN_BACK
、BTN_SIDE
、BTN_FORWARD
、BTN_EXTRA
、BTN_STYLUS
、BTN_STYLUS2
:(可選)報告按鈕狀態。BTN_TOOL_FINGER
,BTN_TOOL_PEN
,BTN_TOOL_RUBBER
,BTN_TOOL_BRUSH
,BTN_TOOL_PENCIL
,BTN_TOOL_AIRBRUSH
,BTN_TOOL_MOUSE
,BTN_TOOL_LENS
,BTN_TOOL_DOUBLETAP
,BTN_TOOL_TRIPLETAP
,BTN_TOOL_QUADTAP
報告工具類型:(可選)
多點觸控設備使用以下 Linux 輸入事件:
ABS_MT_POSITION_X
:(必需)報告工具的 X 坐標。ABS_MT_POSITION_Y
:(必需)報告工具的 Y 坐標。ABS_MT_PRESSURE
:(可選)報告施加到工具尖端的物理壓力或觸摸接觸的信號強度。ABS_MT_TOUCH_MAJOR
:(可選)報告觸摸接觸的橫截面積,或觸摸接觸的較長尺寸的長度。ABS_MT_TOUCH_MINOR
:(可選)報告觸摸接觸的較短尺寸的長度。如果ABS_MT_TOUCH_MAJOR
正在報告面積測量,則不應使用該軸。ABS_MT_WIDTH_MAJOR
:(可選)報告工具本身的橫截面積,或工具本身較長尺寸的長度。如果工具本身的尺寸未知,則不應使用此軸。ABS_MT_WIDTH_MINOR
:(可選)報告工具本身較短尺寸的長度。如果ABS_MT_WIDTH_MAJOR
正在報告面積測量值或工具本身的尺寸未知,則不應使用該軸。ABS_MT_ORIENTATION
:(可選)報告工具的方向。ABS_MT_DISTANCE
:(可選)報告工具與觸摸設備表面的距離。ABS_MT_TOOL_TYPE
:(可選)將工具類型報告為MT_TOOL_FINGER
或MT_TOOL_PEN
。ABS_MT_TRACKING_ID
:(可選)報告工具的跟踪 ID。跟踪 ID 是一個任意的非負整數,用於在多個工具處於活動狀態時獨立地識別和跟踪每個工具。例如,當多個手指觸摸設備時,每個手指都應分配一個不同的跟踪 ID,只要手指保持接觸,就會使用該 ID。當相關工具移出範圍時,跟踪 ID 可能會被重複使用。ABS_MT_SLOT
:(可選)在使用 Linux 多點觸控協議“B”時報告工具的插槽 ID。有關詳細信息,請參閱 Linux 多點觸控協議文檔。BTN_TOUCH
:(必需)指示工具是否正在接觸設備。BTN_LEFT
、BTN_RIGHT
、BTN_MIDDLE
、BTN_BACK
、BTN_SIDE
、BTN_FORWARD
、BTN_EXTRA
、BTN_STYLUS
、BTN_STYLUS2
:(可選)報告按鈕狀態。BTN_TOOL_FINGER
,BTN_TOOL_PEN
,BTN_TOOL_RUBBER
,BTN_TOOL_BRUSH
,BTN_TOOL_PENCIL
,BTN_TOOL_AIRBRUSH
,BTN_TOOL_MOUSE
,BTN_TOOL_LENS
,BTN_TOOL_DOUBLETAP
,BTN_TOOL_TRIPLETAP
,BTN_TOOL_QUADTAP
報告工具類型:(可選)
如果同時定義了單點觸摸和多點觸摸協議的軸,則將僅使用多點觸摸軸,而忽略單點觸摸軸。
ABS_X
、ABS_Y
、ABS_MT_POSITION_X
和ABS_MT_POSITION_Y
軸的最小值和最大值以設備特定的表面單位定義設備活動區域的邊界。在觸摸屏的情況下,活動區域描述了觸摸設備實際覆蓋顯示屏的部分。對於觸摸屏,系統會根據以下計算自動對上報的以表面為單位的觸摸位置進行插值,得到以顯示像素為單位的觸摸位置:
displayX = (x - minX) * displayWidth / (maxX - minX + 1) displayY = (y - minY) * displayHeight / (maxY - minY + 1)
觸摸屏可能會報告報告的活動區域之外的觸摸。
在活動區域外啟動的觸摸不會傳送到應用程序,但可用於虛擬鍵。
在活動區域內啟動的觸摸,或進入和離開顯示區域的觸摸被傳送到應用程序。因此,如果觸摸在應用程序的邊界內開始,然後移出活動區域,則應用程序可能會收到顯示坐標為負或超出顯示邊界的觸摸事件。這是預期的行為。
觸摸設備永遠不應將觸摸坐標限制在活動區域的邊界內。如果觸摸離開活動區域,則應將其報告為活動區域外,或者根本不報告。
例如,如果用戶的手指在觸摸屏的左上角附近觸摸,它可能會報告坐標 (minX, minY)。如果手指繼續移動到活動區域之外,觸摸屏應該開始報告坐標小於 minX 和 minY 的坐標,例如 (minX - 2, minY - 3),或者它應該完全停止報告觸摸。換句話說,當用戶的手指真正觸摸到活動區域之外時,觸摸屏不應報告 (minX, minY)。
將觸摸坐標夾緊到顯示邊緣會在屏幕邊緣周圍創建一個人為的硬邊界,這會阻止系統平滑地跟踪進入或離開顯示區域邊界的運動。
ABS_PRESSURE
或ABS_MT_PRESSURE
報告的值(如果有的話)在工具接觸設備時必須為非零,否則為零以指示工具懸停。報告壓力信息是可選的,但強烈建議。應用程序可以使用壓力信息來實現壓敏繪圖等效果。
當工具接觸設備時,
ABS_TOOL_WIDTH
、ABS_MT_TOUCH_MAJOR
、ABS_MT_TOUCH_MINOR
、ABS_MT_WIDTH_MAJOR
或ABS_MT_WIDTH_MINOR
報告的值應為非零,否則為零,但這不是必需的。例如,觸摸設備可能能夠測量手指觸摸接觸的尺寸,但不能測量手寫筆觸摸接觸的尺寸。報告大小信息是可選的,但強烈建議。應用程序可以使用壓力信息來實現大小敏感繪圖和其他效果。
當工具接觸設備時,
ABS_DISTANCE
或ABS_MT_DISTANCE
報告的值應接近零。即使工具直接接觸,該距離也可能保持非零。報告的確切值取決於硬件測量距離的方式。報告距離信息是可選的,但建議用於手寫筆設備。
當工具垂直於設備時,
ABS_TILT_X
和ABS_TILT_Y
報告的值應為零。非零傾斜表示工具保持在傾斜狀態。假定沿 X 軸和 Y 軸的傾斜角以與垂直線的度數為單位指定。每個軸的中心點(完全垂直)由
(max + min) / 2
給出。小於中心點的值表示向上或向左傾斜,大於中心點的值表示向下或向右傾斜。InputReader
將 X 和 Y 傾斜分量轉換為範圍從 0 到PI / 2
弧度的垂直傾斜角和範圍從-PI
到PI
弧度的平面方向角。這種表示導致方向描述與用於描述手指觸摸的內容兼容。報告傾斜信息是可選的,但建議用於手寫筆設備。
如果工具類型由
ABS_MT_TOOL_TYPE
報告,它將取代BTN_TOOL_*
報告的任何工具類型信息。如果根本沒有可用的工具類型信息,則工具類型默認為MotionEvent.TOOL_TYPE_FINGER
。根據以下條件確定工具處於活動狀態:
使用單點觸控協議時,如果
BTN_TOUCH
或BTN_TOOL_*
為 1,則該工具處於活動狀態。此條件意味著
InputReader
至少需要了解一些有關工具性質的信息,無論是接觸還是工具類型。如果沒有可用信息,則假定該工具處於非活動狀態(超出範圍)。使用多點觸控協議“A”時,只要該工具出現在最近的同步報告中,它就會處於活動狀態。當該工具停止出現在同步報告中時,它就不復存在了。
使用多點觸控協議“B”時,只要有活動插槽,該工具就會處於活動狀態。當插槽被清除時,該工具將不復存在。
根據以下條件確定工具懸停:
如果工具是
BTN_TOOL_MOUSE
或BTN_TOOL_LENS
,則工具不會懸停,即使以下任一條件為真。如果工具處於活動狀態並且驅動程序報告壓力信息,並且報告的壓力為零,則工具懸停。
如果該工具處於活動狀態且驅動程序支持
BTN_TOUCH
鍵碼且BTN_TOUCH
的值為零,則該工具處於懸停狀態。
InputReader
支持多點觸控協議“A”和“B”。新的驅動程序應該使用“B”協議,但兩者都可以。從 Android Ice Cream Sandwich 4.0 開始,可能需要更改觸摸屏驅動程序以符合 Linux 輸入協議規範。
可能需要進行以下更改:
當工具變為非活動狀態(手指“向上”)時,它應該停止出現在後續的多點觸控同步報告中。當所有工具都變為非活動狀態(所有手指都“向上”)時,驅動程序應發送一個空的同步報告數據包,例如
SYN_MT_REPORT
後跟SYN_REPORT
。以前版本的 Android 期望通過發送壓力值 0 來報告“向上”事件。舊行為與 Linux 輸入協議規範不兼容,不再受支持。
應使用
ABS_MT_PRESSURE
報告物理壓力或信號強度信息。以前版本的 Android 從
ABS_MT_TOUCH_MAJOR
檢索壓力信息。舊行為與 Linux 輸入協議規範不兼容,不再受支持。應使用
ABS_MT_TOUCH_MAJOR
報告觸摸大小信息。以前版本的 Android 從
ABS_MT_TOOL_MAJOR
檢索尺寸信息。舊行為與 Linux 輸入協議規範不兼容,不再受支持。
觸摸設備驅動程序不再需要特定於 Android 的自定義設置。依靠標準的 Linux 輸入協議,Android 可以使用未修改的驅動程序支持更廣泛的觸摸外圍設備,例如外部 HID 多點觸控觸摸屏。
觸摸設備操作
下面簡單總結一下Android上的觸摸設備操作。
EventHub
從evdev
驅動程序讀取原始事件。InputReader
使用原始事件並更新有關每個工具的位置和其他特徵的內部狀態。它還跟踪按鈕狀態。如果 BACK 或 FORWARD 按鈕被按下或釋放,
InputReader
會通知InputDispatcher
有關按鍵事件。InputReader
確定是否發生了虛擬按鍵按下。如果是,它會通知InputDispatcher
有關按鍵事件。InputReader
確定觸摸是否在顯示範圍內啟動。如果是,它會通知InputDispatcher
關於觸摸事件。如果沒有觸摸工具但至少有一個懸停工具,則
InputReader
將懸停事件通知給InputDispatcher
。如果觸摸設備類型是pointer ,
InputReader
執行指針手勢檢測,相應地移動指針和點,並通知InputDispatcher
有關指針事件。InputDispatcher
使用WindowManagerPolicy
來確定是否應分派事件以及是否應喚醒設備。然後,InputDispatcher
將事件傳遞給適當的應用程序。
觸摸設備配置
觸摸設備行為由設備的軸、按鈕、輸入屬性、輸入設備配置、虛擬鍵映射和鍵佈局決定。
有關參與鍵盤配置的文件的更多詳細信息,請參閱以下部分:
特性
系統依賴於許多輸入設備配置屬性來配置和校準觸摸設備行為。
原因之一是觸摸設備的設備驅動程序經常使用特定於設備的單元來報告觸摸的特徵。
例如,許多觸摸設備使用內部設備特定的尺度來測量觸摸接觸面積,例如觸摸觸發的傳感器節點總數。這個原始尺寸值對應用程序沒有意義,因為它們需要了解觸摸設備傳感器節點的物理尺寸和其他特性。
該系統使用輸入設備配置文件中編碼的校準參數來解碼、轉換和規範化觸摸設備報告的值,使其成為應用程序可以理解的更簡單的標準表示形式。
文檔約定
出於文檔目的,我們將使用以下約定來描述系統在校準過程中使用的值。
原始軸值
以下表達式表示觸摸設備驅動程序報告為EV_ABS
事件的原始值。
-
raw.x
-
ABS_X
或ABS_MT_POSITION_X
軸的值。 -
raw.y
-
ABS_Y
或ABS_MT_POSITION_Y
軸的值。 -
raw.pressure
-
ABS_PRESSURE
或ABS_MT_PRESSURE
軸的值,如果不可用則為 0。 -
raw.touchMajor
-
ABS_MT_TOUCH_MAJOR
軸的值,如果不可用則為 0。 -
raw.touchMinor
-
ABS_MT_TOUCH_MINOR
軸的值,如果不可用,raw.touchMajor
。 -
raw.toolMajor
-
ABS_TOOL_WIDTH
或ABS_MT_WIDTH_MAJOR
軸的值,如果不可用則為 0。 -
raw.toolMinor
-
ABS_MT_WIDTH_MINOR
軸的值,如果不可用,raw.toolMajor
。 -
raw.orientation
-
ABS_MT_ORIENTATION
軸的值,如果不可用則為 0。 -
raw.distance
-
ABS_DISTANCE
或ABS_MT_DISTANCE
軸的值,如果不可用則為 0。 -
raw.tiltX
-
ABS_TILT_X
軸的值,如果不可用則為 0。 -
raw.tiltY
-
ABS_TILT_Y
軸的值,如果不可用則為 0。
原始軸範圍
以下表達式表示原始值的範圍。它們是通過為每個軸調用EVIOCGABS
ioctl 獲得的。
-
raw.*.min
- 原始軸的包含最小值。
-
raw.*.max
- 原始軸的包含最大值。
-
raw.*.range
- 相當於
raw.*.max - raw.*.min
。 -
raw.*.fuzz
- 原始軸的精度。例如。 fuzz = 1 表示值精確到 +/- 1 個單位。
-
raw.width
- 觸摸區域包含的寬度,相當於
raw.x.range + 1
。 -
raw.height
- 觸摸區域包含的高度,相當於
raw.y.range + 1
。
輸出範圍
以下表達式表示輸出坐標系的特徵。該系統使用線性插值將觸摸位置信息從觸摸設備使用的表面單位轉換為將報告給顯示像素等應用程序的輸出單位。
-
output.width
- 輸出寬度。對於觸摸屏(與顯示器相關聯),這是以像素為單位的顯示寬度。對於觸摸板(不與顯示器關聯),輸出寬度等於
raw.width
,表示不會執行插值。 -
output.height
- 輸出高度。對於觸摸屏(與顯示器相關聯),這是以像素為單位的顯示高度。對於觸摸板(與顯示器無關),輸出高度等於
raw.height
,表示不會執行插值。 -
output.diag
- 輸出坐標系的對角線長度,相當於
sqrt(output.width ^2 + output.height ^2)
。
基本配置
觸摸輸入映射器使用輸入設備配置文件中的許多配置屬性來指定校準值。下表描述了一些通用配置屬性。所有其他屬性以及它們用於校準的字段將在以下部分中進行描述。
touch.deviceType
定義: touch.deviceType
= touchScreen
| touchPad
| pointer
| default
指定觸摸設備類型。
如果值為
touchScreen
,則觸摸設備是與顯示器關聯的觸摸屏。如果值為
touchPad
,則觸摸設備是與顯示器無關的觸摸板。如果值為
pointer
,則觸摸設備是與顯示器無關的觸摸板,其動作用於間接多點觸摸指針手勢。如果取值為
default
,系統會根據分類算法自動檢測設備類型。
有關設備類型如何影響觸摸設備行為的更多詳細信息,請參閱分類部分。
在 Honeycomb 之前,所有觸摸設備都被認為是觸摸屏。
touch.orientationAware
定義: touch.orientationAware
= 0
| 1
指定觸摸設備是否應對顯示方向變化作出反應。
如果該值為
1
,則只要顯示方向發生變化,觸摸設備報告的觸摸位置就會旋轉。如果該值為
0
,則觸摸設備報告的觸摸位置不受顯示方向更改的影響。
如果設備是觸摸屏,則默認值為1
,否則為0
。
系統區分內部和外部觸摸屏和顯示器。方向感知內部觸摸屏根據內部顯示器的方向旋轉。方向感知外部觸摸屏基於外部顯示器的方向旋轉。
方向感知用於支持 Nexus One 等設備上觸摸屏的旋轉。例如,當設備從其自然方向順時針旋轉 90 度時,觸摸的絕對位置將被重新映射,使得觸摸屏絕對坐標系左上角的觸摸被報告為左上角的觸摸顯示器旋轉坐標系的角點。這樣做是為了使用與應用程序用來繪製其視覺元素的坐標系相同的坐標係來報告觸摸。
在 Honeycomb 之前,所有觸摸設備都被認為是方向感知的。
touch.gestureMode
定義: touch.gestureMode
= pointer
| spots
| default
指定指針手勢的呈現模式。此配置屬性僅在觸摸設備的類型為pointer時才相關。
如果值為
pointer
,則觸摸板手勢將通過類似於鼠標指針的光標呈現。如果值為
spots
,則觸摸板手勢由表示手勢質心的錨點和表示各個手指位置的一組圓形點表示。
當設置了INPUT_PROP_SEMI_MT
輸入屬性時,默認值為pointer
,否則為spots
。
X
和Y
字段
X 和 Y 字段提供接觸區域中心的位置信息。
計算
計算很簡單:來自觸摸驅動器的位置信息被線性插值到輸出坐標系。
xScale = output.width / raw.width yScale = output.height / raw.height If not orientation aware or screen rotation is 0 degrees: output.x = (raw.x - raw.x.min) * xScale output.y = (raw.y - raw.y.min) * yScale Else If rotation is 90 degrees: output.x = (raw.y - raw.y.min) * yScale output.y = (raw.x.max - raw.x) * xScale Else If rotation is 180 degrees: output.x = (raw.x.max - raw.x) * xScale output.y = (raw.y.max - raw.y) * yScale Else If rotation is 270 degrees: output.x = (raw.y.max - raw.y) * yScale output.y = (raw.x - raw.x.min) * xScale End If
TouchMajor
, TouchMinor
, ToolMajor
, ToolMinor
, Size
字段
TouchMajor
和TouchMinor
字段以輸出單位(像素)描述接觸區域的近似尺寸。
ToolMajor
和ToolMinor
字段以輸出單位(像素)描述工具本身的近似尺寸。
Size
字段描述了相對於觸摸設備可以感應到的最大可能觸摸的標準化觸摸大小。最小可能的歸一化尺寸為 0.0(無接觸,或者無法測量),最大可能的歸一化尺寸為 1.0(傳感器區域飽和)。
當可以測量近似長度和寬度時, TouchMajor
字段指定接觸區域的較長維度, TouchMinor
字段指定接觸區域的較短維度。當只能測量接觸區域的近似直徑時, TouchMajor
和TouchMinor
字段將相等。
同樣, ToolMajor
字段指定較長的尺寸,而ToolMinor
字段指定工具橫截面積的較短尺寸。
如果觸摸尺寸不可用但工具尺寸可用,則工具尺寸將設置為等於觸摸尺寸。相反,如果工具尺寸不可用但觸摸尺寸可用,則觸摸尺寸將設置為等於工具尺寸。
觸摸設備以各種方式測量或報告觸摸尺寸和工具尺寸。當前的實現支持三種不同類型的測量:直徑、面積和表面單位的幾何邊界框。
touch.size.calibration
定義: touch.size.calibration
= none
| geometric
| diameter
| area
| default
指定觸摸驅動程序用於報告觸摸大小和工具大小的測量類型。
如果值為
none
,則大小設置為零。如果值為
geometric
,則假定大小以與位置相同的表面單位指定,因此它以相同的方式縮放。如果值為
diameter
,則假定大小與觸摸或工具的直徑(寬度)成正比。如果值為
area
,則假定大小與觸摸或工具的面積成比例。如果值為
default
,如果raw.touchMajor
或raw.toolMajor
軸可用,系統將使用geometric
校準,否則使用none
校準。
touch.size.scale
定義: touch.size.scale
= <一個非負浮點數>
指定校準中使用的常數比例因子。
默認值為1.0
。
touch.size.bias
定義: touch.size.bias
= <一個非負浮點數>
指定校準中使用的恆定偏差值。
默認值為0.0
。
touch.size.isSummed
定義: touch.size.isSummed
= 0
| 1
指定是將大小報告為所有活動接觸的大小總和,還是針對每個接觸單獨報告。
如果該值為
1
,則報告的大小將除以使用前的聯繫人數量。如果值為
0
,則報告的大小將按原樣使用。
默認值為0
。
某些觸摸設備,尤其是“Semi-MT”設備無法區分多個觸點的各個尺寸,因此它們會報告代表其總面積或寬度的尺寸測量值。對於此類設備,此屬性僅應設置為1
。如有疑問,請將此值設置為0
。
計算
TouchMajor
、 TouchMinor
、 ToolMajor
、 ToolMinor
和Size
字段的計算取決於指定的校準參數。
If raw.touchMajor and raw.toolMajor are available: touchMajor = raw.touchMajor touchMinor = raw.touchMinor toolMajor = raw.toolMajor toolMinor = raw.toolMinor Else If raw.touchMajor is available: toolMajor = touchMajor = raw.touchMajor toolMinor = touchMinor = raw.touchMinor Else If raw.toolMajor is available: touchMajor = toolMajor = raw.toolMajor touchMinor = toolMinor = raw.toolMinor Else touchMajor = toolMajor = 0 touchMinor = toolMinor = 0 size = 0 End If size = avg(touchMajor, touchMinor) If touch.size.isSummed == 1: touchMajor = touchMajor / numberOfActiveContacts touchMinor = touchMinor / numberOfActiveContacts toolMajor = toolMajor / numberOfActiveContacts toolMinor = toolMinor / numberOfActiveContacts size = size / numberOfActiveContacts End If If touch.size.calibration == "none": touchMajor = toolMajor = 0 touchMinor = toolMinor = 0 size = 0 Else If touch.size.calibration == "geometric": outputScale = average(output.width / raw.width, output.height / raw.height) touchMajor = touchMajor * outputScale touchMinor = touchMinor * outputScale toolMajor = toolMajor * outputScale toolMinor = toolMinor * outputScale Else If touch.size.calibration == "area": touchMajor = sqrt(touchMajor) touchMinor = touchMajor toolMajor = sqrt(toolMajor) toolMinor = toolMajor Else If touch.size.calibration == "diameter": touchMinor = touchMajor toolMinor = toolMajor End If If touchMajor != 0: output.touchMajor = touchMajor * touch.size.scale + touch.size.bias Else output.touchMajor = 0 End If If touchMinor != 0: output.touchMinor = touchMinor * touch.size.scale + touch.size.bias Else output.touchMinor = 0 End If If toolMajor != 0: output.toolMajor = toolMajor * touch.size.scale + touch.size.bias Else output.toolMajor = 0 End If If toolMinor != 0: output.toolMinor = toolMinor * touch.size.scale + touch.size.bias Else output.toolMinor = 0 End If output.size = size
Pressure
場
Pressure
字段將施加到觸摸設備的近似物理壓力描述為介於 0.0(無觸摸)和 1.0(最大力)之間的歸一化值。
零壓力表示工具懸停。
touch.pressure.calibration
定義: touch.pressure.calibration
= none
| physical
| amplitude
| default
指定觸摸驅動程序用來報告壓力的測量類型。
如果值為
none
,則壓力未知,因此觸摸時設置為 1.0,懸停時設置為 0.0。如果該值為
physical
,則假定壓力軸測量施加到觸摸板上的實際物理壓力強度。If the value is
amplitude
, the pressure axis is assumed to measure the signal amplitude, which is related to the size of the contact and the pressure applied.If the value is
default
, the system uses thephysical
calibration if the pressure axis available, otherwise usesnone
.
touch.pressure.scale
Definition: touch.pressure.scale
= <a non-negative floating point number>
Specifies a constant scale factor used in the calibration.
The default value is 1.0 / raw.pressure.max
.
Calculation
The calculation of the Pressure
field depends on the specified calibration parameters.
If touch.pressure.calibration == "physical" or "amplitude": output.pressure = raw.pressure * touch.pressure.scale Else If hovering: output.pressure = 0 Else output.pressure = 1 End If End If
Orientation
and Tilt
Fields
The Orientation
field describes the orientation of the touch and tool as an angular measurement. An orientation of 0
indicates that the major axis is oriented vertically, -PI/2
indicates that the major axis is oriented to the left, PI/2
indicates that the major axis is oriented to the right. When a stylus tool is present, the orientation range may be described in a full circle range from -PI
or PI
.
The Tilt
field describes the inclination of the tool as an angular measurement. A tilt of 0
indicates that the tool is perpendicular to the surface. A tilt of PI/2
indicates that the tool is flat on the surface.
touch.orientation.calibration
Definition: touch.orientation.calibration
= none
| interpolated
| vector
| default
Specifies the kind of measurement used by the touch driver to report the orientation.
If the value is
none
, the orientation is unknown so it is set to 0.If the value is
interpolated
, the orientation is linearly interpolated such that a raw value ofraw.orientation.min
maps to-PI/2
and a raw value ofraw.orientation.max
maps toPI/2
. The center value of(raw.orientation.min + raw.orientation.max) / 2
maps to0
.If the value is
vector
, the orientation is interpreted as a packed vector consisiting of two signed 4-bit fields. This representation is used on Atmel Object Based Protocol parts. When decoded, the vector yields an orientation angle and confidence magnitude. The confidence magnitude is used to scale the size information, unless it is geometric.If the value is
default
, the system uses theinterpolated
calibration if the orientation axis available, otherwise usesnone
.
Calculation
The calculation of the Orientation
and Tilt
fields depends on the specified calibration parameters and available input.
If touch.tiltX and touch.tiltY are available: tiltXCenter = average(raw.tiltX.min, raw.tiltX.max) tiltYCenter = average(raw.tiltY.min, raw.tiltY.max) tiltXAngle = (raw.tiltX - tiltXCenter) * PI / 180 tiltYAngle = (raw.tiltY - tiltYCenter) * PI / 180 output.orientation = atan2(-sin(tiltXAngle), sinf(tiltYAngle)) output.tilt = acos(cos(tiltXAngle) * cos(tiltYAngle)) Else If touch.orientation.calibration == "interpolated": center = average(raw.orientation.min, raw.orientation.max) output.orientation = PI / (raw.orientation.max - raw.orientation.min) output.tilt = 0 Else If touch.orientation.calibration == "vector": c1 = (raw.orientation & 0xF0) >> 4 c2 = raw.orientation & 0x0F If c1 != 0 or c2 != 0: If c1 >= 8 Then c1 = c1 - 16 If c2 >= 8 Then c2 = c2 - 16 angle = atan2(c1, c2) / 2 confidence = sqrt(c1*c1 + c2*c2) output.orientation = angle If touch.size.calibration == "diameter" or "area": scale = 1.0 + confidence / 16 output.touchMajor *= scale output.touchMinor /= scale output.toolMajor *= scale output.toolMinor /= scale End If Else output.orientation = 0 End If output.tilt = 0 Else output.orientation = 0 output.tilt = 0 End If If orientation aware: If screen rotation is 90 degrees: output.orientation = output.orientation - PI / 2 Else If screen rotation is 270 degrees: output.orientation = output.orientation + PI / 2 End If End If
Distance
Field
The Distance
field describes the distance between the tool and the touch device surface. A value of 0.0 indicates direct contact and larger values indicate increasing distance from the surface.
touch.distance.calibration
Definition: touch.distance.calibration
= none
| scaled
| default
Specifies the kind of measurement used by the touch driver to report the distance.
If the value is
none
, the distance is unknown so it is set to 0.If the value is
scaled
, the reported distance is multiplied by a constant scale factor.If the value is
default
, the system uses thescaled
calibration if the distance axis available, otherwise usesnone
.
touch.distance.scale
Definition: touch.distance.scale
= <a non-negative floating point number>
Specifies a constant scale factor used in the calibration.
The default value is 1.0
.
Calculation
The calculation of the Distance
field depends on the specified calibration parameters.
If touch.distance.calibration == "scaled": output.distance = raw.distance * touch.distance.scale Else output.distance = 0 End If
Example
# Input device configuration file for a touch screen that supports pressure, # size and orientation. The pressure and size scale factors were obtained # by measuring the characteristics of the device itself and deriving # useful approximations based on the resolution of the touch sensor and the # display. # # Note that these parameters are specific to a particular device model. # Different parameters will need to be used for other devices. # Basic Parameters touch.deviceType = touchScreen touch.orientationAware = 1 # Size # Based on empirical measurements, we estimate the size of the contact # using size = sqrt(area) * 28 + 0. touch.size.calibration = area touch.size.scale = 28 touch.size.bias = 0 touch.size.isSummed = 0 # Pressure # Driver reports signal strength as pressure. # # A normal index finger touch typically registers about 80 signal strength # units although we don't expect these values to be accurate. touch.pressure.calibration = amplitude touch.pressure.scale = 0.0125 # Orientation touch.orientation.calibration = vector
Compatibility Notes
The configuration properties for touch devices changed significantly in Android Ice Cream Sandwich 4.0. All input device configuration files for touch devices must be updated to use the new configuration properties.
Older touch device drivers may also need to be updated.
Virtual Key Map Files
Touch devices are often used to implement virtual keys.
There are several ways of doing this, depending on the capabilities of the touch controller. Some touch controllers can be directly configured to implement soft keys by setting firmware registers. Other times it is desirable to perform the mapping from touch coordinates to key codes in software.
When virtual keys are implemented in software, the kernel must export a virtual key map file called virtualkeys.<devicename>
as a board property. For example, if the touch screen device drivers reports its name as "touchyfeely" then the virtual key map file must have the path /sys/board_properties/virtualkeys.touchyfeely
.
A virtual key map file describes the coordinates and Linux key codes of virtual keys on the touch screen.
In addition to the virtual key map file, there must be a corresponding key layout file and key character map file to map the Linux key codes to Android key codes and to specify the type of the keyboard device (usually SPECIAL_FUNCTION
).
Syntax
A virtual key map file is a plain text file consisting of a sequence of virtual key layout descriptions either separated by newlines or by colons.
Comment lines begin with '#' and continue to the end of the line.
Each virtual key is described by 6 colon-delimited components:
-
0x01
: A version code. Must always be0x01
. - <Linux key code>: The Linux key code of the virtual key.
- <centerX>: The X pixel coordinate of the center of the virtual key.
- <centerY>: The Y pixel coordinate of the center of the virtual key.
- <width>: The width of the virtual key in pixels.
- <height>: The height of the virtual key in pixels.
All coordinates and sizes are specified in terms of the display coordinate system.
Here is a virtual key map file all written on one line.
# All on one line 0x01:158:55:835:90:55:0x01:139:172:835:125:55:0x01:102:298:835:115:55:0x01:217:412:835:95:55
The same virtual key map file can also be written on multiple lines.
# One key per line 0x01:158:55:835:90:55 0x01:139:172:835:125:55 0x01:102:298:835:115:55 0x01:217:412:835:95:55
In the above example, the touch screen has a resolution of 480x800. Accordingly, all of the virtual keys have a <centerY> coordinate of 835, which is a little bit below the visible area of the touch screen.
The first key has a Linux scan code of 158
( KEY_BACK
), centerX of 55
, centerY of 835
, width of 90
and height of 55
.
Example
Virtual key map file: /sys/board_properties/virtualkeys.touchyfeely
.
0x01:158:55:835:90:55 0x01:139:172:835:125:55 0x01:102:298:835:115:55 0x01:217:412:835:95:55
Key layout file: /system/usr/keylayout/touchyfeely.kl
.
key 158 BACK key 139 MENU key 172 HOME key 217 SEARCH
Key character map file: /system/usr/keychars/touchyfeely.kcm
.
type SPECIAL_FUNCTION
Indirect Multi-touch Pointer Gestures
In pointer mode, the system interprets the following gestures:
Single finger tap: click.
Single finger motion: move the pointer.
Single finger motion plus button presses: drag the pointer.
Two finger motion both fingers moving in the same direction: drag the area under the pointer in that direction. The pointer itself does not move.
Two finger motion both fingers moving towards each other or apart in different directions: pan/scale/rotate the area surrounding the pointer. The pointer itself does not move.
Multiple finger motion: freeform gesture.
Palm rejection
As of Android 13, the system can automatically reject inputs from palms when the built-in framework is enabled. In-house, custom-built solutions are still supported, though they might need to be modified to return the TOOL_TYPE_PALM
flag when a palm is detected. The built-in framework also works in conjunction with custom solutions.
The actual model looks at the first 90 ms of gesture data, at the current pointer, and at the surrounding pointers, then considers how far away from the edge of the display the touches are. It then determines, on a per-pointer basis, which of the pointers are palms. It also takes into account the size of each contact, as reported by TouchMajor
and TouchMinor
. The Android framework then removes the pointers that are marked as palms from the touch stream.
If a pointer was already sent to the apps, then the system either:
- (If there are other active pointers) Cancels the pointer with
ACTION_POINTER_UP
andFLAG_CANCELED
set. - (If this is the only pointer) Cancels the pointer with
ACTION_CANCEL
.
A public API, MotionEvent.FLAG_CANCELED
, indicates that the current event shouldn't trigger user action. This flag is set for both ACTION_CANCEL
and ACTION_POINTER_UP
.
If the palm pointer wasn't sent to apps, then the system simply drops the pointer.
Enable palm rejection
- In your touch driver, use the
input_abs_set_res
macro to set the resolutions for the following fields (units are pixels per mm ):-
ABS_MT_POSITION_X
-
ABS_MT_POSITION_Y
-
ABS_MT_TOUCH_MAJOR
-
ABS_MT_TOUCH_MINOR
Support for
ABS_MT_TOUCH_MINOR
is optional. However, if your device does support it, make sure the resolution is set correctly. -
- To confirm the fields are set correctly, run:
$ adb shell getevent -li
- To enable the feature during runtime, run:
$ adb shell device_config put input_native_boot palm_rejection_enabled 1
- Restart the
system_server
process.$ adb shell stop && adb shell start
- Confirm that
adb shell dumpsys input
shows that there are palm rejectors insideUnwantedInteractionBlocker
. If it doesn't, check the input-related logs to find clues on what might be misconfigured.See the following example for reference:
UnwantedInteractionBlocker: mEnablePalmRejection: true isPalmRejectionEnabled (flag value): true mPalmRejectors: deviceId = 3: mDeviceInfo: max_x =
max_y = x_res = 11.00 y_res = 11.00 major_radius_res = 1.00 minor_radius_res = 1.00 minor_radius_supported = true touch_major_res = 1 touch_minor_res = 1 mSlotState: mSlotsByPointerId: mPointerIdsBySlot: mSuppressedPointerIds: {} - To permanently enable the feature, add the corresponding sysprop command in your
init**rc
file:setprop persist.device_config.input_native_boot.palm_rejection_enabled 1