Lançamento:
Android 11 (nível 30 da API) - API Thermal
Android 12 (nível 31 da API) - API NDK
(Pré-lançamento) Android 15 (DP1) - getThermalHeadroomThresholds()
A performance em potencial do app é limitada pelo estado térmico do dispositivo, que pode variar de acordo com características como clima, uso recente e o design térmico do aparelho. Os dispositivos só podem manter um alto nível de performance por um período limitado antes de serem limitados termicamente. Um objetivo importante da implementação precisa ser atingir as metas de performance sem exceder as limitações térmicas. A API Thermal permite isso sem a necessidade de otimizações específicas do dispositivo. Além disso, ao depurar problemas de performance, é importante saber se o estado térmico do dispositivo está limitando a performance.
Os mecanismos de jogo geralmente têm parâmetros de performance relacionados ao tempo de execução que podem ajustar o tanto de recursos do dispositivo usados pelo mecanismo. Por exemplo, esses parâmetros podem definir o número de linhas de execução de worker, afinidade entre linha de execução e worker para núcleos grandes e pequenos, opções de fidelidade de GPU e resoluções de framebuffer. No Unity Engine, os desenvolvedores de jogos podem ajustar a carga de trabalho mudando as Configurações de qualidade usando o plug-in de desempenho adaptável. No Unreal Engine, use as Configurações de escalonamento para ajustar os níveis de qualidade dinamicamente.
Quando um dispositivo se aproxima de um estado térmico não seguro, o jogo pode evitar a limitação, reduzindo a carga de trabalho por esses parâmetros. Para evitar a limitação, monitore o estado térmico do dispositivo e ajuste de forma proativa a carga de trabalho do mecanismo de jogo. Depois que o dispositivo superaquece, a carga de trabalho precisa ficar abaixo do nível de performance sustentável para dissipar o calor. Depois que o headroom térmico diminui para níveis mais seguros, o jogo pode aumentar as configurações de qualidade novamente, mas é importante encontrar um nível de qualidade sustentável para um tempo de jogo ideal.
Para monitorar o estado térmico do dispositivo, pesquise o
método
getThermalHeadroom
. Esse método prevê por quanto tempo o dispositivo pode manter o nível de
performance atual sem superaquecimento. Se o tempo for menor que a quantidade
necessária para executar a carga de trabalho, o jogo vai precisar diminuir essa carga a um
nível sustentável. Por exemplo, o jogo pode mudar para núcleos menores, reduzir o
frame rate ou diminuir a fidelidade.
![Pré-integração da API Thermal do ADPF](https://developer.android.google.cn/static/games/optimize/adpf/images/adpf_thermal_pre-integration.png?authuser=7&hl=pt-br)
![API Thermal ADPF pós-integração](https://developer.android.google.cn/static/games/optimize/adpf/images/adpf_thermal_post-integration.png?authuser=7&hl=pt-br)
Adquirir o Thermal Manager
Para usar a API Thermal, primeiro você precisa adquirir o Thermal Manager.
C++
AThermalManager* thermal_manager = AThermal_acquireManager();
Java
PowerManager powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
Prever o headroom térmico x segundos à frente para ter mais controle
Você pode pedir ao sistema para prever a temperatura x segundos à frente com a carga de trabalho atual. Isso oferece um controle mais refinado e mais tempo para reagir, reduzindo a carga de trabalho para evitar que o estrangulamento térmico seja acionado.
O resultado varia de 0,0f (sem limitação, THERMAL_STATUS_NONE
) a 1,0f
(limitação alta, THERMAL_STATUS_SEVERE
).
Se você tiver diferentes níveis de qualidade gráfica nos jogos, siga nossas
diretrizes de margem térmica.
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);
Como alternativa, use o status térmico para esclarecimento
Cada modelo de dispositivo pode ser projetado de maneira diferente. Alguns dispositivos podem distribuir o calor melhor e, portanto, suportar uma margem térmica maior antes de serem limitados. Se você quiser ler um agrupamento simplificado de intervalos de margem térmica, verifique o status térmico para entender o valor da margem térmica no dispositivo atual.
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);
Receber notificações quando o status térmico mudar
Também é possível evitar a pesquisa da thermalHeadroom
até que a thermalStatus
atinja
um determinado nível (por exemplo, THERMAL_STATUS_LIGHT
).
Para isso, registre um callback para que o sistema notifique você sempre que o
status mudar.
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);
Não se esqueça de remover o listener quando terminar.
C++
int result = AThermal_unregisterThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
// failed, check whether the callback has been registered previously
}
Java
powerManager.removeThermalStatusListener(listener);
Limpeza
Quando terminar, você vai precisar limpar o thermal_manager que adquiriu. Se você estiver usando Java, a referência do PowerManager poderá ser coletada automaticamente. No entanto, se você estiver usando a API Java pelo JNI e tiver retido uma referência, lembre-se de limpá-la.
C++
AThermal_releaseManager(thermal_manager);
Para um guia completo sobre como implementar a API Thermal em um jogo C++ nativo usando a API C++ (API NDK) e a API Java (por meio do JNI), consulte a seção Integrar a API Thermal no codelab de adaptabilidade.
Diretrizes de margem térmica
Para monitorar o estado térmico do dispositivo, pesquise o
método
getThermalHeadroom
. Esse método prevê por quanto tempo o dispositivo pode manter o nível de
performance atual antes de atingir THERMAL_STATUS_SEVERE
.
Por exemplo, se getThermalHeadroom(30)
retornar 0,8, isso indica que em 30
segundos, o headroom deve chegar a 0,8, com uma distância de 0,2
do estrangulamento severo, ou 1,0. Se o tempo for menor que a quantidade necessária para
executar a carga de trabalho, o jogo vai precisar diminuir essa carga a um
nível sustentável. Por exemplo, o jogo pode reduzir a frame rate, diminuir a fidelidade ou
reduzir o trabalho de conectividade de rede.
Status térmicos e significado
- Se o dispositivo não estiver sob limitação térmica:
- Alguma limitação, mas sem impacto significativo na performance:
- Limitação significativa que afeta a performance:
Limitações de dispositivo da API Thermal
Há algumas limitações conhecidas ou requisitos adicionais da API Thermal devido às implementações da API Thermal em dispositivos mais antigos. As limitações e como contornar são as seguintes:
- Não chame a API
GetThermalHeadroom()
com muita frequência. Se você fizer isso, a API vai retornarNaN
. Não chame mais de uma vez a cada 10 segundos. - Evite chamar de várias linhas de execução. É mais difícil garantir a frequência
de chamadas, e isso pode fazer com que a API retorne
NaN
. - Se o valor inicial de
GetThermalHeadroom()
for NaN, a API não estará disponível no dispositivo. - Se
GetThermalHeadroom()
retornar um valor alto (por exemplo, 0,85 ou mais) eGetCurrentThermalStatus()
ainda retornarTHERMAL_STATUS_NONE
, é provável que o status não tenha sido atualizado. Use heurísticas para estimar o status correto de limitação térmica ou use apenasgetThermalHeadroom()
semgetCurrentThermalStatus()
.
Exemplo de heurísticas:
- Verifique se a API Thermal tem suporte.
isAPISupported()
verifica o valor da primeira chamada paragetThermalHeadroom
para garantir que ele não seja 0 ou NaN e pula o uso da API se o primeiro valor for 0 ou NaN. - Se
getCurrentThermalStatus()
retornar um valor diferente deTHERMAL_STATUS_NONE
, o dispositivo estará sendo limitado termicamente. - Se
getCurrentThermalStatus()
continuar retornandoTHERMAL_STATUS_NONE
, isso não significa necessariamente que o dispositivo não está sendo limitado termicamente. Isso pode significar que ogetCurrentThermalStatus()
não tem suporte para o dispositivo. Verifique o valor de retorno degetThermalHeadroom()
para garantir a condição do dispositivo. - Se
getThermalHeadroom()
retornar um valor de > 1,0, o status poderá serTHERMAL_STATUS_SEVERE
ou maior, reduzir a carga de trabalho imediatamente e manter a carga de trabalho mais baixa até quegetThermalHeadroom()
retorne um valor menor. - Se
getThermalHeadroom()
retornar um valor de 0, 95, o status poderá serTHERMAL_STATUS_MODERATE
ou maior. Reduza a carga de trabalho imediatamente e mantenha a observação para evitar leituras mais altas. - Se
getThermalHeadroom()
retornar um valor de 0, 85, o status poderá serTHERMAL_STATUS_LIGHT
. Fique atento e reduza a carga de trabalho se possível.
Pseudocódigo:
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.
}
}
}
Diagrama: