adb shell input 分析(1)

adb shell input的功能

adb shell input可以通過adb命令行發送input事件。包含keyevent和text兩種。

keyevent

對於安卓API KeyEvent定義的健值均可支持

https://developer.android.com/reference/android/view/KeyEvent

健值舉例:

KEYCODE_0
Added in API level 1
public static final int KEYCODE_0
Key code constant: '0' key.

Constant Value: 7 (0x00000007)

KEYCODE_1
Added in API level 1
public static final int KEYCODE_1
Key code constant: '1' key.

Constant Value: 8 (0x00000008)

KEYCODE_11
Added in API level 21
public static final int KEYCODE_11
Key code constant: '11' key.

Constant Value: 227 (0x000000e3)

KEYCODE_12
Added in API level 21
public static final int KEYCODE_12
Key code constant: '12' key.

Constant Value: 228 (0x000000e4)

KEYCODE_2
Added in API level 1
public static final int KEYCODE_2
Key code constant: '2' key.

Constant Value: 9 (0x00000009)

KEYCODE_3
Added in API level 1
public static final int KEYCODE_3
Key code constant: '3' key.

Constant Value: 10 (0x0000000a)

KEYCODE_3D_MODE
public static final int KEYCODE_3D_MODE
Key code constant: 3D Mode key. Toggles the display between 2D and 3D mode. * @apiSince 14

Constant Value: 206 (0x000000ce)

KEYCODE_4
Added in API level 1
public static final int KEYCODE_4
Key code constant: '4' key.

Constant Value: 11 (0x0000000b)

KEYCODE_5
Added in API level 1
public static final int KEYCODE_5
Key code constant: '5' key.

Constant Value: 12 (0x0000000c)

例如,發送一個back鍵:

通過查詢上述文檔,我們發現back鍵值爲4,所以連通adb調試後,命令行輸入:

adb shell input keyevent 4

手機端就會響應back鍵(如果當前頁面可以響應back)。

text

也可以支持直接的文本輸入,例如,在手機端打開一個可以響應文本輸入的界面,例如EditText控件,命令行輸入:

adb shell input text 123

手機端EditText會填充文本123。

支持文本單引號和雙引號:

adb shell input text "123"

adb shell input text '123'

都是可以的。

adb shell input的實現機制

從分析log開始

通過命令行調試一個back鍵值:adb shell input keyevent 4,看到手機端有如下log:

一部分是AndroidRuntime的log:

12-12 16:32:57.324  9375  9375 D AndroidRuntime: >>>>>> START com.android.internal.os.RuntimeInit uid 2000 <<<<<<
12-12 16:32:57.329  9375  9375 D AndroidRuntime: CheckJNI is OFF
12-12 16:32:57.445  9375  9375 D AndroidRuntime: Calling main entry com.android.commands.input.Input
12-12 16:32:57.509  9375  9375 D AndroidRuntime: Shutting down VM

另一部分,在start和shutting down中間,看到了keyevent相關: 

12-12 16:14:30.277  8641  8641 I Input   : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=637379, downTime=637379, deviceId=-1, source=0x101 }
12-12 16:14:30.374  8641  8641 I Input   : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=637379, downTime=637379, deviceId=-1, source=0x101 }

再試一下文本:adb shell input text 12,AndroidRuntime的沒區別,文本的處理:

12-12 16:40:19.753  9491  9491 I Input   : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_1, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2186856, downTime=2186856, deviceId=-1, source=0x101 }
12-12 16:40:19.757  9491  9491 I Input   : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_1, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2186856, downTime=2186856, deviceId=-1, source=0x101 }
12-12 16:40:19.763  9491  9491 I Input   : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_2, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2186856, downTime=2186856, deviceId=-1, source=0x101 }
12-12 16:40:19.772  9491  9491 I Input   : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_2, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2186856, downTime=2186856, deviceId=-1, source=0x101 }

再來一個大小寫混合的:adb shell input text AbCd

12-12 16:41:43.986  9566  9566 I Input   : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_SHIFT_LEFT, scanCode=0, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:43.990  9566  9566 I Input   : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_A, scanCode=0, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:43.993  9566  9566 I Input   : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_A, scanCode=0, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.000  9566  9566 I Input   : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_SHIFT_LEFT, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.022  9566  9566 I Input   : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_B, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.027  9566  9566 I Input   : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_B, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.049  9566  9566 I Input   : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_SHIFT_LEFT, scanCode=0, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.052  9566  9566 I Input   : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_C, scanCode=0, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.055  9566  9566 I Input   : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_C, scanCode=0, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.075  9566  9566 I Input   : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_SHIFT_LEFT, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.078  9566  9566 I Input   : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_D, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.082  9566  9566 I Input   : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_D, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }

從上面log基本上可以看出,對於text,實際上是拆分成每個字符,分別發了一個對應的KeyEvent Down&Up ,相當於一個字符兩個KeyEvent。對於大寫字母,前後再增加了KEYCODE_SHIFT_LEFT的Down和Up。

那麼,中文文本呢?以上面的機制看,肯定是無法支持的。試驗一下:adb shell input text 中文

手機端無反應,從log上看到了crash:

--------- beginning of crash

12-12 16:48:45.884  9749  9749 E AndroidRuntime: FATAL EXCEPTION: main

12-12 16:48:45.884  9749  9749 E AndroidRuntime: PID: 9749

12-12 16:48:45.884  9749  9749 E AndroidRuntime: java.lang.NullPointerException: Attempt to get length of null array

12-12 16:48:45.884  9749  9749 E AndroidRuntime: 	at com.android.commands.input.Input.sendText(Input.java:173)

12-12 16:48:45.884  9749  9749 E AndroidRuntime: 	at com.android.commands.input.Input.run(Input.java:82)

12-12 16:48:45.884  9749  9749 E AndroidRuntime: 	at com.android.commands.input.Input.main(Input.java:59)

12-12 16:48:45.884  9749  9749 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)

12-12 16:48:45.884  9749  9749 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:332)

--------- beginning of system

12-12 16:48:45.892  9749  9749 E MQSEventManagerDelegate: reportJEEvent error happened:java.lang.RuntimeException: Bad file descriptor

12-12 16:48:45.893  9749  9749 E AndroidRuntime: Error reporting crash

12-12 16:48:45.893  9749  9749 E AndroidRuntime: java.lang.RuntimeException: Bad file descriptor

12-12 16:48:45.893  9749  9749 E AndroidRuntime: 	at android.os.BinderProxy.transactNative(Native Method)

12-12 16:48:45.893  9749  9749 E AndroidRuntime: 	at android.os.BinderProxy.transact(Binder.java:510)

12-12 16:48:45.893  9749  9749 E AndroidRuntime: 	at android.os.ServiceManagerProxy.getService(ServiceManagerNative.java:123)

12-12 16:48:45.893  9749  9749 E AndroidRuntime: 	at android.os.ServiceManager.getService(ServiceManager.java:55)

12-12 16:48:45.893  9749  9749 E AndroidRuntime: 	at android.app.ActivityManagerNative$1.create(ActivityManagerNative.java:2778)

12-12 16:48:45.893  9749  9749 E AndroidRuntime: 	at android.app.ActivityManagerNative$1.create(ActivityManagerNative.java:2776)

12-12 16:48:45.893  9749  9749 E AndroidRuntime: 	at android.util.Singleton.get(Singleton.java:34)

12-12 16:48:45.893  9749  9749 E AndroidRuntime: 	at android.app.ActivityManagerNative.getDefault(ActivityManagerNative.java:87)

12-12 16:48:45.893  9749  9749 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:169)

12-12 16:48:45.893  9749  9749 E AndroidRuntime: 	at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)

12-12 16:48:45.893  9749  9749 E AndroidRuntime: 	at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)

12-12 16:48:45.901  9749  9749 E ProcessInjector: error while reportKillProcessEvent to system server!

12-12 16:48:45.901  9749  9749 E ProcessInjector: java.lang.reflect.InvocationTargetException

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at java.lang.reflect.Method.invoke(Native Method)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at android.os.ProcessInjector.reportKillProcessEvent(ProcessInjector.java:20)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at android.os.Process.killProcess(Process.java:1120)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:179)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)

12-12 16:48:45.901  9749  9749 E ProcessInjector: Caused by: java.lang.RuntimeException: Bad file descriptor

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at android.os.BinderProxy.transactNative(Native Method)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at android.os.BinderProxy.transact(Binder.java:510)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at android.os.ServiceManagerProxy.getService(ServiceManagerNative.java:123)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at android.os.ServiceManager.getService(ServiceManager.java:55)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at android.app.ActivityManagerNative$1.create(ActivityManagerNative.java:2778)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at android.app.ActivityManagerNative$1.create(ActivityManagerNative.java:2776)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at android.util.Singleton.get(Singleton.java:34)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	at android.app.ActivityManagerNative.getDefault(ActivityManagerNative.java:87)

12-12 16:48:45.901  9749  9749 E ProcessInjector: 	... 6 more

接下來會結合安卓源代碼,分析一下機制。 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章