Watchdog ตรวจสอบการใช้งานหน่วยความจำแฟลชโดยติดตามจำนวนการเขียน I/O ของดิสก์ทั้งหมดที่สร้างโดยแอปและบริการทั้งหมดโดยใช้สถิติ I/O ดิสก์ต่อ UID ที่เคอร์เนลเปิดเผยที่ตำแหน่ง `/proc/uid_io/stats` เมื่อแอพหรือบริการเกินเกณฑ์การใช้งานดิสก์ I/O มากเกินไป Watchdog จะดำเนินการกับแอพหรือบริการนั้น เกณฑ์การใช้มากเกินไปของดิสก์ I/O และการดำเนินการเพื่อดำเนินการกับการใช้มากเกินไปถูกกำหนดไว้ล่วงหน้าในการกำหนดค่าการใช้มากเกินไปของดิสก์ I/O
เกณฑ์การใช้งานมากเกินไป
- เกณฑ์การใช้ดิสก์ I/O มากเกินไปจะบังคับใช้เป็นประจำทุกวัน กล่าวคือ การเขียนทั้งหมดที่ทำโดยแอป/บริการจะถูกรวบรวมตั้งแต่เริ่มต้นวันตามปฏิทิน UTC ปัจจุบัน และตรวจสอบกับเกณฑ์ที่กำหนดไว้ในการกำหนดค่าการใช้งานมากเกินไป
- เมื่อสตาร์ทรถหลายครั้งในวันที่กำหนด โมดูล Watchdog จะจัดเก็บสถิติการใช้งานดิสก์ I/O ไว้ในหน่วยความจำแฟลช และรวมสถิติเหล่านั้นตั้งแต่เริ่มต้นวันตามปฏิทิน UTC ปัจจุบัน
การกระทำที่มากเกินไป
เมื่อแอปเกินเกณฑ์การใช้งานดิสก์ I/O มากเกินไปซ้ำแล้วซ้ำอีก Watchdog จะดำเนินการตามที่กำหนดไว้ในการกำหนดค่าการใช้งานมากเกินไป
- แอพและบริการของผู้จำหน่ายทั้งหมดถือว่ามีความสำคัญต่อความเสถียรของระบบโดยรวม ดังนั้นจึงไม่ถูกยุติเมื่อใช้ดิสก์ I/O มากเกินไป อย่างไรก็ตาม การกำหนดค่าการใช้งานมากเกินไปสามารถกำหนดรายการแอปและบริการของผู้จำหน่ายที่ยุติการใช้งานอย่างปลอดภัยได้
- แอพของบุคคลที่สามทั้งหมดนั้นปลอดภัยที่จะยุติ
เมื่อแอปหรือบริการยุติได้อย่างปลอดภัย Watchdog จะปิดใช้งานแอปหรือบริการด้วยสถานะองค์ประกอบของแอป PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
การกำหนดค่ามากเกินไป
การกำหนดค่าการใช้งานมากเกินไปประกอบด้วยขีดจำกัดและการดำเนินการของดิสก์ I/O มากเกินไป การกำหนดค่าการใช้งานมากเกินไปเริ่มต้นถูกกำหนดไว้ในอิมเมจของระบบและผู้จำหน่าย และมาพร้อมกับบิลด์ ผู้จัดจำหน่ายสามารถเลือกรวมการกำหนดค่าผู้จัดจำหน่ายในอิมเมจของผู้จัดจำหน่ายได้ เมื่อไม่ได้ระบุการกำหนดค่าของผู้จัดจำหน่าย การกำหนดค่าระบบจะถูกใช้สำหรับแอปและบริการของผู้จัดจำหน่ายด้วยเช่นกัน
Watchdog เปิดเผย API ของระบบผ่าน CarWatchdogManager
ซึ่งช่วยให้แอปหรือบริการของผู้จำหน่ายอัปเดตการกำหนดค่าของผู้จำหน่ายได้ตลอดเวลา
คำจำกัดความของการกำหนดค่ามากเกินไป
การกำหนดค่าการใช้งานมากเกินไปจะแบ่งตามประเภทส่วนประกอบ เช่น ระบบ ผู้จำหน่าย และบุคคลที่สาม 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 -
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 ควรมีแท็กเดียวเท่านั้นสำหรับแต่ละฟิลด์การกำหนดค่า ต้องกำหนดคอนฟิกูเรชันการใช้งานมากเกินไปของ 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>
อัปเดตการกำหนดค่าการใช้งานมากเกินไปผ่าน API ระบบ CarWatchdogManager
การกำหนดค่า 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(); }
แอพที่ติดตามการใช้ทรัพยากรมากเกินไป
แอพผู้จำหน่ายและบุคคลที่สามสามารถฟังการแจ้งเตือนการใช้ทรัพยากรมากเกินไปของแอพเฉพาะจาก Watchdog หรือสำรวจ CarWatchdogManager
สำหรับสถิติการใช้ทรัพยากรมากเกินไปของแอพโดยเฉพาะในช่วง 30 วันที่ผ่านมา
ฟังการแจ้งเตือนการใช้ทรัพยากรมากเกินไป
แอพสามารถใช้ Listener ที่ใช้ทรัพยากรมากเกินไป และลงทะเบียน Listener กับ CarWatchdogManager
เพื่อรับการแจ้งเตือนเฉพาะของแอพ เมื่อเกินเกณฑ์ 80% หรือ 100% ของขีดจำกัดการใช้งาน I/O ของดิสก์มากเกินไป แอปสามารถใช้การแจ้งเตือนเหล่านี้เพื่อ:
- บันทึกสถิติการใช้งานดิสก์ I/O มากเกินไปสำหรับการวิเคราะห์แบบออฟไลน์ นักพัฒนาแอปสามารถใช้การบันทึกนี้เพื่อแก้ไขปัญหาการใช้งานดิสก์ I/O มากเกินไป
- ลดการเขียน I/O ของดิสก์จนกว่าตัวนับการใช้งานมากเกินไปจะรีเซ็ต
ไคลเอนต์จาวา
- ใช้งาน Listener โดยสืบทอด
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() } } }
- ลงทะเบียนอินสแตนซ์ Listener โดยการเรียก
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); }
- ยกเลิกการลงทะเบียนอินสแตนซ์ Listener เมื่อแอปฟังเสร็จแล้ว:
private void removeResourceOveruseListener() { CarWatchdogManager manager = (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE); mCarWatchdogManager.removeResourceOveruseListener( mListenerImpl); }
ลูกค้าพื้นเมือง
- รวม
carwatchdog_aidl_interface-ndk_platform
ในการพึ่งพาshared_libs
ของกฎการสร้างAndroid.bp
cc_binary { name: "sample_native_client", srcs: [ "src/*.cpp" ], shared_libs: [ "carwatchdog_aidl_interface-ndk_platform", "libbinder_ndk", ], vendor: true, }
- เพิ่มนโยบาย SELinux เพื่ออนุญาตให้โดเมนบริการของผู้ขายใช้ Binder (มาโคร
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
- ใช้งาน Listener การใช้ทรัพยากรมากเกินไปโดยสืบทอด
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(); }
- เริ่มต้นเธรดพูลของ Binder และลงทะเบียน Listener ที่ใช้ทรัพยากรมากเกินไปกับเซิร์ฟเวอร์ Watchdog เซิร์ฟเวอร์ Watchdog ได้รับการลงทะเบียนภายใต้ชื่อบริการ
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 สำหรับสถิติการใช้งาน I/O มากเกินไปเฉพาะแอป ATS ในช่วง 30 วันล่าสุด
ไคลเอนต์จาวา
ใช้ 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 วัน การตั้งค่านี้จะถูกรีเซ็ตเป็นค่าเริ่มต้นโดยอัตโนมัติ ขีดจำกัดวันสามารถแก้ไขได้ด้วยแอปซ้อนทับ RRO โดยใช้ watchdogUserPackageSettingsResetDays
สูงสุด 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 มากเกินไปซ้ำๆ ผู้ใช้จะได้รับการแจ้งเตือนต่อไปนี้:
- เมื่อผู้ใช้คลิกปุ่ม จัดลำดับความสำคัญของแอป หน้าการตั้งค่าของแอปจะเปิดขึ้น ซึ่งผู้ใช้สามารถสลับเปิดหรือปิดการตั้ง ค่าประสิทธิภาพของแอปจัดลำดับความสำคัญ ได้
- เมื่อผู้ใช้คลิกที่ปุ่ม ปิดใช้งานแอป แอปจะถูกปิดใช้งานจนกว่าผู้ใช้จะเปิดแอปหรือเปิดใช้งานบนหน้าการตั้งค่าของแอป
- สำหรับแอปที่สามารถถอนการติดตั้งได้ ปุ่ม ปิดใช้งานแอป จะถูกแทนที่ด้วยปุ่ม ถอนการติดตั้งแอป เมื่อผู้ใช้คลิกปุ่ม ถอนการติดตั้งแอป หน้าการตั้งค่าของแอปจะเปิดขึ้น ซึ่งผู้ใช้สามารถถอนการติดตั้งแอปได้
คำแนะนำสำหรับการใช้งาน Launcher
เมื่อแอปถูกปิดใช้งานเนื่องจากการใช้ทรัพยากรมากเกินไป แอปจะหายไปจากแอป Launcher เริ่มต้นเนื่องจาก CarService อัปเดตสถานะการเปิดใช้งานแอปเป็น PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
OEM ต้องอัปเดตการใช้งานตัวเรียกใช้งานในตัวเพื่อแสดงแอปเหล่านี้ว่าผิดปกติ เพื่อให้ผู้ใช้สามารถใช้งานได้หากจำเป็น ดูคำแนะนำต่อไปนี้ตามรุ่นบิวด์
การเปิดตัว Android SC V2
- การใช้งานตัวเรียกใช้งานควรใช้แฟล็ก
MATCH_DISABLED_UNTIL_USED_COMPONENTS
เมื่อดึงรายการแพ็คเกจที่จะแสดงบนตัวเรียกใช้งาน - เมื่อผู้ใช้คลิกแอปที่อยู่ในสถานะ
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
แอป Launcher จะต้องเปิดใช้งานแอปโดยการตั้งค่าสถานะเปิดใช้งานเป็น: