Uscita:
Android 11 (livello API 30) - API termica
Android 12 (livello API 31) - API NDK
(Anteprima) Android 15 (DP1) - getThermalHeadroomThresholds()
Le prestazioni potenziali della tua app sono limitate dallo stato termico del dispositivo, che può variare in base a caratteristiche quali meteo, utilizzo recente, e dal design termico del dispositivo. I dispositivi possono mantenere solo un livello le prestazioni per un periodo di tempo limitato prima di essere limitate termicamente. Una chiave l'obiettivo dell'implementazione dovrebbe essere raggiungere gli obiettivi di rendimento senza superando i limiti termici. L'API Thermal rende possibile tutto questo senza bisogno per ottimizzazioni specifiche del dispositivo. Inoltre, quando esegui il debug delle prestazioni problemi, sapere se lo stato termico del dispositivo limita le prestazioni importanti.
Di solito i motori di gioco hanno parametri delle prestazioni di runtime che consentono di regolare carico di lavoro che il motore applica al dispositivo. Ad esempio, questi parametri possono impostare il numero di thread worker, l'affinità tra i thread di lavoro per i core grandi e piccoli, Opzioni di fedeltà GPU e risoluzioni framebuffer. In Unity Engine, gli sviluppatori possono regolare il carico di lavoro modificando la colonna Qualità Impostazioni usando il plug-in Adaptive Performance. Per Unreal Engine, utilizza le impostazioni di scalabilità per regolare i livelli qualitativi in modo dinamico.
Quando un dispositivo si avvicina a uno stato termico non sicuro, il gioco può evitare limitato diminuendo il carico di lavoro attraverso questi parametri. Da evitare è necessario monitorare lo stato termico del dispositivo e regolare il carico di lavoro del motore grafico. Se il dispositivo si surriscalda, il carico di lavoro deve scendere al di sotto del livello di prestazioni sostenibile per dissipare il calore. Dopo il giorno il margine termico si riduce a livelli più sicuri, il gioco può aumentare impostazioni qualitative, ma occorre assicurarsi di un livello qualitativo sostenibile per una riproduzione ottimale.
Puoi monitorare lo stato termico del dispositivo eseguendo il polling della
getThermalHeadroom
. Questo metodo prevede per quanto tempo il dispositivo può mantenere lo stato attuale
senza surriscaldarsi. Se il tempo è inferiore alla quantità di tempo
necessario per eseguire il carico di lavoro, il gioco dovrebbe ridurlo
livello sostenibile. Ad esempio, il gioco può passare a core più piccoli, ridurre
una frequenza fotogrammi
o una fedeltà inferiore.
Acquisisci il gestore termico
Per utilizzare l'API Thermal, devi prima acquisire Thermal Manager
C++
AThermalManager* thermal_manager = AThermal_acquireManager();
Java
PowerManager powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
Prevedi il margine termico x secondi per un maggiore controllo
Puoi chiedere al sistema di prevedere la temperatura x secondi in anticipo con il carico di lavoro attuale. In questo modo avrai un controllo più granulare e più tempo reagiscono riducendo il carico di lavoro per evitare l'attivazione della limitazione termica.
Il risultato va da 0.0f (nessuna limitazione, THERMAL_STATUS_NONE
) a 1.0f
(limitazione elevata, THERMAL_STATUS_SEVERE
).
Se hai diversi livelli di qualità grafica nei tuoi giochi, puoi seguire le nostre
Linee guida sul margine termico.
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);
In alternativa, fai affidamento sullo stato termico per chiarimenti
Ogni modello di dispositivo può essere progettato in modo diverso. Alcuni dispositivi potrebbero riuscire a distribuiscono meglio il calore e sono in grado di tollerare un margine termico più elevato prima di essere limitata. Se vuoi leggere un raggruppamento semplificato di intervalli di margine termico, puoi controllare lo stato termico per trovare un senso il valore di margine termico sul dispositivo corrente.
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);
Ricevi una notifica quando lo stato termico cambia
Puoi anche evitare di eseguire il polling di thermalHeadroom
fino all'attivazione di thermalStatus
di un determinato livello (ad esempio: THERMAL_STATUS_LIGHT
).
Per farlo, puoi registrare una richiamata per consentire al sistema di avvisarti ogni volta che
è cambiato.
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);
Al termine, ricordati di rimuovere il 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);
Pulizia
Al termine, dovrai eseguire la pulizia del gestore termico che hai acquisito. Se utilizzi Java, il riferimento di PowerManager può essere ignorato automaticamente raccolti per te. Ma se utilizzi l'API Java tramite JNI e disponi un riferimento, ricordati di ripulire il riferimento.
C++
AThermal_releaseManager(thermal_manager);
Per una guida completa su come implementare l'API Thermal in un gioco C++ nativo utilizzando sia l'API C++ (API NDK) che l'API Java (tramite JNI), consulta la integrazione Sezione relativa all'API Thermal nel codelab sull'adeguabilità .
Linee guida per il margine termico
Puoi monitorare lo stato termico del dispositivo eseguendo il polling della
getThermalHeadroom
. Questo metodo prevede per quanto tempo il dispositivo può mantenere lo stato attuale
di rendimento prima di raggiungere THERMAL_STATUS_SEVERE
.
Ad esempio, se getThermalHeadroom(30)
restituisce 0,8, indica che in 30
secondi, si prevede che l'headroom raggiungerà 0,8, dove c'è 0,2 di distanza
da una grave limitazione o 1, 0. Se il tempo è inferiore alla quantità necessaria per
il carico di lavoro, il gioco dovrebbe ridurlo
livello. Ad esempio, il gioco può ridurre la frequenza fotogrammi, la fedeltà inferiore o
il lavoro di connettività di rete.
Stati e significato termici
- Se il dispositivo non viene limitato termicamente:
- Alcune limitazioni, ma nessun impatto significativo sulle prestazioni:
- Limitazione significativa che influisce sulle prestazioni:
Limitazioni dell'API Thermal sui dispositivi
Esistono alcune limitazioni note o requisiti aggiuntivi dell'API Thermal, dovuti alle implementazioni dell'API termica su dispositivi meno recenti. Come e i limiti per aggirarli sono i seguenti:
- Non chiamare l'API
GetThermalHeadroom()
troppo spesso. In questo modo far sì che l'API restituisca NaN. Dovresti chiamarlo al massimo una volta al secondo. - Se il valore iniziale di
GetThermalHeadroom()
è NaN, l'API non è disponibile sul dispositivo - Se
GetThermalHeadroom()
restituisce un valore alto (ad es. 0,85 o più) eGetCurrentThermalStatus()
restituisce ancoraTHERMAL_STATUS_NONE
, lo stato è probabilmente non verranno aggiornate. Usa l'euristica per stimare la limitazione termica corretta o usa semplicementegetThermalHeadroom()
senzagetCurrentThermalStatus()
.
Esempio di euristica:
- Verifica che l'API Thermal sia supportata.
isAPISupported()
controlla il valore di la prima chiamata agetThermalHeadroom
per assicurarti che non sia 0 o NaN e ignora utilizzando l'API se il primo valore è 0 o NaN. - Se
getCurrentThermalStatus()
restituisce un valore diverso daTHERMAL_STATUS_NONE
, il dispositivo è in fase di limitazione termica. - Se
getCurrentThermalStatus()
continua a restituireTHERMAL_STATUS_NONE
, non significa necessariamente che il dispositivo non sia sottoposto a una limitazione termica. Potrebbe significa chegetCurrentThermalStatus()
non è supportato sul dispositivo. Controlla il valore restituito digetThermalHeadroom()
per garantire la condizione di del dispositivo. - Se
getThermalHeadroom()
restituisce il valore > 1.0, lo stato potrebbe essereTHERMAL_STATUS_SEVERE
o superiore, ridurre immediatamente il carico di lavoro mantieni un carico di lavoro inferiore finchégetThermalHeadroom()
non restituisce un valore inferiore - Se
getThermalHeadroom()
restituisce un valore pari a 0,95, lo stato potrebbe essereTHERMAL_STATUS_MODERATE
o superiore, riduci subito il carico di lavoro e rimanere in guardia per evitare un aumento della lettura - Se
getThermalHeadroom()
restituisce un valore pari a 0,85, lo stato potrebbe essereTHERMAL_STATUS_LIGHT
, rimanere in guardia e ridurre il carico di lavoro se possibile
Pseudocodice:
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.
}
}
}
Diagramma: