Android Enterpriseを支えるAndroid OSのソースコード解説

今年のAndroid Enterpriseアドベントカレンダーの締めくくりとして、この過疎っているアドベントカレンダーで紹介してきた機能の裏側（おもにAndroidフレームワークのソースコード）の解説を軽くしてみようと思います！

## まえおき

Android Enterpriseにはいくつかの動作モードがあります。

https://support.google.com/work/android/topic/9563482?hl=ja&ref_topic=9621435

１つのデバイスを仕事専用デバイスとしてMDM管理下に置くFully Managed deviceだけではなく、個人端末の業務利用（いわゆるBYOD）や業務端末の個人利用（BYODの逆）ができるWork Profileと呼ばれるモードがあるのが特徴的です。

１つのデバイスを複数のプロファイルで利用する、それをAndroid OS / Google Playサービスはどのように利用しているのでしょうか？

## Android OSはそもそも複数ユーザで利用ができる

Androidは、もう８年前くらいのバージョン4.2から複数ユーザで使えるように設計がされています。ただ、私が知る限り実際にそんな使い方をしている人は一人もいません。なぜかというと、デフォルトではマルチユーザのUIはオフられており、**端末メーカーが**オンにしない限りユーザの目に触れることがないからです。

以下のページにも言及されています。

https://source.android.com/docs/devices/admin/multi-user

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/975548f3-0c8c-c2c0-4bb5-4099d29d9174.png)

日本では依然として、Android OSの知識に乏しい通信キャリアの人が考えた仕様に従い、端末メーカーが仕様を満たす端末が納入されるという生産構造が優勢のため、この機能を有効化した端末というのは一部のタブレットを除きおそらく今までにありません。

そんなマルチユーザ機能ですが、複数ユーザで使わずとも「プライベートな自分」「仕事モードの自分」が共存する形で使えたらいいんじゃね？と誰かすごい人が思いついたんでしょう。そんなわけでAndroid 5.0, 5.1ごろから本格的に「Android for Work」の一環として、この複数ユーザ機能が企業向けデバイス管理の用途で活用され始めたわけです。

最近のAndroid OSのソースコードは、本当に複雑化してなかなかどこから見始めたらよいか難しいですが、当時のAndroid 6ごろのコードであれば、システムサービスがまだ１ファイルに収まっているものが多く、サラッと眺めやすいです。（Android 12のソースコードでも、ディレクトリ構造は結構変わっていますが、機能の骨格はそんなに大きくは変わっていません）

* マルチユーザまわりを司るのは servicesの pm配下、UserManagerService
  * https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-6.0.1_r81/services/core/java/com/android/server/pm/UserManagerService.java
* デバイス管理系のオペレーションを行うのがDevicePolicyManagerService
  * https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-6.0.1_r81/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java

DevicePolicyManagerのほうで、結構多くのAPIがメンバ変数として持っているUserManagerに対するスルーパスなのがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/455dad63-3c67-28c4-6f66-24dc10a1a3ae.png)

ちなみにUserManagerService自体は、結局のところ、 /data/system/ 配下のファイルシステムにXMLファイルを持っていてそこでユーザ情報を管理していたり、 /data/ をユーザ単位でディレクトリわけて情報/権限管理していたり、などファイルシステムとやり取りしている部分が結構多いです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/40738740-5d7c-e58a-6be4-5e2353770acb.png)

なので、UserManagerのAPI名から「あ、ユーザ作ってるんだなー」「あ、プロファイル削除してるんだなー」以上のことはそんなに深追いしないで抽象的なまままずは概念理解を進めると読みやすいです。

## DeviceOwnerという概念

通常のアプリでは、カメラ機能を無効化したり、VPNを常時有効化して通信内容をサーバーに記録させたり、といったことは当然できません。

AndroidフレームワークとしてはDevicePolicyManagerにそのようなAPIは備わっているものの、セキュリティの観点で当然ながら万人がそれを利用できるようにはなっていないのです。

そこで登場するのが DeviceOwner, ProfileOwnerです。ユーザのような名前をしていますが、「強いことをできる**特権**」みたいなもんです。

DevicePolicyManagerServiceのソースコードを見ると、 `getActiveAdminForCallerLocked` というメソッド呼び出しが各制御APIにあるのがわかります。この中で、有効なDeviceOwner, ProfileOwnerのアプリケーションからの呼び出しであるかどうかをチェックしています。

DeviceOwner, ProfileOwnerの特権は、開発者であればADBコマンドで任意のアプリに付与することができますが、普通のデバイスユーザはどうやって特権を付与しているのでしょう？

正解は、Provision.apkのソースコードを見ると書いてあります。

https://android.googlesource.com/platform/packages/apps/Provision/+/refs/tags/android-12.1.0_r27/src/com/android/provision/DefaultActivity.java

ただ、Android 6頃のソースコードにはなく、比較的最近のバージョンで追加されたものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/9bbecca4-6cdc-2015-c728-4f8341cb605c.png)

色々書いてあるものの、要するに、デバイスのプロビジョニングを行うアプリケーションの中でDeviceOwnerの指定もしていますよ、ということ。

通常のデバイスであれば、買ってきて初めて起動するときにGoogleのセットアップウィザードが起動してGoogleアカウントとか入れさせられる、あれです。

Googleアカウントを入力する代わりに `afw#hogehoge` 的なコードを入力したり、セットアップウィザードの最初の画面で連打してQRコードリーダーを起動したり、普通のユーザが感づかないところにその入口が設置されているのです。

それぞれ

* EMMトークン
  * https://help.zoho.com/portal/ja/kb/one/admin-guide/managing-devices/device-enrollment/articles/emm%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AB%E3%82%88%E3%82%8B%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%81%AE%E7%99%BB%E9%8C%B2#Prerequisites
  * https://www.manageengine.com/mobile-device-management/help/enrollment/mdm_android_qr_code_enrollment.html
* QRコードプロビジョニング
  * https://help.ivanti.com/wl/help/ja_JP/AVA/6.3/Avalanche/Enabler/AE-QR-provisioning.htm

あたりのキーワードでぐぐると色々出てくると思います。

GoogleセットアップウィザードはGoogleのクローズドな実装なので、ソースコードは残念ながら公開されていません。まぁProvision.apkと同じように、いい感じのタイミングで ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE を呼び出したりしているのでしょう。

## Cross Profileの実装

UserManagerの中で、基本的には「ユーザ」「プロファイル」というのはその境界を超えて情報をやりとりすることはないよう設計がされています。

しかしながら、

* クリップボード情報
* 写真アップロード時のカメラ画像

など、必ずしもユーザごとにパーティションしていることが使いやすいとは限らない場面が多々存在するので、特定の手続きを踏めばその境界を超えることができるようにも設計されています。

ただ、UserManager自体がそのロジックをガッツリ持っているわけではなく、UserManagerはあくまでフラグ管理だけです。

PackageManagerServiceなど、使う側が頑張ってチェックしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/f0674cc7-09da-8346-c094-a23f60931821.png)

中は大したことやっていなくて、パーミッションの確認+α程度です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/4a6918de-404b-fbf4-e449-b6dd1eccea02.png)

このあたりは、最近のAndroidバージョンでは `CrossProfileAppsService` という１つのクラスにそのあたりの実装が集約されてだいぶ読みやすくなっています。

https://android.googlesource.com/platform/frameworks/base.git/+/refs/tags/android-12.1.0_r27/core/java/android/content/pm/CrossProfileApps.java

https://android.googlesource.com/platform/frameworks/base.git/+/refs/tags/android-12.1.0_r27/services/core/java/com/android/server/pm/CrossProfileAppsService.java

## まとめ

今年のAndroid Enterpriseアドベントカレンダーの締めくくりとして、アドベントカレンダーで紹介してきた機能の裏側のAndroidフレームワークのソースコードの解説を軽くしてみました。

Androidのソースコードはバージョンを経るたびにシステムサービスが増え、それなりに複雑化していますが、根幹を支えるサービスやその役割は、多くは昔から変わっていません。そのため適宜わざと昔のソースコードもとりあげながらの解説としてみました。

アプリを作るだけであれば、99.9%役に立つことはありませんが、OSよりの仕組みに興味があるかたにとっては入り口となる記事となったことを祈っています。

それでは今年も残りわずかとなりましたが、良いお年を！