Dirilis:
Android 11 (API Level 30) - Thermal API
Android 12 (API Level 31) - NDK API
(Pratinjau) Android 15 (DP1) - getThermalHeadroomThresholds()
Potensi performa aplikasi Anda dibatasi oleh status termal perangkat, yang dapat bervariasi berdasarkan karakteristik seperti cuaca, penggunaan terbaru, dan desain termal perangkat. Perangkat hanya dapat mempertahankan level performa yang tinggi selama jangka waktu tertentu sebelum di-throttle secara termal. Sasaran utama penerapan Anda adalah untuk mencapai sasaran performa tanpa melampaui batasan termal. Thermal API memungkinkannya tanpa memerlukan pengoptimalan khusus perangkat. Selain itu, saat men-debug masalah performa, penting untuk mengetahui apakah status termal perangkat Anda membatasi performa atau tidak.
Game engine biasanya memiliki parameter performa runtime yang dapat menyesuaikan beban kerja yang diberikan mesin di perangkat. Misalnya, parameter ini dapat menetapkan jumlah thread pekerja, afinitas thread pekerja untuk core besar dan kecil, opsi fidelitas GPU, dan resolusi framebuffer. Di Unity Engine, developer game dapat menyesuaikan beban kerja dengan mengubah Setelan Kualitas menggunakan plugin Adaptive Performance. Untuk Unreal Engine, gunakan Setelan Skalabilitas untuk menyesuaikan tingkat kualitas secara dinamis.
Saat perangkat mendekati status termal yang tidak aman, game Anda dapat menghindari throttling dengan mengurangi beban kerja melalui parameter ini. Untuk menghindari throttling, Anda harus memantau status termal perangkat dan secara proaktif menyesuaikan beban kerja game engine. Setelah perangkat menjadi terlalu panas, beban kerja harus berkurang di bawah level performa berkelanjutan untuk menghilangkan panas. Setelah headroom termal menurun ke tingkat yang lebih aman, game dapat meningkatkan setelan kualitas lagi, tetapi pastikan untuk menemukan tingkat kualitas yang berkelanjutan untuk waktu bermain yang optimal.
Anda dapat memantau status termal perangkat dengan memilih
metode
getThermalHeadroom
. Metode ini memprediksi berapa lama perangkat dapat mempertahankan level performa
saat ini tanpa panas berlebih. Jika waktunya kurang dari jumlah
yang diperlukan untuk menjalankan beban kerja, game Anda harus mengurangi beban kerja ke
level yang berkelanjutan. Misalnya, game dapat beralih ke core yang lebih kecil, mengurangi
kecepatan frame, atau menurunkan fidelitas.
![Pra-Integrasi ADPF Thermal API](https://developer.android.google.cn/static/games/optimize/adpf/images/adpf_thermal_pre-integration.png?authuser=0&hl=id)
![Pasca-Integrasi ADPF Thermal API](https://developer.android.google.cn/static/games/optimize/adpf/images/adpf_thermal_post-integration.png?authuser=0&hl=id)
Memperoleh Pengelola Termal
Untuk menggunakan Thermal API, Anda harus mendapatkan Pengelola Termal terlebih dahulu
C++
AThermalManager* thermal_manager = AThermal_acquireManager();
Java
PowerManager powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
Memperkirakan Headroom Termal x detik ke depan untuk kontrol yang lebih besar
Anda dapat meminta sistem untuk memperkirakan suhu x detik ke depan dengan beban kerja saat ini. Hal ini memberi Anda kontrol yang lebih terperinci dan lebih banyak waktu untuk bereaksi dengan mengurangi beban kerja untuk mencegah throttling termal aktif.
Hasilnya berkisar dari 0,0f (tanpa throttling, THERMAL_STATUS_NONE
) hingga 1,0f
(throttling berat, THERMAL_STATUS_SEVERE
).
Jika memiliki tingkat kualitas grafis yang berbeda dalam game, Anda dapat mengikuti
Pedoman Headroom Termal kami.
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);
Atau, gunakan status termal untuk mendapatkan klarifikasi
Setiap model perangkat mungkin didesain secara berbeda. Beberapa perangkat mungkin dapat mendistribusikan panas dengan lebih baik sehingga dapat menahan headroom termal yang lebih tinggi sebelum di-throttle. Jika ingin membaca pengelompokan rentang headroom termal yang disederhanakan, Anda dapat memeriksa status termal untuk memahami nilai headroom termal di perangkat saat ini.
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);
Mendapatkan notifikasi saat status termal berubah
Anda juga dapat menghindari polling thermalHeadroom
hingga thermalStatus
mencapai
tingkat tertentu (misalnya: THERMAL_STATUS_LIGHT
).
Untuk melakukannya, Anda dapat mendaftarkan callback agar sistem memberi tahu Anda setiap kali
status berubah.
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);
Jangan lupa untuk menghapus pemroses setelah selesai
C++
int result = AThermal_unregisterThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
// failed, check whether the callback has been registered previously
}
Java
powerManager.removeThermalStatusListener(listener);
Pembersihan
Setelah selesai, Anda harus membersihkan thermal_manager yang diperoleh. Jika Anda menggunakan Java, referensi PowerManager dapat otomatis dikumpulkan sampah untuk Anda. Namun, jika Anda menggunakan Java API melalui JNI dan telah mempertahankan referensi, jangan lupa untuk membersihkan referensi tersebut.
C++
AThermal_releaseManager(thermal_manager);
Untuk panduan lengkap tentang cara menerapkan Thermal API pada game C++ native menggunakan C++ API (NDK API) dan Java API (melalui JNI), lihat bagian Mengintegrasikan Thermal API di bagian Codelab Adaptasi.
Panduan headroom termal
Anda dapat memantau status termal perangkat dengan memilih
metode
getThermalHeadroom
. Metode ini memprediksi berapa lama perangkat dapat mempertahankan level performa
saat ini sebelum mencapai THERMAL_STATUS_SEVERE
.
Misalnya, jika getThermalHeadroom(30)
menampilkan 0,8, hal ini menunjukkan bahwa dalam 30
detik, headroom diperkirakan akan mencapai 0,8, dengan jarak 0,2
dari throttling yang parah, atau 1,0. Jika waktunya kurang dari jumlah yang diperlukan untuk
menjalankan beban kerja, game Anda harus mengurangi beban kerja ke level
yang berkelanjutan. Misalnya, game dapat mengurangi kecepatan frame, menurunkan fidelitas, atau
mengurangi pekerjaan konektivitas jaringan.
Status dan arti termal
- Jika perangkat tidak mengalami throttling termal:
- Beberapa throttling, tetapi tidak berdampak signifikan pada performa:
- Throttling signifikan yang memengaruhi performa:
Batasan perangkat Thermal API
Ada beberapa batasan atau persyaratan tambahan yang diketahui dari Thermal API, karena implementasi API termal di perangkat lama. Batasan dan cara mengatasinya adalah sebagai berikut:
- Jangan terlalu sering memanggil API
GetThermalHeadroom()
. Jika Anda melakukannya, API akan menampilkanNaN
. Anda tidak boleh memanggilnya lebih dari sekali setiap 10 detik. - Hindari panggilan dari beberapa thread, karena akan lebih sulit untuk memastikan frekuensi
panggilan dan dapat menyebabkan API menampilkan
NaN
. - Jika nilai awal
GetThermalHeadroom()
adalah NaN, API tidak tersedia di perangkat - Jika
GetThermalHeadroom()
menampilkan nilai tinggi (misalnya: 0,85 atau lebih) danGetCurrentThermalStatus()
masih menampilkanTHERMAL_STATUS_NONE
, statusnya kemungkinan tidak diperbarui. Gunakan heuristik untuk memperkirakan status throttling termal yang benar atau cukup gunakangetThermalHeadroom()
tanpagetCurrentThermalStatus()
.
Contoh heuristik:
- Pastikan Thermal API didukung.
isAPISupported()
memeriksa nilai panggilan pertama kegetThermalHeadroom
untuk memastikan bahwa nilainya bukan 0 atau NaN dan mengabaikan penggunaan API jika nilai pertama adalah 0 atau NaN. - Jika
getCurrentThermalStatus()
menampilkan nilai selainTHERMAL_STATUS_NONE
, perangkat sedang dibatasi secara termal. - Jika
getCurrentThermalStatus()
terus menampilkanTHERMAL_STATUS_NONE
, hal ini tidak selalu berarti perangkat tidak mengalami throttling termal. Hal ini dapat berarti bahwagetCurrentThermalStatus()
tidak didukung di perangkat. Periksa nilai yang ditampilkangetThermalHeadroom()
untuk memastikan kondisi perangkat. - Jika
getThermalHeadroom()
menampilkan nilai > 1,0, statusnya sebenarnya dapatTHERMAL_STATUS_SEVERE
atau lebih tinggi, segera kurangi beban kerja dan pertahankan beban kerja yang lebih rendah hinggagetThermalHeadroom()
menampilkan nilai yang lebih rendah - Jika
getThermalHeadroom()
menampilkan nilai 0,95, statusnya sebenarnya dapat berupaTHERMAL_STATUS_MODERATE
atau lebih tinggi, segera kurangi beban kerja dan terus waspada untuk mencegah pembacaan yang lebih tinggi - Jika
getThermalHeadroom()
menampilkan nilai 0,85, statusnya sebenarnya dapat berupaTHERMAL_STATUS_LIGHT
, terus waspada dan kurangi beban kerja jika memungkinkan
Kode semu:
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.
}
}
}
Diagram: