워치독은 `/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. 공급업체는 지원되는 두 가지 앱 카테고리인 지도 및 미디어 앱 중 하나에 패키지(서드 파티 패키지 포함)를 매핑할 수 있습니다. 이 매핑은 지도 및 미디어 앱에 더 높은 디스크 I/O 초과 사용 임곗값을 제공하기 위해 진행됩니다. 이러한 앱이 다른 앱 유형보다 더 많은 데이터를 다운로드하고 디스크에 쓰는 경향이 있기 때문입니다.Component level thresholds. 모든 공급업체 패키지의 일반 임곗값을 정의합니다(즉,Package specific thresholds또는Application category specific thresholds에 적용되지 않는 패키지가 이러한 임곗값을 가져옴). 디스크 I/O 초과 사용 구성을 정의할 때 공급업체는 구성요소 수준 임곗값을 0이 아닌 값으로 정의해야 합니다.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 초과 사용 임곗값은 서드 파티 앱의 기본 임곗값입니다. 이러한 임곗값은 시스템 이미지와 함께 제공됩니다.
- 앱 포그라운드 모드에서 3GiB 쓰기
- 앱 백그라운드 모드에서 2GiB 쓰기
- 시스템 차고 모드에서 4GiB 쓰기
- 이 수치는 기본 임곗값입니다. 디스크 I/O 사용량을 더 잘 이해하게 되면 이러한 임곗값은 업데이트됩니다.
초과 사용 구성 XML 형식
기본 공급업체 구성은 빌드 이미지의 /vendor/etc/automotive/watchdog/resource_overuse_configuration.xml 위치에 배치할 수 있습니다(선택사항). 이 구성이 지정되지 않으면 시스템 정의 구성이 공급업체 앱과 서비스에도 적용됩니다.
XML 파일에는 구성 필드당 하나의 태그만 포함되어야 합니다. XML 파일에 I/O 초과 사용 구성을 정의해야 합니다. 모든 임곗값은 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를 폴링할 수 있습니다.
리소스 초과 사용 알림 수신 대기
앱은 디스크 I/O 초과 사용 임곗값의 80% 또는 100%를 초과할 경우 앱별 알림을 수신하기 위해 리소스 초과 사용 리스너를 구현하고 CarWatchdogManager와 함께 리스너를 등록할 수 있습니다. 앱은 이러한 알림을 사용하여 다음 작업을 할 수 있습니다.
- 오프라인 분석을 위해 디스크 I/O 초과 사용 통계를 기록합니다. 앱 개발자는 이 로깅을 사용하여 디스크 I/O 초과 사용 문제를 디버그할 수 있습니다.
- 초과 사용 카운터가 초기화될 때까지 디스크 I/O 쓰기를 줄입니다.
자바 클라이언트
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.bpcc_binary { name: "sample_native_client", srcs: [ "src/*.cpp" ], shared_libs: [ "carwatchdog_aidl_interface-ndk_platform", "libbinder_ndk", ], vendor: true, } - 공급업체 서비스 도메인에 바인더(
binder_user매크로)를 사용하도록 허용하고 공급업체 서비스 도메인을carwatchdog클라이언트 도메인((carwatchdog_client_domain macro)매크로)에 추가하려면 SELinux 정책을 추가합니다.sample_client.te및file_contexts의 경우 아래 코드를 참고하세요.sample_client.tetype 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.hclass 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.cppndk::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.cppint 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.cppvoid 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); }
리소스 초과 사용 통계 폴링
앱은 최근 30일의 앱별 I/O 초과 사용 통계 ATS를 가져오기 위해 CarWatchdogManager를 폴링할 수 있습니다.
Java 클라이언트
CarWatchdogManager.getResourceOveruseStats를 사용하여 리소스 초과 사용 통계를 가져옵니다. CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO 플래그를 전달하여 디스크 I/O 초과 사용 통계를 가져옵니다.
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를 사용하여 리소스 초과 사용 통계를 가져옵니다. ResourceType.IO enum을 전달하여 디스크 I/O 초과 사용 통계를 가져옵니다.
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 설정이 있습니다(아래 이미지 참고). 이는 사용자가 시스템 성능 및 장기 하드웨어 성능보다 앱 성능을 우선시할 수 있는 설정입니다.
이 설정은 리소스 초과 사용 시 안전하게 종료되는 앱에만 사용할 수 있습니다. 그 외의 경우에는 이 설정은 비활성화됩니다. 앱에서 이 설정이 사용 중지(기본 설정)되면 앱은 리소스 초과 사용 시 종료될 수 있습니다. 그 외의 경우에는 앱이 리소스 초과 사용 시 종료되지 않습니다.

사용자가 이 설정을 켜면 다음 확인 대화상자에 설정을 켜면 어떻게 되는지 설명이 표시됩니다.

90일이 지나면 이 설정은 기본값으로 자동 재설정됩니다. 날짜 제한은 watchdogUserPackageSettingsResetDays를 사용하여 RRO 오버레이 앱으로 수정할 수 있으며 최대 180일까지입니다. 자세한 내용은 런타임 시 앱 리소스 값 변경을 참고하세요. 다음 오버레이 태그 예는 AndroidManifest.xml에 포함될 수 있습니다.
<overlay android:priority="<insert-value>"
android:targetPackage="com.android.car.updatable"
android:targetName="CarServiceCustomization"
android:resourcesMap="@xml/overlays" />
res/values/config.xml에서:
<resources> <integer name="watchdogUserPackageSettingsResetDays">value</integer> </resources>
res/xml/overlays.xml에서:
<overlay> <item target="integer/watchdogUserPackageSettingsResetDays" value="@integer/watchdogUserPackageSettingsResetDays" /> </overlay>
사용자 알림
앱 또는 서비스가 특정 기간 내에 디스크 I/O를 반복적으로 초과 사용(예: 정의된 임곗값을 초과할 정도로 데이터를 디스크에 씀)하고 리소스 초과 사용 시 안전하게 종료된 경우 사용자에게 차량이 운전자 주의 분산 행동 허용 상태로 전환되었음을 알립니다.
운전 중에 첫 번째 사용자 알림은 운전자 알림으로 게시되고 그 외 다른 알림은 알림 센터에 게시됩니다.
예를 들어 앱이 디스크 I/O를 반복적으로 초과 사용할 경우 사용자는 다음과 같은 알림을 받습니다.
- 사용자가 앱 우선순위 지정 버튼을 클릭하면 앱의 설정 페이지가 실행됩니다. 여기에서 사용자는 앱 성능 우선순위 지정 설정을 켜거나 끌 수 있습니다.
- 사용자가 앱 사용 중지 버튼을 클릭하면 사용자가 앱을 실행하거나 앱의 설정 페이지에서 앱을 사용 설정할 때까지 앱이 사용 중지됩니다.
- 제거 가능한 앱의 경우 앱 사용 중지 버튼은 앱 제거 버튼으로 대체됩니다. 사용자가 앱 제거 버튼을 클릭하면 앱의 설정 페이지가 실행되고 사용자는 그 페이지에서 앱을 제거할 수 있습니다.


런처 구현 권장사항
리소스 초과 사용으로 인해 앱이 사용 중지되면 앱은 기본 런처 앱에 표시되지 않습니다. CarService가 앱의 enabled 상태를 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED로 업데이트하기 때문입니다.
OEM은 내장된 런처 구현을 업데이트하여 이러한 앱을 이례적인 것으로 표시해야 합니다. 그래야 사용자가 필요할 때 이러한 앱을 사용할 수 있습니다. 빌드 출시에 따라 다음 권장사항을 참고하세요.
Android SC V2 출시
- 런처 구현에서는 런처에 표시할 패키지 목록을 가져올 때
MATCH_DISABLED_UNTIL_USED_COMPONENTS플래그를 사용해야 합니다. - 사용자가
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED상태에 있는 앱을 클릭할 경우 런처 앱은 enabled 상태를 다음과 같이 설정하여 앱을 사용 설정해야 합니다.