1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "thermal"
18 
19 #include <android-base/thread_annotations.h>
20 #include <android/os/BnThermalStatusListener.h>
21 #include <android/os/IThermalService.h>
22 #include <android/thermal.h>
23 #include <binder/IServiceManager.h>
24 #include <thermal_private.h>
25 #include <utils/Log.h>
26 
27 #include <cerrno>
28 #include <limits>
29 #include <thread>
30 
31 using android::sp;
32 
33 using namespace android;
34 using namespace android::os;
35 
36 struct ThermalServiceListener : public BnThermalStatusListener {
37 public:
38     virtual binder::Status onStatusChange(int32_t status) override;
ThermalServiceListenerThermalServiceListener39     ThermalServiceListener(AThermalManager *manager) {
40         mMgr = manager;
41     }
42 
43 private:
44     AThermalManager *mMgr;
45 };
46 
47 struct ListenerCallback {
48     AThermal_StatusCallback callback;
49     void* data;
50 };
51 
52 static IThermalService *gIThermalServiceForTesting = nullptr;
53 
54 struct AThermalManager {
55 public:
56     static AThermalManager *createAThermalManager();
57     AThermalManager() = delete;
58     ~AThermalManager();
59     status_t notifyStateChange(int32_t status);
60     status_t getCurrentThermalStatus(int32_t *status);
61     status_t addListener(AThermal_StatusCallback, void *data);
62     status_t removeListener(AThermal_StatusCallback, void *data);
63     status_t getThermalHeadroom(int32_t forecastSeconds, float *result);
64     status_t getThermalHeadroomThresholds(const AThermalHeadroomThreshold **, size_t *size);
65 
66 private:
67     AThermalManager(sp<IThermalService> service);
68     sp<IThermalService> mThermalSvc;
69     std::mutex mListenerMutex;
70     sp<ThermalServiceListener> mServiceListener GUARDED_BY(mListenerMutex);
71     std::vector<ListenerCallback> mListeners GUARDED_BY(mListenerMutex);
72     std::mutex mThresholdsMutex;
73     const AThermalHeadroomThreshold *mThresholds = nullptr; // GUARDED_BY(mThresholdsMutex)
74     size_t mThresholdsCount GUARDED_BY(mThresholdsMutex);
75 };
76 
onStatusChange(int32_t status)77 binder::Status ThermalServiceListener::onStatusChange(int32_t status) {
78     if (mMgr != nullptr) {
79         mMgr->notifyStateChange(status);
80     }
81     return binder::Status::ok();
82 }
83 
createAThermalManager()84 AThermalManager* AThermalManager::createAThermalManager() {
85     if (gIThermalServiceForTesting) {
86         return new AThermalManager(gIThermalServiceForTesting);
87     }
88     sp<IBinder> binder =
89             defaultServiceManager()->checkService(String16("thermalservice"));
90 
91     if (binder == nullptr) {
92         ALOGE("%s: Thermal service is not ready ", __FUNCTION__);
93         return nullptr;
94     }
95     return new AThermalManager(interface_cast<IThermalService>(binder));
96 }
97 
AThermalManager(sp<IThermalService> service)98 AThermalManager::AThermalManager(sp<IThermalService> service)
99       : mThermalSvc(std::move(service)), mServiceListener(nullptr) {}
100 
~AThermalManager()101 AThermalManager::~AThermalManager() {
102     std::unique_lock<std::mutex> listenerLock(mListenerMutex);
103 
104     mListeners.clear();
105     if (mServiceListener != nullptr) {
106         bool success = false;
107         mThermalSvc->unregisterThermalStatusListener(mServiceListener, &success);
108         mServiceListener = nullptr;
109     }
110     listenerLock.unlock();
111     std::unique_lock<std::mutex> lock(mThresholdsMutex);
112     delete[] mThresholds;
113 }
114 
notifyStateChange(int32_t status)115 status_t AThermalManager::notifyStateChange(int32_t status) {
116     std::unique_lock<std::mutex> lock(mListenerMutex);
117     AThermalStatus thermalStatus = static_cast<AThermalStatus>(status);
118 
119     for (auto listener : mListeners) {
120         listener.callback(listener.data, thermalStatus);
121     }
122     return OK;
123 }
124 
addListener(AThermal_StatusCallback callback,void * data)125 status_t AThermalManager::addListener(AThermal_StatusCallback callback, void *data) {
126     std::unique_lock<std::mutex> lock(mListenerMutex);
127 
128     if (callback == nullptr) {
129         // Callback can not be nullptr
130         return EINVAL;
131     }
132     for (const auto& cb : mListeners) {
133         // Don't re-add callbacks.
134         if (callback == cb.callback && data == cb.data) {
135             return EINVAL;
136         }
137     }
138     mListeners.emplace_back(ListenerCallback{callback, data});
139 
140     if (mServiceListener != nullptr) {
141         return OK;
142     }
143     bool success = false;
144     mServiceListener = new ThermalServiceListener(this);
145     if (mServiceListener == nullptr) {
146         return ENOMEM;
147     }
148     auto ret = mThermalSvc->registerThermalStatusListener(mServiceListener, &success);
149     if (!success || !ret.isOk()) {
150         ALOGE("Failed in registerThermalStatusListener %d", success);
151         if (ret.exceptionCode() == binder::Status::EX_SECURITY) {
152             return EPERM;
153         }
154         return EPIPE;
155     }
156     return OK;
157 }
158 
removeListener(AThermal_StatusCallback callback,void * data)159 status_t AThermalManager::removeListener(AThermal_StatusCallback callback, void *data) {
160     std::unique_lock<std::mutex> lock(mListenerMutex);
161 
162     auto it = std::remove_if(mListeners.begin(),
163                              mListeners.end(),
164                              [&](const ListenerCallback& cb) {
165                                     return callback == cb.callback &&
166                                            data == cb.data;
167                              });
168     if (it == mListeners.end()) {
169         // If the listener and data pointer were not previously added.
170         return EINVAL;
171     }
172     mListeners.erase(it, mListeners.end());
173 
174     if (!mListeners.empty()) {
175         return OK;
176     }
177     if (mServiceListener == nullptr) {
178         return OK;
179     }
180     bool success = false;
181     auto ret = mThermalSvc->unregisterThermalStatusListener(mServiceListener, &success);
182     if (!success || !ret.isOk()) {
183         ALOGE("Failed in unregisterThermalStatusListener %d", success);
184         if (ret.exceptionCode() == binder::Status::EX_SECURITY) {
185             return EPERM;
186         }
187         return EPIPE;
188     }
189     mServiceListener = nullptr;
190     return OK;
191 }
192 
getCurrentThermalStatus(int32_t * status)193 status_t AThermalManager::getCurrentThermalStatus(int32_t *status) {
194     binder::Status ret = mThermalSvc->getCurrentThermalStatus(status);
195 
196     if (!ret.isOk()) {
197         if (ret.exceptionCode() == binder::Status::EX_SECURITY) {
198             return EPERM;
199         }
200         return EPIPE;
201     }
202     return OK;
203 }
204 
getThermalHeadroom(int32_t forecastSeconds,float * result)205 status_t AThermalManager::getThermalHeadroom(int32_t forecastSeconds, float *result) {
206     binder::Status ret = mThermalSvc->getThermalHeadroom(forecastSeconds, result);
207 
208     if (!ret.isOk()) {
209         if (ret.exceptionCode() == binder::Status::EX_SECURITY) {
210             return EPERM;
211         }
212         return EPIPE;
213     }
214     return OK;
215 }
216 
getThermalHeadroomThresholds(const AThermalHeadroomThreshold ** result,size_t * size)217 status_t AThermalManager::getThermalHeadroomThresholds(const AThermalHeadroomThreshold **result,
218                                                        size_t *size) {
219     std::unique_lock<std::mutex> lock(mThresholdsMutex);
220     if (mThresholds == nullptr) {
221         auto thresholds = std::make_unique<std::vector<float>>();
222         binder::Status ret = mThermalSvc->getThermalHeadroomThresholds(thresholds.get());
223         if (!ret.isOk()) {
224             if (ret.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
225                 // feature is not enabled
226                 return ENOSYS;
227             }
228             return EPIPE;
229         }
230         mThresholdsCount = thresholds->size();
231         auto t = new AThermalHeadroomThreshold[mThresholdsCount];
232         for (int i = 0; i < (int)mThresholdsCount; i++) {
233             t[i].headroom = (*thresholds)[i];
234             t[i].thermalStatus = static_cast<AThermalStatus>(i);
235         }
236         mThresholds = t;
237     }
238     *size = mThresholdsCount;
239     *result = mThresholds;
240     return OK;
241 }
242 
243 /**
244   * Acquire an instance of the thermal manager. This must be freed using
245   * {@link AThermal_releaseManager}.
246   *
247   * @return manager instance on success, nullptr on failure.
248  */
AThermal_acquireManager()249 AThermalManager* AThermal_acquireManager() {
250     auto manager = AThermalManager::createAThermalManager();
251 
252     return manager;
253 }
254 
255 /**
256  * Release the thermal manager pointer acquired by
257  * {@link AThermal_acquireManager}.
258  *
259  * @param manager The manager to be released.
260  *
261  */
AThermal_releaseManager(AThermalManager * manager)262 void AThermal_releaseManager(AThermalManager *manager) {
263     delete manager;
264 }
265 
266 /**
267   * Gets the current thermal status.
268   *
269   * @param manager The manager instance to use to query the thermal status,
270   * acquired by {@link AThermal_acquireManager}.
271   *
272   * @return current thermal status, ATHERMAL_STATUS_ERROR on failure.
273 */
AThermal_getCurrentThermalStatus(AThermalManager * manager)274 AThermalStatus AThermal_getCurrentThermalStatus(AThermalManager *manager) {
275     int32_t status = 0;
276     status_t ret = manager->getCurrentThermalStatus(&status);
277     if (ret != OK) {
278         return AThermalStatus::ATHERMAL_STATUS_ERROR;
279     }
280     return static_cast<AThermalStatus>(status);
281 }
282 
283 /**
284  * Register the thermal status listener for thermal status change.
285  *
286  * @param manager The manager instance to use to register.
287  * acquired by {@link AThermal_acquireManager}.
288  * @param callback The callback function to be called when thermal status updated.
289  * @param data The data pointer to be passed when callback is called.
290  *
291  * @return 0 on success
292  *         EINVAL if the listener and data pointer were previously added and not removed.
293  *         EPERM if the required permission is not held.
294  *         EPIPE if communication with the system service has failed.
295  */
AThermal_registerThermalStatusListener(AThermalManager * manager,AThermal_StatusCallback callback,void * data)296 int AThermal_registerThermalStatusListener(AThermalManager *manager,
297         AThermal_StatusCallback callback, void *data) {
298     return manager->addListener(callback, data);
299 }
300 
301 /**
302  * Unregister the thermal status listener previously resgistered.
303  *
304  * @param manager The manager instance to use to unregister.
305  * acquired by {@link AThermal_acquireManager}.
306  * @param callback The callback function to be called when thermal status updated.
307  * @param data The data pointer to be passed when callback is called.
308  *
309  * @return 0 on success
310  *         EINVAL if the listener and data pointer were not previously added.
311  *         EPERM if the required permission is not held.
312  *         EPIPE if communication with the system service has failed.
313  */
AThermal_unregisterThermalStatusListener(AThermalManager * manager,AThermal_StatusCallback callback,void * data)314 int AThermal_unregisterThermalStatusListener(AThermalManager *manager,
315         AThermal_StatusCallback callback, void *data) {
316     return manager->removeListener(callback, data);
317 }
318 
319 /**
320  * Provides an estimate of how much thermal headroom the device currently has
321  * before hitting severe throttling.
322  *
323  * Note that this only attempts to track the headroom of slow-moving sensors,
324  * such as the skin temperature sensor. This means that there is no benefit to
325  * calling this function more frequently than about once per second, and attempts
326  * to call significantly more frequently may result in the function returning {@code NaN}.
327  *
328  * See also PowerManager#getThermalHeadroom.
329  *
330  * @param manager The manager instance to use
331  * @param forecastSeconds how many seconds in the future to forecast
332  * @return a value greater than or equal to 0.0 where 1.0 indicates the SEVERE throttling
333  *  	   threshold. Returns NaN if the device does not support this functionality or if
334  * 	       this function is called significantly faster than once per second.
335  */
AThermal_getThermalHeadroom(AThermalManager * manager,int forecastSeconds)336 float AThermal_getThermalHeadroom(AThermalManager *manager, int forecastSeconds) {
337     float result = 0.0f;
338     status_t ret = manager->getThermalHeadroom(forecastSeconds, &result);
339     if (ret != OK) {
340         result = std::numeric_limits<float>::quiet_NaN();
341     }
342     return result;
343 }
344 
AThermal_getThermalHeadroomThresholds(AThermalManager * manager,const AThermalHeadroomThreshold ** outThresholds,size_t * size)345 int AThermal_getThermalHeadroomThresholds(AThermalManager *manager,
346                                           const AThermalHeadroomThreshold **outThresholds,
347                                           size_t *size) {
348     if (outThresholds == nullptr || *outThresholds != nullptr || size == nullptr) {
349         return EINVAL;
350     }
351     return manager->getThermalHeadroomThresholds(outThresholds, size);
352 }
353 
AThermal_setIThermalServiceForTesting(void * iThermalService)354 void AThermal_setIThermalServiceForTesting(void *iThermalService) {
355     gIThermalServiceForTesting = static_cast<IThermalService *>(iThermalService);
356 }
357