Ngày phát hành:
Android 11 (API cấp 30) – Thermal API
Android 12 (API cấp 31) – NDK API
(Bản dùng thử) Android 15 (DP1) – getThermalHeadroomThresholds()
Hiệu suất tiềm năng của ứng dụng bị giới hạn bởi trạng thái nhiệt của thiết bị. Trạng thái nhiệt có thể thay đổi tuỳ theo các yếu tố đặc thù như thời tiết, mức sử dụng gần đây và thiết kế tản nhiệt của thiết bị. Các thiết bị chỉ có thể duy trì hiệu suất cao trong một khoảng thời gian giới hạn trước khi bị điều tiết nhiệt. Mục tiêu chính của việc triển khai là đạt được mục tiêu về hiệu suất mà không bị vượt quá giới hạn nhiệt. Thermal API giúp bạn thực hiện việc này mà không cần tối ưu hoá cho từng thiết bị. Ngoài ra, khi gỡ lỗi các vấn đề về hiệu suất, điều quan trọng là bạn phải biết liệu trạng thái nhiệt của thiết bị có đang giới hạn hiệu suất hay không.
Các công cụ phát triển trò chơi thường có các thông số hiệu suất trong thời gian chạy giúp điều chỉnh mức tải mà công cụ phân cho thiết bị. Ví dụ: các thông số này có thể thiết lập số lượng luồng công việc, chỉ định luồng công việc cho các nhân xử lý lớn và nhỏ, các tuỳ chọn về độ trung thực của GPU cũng như độ phân giải bộ đệm khung. Trong Unity Engine, nhà phát triển trò chơi có thể điều chỉnh khối lượng công việc bằng cách thay đổi Cài đặt chất lượng bằng trình bổ trợ Adaptive Performance. Đối với Unreal Engine, hãy dùng Scalability Settings (Chế độ cài đặt khả năng mở rộng) để điều chỉnh các cấp độ chất lượng một cách linh hoạt.
Khi thiết bị đạt đến trạng thái nhiệt không an toàn, trò chơi có thể tránh bị điều tiết bằng cách giảm mức tải thông qua các thông số này. Để tránh việc bị điều tiết, bạn nên theo dõi trạng thái nhiệt của thiết bị và chủ động điều chỉnh mức tải của công cụ phát triển trò chơi.
Khi thiết bị quá nóng, mức tải phải giảm xuống dưới mức hiệu suất ổn định để phân tán nhiệt. Sau khi khoảng không nhiệt giảm xuống mức an toàn hơn, trò chơi có thể tăng lại chế độ cài đặt chất lượng nhưng hãy nhớ tìm ra mức chất lượng bền vững để có thời gian chơi tối ưu.
Bạn có thể theo dõi trạng thái nhiệt của thiết bị bằng cách thăm dò phương thức getThermalHeadroom. Phương thức này dự đoán khoảng thời gian thiết bị có thể duy trì mức hiệu suất hiện tại mà không quá nhiệt. Nếu khoảng thời gian này ít hơn thời gian cần thiết để chạy mức tải, thì trò chơi sẽ giảm mức tải xuống một mức ổn định. Ví dụ: trò chơi có thể chuyển sang các nhân xử lý nhỏ hơn, giảm tốc độ khung hình hoặc giảm độ trung thực.
Tải Thermal Manager
Để sử dụng Thermal API, trước tiên, bạn cần phải có Thermal Manager
C++
AThermalManager* thermal_manager = AThermal_acquireManager();
Java
PowerManager powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
Dự đoán khoảng trống nhiệt trong x giây tới để có thêm quyền kiểm soát
Bạn có thể yêu cầu hệ thống dự báo nhiệt độ trong x giây tới với khối lượng công việc hiện tại. Điều này giúp bạn kiểm soát chi tiết hơn và có thêm thời gian phản ứng bằng cách giảm khối lượng công việc để ngăn tình trạng điều tiết nhiệt xảy ra.
Kết quả nằm trong khoảng từ 0,0f (không điều tiết, THERMAL_STATUS_NONE)
đến 1.0f (giảm hiệu suất đáng kể, THERMAL_STATUS_SEVERE). Nếu có nhiều cấp độ chất lượng đồ hoạ trong trò chơi, bạn có thể làm theo Nguyên tắc về khoảng trống nhiệt của chúng tôi.
C++
float thermal_headroom = AThermal_getThermalHeadroom(0);
ALOGI("ThermalHeadroom: %f", thermal_headroom);
Java
float thermalHeadroom = powerManager.getThermalHeadroom(0);
Log.d("ADPF", "ThermalHeadroom: " + thermalHeadroom);
Ngoài ra, hãy dựa vào trạng thái nhiệt để làm rõ
Mỗi mẫu thiết bị có thể được thiết kế theo cách khác nhau. Một số thiết bị có thể phân tán nhiệt tốt hơn và do đó có thể chịu được khoảng không nhiệt cao hơn trước khi bị điều tiết. Nếu muốn đọc một nhóm đơn giản gồm các dải khoảng không nhiệt, bạn có thể kiểm tra trạng thái nhiệt để hiểu giá trị khoảng không nhiệt trên thiết bị hiện tại.
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);
Nhận thông báo khi trạng thái nhiệt thay đổi
Bạn cũng có thể tránh thăm dò thermalHeadroom cho đến khi thermalStatus đạt đến một mức nhất định (ví dụ: THERMAL_STATUS_LIGHT). Để làm như vậy, bạn có thể đăng ký một lệnh gọi lại để hệ thống thông báo cho bạn bất cứ khi nào trạng thái thay đổi.
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);
Hãy nhớ xoá trình nghe khi hoàn tất
C++
int result = AThermal_unregisterThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
// failed, check whether the callback has been registered previously
}
Java
powerManager.removeThermalStatusListener(listener);
Dọn dẹp
Sau khi hoàn tất, bạn cần dọn dẹp thermal_manager mà bạn đã thu được. Nếu đang sử dụng Java, thì bạn có thể tự động thu thập rác tham chiếu PowerManager. Nhưng nếu bạn đang sử dụng Java API thông qua JNI và đã giữ lại một lượt tham chiếu, hãy nhớ dọn dẹp lượt tham chiếu đó!
C++
AThermal_releaseManager(thermal_manager);
Để xem hướng dẫn đầy đủ về cách triển khai Thermal API trên một trò chơi C++ gốc bằng cả API C++ (NDK API) và API Java (thông qua JNI), hãy xem phần Tích hợp Thermal API trong phần Lớp học lập trình về khả năng thích ứng.
Nguyên tắc về khoảng trống nhiệt
Bạn có thể theo dõi trạng thái nhiệt của thiết bị bằng cách thăm dò phương thức getThermalHeadroom. Phương thức này dự đoán khoảng thời gian thiết bị có thể duy trì mức hiệu suất hiện tại trước khi đạt đến THERMAL_STATUS_SEVERE.
Ví dụ: nếu getThermalHeadroom(30) trả về 0,8, thì điều này cho biết trong 30 giây, khoảng trống dự kiến sẽ đạt 0,8, tức là còn cách 0,2 nữa là đến mức điều tiết nghiêm trọng (1,0). Nếu khoảng thời gian này ít hơn thời gian cần thiết để chạy mức tải, thì trò chơi sẽ giảm mức tải xuống một mức ổn định. Ví dụ: trò chơi có thể giảm tốc độ khung hình, giảm độ trung thực hoặc giảm mức sử dụng kết nối mạng.
Ý nghĩa và trạng thái nhiệt
- Nếu thiết bị không bị điều tiết nhiệt:
- Đôi khi có điều tiết, nhưng không ảnh hưởng đáng kể đến hiệu suất:
- Điều tiết đáng kể, ảnh hưởng đến hiệu suất:
Các hạn chế về thiết bị của Thermal API
Có một số hạn chế đã biết hoặc yêu cầu bổ sung của Thermal API, do việc triển khai Thermal API trên các thiết bị cũ. Sau đây là các hạn chế và cách khắc phục:
- Đừng gọi API
GetThermalHeadroom()quá thường xuyên. Nếu bạn làm như vậy, API sẽ trả vềNaN. Bạn không nên gọi phương thức này nhiều hơn một lần sau mỗi 10 giây. - Tránh gọi từ nhiều luồng, khó đảm bảo tần suất gọi và có thể khiến API trả về
NaN. - Nếu giá trị ban đầu của
GetThermalHeadroom()là NaN, thì API sẽ không có sẵn trên thiết bị - Nếu
GetThermalHeadroom()trả về một giá trị cao (ví dụ: 0,85 trở lên) vàGetCurrentThermalStatus()vẫn trả vềTHERMAL_STATUS_NONE, thì có thể trạng thái chưa được cập nhật. Sử dụng phương pháp phỏng đoán để ước tính trạng thái điều tiết nhiệt chính xác hoặc chỉ sử dụnggetThermalHeadroom()mà không cógetCurrentThermalStatus().
Ví dụ về suy nghiệm:
- Kiểm tra để đảm bảo Thermal API được hỗ trợ.
isAPISupported()kiểm tra giá trị của lệnh gọi đầu tiên đếngetThermalHeadroomđể đảm bảo giá trị đó không phải là 0 hoặc NaN và bỏ qua việc sử dụng API nếu giá trị đầu tiên là 0 hoặc NaN. - Nếu
getCurrentThermalStatus()trả về một giá trị khác vớiTHERMAL_STATUS_NONE, thì thiết bị đang bị điều tiết nhiệt. - Nếu
getCurrentThermalStatus()liên tục trả vềTHERMAL_STATUS_NONE, thì điều đó không nhất thiết có nghĩa là thiết bị không bị điều tiết nhiệt. Điều này có thể có nghĩa là thiết bị không hỗ trợgetCurrentThermalStatus(). Kiểm tra giá trị trả về củagetThermalHeadroom()để đảm bảo tình trạng của thiết bị. - Nếu
getThermalHeadroom()trả về giá trị > 1.0, thì trạng thái thực tế có thể làTHERMAL_STATUS_SEVEREtrở lên, hãy giảm ngay khối lượng công việc và duy trì khối lượng công việc thấp hơn cho đến khigetThermalHeadroom()trả về giá trị thấp hơn - Nếu
getThermalHeadroom()trả về giá trị 0,95, thì trạng thái thực tế có thể làTHERMAL_STATUS_MODERATEtrở lên, hãy giảm ngay khối lượng công việc và tiếp tục theo dõi để tránh chỉ số cao hơn - Nếu
getThermalHeadroom()trả về giá trị 0,85, thì trạng thái thực tế có thể làTHERMAL_STATUS_LIGHT, hãy tiếp tục theo dõi và giảm tải nếu có thể
Mã giả:
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.
}
}
}
Sơ đồ: