支援直接啟動模式

當裝置處於開機狀態,但使用者未解鎖裝置時,Android 7.0 會在安全的「直接啟動」模式下執行。為支援這項功能,系統會提供兩個資料儲存位置:

  • 憑證加密儲存空間,這是預設的儲存位置,只有在使用者解鎖裝置後才能使用。
  • 裝置加密儲存空間,這是在直接啟動模式中,以及使用者解鎖裝置後皆可使用的儲存位置。

根據預設,應用程式不會在直接啟動模式下執行。如果您的應用程式必須在直接啟動模式下執行動作,您可以註冊要在這個模式執行的應用程式元件。需在直接啟動模式下執行的應用程式常見用途包括:

  • 設有排程通知的應用程式,例如鬧鐘應用程式。
  • 提供重要使用者通知的應用程式,例如簡訊應用程式。
  • 提供無障礙服務的應用程式,例如 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.LOCKED_BOOT_COMPLETED" />
  </intent-filter>
</receiver>

使用者解鎖裝置後,所有元件皆可存取裝置加密儲存空間與憑證加密儲存空間。

存取裝置加密儲存空間

如要存取裝置加密儲存空間,請呼叫 Context.createDeviceProtectedStorageContext() 來建立第二個 Context 例項。使用此結構定義的所有 Storage API 呼叫都會存取裝置加密儲存空間。下列範例會存取裝置加密儲存空間,並開啟現有的應用程式資料檔案:

Kotlin

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

Java

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(),將目的地結構定義做為方法呼叫端,並將來源結構定義做為引數,即可在憑證加密儲存空間和裝置加密儲存空間之間,遷移偏好設定和資料庫資料。

請勿將使用者私人資訊 (例如密碼或授權權杖) 從憑證加密儲存空間遷移至裝置加密儲存空間。在思考要將哪些資料遷移到裝置加密儲存空間時,請運用您的判斷力做出最佳決定。在某些情況下,您可能需要管理兩個加密儲存庫中的個別資料組合。

測試可偵測加密功能的應用程式

請在啟用直接啟動模式的狀態下測試加密感知應用程式。

只要設定了螢幕鎖定憑證 (PIN 碼、解鎖圖案或密碼),大多數搭載新版 Android 的裝置就會啟用直接啟動模式,具體來說,凡是使用檔案型加密的裝置都是如此。如要檢查裝置是否使用檔案型加密,請執行下列殼層指令:

adb shell getprop ro.crypto.type

如果輸出結果是 file,表示裝置已啟用檔案型加密。

在預設未使用檔案型加密的裝置上,可能會有其他測試直接啟動模式的選項:

  • 部分裝置採用全磁碟加密 (ro.crypto.type=block),且搭載的 Android 版本介於 7.0 至 12,可以轉換成檔案型加密。方法有以下兩種:

      警告:凡是轉換成檔案型加密的方法,都會抹除裝置上的所有使用者資料。

    • 在 Android 手機上啟用「開發人員選項」,方法是依序前往「設定」>「關於手機」,然後輕觸「版本號碼」七次。接著依序前往「設定」>「開發人員選項」,選取「轉換成檔案加密」
    • 或者,您也可以執行下列殼層指令:
      adb reboot-bootloader
      fastboot --wipe-and-use-fbe
      
  • 搭載 Android 13 以下版本的裝置支援「模擬」直接啟動模式,該模式會使用檔案權限,模擬加密檔案鎖定/解鎖的效果。模擬模式可能會導致資料遺失,請僅在開發階段使用。如要啟用模擬直接啟動模式,請在裝置上設定鎖定模式。如果在設定鎖定模式時看到安全啟動畫面出現提示,請選擇「不用了,謝謝」,然後執行以下殼層指令:

    adb shell sm set-emulate-fbe true
    

    如要關閉模擬直接啟動模式,請執行下列殼層指令:

    adb shell sm set-emulate-fbe false
    

    如果執行上述其中一項指令,裝置就會重新啟動。

查看裝置政策加密狀態

裝置管理應用程式可以使用 DevicePolicyManager.getStorageEncryptionStatus() 查看裝置目前的加密狀態。

如果應用程式指定的 API 級別低於 Android 7.0 (API 24),若裝置在直接啟動模式下使用全磁碟加密或檔案型加密,getStorageEncryptionStatus() 會傳回 ENCRYPTION_STATUS_ACTIVE。不論是何種做法,資料一律會以靜態資料加密方式儲存。

如果應用程式指定 Android 7.0 (API 24) 以上版本,若裝置採用全磁碟加密,getStorageEncryptionStatus() 會傳回 ENCRYPTION_STATUS_ACTIVE。如果裝置在直接啟動模式下使用檔案型加密,系統會傳回 ENCRYPTION_STATUS_ACTIVE_PER_USER

如要建構指定 Android 7.0 版本的裝置管理應用程式,請務必檢查 ENCRYPTION_STATUS_ACTIVEENCRYPTION_STATUS_ACTIVE_PER_USER,判斷裝置是否經過加密。

其他程式碼範例

DirectBoot 進一步示範了本頁提到的 API 用法。