ランタイム リソース オーバーレイ(RRO)は、実行時にターゲット パッケージのリソース値を変更するパッケージです。たとえば、システム イメージにインストールされているアプリの動作が、リソースの値に基づいて変わる場合があります。そのような場合、ビルド時にリソース値をハードコードするのではなく、別のパーティションにインストールした RRO によって、実行時にアプリのリソースの値を変更できます。
RRO は有効または無効にできます。有効 / 無効状態をプログラムで設定し、RRO によるリソース値の変更機能を切り替えることができます。RRO はデフォルトでは無効になっています(ただし、静的 RRO はデフォルトで有効になっています)。
リソースをオーバーレイする
オーバーレイは、オーバーレイ パッケージで定義されたリソースを、ターゲット パッケージで定義されたリソースにマッピングすることで機能します。アプリがターゲット パッケージ内のリソースの値を解決しようとすると、代わりに、ターゲット リソースのマッピング先であるオーバーレイ リソースの値が返されます。
マニフェストをセットアップする
<manifest> タグの子として <overlay> タグを含むパッケージは、RRO パッケージと見なされます。
必須の
android:targetPackage属性の値は、RRO によってオーバーレイするパッケージの名前を指定します。オプションの
android:targetName属性の値は、RRO によってオーバーレイするターゲット パッケージのオーバーレイ可能なリソース サブセットの名前を指定します。ターゲットでオーバーレイ可能なリソースセットが定義されていない場合、この属性は存在しません。
次のコードは、オーバーレイ AndroidManifest.xml の例を示しています。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.overlay">
<application android:hasCode="false" />
<overlay android:targetPackage="com.example.target"
android:targetName="OverlayableResources"/>
</manifest>
オーバーレイは、コードをオーバーレイできないため、DEX ファイルを含めることはできません。また、マニフェストの <application> タグの android:hasCode 属性を false に設定する必要があります。
リソースマップを定義する
Android 11 以上でオーバーレイ リソースのマップを定義するには、次のようなメカニズムが推奨されます。オーバーレイ パッケージの res/xml ディレクトリにファイルを作成し、オーバーレイするターゲット リソースとその置換値を列挙した後、<overlay> マニフェスト タグの android:resourcesMap 属性の値をリソース マッピング ファイルへの参照に設定するという方法です。
次のコードは、res/xml/overlays.xml ファイルの例を示しています。
<?xml version="1.0" encoding="utf-8"?>
<overlay xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- Overlays string/config1 and string/config2 with the same resource. -->
<item target="string/config1" value="@string/overlay1" />
<item target="string/config2" value="@string/overlay1" />
<!-- Overlays string/config3 with the string "yes". -->
<item target="string/config3" value="@android:string/yes" />
<!-- Overlays string/config4 with the string "Hardcoded string". -->
<item target="string/config4" value="Hardcoded string" />
<!-- Overlays integer/config5 with the integer "42". -->
<item target="integer/config5" value="42" />
</overlay>
次のコードは、オーバーレイ マニフェストの例を示しています。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.overlay">
<application android:hasCode="false" />
<overlay android:targetPackage="com.example.target"
android:targetName="OverlayableResources"
android:resourcesMap="@xml/overlays"/>
</manifest>
パッケージをビルドする
Android 11 以上は、オーバーレイに対して Soong ビルドルールをサポートしています。このルールによって、Android Asset Packaging Tool 2(AAPT2)が、同じ値を持つリソースの設定の重複排除を試みたり(--no-resource-deduping)、デフォルト設定のないリソースを削除したりすること(--no-resource-removal)を防止できます。次のコードは、Android.bp ファイルの例を示しています。
runtime_resource_overlay {
name: "ExampleOverlay",
sdk_version: "current",
}
リソースを解決する
ターゲット リソースまたはオーバーレイ リソースでクエリ対象のリソースに関する設定が複数定義されている場合、リソース ランタイムは、デバイス設定に最も一致する設定の値を返します。最も一致する設定を判断するには、オーバーレイ リソース設定のセットをターゲット リソース設定のセットに統合した後、通常のリソース解決フローが実施されます(詳細については、Android が最適なリソースを見つける仕組みをご覧ください)。
たとえば、オーバーレイが drawable-en 設定の値を定義し、ターゲットが drawable-en-port の値を定義している場合、drawable-en-port のほうがより一致しているので、実行時にはターゲット設定 drawable-en-port の値が選択されます。すべての drawable-en 設定をオーバーレイするには、ターゲットが定義している各 drawable-en 設定の値をオーバーレイでも定義する必要があります。
オーバーレイは自身のリソースを参照できます。動作は、Android のリリースによって異なります。
Android 11 以上では、各オーバーレイに独自の予約済みリソース ID スペースがあり、ターゲット リソース ID スペースや他のオーバーレイ リソース ID スペースと重複することがないため、自身のリソースを参照するオーバーレイは正常に機能します。
Android 10 以下では、オーバーレイとターゲットのパッケージが同じリソース ID スペースを共有するため、
@type/name構文を使用してそれぞれが自身のリソースを参照しようとすると、競合や予期せぬ動作が生じる場合があります。
オーバーレイを有効または無効にする
オーバーレイは手動またはプログラミングで有効 / 無効にできます。
オーバーレイを手動で有効または無効にする
手動で有効にして RRO を確認するには、以下のコマンドを実行します。
adb shell cmd overlay enable --user current com.example.carrro
adb shell cmd overlay list --user current | grep -i com.example com.example.carrroこの場合、システム UI を所有するシステム ユーザー(userId = 0)の RRO が有効になります。この指示は、フォアグラウンド ユーザー(userId = 10)が開始したアプリには影響しません。フォアグラウンド ユーザーの RRO を有効にするには、パラメータ -–user 10 を使用します。
adb shell cmd overlay enable --user 10 com.example.carrroオーバーレイをプログラミングで有効または無効にする
変更可能なオーバーレイを有効または無効にするには OverlayManager API を使用します(Context#getSystemService(Context.OVERLAY_SERVICE) を使用して API インターフェースを取得します)。オーバーレイを有効にできるのは、オーバーレイがターゲットとするパッケージ、または android.permission.CHANGE_OVERLAY_PACKAGES 権限を持つパッケージのみです。オーバーレイを有効または無効にすると、設定変更イベントがターゲット パッケージに伝えられ、ターゲット アクティビティが再起動します。
オーバーレイ可能なリソースを制限する
Android 10 以上では、RRO でオーバーレイ可能なリソースのセットを <overlayable> XML タグで公開します。次の res/values/overlayable.xml ファイルの例では、string/foo と integer/bar は、デバイスの外観のテーマを設定するためのリソースです。これらのリソースをオーバーレイするには、オーバーレイ可能なリソースのコレクションに名前を付けて、オーバーレイのターゲットとして明示的に指定する必要があります。
<!-- The collection of resources for theming the appearance of the device -->
<overlayable name="ThemeResources">
<policy type="public">
<item type="string" name="foo/" />
<item type="integer" name="bar/" />
</policy>
...
</overlayable>
1 つの APK で複数の <overlayable> タグを定義できますが、各タグの名前はパッケージ内で一意である必要があります。たとえば、次のように定義します。
2 つの異なるパッケージの両方で
<overlayable name="foo">を定義することは可能です。1 つの APK で 2 つの
<overlayable name="foo">ブロックを定義することはできません。
次のコードは、AndroidManifest.xml ファイルのオーバーレイの例を示しています。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my.theme.overlay">
<application android:hasCode="false" />
<!-- This overlay will override the ThemeResources resources -->
<overlay android:targetPackage="android" android:targetName="ThemeResources">
</manifest>
アプリで <overlayable> タグを定義する場合、そのアプリをターゲットにするオーバーレイには次の特徴があります。
targetNameを指定する必要があります。<overlayable>タグ内にリストされたリソースのみをオーバーレイできます。1 つの
<overlayable>名のみをターゲットにすることができます。
パッケージ内でオーバーレイ可能なリソースが公開されていても、android:targetName を使用して特定の <overlayable> タグがターゲットに指定されていなければ、そのパッケージをターゲットとするオーバーレイは有効にできません。
制限ポリシー
オーバーレイ可能なリソースに制限を適用するには、<policy> タグを使用します。type 属性では、指定されたリソースをオーバーライドするためにオーバーレイで遵守する必要があるポリシーを指定します。サポートされているタイプは次のとおりです。
public。任意のオーバーレイでリソースをオーバーライドできます。system。システム パーティション上の任意のオーバーレイでリソースをオーバーライドできます。vendor。ベンダー パーティション上の任意のオーバーレイでリソースをオーバーライドできます。product。プロダクト パーティション上の任意のオーバーレイでリソースをオーバーライドできます。oem。oem パーティション上の任意のオーバーレイでリソースをオーバーライドできます。odm。odm パーティション上の任意のオーバーレイでリソースをオーバーライドできます。signature。ターゲット APK と同じ署名で署名された任意のオーバーレイでリソースをオーバーライドできます。actor。actor APK と同じ署名で署名された任意のオーバーレイでリソースをオーバーライドできます。actor はシステム構成の named-actor タグで宣言されます。config_signature。overlay-config APK と同じ署名で署名された任意のオーバーレイでリソースをオーバーライドできます。overlay-config はシステム構成の overlay-config-signature タグで宣言されます。
次のコードは、res/values/overlayable.xml ファイルの <policy> タグの例を示しています。
<overlayable name="ThemeResources">
<policy type="vendor" >
<item type="string" name="foo" />
</policy>
<policy type="product|signature" >
<item type="string" name="bar" />
<item type="string" name="baz" />
</policy>
</overlayable>
複数のポリシーを指定するには、区切り文字として縦棒(|)を使用します。複数のポリシーを指定した場合、<policy> タグ内にリストされたリソースをオーバーライドするために遵守する必要があるポリシーは 1 つだけです。
オーバーレイを設定する
Android は、Android のリリース バージョンに応じてオーバーレイの可変性、デフォルト状態、優先度を設定するさまざまなメカニズムをサポートしています。
Android 11 以降を搭載したデバイスでは、マニフェスト属性の代わりに
OverlayConfigファイル(config.xml)を使用できます。オーバーレイにはオーバーレイ ファイルの使用をおすすめします。すべてのデバイスで、静的 RRO の設定にマニフェスト属性(
android:isStaticとandroid:priority)を使用できます。
OverlayConfig を使用する
Android 11 以上では、OverlayConfig を使用してオーバーレイの可変性、デフォルト状態、優先度を設定できます。オーバーレイを設定するには、partition/overlay/config/config.xml でオーバーレイ ファイルを作成するか、同じ場所のオーバーレイ ファイルを変更します。この場合、partition は、設定対象オーバーレイのパーティションです。設定するには、オーバーレイが設定されているパーティションの overlay/ ディレクトリにオーバーレイが存在している必要があります。次のコードは、product/overlay/config/config.xml の例を示しています。
<config>
<merge path="OEM-common-rros-config.xml" />
<overlay package="com.oem.overlay.device" mutable="false" enabled="true" />
<overlay package="com.oem.green.theme" enabled="true" />
</config>"
<overlay> タグには、設定対象のオーバーレイ パッケージを示す package 属性が必要です。オプションの enabled 属性は、オーバーレイをデフォルトで有効にするかどうかを制御します(デフォルトは false)。オプションの mutable 属性は、オーバーレイを変更可能にするかどうか、および実行時に有効化状態をプログラムで変更できるかどうかを制御します(デフォルトは true)。構成ファイル内にリストされていないオーバーレイは変更可能であり、デフォルトで無効になっています。
オーバーレイの優先順位
複数のオーバーレイが同じリソースをオーバーライドしている場合は、オーバーレイの順序が重要になります。上位の設定を持つオーバーレイほど優先順位が低くなります。異なるパーティションにあるオーバーレイの優先順位(低いものから順に)は、次のとおりです。
systemvendorodmoemproductsystem_ext
ファイルを統合する
<merge> タグを使用すると、構成ファイル内の指定の場所に他の構成ファイルを統合できます。このタグの path 属性は、統合するファイルのパス(オーバーレイ構成ファイルが含まれるディレクトリを基準とする相対パス)を表します。
マニフェスト属性 / 静的 RRO を使用する
Android 10 以下でオーバーレイの不変性と優先順位を設定するには、以下のマニフェスト属性を使用します。
android:isStatic。このブール値属性の値がtrueに設定されている場合、オーバーレイはデフォルトで有効とされ、変更できません。これにより、オーバーレイは無効化できなくなります。android:priority。この数値属性の値(静的なオーバーレイにのみ影響します)は、複数の静的オーバーレイが同じリソース値をターゲットにしている場合のオーバーレイの優先順位を設定します。数値が大きいほど優先度が高くなります。
次のコードは、AndroidManifest.xml の例を示しています。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.overlay">
<application android:hasCode="false" />
<overlay android:targetPackage="com.example.target"
android:isStatic="true"
android:priority="5"/>
</manifest>
Android 11 の変更点
Android 11 以降では、構成ファイルが partition/overlay/config/config.xml にある場合、そのファイルを使用してオーバーレイが設定されます。android:isStatic と android:priority はパーティション内のオーバーレイに影響しません。任意のパーティションでオーバーレイ構成ファイルを定義すると、オーバーレイ パーティションの優先順位が適用されます。
さらに、Android 11 以降では、パッケージのインストール時に読み取られるリソースの値に静的オーバーレイで影響を及ぼす機能が削除されています。一般的なユースケースとしては、コンポーネントの有効化状態を設定するブール値の値を静的オーバーレイで変更する場合、<component-override> SystemConfig タグを使用します(Android 11 の新機能)。
オーバーレイをデバッグする
オーバーレイの有効化、無効化、ダンプを手動で行うには、オーバーレイ マネージャーの次のシェルコマンドを使用します。
adb shell cmd overlayユーザーを指定せずに enable を使用した場合は、システム UI を所有する現在のユーザー、つまりシステム ユーザー(userId = 0)に影響し、アプリを所有するフォアグラウンド ユーザー(userId = 10)には影響しません。フォアグラウンド ユーザーの RRO を有効にするには、パラメータ –-user 10 を使用します。
adb shell cmd overlay enable --user 10 com.example.carrroOverlayManagerService は idmap2 を使用して、ターゲット パッケージのリソース ID をオーバーレイ パッケージのリソース ID にマッピングします。生成された ID のマッピングは /data/resource-cache/ に格納されます。オーバーレイが正常に機能しない場合は、/data/resource-cache/ でオーバーレイの対応する idmap ファイルを探して、次のコマンドを実行します。
adb shell idmap2 dump --idmap-path [file]このコマンドは、次のようなリソースのマッピングを出力します。
[target res id] - > [overlay res id] [resource name]
0x01040151 -> 0x01050001 string/config_dozeComponent
0x01040152 -> 0x01050002 string/config_dozeDoubleTapSensorType
0x01040153 -> 0x01050003 string/config_dozeLongPressSensorType