워치독은 `/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.bp
cc_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.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); }
리소스 초과 사용 초과 폴링
애플리케이션은 최근 30일의 앱별 I/O 초과 사용 통계 ATS를 가져오기 위해 CarWatchdogManager를 폴링할 수 있습니다.
자바 클라이언트
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
설정이 있습니다(아래 이미지 참고). 이는 사용자가 시스템 성능 및 장기 하드웨어 성능보다 애플리케이션 성능을 우선시할 수 있는 설정입니다.
이 설정은 리소스 초과 사용 시 안전하게 종료되는 애플리케이션에만 사용할 수 있습니다. 그 외의 경우에는 이 설정은 비활성화됩니다. 애플리케이션에 이 설정이 사용 중지(기본 설정)되면 애플리케이션은 리소스 초과 사용 시 종료될 수 있습니다. 그 외의 경우에는 애플리케이션은 리소스 초과 사용 시 종료되지 않습니다.
사용자가 이 설정을 켜면 다음 확인 대화상자에 설정을 켜면 어떻게 되는지에 관한 설명이 표시됩니다.
사용자 알림
애플리케이션 또는 서비스가 특정 기간 내에 디스크 I/O를 반복적으로 초과 사용(예: 정의된 임곗값을 초과할 정도로 데이터를 디스크에 씀)하고 리소스 초과 사용 시 안전하게 종료된 경우 사용자에게 차량이 운전자 주의 분산 행동 허용 상태로 전환되었음을 알립니다.
운전 중에 첫 번째 사용자 알림은 운전자 알림으로 게시되고 그 외 다른 알림은 알림 센터에 게시됩니다.
예를 들어 앱이 디스크 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
상태에 있는 애플리케이션을 클릭할 경우 런처 앱은 사용 설정된 상태를 다음과 같이 설정하여 애플리케이션을 사용 설정해야 합니다.