เผยแพร่แล้ว
Android 11 (API ระดับ 30) - Thermal API
Android 12 (API ระดับ 31) - NDK API
(เวอร์ชันตัวอย่าง) Android 15 (DP1) - getThermalHeadroomThresholds()
ประสิทธิภาพที่เป็นไปได้ของแอปถูกจำกัดโดยสถานะความร้อนของอุปกรณ์ ซึ่งอาจแตกต่างกันไปตามลักษณะต่างๆ เช่น สภาพอากาศ การใช้งานล่าสุด และการออกแบบการระบายความร้อนของอุปกรณ์ อุปกรณ์จะรักษาประสิทธิภาพระดับสูงได้เพียงระยะเวลาหนึ่งเท่านั้นก่อนที่จะมีการจำกัดความร้อน เป้าหมายหลักของการติดตั้งใช้งานควรเป็นการบรรลุเป้าหมายด้านประสิทธิภาพโดยไม่เกินขีดจำกัดการระบายความร้อน Thermal API ทําให้เป็นไปได้โดยไม่ต้องเพิ่มประสิทธิภาพเฉพาะอุปกรณ์ นอกจากนี้ เมื่อแก้ไขข้อบกพร่องด้านประสิทธิภาพ คุณควรทราบว่าสถานะความร้อนของอุปกรณ์จํากัดประสิทธิภาพหรือไม่
โดยปกติแล้วเครื่องมือสร้างเกมจะมีพารามิเตอร์ประสิทธิภาพรันไทม์ที่สามารถปรับภาระงานที่เครื่องมือสร้างเกมจะส่งไปยังอุปกรณ์ เช่น พารามิเตอร์เหล่านี้สามารถตั้งค่าจำนวนเทรดของผู้ปฏิบัติงาน ความสัมพันธ์ของเทรดของผู้ปฏิบัติงานสำหรับแกนหลักและแกนรอง ตัวเลือกความถูกต้องของ GPU และความละเอียดของเฟรมบัฟเฟอร์ ใน Unity Engine นักพัฒนาเกมสามารถปรับภาระงานได้โดยเปลี่ยนการตั้งค่าคุณภาพโดยใช้ปลั๊กอิน Adaptive Performance สำหรับ Unreal Engine ให้ใช้การตั้งค่าความสามารถในการปรับขนาดเพื่อปรับระดับคุณภาพแบบไดนามิก
เมื่ออุปกรณ์มีอุณหภูมิใกล้ถึงสถานะความร้อนที่ไม่ปลอดภัย เกมจะหลีกเลี่ยงการจำกัดด้วยวิธีลดภาระงานผ่านพารามิเตอร์เหล่านี้ หากต้องการหลีกเลี่ยงการจำกัดความเร็ว คุณควรตรวจสอบสถานะความร้อนของอุปกรณ์และปรับปริมาณงานของเครื่องมือของเกมอย่างสม่ำเสมอ เมื่ออุปกรณ์ร้อนเกินไป ปริมาณงานจะต้องลดลงต่ำกว่าระดับประสิทธิภาพที่ยั่งยืนเพื่อกระจายความร้อน หลังจากที่ระยะความเย็นลดลงสู่ระดับที่ปลอดภัยยิ่งขึ้น เกมจะเพิ่มการตั้งค่าคุณภาพได้อีกครั้ง แต่อย่าลืมหาระดับคุณภาพที่ยั่งยืนเพื่อให้เล่นได้นานที่สุด
คุณสามารถตรวจสอบสถานะความร้อนของอุปกรณ์ได้โดยการปลุกวิธี getThermalHeadroom
วิธีนี้คาดการณ์ระยะเวลาที่อุปกรณ์จะรักษาระดับประสิทธิภาพปัจจุบันไว้ได้โดยไม่ร้อนเกินไป หากเวลาน้อยกว่าระยะเวลาที่จําเป็นในการใช้งานเวิร์กโหลด เกมควรลดปริมาณเวิร์กโหลดให้อยู่ในระดับที่ยั่งยืน เช่น เกมอาจเปลี่ยนไปใช้แกนประมวลผลที่เล็กลง ลดอัตราเฟรม หรือลดคุณภาพ
![การผสานรวม ADPF Thermal API ล่วงหน้า](https://developer.android.google.cn/static/games/optimize/adpf/images/adpf_thermal_pre-integration.png?authuser=0&hl=th)
![ADPF Thermal API หลังการผสานรวม](https://developer.android.google.cn/static/games/optimize/adpf/images/adpf_thermal_post-integration.png?authuser=0&hl=th)
ซื้อ Thermal Manager
หากต้องการใช้ Thermal API คุณจะต้องซื้อ Thermal Manager ก่อน
C++
AThermalManager* thermal_manager = AThermal_acquireManager();
Java
PowerManager powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
คาดการณ์กำลังไฟเหลือ x วินาทีล่วงหน้าเพื่อให้ควบคุมได้มากขึ้น
คุณสามารถขอให้ระบบคาดการณ์อุณหภูมิล่วงหน้า x วินาทีโดยอิงตามปริมาณงานปัจจุบัน วิธีนี้ช่วยให้คุณควบคุมได้ละเอียดยิ่งขึ้นและมีเวลาในการตอบสนองมากขึ้นด้วยการปรับลดภาระงานเพื่อป้องกันไม่ให้ระบบควบคุมการระบายความร้อนทำงาน
ผลลัพธ์จะอยู่ระหว่าง 0.0f (ไม่มีการจำกัด THERMAL_STATUS_NONE
) ถึง 1.0f (การจำกัดอย่างมาก THERMAL_STATUS_SEVERE
)
หากเกมมีระดับคุณภาพกราฟิกที่แตกต่างกัน คุณสามารถปฏิบัติตามหลักเกณฑ์เกี่ยวกับ Headroom ความร้อน
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
ได้จนกว่า 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);
อย่าลืมนำเครื่องมือฟังออกเมื่อดำเนินการเสร็จแล้ว
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 วินาที คาดว่า Headroom จะถึง 0.8 ซึ่งอยู่ห่างจากการจำกัดแบนด์วิดท์อย่างรุนแรงหรือ 1.0 เพียง 0.2 หากเวลาน้อยกว่าระยะเวลาที่จําเป็นต่อการทํางานของภาระงาน เกมควรลดภาระงานให้อยู่ในระดับที่ยั่งยืน เช่น เกมอาจลดอัตราเฟรม ลดความเที่ยงตรง หรือลดการทำงานในการเชื่อมต่อเครือข่าย
สถานะและความหมายของอุณหภูมิ
- หากอุปกรณ์ไม่ได้ถูกจำกัดความร้อน ให้ทำดังนี้
- มีการจำกัดบางอย่าง แต่ไม่มีผลกระทบต่อประสิทธิภาพอย่างมีนัยสำคัญ
- การจำกัดที่สำคัญที่ส่งผลต่อประสิทธิภาพ
ข้อจํากัดของอุปกรณ์สำหรับ Thermal API
Thermal API มีข้อจำกัดหรือข้อกำหนดเพิ่มเติมที่ทราบอยู่บ้าง เนื่องจากการติดตั้งใช้งาน Thermal API ในอุปกรณ์รุ่นเก่า ข้อจำกัดและวิธีแก้ปัญหามีดังนี้
- อย่าเรียก
GetThermalHeadroom()
API บ่อยเกินไป หากดำเนินการดังกล่าว API จะแสดงผลเป็นNaN
คุณไม่ควรเรียกใช้มากกว่า 1 ครั้งในทุกๆ 10 วินาที - หลีกเลี่ยงการเรียกจากหลายเธรด เนื่องจากจะตรวจสอบความถี่ในการเรียกได้ยากขึ้นและอาจทําให้ API แสดงผล
NaN
- หากค่าเริ่มต้นของ
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.
}
}
}
แผนภาพ