API Thermal

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.

Pre-integrazione dell'API Thermal ADPF
Figura 1. Margine termico senza monitorare attivamente getThermalHeadroom
.
. Post-integrazione dell'API Thermal ADPF
Figura 2. Margine termico con monitoraggio attivo di "getThermalHeadroom"

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

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ù) e GetCurrentThermalStatus() restituisce ancora THERMAL_STATUS_NONE, lo stato è probabilmente non verranno aggiornate. Usa l'euristica per stimare la limitazione termica corretta o usa semplicemente getThermalHeadroom() senza getCurrentThermalStatus().

Esempio di euristica:

  1. Verifica che l'API Thermal sia supportata. isAPISupported() controlla il valore di la prima chiamata a getThermalHeadroom per assicurarti che non sia 0 o NaN e ignora utilizzando l'API se il primo valore è 0 o NaN.
  2. Se getCurrentThermalStatus() restituisce un valore diverso da THERMAL_STATUS_NONE, il dispositivo è in fase di limitazione termica.
  3. Se getCurrentThermalStatus() continua a restituire THERMAL_STATUS_NONE, non significa necessariamente che il dispositivo non sia sottoposto a una limitazione termica. Potrebbe significa che getCurrentThermalStatus() non è supportato sul dispositivo. Controlla il valore restituito di getThermalHeadroom() per garantire la condizione di del dispositivo.
  4. Se getThermalHeadroom() restituisce il valore > 1.0, lo stato potrebbe essere THERMAL_STATUS_SEVERE o superiore, ridurre immediatamente il carico di lavoro mantieni un carico di lavoro inferiore finché getThermalHeadroom() non restituisce un valore inferiore
  5. Se getThermalHeadroom() restituisce un valore pari a 0,95, lo stato potrebbe essere THERMAL_STATUS_MODERATE o superiore, riduci subito il carico di lavoro e rimanere in guardia per evitare un aumento della lettura
  6. Se getThermalHeadroom() restituisce un valore pari a 0,85, lo stato potrebbe essere THERMAL_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:

Esempio euristico ADPF
Figura 3.Esempio di euristica per determinare il supporto delle API termiche su dispositivi meno recenti