1 /*
2  * Copyright (C) 2018 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 #include "SensorsHidlEnvironmentV1_0.h"
18 
19 #include <log/log.h>
20 
21 #include <vector>
22 
23 using ::android::hardware::hidl_vec;
24 using ::android::hardware::sensors::V1_0::ISensors;
25 using ::android::hardware::sensors::V1_0::Result;
26 using ::android::hardware::sensors::V1_0::SensorInfo;
27 
HidlTearDown()28 void SensorsHidlEnvironmentV1_0::HidlTearDown() {
29     mStopThread = true;
30     if (mPollThread.joinable()) {
31         mPollThread.detach();
32     }
33 }
34 
resetHal()35 bool SensorsHidlEnvironmentV1_0::resetHal() {
36     // wait upto 100ms * 10 = 1s for hidl service.
37     constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
38 
39     std::string step;
40     bool succeed = false;
41     for (size_t retry = 10; retry > 0; --retry) {
42         // this do ... while is for easy error handling
43         do {
44             step = "getService()";
45             sensors = ISensors::getService(mServiceName);
46             if (sensors == nullptr) {
47                 break;
48             }
49 
50             step = "poll() check";
51             // Poke ISensor service. If it has lingering connection from previous generation of
52             // system server, it will kill itself. There is no intention to handle the poll result,
53             // which will be done since the size is 0.
54             if (!sensors->poll(0, [](auto, const auto&, const auto&) {}).isOk()) {
55                 break;
56             }
57 
58             step = "getSensorList";
59             std::vector<SensorInfo> sensorList;
60             if (!sensors
61                      ->getSensorsList([&](const hidl_vec<SensorInfo>& list) {
62                          sensorList.reserve(list.size());
63                          for (size_t i = 0; i < list.size(); ++i) {
64                              sensorList.push_back(list[i]);
65                          }
66                      })
67                      .isOk()) {
68                 break;
69             }
70 
71             // stop each sensor individually
72             step = "stop each sensor";
73             bool ok = true;
74             for (const auto& i : sensorList) {
75                 if (!sensors->activate(i.sensorHandle, false).isOk()) {
76                     ok = false;
77                     break;
78                 }
79             }
80             if (!ok) {
81                 break;
82             }
83 
84             // mark it done
85             step = "done";
86             succeed = true;
87         } while (0);
88 
89         if (succeed) {
90             return true;
91         }
92 
93         // Delay 100ms before retry, hidl service is expected to come up in short time after crash.
94         ALOGI("%s unsuccessful, try again soon (remaining retry %zu).", step.c_str(), retry - 1);
95         std::this_thread::sleep_for(RETRY_DELAY);
96     }
97 
98     sensors = nullptr;
99     return false;
100 }
101 
startPollingThread()102 void SensorsHidlEnvironmentV1_0::startPollingThread() {
103     mStopThread = false;
104     mPollThread = std::thread(pollingThread, this, std::ref(mStopThread));
105     mEvents.reserve(128);
106 }
107 
pollingThread(SensorsHidlEnvironmentV1_0 * env,std::atomic_bool & stop)108 void SensorsHidlEnvironmentV1_0::pollingThread(SensorsHidlEnvironmentV1_0* env,
109                                                std::atomic_bool& stop) {
110     ALOGD("polling thread start");
111 
112     while (!stop) {
113         if (!env->sensors
114                      ->poll(64,
115                             [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
116                                 if (result != Result::OK ||
117                                     (events.size() == 0 && dynamicSensorsAdded.size() == 0) ||
118                                     stop) {
119                                     stop = true;
120                                     return;
121                                 }
122 
123                                 for (const auto& e : events) {
124                                     env->addEvent(e);
125                                 }
126                             })
127                      .isOk()) {
128             break;
129         }
130     }
131     ALOGD("polling thread end");
132 }