Androidのユーザー補助サービス(Accessibility Service)は楽しい

先日クックパッドで開催された potatotips #42Android のセキュリティよくなってきた話という発表をしました。 Androidのセキュリティに関する改善の歴史と、ユーザー補助サービスによるアプリ権限奪取のデモという内容でしたが、短い時間での発表だったため、ユーザー補助サービスについてあまり十分な説明ができませんでした。

この記事では、ユーザー補助サービスのより詳細な説明や(悪用以外の)活用方法、個人的に問題として考えている部分について説明しようと思います。 発表ではネガティブな面をアピールしてしまいましたが、ユーザー補助サービスを使った開発は非常に奥深く面白いので、その楽しさを少しでも伝えられればと思います。

ユーザー補助サービスとは

ユーザー補助サービス(Accessibility Service)とは、Androidアプリとユーザーの間のやり取りをサポートするためのAndroidの機能です。 ユーザー補助サービスを利用するとアプリの切り替えや画面の更新、通知の変化を読み取って音声などの別の手段でユーザーに通知することができます。 また、逆にユーザーの操作を検出してアプリに他の種類のタッチイベントとして通知させることもできます。 どちらかの単方向ではなく、アプリとユーザーの双方向のやりとりを補助できるのが大きな特徴です。

どのように動作するのか

AccessibilityEventを介してアプリ更新やユーザーの操作を検知することができます。 ユーザー補助サービスを利用するアプリでは取得できるイベントや取得できるパラメータに関して細かく設定できます。 開発者は良心に基づき最小権限で実装することが求められますが、AccessibilityServiceInfoの設定項目が非常に複雑な上、ユーザーのからの許可は「ユーザー補助」として一括で扱われるため正しい設定が難しくなっています。 個人的にインストール済みアプリのユーザー補助サービス権限についてはかなり注意を払っていますが、その権限が動作に必要最小限なのかどうかは正直あまり自信がありません。

権限の話はさておき、ユーザー補助サービスが有効になったアプリではAccessibilityService(というService)を通じて様々なイベントを受け取ることができます。 Viewイベントの場合は発生源のView情報も受け取ることができますが、Viewそのものにアクセスすることはできず、あくまでユーザー補助サービスを通して可能な範囲でのデータ取得となります。

アプリ、ユーザーのイベントを受け取る

僕が特に面白いと思っているのはこの部分です。 最前面のアプリが切り替わった時にそのパッケージを取得したり、表示中画面の文字列に特定の文言が含まれているかを判定したりすることができます。 「あるアプリの情報を他のアプリから知ることができる」という部分の面白さは非常に奥深く、GoogleNowなどもこのような方法で表示中アプリの情報を得ているかもしれない、何かより面白いことができるかもしれないと思うとわくわくします。 ユーザーのタップ情報を検知して対象Viewのサイズや配置などを知ったり、アプリごとの利用時間を測ったり、簡単な実装でも色々変わったことができて非常に面白いです。

ただし、Viewの情報がわかるといってもAccessibilityNodeInfoを経由して取得できる項目は限られており、画像や色、スタイルといった情報は残念ながら取得できません…。

アプリにイベントを伝える

ユーザー補助サービスでは、ユーザーの代わりにView操作を行うことができます。 Viewのクリックや画面のスクロール、文字列の入力など、ユーザーがアプリで操作可能なことは大体行うことができます。 先日のデモではアプリの権限を許可するためのSwitchコンポーネントに対してクリック操作を行うことでユーザー操作を介さずに自アプリに権限を与えていました。 こちらのほうは汎用的に使える機能を実装するのが難しく、正直あまり使ったことがありません。 開発中のアプリの入力画面に対してテストデータの入力を補助できるような、デバッグ補助アプリのようなものを作れるかもしれません。 正直ユーザー補助サービスでやらなくても…という感じですが、別のパッケージで実装できるので本体アプリを操作する必要がないのが利点でしょうか。

利用例

例えば、ユーザー補助サービスを使うと以下のようなアプリを作ることができます。

  • 表示中のアプリのパッケージ名やViewIdから効率的に入力補助を行うパスワード管理アプリ
    • 実際に1passwordなどはこのような動作になっているようです
  • 最前面のアプリを変更するイベントを監視し、アプリの利用時間を計測するアプリ
    • RescueTimeなどはおそらくこういった実装になっています
    • 有名サービスとはいえユーザー補助サービスを許可するのは怖いので自分で実装してみるのも良いかもしれません
  • 画面をタップした際、押されたViewのサイズなどを知ることができるアプリ
    • DroidKaigi 2017 で門田さんが発表していたアプリです
    • ユーザー補助サービス自体はUIを持たないため、画面を通じてユーザーにフィードバックするのが難しくなりがちですね…

このように、アイデア次第で色々なアプリを作ることができるのが魅力です。 普通のアプリよりはるかに広範囲なものを操作できるのも楽しいですね。

問題点と今後の展望

すでに書いたとおり、もっとも大きな問題点は「ユーザー補助サービスの権限があまりに強すぎる」というところだと思います。 アプリやユーザーのイベントを受け取る、アプリの操作を行うという双方向のアクションが可能にも関わらず、設定は一箇所のみで確認も非常に簡素です。 これはユーザー補助サービス本来の目的としては正しいですが、セキュリティモデルとしては自分で開発していても心配になるレベルです。 より細かく権限設定できるようにするか、一部の頻出機能はユーザー補助サービスとは別の機能として切り出したほうが良いと感じています。

実際にAndroid Oでは文字列入力補助のためにAutofill Frameworkが導入され、必要最小限のイベント通知とフィードバックのみが行えるようになります。 このような仕組みが今後も拡張されることで、今後はユーザー補助サービスだけに頼らなくても他のアプリと協調して動作するアプリが安全に作れるようになることを期待しています。

まとめ

ユーザー補助サービス非常に楽しいのでぜひ遊びましょう。 限られたイベントとAccessibilityNodeInfoを通じてアプリと会話する経験をすることで、よりAndroid(OS)の気持ちになってアプリのことを考えることができ(ると思ってい)ます。 また、ユーザー補助サービスの何が危険でどうすれば安全なのかを理解する上でも、実際に自分でイベントの取得やフィードバックを行ってみてできることを確かめてみることが大事だと思います。