ウォッチドッグはフラッシュ メモリの使用状況をモニタリングします。モニタリングでは、ロケーション `/proc/uid_io/stats` でカーネルによって公開された UID ごとのディスク I/O 統計情報を使用して、すべてのアプリとサービスによって行われたディスク I/O 書き込みの合計数を追跡します。アプリまたはサービスがディスク I/O の過剰使用のしきい値を超えると、ウォッチドッグはアプリまたはサービスにアクションを実行します。ディスク I/O の過剰使用のしきい値と超過使用に対するアクションは、ディスク I/O の過剰使用構成で事前定義されています。
過剰使用のしきい値
- ディスク I/O の過剰使用のしきい値は、毎日適用されます。つまり、アプリ / サービスによって行われた書き込みはすべて、現在の UTC 暦日以降に集計され、過剰使用構成において定義されているしきい値と照合されます。
- 特定の日に車両が複数回起動されると、ウォッチドッグ モジュールはディスク I/O の使用統計情報をフラッシュ メモリに保存し、現在の UTC 暦日の開始時点からこの情報を集計します。
過剰使用アクション
アプリが定義されたディスク I/O の過剰使用のしきい値を繰り返し超過すると、ウォッチドッグは過剰使用構成で定義されているアクションを実行します。
- すべてのベンダーアプリとサービスはシステム全体の安定性にとって重要とみなされるため、ディスク I/O の過剰使用が原因で終了することはありません。ただし、過剰使用構成では、安全に終了できるベンダーアプリとサービスのリストを定義できます。
- サードパーティ アプリはすべて、安全に終了できます。
アプリまたはサービスを安全に終了できる場合、ウォッチドッグはアプリまたはサービスを無効にし、アプリケーション コンポーネントの状態が
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
に変わります。
過剰使用構成
過剰使用構成には、ディスク I/O の過剰使用のしきい値とアクションが含まれます。デフォルトの過剰使用構成は、システム イメージとベンダー イメージで定義され、ビルドとともに提供されます。ベンダーは、オプションでベンダー構成をベンダー イメージに含めることができます。ベンダー構成が指定されていない場合は、システム構成がベンダーアプリとサービスにも使用されます。
ウォッチドッグは CarWatchdogManager
を介してシステム API を公開し、ベンダーアプリまたはサービスがいつでもベンダー構成を更新できるようにします。
過剰使用構成の定義
過剰使用構成はコンポーネントのタイプ(たとえば、システム、ベンダー、サードパーティなど)で分割されます。OEM は、ベンダー コンポーネント構成のみを更新する必要があります。
ベンダー構成
ベンダー構成では、すべてのベンダーアプリとサービス、すべてのマップアプリとメディアアプリについて、ディスク I/O の過剰使用のしきい値とアクションが定義されています。この構成には、次の構成フィールドが含まれています。
Vendor package prefixes
。ベンダー パーティションにインストールされているすべてのパッケージは、ベンダー パッケージとみなされます。ベンダーは、これらのパッケージに加えて、プリインストールされているパッケージを、vendor package prefixes
構成にパッケージ プレフィックスを追加することでベンダー パッケージとして分類できます。 この構成では正規表現を受け入れません。Safe-to-terminate packages
。ベンダーは、完全なパッケージ名をsafe-to-terminate packages
構成に追加することで、安全に終了できるベンダー パッケージを指定できます。Application category mappings
。ベンダーは任意のパッケージ(サードパーティ パッケージなど)を、サポートされている 2 つのアプリカテゴリ(マップアプリとメディアアプリ)のいずれかにマッピングできます。このマッピングは、マップアプリとメディアアプリのディスク I/O の過剰使用のしきい値を高くするために行われます。これらのアプリには、他のアプリタイプよりも多くのデータをダウンロードしてディスクに書き込む傾向があるためです。Component level thresholds
。すべてのベンダー パッケージの一般的なしきい値を定義します(つまり、Package specific thresholds
またはApplication category specific thresholds
に含まれないパッケージはこれらのしきい値を取得します)。ベンダーは、ディスク I/O の過剰使用構成を定義する際に、ゼロ以外のコンポーネント レベルのしきい値を定義する必要があります。Package specific thresholds
。ベンダーは、特定のベンダー パッケージに特別なしきい値を定義できます。マッピングには完全なパッケージ名を含める必要があります。この構成で定義されたしきい値は、特定のパッケージについて他の構成で定義されたしきい値よりも優先されます。Application category specific thresholds
。ベンダーは、特定のアプリカテゴリに対して特別なしきい値を指定できます。アプリカテゴリは、サポートされているカテゴリ(マップアプリやメディアアプリ)のいずれかである必要があります。この構成で定義されているしきい値は、Application category mappings
を使用して特定のパッケージにマッピングされています。System-wide thresholds
。ベンダーはこの構成を指定することはできません。
Vendor package prefixes
、Safe-to-terminate packages
、Component level thresholds
、Package specific
thresholds
構成ファイルは、ベンダーのアプリとサービスのベンダー構成によってのみ更新できます。Application category specific
thresholds
構成は、すべてのマップアプリとメディアアプリのベンダー構成によってのみ更新できます。
過剰使用のしきい値には、次のモードで書き込みが許可されるバイト数が含まれます。
- アプリ / サービスのフォアグラウンド モードとバックグラウンド モード
- システム ガレージ モード
この分類により、ユーザー向けのフォアグラウンド アプリ / サービスは、バックグラウンド アプリ / サービスよりも多くのデータを書き込むことができます。ガレージモードでは、アプリとサービスはアップデートをダウンロードする傾向があるため、それぞれに他のモードで実行されているアプリとサービスよりも高いしきい値が必要です。
システム構成とサードパーティ構成
OEM は、システム構成とサードパーティ構成を更新できません。
- システム構成では、システムアプリとサービスの I/O の過剰使用しきい値とアクションを定義します。
- この構成でも
Application category mappings
が更新される場合があります。したがって、この構成フィールドはシステム構成とベンダー構成の間で共有されます。
- この構成でも
- サードパーティ構成では、すべてのサードパーティ アプリのしきい値が定義されます。システムにプリインストールされていないアプリはすべて、サードパーティ アプリです。
- すべてのサードパーティ アプリは同じしきい値を受け取ります(たとえば、サードパーティ アプリが特別なしきい値を受け取ることはありません)。ただし、マップアプリとメディアアプリの場合、しきい値はベンダー構成によって定義されます。
- 次のディスク I/O の過剰使用のしきい値は、サードパーティ アプリのデフォルトのしきい値です。これらのしきい値はシステム イメージとともに提供されます。
- アプリのフォアグラウンド モードでの 3 GiB の書き込み。
- アプリのバックグラウンド モードでの 2 GiB の書き込み。
- システム ガレージモードでの 4 GiB の書き込み。
- 前述のしきい値は基本しきい値です。これらのしきい値は、ディスク I/O の使用状況の理解が進むにつれて更新される予定です。
過剰使用構成の XML 形式
デフォルトのベンダー構成は、ビルドイメージのロケーション /vendor/etc/automotive/watchdog/resource_overuse_configuration.xml
に配置できます(省略可)。この構成が指定されていない場合、システム定義の構成はベンダーアプリとサービスにも適用されます。
XML ファイルには、構成フィールドごとに 1 つのタグのみを含める必要があります。I/O の過剰使用構成は、XML ファイルで定義する必要があります。すべてのしきい値は MiB 単位で指定する必要があります。
XML 構成の例を以下に示します。
<resourceOveruseConfiguration version="1.0"> <componentType> VENDOR </componentType> <!-- List of safe to kill vendor packages. --> <safeToKillPackages> <package> com.vendor.package.A </package> <package> com.vendor.package.B </package> </safeToKillPackages> <!-- List of vendor package prefixes. --> <vendorPackagePrefixes> <packagePrefix> com.vendor.package </packagePrefix> </vendorPackagePrefixes> <!-- List of unique package names to app category mappings. --> <packagesToAppCategoryTypes> <packageAppCategory type="MEDIA"> com.vendor.package.A </packageAppCategory> <packageAppCategory type="MAPS"> com.google.package.B </packageAppCategory> <packageAppCategory type="MEDIA"> com.third.party.package.C </packageAppCategory> </packagesToAppCategoryTypes> <ioOveruseConfiguration> <!-- Thresholds in MiB for all vendor packages that don't have package specific thresholds. --> <componentLevelThresholds> <state id="foreground_mode"> 1024 </state> <state id="background_mode"> 512 </state> <state id="garage_mode"> 3072 </state> </componentLevelThresholds> <packageSpecificThresholds> <!-- IDs must be unique --> <perStateThreshold id="com.vendor.package.C"> <state id="foreground_mode"> 400 </state> <state id="background_mode"> 100 </state> <state id="garage_mode"> 200 </state> </perStateThreshold> <perStateThreshold id="com.vendor.package.D"> <state id="foreground_mode"> 1024 </state> <state id="background_mode"> 500 </state> <state id="garage_mode"> 2048 </state> </perStateThreshold> </packageSpecificThresholds> <!-- Application category specific thresholds. --> <appCategorySpecificThresholds> <!-- One entry per supported application category --> <perStateThreshold id="MEDIA"> <state id="foreground_mode"> 600 </state> <state id="background_mode"> 700 </state> <state id="garage_mode"> 1024 </state> </perStateThreshold> <perStateThreshold id="MAPS"> <state id="foreground_mode"> 800 </state> <state id="background_mode"> 900 </state> <state id="garage_mode"> 2048 </state> </perStateThreshold> </appCategorySpecificThresholds> </ioOveruseConfiguration> </resourceOveruseConfiguration>
CarWatchdogManager システム API による過剰使用構成の更新
上記の XML 構成は、ビルドイメージでのみ指定できます。ビルドのリリース後に OEM がデバイス構成を更新する場合は、次の API を使用してデバイス上の構成に変更を加えることができます。
- 呼び出し元に
Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG
権限を付与します。 - 新しい構成の更新と設定には、既存の構成を使用する必要があります。既存の構成を取得するには API
CarWatchdogManager.getResourceOveruseConfigurations
を使用します。既存の構成を使用しない場合は、すべての構成(システム構成とサードパーティ構成を含む)が上書きされますが、この方法はおすすめできません。 - 差分変更で既存の構成を更新し、新しい構成を設定します。システム コンポーネントとサードパーティ コンポーネントの構成は更新しないでください。
- 新しい構成を設定するには API
CarWatchdogManager.setResourceOveruseConfigurations
を使用します。 - ディスク I/O の過剰使用構成を取得して設定するには、
CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO
フラグを使用します。
リソースの過剰使用構成を更新する実装例を以下に示します。
void updateResourceOveruseConfigurations() { CarWatchdogManager manager = (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE); List<ResourceOveruseConfiguration> resourceOveruseConfigurations = manager.getResourceOveruseConfigurations( CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO); List<ResourceOveruseConfiguration> newResourceOveruseConfigurations = new List<>(); ResourceOveruseConfiguration vendorConfiguration; for(ResourceOveruseConfiguration config : resourceOveruseConfigurations) { // Do not update the configurations of the system and third-party component types. if (config.getComponentType() != ResourceOveruseConfiguration.COMPONENT_TYPE_VENDOR) { newResourceOveruseConfigurations.add(config); continue; } vendorConfiguration = config; } if (vendorConfiguration == null) { ResourceOveruseConfiguration.Builder vendorConfigBuilder = new ResourceOveruseConfiguration.Builder(); initializeConfig(vendorConfigBuilder); newResourceOveruseConfigurations.add(vendorConfigBuilder.build()); } else { ResourceOveruseConfiguration newVendorConfig = updateConfig(vendorConfiguration); newResourceOveruseConfigurations.add(newVendorConfig); } int result = manager.setResourceOveruseConfigurations( newResourceOveruseConfigurations, if (result != CarWatchdogManager.RETURN_CODE_SUCCESS) { // Failed to set the resource overuse configurations. } } /** Sets the delta between the old configuration and the new configuration. */ ResourceOveruseConfiguration updateConfig( ResourceOveruseConfiguration oldConfiguration) { // Replace com.vendor.package.A with com.vendor.package.B in the safe-to-kill list. List<String> safeToKillPackages = oldConfiguration.getSafeToKillPackages(); safeToKillPackages.remove("com.vendor.package.A"); safeToKillPackages.add("com.vendor.package.B"); ResourceOveruseConfiguration.Builder configBuilder = new ResourceOveruseConfiguration.Builder( oldConfiguration.getComponentType(), safeToKillPackages, oldConfiguration.getVendorPackagePrefixes(), oldConfiguration.getPackagesToAppCategoryTypes()); configBuilder.addVendorPackagePrefixes("com.vendor."); configBuilder.addPackagesToAppCategoryTypes("com.vendor.package.B", ResourceOveruseConfiguration.APPLICATION_CATEGORY_TYPE_MAPS); IoOveruseConfiguration oldIoConfiguration = oldConfiguration.getIoOveruseConfiguration(); IoOveruseConfiguration.Builder ioConfigBuilder = new IoOveruseConfiguration.Builder( oldIoConfiguration.getComponentLevelThresholds(), oldIoConfiguration.getPackageSpecificThresholds(), oldIoConfiguration.getAppCategorySpecificThresholds(), oldIoConfiguration.getSystemWideThresholds()); // Define the amount of bytes based on the flash memory specification, expected lifetime, // and estimated average amount of bytes written by a package during different modes. ioConfigBuilder.addPackageSpecificThresholds("com.vendor.package.B", new PerStateBytes(/* foregroundModeBytes= */ 2 * 1024 * 1024 * 1024, /* backgroundModeBytes= */ 500 * 1024 * 1024, /* garageModeBytes= */ 3 * 1024 * 1024 * 1024)); return configBuilder.setIoOveruseConfiguration(ioConfigBuilder.build()).build(); }
アプリでのリソース過剰使用のモニタリング
ベンダーアプリとサードパーティ アプリは、ウォッチドッグからのアプリ固有のリソース過剰使用通知をリッスンできます。また、過去 30 日間のアプリ固有のリソース過剰使用統計情報について CarWatchdogManager
をポーリングすることもできます。
リソース過剰使用通知のリッスン
アプリは、リソース過剰使用リスナーを実装でき、リスナーを CarWatchdogManager
に登録して、ディスク I/O の過剰使用しきい値の 80% または 100% を超えたときにアプリ固有の通知を受け取れます。アプリはこれらの通知を使用して次のことを行えます。
- オフライン分析のためにディスク I/O の過剰使用統計情報をログに記録する。アプリケーション デベロッパーは、このログを使用してディスク I/O の過剰使用をデバッグできます。
- 過剰使用カウンタがリセットされるまで、ディスク I/O 書き込みを減らします。
Java クライアント
CarWatchdogManager.ResourceOveruseListener
を継承してリスナーを実装します。class ResourceOveruseListenerImpl implements CarWatchdogManager.ResourceOveruseListener { @Override public void onOveruse( @NonNull ResourceOveruseStats resourceOveruseStats) { // 1. Log/Upload resource overuse metrics. // 2. Reduce writes until the counters reset. IoOveruseStats ioOveruseStats = resourceOveruseStats.getIoOveruseStats(); // Stats period - [ioOveruseStats.getStartTime(), ioOveruseStats.getStartTime() // + ioOveruseStats.getDurationInSeconds()] // Total I/O overuses - ioOveruseStats.getTotalOveruses() // Total bytes written - ioOveruseStats.getTotalBytesWritten() // Remaining write bytes for the current UTC calendar day - // ioOveruseStats.getRemainingWriteBytes() } } }
CarWatchdogManager.addResourceOveruseListener
を呼び出してリスナー インスタンスを登録します。private void addResourceOveruseListener() { CarWatchdogManager manager = (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE); // Choose a proper executor to handle resource overuse notifications. Executor executor = mContext.getMainExecutor(); manager.addResourceOveruseListener( executor, CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, mListenerImpl); }
- アプリのリッスンが完了したら、リスナー インスタンスの登録を解除します。
private void removeResourceOveruseListener() { CarWatchdogManager manager = (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE); mCarWatchdogManager.removeResourceOveruseListener( mListenerImpl); }
ネイティブ クライアント
- ビルドルールの
shared_libs
依存関係にcarwatchdog_aidl_interface-ndk_platform
を含めます。Android.bp
cc_binary { name: "sample_native_client", srcs: [ "src/*.cpp" ], shared_libs: [ "carwatchdog_aidl_interface-ndk_platform", "libbinder_ndk", ], vendor: true, }
- SELinux ポリシーを追加して、ベンダー サービス ドメインでバインダー(
binder_user
マクロ)を使用できるようにし、ベンダー サービス ドメインをcarwatchdog
クライアント ドメイン(carwatchdog_client_domain macro)
に追加します。sample_client.te
とfile_contexts
については、以下のコードを参照してください。sample_client.te
type sample_client, domain; type sample_client_exec, exec_type, file_type, vendor_file_type; carwatchdog_client_domain(sample_client) init_daemon_domain(sample_client) binder_use(sample_client)
file_contexts
/vendor/bin/sample_native_client u:object_r:sample_client_exec:s0
BnResourceOveruseListener
を継承して、リソースの過剰使用リスナーを実装します。BnResourceOveruseListener::onOveruse
をオーバーライドして、リソースの過剰使用通知を処理します。ResourceOveruseListenerImpl.h
class ResourceOveruseListenerImpl : public BnResourceOveruseListener { public: ndk::ScopedAStatus onOveruse( ResourceOveruseStats resourceOveruseStats) override; private: void initialize(); void terminate(); std::shared_ptr<ICarWatchdog> mWatchdogServer; std::shared_ptr<IResourceOveruseListener> mListener; }
ResourceOveruseListenerImpl.cpp
ndk::ScopedAStatus ResourceOveruseListenerImpl::onOveruse( ResourceOveruseStats resourceOveruseStats) { // 1. Log/Upload resource overuse metrics. // 2. Reduce writes until the counters reset. if (stats.getTag() != ResourceOveruseStats::ioOveruseStats) { // Received resourceOveruseStats doesn't contain I/O overuse stats. } const IoOveruseStats& ioOveruseStats = stats.get(); // Stats period - [ioOveruseStats.startTime, // ioOveruseStats.startTime + ioOveruseStats.durationInSeconds] // Total I/O overuses - ioOveruseStats.totalOveruses // Total bytes written - ioOveruseStats.writtenBytes // Remaining write bytes for the current UTC calendar day - // ioOveruseStats.remainingWriteBytes return ndk::ScopedAStatus::ok(); }
- バインダー スレッドプールを開始し、リソースの過剰使用リスナーをウォッチドッグ サーバーに登録します。ウォッチドッグ サーバーは、サービス名
android.automotive.watchdog.ICarWatchdog/default
で登録されます。main.cpp
int main(int argc, char** argv) { ABinderProcess_setThreadPoolMaxThreadCount(1); ABinderProcess_startThreadPool(); std::shared_ptr<ResourceOveruseListenerImpl> listener = ndk::SharedRefBase::make<ResourceOveruseListenerImpl>(); // The listener is added in initialize(). listener->initialize(); ... Run service ... // The listener is removed in terminate(). listener->terminate(); }
ResourceOveruseListenerImpl.cpp
void ResourceOveruseListener::initialize() { ndk::SpAIBinder binder(AServiceManager_getService( "android.automotive.watchdog.ICarWatchdog/default")); std::shared_ptr<ICarWatchdog> server = ICarWatchdog::fromBinder(binder); mWatchdogServer = server; std::shared_ptr<IResourceOveruseListener> listener = IResourceOveruseListener::fromBinder(this->asBinder()); mWatchdogServer->addResourceOveruseListener( std::vector<int>{ResourceType.IO}, listener); mListener = listener; } void ResourceOveruseListener::terminate() { mWatchdogServer->removeResourceOveruseListener(mListener); }
ポーリング リソースの過剰使用統計情報
アプリは、CarWatchdogManager をポーリングして、直近 30 日間のアプリ固有の I/O 過剰使用統計情報 ATS を取得できます。
Java クライアント
リソースの過剰使用の統計情報を取得するには CarWatchdogManager.getResourceOveruseStats
を使用します。ディスク I/O の過剰使用統計情報を取得するには、CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO
フラグを渡します。
private void getResourceOveruseStats() { CarWatchdogManager manager = (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE); // Returns resource overuse stats with I/O overuse stats for the past // 7 days. Stats are available for up to the past 30 days. ResourceOveruseStats resourceOveruseStats = mCarWatchdogManager.getResourceOveruseStats( CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, CarWatchdogManager.STATS_PERIOD_PAST_7_DAYS); IoOveruseStats ioOveruseStats = resourceOveruseStats.getIoOveruseStats(); // Stats period - [ioOveruseStats.getStartTime(), ioOveruseStats.getStartTime() // + ioOveruseStats.getDurationInSeconds()] // Total I/O overuses - ioOveruseStats.getTotalOveruses() // Total bytes written - ioOveruseStats.getTotalBytesWritten() // Remaining write bytes for the UTC calendar day - // ioOveruseStats.getRemainingWriteBytes() }
ネイティブ クライアント
リソースの過剰使用の統計情報を取得するには CarWatchdogServer.getResourceOveruseStats
を使用します。ディスク I/O の過剰使用統計情報を取得するには、ResourceType.IO
列挙型を渡します。
void getResourceOveruseStats() { ndk::SpAIBinder binder(AServiceManager_getService( "android.automotive.watchdog.ICarWatchdog/default")); std::shared_ptr<ICarWatchdog> server = ICarWatchdog::fromBinder(binder); // Returns the stats only for the current UTC calendar day. const std::vector<ResourceOveruseStats> resourceOveruseStats; ndk::ScopedAStatus status = server.getResourceOveruseStats( std::vector<int>{ResourceType.IO}, &resourceOveruseStats); if (!status.isOk()) { // Failed to get the resource overuse stats. return; } for (const auto& stats : resourceOveruseStats) { if (stats.getTag() != ResourceOveruseStats::ioOveruseStats) { continue; } const IoOveruseStats& ioOveruseStats = stats.get(); // Stats period - [ioOveruseStats.startTime, // ioOveruseStats.startTime + ioOveruseStats.durationInSeconds] // Total I/O overuses - ioOveruseStats.totalOveruses // Total bytes written - ioOveruseStats.writtenBytes // Remaining write bytes for the current UTC calendar day - // ioOveruseStats.remainingWriteBytes } }
リソース過剰使用の UX
アプリのパフォーマンス設定を優先する
アプリの設定ページには Prioritize app performance
設定(下の画像を参照)があり、ユーザーはシステムのパフォーマンスやハードウェアの長期的なパフォーマンスよりもアプリのパフォーマンスを優先できます。
この設定は、リソースの過剰使用時に安全に終了できるアプリでのみ使用できます。それ以外の場合、この設定はグレー表示されます。アプリのこの設定をオフに切り替えると(デフォルト設定)、リソースの過剰使用時にアプリが終了する可能性があります。それ以外の場合、リソース過剰使用でアプリは終了しません。
ユーザーがこの設定をオンに切り替えると、次の確認ダイアログで、設定を切り替えた場合の影響に関する説明が表示されます。
ユーザー通知
アプリまたはサービスが特定の期間内にディスク I/O を繰り返し使用し(たとえば、定義済みのしきい値を超えてディスクにデータを書き込む)、リソースの過剰使用時に安全に終了できる場合、車両が allow-driver-distraction 状態になった後にユーザーに通知が送られます。
最初のユーザー通知(運転中)はヘッドアップ通知として送信され、その他の通知は通知センターに送信されます。
たとえば、アプリがディスク I/O を繰り返し使いすぎると、ユーザーは次の通知を受け取ります。
- ユーザーが [アプリを優先] ボタンをクリックすると、アプリの設定ページが表示され、[アプリのパフォーマンスを優先する] の設定をオンまたはオフにできます。
- ユーザーが [アプリを無効にする] ボタンをクリックすると、ユーザーがアプリを起動するか、アプリの設定ページで有効にするまで、アプリは無効になります。
- アンインストールできないアプリの場合、[アプリを無効にする] ボタンが [アプリをアンインストールする] ボタンに置き換えられます。ユーザーが [アプリをアンインストール] ボタンをクリックすると、アプリの [設定] ページが開きます。ここで、ユーザーはアプリをアンインストールできます。
ランチャー実装の推奨事項
リソース過剰使用によりアプリケーションが無効になると、CarService はアプリの有効状態を PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
として更新するので、アプリはデフォルトのランチャー アプリに表示されなくなります。OEM は、組み込みランチャーの実装を更新して、通常とは異なる方法でこれらのアプリを表示する必要があります。これにより、ユーザーは必要に応じてアプリを利用できるようになります。ビルドリリースに基づく次の推奨事項をご覧ください。
Android SC V2 リリース
- ランチャーの実装では、ランチャーに表示するパッケージのリストを取得する際に
MATCH_DISABLED_UNTIL_USED_COMPONENTS
フラグを使用する必要があります。 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
状態にあるアプリをユーザーがクリックしたとき、ランチャー アプリは、有効化状態を次のように設定して、アプリを有効にする必要があります。