blob: d8bde8354c79b03a1919c2883180dc1355fa6703 [file] [log] [blame]
Anthony Stangea689f8a2019-07-30 11:35:48 -04001/*
2 * Copyright (C) 2019 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 "HalProxy.h"
18
19#include <android/hardware/sensors/2.0/types.h>
20
Stan Rokita28790672019-08-20 14:32:15 -070021#include <dlfcn.h>
22
23#include <fstream>
24#include <functional>
25
Anthony Stangea689f8a2019-07-30 11:35:48 -040026namespace android {
27namespace hardware {
28namespace sensors {
29namespace V2_0 {
30namespace implementation {
31
Stan Rokita28790672019-08-20 14:32:15 -070032typedef ISensorsSubHal*(SensorsHalGetSubHalFunc)(uint32_t*);
33
Anthony Stangea689f8a2019-07-30 11:35:48 -040034// TODO: Use this wake lock name as the prefix to all sensors HAL wake locks acquired.
35// constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP";
36
37// TODO: Use the following class as a starting point for implementing the full HalProxyCallback
38// along with being inspiration for how to implement the ScopedWakelock class.
39/**
40 * Callback class used to provide the HalProxy with the index of which subHal is invoking
41 */
42class SensorsCallbackProxy : public ISensorsCallback {
43 public:
44 SensorsCallbackProxy(wp<HalProxy>& halProxy, int32_t subHalIndex)
45 : mHalProxy(halProxy), mSubHalIndex(subHalIndex) {}
46
47 Return<void> onDynamicSensorsConnected(
48 const hidl_vec<SensorInfo>& dynamicSensorsAdded) override {
49 sp<HalProxy> halProxy(mHalProxy.promote());
50 if (halProxy != nullptr) {
51 return halProxy->onDynamicSensorsConnected(dynamicSensorsAdded, mSubHalIndex);
52 }
53 return Return<void>();
54 }
55
56 Return<void> onDynamicSensorsDisconnected(
57 const hidl_vec<int32_t>& dynamicSensorHandlesRemoved) override {
58 sp<HalProxy> halProxy(mHalProxy.promote());
59 if (halProxy != nullptr) {
60 return halProxy->onDynamicSensorsDisconnected(dynamicSensorHandlesRemoved,
61 mSubHalIndex);
62 }
63 return Return<void>();
64 }
65
66 private:
67 wp<HalProxy>& mHalProxy;
68 int32_t mSubHalIndex;
69};
70
71HalProxy::HalProxy() {
Stan Rokita28790672019-08-20 14:32:15 -070072 const char* kMultiHalConfigFilePath = "/vendor/etc/sensors/hals.conf";
Stan Rokitadc7a8e72019-08-23 12:35:40 -070073 initializeSubHalListFromConfigFile(kMultiHalConfigFilePath);
74 initializeSensorList();
Anthony Stangea689f8a2019-07-30 11:35:48 -040075}
76
Anthony Stangeaacbf942019-08-30 15:21:34 -040077HalProxy::HalProxy(std::vector<ISensorsSubHal*>& subHalList) : mSubHalList(subHalList) {
Stan Rokitadc7a8e72019-08-23 12:35:40 -070078 initializeSensorList();
Anthony Stangeaacbf942019-08-30 15:21:34 -040079}
80
Anthony Stangea689f8a2019-07-30 11:35:48 -040081HalProxy::~HalProxy() {
82 // TODO: Join any running threads and clean up FMQs and any other allocated
83 // state.
84}
85
Stan Rokitadc7a8e72019-08-23 12:35:40 -070086Return<void> HalProxy::getSensorsList(getSensorsList_cb _hidl_cb) {
87 _hidl_cb(mSensorList);
Anthony Stangea689f8a2019-07-30 11:35:48 -040088 return Void();
89}
90
91Return<Result> HalProxy::setOperationMode(OperationMode /* mode */) {
92 // TODO: Proxy API call to all sub-HALs and return appropriate result.
93 return Result::INVALID_OPERATION;
94}
95
Stan Rokita4b4c7b72019-09-10 15:07:59 -070096Return<Result> HalProxy::activate(int32_t sensorHandle, bool enabled) {
97 return getSubHalForSensorHandle(sensorHandle)
98 ->activate(zeroOutFirstByte(sensorHandle), enabled);
Anthony Stangea689f8a2019-07-30 11:35:48 -040099}
100
101Return<Result> HalProxy::initialize(
102 const ::android::hardware::MQDescriptorSync<Event>& eventQueueDescriptor,
103 const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
104 const sp<ISensorsCallback>& sensorsCallback) {
105 Result result = Result::OK;
106
107 // TODO: clean up sensor requests, if not already done elsewhere through a death recipient, and
108 // clean up any other resources that exist (FMQs, flags, threads, etc.)
109
110 mDynamicSensorsCallback = sensorsCallback;
111
112 // Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions.
113 mEventQueue =
114 std::make_unique<EventMessageQueue>(eventQueueDescriptor, true /* resetPointers */);
115
116 // Create the EventFlag that is used to signal to the framework that sensor events have been
117 // written to the Event FMQ
118 if (EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag) != OK) {
119 result = Result::BAD_VALUE;
120 }
121
122 // Create the Wake Lock FMQ that is used by the framework to communicate whenever WAKE_UP
123 // events have been successfully read and handled by the framework.
124 mWakeLockQueue =
125 std::make_unique<WakeLockMessageQueue>(wakeLockDescriptor, true /* resetPointers */);
126
127 if (!mDynamicSensorsCallback || !mEventQueue || !mWakeLockQueue || mEventQueueFlag == nullptr) {
128 result = Result::BAD_VALUE;
129 }
130
131 // TODO: start threads to read wake locks and process events from sub HALs.
132
133 return result;
134}
135
Stan Rokita4b4c7b72019-09-10 15:07:59 -0700136Return<Result> HalProxy::batch(int32_t sensorHandle, int64_t samplingPeriodNs,
137 int64_t maxReportLatencyNs) {
138 return getSubHalForSensorHandle(sensorHandle)
139 ->batch(zeroOutFirstByte(sensorHandle), samplingPeriodNs, maxReportLatencyNs);
Anthony Stangea689f8a2019-07-30 11:35:48 -0400140}
141
Stan Rokita4b4c7b72019-09-10 15:07:59 -0700142Return<Result> HalProxy::flush(int32_t sensorHandle) {
143 return getSubHalForSensorHandle(sensorHandle)->flush(zeroOutFirstByte(sensorHandle));
Anthony Stangea689f8a2019-07-30 11:35:48 -0400144}
145
146Return<Result> HalProxy::injectSensorData(const Event& /* event */) {
147 // TODO: Proxy API call to appropriate sub-HAL.
148 return Result::INVALID_OPERATION;
149}
150
151Return<void> HalProxy::registerDirectChannel(const SharedMemInfo& /* mem */,
152 registerDirectChannel_cb _hidl_cb) {
153 // TODO: During init, discover the first sub-HAL in the config that has sensors with direct
154 // channel support, if any, and proxy the API call there.
155 _hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */);
156 return Return<void>();
157}
158
159Return<Result> HalProxy::unregisterDirectChannel(int32_t /* channelHandle */) {
160 // TODO: During init, discover the first sub-HAL in the config that has sensors with direct
161 // channel support, if any, and proxy the API call there.
162 return Result::INVALID_OPERATION;
163}
164
165Return<void> HalProxy::configDirectReport(int32_t /* sensorHandle */, int32_t /* channelHandle */,
166 RateLevel /* rate */, configDirectReport_cb _hidl_cb) {
167 // TODO: During init, discover the first sub-HAL in the config that has sensors with direct
168 // channel support, if any, and proxy the API call there.
169 _hidl_cb(Result::INVALID_OPERATION, 0 /* reportToken */);
170 return Return<void>();
171}
172
173Return<void> HalProxy::debug(const hidl_handle& /* fd */, const hidl_vec<hidl_string>& /* args */) {
174 // TODO: output debug information
175 return Return<void>();
176}
177
178Return<void> HalProxy::onDynamicSensorsConnected(
179 const hidl_vec<SensorInfo>& /* dynamicSensorsAdded */, int32_t /* subHalIndex */) {
180 // TODO: Map the SensorInfo to the global list and then invoke the framework's callback.
181 return Return<void>();
182}
183
184Return<void> HalProxy::onDynamicSensorsDisconnected(
185 const hidl_vec<int32_t>& /* dynamicSensorHandlesRemoved */, int32_t /* subHalIndex */) {
186 // TODO: Unmap the SensorInfo from the global list and then invoke the framework's callback.
187 return Return<void>();
188}
189
Stan Rokitadc7a8e72019-08-23 12:35:40 -0700190void HalProxy::initializeSubHalListFromConfigFile(const char* configFileName) {
191 std::ifstream subHalConfigStream(configFileName);
192 if (!subHalConfigStream) {
193 LOG_FATAL("Failed to load subHal config file: %s", configFileName);
194 } else {
195 std::string subHalLibraryFile;
196 while (subHalConfigStream >> subHalLibraryFile) {
197 void* handle = dlopen(subHalLibraryFile.c_str(), RTLD_NOW);
198 if (handle == nullptr) {
199 LOG_FATAL("dlopen failed for library: %s", subHalLibraryFile.c_str());
200 } else {
201 SensorsHalGetSubHalFunc* sensorsHalGetSubHalPtr =
202 (SensorsHalGetSubHalFunc*)dlsym(handle, "sensorsHalGetSubHal");
203 if (sensorsHalGetSubHalPtr == nullptr) {
204 LOG_FATAL("Failed to locate sensorsHalGetSubHal function for library: %s",
205 subHalLibraryFile.c_str());
206 } else {
207 std::function<SensorsHalGetSubHalFunc> sensorsHalGetSubHal =
208 *sensorsHalGetSubHalPtr;
209 uint32_t version;
210 ISensorsSubHal* subHal = sensorsHalGetSubHal(&version);
211 if (version != SUB_HAL_2_0_VERSION) {
212 LOG_FATAL("SubHal version was not 2.0 for library: %s",
213 subHalLibraryFile.c_str());
214 } else {
215 ALOGV("Loaded SubHal from library: %s", subHalLibraryFile.c_str());
216 mSubHalList.push_back(subHal);
217 }
218 }
219 }
220 }
221 }
222}
223
224void HalProxy::initializeSensorList() {
225 for (size_t subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) {
226 ISensorsSubHal* subHal = mSubHalList[subHalIndex];
227 auto result = subHal->getSensorsList([&](const auto& list) {
228 for (SensorInfo sensor : list) {
229 if ((sensor.sensorHandle & 0xFF000000) != 0) {
230 ALOGE("SubHal sensorHandle's first byte was not 0");
231 } else {
232 ALOGV("Loaded sensor: %s", sensor.name.c_str());
233 sensor.sensorHandle |= (subHalIndex << 24);
234 mSensorList.push_back(sensor);
235 }
236 }
237 });
238 if (!result.isOk()) {
239 ALOGE("getSensorsList call failed for SubHal: %s", subHal->getName().c_str());
240 }
241 }
242}
243
Stan Rokita16385312019-09-10 14:54:36 -0700244ISensorsSubHal* HalProxy::getSubHalForSensorHandle(uint32_t sensorHandle) {
245 return mSubHalList[static_cast<size_t>(sensorHandle >> 24)];
246}
247
248uint32_t HalProxy::zeroOutFirstByte(uint32_t num) {
249 return num & 0x00FFFFFF;
250}
251
Anthony Stangea689f8a2019-07-30 11:35:48 -0400252} // namespace implementation
253} // namespace V2_0
254} // namespace sensors
255} // namespace hardware
256} // namespace android