従来のストレージ

Android の外部ストレージ HAL のアイコン

Android は、従来のストレージを備えたデバイスをサポートします。従来のストレージは大文字と小文字を区別しないファイルシステムとして定義されており、変更不能な POSIX 権限クラスとモードを使用します。従来のストレージの概念には、エミュレートされたポータブル ストレージも含まれます。ポータブル ストレージは、システムに取り込まれていないため、フォーマットと暗号化が行われていない(つまり、特定のデバイスに結びつけられていない)外部ストレージとして定義されます。従来の外部ストレージでは、保存されたデータに対して最小限の保護しか提供されないことから、外部ストレージ上のシステムコードに機密データを保存すべきではありません。つまり、構成ファイルとログファイルを保存するのは、それらを効果的に保護できる内部ストレージにのみとする必要があります。

マルチユーザー外部ストレージ

Android 4.2 以降、デバイスは複数のユーザーをサポートできるようになり、外部ストレージは以下の制約に従うことが必要になりました。

  • ユーザーごとに他のストレージと分離されたプライマリ外部ストレージを持ち、他のユーザーのプライマリ外部ストレージにはアクセスしません。
  • /sdcard パスは、プロセスを実行しているユーザーに応じて、ユーザー固有の適正なプライマリ外部ストレージとして解決します。
  • Android/obb ディレクトリにあるサイズの大きな OBB ファイル用ストレージは、最適化のために複数のユーザー間で共有できるようにします。
  • セカンダリ外部ストレージでは、統合された権限で許可されるパッケージ固有のディレクトリ以外では、アプリによる書き込みを行いません。

この機能のデフォルトのプラットフォーム実装では、Linux カーネルの名前空間を利用して、Zygote でフォークしたプロセスごとにマウント テーブルを分割して作成します。次に、バインドマウントを使用して、そのプライベート名前空間にユーザー固有の適正なプライマリ外部ストレージを用意します。

起動時に、EMULATED_STORAGE_SOURCE にあるエミュレートされた単一外部ストレージの FUSE デーモンが、システムによりマウントされます。これはアプリからは隠蔽されます。Zygote によってフォークされた後、FUSE デーモンの配下にある適切なユーザー固有サブディレクトリが EMULATED_STORAGE_TARGET にバインドマウントされます。これにより、外部ストレージのパスがアプリに対して正しく解決されます。アプリには、他のユーザーのストレージに対するアクセス可能なマウント ポイントがないため、アプリがアクセスできるのはストレージを起動させたユーザーのストレージのみになります。

また、この実装では、共有サブツリー カーネル機能を使用して、マウント イベントをデフォルトのルート名前空間からアプリ名前空間に伝達し、それによって ASEC コンテナや OBB マウントなどの機能が正常に動作し続けるようにします。これは、rootfs を共有用にマウントしてから、Zygote による名前空間を作成した後にスレーブとして再マウントすることで実現されます。

複数の外部ストレージ デバイス

Android 4.4 以降では、デベロッパーが Context.getExternalFilesDirs()Context.getExternalCacheDirs()Context.getObbDirs() を通じて、複数の外部ストレージ デバイスを扱えるようにしています。

これらの API を通じて扱えるようにする外部ストレージ デバイスは、バッテリー収納部にある SD カードスロットなど、デバイスにほぼ固定された部分であることが必要です。デベロッパーは、そのような場所に保存されたデータが長期間にわたって利用されることを想定しています。そのため、一時的なストレージ デバイス(USB マスストレージ ドライブなど)は、これらの API を通じて扱えるようにすることはできません。

WRITE_EXTERNAL_STORAGE 権限で書き込みアクセス権を付与するのは、デバイス上のプライマリ外部ストレージのみである必要があります。アプリでセカンダリ外部ストレージへの書き込みを行うことは許可されません。ただし、パッケージ固有のディレクトリが統合された権限によって許可されている場合は除きます。このような方法で書き込みを制限することで、アプリがアンインストールされた際に、システムによるファイルのクリーンアップが可能となります。

USB メディアのサポート

Android 6.0 では、USB フラッシュ ドライブなど、デバイスに短時間接続されるポータブル ストレージ デバイスがサポートされています。ユーザーが新しいポータブル デバイスを挿入すると、プラットフォームがそのデバイスのコンテンツのコピーまたは管理を促す通知を表示します。

Android 6.0 では、取り込まれていないデバイスはポータブル デバイスと見なされます。ポータブル ストレージは短時間しか接続されないため、プラットフォームはメディア スキャンなどの負荷の高いオペレーションを回避します。サードパーティ アプリは、ストレージ アクセス フレームワークを介してポータブル ストレージ上のファイルとやり取りする必要があります。プライバシーとセキュリティ上の理由により、直接のアクセスは明示的にブロックされます。