Android実機を再起動＆ロック解除まで自動でやっちゃう

基本操作は[こちらのQiita記事](https://qiita.com/techno-tanoC/items/b93723618a792c7096ee)の通りなのですが、メーカー製の実機を操作しようとすると一筋縄ではいかなかった事があったのでメモ代わりです。

使った実機はこちら。

* [SO-02E] (https://www.sonymobile.co.jp/xperia/docomo/so-02e/)
    * 開発者オプションから、スリープ状態にならないよう設定済み
    * パスコードロックなどはかかっていない

USB接続した親機のshellから操作する前提です。


# デバイス再起動後、スクリーンロックを解除する


## まず再起動する

```
$ adb reboot
```

これはワンコマンドで可能なので簡単。

## 再起動の完了を待つ

`adb` の　`wait-for-device` （デバイスが操作可能になるまで待ってから、引数の操作を実行してくれる）を使えば解決…とは行きませんでした。
なんと電源が入った瞬間に次の動作が始まってしまいます。

adbを使ってロック画面になるまで待つ、比較的お手軽な方法が見つからなかったので、ここは `sleep` を使います。
rebootコマンドを打ってから1分ちょっとで再起動が終わるようだったので、ここでは念の為2分待っておきます。

```
$ sleep 2m
```

## ロックを解除する

SO-02Eのロック画面はこんな感じ。

![Screenshot_2018-09-11-12-51-10.png](https://qiita-image-store.s3.amazonaws.com/0/41896/a3b9460f-e220-a2dc-d058-6ec797f7aa35.png)

今回はパスコードロックなどは設定していないので、中央下部のロック解除ボタンを触ればロック解除できます。
なにかキーボード操作すれば解除できるのかどうかは不明。

[adb screen unlockとかでググる](https://www.google.co.jp/search?q=adb+screen+unlock&oq=adb+screen+unlock)とたくさん解除方法の候補が見つかりますが、大半はAVD（エミュレータ）向けのものです。
今回の操作対象SO-02Eには `adb shell input keyevent 82` とかしても何も起こりませんでした。
何種類かキーコードを送ってみましたがどれも反応なし。
仕方ないのでスクリーンのロック解除ボタンを押したことにして、ロック解除を試みます。

### ロック解除ボタンの座標を探る

`shell getevent` を使うことで端末のデバイスファイルの変化を見ることができます。
また、 `-i` オプションでデバイスファイルの概要を表示できます。
まずはこのオプションで、タッチセンサのデバイスファイルを探します。

SO-02Eの場合、 `/dev/input/event1` がスクリーンのタッチセンサの対応したデバイスファイルでした。

```
$ adb shell getevent -i /dev/input/event1
add device 1: /dev/input/event1
  bus:      0018
  vendor    0001
  product   0001
  version   0001
  name:     "clearpad"
  location: ""
  id:       ""
  version:  1.0.1
  events:
    ABS (0003): 002f  : value 0, min 0, max 9, fuzz 0, flat 0, resolution 0
                0030  : value 0, min 0, max 16, fuzz 0, flat 0, resolution 0
                0031  : value 0, min 0, max 16, fuzz 0, flat 0, resolution 0
                0034  : value 0, min -1, max 1, fuzz 0, flat 0, resolution 0
                0035  : value 0, min 0, max 1079, fuzz 0, flat 0, resolution 0
                0036  : value 0, min 0, max 1919, fuzz 0, flat 0, resolution 0
                0039  : value 0, min 0, max 65535, fuzz 0, flat 0, resolution 0
                003a  : value 0, min 0, max 255, fuzz 0, flat 0, resolution 0
  input props:
    <none>
```

今度は `-l` オプションでどのようなイベントが起きたのか、イベントの名称とともに観察します。

```
$ adb shell getevent -l /dev/input/event1
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_TRACKING_ID   00000000
EV_ABS       ABS_MT_POSITION_X    000002f4
EV_ABS       ABS_MT_POSITION_Y    0000043d
EV_ABS       ABS_MT_PRESSURE      0000004e
EV_ABS       ABS_MT_TOUCH_MAJOR   00000005
EV_ABS       ABS_MT_TOUCH_MINOR   00000004
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_POSITION_Y    0000043b
EV_ABS       ABS_MT_PRESSURE      00000050
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_POSITION_Y    00000439
EV_ABS       ABS_MT_PRESSURE      00000051
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_POSITION_X    000002f3
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_POSITION_X    000002f1
EV_ABS       ABS_MT_POSITION_Y    0000043a
EV_ABS       ABS_MT_PRESSURE      00000050
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_POSITION_X    000002eb
EV_ABS       ABS_MT_POSITION_Y    0000043c
EV_ABS       ABS_MT_PRESSURE      00000052
EV_ABS       ABS_MT_TOUCH_MINOR   00000003
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_POSITION_X    000002dd
EV_ABS       ABS_MT_POSITION_Y    0000043f
EV_ABS       ABS_MT_PRESSURE      00000053
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_POSITION_X    000002ca
EV_ABS       ABS_MT_PRESSURE      00000052
EV_ABS       ABS_MT_TOUCH_MINOR   00000004
EV_SYN       SYN_REPORT           00000000
（以下略）
```

どうやら `ABS_MT_POSITION_X` が指が触れている箇所のスクリーンX座標、 `ABS_MT_POSITION_Y` が同じくY座標のようです。
ロック画面にしてからロック解除ボタンをタップし、ボタンの座標を探します。

```
$ adb shell getevent -l /dev/input/event1
EV_ABS       ABS_MT_TRACKING_ID   00000001
EV_ABS       ABS_MT_POSITION_X    000001ef
EV_ABS       ABS_MT_POSITION_Y    000005fb
EV_ABS       ABS_MT_PRESSURE      00000051
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_POSITION_X    000001ed
EV_ABS       ABS_MT_POSITION_Y    000005f9
EV_ABS       ABS_MT_PRESSURE      00000057
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_POSITION_Y    000005f7
EV_ABS       ABS_MT_PRESSURE      00000058
EV_ABS       ABS_MT_TOUCH_MINOR   00000005
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_POSITION_Y    000005f5
EV_ABS       ABS_MT_PRESSURE      00000057
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_POSITION_X    000001ef
EV_ABS       ABS_MT_PRESSURE      0000004d
EV_ABS       ABS_MT_TOUCH_MINOR   00000003
EV_SYN       SYN_REPORT           00000000
EV_ABS       ABS_MT_TRACKING_ID   ffffffff
EV_SYN       SYN_REPORT           00000000
```

タップしてる間だけでも指がぶれているようで、座標更新のイベントが沢山走っています。
とりあえず、XとYの最新値を探すと、以下の箇所がロック解除ボタンを触ったときの座標のようです。

* `ABS_MT_POSITION_X    000001ef`
* `ABS_MT_POSITION_Y    000005f5`

16進数なので、10進数に直すと `(495, 1525)` でしょうか。

座標がわかれば、後は `shell input touchscreen tap` コマンドで座標を送ってやるだけです。
ロック画面にしてコマンドを送ります。

```
$ adb shell input touchscreen tap 495 1525
```

ロック解除できました！

# まとめ

念の為にデバイス操作を待ち受けるとして、最終的に以下で再起動からロック解除まで行けました。

```
$ adb wait-for-device reboot && sleep 2m && adb wait-for-device shell input touchscreen tap 495 1525
```

たまにメモリ不足と疑われる状態に陥って正常にテストが動かないことがあったりしたので、これで解消できそうです。