Veröffentlicht:
Android 11 (API-Level 30) – Thermal API
Android 12 (API-Level 31) – NDK API
(Vorabversion) Android 15 (DP1) – getThermalHeadroomThresholds()
Die potenzielle Leistung deiner App ist durch den Temperaturzustand des Geräts begrenzt, der je nach Eigenschaften wie Wetter, jüngster Nutzung und thermischer Beschaffenheit des Geräts variieren kann. Geräte können nur für einen begrenzten Zeitraum ein hohes Leistungsniveau aufrechterhalten, bevor sie thermisch gedrosselt werden. Ein zentrales Ziel der Implementierung sollte darin bestehen, Leistungsziele ohne Überschreiten von Temperaturbeschränkungen zu erreichen. Mit der Thermal API ist es möglich, ohne dass gerätespezifische Optimierungen erforderlich sind. Außerdem ist es beim Beheben von Leistungsproblemen wichtig, zu wissen, ob der Temperaturzustand Ihres Geräts die Leistung beeinträchtigt. Außerdem ist es beim Beheben von Leistungsproblemen wichtig zu wissen, ob der Temperaturzustand Ihres Geräts die Leistung einschränkt.
Spiel-Engines haben normalerweise Parameter für die Laufzeitleistung, mit denen die Arbeitslast angepasst werden kann, die die Engine auf das Gerät aufwendet. Mit diesen Parametern können Sie beispielsweise die Anzahl der Worker-Threads, die Worker-Thread-Affinität für große und kleine Kerne, die Optionen zur Grafikqualität und die Framebuffer-Auflösungen festlegen. In Unity Engine können Spieleentwickler die Arbeitslast anpassen, indem sie die Qualitätseinstellungen mithilfe des Adaptive Performance-Plug-ins ändern. Verwenden Sie für Unreal Engine die Skalierbarkeitseinstellungen, um die Qualitätsstufen dynamisch anzupassen.
Wenn sich ein Gerät einem unsicheren Temperaturzustand nähert, kann Ihr Spiel nicht gedrosselt werden, indem die Arbeitslast durch diese Parameter verringert wird. Um eine Drosselung zu vermeiden, sollten Sie den Temperaturzustand des Geräts überwachen und die Arbeitslast der Spiel-Engine proaktiv anpassen. Wenn das Gerät überhitzt, muss die Arbeitslast unter das nachhaltige Leistungsniveau fallen, um Wärme abzuleiten. Sobald der theoretische Toleranzbereich auf sicherere Levels gesunken ist, kann das Spiel die Qualitätseinstellungen wieder erhöhen. Achten Sie aber darauf, eine nachhaltige Qualität für eine optimale Spielzeit zu finden.
Sie können den Temperaturzustand des Geräts überwachen, indem Sie die Methode getThermalHeadroom
abfragen. Mit dieser Methode wird vorhergesagt, wie lange das Gerät das aktuelle Leistungsniveau ohne Überhitzung halten kann. Wenn die Zeit kürzer ist, als zum Ausführen der Arbeitslast erforderlich ist, sollte Ihr Spiel die Arbeitslast auf ein nachhaltiges Niveau reduzieren. Im Spiel kann es beispielsweise zu kleineren Kernen kommen, die Framerate reduzieren oder die Grafikqualität verschlechtern.
![Vorintegration der ADPF Thermal API](https://developer.android.google.cn/static/games/optimize/adpf/images/adpf_thermal_pre-integration.png?authuser=6&hl=de)
![ADPF Thermal API – Nach-Integration](https://developer.android.google.cn/static/games/optimize/adpf/images/adpf_thermal_post-integration.png?authuser=6&hl=de)
Thermal Manager übernehmen
Wenn Sie die Thermal API nutzen möchten, müssen Sie zuerst den Thermal Manager erwerben
C++
AThermalManager* thermal_manager = AThermal_acquireManager();
Java
PowerManager powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
Prognostizieren Sie für mehr Kontrolle den thermischen Toleranzbereich x Sekunden im Voraus.
Sie können das System bitten, die Temperatur für die aktuelle Arbeitslast auf x Sekunden voraus zu prognostizieren. Dies gibt Ihnen eine genauere Kontrolle und mehr Zeit zum Reagieren, da die Arbeitslast reduziert wird, um eine Drosselung der Wärme zu verhindern.
Das Ergebnis reicht von 0,0f (keine Drosselung, THERMAL_STATUS_NONE
) bis 1,0f (starke Drosselung, THERMAL_STATUS_SEVERE
).
Wenn Sie in Ihren Spielen unterschiedliche Grafikqualitätsstufen haben, können Sie unseren Richtlinien für thermische Toleranzbereiche folgen.
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);
Alternativ kannst du dich zur Klärung auf den Temperaturstatus verlassen
Jedes Gerätemodell kann anders aufgebaut sein. Einige Geräte können die Wärme besser verteilen und so einen höheren thermischen Toleranzbereich aushalten, bevor sie gedrosselt werden. Wenn Sie eine vereinfachte Gruppierung der Bereiche des thermischen Toleranzraums lesen möchten, können Sie den Temperaturstatus prüfen, um den Wert des thermischen Tolerraums auf dem aktuellen Gerät zu ermitteln.
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);
Benachrichtigungen erhalten, wenn sich der Temperaturzustand ändert
Sie können auch vermeiden, thermalHeadroom
abzufragen, bis thermalStatus
ein bestimmtes Level erreicht (z. B. THERMAL_STATUS_LIGHT
). Dazu können Sie einen Callback registrieren, mit dem Sie das System benachrichtigt, wenn sich der Status geändert hat.
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);
Denken Sie daran, den Listener zu entfernen, wenn Sie fertig sind.
C++
int result = AThermal_unregisterThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
// failed, check whether the callback has been registered previously
}
Java
powerManager.removeThermalStatusListener(listener);
Bereinigung
Sobald Sie fertig sind, müssen Sie das von Ihnen erworbene Thermal Manager bereinigen. Wenn Sie Java verwenden, kann die PowerManager-Referenz automatisch für Sie automatisch bereinigt werden. Wenn Sie jedoch die Java API über JNI verwenden und eine Referenz beibehalten haben, denken Sie daran, die Referenz zu bereinigen.
C++
AThermal_releaseManager(thermal_manager);
Eine vollständige Anleitung zum Implementieren der Thermal API in einem nativen C++-Spiel mit der C++ API (NDK API) und der Java API (über JNI) finden Sie im Abschnitt Integrate Thermal API im Abschnitt Anpassungscodelab.
Richtlinien für den thermischen Toleranzbereich
Sie können den Temperaturzustand des Geräts überwachen, indem Sie die Methode getThermalHeadroom
abfragen. Mit dieser Methode wird vorhergesagt, wie lange das Gerät das aktuelle Leistungsniveau halten kann, bevor THERMAL_STATUS_SEVERE
erreicht wird.
Wenn getThermalHeadroom(30)
beispielsweise 0,8 zurückgibt, wird erwartet, dass der Toleranzbereich in 30 Sekunden 0,8 erreicht (bei einer Entfernung von 0,2 von einer starken Drosselung) und 1,0. Wenn die Zeit unter dem erforderlichen Zeitaufwand zum Ausführen der Arbeitslast liegt, sollte Ihr Spiel die Arbeitslast auf ein tragfähiges Niveau reduzieren. Das Spiel kann beispielsweise die Framerate oder die Grafikqualität reduzieren oder die Arbeit an der Netzwerkverbindung reduzieren.
Temperaturstatus und Bedeutung
- Wenn das Gerät nicht thermisch gedrosselt wird:
- Etwas Drosselung, aber keine nennenswerten Auswirkungen auf die Leistung:
- Erhebliche Drosselung, die sich auf die Leistung auswirkt:
Geräteeinschränkungen der Thermal API
Aufgrund von Implementierungen der Thermal API auf älteren Geräten gibt es einige bekannte Einschränkungen oder zusätzliche Anforderungen für die Thermal API. Es gibt folgende Einschränkungen und wie Sie sie umgehen können:
- Rufe die
GetThermalHeadroom()
API nicht zu häufig auf. Andernfalls gibt die API NaN zurück. Sie sollte maximal einmal pro Sekunde aufgerufen werden. - Wenn der Anfangswert von
GetThermalHeadroom()
NaN ist, ist die API auf dem Gerät nicht verfügbar. - Wenn
GetThermalHeadroom()
einen hohen Wert zurückgibt (z.B.0,85 oder höher) undGetCurrentThermalStatus()
immer nochTHERMAL_STATUS_NONE
zurückgibt, wird der Status wahrscheinlich nicht aktualisiert. Verwenden Sie die Heuristik, um den korrekten Status der Drosselung der Energiezufuhr zu schätzen, oder verwenden Sie einfachgetThermalHeadroom()
ohnegetCurrentThermalStatus()
.
Beispiel für Heuristik:
- Prüfen Sie, ob die Thermal API unterstützt wird.
isAPISupported()
prüft den Wert des ersten Aufrufs vongetThermalHeadroom
, um sicherzustellen, dass er nicht 0 oder NaN ist. Wenn der erste Wert entweder 0 oder NaN ist, wird er mit der API übersprungen. - Wenn
getCurrentThermalStatus()
einen anderen Wert alsTHERMAL_STATUS_NONE
zurückgibt, wird das Gerät thermisch gedrosselt. - Wenn
getCurrentThermalStatus()
weiterhinTHERMAL_STATUS_NONE
zurückgibt, bedeutet dies nicht zwangsläufig, dass das Gerät nicht thermisch gedrosselt wird. Möglicherweise wirdgetCurrentThermalStatus()
auf dem Gerät nicht unterstützt. Prüfen Sie den Rückgabewert vongetThermalHeadroom()
, um den Zustand des Geräts sicherzustellen. - Wenn
getThermalHeadroom()
einen Wert von > 1,0 zurückgibt, könnte der Status tatsächlichTHERMAL_STATUS_SEVERE
oder höher sein, die Arbeitslast sofort reduzieren und eine geringere Arbeitslast beibehalten, bisgetThermalHeadroom()
einen niedrigeren Wert zurückgibt - Wenn
getThermalHeadroom()
einen Wert von 0,95 zurückgibt, könnte der Status tatsächlichTHERMAL_STATUS_MODERATE
oder höher sein, die Arbeitslast sofort reduzieren und die Überwachung beibehalten, um höhere Lesevorgänge zu verhindern - Wenn
getThermalHeadroom()
einen Wert von 0, 85 zurückgibt, könnte der Status tatsächlichTHERMAL_STATUS_LIGHT
sein. Behalten Sie das Watchout bei und reduzieren Sie die Arbeitslast nach Möglichkeit.
Pseudocode:
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.
}
}
}
Diagramm: