출시됨:
Android 11 (API 수준 30) - 열 API
Android 12 (API 수준 31) - NDK API
(미리보기) Android 15 (DP1) - getThermalHeadroomThresholds()
앱은 기기의 열 상태에 따라 잠재적으로 성능이 제한되며, 기기의 열 상태는 날씨, 최근 사용량, 기기의 열 관련 설계와 같은 특성에 따라 달라질 수 있습니다. 기기는 온도로 인해 성능이 제한되기 전에 제한된 시간 동안만 높은 수준의 성능을 유지할 수 있습니다. 구현의 주요 목표는 열 제한을 초과하지 않고 성능 목표를 달성하는 것입니다. 열 API를 사용하면 기기별 최적화가 필요하지 않습니다. 또한 성능 문제를 디버그할 때는 기기의 열 상태가 성능을 제한하는지 파악하는 것이 중요합니다.
게임 엔진에는 일반적으로 엔진이 기기에 부여하는 워크로드를 조정할 수 있는 런타임 성능 매개변수가 있습니다. 예를 들어, 이러한 매개변수는 작업자 스레드 수, 큰 코어와 작은 코어의 작업자 스레드 어피니티, GPU 충실도 옵션, 프레임 버퍼 해상도를 설정할 수 있습니다. Unity 엔진에서 게임 개발자는 적응형 성능 플러그인을 사용하여 품질 설정을 변경하여 워크로드를 조정할 수 있습니다. Unreal Engine의 경우 확장성 설정을 사용하여 품질 수준을 동적으로 조정합니다.
기기가 안전하지 않은 열 상태에 도달하면 게임은 이러한 매개변수를 통해 워크로드를 줄여 성능이 제한되는 상황을 피할 수 있습니다. 제한 상황을 피하려면 기기의 열 상태를 모니터링하고 게임 엔진 워크로드를 미리 조정해야 합니다.
기기가 일단 과열되면 열을 방출하기 위해 워크로드가 지속 가능한 성능 수준 아래로 떨어져야 합니다. 열 여유가 더 안전한 수준으로 감소한 후 게임은 품질 설정을 다시 높일 수 있지만 최적의 플레이 시간을 위해 지속 가능한 품질 수준을 찾아야 합니다.
getThermalHeadroom 메서드를 폴링하여 기기의 열 상태를 모니터링할 수 있습니다. 이 메서드는 기기가 과열되지 않고 얼마나 오랫동안 현재 성능 수준을 유지할 수 있는지를 예측합니다. 시간이 워크로드를 실행하는 데 필요한 시간보다 적으면 게임에서 지속 가능한 수준으로 워크로드를 줄여야 합니다. 예를 들어 게임은 더 작은 코어로 전환하거나 프레임 속도를 낮추거나 충실도를 낮출 수 있습니다.
Thermal Manager 획득
열 API를 사용하려면 먼저 열 관리자를 획득해야 합니다.
C++
AThermalManager* thermal_manager = AThermal_acquireManager();
자바
PowerManager powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
더 나은 제어를 위해 x초 후의 열 여유 공간 예측
현재 워크로드로 x초 후의 온도를 예측하도록 시스템에 요청할 수 있습니다. 이를 통해 더 세밀하게 제어할 수 있으며, 열 제한이 시작되지 않도록 워크로드를 줄여 반응할 시간을 더 확보할 수 있습니다.
결과는 0.0f (제한 없음, THERMAL_STATUS_NONE)에서
1.0f (심한 스로틀링, THERMAL_STATUS_SEVERE)로 설정합니다. 게임에 다양한 그래픽 품질 수준이 있는 경우 열 여유 공간 가이드라인을 따르세요.
C++
float thermal_headroom = AThermal_getThermalHeadroom(0);
ALOGI("ThermalHeadroom: %f", thermal_headroom);
자바
float thermalHeadroom = powerManager.getThermalHeadroom(0);
Log.d("ADPF", "ThermalHeadroom: " + thermalHeadroom);
또는 열 상태를 사용하여 명확히 함
기기 모델마다 설계가 다를 수 있습니다. 일부 기기는 열을 더 잘 분산할 수 있으므로 제한되기 전에 더 높은 열 여유를 견딜 수 있습니다. 열 헤드룸 범위의 간소화된 그룹을 읽으려면 열 상태를 확인하여 현재 기기의 열 헤드룸 값을 파악하면 됩니다.
C++
AThermalStatus thermal_status = AThermal_getCurrentThermalStatus(thermal_manager);
ALOGI("ThermalStatus is: %d", thermal_status);
자바
int thermalStatus = powerManager.getCurrentThermalStatus();
Log.d("ADPF", "ThermalStatus is: " + thermalStatus);
열 상태가 변경될 때 알림 받기
thermalStatus이 특정 수준 (예: THERMAL_STATUS_LIGHT)에 도달할 때까지 thermalHeadroom를 폴링하지 않아도 됩니다. 이렇게 하려면 상태가 변경될 때마다 시스템에서 알림을 보내도록 콜백을 등록하면 됩니다.
C++
int result = AThermal_registerThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
// failed, check whether you have previously registered callback that
// hasn’t been unregistered
}
자바
// 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);
완료되면 리스너를 삭제해야 합니다.
C++
int result = AThermal_unregisterThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
// failed, check whether the callback has been registered previously
}
자바
powerManager.removeThermalStatusListener(listener);
정리
완료되면 획득한 thermal_manager를 정리해야 합니다. Java를 사용하는 경우 PowerManager 참조가 자동으로 가비지 컬렉션될 수 있습니다. 하지만 JNI를 통해 Java API를 사용하고 참조를 유지한 경우 참조를 정리해야 합니다.
C++
AThermal_releaseManager(thermal_manager);
C++ API (NDK API)와 Java API (JNI를 통해)를 모두 사용하여 네이티브 C++ 게임에 Thermal API를 구현하는 방법에 관한 전체 가이드는 적응성 Codelab 섹션의 Thermal API 통합 섹션을 참고하세요.
열 헤드룸 가이드라인
getThermalHeadroom 메서드를 폴링하여 기기의 열 상태를 모니터링할 수 있습니다. 이 메서드는 기기가 THERMAL_STATUS_SEVERE에 도달하기 전에 현재 성능 수준을 얼마나 오랫동안 유지할 수 있는지 예측합니다.
예를 들어 getThermalHeadroom(30)가 0.8을 반환하면 30초 후에 헤드룸이 0.8에 도달할 것으로 예상되며, 이는 심각한 제한(1.0)에서 0.2만큼 떨어진 거리입니다. 시간이 워크로드를 실행하는 데 필요한 시간보다 적으면 게임에서 지속 가능한 수준으로 워크로드를 줄여야 합니다. 예를 들어 게임은 프레임 속도를 줄이거나, 충실도를 낮추거나, 네트워크 연결 작업을 줄일 수 있습니다.
열 상태 및 의미
- 기기가 열 제한되지 않는 경우 다음을 실행합니다.
- 일부 제한이 있지만 성능에 큰 영향은 없는 경우:
- 성능에 영향을 미치는 심각한 제한이 있는 경우:
Thermal API의 기기 제한사항
이전 기기에서 Thermal API를 구현했기 때문에 Thermal API에는 알려진 제한사항이나 추가 요구사항이 있습니다. 제한사항과 이를 해결하는 방법은 다음과 같습니다.
GetThermalHeadroom()API를 너무 자주 호출하지 마세요. 이렇게 하면 API가NaN를 반환합니다. 10초에 한 번 이상 호출하면 안 됩니다.- 여러 스레드에서 호출하지 마세요. 호출 빈도를 보장하기가 더 어려워지고 API가
NaN를 반환할 수 있습니다. GetThermalHeadroom()의 초기 값이 NaN이면 기기에서 API를 사용할 수 없습니다.GetThermalHeadroom()가 높은 값을 반환하고 (예: 0.85 이상)GetCurrentThermalStatus()이 여전히THERMAL_STATUS_NONE를 반환하는 경우 상태가 업데이트되지 않았을 수 있습니다. 휴리스틱을 사용하여 올바른 열 제한 상태를 추정하거나getCurrentThermalStatus()없이getThermalHeadroom()를 사용합니다.
휴리스틱 예:
- Thermal API가 지원되는지 확인합니다.
isAPISupported()는getThermalHeadroom의 첫 번째 호출 값을 확인하여 0 또는 NaN이 아닌지 확인하고 첫 번째 값이 0 또는 NaN인 경우 API 사용을 건너뜁니다. getCurrentThermalStatus()가THERMAL_STATUS_NONE이외의 값을 반환하면 기기가 열로 인해 제한되고 있는 것입니다.getCurrentThermalStatus()가 계속THERMAL_STATUS_NONE를 반환한다고 해서 기기가 열 제한되지 않는다는 의미는 아닙니다. 이는 기기에서getCurrentThermalStatus()이 지원되지 않음을 의미할 수 있습니다.getThermalHeadroom()의 반환 값을 확인하여 기기 상태를 확인합니다.getThermalHeadroom()가 1.0보다 큰 값을 반환하면 상태가 실제로THERMAL_STATUS_SEVERE이상일 수 있습니다.getThermalHeadroom()가 더 낮은 값을 반환할 때까지 워크로드를 즉시 줄이고 더 낮은 워크로드를 유지하세요.getThermalHeadroom()가 0.95 값을 반환하면 상태가 실제로THERMAL_STATUS_MODERATE이상일 수 있으므로 즉시 워크로드를 줄이고 더 높은 수치를 방지하기 위해 주의를 기울이세요.getThermalHeadroom()에서 0.85 값을 반환하는 경우 상태가 실제로THERMAL_STATUS_LIGHT일 수 있으므로 주의를 기울이고 가능한 경우 워크로드를 줄이세요.
의사코드:
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.
}
}
}
다이어그램: