対象範囲別ストレージ

対象範囲別ストレージは、アプリによる外部ストレージに対するアクセスを制限します。Android 11 以降、API 30 以降をターゲットとするアプリでは、対象範囲別ストレージを使用する必要があります。以前(Android 10)は、対象範囲別ストレージをアプリで無効にすることができました。

アプリによるアクセスの制限

対象範囲別ストレージの目的は、アプリとユーザーデータのプライバシーを保護することです。これには、ユーザー情報(写真メタデータなど)の保護、明示的な許可なしでアプリがユーザー ファイルを変更または削除することの防止、「ダウンロード」フォルダなどにダウンロードされた機密性の高いユーザー ドキュメントの保護が含まれます。

対象範囲別ストレージを使用するアプリには、次のアクセスレベルを付与できます(実際のアクセス権は実装によって異なります)。

  • 権限のない独自のファイルに対する読み取りアクセス権と書き込みアクセス権
  • READ_EXTERNAL_STORAGE 権限のある他のアプリのメディア ファイルに対する読み取りアクセス権
  • 他のアプリのメディア ファイルに対する書き込みアクセス権は、ユーザーが直接同意した場合にのみ許可されます(システム ギャラリーや、「すべてのファイル」アクセス権の対象となるアプリを除きます)
  • 他のアプリの外部アプリデータ ディレクトリに対する読み取りアクセス権または書き込みアクセス権はありません

FUSE で対象範囲別ストレージを使用する

Android 11 以降では Filesystem in Userspace(FUSE)がサポートされており、MediaProvider モジュールがユーザー空間でのファイル操作を調べ、アクセスを許可、拒否、訂正するポリシーに基づいてファイルに対するアクセスを制限できます。FUSE を使用する対象範囲別ストレージ内のアプリは、対象範囲別ストレージのプライバシー機能と、直接ファイルパスを使用してファイルにアクセスする(アプリで File API を機能させ続ける)機能を得ます。

Android 10 では、MediaProvider によるファイル アクセスには対象範囲別ストレージ ルールが適用されますが、カーネル呼び出しのインターセプトに手間がかかるため、直接ファイルパス アクセス(File API や NDK API を使用するなど)には適用されません。そのため、対象範囲別ストレージ内のアプリは、直接ファイルパスを使用してファイルにアクセスできませんでした。File API アクセスを MediaProvider API に書き換えるにはコードを大幅に変更する必要があったため、この制限はアプリ デベロッパーの適応能力に影響を与えました。

FUSE と SDCardFS

Android 11 での FUSE のサポートは、SDCardFS のサポート終了とは関係ありませんが、以前 SDCardFS を使用していたデバイスにメディアストアの代替手段を提供します。デバイスは:

  • カーネル 5.4 以降を使用して Android 11 以降でリリースする場合、SDCardFS を使用できません。
  • Android 11 以降にアップグレードすると、SDCardFS 上で FUSE をホストして、ファイル操作をインターセプトし、プライバシー目標を達成できます。

FUSE のパフォーマンス調整

Android では以前、外部ストレージが FUSE としてマウントされていた Android 7 以前で FUSE がサポートされていました。FUSE の実装に関するパフォーマンスとデッドロックの問題により、Android 8 では SDCardFS が導入されました。Android 11 では、改良され十分にテストされた libfuse の実装で FUSE のサポートが再度導入されました。Android 7 以前でのパフォーマンスの問題を解決するように調整できます。

FUSE の調整には、次の微調整が含まれます。

  • Android/data ディレクトリと Android/obb ディレクトリの FUSE をバイパスすることで、これらのディレクトリに依存するゲームアプリのパフォーマンスを改善する。
  • パフォーマンスの良い読み取りとスムーズなメディア再生を維持するための最適化(FUSE ファイル システムの先読みとダーティ比の調整など)。
  • FUSE の書き戻しキャッシュを使用する。
  • 権限をキャッシュ保存することでシステム サーバーに対する IPC を削減する。
  • 一括操作を高速化するために、すべてのファイルへのアクセス権を持つアプリを最適化。

上記の微調整により、FUSE デバイスと FUSE 以外のデバイスの間で同等のパフォーマンスが得られます。たとえば、FUSE を使用する調整済みの Pixel 2 とメディアストアを使用する Pixel 2 をテストしたところ、ファイルパス アクセスとメディアストアの間でシーケンシャル読み取りのパフォーマンス(動画再生など)が同等でした。ただし、シーケンシャル書き込みは FUSE の方が若干遅く、ランダム読み取りとランダム書き込みは最大で 2 倍遅くなることがありました。

パフォーマンスの測定値は、デバイスによって、また特定のユースケース間で変化する可能性があります。MediaProvider API は非常に一貫したパフォーマンスを提供するため、パフォーマンスを優先するアプリ デベロッパーは、アプリに MediaProvider API を使用する必要があります。

FUSE のパフォーマンスへの影響を軽減する

FUSE のパフォーマンスへの影響は、外部共有ストレージのみに保存されているファイルを頻繁に使用する場合に限られます。外部プライベート ストレージ(android/data ディレクトリと android/obb ディレクトリを含む)は FUSE によってバイパスされ、内部ストレージ(多くのアプリがデータを保存し、暗号化して安全を保つ /data/data など)は FUSE でマウントされません。

  • 共有外部ストレージを頻繁には使用しないアプリは多くの場合、少数のファイル(通常は 100 ファイル未満)しか扱いません。こうしたアプリでは、一般的な読み書き操作に関する既存の最適化によるメリットが得られ、Android 11 では、FUSE に関連したパフォーマンスへの影響はありません。

  • 通常、共有外部ストレージを頻繁に使用するアプリは、1,000 ファイル程度を保持するディレクトリのリスティングまたは削除、ファイル システム上で 100 万ファイル程度を保持するディレクトリの作成または削除など、一括ファイル操作を行います。一括ファイル操作は、Android 11 の FUSE の影響を受ける可能性がありますが、こうしたアプリが MANAGE_EXTERNAL_STORAGE 権限の対象となる場合は、2020 年 10 月のアップデートに含まれるパフォーマンス最適化によるメリットを得られます。

FUSE のパフォーマンス オーバーヘッドを回避するために、アプリは外部プライベート ストレージにデータを保存するか、ContentProvider クラスのバルク API を使用して FUSE をバイパスし、パフォーマンスを最適化したパスを得ることができます。さらに、MediaProvider システム コンポーネントに対する 2020 年 10 月のアップデートでは、MANAGE_EXTERNAL_STORAGE 権限を持つファイル マネージャーや同様のアプリ(バックアップ、復元、ウイルス対策など)のパフォーマンス最適化が行われています。

パフォーマンスに優先するプライバシー

FUSE 用に調整されたデバイスでは、クリティカル ユーザー ジャーニーのパフォーマンスの大半は Android 10 と Android 11 で同等です。ただし、一連のファイル操作のベンチマーク テストを行うと、Android 11 は Android 10 よりもパフォーマンスが低い場合があります。Android 11 でパフォーマンスが低下するファイル アクセス パターン(ランダム読み取りやランダム書き込みなど)に対しては、MediaProvider API を使用して、アプリを FUSE 以外のアクセスモードにすることをおすすめします。最適かつ一貫性のあるパフォーマンスが得られます。

MediaProvider と FUSE の更新

MediaProvider システム コンポーネントの動作は、Android リリースによって異なります。

  • Android 10 以前では、SDCardFS はファイル システムであり、MediaProvider はファイルのコレクション(画像、動画、音楽ファイルなど)へのインターフェースを提供していました。アプリで File API を使用してファイルを作成すると、ファイルをスキャンしてデータベースに記録するよう MediaProvider に要求できます。

  • Android 11 以降では、SDCardFS のサポートが終了し、MediaProvider は外部ストレージのファイル システム ハンドラ(FUSE 用)となり、外部ストレージのファイル システムと MediaProvider データベースの整合性が保たれるようになりました。FUSE ファイル システムのユーザー空間ハンドラとして、MediaProvider はカーネル呼び出しをインターセプトし、ファイル操作でのプライバシーが保護されます。

Android 11 以降では、MediaProvider は Android リリース外で更新可能なモジュラー システム コンポーネント(メインライン モジュール)でもあります。つまり、MediaProvider で見つかったパフォーマンス、プライバシー、セキュリティに関する問題の修正は可能であり、Google Play ストアや他のパートナーが提供する仕組みを通じて無線(OTA)で配信されます。FUSE ハンドラで想定される範囲内のものはすべて更新可能であるため、更新して FUSE のパフォーマンス低下やバグを修正できます。