Veröffentlichung:
Android 11 (API-Level 30) – Thermal API
Android 12 (API-Level 31) – NDK API
(Vorabversion) Android 15 (DP1) – getThermalHeadroomThresholds()
Die potenzielle Leistung Ihrer App wird durch den thermischen Zustand des Geräts begrenzt. Dieser kann je nach Eigenschaften wie Wetter, letzter Nutzung und thermischem Design des Geräts variieren. Geräte können nur für eine begrenzte Zeit eine hohe Leistung aufrechterhalten, bevor sie aufgrund von Überhitzung gedrosselt werden. Ein wichtiges Ziel Ihrer Implementierung sollte es sein, die Leistungsziele zu erreichen, ohne die thermischen Einschränkungen zu überschreiten. Die Thermal API macht dies ohne gerätespezifische Optimierungen möglich. Außerdem ist es beim Beheben von Leistungsproblemen wichtig zu wissen, ob die Leistung durch den Temperaturstatus des Geräts eingeschränkt wird.
Spiele-Engines haben in der Regel Laufzeitleistungsparameter, mit denen sich die Arbeitslast der Engine auf dem Gerät anpassen lässt. 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 GPU-Fidelity-Optionen und die Framebufferauflösungen festlegen. In der Unity Engine können Spieleentwickler die Arbeitslast anpassen, indem sie die Qualitätseinstellungen mit dem Adaptive Performance-Plug-in ändern. In der Unreal Engine kannst du die Skalierungseinstellungen verwenden, um die Qualitätsstufen dynamisch anzupassen.
Wenn ein Gerät einen gefährlichen thermischen Zustand erreicht, kann Ihr Spiel durch Verringern der Arbeitslast über diese Parameter gedrosselt werden. Um das Drosseln zu vermeiden, sollten Sie den thermischen Zustand des Geräts überwachen und die Arbeitslast der Game-Engine proaktiv anpassen. Wenn das Gerät überhitzt, muss die Arbeitslast unter das nachhaltige Leistungsniveau sinken, damit die Wärme abgeleitet werden kann. Sobald der thermische Spielraum auf ein sichereres Niveau gesunken ist, kann das Spiel die Qualitätseinstellungen wieder erhöhen. Achten Sie jedoch darauf, ein nachhaltiges Qualitätsniveau für eine optimale Spielzeit zu finden.
Sie können den thermischen Zustand des Geräts überwachen, indem Sie die Methode getThermalHeadroom
abfragen. Mit dieser Methode wird vorhergesagt, wie lange das Gerät das aktuelle Leistungsniveau beibehalten kann, ohne sich zu überhitzen. Wenn die Zeit kürzer ist als die Zeit, die zum Ausführen der Arbeitslast erforderlich ist, sollte Ihr Spiel die Arbeitslast auf ein nachhaltiges Niveau senken. So kann das Spiel beispielsweise auf kleinere Kerne umstellen, die Framerate reduzieren oder die Wiedergabequalität senken.
![Vor der ADPF Thermal API-Integration](https://developer.android.google.cn/static/games/optimize/adpf/images/adpf_thermal_pre-integration.png?authuser=4&hl=de)
![ADPF Thermal API – Nach der Integration](https://developer.android.google.cn/static/games/optimize/adpf/images/adpf_thermal_post-integration.png?authuser=4&hl=de)
Thermal Manager erwerben
Wenn Sie die Thermal API verwenden 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);
Vorhersage des thermischen Spielraums für x Sekunden für mehr Kontrolle
Sie können das System bitten, die Temperatur mit der aktuellen Arbeitslast x Sekunden in die Zukunft vorherzusagen. So haben Sie eine genauere Kontrolle und mehr Zeit, um zu reagieren, indem Sie die Arbeitslast reduzieren, um zu verhindern, dass die thermische Drosselung aktiviert wird.
Das Ergebnis reicht von 0,0 f (keine Drosselung, THERMAL_STATUS_NONE
) bis 1,0 f (starke Drosselung, THERMAL_STATUS_SEVERE
).
Wenn Sie in Ihren Spielen unterschiedliche Grafikqualitätsstufen haben, können Sie unseren Richtlinien für den thermischen Spielraum 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 können Sie sich anhand des Temperaturstatus informieren.
Die Gerätemodelle können unterschiedlich gestaltet sein. Einige Geräte können die Wärme möglicherweise besser verteilen und so einen höheren thermischen Spielraum verkraften, bevor sie gedrosselt werden. Wenn Sie eine vereinfachte Gruppierung der Bereiche für den thermischen Spielraum sehen möchten, können Sie den thermischen Status prüfen, um den Wert für den thermischen Spielraum auf dem aktuellen Gerät zu verstehen.
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 Temperaturstatus ändert
Sie können auch verhindern, dass thermalHeadroom
abgefragt wird, bis thermalStatus
einen bestimmten Wert erreicht (z. B. THERMAL_STATUS_LIGHT
). Dazu können Sie einen Rückruf registrieren, damit Sie vom System benachrichtigt werden, 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
Wenn Sie fertig sind, müssen Sie den abgerufenen thermal_manager bereinigen. Wenn Sie Java verwenden, kann die PowerManager-Referenz automatisch für Sie vom Garbage Collector erfasst 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 zur Implementierung der Thermal API in einem nativen C++-Spiel mithilfe der C++ API (NDK API) und der Java API (über JNI) finden Sie im Abschnitt Thermal API integrieren im Codelab zur Anpassungsfähigkeit.
Richtlinien für den thermischen Spielraum
Sie können den thermischen Zustand des Geräts überwachen, indem Sie die Methode getThermalHeadroom
abfragen. Mit dieser Methode wird vorhergesagt, wie lange das Gerät die aktuelle Leistung aufrechterhalten kann, bevor THERMAL_STATUS_SEVERE
erreicht wird.
Wenn getThermalHeadroom(30)
beispielsweise 0,8 zurückgibt, bedeutet das, dass der Spielraum in 30 Sekunden voraussichtlich 0,8 erreicht, was 0,2 Punkte von einer starken Drosselung (1,0) entfernt ist. Wenn die Zeit kürzer ist als die Zeit, die zum Ausführen der Arbeitslast erforderlich ist, sollte Ihr Spiel die Arbeitslast auf ein nachhaltiges Niveau senken. Das Spiel kann beispielsweise die Framerate reduzieren, die Wiedergabequalität senken oder die Netzwerkverbindung optimieren.
Temperaturstatus und ihre Bedeutung
- Wenn das Gerät nicht thermisch gedrosselt wird:
- Es kommt zu einer gewissen Drosselung, aber es gibt keine erheblichen Auswirkungen auf die Leistung:
- Eine erhebliche Drosselung, die sich auf die Leistung auswirkt:
Geräteeinschränkungen der Thermal API
Aufgrund der Implementierung der Thermal API auf älteren Geräten gibt es einige bekannte Einschränkungen oder zusätzliche Anforderungen. Die Einschränkungen und ihre Umgehungsmöglichkeiten sind:
- Rufen Sie die
GetThermalHeadroom()
API nicht zu häufig auf. In diesem Fall gibt die APINaN
zurück. Sie sollten die Funktion nicht öfter als einmal alle 10 Sekunden aufrufen. - Vermeiden Sie Aufrufe aus mehreren Threads. Es ist schwieriger, die Aufrufhäufigkeit zu gewährleisten, und es kann dazu führen, dass die API
NaN
zurückgibt. - 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 mehr) undGetCurrentThermalStatus()
weiterhinTHERMAL_STATUS_NONE
zurückgibt, wird der Status wahrscheinlich nicht aktualisiert. Verwenden Sie Heuristiken, um den korrekten Status der thermischen Drosselung zu schätzen, oder verwenden Sie einfachgetThermalHeadroom()
ohnegetCurrentThermalStatus()
.
Beispiel für Heuristiken:
- 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 0 oder NaN ist, wird die API nicht verwendet. - Wenn
getCurrentThermalStatus()
einen anderen Wert alsTHERMAL_STATUS_NONE
zurückgibt, wird das Gerät thermisch gedrosselt. - Wenn
getCurrentThermalStatus()
immer wiederTHERMAL_STATUS_NONE
zurückgibt, bedeutet das nicht unbedingt, dass das Gerät nicht thermisch gedrosselt wird. Möglicherweise wirdgetCurrentThermalStatus()
auf dem Gerät nicht unterstützt. Prüfe den Rückgabewert vongetThermalHeadroom()
, um den Zustand des Geräts zu prüfen. - Wenn
getThermalHeadroom()
einen Wert von über 1,0 zurückgibt, könnte der Status tatsächlichTHERMAL_STATUS_SEVERE
oder höher sein. Reduzieren Sie die Arbeitslast sofort und halten Sie sie so niedrig, bisgetThermalHeadroom()
einen niedrigeren Wert zurückgibt. - Wenn
getThermalHeadroom()
den Wert 0,95 zurückgibt, könnte der Status tatsächlichTHERMAL_STATUS_MODERATE
oder höher sein. Reduzieren Sie die Arbeitslast sofort und achten Sie darauf, dass der Wert nicht noch höher wird. - Wenn
getThermalHeadroom()
den Wert 0, 85 zurückgibt, könnte der Status tatsächlichTHERMAL_STATUS_LIGHT
sein. Behalten Sie die Situation im Auge 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: