このページでは、Android が同時に利用可能なネットワークから選択する方法を説明します。このネットワーク選択メカニズムは、Android がアプリやシステムのネットワーク リクエストに対応する方法に影響し、アプリによるデフォルト ネットワークの選択方法にも影響します。
ネットワーク選択の動作
ここでは、Android 12 以降を搭載したデバイスと Android 11 以前を搭載したデバイスでのネットワーク選択の動作を説明します。
Android 12
Android 12 以降を搭載したデバイスでは、Android は NetworkScore
クラスを使用して、利用可能なネットワークから選択します。このクラスには、ポリシーの決定に必要なフラグが多数含まれています。各フラグは、ネットワーク選択に重要となるネットワークの属性を意味的に表します。
ネットワーク エージェント(NetworkAgent
)では、POLICY_TRANSPORT_PRIMARY
フラグを使用して、そのネットワークが、同じトランスポートのネットワークが複数存在するときに優先するネットワークであることを指定します。この典型的な例は、ユーザーがデフォルトで使用する SIM カードを設定画面のスイッチで選択できるデュアル SIM デバイスです。Android では、特定のトランスポート内で、POLICY_TRANSPORT_PRIMARY
フラグが設定されているネットワークが、このフラグが設定されていないネットワークよりも優先されます。
ネットワーク エージェントでは、POLICY_EXITING
フラグを使用して、間もなく切断されるネットワークを識別します。この典型的な例は、ユーザーがネットワークの範囲外に出て Wi-Fi ネットワークの品質が低下する場合です。Android では、このフラグのないネットワークが利用できる場合は、このフラグのあるネットワークの使用が回避されます。各ネットワーク エージェントでは、範囲外に出たと見なせるほどネットワーク品質が低下したかどうかを判断できます。
また、NetworkScore
クラスを使用すると、ネットワーク エージェントで KEEP_CONNECTED_FOR_HANDOVER
フラグと NetworkScore.Builder.setKeepConnectedReason
メソッドを使用して、ネットワークが維持されるように宣言することができます。この KEEP_CONNECTED_FOR_HANDOVER
フラグは、選択候補のネットワークに使用できるフラグです。このフラグを使用すると、ネットワーク エージェントで、ネットワーク性能が評価されるまでの間、セカンダリ Wi-Fi STA のネットワークをプライマリ ネットワークにすることなく有効にできるようになります。ネットワーク エージェントでこのフラグが宣言されない場合、選択候補のネットワークは、ネットワークの性能が評価される前にリクエストに対応することはないため、無効にされます。
この選択では、2 つのネットワークが特定のリクエストに対応でき、ポリシーの観点からは同等である場合、現在リクエストに対応しているネットワークが優先されます。リクエストに対応しているネットワークがない場合は、どちらかが選択されます。その後は、ポリシーフラグが変更されるまで、選択されたネットワークが優先され続けます。
ネットワーク選択機能の実装は、AOSP の Connectivity モジュールにあります。ネットワーク選択のポリシー ロジックは、NetworkRanker
クラスとそのヘルパークラスにあります。つまり、デバイス メーカーはネットワーク選択のコードを直接カスタマイズすることはできず、ネットワークに関する必要な情報を伝えるために NetworkScore
のフラグを使用する必要があります。
Android 11
Android 11 以前を搭載しているデバイスの場合、Android では、ネットワーク エージェントの実装(NetworkAgent
)から送られた単純な整数に基づいてネットワーク選択が行われます。リクエストごとに、そのリクエストに対応できて、数値スコアが最大のネットワークが選択されます。この数値スコアは、ネットワーク エージェントから送信された整数と、さまざまな条件(ネットワークが検証済みかどうか、ネットワークが VPN であるかどうかなど)に基づいた追加のボーナスまたはペナルティから構成されます。個々のネットワーク エージェントは、ポリシーを決定するために互いに同期します。
あるリクエストを 2 つのネットワークが対応でき、同じ数値スコアを持つ場合の動作は未定義です。
NetworkScore クラス
ネットワーク選択機能の中心となるクラスは NetworkScore
です。このクラスには、利用可能なフラグと setKeepConnectedReason
メソッドの API とドキュメントが含まれます。
NetworkScore
クラスは、ビルダークラスを使用して構築し、初期化時に NetworkAgent
コンストラクタに渡す必要があります。ネットワーク スコアは、NetworkAgent#sendNetworkScore
メソッドを使用していつでも更新できます。
ネットワーク エージェントの実装例
AOSP には、さまざまなネットワーク エージェントの実装例が含まれています。以下の実装例があります。
DcNetworkAgent
: ネットワーク スコアを使用して、モバイル ネットワークのポリシーを伝えます。ClientModeImpl.WifiNetworkAgent
: ネットワーク スコアを使用して、Wi-Fi ネットワークのポリシーを伝えます。この実装では、POLICY_EXITING
フラグを使用したネットワーク スコアに従来の整数との下位互換性があります。
Android 12 にアップグレードするデバイス
デバイスを Android 12 にアップグレードするデバイス メーカーは、NetworkScore
クラスを使用するようにネットワーク エージェントの実装を変更する必要があります。Android 11 以前で使用されていた従来の整数は NetworkScore
に渡されますが、Android 12 ではログと非回帰的な目的にのみ使用されます。Android 12 では、デバイス メーカーは NetworkScore
のフラグを使用して望ましい変更を表明する必要があります。すると、Connectivity メインライン モジュールでは、それらのフラグを使用してネットワーク選択の決定を行います。Android 11 以前のコードを使用して、Android 12 の実装に対してビルドを行っている場合は、以前の整数を更新するメソッドが Android 12 で削除されたため、ビルドエラーが発生する可能性があります。
内部の NetworkFactory
クラスを使用するネットワーク エージェントの場合、ファクトリが作成できる最も強いネットワークのスコアを表す NetworkScore
オブジェクトでスコアフィルタを表現する必要があります。これは、Android 12 では、NetworkFactory
クラスは、Android 11 以前のすべてのリクエストではなく、NetworkFactory
に宣言されたスコアフィルタに一致するリクエストのみを渡すためです。
すべてのリクエストを NetworkFactory
に渡すことがないように、フィルタを渡して実装の簡素化とバッテリーの節約を図ることをおすすめします。ただし、カスタム実装ですべてのリクエストを NetworkFactory
に渡す場合、通常の NetworkFactory.register
メソッドの代わりに NetworkFactory.registerIgnoringScore
を登録できます。この方法を使用する場合は、対応できないリクエストをファクトリが評価しないことでバッテリーを節約するために、ファクトリが作成できる最高スコアを最も正確に表すスコアフィルタを渡すことをおすすめします。
検証
Android デバイスでネットワーク選択の動作を確認するには、次のテストを使用します。
NetworkScoreTest
CTS テストNetworkRanker
単体テスト
実装が正しくない場合、NetworkCallback
の使用に対して予期しないネットワークがアプリに返されることがあります。これには、デバイスのデフォルト ネットワークの選択も含まれます(ConnectivityManager.registerDefaultNetworkCallback
でネットワーク コールバックを使用したときにシステムからアプリに送信されるネットワーク)。
実装が正しくない場合の問題として、ネットワーク エージェントがリクエストに対する評価対象とならないスコアで有効にされ、直後に無効にされることで、深刻なバッテリーの消耗が生じることがあります。エージェントが何度も有効にされると、バッテリー使用量が大幅に増加する可能性があります。