このページでは、Android プラットフォームで複数ユーザーをテストする際の重要な観点について説明します。マルチユーザー サポートの実装については、複数ユーザーのサポートをご覧ください。
デバイスパス
次の表に、一部のデバイスパスとその解決方法を示します。 パス列の値は、すべてユーザーごとのサンドボックス化されたストレージです。 Android のストレージは年々進化しています。詳しくは、ストレージのドキュメントをご覧ください。
| パス | システムパス(省略可) | 目的 | 
|---|---|---|
| /data/user/{userId}/{app.path} | /data/data | アプリ ストレージ | 
| /storage/emulated/{userId} | /sdcard | 共有内部ストレージ | 
| /data/media/{userId} | なし | ユーザーのメディアデータ(音楽、動画など) | 
| /data/system/users/{userId} | なし | ユーザーごとのシステム構成や状態 システムアプリからのみアクセス可能 | 
次は、ユーザーごとのパスを使用する例です。
# to access user 10's private application data for app com.bar.foo:
$ adb shell ls /data/user/10/com.bar.foo/
ユーザーをまたぐ adb の操作
以下の adb コマンドは、複数のユーザーを取り扱う場合に使用できます。コマンドの一部は、Android 9 以降でのみサポートされています。
- adb shell am instrument --user <userId>: 特定のユーザーに対してインストゥルメンテーション テストを実行します。デフォルトでは、現在のユーザーが使用されます。
- adb install --user <userId>: 特定のユーザーに対してパッケージをインストールします。全ユーザーに対してパッケージがインストールされるようにするには、各ユーザーに対してこのコマンドを呼び出す必要があります。
- adb uninstall --user <userId>: 特定のユーザーのパッケージをアンインストールします。- --userフラグを付けずに呼び出すと、すべてのユーザーのパッケージをアンインストールします。
- adb shell am get-current-user: 現在(フォアグラウンド)のユーザー ID を取得します。
- adb shell pm list users: 既存のユーザーのリストを取得します。
- adb shell pm create-user: 新規のユーザーを作成し、その ID を返します。
- adb shell pm remove-user: ID により特定のユーザーを削除します。
- adb shell pm disable --user <userId>: 特定のユーザーのパッケージを無効にします。
- adb shell pm enable --user <userId>: 特定のユーザーのパッケージを有効にします。
- adb shell pm list packages --user <userId>: 特定のユーザーのパッケージを表示します。- -eを指定すると有効なパッケージを表示し、- -dを指定すると無効なパッケージを表示します。デフォルトでは、常にシステム ユーザーのパッケージを表示します。
以下で、複数ユーザーに対する adb の動作について説明します。
- adb(正確には- adbdデーモン)は、現在のユーザーに関係なく、常にシステム ユーザー(ユーザー ID が 0)として動作します。したがって、ユーザーに依存するデバイスパス(- /sdcard/など)は常にシステム ユーザーとして解決されます。詳しくは、デバイスパスをご覧ください。
- デフォルト ユーザーが指定されていない場合は、 - adbの各サブコマンドは別のユーザーとして実行されます。- --user <userId>フラグをサポートしているコマンドには、- am get-current-userでユーザー ID を取得してから、明示的にこのフラグを使用することをおすすめします。Android 9 までは、すべてのコマンドで明示的に user フラグを使用することはできませんでした。
- Android 9 以降では、セカンダリ ユーザーの - /sdcardパスへのアクセスが拒否されます。テスト中にファイルを取得する方法については、マルチユーザー データのコンテンツ プロバイダをご覧ください。
マルチユーザー データのコンテンツ プロバイダ
Android 9 以降では、adb はシステム ユーザーとして動作し、データはサンドボックス化されているため、システム ユーザー以外のユーザーのテストデータを push または pull するにはコンテンツ プロバイダを使用する必要があります。ただし、次の場合にはその必要がありません。
- adbdがルートとして動作している(- adb rootを使用)。これは- userdebugビルドまたは- userengビルドでのみ可能です。
- Trade Federation(Tradefed)の - ITestDeviceを使用してファイルを push または pull している。この場合は、テスト構成の- /sdcard/パスを使用します。たとえば、- NativeDevice.javaの- pushFileのソースコードを確認してください。
コンテンツ プロバイダがセカンダリ ユーザーで動作している場合は、user や uri などの適切なパラメータを指定して adb shell content コマンドを使用することによりアクセスできます。
アプリ デベロッパー向けの回避策
push コマンドまたは pull コマンドの代わりに、adb content と ContentProvider のインスタンスを使用してテストファイルを操作します。
- 必要に応じて、ファイルの提供や保存ができるアプリがホストしている ContentProviderのインスタンスを作成します。アプリの内部ストレージを使用してください。
- adb shell contentの- readコマンドまたは- writeコマンドを使用して、ファイルを push または pull します。
メディア ファイルの回避策
メディア ファイルを SD カードのメディア パーティションに push するには、MediaStore 公開 API を使用します。次に例を示します。
# push MVIMG_20190129_142956.jpg to /storage/emulated/10/Pictures
# step 1
$ adb shell content insert --user 10 --uri content://media/external/images/media/ --bind _display_name:s:foo.jpg
# step 2
$ adb shell content query --user 10 --projection _id --uri content://media/external/images/media/ --where "_display_name=\'foo.jpg\'"
# step 3
$ adb shell content write --user 10 --uri content://media/external/images/media/8022 < MVIMG_20190129_142956.jpg
汎用コンテンツ プロバイダをインストールする
ユーザーごとの /sdcard パスにファイルを読み書きする既存のコンテンツ プロバイダをインストールして使用します。
make TradefedContentProvider を使用してソースから TradefedContentProvider.apk をビルドします。
```
# install content provider apk
$ adb install --user 10 -g TradefedContentProvider.apk
# pull some_file.txt
$ adb shell content read --user 10 --uri content://android.tradefed.contentprovider/sdcard/some_file.txt > local_file.txt
# push local_file.txt
$ adb shell content write --user 10 --uri content://android.tradefed.contentprovider/sdcard/some_file.txt < local_file.txt
```
Trade Federation のマルチユーザー サポート
Tradefed は Android の公式テストハーネスです。ここでは、Tradefed に組み込まれているマルチユーザー テストシナリオのサポートについて一部を説明します。
ステータス チェッカー
システム ステータス チェッカー(SSC)はターゲット作成ツールの前に実行され、そのクリーンアップはターゲット作成ツールの後で実行されます。
UserChecker は、デベロッパーによる複数ユーザーのテストを支援することを目的として明示的に定義されています。テストでデバイス上のユーザーの状態が変更されたかどうかを追跡します(ティアダウンの際に削除せずにユーザーを作成したなど)。また、user-cleanup が設定されている場合は、テスト後に自動的にクリーンアップを試みます。この場合も、テストの修正を行ううえで有用なエラーを確認できます。
<system_checker class="com.android.tradefed.suite.checker.UserChecker" >
    <option name="user-cleanup" value="true" />
</system_checker>
ターゲット作成ツール
ターゲット作成ツールは通常、特定の構成でデバイスをセットアップするために使用されます。マルチユーザー テストの場合は、作成ツールを使用して特定タイプのユーザーを作成したり、他のユーザーに切り替えたりすることもできます。
セカンダリ ユーザーがないデバイスタイプの場合は、AndroidTest.xml 内で CreateUserPreparer を使用してセカンダリ ユーザーを作成し、そのユーザーに切り替えられます。テストの最後に、作成ツールが元のユーザーに戻して、セカンダリ ユーザーを削除します。
<target_preparer
  class="com.google.android.tradefed.targetprep.CreateUserPreparer" >
</target_preparer>
作成しようとするユーザータイプがすでにデバイスに存在する場合は、SwitchUserTargetPreparer を使用してその既存のユーザーに切り替えます。一般的な user-type の値には system や secondary があります。
<target_preparer
  class="com.android.tradefed.targetprep.SwitchUserTargetPreparer">
    <option name="user-type" value="secondary" />
</target_preparer>
ホストドリブン テスト
インスタンスによっては、テスト中にユーザーを切り替えることが必要な場合がありますが、UI Automator などのデバイス側のテスト フレームワーク内からは切り替えないでください。テストプロセスが突如強制終了される可能性があります。代わりに、Tradefed のホストドリブン テスト フレームワークのようなホスト側のテスト フレームワークを使用します。これにより、ITestDevice にアクセスして必要なユーザーに切り替えられるようになります。
ユーザーの状態を変更するホストドリブン テストには、終了後にテストが適切にクリーンアップされるように UserChecker(ステータス チェッカーを参照)を使用します。
