출시일:
Android 11 (API 수준 30) - Thermal API
Android 12 (API 수준 31) - NDK API
(미리보기) Android 15 (DP1) - getThermalHeadroomThresholds()
앱은 기기의 열 상태에 따라 잠재적으로 성능이 제한되며, 기기의 열 상태는 날씨, 최근 사용량, 기기의 열 관련 설계와 같은 특성에 따라 달라질 수 있습니다. 기기는 열 제한 전에 제한된 시간 동안만 높은 수준의 성능을 유지할 수 있습니다. 구현의 주요 목표는 열 제한을 초과하지 않고 성능 목표를 달성하는 것입니다. Thermal API를 사용하면 기기별 최적화 없이도 이를 수행할 수 있습니다. 또한 성능 문제를 디버깅할 때는 기기의 열 상태가 성능을 제한하는지 아는 것이 중요합니다. 또한 성능 문제를 디버깅할 때는 기기의 열 상태가 성능을 제한하는지 아는 것이 중요합니다.
게임 엔진에는 일반적으로 엔진이 기기에 부여하는 워크로드를 조정할 수 있는 런타임 성능 매개변수가 있습니다. 예를 들어, 이러한 매개변수는 작업자 스레드 수, 큰 코어와 작은 코어의 작업자 스레드 어피니티, GPU 충실도 옵션, 프레임 버퍼 해상도를 설정할 수 있습니다. Unity Engine에서 게임 개발자는 적응형 성능 플러그인으로 품질 설정을 변경하여 워크로드를 조정할 수 있습니다. Unreal Engine의 경우 Scalability Settings를 사용하여 품질 수준을 동적으로 조정합니다.
기기가 안전하지 않은 열 상태에 도달하면 게임은 이러한 매개변수를 통해 워크로드를 줄여 성능이 제한되는 상황을 피할 수 있습니다. 제한 상황을 피하려면 기기의 열 상태를 모니터링하고 게임 엔진 워크로드를 미리 조정해야 합니다. 기기가 일단 과열되면 열을 방출하기 위해 워크로드가 지속 가능한 성능 수준 아래로 떨어져야 합니다. 열 헤드룸이 더 안전한 수준으로 감소하면 게임 품질 설정을 다시 높일 수 있지만 최적의 플레이 시간을 위해 지속 가능한 품질 수준을 찾아야 합니다.
getThermalHeadroom
메서드를 폴링하여 기기의 열 상태를 모니터링할 수 있습니다. 이 메서드는 기기가 과열되지 않고 얼마나 오랫동안 현재 성능 수준을 유지할 수 있는지 예측합니다. 시간이 워크로드를 실행하는 데 필요한 시간보다 적으면 게임에서 지속 가능한 수준으로 워크로드를 줄여야 합니다. 예를 들어 게임은 더 작은 코어로 전환하거나 프레임 속도를 낮추거나 충실도를 낮출 수 있습니다.
열 관리자 획득
Thermal API를 사용하려면 먼저 Thermal Manager를 획득해야 합니다.
C++
AThermalManager* thermal_manager = AThermal_acquireManager();
Java
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(10);
ALOGI("ThermalHeadroom in 10 sec: %f", thermal_headroom);
Java
float thermalHeadroom = powerManager.getThermalHeadroom(10);
Log.d("ADPF", "ThermalHeadroom in 10 sec: " + thermalHeadroom);
또는 명확한 설명을 위해 열 상태를 활용합니다.
각 기기 모델은 다르게 설계될 수 있습니다. 일부 기기는 열을 더 잘 분배할 수 있으므로 제한되기 전에 더 높은 열 헤드룸을 견딜 수 있습니다. 열 헤드룸 범위의 단순화된 그룹을 읽으려면 열 상태를 확인하여 현재 기기의 열 헤드룸 값을 파악하면 됩니다.
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);
열 상태가 변경되면 알림 받기
또한 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
}
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);
완료되면 리스너를 삭제해야 합니다.
C++
int result = AThermal_unregisterThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
// failed, check whether the callback has been registered previously
}
Java
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에 도달할 것으로 예상되며 심각한 제한에서 0.2 거리가 떨어져 있는 경우 1.0입니다. 시간이 워크로드를 실행하는 데 필요한 시간보다 짧은 경우 게임은 워크로드를 지속 가능한 수준으로 줄여야 합니다. 예를 들어 게임은 프레임 속도를 낮추거나 충실도를 낮추거나 네트워크 연결 작업을 줄일 수 있습니다.
열 상태 및 의미
- 기기가 열로 제한되지 않는 경우:
- 약간의 제한이 있지만 성능에 큰 영향을 미치지는 않습니다.
- 성능에 영향을 미치는 심각한 제한:
Thermal API의 기기 제한사항
이전 기기에 Thermal API를 구현했기 때문에 Thermal API에 몇 가지 알려진 제한사항이나 추가 요구사항이 있습니다. 제한사항과 해결 방법은 다음과 같습니다.
GetThermalHeadroom()
API를 너무 자주 호출하지 마세요. 이렇게 하면 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.
}
}
}
다이어그램: