ダイレクト ブートのサポート

Android 7.0 は、電源を入れたあとにユーザーが端末のロックを解除していない状態で、セキュリティで保護されたダイレクト ブート モードで動作します。この機能をサポートするため、システムは次の 2 つのデータ保存先を備えています。

  • 認証情報暗号化ストレージ。これはデフォルトの保存先で、ユーザーが端末のロックを解除した後にだけ使用できます。
  • 端末暗号化ストレージ。この保存先は、ダイレクト ブート モード中とユーザーが端末のロックを解除した後の両方で使用できます。

デフォルトでは、ダイレクト ブート モード中はアプリは実行されません。ダイレクト ブート モード中もアプリを動作させたい場合は、このモードで実行するアプリ コンポーネントを登録します。ダイレクト ブート モードで実行する必要がある主なアプリは次のとおりです。

  • アラーム クロック アプリなど、通知がスケジュールされているアプリ。
  • SMS アプリなど、重要なユーザー通知を表示するアプリ。
  • Talkback など、ユーザー補助機能サービスを提供するアプリ。

ダイレクト ブート モードで実行中にアプリがデータにアクセスする必要がある場合は、端末暗号化ストレージを使用します。端末暗号化ストレージにはキーで暗号化されたデータが保存され、端末がセキュアブートに成功した場合にのみこのデータを使用できます。

ユーザーの認証情報に関連付けたキーで暗号化しなければならない PIN やパスワードなどのデータには、認証情報暗号化ストレージを使用します。認証情報暗号化ストレージは、ユーザーが端末のロック解除に成功した後に使用可能になり、ユーザーが端末を再起動するまでアクセスできます。ユーザーが端末をロック解除した後にロック画面を有効にしても、認証情報暗号化ストレージはロックされません。

ダイレクト ブート中に実行するためのアクセスを要求する

ダイレクト ブート モード中にアプリを実行したり、端末暗号化ストレージにアクセスしたりするには、アプリ コンポーネントの登録が必要です。登録するためには、アプリのコンポーネントが暗号化対応するように指定します。暗号化対応コンポーネントとして指定するには、マニフェスト内で android:directBootAware 属性を true に設定します。

暗号化対応コンポーネントを登録しておくと、端末を再起動したときにシステムから ACTION_LOCKED_BOOT_COMPLETED ブロードキャスト メッセージを受信できます。この時点で端末暗号化ストレージが使用できるようになり、コンポーネントはダイレクト ブート モード中にスケジュールしたアラームのトリガーなど、必要なタスクを実行できます。

次のコード スニペットは、アプリのマニフェスト内で BroadcastReceiver を暗号化対応として登録し、ACTION_LOCKED_BOOT_COMPLETED のインテント フィルタを追加する方法の例を示しています。

<receiver
  android:directBootAware="true" >
  ...
  <intent-filter>
    <action android:name="android.intent.action.ACTION_LOCKED_BOOT_COMPLETED" />
  </intent-filter>
</receiver>

ユーザーが端末のロックを解除すると、すべてのコンポーネントは端末暗号化ストレージと認証情報暗号化ストレージの両方にアクセスできます。

端末暗号化ストレージにアクセスする

端末暗号化ストレージにアクセスするには、Context.createDeviceProtectedStorageContext() を呼び出して追加の Context インスタンスを作成します。このコンテキストで実行されたストレージ API 呼び出しはすべて、端末暗号化ストレージにアクセスします。次の例では、端末暗号化ストレージにアクセスして既存のアプリのデータ ファイルを開きます。

Context directBootContext = appContext.createDeviceProtectedStorageContext();
// Access appDataFilename that lives in device encrypted storage
FileInputStream inStream = directBootContext.openFileInput(appDataFilename);
// Use inStream to read content...

端末暗号化ストレージは、ダイレクト ブート モード中にアクセスが必要な情報のみに対して使用してください。汎用的な暗号化された保存先として、端末暗号化ストレージを使用することはできません。ユーザーの個人情報や、ダイレクト ブート モード中に必要ではない暗号化されたデータには、認証情報暗号化ストレージを使用してください。

ユーザーによる端末のロック解除の通知を受信する

再起動後にユーザーが端末のロックを解除すると、アプリは認証情報暗号化ストレージにアクセスするよう切り替えて、ユーザーの認証情報に応じて通常のシステム サービスを使用します。

再起動後、ユーザーが端末のロックを解除したときに通知を受信するには、実行中のコンポーネントから BroadcastReceiver を登録して、ロック解除の通知メッセージをリッスンするようにします。端末の起動後、ユーザーが端末のロックを解除した場合の動作は次のとおりです。

  • アプリに即時の通知が必要なフォアグラウンド プロセスがある場合、ACTION_USER_UNLOCKED メッセージをリッスンします。
  • アプリで遅延通知に対応できるバックグラウンド プロセスのみが使用されている場合、ACTION_BOOT_COMPLETED メッセージをリッスンします。

ユーザーが端末のロックを解除しているかどうかを確認するには、UserManager.isUserUnlocked() を呼び出します。

既存のデータを移行する

ユーザーが端末をアップデートしてダイレクト ブート モードを使用できるようになると、既存のデータを端末暗号化ストレージに移行しなければならない場合があります。Context.moveSharedPreferencesFrom() および Context.moveDatabaseFrom() を使用すると、設定やデータベースのデータを認証情報暗号化ストレージと端末暗号化ストレージ間で移行できます。

どのデータを認証情報暗号化ストレージから端末暗号化ストレージに移行するかは、慎重に判断してください。パスワードや認証トークンなどのユーザーの個人情報は、端末暗号化ストレージに移行しないでください。場合によっては、この 2 つの暗号化された保存先に、データセットを振り分けて管理する必要があります。

暗号化対応アプリをテストする

ダイレクト ブート モードを有効にして、暗号化対応アプリをテストします。ダイレクト ブートを有効にする方法は 2 つあります。

警告: ダイレクト ブートを有効にすると、端末上のすべてのユーザーデータが消去されます。

Android 7.0 がインストールされたサポート対象端末では、次のいずれかの方法を使用してダイレクト ブートを有効にします。

  • 端末で、[Developer options] がまだ有効になっていない場合は、次の手順で有効にします。[Settings] > [About phone] を選択して [Build number] を 7 回タップします。[Developer options] 画面が表示されたら、[Settings] > [Developer options][Convert to file encryption] を選択します。
  • 次の adb shell コマンドを使用して、ダイレクト ブート モードを有効にします。
    $ adb reboot-bootloader
    $ fastboot --wipe-and-use-fbe
    

テスト端末でモードの切り替えが必要な場合、エミュレーションされたダイレクト ブート モードも使用できます。ただし、データが失われる可能性があるため、エミュレーション モードは開発中にのみ使用してください。エミュレーションされたダイレクト ブート モードを有効にするには、端末でロックパターンを設定します。ロックパターンの設定時に [Secure start-up] 画面が表示表示された場合は、[No thanks] を選択します。次に、以下の adb shell コマンドを実行します。

$ adb shell sm set-emulate-fbe true

エミュレーションされたダイレクト ブート モードを無効にするには、次のコマンドを使用します。

$ adb shell sm set-emulate-fbe false

このコマンドを実行すると、端末が再起動します。

デバイス ポリシーの暗号化ステータスを確認する

端末管理アプリで DevicePolicyManager.getStorageEncryptionStatus() を使用すると、端末の現在の暗号化ステータスを確認できます。アプリが API レベル 24.0(Android 7.0)未満を対象としており、端末でフルディスク暗号化またはダイレクト ブート モードを使ったファイルベースの暗号化が使用されている場合は、getStorageEncryptionStatus() によって ENCRYPTION_STATUS_ACTIVE が返されます。どちらの暗号化の場合でも、データは常に暗号化されて安全に保存されます。アプリが API レベル 24.0 以上を対象としており、端末でフルディスク暗号化が使用されている場合は、getStorageEncryptionStatus() によって ENCRYPTION_STATUS_ACTIVE が返されます。また、端末でダイレクト ブート モードを使ったファイルベースの暗号化が使用されている場合は、ENCRYPTION_STATUS_ACTIVE_PER_USER が返されます。

Android 7.0 を対象とする端末管理アプリを作成する場合は、ENCRYPTION_STATUS_ACTIVEENCRYPTION_STATUS_ACTIVE_PER_USER の両方を確認し、端末が暗号化されているかどうかを判定します。