เผยแพร่:
Android 11 (API ระดับ 30) - Thermal API
Android 12 (API ระดับ 31) - NDK API
(เวอร์ชันตัวอย่าง) Android 15 (DP1) - getThermalHeadroomThresholds()
ประสิทธิภาพที่เป็นไปได้ของแอปถูกจํากัดด้วยสถานะความร้อนของ ซึ่งอาจแตกต่างกันไปตามลักษณะ เช่น สภาพอากาศ การใช้งานล่าสุด และการออกแบบความร้อนของอุปกรณ์ อุปกรณ์สามารถรักษาระดับ ประสิทธิภาพเป็นระยะเวลาจำกัดก่อนที่จะถูกควบคุมด้วยความร้อน คีย์ ในการใช้งานของคุณควรเป็น บรรลุเป้าหมายด้านประสิทธิภาพ เกินขีดจำกัดทางความร้อน Thermal API ทำให้ทุกอย่างเป็นไปได้โดยไม่จำเป็นต้อง สำหรับการเพิ่มประสิทธิภาพเฉพาะอุปกรณ์ นอกจากนี้ เมื่อแก้ไขข้อบกพร่องด้านประสิทธิภาพ การทราบว่าสถานะความร้อนของอุปกรณ์จำกัดประสิทธิภาพอยู่หรือไม่ เป็นอย่างมาก
เครื่องมือเกมมักมีพารามิเตอร์ประสิทธิภาพรันไทม์ที่สามารถปรับ ภาระงานที่เครื่องยนต์ทำให้อุปกรณ์ ตัวอย่างเช่น พารามิเตอร์เหล่านี้สามารถสร้าง จำนวนเธรดผู้ปฏิบัติงาน แอฟฟินิตี้เทรดผู้ปฏิบัติงานสำหรับแกนขนาดใหญ่และเล็ก ตัวเลือกความแม่นยำของ GPU และความละเอียดของ Framebuffer ใน Unity Engine ก็สามารถปรับปริมาณงานโดยเปลี่ยนคุณภาพ การตั้งค่า โดยใช้ปลั๊กอินประสิทธิภาพแบบปรับอัตโนมัติ สำหรับ Unreal Engine ให้ใช้การตั้งค่าความสามารถในการปรับขนาดเพื่อปรับ แบบไดนามิก
เมื่ออุปกรณ์เข้าสู่สถานะความร้อนที่ไม่ปลอดภัย เกมของคุณจะหลีกเลี่ยง ซึ่งควบคุมโดยการลดภาระงานผ่านพารามิเตอร์เหล่านี้ วิธีหลีกเลี่ยง มีการควบคุม คุณควรตรวจดูสถานะความร้อนของอุปกรณ์และเชิงรุก ปรับภาระงานของ Game Engine เมื่ออุปกรณ์มีความร้อนสูงเกินไป ภาระงานจะต้อง ให้ประสิทธิภาพลดลงต่ำกว่าระดับประสิทธิภาพที่ยั่งยืนเพื่อกระจายความร้อน หลัง ช่องว่างทางความร้อนจะลดลงในระดับที่ปลอดภัยขึ้น เกมจึงสามารถเพิ่ม การตั้งค่าคุณภาพอีกครั้ง แต่อย่าลืมหาระดับคุณภาพที่ยั่งยืน เพื่อเวลาการเล่นที่เหมาะสมที่สุด
คุณเฝ้าติดตามสถานะความร้อนของอุปกรณ์ได้โดยแบบสำรวจ
getThermalHeadroom
วิธีนี้จะคาดการณ์ว่าอุปกรณ์จะรักษากระแสไฟได้นานแค่ไหน
โดยไม่ทำความร้อนจนเกินไป หากเวลาน้อยกว่าจำนวนดังกล่าว
ที่จำเป็นสำหรับการเรียกใช้ภาระงาน เกมของคุณควรลดปริมาณงานลงเป็น
ยั่งยืน ตัวอย่างเช่น เกมสามารถเปลี่ยนไปใช้แกนที่เล็กลง ลด
อัตราเฟรมหรือความละเอียดที่ต่ำลง
รับ Thermal Manager
คุณต้องหา Thermal Manager ก่อนจึงจะใช้ Thermal API ได้
C++
AThermalManager* thermal_manager = AThermal_acquireManager();
Java
PowerManager powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
คาดการณ์ Thermal Headroom x วินาทีเพื่อการควบคุมที่มากขึ้น
คุณขอให้ระบบคาดการณ์อุณหภูมิ x วินาทีล่วงหน้าได้โดยใช้ ปริมาณงานปัจจุบัน ทำให้คุณควบคุมได้ละเอียดยิ่งขึ้นและมีเวลามากขึ้น จะตอบสนองด้วยการลดปริมาณงานเพื่อป้องกันไม่ให้การควบคุมความร้อนส่งเข้ามา
ผลลัพธ์มีตั้งแต่ 0.0f (ไม่มีการควบคุม THERMAL_STATUS_NONE
) ถึง 1.0f
(การควบคุมอย่างหนัก THERMAL_STATUS_SEVERE
)
หากเกมของคุณมีระดับคุณภาพของกราฟิกแตกต่างกัน ก็ทำตาม
หลักเกณฑ์เกี่ยวกับช่องว่างทางความร้อน
C++
float thermal_headroom = AThermal_getThermalHeadroom(10);
ALOGI("ThermalHeadroom in 10 sec: %f", thermal_headroom);
Java
float thermalHeadroom = powerManager.getThermalHeadroom(10);
Log.d("ADPF", "ThermalHeadroom in 10 sec: " + thermalHeadroom);
อีกทางเลือกหนึ่งคืออาศัยสถานะความร้อนเพื่อการชี้แจง
อุปกรณ์แต่ละรุ่นอาจออกแบบแตกต่างกันไป อุปกรณ์บางเครื่องอาจทำสิ่งต่อไปนี้ได้ กระจายความร้อนได้ดีขึ้น จึงทำให้สามารถทนต่อช่องว่างทางความร้อนที่สูงขึ้นได้ ก่อนจะถูกควบคุม ถ้าต้องการอ่านการจัดกลุ่มช่วงของ ช่องว่างทางความร้อน คุณสามารถตรวจสอบสถานะความร้อนเพื่อทำความเข้าใจ ค่าช่องว่างทางความร้อนในอุปกรณ์ปัจจุบัน
C++
AThermalStatus thermal_status = AThermal_getCurrentThermalStatus(thermal_manager);
ALOGI("ThermalStatus is: %d", thermal_status);
Java
int thermalStatus = powerManager.getCurrentThermalStatus();
Log.d("ADPF", "ThermalStatus is: " + thermalStatus);
รับการแจ้งเตือนเมื่อสถานะของความร้อนมีการเปลี่ยนแปลง
นอกจากนี้คุณยังหลีกเลี่ยงการสำรวจ thermalHeadroom
ได้จนกว่า Hit thermalStatus
ระดับหนึ่ง (เช่น THERMAL_STATUS_LIGHT
)
ในการดำเนินการดังกล่าว คุณสามารถลงทะเบียนการติดต่อกลับเพื่อให้ระบบแจ้งให้คุณทราบเมื่อใดก็ตามที่
สถานะ เปลี่ยนไป
C++
int result = AThermal_registerThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
// failed, check whether you have previously registered callback that
// hasn’t been unregistered
}
Java
// PowerManager.OnThermalStatusChangedListener is an interface, thus you can
// also define a class that implements the methods
PowerManager.OnThermalStatusChangedListener listener = new
PowerManager.OnThermalStatusChangedListener() {
@Override
public void onThermalStatusChanged(int status) {
Log.d("ADPF", "ThermalStatus changed: " + status);
// check the status and flip the flag to start/stop pooling when
// applicable
}
};
powerManager.addThermalStatusListener(listener);
อย่าลืมนำ Listener ออกเมื่อเสร็จแล้ว
C++
int result = AThermal_unregisterThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
// failed, check whether the callback has been registered previously
}
Java
powerManager.removeThermalStatusListener(listener);
ทำความสะอาดข้อมูล
เมื่อดำเนินการเสร็จแล้ว คุณจะต้องล้าง thermal_manager ที่ได้มา หากคุณใช้ Java การอ้างอิง PowerManager อาจกลายเป็นขยะโดยอัตโนมัติ ที่รวบรวมไว้ให้คุณ แต่ถ้าคุณใช้ Java API ผ่าน JNI และ เก็บข้อมูลอ้างอิงไว้ อย่าลืมลบข้อมูลอ้างอิง!
C++
AThermal_releaseManager(thermal_manager);
สำหรับคำแนะนำทั้งหมดเกี่ยวกับวิธีใช้ Thermal API ในเกม C++ ที่มาพร้อมเครื่อง ทั้ง C++ API (NDK API) และ Java API (ผ่าน JNI) โปรดดูการผสานรวม ส่วน Thermal API ใน Adaptability Codelab
หลักเกณฑ์ช่องว่างทางความร้อน
คุณเฝ้าติดตามสถานะความร้อนของอุปกรณ์ได้โดยแบบสำรวจ
getThermalHeadroom
วิธีนี้จะคาดการณ์ว่าอุปกรณ์จะรักษากระแสไฟได้นานแค่ไหน
ระดับประสิทธิภาพก่อนที่จะถึง THERMAL_STATUS_SEVERE
เช่น หาก getThermalHeadroom(30)
แสดงผล 0.8 แสดงว่าใน 30
วินาที ช่องว่างควรอยู่ที่ 0.8 ซึ่งเป็นจุดที่ห่างออกไป 0.2
จากการควบคุมระดับรุนแรง หรือ 1.0 ถ้าเวลาน้อยกว่าระยะเวลาที่ต้องใช้ในการ
ดำเนินการให้ภาระงาน เกมของคุณควรลดปริมาณงานลง
ตัวอย่างเช่น เกมอาจลดอัตราเฟรม ความละเอียดต่ำลง หรือ
ทำให้การเชื่อมต่อเครือข่ายลดลง
สถานะและความหมายของความร้อน
- หากอุปกรณ์ไม่ได้ถูกควบคุมด้วยความร้อน ให้ทำดังนี้
- มีการควบคุมบ้าง แต่ไม่มีผลกระทบอย่างมากต่อประสิทธิภาพ:
- การควบคุมที่สำคัญซึ่งส่งผลต่อประสิทธิภาพ
ข้อจำกัดด้านอุปกรณ์ของ Thermal API
ทั้งนี้เนื่องจาก Thermal API มีข้อจำกัดที่ทราบหรือข้อกำหนดเพิ่มเติมบางอย่าง เกี่ยวกับการใช้งาน Thermal API ในอุปกรณ์รุ่นเก่า ข้อจำกัดและวิธีการ วิธีหลีกเลี่ยงปัญหามีดังนี้
- อย่าเรียกใช้
GetThermalHeadroom()
API บ่อยเกินไป การดำเนินการนี้จะ ทำให้ API แสดงผล NaN คุณควรโทรอย่างน้อย 1 ครั้งต่อวินาที - หากค่าเริ่มต้นของ
GetThermalHeadroom()
คือ NaN แสดงว่า API จะไม่ พร้อมใช้งานบนอุปกรณ์ - หาก
GetThermalHeadroom()
แสดงผลค่าสูง (เช่น 0.85 ขึ้นไป) และGetCurrentThermalStatus()
ยังคงแสดงผลTHERMAL_STATUS_NONE
แต่สถานะคือ น่าจะยังไม่ได้อัปเดต ใช้ฮิวริสติกเพื่อประมาณการควบคุมความร้อนที่ถูกต้อง หรือใช้getThermalHeadroom()
โดยไม่มีgetCurrentThermalStatus()
ตัวอย่างการวิเคราะห์วิธีการ:
- ตรวจสอบว่าระบบรองรับ Thermal API
isAPISupported()
ตรวจสอบค่าของ การเรียกgetThermalHeadroom
ครั้งแรกเพื่อให้แน่ใจว่าไม่ใช่ 0 หรือ NaN และ ข้ามการใช้ API หากค่าแรกเป็น 0 หรือ NaN - หาก
getCurrentThermalStatus()
แสดงผลค่าอื่นที่ไม่ใช่THERMAL_STATUS_NONE
อุปกรณ์ถูกควบคุมด้วยความร้อน - หาก
getCurrentThermalStatus()
แสดงผลTHERMAL_STATUS_NONE
ต่อไปเรื่อยๆ ไม่ได้หมายความว่าอุปกรณ์ไม่ได้ถูกควบคุมด้วยความร้อนเสมอไป น่าจะ หมายความว่าอุปกรณ์นี้ไม่รองรับgetCurrentThermalStatus()
ตรวจสอบค่าผลลัพธ์getThermalHeadroom()
เพื่อให้แน่ใจว่าเงื่อนไขของ อุปกรณ์ - หาก
getThermalHeadroom()
แสดงผลค่า > 1.0 สถานะอาจ เท่ากับTHERMAL_STATUS_SEVERE
ขึ้นไป ลดปริมาณงานทันที และ จะรักษาปริมาณงานที่ต่ำกว่าไว้จนกว่าgetThermalHeadroom()
จะแสดงผลค่าที่ต่ำกว่า - หาก
getThermalHeadroom()
แสดงผลค่า 0.95 สถานะอาจแสดง เท่ากับTHERMAL_STATUS_MODERATE
ขึ้นไป ลดปริมาณงานทันที และคอยเฝ้าระวังเพื่อป้องกันการอ่านค่าที่สูงขึ้น - หาก
getThermalHeadroom()
แสดงผลค่า 0.85 สถานะอาจแสดง และเป็นTHERMAL_STATUS_LIGHT
รักษาการเฝ้าระวังและลดปริมาณงาน ถ้าเป็นไปได้
ซูโดโค้ด:
bool isAPISupported() {
float first_value_of_thermal_headroom = getThermalHeadroom();
if ( first_value_of_thermal_headroom == 0 ||
first_value_of_thermal_headroom == NaN ) {
// Checked the thermal Headroom API's initial return value
// it is NaN or 0,so, return false (not supported)
return false;
}
return true;
}
if (!isAPISupported()) {
// Checked the thermal Headroom API's initial return value, it is NaN or 0
// Don’t use the API
} else {
// Use thermalStatus API to check if it returns valid values.
if (getCurrentThermalStatus() > THERMAL_STATUS_NONE) {
// The device IS being thermally throttled
} else {
// The device is not being thermally throttled currently. However, it
// could also be an indicator that the ThermalStatus API may not be
// supported in the device.
// Currently this API uses predefined threshold values for thermal status
// mapping. In the future you may be able to query this directly.
float thermal_headroom = getThermalHeadroom();
if ( thermal_headroom > 1.0) {
// The device COULD be severely throttled.
} else if ( thermal_headroom > 0.95) {
// The device COULD be moderately throttled.
} else if ( thermal_headroom > 0.85) {
// The device COULD be experiencing light throttling.
}
}
}
แผนภาพ: