SDK ランタイムの概要

Android プラットフォームでは、アプリ サンドボックスのコンセプトをもちいることで、プロセス境界に沿ったアプリコードの堅牢な実行とセキュリティ境界が維持されます。アプリにサードパーティのコードを含めることは一般的であり、多くの場合、広告 SDK や分析 SDK などの SDK の形をとります。このような再利用により、アプリ デベロッパーはアプリの差別化に専念できると同時に、専門家の力を借り、負担なく独自で行える範囲をさらに広げることができます。

ほとんどのオペレーティング システムと同様に、Android では、SDK はホストアプリのサンドボックス内で実行され、ホストアプリと同じ特権と権限を継承します。また、ホストアプリのメモリとストレージへのアクセス権も継承します。このアーキテクチャでは SDK とアプリを柔軟に統合できますが、非公開のユーザーデータが収集され共有される可能性も生じます。さらに、アプリ デベロッパーは、サードパーティ SDK の機能やアクセスするデータの範囲を十分に把握していない場合があり、アプリのデータ収集や共有の方法について説明することは困難です。

Android 14 では、サードパーティ SDK を SDK ランタイムという専用のランタイム環境で実行できるようにする、新しいプラットフォーム機能を追加しました。SDK ランタイムは、次のように、ユーザーデータの収集と共有に関する安全対策と保証を強化します。

  • 実行環境の変更
  • SDK の権限とデータアクセス権の明確な定義

この設計について、モバイルアプリ広告コミュニティからのフィードバックをお待ちしています。また、幅広いデベロッパー コミュニティからのフィードバックもお待ちしています。お寄せいただいたフィードバックは、さらなるユースケースのサポートを含め、SDK ランタイムの今後のバージョンに役立てられます。

目標

この提案では、以下の目標を達成することを目指します。

  • プロセスの分離と明確に定義された API およびデータアクセス制御を通じて、サードパーティ SDK によってユーザーのアプリデータが秘密裡にアクセスされたり共有されたりすることを抑えます。プロセスの分離の詳細については、このドキュメントの別のセクションをご覧ください。
  • SDK による一意の永続的な識別子へのアクセスを制限することで、サードパーティ SDK によってユーザーのアプリ使用状況が秘密裡に追跡されることを抑えます。
  • アプリ デベロッパーとエンドユーザーの負担を軽減し、安全性を確保したうえで、アプリに対する SDK アップデートの配信を推進します。信頼できる SDK の配信モデルの案については、このドキュメントの別のセクションをご覧ください。
  • アプリ デベロッパーが、アプリのデータアクセスと共有の方法について適切に説明できるようにします。
  • SDK デベロッパーが、JNI コードなどの安全でない特定の言語構造を制限することで、他の SDK による改ざんを防止できるようにします。
  • メディアを表示するリモートビューを完全に制御することで、広告 SDK が無効なトラフィックや広告の不正行為を検出して防止できるようにします。
  • アプリ デベロッパーと SDK デベロッパーへの過度な影響をできる限り最小に抑えます。

独立したプロセスで SDK を実行する

今回提案する SDK ランタイムでは、対応している SDK(以下「RE(ランタイム対応)SDK」)を、アプリの別のプロセスで動作するようにします。このプラットフォームにより、アプリのプロセスと SDK ランタイム間の双方向通信が容易になります。詳細については、このドキュメントの通信に関するセクションをご覧ください。非 RE SDK は、現状と同様にアプリのプロセス内に残ります。次の図は、これらの変更を示しています。

アプリのプロセスを実行しているすべてのものを示す前図
SDK ランタイムに追加される前は、SDK を呼び出すコードと、このコードからの呼び出しを受け取る SDK はすべてアプリのプロセス内に存在します

アプリプロセスと SDK ランタイム プロセスに分割されたプロセスを示す「変更後」の図
SDK ランタイムに追加された後、アプリのフォアグラウンド プロセスで、SDK を呼び出すコードが SDK インターフェースと通信します。これらのインターフェースは、プロセス境界を越えて SDK ランタイム プロセスに含まれ、SDK 自体を呼び出します。

信頼性の高い新しい SDK 配信モデル

SDK とアプリの分離という提案は、SDK とアプリの配信という別の分離コンセプトにもつながります。この提案では、アプリの SDK ランタイムに正しい SDK がインストールされるように、配信とインストールについて信頼性の高いメカニズムが必要になります。そうすることで、無効な SDK が読み込まれないようにユーザーとアプリ デベロッパーを保護できるほか、アプリストアで SDK を配信するアプリ デベロッパーの負担を大幅に減らすことができます。

SDK を配信する際には、アプリストアにアップロードする前にアプリと静的にリンクしてパッケージ化する必要がありますが、これがなくなります。代わりに、次のプロセスが発生します。

  1. SDK デベロッパーは、アプリ自体とは別に、バージョニングされた SDK をアプリストアにアップロードします。
  2. アプリ デベロッパーは、SDK の依存関係をバージョンごとに指定してビルドし、実際の SDK の依存関係を含まないアプリリリースをアップロードします。
  3. ユーザーがこのアプリをダウンロードする際には、インストール プロセスでアプリに指定された SDK の依存関係が使用され、アプリがアプリストアからダウンロードされます。

この新しい配信メカニズムにより、SDK デベロッパーは、SDK に互換性を破らない変更(API やそのセマンティクスの変更はない)を加え、アプリ デベロッパーの関与なしにデバイスへ配信することができます。このような SDK の互換性を破らない変更については、デプロイやロールバックの際に、アプリ デベロッパーによる新しい SDK でのアプリの再ビルドや、エンドユーザーによるアプリの更新を待つことが必須ではなくなります。互換性を破る変更については、今後もアプリ デベロッパーによる更新が必要ですが、互換性を破らない変更と修正については、SDK デベロッパーが最新の内容をより多くのユーザーに迅速かつ一様に提供でき、しいてはバージョン サポートを最小限に抑えることが望めます。

SDK 配信の変更案を次の図に示します。

変更前の図
SDK ランタイムの導入前は、デベロッパーは SDK をアプリに直接送信していました。

変更後の図
SDK ランタイムの導入後、SDK デベロッパーは SDK アップロード UI を使用して、SDK をアプリストアに公開するようになります。 アプリストアは、SDK の依存関係とともに、エンドユーザー デバイスへのアプリの配信を処理します。

SDK とアプリのビルド、実行、配信方法の変更

この提案は、柔軟な SDK ランタイムと配信技術の実現を目的とした最初のものです。以降のセクションでは、次の幅広いカテゴリにわたる一連の変更について提案します。

  • アクセス: 権限、メモリ、ストレージ
  • 実行: 言語、ランタイムの変更、ライフサイクル、メディアのレンダリング
  • 通信: アプリ~SDK 間、SDK~SDK 間
  • 開発: このモデルでのビルド、デバッグ、テストの方法
  • 配信: Android、アプリ、SDK のバージョン間での配信、更新、ロールバックの方法

このドキュメントには、一般的な質問に対応するためのよくある質問も記載されています。

これは初期設計案であり、エコシステムのメンバーにとって重要な変更となる可能性があります。そのため、皆様からのフィードバックをお待ちしています。こちらの Issue Tracker からご意見をお寄せください。

アクセス

システムのプライバシーを管理するということは、さまざまな当事者による複数のリソースへのアクセス方法を管理するということを意味します。Google は、プライバシーに関する価値提案を満たすために、アプリ、SDK、ユーザーデータへのアクセスモデルを更新し、最小権限の原則に従って、機密情報になり得るデータへの非公開のアクセスを防止することを提案します。

SDK の権限

個別のプロセスとして、SDK ランタイムには、ユーザーがアプリに付与した権限を継承するのではなく、独自の明確に定義された権限セットが用意されます。広告関連の SDK で使用される権限に関する予備調査に基づき、SDK ランタイムの SDK がデフォルトで次の権限にアクセスできるようにすることを提案します。

  • INTERNET: ウェブサービスと通信できるようにするためのインターネット アクセス。
  • ACCESS_NETWORK_STATE: ネットワークに関する情報へのアクセス。
  • READ_BASIC_PHONE_STATE: スマートフォンの状態に関する情報(モバイル ネットワークの種類など)にアクセスします。
  • クロスアプリ識別子にアクセスすることなく、主要な広告機能を提供できるプライバシー保護 API の利用に関する権限。
  • AD_ID: 広告 ID をリクエストする機能。これも、この権限に対するアプリのアクセス権によって制限されます。

現在、プライバシーとユーザビリティの両面からエンドユーザーへの影響を抑えつつ、追加の権限を承認するかどうか、またどのように承認するかについて検討しています。この権限のセットでは対応できないと考えられるユースケースがあれば、ぜひフィードバックをお寄せください

メモリ

SDK ランタイムには独自のプロセスがあることから、メモリについても分離された独自の領域が用意されます。この構造においては、SDK がアプリのメモリ領域にアクセスすることがデフォルトで拒否され、同様に SDK のメモリ領域にアクセスすることもできなくなります。最小権限の原則に沿ったうえで、このデフォルトの動作を維持することを提案します。

ストレージ

ここでの提案の目的は、SDK が通常のオペレーションのためにストレージにアクセスする必要性と、永続ストレージを使用したアプリ間やプロセス間のトラッキングを最小限に抑えることのバランスをとることです。ストレージにアクセスする方法について、次のように更新することを提案します。

  • アプリは SDK のストレージに直接アクセスできない。その逆も同様。
  • デバイスの外部ストレージに SDK からはアクセスできない。
  • 各 SDK ランタイム内に、すべての SDK からアクセス可能なストレージと、特定の SDK 専用のストレージを用意する。

現在のストレージ モデルのように、ストレージ自体のサイズに任意の制限はありません。SDK は、アセットのキャッシュにストレージを使用できます。このストレージは、SDK がアクティブに実行されていないときに定期的に消去されます。

実行

アプリ、SDK、ユーザーの間でプライベート システムを確保するには、実行コンテキスト自体(コード形式、言語構造、アクセス可能な API、システムデータ)でプライバシー境界を強化するか、少なくとも回避する手段を導入しないようにする必要があります。同時に、現在の SDK の高機能なプラットフォームとランタイム機能の大部分にも引き続きアクセスできるようにします。このバランスをとるために、ランタイム環境に対する一連の更新を提案します。

コード

Android コード(アプリと SDK)は、コードの記述に使用したプログラミング言語が Kotlin か Java かにかかわらず、主に Android ランタイム(ART)によって解釈されます。ART には豊富な機能があり、その言語構造や代替手段(具体的にはネイティブ コード)と比較した場合の検証可能性もふまえると、機能性とプライバシーのバランスが適切に保たれていると考えられます。ランタイムで有効な SDK コードは、JNI アクセスをサポートするのではなく、Dex バイトコードのみで構成することを提案します。

カスタム パッケージの SQLite を使用するなどのユースケースもあります。ネイティブ コードを使用している場合には、Android SDK の組み込みバージョンの SQLite など、代替手段に置き換える必要があります。

SELinux

Android では、各プロセス(root として実行されているものを含む)が特定の SELinux コンテキストで実行されるため、カーネルでシステム サービス、ファイル、デバイス、その他のプロセスへのアクセス制御を管理できます。Google が進めようとしているプライバシー保護の回避を最小限に抑えつつ、SDK のユースケースの大部分を保持するために、システム以外のアプリの SELinux コンテキストから、SDK ランタイムを対象に次のように更新することを提案します。

  • アクセスできるシステム サービスを一部に限る(設計中)。
  • SDK が APK 内のコードの読み込みと実行しかできないようにする
  • アクセスできるシステム プロパティを一部に限る(設計中)。

API

SDK ランタイム内では、リフレクション API と呼び出し API を使用できます。ただし、別のランタイム対応の SDK でリフレクション API や呼び出し API を使用することはできません。禁止されている API の提案について詳しくは、今後の更新でお知らせします。

さらに、最近の Android プラットフォーム リリースでは、プライバシー強化のために永続的な識別子へのアクセスが制限されるようになりました。SDK ランタイムでは、クロスアプリ トラッキングに使用される可能性のある識別子へのアクセスをさらに制限することを提案します。

SDK ランタイム API は、フォアグラウンドで実行されているアプリからのみアクセスできます。バックグラウンドでアプリから SdkSandboxManager API にアクセスしようとすると、SecurityException がスローされます。

また、RE SDK では、通知 API を使用したユーザー通知の送信がいかなる時点でもできません。

Lifecycle

現在、アプリ SDK はホストアプリのライフサイクルに従うようになっています。つまり、アプリがフォアグラウンドで開始または終了される、シャットダウンされる、メモリ負荷のためにオペレーティング システムによって強制停止されると、アプリ SDK も同じ動作をします。そこで、アプリ SDK を別のプロセスに分割するよう提案しますが、これはライフサイクルを次のように変更することを意味します。

  • アプリは、ユーザーまたはオペレーティング システムによって終了させることができる。直後に、SDK ランタイムが自動的に終了する。
  • SDK ランタイムは、メモリ負荷や、SDK での未処理の例外などにより、オペレーティング システムによって終了させることができる。

    Android 14 ではアプリがフォアグラウンドにある場合、SDK ランタイムは高優先度で実行され、停止する可能性は低くなります。アプリがバックグラウンドに移行すると、SDK ランタイム プロセスの優先度が低くなり、停止の対象になります。アプリがフォアグラウンドに戻っても、SDK ランタイム プロセスの優先度は低いままです。そのため、メモリ不足で終了してしまう可能性は、アプリより非常に高くなります。

    Android 14 以降では、アプリと SDK ランタイムのプロセス優先度は一致しています。アプリと SDK ランタイムの ActivityManager.RunningAppProcessInfo.importance のプロセス優先度はほぼ同じです。

    アプリの実行中に SDK ランタイムが終了した場合(SDK に未処理の例外がある場合など)、以前に読み込まれたすべての SDK とリモートビューを含む SDK ランタイムの状態が失われます。アプリ デベロッパーは、次のいずれかの方法で SDK ランタイムの終了に伴って処理を実行できます。

    • このプロポーザルでは、関連するライフサイクル コールバック メソッドをアプリ デベロッパーに提供し、SDK ランタイムの終了が発生したタイミングを検出します。
    • 広告の表示中に SDK ランタイムが終了した場合、広告が想定どおりに機能しなくなる可能性があります。たとえば、ビューが画面上でフリーズし、操作できなくなることがあります。アプリでは、ユーザー エクスペリエンスに影響しない場合は広告ビューを削除できます。
    • アプリでは SDK の読み込みと広告のリクエストを再試行できます。
    • Android 14 では、SDK の読み込み中に SDK ランタイムが終了し、アプリ デベロッパーが前述のライフサイクル コールバック メソッドを登録していない場合、デフォルトではアプリは終了します。SDK を読み込んだアプリプロセスのみが正常に終了します。
    • 通信のために SDK から返されたバインダ オブジェクト(SandboxedSdk など)は、アプリで使用されている場合に DeadObjectException をスローします。

    このライフサイクル モデルは、今後の更新で変更される可能性があります。

    永続的な障害が発生した場合には、アプリ デベロッパーは SDK を使用しないグレースフル デグラデーションを予定する必要があります。あるいは、SDK がアプリのコア機能に不可欠であればユーザーに通知する必要があります。このアプリと SDK の間のインタラクションについて詳しくは、このドキュメントの通信のセクションをご覧ください。

非 RE SDK では、サービス、アクティビティ、ブロードキャストなど、組み込みアプリで使用できる標準的な OS プリミティブを引き続き使用できますが、RE SDK では使用できません。

特別な場合

次のようなケースはサポートされていないため、予期しない動作が発生する可能性があります。

  • 複数のアプリが同じ UID を共有している場合、SDK ランタイムが正常に機能しない可能性があります。共有 UID のサポートは今後追加される可能性があります。
  • 複数のプロセスを使用するアプリの場合、SDK の読み込みはメインプロセスで行う必要があります。

メディアのレンダリング

複数の SDK で、テキスト、画像、動画などのコンテンツをアプリ指定のビューにレンダリングする場合があります。これを実現するために、リモート レンダリング アプローチを提案します。このアプローチでは、SDK が SDK ランタイム内からメディアをレンダリングしますが、アプリ指定のビューでメディアをレンダリングできるように SurfaceControlViewHost API を使用します。これにより、SDK では、ユーザーに限定された方法でメディアをレンダリングする機能が提供されるとともに、レンダリングされたメディアに対する無効または不正なユーザー操作の防止と検出が行えます。

SDK ではなくアプリがレンダリングするネイティブ広告は、SDK ランタイムの SDK でサポートされます。ネイティブ広告以外でも、シグナルの収集処理とクリエイティブの取得処理が一貫して行われます。これについては現在調査中です。

インストリーム動画広告は、アプリ内のプレーヤーに表示される動画とともに配信される広告です。動画が SDK のプレーヤーやビューではなくアプリのプレーヤー内で再生されるため、レンダリング モデルが他の広告フォーマットとは異なります。Google は、サーバーサイドの広告挿入と SDK ベースの広告挿入の両方をサポートするメカニズムを検討しています。

システムの状態

Google は、SDK ランタイムがエンドユーザーのデバイスに与えるシステムの健全性への影響を最小限に抑え、その方法を設計しています。ただし、システムの健全性への影響が原因で、Android(Go エディション)など、システム リソースが非常に限られている一部のエントリーレベルの Android 14 デバイスは、SDK ランタイムをサポートしない可能性があります。SDK ランタイムを正常に使用するために必要な最小要件については、近日中にお知らせいたします。

通信

現在、アプリと SDK は同じプロセスで実行されているため、両者の間の通信は妨げられず、仲介もされません。また、Android では、SDK で通信の開始と終了を行う場合でもアプリ間の通信が可能です。この自由な通信モデルにより、さまざまなユースケースが実現される一方で、アプリとアプリ、アプリ内の SDK と SDK、アプリ間の SDK と SDK の間で、非公開のデータが共有される可能性が生じます。このような通信の価値と Google が掲げた目標の実現との間でバランスを取ることを目指し、通信モデルを次のように更新することを提案します。

アプリ~SDK 間

アプリと SDK の間のインターフェースは SDK への最も一般的な通信経路です。SDK の API には、ユーザー向けの差別化とイノベーションの多くが存在しています。Google は、SDK のイノベーションと差別化の機能を保つことを目指します。その結果として、SDK がアプリに対して API を公開し、アプリがイノベーションの恩恵をすべて受けられるようにすることを提案します。

具体的には、SDK ランタイムのプロセス境界構造をふまえ、アプリと SDK の間の境界を越えて API の呼び出しとレスポンスまたはコールバックを伝送するために、アプリ内でアクセス可能なマーシャリング レイヤを構築します。このマーシャリング レイヤのインターフェースは SDK デベロッパーが定義し、Google が開発する公式のオープンソース ビルドツールで生成します。

この提案では、アプリ デベロッパーと SDK デベロッパーがマーシャリングに関連するボイラープレートを記述しなくていいようにすることを目指します。また同時に、SDK デベロッパーに柔軟性を提供しつつ、SDK コードが SDK ランタイムで実行されるようにして、Google の目指すプライバシー目標を達成できるようにします。なお、この方法を採用する場合には、API の定義言語とツールについて、デベロッパーの意見を取り入れて設計する予定です。

一般的なインタラクション モデルは次のようになります。

  • アプリがインターフェースを通じて SDK を呼び出し、コールバックで渡す。
  • SDK がコールバックを使用して非同期的にリクエストを処理し、応答する。
  • 任意のパブリッシャー サブスクライバー モデルに一般化できる。つまり、アプリはコールバックで SDK のイベントに登録でき、イベントが発生するとコールバックがトリガーされる。

この新しいクロスプロセス構造を提案することで、アプリ自体のプロセス ライフサイクルと、SDK ランタイムのプロセス ライフサイクルという 2 つのプロセス ライフサイクルを管理する必要が生じます。今回の提案では、この点を可能な限り自動化することで、アプリ デベロッパーと SDK デベロッパーへの影響を最小限に抑えることを目指しています。検討中のアプローチを次の図に示します。

図
アプリと SDK を起動する際のアプリ~ SDK 間のインタラクションを示すシーケンス図。

プラットフォームでは、SDK ランタイム プロセスに SDK を動的に読み込み、プロセスの状態の変化について通知を受け、SDK ランタイムに読み込まれた SDK とやりとりするための新しい API が公開されます。

上の図のグラフは、マーシャリング レイヤがない下位レベルでのアプリ~ SDK 間の通信を示しています。

アプリは、次の手順で SDK ランタイム プロセスで実行されている SDK と通信します。

  1. アプリは SDK とやりとりする前に、SDK を読み込むようプラットフォームにリクエストします。システムの整合性を確保するために、アプリがマニフェスト ファイルで読み込む予定の SDK を指定します。指定された SDK だけが読み込みを行えます。

    次のコード スニペットに API の例を示します。

    SdkSandboxManager.loadSdk(String sdkName, Bundle data, Executor executor,
        OutcomeReceiver<SandboxedSdk, LoadSdkException> receiver)
    
  2. SDK は、読み込み完了の通知を受け取り、そのインターフェースを返します。このインターフェースは、アプリプロセスで使用するためのものです。プロセス境界外でインターフェースを共有するには、インターフェースを IBinder オブジェクトとして返す必要があります。

    バインドされたサービスに関するガイドで、IBinder を提供するさまざまな方法について説明しています。どの方法を採用するとしても、SDK と呼び出し元アプリ間で一貫して使用する必要があります。図は AIDL を例として使用しています。

  3. SdkSandboxManagerIBinder インターフェースを受け取り、アプリに返します。

  4. アプリは IBinder を取得して SDK インターフェースにキャストし、その関数を呼び出します。

    IBinder binder = sandboxSdk.getInterface();
    ISdkInterface mySdkInterface = ISdkInterface.Stub.asInterface(binder);
    mySdkInterface.something();
    

アプリは、次の手順で SDK からメディアをレンダリングすることもできます。

  1. このドキュメントのメディア レンダリングのセクションで説明したように、SDK を取得してビューにメディアをレンダリングするために、アプリは requestSurfacePackage() を呼び出して該当する SurfaceControlViewHost.SurfacePackage を取得します。

    次のコード スニペットに API の例を示します。

    SdkSandboxManager.requestSurfacePackage(String sdkName, Bundle extraParams,
            Executor executor,
            OutcomeReceiver<Bundle, RequestSurfacePackageException> receiver)
    
  2. アプリは、SurfaceViewsetChildSurfacePackage API を介して、返された SurfacePackageSurfaceView に埋め込むことができます。

    次のコード スニペットに API の例を示します。

    SurfaceView.setChildSurfacePackage(SurfacePackage surfacePackage)
    

この提案では、IBinder API と requestSurfacePackage() API は汎用であり、アプリから直接呼び出されることを想定していません。代わりに、先に説明したように、アプリ デベロッパーの負担を軽減するため、これらの API は生成された API リファレンスによって「shim」レイヤで呼び出されます。

SDK~SDK 間

同じアプリ内の 2 つの SDK 間で通信を行う必要があるケースはよくあります。このケースは、ある SDK が、構成要素 SDK で構成されるように設計されている場合に生じる可能性があります。また、呼び出し元アプリからのリクエストに対応するために、異なる当事者の 2 つの SDK が連携する必要がある場合にも生じる可能性があります。

考慮すべき重要なケースが 2 つあります。

  • 両方の SDK がランタイム対応の場合: この場合、両方の SDK が SDK ランタイムで実行され、すべての保護が適用されます。各 SDK は、現在アプリ内で行っているような通信を行うことはできません。そのため、SdkSandboxController の API が追加され、読み込まれたすべての RE-SDK の SandboxedSdk オブジェクトを取得できるようになっています。これにより、RE-SDK が SDK ランタイムに読み込まれた他の SDK と通信できるようになります。
  • 一方の SDK のみがランタイムで有効になっている場合:
    • 呼び出し元 SDK がアプリ内で実行されている場合は、SDK ランタイム内の 2 番目の SDK をアプリ自体が呼び出す場合と同じように動作します。
    • 呼び出し元 SDK が SDK ランタイム内で実行されている場合については、アプリ~ SDK 間のセクションで説明されている IBinder を使用してメソッドを公開することを提案します。この呼び出しでは、指定のコールバックを使用して、アプリのコードでリッスン、処理、応答を行います。
    • ランタイムで有効になっていない広告 SDK は、自身を登録できない場合があります。そのため、パートナー SDK やアプリ SDK をアプリの直接の依存関係として含め、登録を処理するメディエーション SDK を作成することをおすすめします。このメディエーター SDK は、ランタイム対応ではない SDK や他のアプリの依存関係と、アダプターとして機能するランタイム対応メディエーターとの間の通信を確立します。

SDK 間通信の機能セットは、以下のカテゴリに分類されます。

  • SDK ランタイム内の SDK 間通信(最新のデベロッパー プレビューで利用可能)
  • アプリと SDK ランタイム間の SDK 間通信(最新のデベロッパー プレビューで利用可能)
  • メディエーションのビューとリモート レンダリングの仕組み(開発中の提案)

プリミティブが設計中で、次のユースケースが検討されています。

  1. メディエーションと入札: 多くの広告 SDK にはメディエーションや入札の機能があります。これにより SDK は他のさまざまな SDK を呼び出して、広告の表示(メディエーション)や、オークション(入札)を行うためのシグナル収集を行います。調整 SDK は通常、調整 SDK が提供するアダプターを通じて他の SDK を呼び出します。前述のプリミティブを考慮すると、調整 SDK は、RE かどうかにかかわらず、通常のオペレーションのためにすべての RE SDK と非 RE SDK にアクセスできる必要があります。この場合のレンダリングについては現在調査中です。
  2. 機能の検出: 一部の SDK プロダクトはより少ない SDK で構成されています。このようなプロダクトでは、SDK 間での検出プロセスを通じて、アプリ デベロッパーに公開される最終的な機能セットが特定されます。このユースケースを有効にするために、登録と検出のプリミティブが想定されます。
  3. パブリッシャー サブスクリプション モデル: 一部の SDK はイベントのセントラル パブリッシャーを持つように設計されます。これは、他の SDK またはアプリが通知を受け取るためにコールバックを通じて登録できるものです。前述のプリミティブは、このユースケースをサポートする必要があります。

アプリ~アプリ間

アプリ間通信は、通信する 2 つのプロセスのうち、少なくとも 1 つがランタイム対応 SDK であり、未公開のデータ共有の潜在的なベクトルです。そのため、SDK ランタイムは、クライアント アプリケーション以外のアプリや、別のアプリ用に作成された別の SDK ランタイム内の SDK と直接通信チャンネルを確立できません。これは次の方法で実現されます。

  • SDK は、マニフェストで <service><contentprovider><activity> などのコンポーネントを定義できません。
  • SDK は ContentProvider を公開したり、ブロードキャストを送信したりできません。
  • SDK は別のアプリに属するアクティビティを起動できますが、インテントで送信できる内容には制限があります。たとえば、このインテントにエクストラやカスタム アクションを追加することはできません。
  • SDK は、サービスの許可リストへの登録またはバインドのみできます。
  • SDK は、システム ContentProvider のサブセット(com.android.providers.settings.SettingsProvider など)にのみアクセスできます。この場合、取得データは識別子を持たず、ユーザーのフィンガープリントの作成には使用できません。これらのチェックは、ContentResolver を使用した ContentProvider へのアクセスにも適用されます。
  • SDK は、保護されたブロードキャスト レシーバのサブセット(android.intent.action.AIRPLANE_MODE など)にのみアクセスできます。

マニフェスト タグ

SDK がインストールされると、PackageManager は SDK のマニフェストを解析し、禁止されているマニフェスト タグが存在する場合は SDK をインストールできません。たとえば、SDK で <service>, <activity>, <provider><receiver> などのコンポーネントが定義されていない場合や、マニフェストで <permission> が宣言されていない場合があります。インストールに失敗したタグは、SDK ランタイムではサポートされていません。インストールに失敗せず、サイレントで無視されるタグは、今後の Android バージョンでサポートされる可能性があります。

これらのチェックは、SDK が SDK バンドルの作成に使用するビルド時ツールによって、またアプリストアにアップロードするときに適用されることもあります。

アクティビティのサポート

SDK ランタイム環境の SDK は、マニフェスト ファイルにアクティビティ タグを追加できず、Context.startActivity を使用して独自のアクティビティを開始できません。代わりに、プラットフォームはリクエスト時に SDK のアクティビティを作成し、SDK と共有します。

プラットフォーム アクティビティの型は android.app.Activity です。プラットフォーム アクティビティは、アプリのアクティビティの 1 つから開始され、アプリタスクの一部です。FLAG_ACTIVITY_NEW_TASK はサポートされていません。

SDK がアクティビティを開始するには、SdkSandboxActivityHandler タイプのインスタンスを登録する必要があります。このインスタンスは、アプリが SdkSandboxManager::startSdkSandboxActivity(Activity, IBinder) を呼び出してアクティビティを開始するときに、アクティビティの作成について通知するために使用されます。

アクティビティのリクエストの流れを以下のグラフに示します。

図 アクティビティを開始するフローを示すシーケンス図。

開発

この提案の基本方針は、デベロッパー エコシステムへの影響を可能な限り最小限に抑えることです。この提案では、RE アプリと SDK の記述、ビルド、デバッグを行うための包括的な開発ツールセットのデベロッパーへの提供を提案します。提案の整合性を確保するため、RE アプリと SDK の設定、オーサリング、ビルドの方法が一部変更されます。

オーサリング

Android Studio と関連ツールが SDK ランタイムに対応するように更新される予定です。デベロッパーが RE アプリと SDK を正しく設定し、既存の呼び出しやサポートされていない呼び出しを関連する新しい代替方法に更新できるようにサポートします。この提案では、デベロッパーにオーサリング フェーズでいくつかの手順を踏むよう求めています。

アプリ デベロッパー

アプリ マニフェストで、アプリの RE SDK と SDK 証明書の依存関係を指定する必要があります。今回の提案全体で、この依存関係の指定をアプリ デベロッパーからの信頼できる情報源として扱います。次に例を示します。

  • 名前: SDK またはライブラリのパッケージ名。
  • メジャー バージョン: SDK のメジャー バージョン コード。
  • 証明書ダイジェスト: SDK ビルドの証明書ダイジェスト。関連するアプリストアを通じて、SDK デベロッパーが特定のビルドについてこの値を取得して登録することを提案します。

これは、RE であるかどうかにかかわらず、アプリストアで配布される SDK にのみ適用されます。SDK を静的にリンクするアプリでは、現在の依存関係メカニズムを使用します。

デベロッパーへの影響を最小限に抑えるという目標をふまえると、SDK ランタイムをサポートするターゲット API レベルが指定されれば、ビルドが SDK ランタイムをサポートしているデバイスで実行されているかどうかにかかわらず、アプリ デベロッパーがビルドを 1 つ用意すれば済むようになることが重要です。

SDK デベロッパー

今回の提案では、RE SDK デベロッパーが、SDK またはライブラリ エンティティを表す新しい要素をマニフェストで明示的に宣言する必要があります。さらに、依存関係と同様の値のセットとマイナー バージョンを指定する必要があります。

  • 名前: SDK またはライブラリのパッケージ名。
  • メジャー バージョン: SDK のメジャー バージョン コード。
  • マイナー バージョン: SDK のマイナー バージョン コード。

RE SDK デベロッパーは、ビルド時の依存関係として他の RE SDK を使用している場合、アプリ デベロッパーが同じ依存関係を宣言する際と同じ方法で RE SDK を宣言する必要が生じます。RE SDK が非 RE SDK に依存する場合は、静的にリンクされます。非 RE SDK が、SDK ランタイムでサポートされていない機能を必要とする場合、またはアプリのプロセスで実行される必要がある場合、ビルド時またはテストパス中に検出される問題が発生する可能性があります。

RE SDK デベロッパーが、RE 未対応デバイスのサポート継続を必要とする場合もあります。RE 未対応デバイスには、Android 12 以前や、このドキュメントのシステムの健全性に関するセクションで説明した、システム リソースが非常に限られているエントリーレベルの Android 14 デバイスなどが挙げられます。Google は、SDK デベロッパーが単一のコードベースを保持して RE 環境と非 RE 環境に対応できるようにするためのアプローチに取り組んでいます。

ビルド

アプリ デベロッパー

アプリ デベロッパーがビルドステップで変更を必要とすることはほとんどないと見込まれます。ローカルで配信されているかアプリストアで配信されているかにかかわらず、lint チェック、コンパイル、ビルドを行うためには、SDK の依存関係がマシン上に存在する必要があります。アプリ デベロッパーから提供されるこれらの詳細情報と通常の使用状況を、Android Studio で抽象化し、可能な限り透明性を保つことを提案します。

デバッグビルドでは、デバッグを可能にするためにすべてのコードとシンボルをデバッグビルドに含める必要があります。一方、リリースビルドでは必要に応じて、アプリストアで配信されるすべての SDK を(RE かどうかにかかわらず)最終的なアーティファクトから削除します。

今は設計の初期段階であるため、具体化するときに詳しくお伝えします。

SDK デベロッパー

Google は、SDK の非 RE 版と RE 版を単一のアーティファクトに組み込んで配信できるようにする取り組みを進めています。これによりアプリ デベロッパーは、RE 版と非 RE 版の両方の SDK で別々のビルドをサポートする必要がなくなります。

アプリと同様に、lint チェック、コンパイル、ビルドを行うためには、アプリストアで配信される依存関係 SDK がマシン上に存在する必要があります。これは、Android Studio によりシームレスに容易に行えるようになることが期待されます。

テスト

アプリ デベロッパー

この提案で説明しているとおり、アプリ デベロッパーは、Android 14 を搭載したデバイスで通常と同じようにアプリをテストすることが可能です。アプリをビルドしたら、RE デバイスまたはエミュレータにインストールできます。このインストール プロセスでは、SDK がリモート SDK リポジトリから取得されたか、ビルドシステムからキャッシュに保存されたかにかかわらず、デバイスまたはエミュレータの SDK ランタイムに正しい SDK がインストールされます。

SDK デベロッパー

SDK デベロッパーは通常、デバイスとエミュレータ上で自社のテストアプリを使用して開発内容をテストします。この点については、今回の提案で変更されることはありません。アプリ内検証は上述のアプリ デベロッパー向けの手順と同様に実施でき、RE アプリと非 RE アプリの両方に単一のビルド アーティファクトが使用されます。SDK デベロッパーは、SDK ランタイムかどうかにかかわらず、コードをステップスルーできます。ただし、高度なデバッグツールやプロファイリング ツールには制約の生じる場合があります。これについては現在調査中です。

配信

アプリの SDK からの分離を提案することで、SDK をアプリストアで配布することが可能になります。これは特定のアプリストアに限ったことではなく、全体として可能です。次のようなメリットがあります。

  • SDK の品質と一貫性が確保されます。
  • SDK デベロッパー向けのパブリケーションが合理化されます。
  • SDK のマイナー バージョン アップデートがインストール済みのアプリに迅速にロールアウトされます。

SDK の配信をサポートするには、アプリストアで以下の機能をほぼすべて提供する必要があります。

  • SDK デベロッパーが、アプリストアで配信可能な SDK をストアにアップロードし、アップデートやロールバックを行い、場合によっては削除を行うメカニズム。
  • SDK とその提供元、アプリとその提供元の整合性を確保し、依存関係を解決するメカニズム。
  • 一貫した信頼性を保ち、パフォーマンスの高い方法でデバイスにデプロイするメカニズム。

制限の変化

SDK ランタイムのコードが直面する制限は、Android の新しいバージョンとともに進化することが予想されます。アプリの互換性を保つため、特定の SDK レベルのメインライン モジュールのアップデートでこれらの制限を変更することはありません。特定の targetSdkVersion に関連付けられた動作は、アプリストアのポリシーによってその targetSdkVersion のサポートが非推奨になるまで保持されます。targetSdkVersion の非推奨化は、アプリよりも早いペースで行われる場合もあります。制限は Android SDK のバージョン間で頻繁に変更されます(特に最初の数回のリリースで変更されます)。

また、外部テスターと内部テスターが、次期バージョンの Android の提案された一連の制限を受け取るグループに参加できるように、カナリア メカニズムを構築しています。これにより、制限のセットに対する提案された変更についてフィードバックを得て、信頼性を高めることができます。

よくある質問

  1. 広告関連の SDK とは何ですか。

    広告関連の SDK とは、広告主が所有していないアプリで、営利目的のメッセージを使用したユーザーのターゲティングを促進する SDK です。これには、以降のターゲティング用にユーザー グループを作成できるアナリティクス SDK、広告配信 SDK、広告の不正使用防止 SDK と不正行為防止 SDK、エンゲージメント SDK、アトリビューション SDK などが含まれますが、これらに限定されません。

  2. どのような SDK でも SDK ランタイムで実行できますか?

    当初の対象は広告関連の SDK ですが、広告関連以外の SDK でプライバシーを重視し、上述の要件で運用できるとお考えのデベロッパーは、SDK ランタイムでの SDK の運用についてフィードバックをお送りください。ただし、SDK ランタイムはすべての SDK 設計と互換性を持つように設計されているわけではありません。記載されている制限以外にも、SDK ランタイムは、ホスティング アプリとのリアルタイムまたは高スループットの通信を必要とする SDK には適さない可能性があります。

  3. プロセスを Java ベースのランタイム内で分離するのではなく、プロセスを分離することを選んだのはなぜですか。

    現時点では、Android ユーザーに提供しようとしているプライバシーの確保に必要なセキュリティ境界を、Java ベースのランタイムによって提供することは容易ではありません。実装するには数年にわたる取り組みが必要となり、成功する保証もありません。そのため、プライバシー サンドボックスでは、実績があり、理解の進んでいる技術であるプロセス境界を使用しています。

  4. SDK を SDK ランタイム プロセスに移行すると、ダウンロード サイズやディスク容量を節約できますか?

    複数のアプリを同じバージョンのランタイム対応 SDK と統合すると、ダウンロード サイズとディスク容量を節約できます。

  5. アプリがバックグラウンドに移動したときなど、SDK ランタイムで SDK がアクセスできるアプリ ライフサイクル イベントにはどのようなものがありますか?

    Google は、クライアント アプリのアプリレベルのライフサイクル イベント(アプリがバックグラウンドに移行する、アプリがフォアグラウンドに移行するなど)について SDK ランタイムに通知するための設計サポートに積極的に取り組んでいます。設計とサンプルコードは、今後のデベロッパー プレビューで共有されます。