blob: 45099b563466a031a0aa48c0d9a7ed696d23942e [file] [log] [blame]
Mike Lockwood07908322013-10-17 08:05:00 -07001/*
2 * Copyright (C) 2013 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 <hardware/sensors.h>
18#include <fcntl.h>
19#include <errno.h>
20#include <dirent.h>
21#include <math.h>
22#include <poll.h>
23#include <pthread.h>
24#include <linux/input.h>
25#include <cutils/atomic.h>
26#include <cutils/log.h>
27
28#include <vector>
29#include <map>
30
31#include <stdio.h>
32#include <dlfcn.h>
33
34// comment out to disable debug-level logging
35#define LOG_NDEBUG 0
36
37static const char* CONFIG_FILENAME = "/system/etc/sensors/hals.conf";
38static const char* LEGAL_SUBHAL_PATH_PREFIX = "/system/lib/hw/";
39static const int MAX_CONF_LINE_LENGTH = 1024;
40
41static pthread_mutex_t init_modules_mutex = PTHREAD_MUTEX_INITIALIZER;
42static pthread_mutex_t init_sensors_mutex = PTHREAD_MUTEX_INITIALIZER;
43
44/*
45 * Vector of sub modules, whose indexes are referred to ni this file as module_index.
46 */
47static std::vector<hw_module_t *> *sub_hw_modules = NULL;
48
49/*
50 * Comparable class that globally identifies a sensor, by module index and local handle.
51 * A module index is the module's index in sub_hw_modules.
52 * A local handle is the handle the sub-module assigns to a sensor.
53 */
54struct FullHandle {
55 int moduleIndex;
56 int localHandle;
57
58 bool operator<(const FullHandle &that) const {
59 if (moduleIndex < that.moduleIndex) {
60 return true;
61 }
62 if (moduleIndex > that.moduleIndex) {
63 return false;
64 }
65 return localHandle < that.localHandle;
66 }
67
68 bool operator=(const FullHandle &that) const {
69 return moduleIndex == that.moduleIndex && localHandle == that.localHandle;
70 }
71};
72
73std::map<int, FullHandle> global_to_full;
74std::map<FullHandle, int> full_to_global;
75int next_global_handle = 1;
76
77static int assign_global_handle(int module_index, int local_handle) {
78 ALOGD("assign_global_handle %d %d", module_index, local_handle);
79 int global_handle = next_global_handle++;
80 FullHandle *full_handle = new FullHandle();
81 full_handle->moduleIndex = module_index;
82 full_handle->localHandle = local_handle;
83 full_to_global[*full_handle] = global_handle;
84 global_to_full[global_handle] = *full_handle;
85 return global_handle;
86}
87
88static int get_local_handle(int global_handle) {
89 return global_to_full[global_handle].localHandle;
90}
91
92static int get_module_index(int global_handle) {
93 ALOGD("get_module_index %d", global_handle);
94 FullHandle f = global_to_full[global_handle];
95 ALOGD("FullHandle moduleIndex %d, localHandle %d", f.moduleIndex, f.localHandle);
96 return f.moduleIndex;
97}
98
99
100/*
101 * Cache of all sensors, with original handles replaced by global handles.
102 * This will be handled to get_sensors_list() callers.
103 */
104static struct sensor_t const* global_sensors_list = NULL;
105static int global_sensors_count = -1;
106
107/*
108 * Extends a sensors_poll_device_1 by including all the sub-module's devices.
109 */
110struct sensors_poll_context_t {
111 /*
112 * This is the device that SensorDevice.cpp uses to make API calls
113 * to the multihal, which fans them out to sub-HALs.
114 */
115 sensors_poll_device_1 proxy_device; // must be first
116
117 void addSubHwDevice(struct hw_device_t*);
118
119 int activate(int handle, int enabled);
120 int setDelay(int handle, int64_t ns);
121 int poll(sensors_event_t* data, int count);
122 int batch(int handle, int flags, int64_t period_ns, int64_t timeout);
123 int flush(int handle);
124 int close();
125
126 std::vector<hw_device_t*> sub_hw_devices;
127
128 sensors_poll_device_t* get_v0_device_by_handle(int global_handle);
129 sensors_poll_device_1_t* get_v1_device_by_handle(int global_handle);
130 int get_device_version_by_handle(int global_handle);
131};
132
133void sensors_poll_context_t::addSubHwDevice(struct hw_device_t* sub_hw_device) {
134 ALOGD("addSubHwDevice");
135 this->sub_hw_devices.push_back(sub_hw_device);
136}
137
138sensors_poll_device_t* sensors_poll_context_t::get_v0_device_by_handle(int handle) {
139 ALOGD("get_v0_device_by_handle(%d)", handle);
140 int sub_index = get_module_index(handle);
141 ALOGD("sub_index: %d", sub_index);
142 return (sensors_poll_device_t*) this->sub_hw_devices[sub_index];
143}
144
145sensors_poll_device_1_t* sensors_poll_context_t::get_v1_device_by_handle(int handle) {
146 int sub_index = get_module_index(handle);
147 return (sensors_poll_device_1_t*) this->sub_hw_devices[sub_index];
148}
149
150int sensors_poll_context_t::get_device_version_by_handle(int handle) {
151 sensors_poll_device_t* v0 = this->get_v0_device_by_handle(handle);
152 return v0->common.version;
153}
154
155int sensors_poll_context_t::activate(int handle, int enabled) {
156 ALOGD("activate");
157 sensors_poll_device_t* v0 = this->get_v0_device_by_handle(handle);
158 int retval = v0->activate(v0, get_local_handle(handle), enabled);
159 ALOGD("retval %d", retval);
160 return retval;
161}
162
163int sensors_poll_context_t::setDelay(int handle, int64_t ns) {
164 ALOGD("setDelay");
165 sensors_poll_device_t* v0 = this->get_v0_device_by_handle(handle);
166 int retval = v0->setDelay(v0, get_local_handle(handle), ns);
167 ALOGD("retval %d", retval);
168 return retval;
169}
170
171int sensors_poll_context_t::poll(sensors_event_t *data, int count) {
172 ALOGD("poll");
173
174 // This only gets the first device. Parallel polling of multiple devices is coming soon.
175 int sub_index = 0;
176 sensors_poll_device_t* v0 = (sensors_poll_device_t*) this->sub_hw_devices[sub_index];
177
178 ALOGD("poll's blocking read begins...");
179 int retval = v0->poll(v0, data, count);
180 ALOGD("...poll's blocking read ends");
181 ALOGD("rewriting %d sensor handles...", retval);
182 // A normal event's "sensor" field is a local handles. Convert it to a global handle.
183 // A meta-data event must have its sensor set to 0, but it has a nested event
184 // with a local handle that needs to be converted to a global handle.
185 FullHandle full_handle;
186 full_handle.moduleIndex = sub_index;
187 for (int i = 0; i < retval; i++) {
188 sensors_event_t *event = &data[i];
189 // If it's a metadata event, rewrite the inner payload, not the sensor field.
190 if (event->type == SENSOR_TYPE_META_DATA) {
191 full_handle.localHandle = event->meta_data.sensor;
192 event->meta_data.sensor = full_to_global[full_handle];
193 } else {
194 full_handle.localHandle = event->sensor;
195 event->sensor = full_to_global[full_handle];
196 }
197 }
198 return retval;
199}
200
201int sensors_poll_context_t::batch(int handle, int flags, int64_t period_ns, int64_t timeout) {
202 ALOGD("batch");
203 int retval = -EINVAL;
204 int version = this->get_device_version_by_handle(handle);
205 if (version >= SENSORS_DEVICE_API_VERSION_1_0) {
206 sensors_poll_device_1_t* v1 = this->get_v1_device_by_handle(handle);
207 retval = v1->batch(v1, get_local_handle(handle), flags, period_ns, timeout);
208 }
209 ALOGD("retval %d", retval);
210 return retval;
211}
212
213int sensors_poll_context_t::flush(int handle) {
214 ALOGD("flush");
215 int retval = -EINVAL;
216 int version = this->get_device_version_by_handle(handle);
217 if (version >= SENSORS_DEVICE_API_VERSION_1_0) {
218 sensors_poll_device_1_t* v1 = this->get_v1_device_by_handle(handle);
219 retval = v1->flush(v1, get_local_handle(handle));
220 }
221 ALOGD("retval %d", retval);
222 return retval;
223}
224
225int sensors_poll_context_t::close() {
226 ALOGD("close");
227 for (std::vector<hw_device_t*>::iterator it = this->sub_hw_devices.begin();
228 it != this->sub_hw_devices.end(); it++) {
229 hw_device_t* dev = *it;
230 int retval = dev->close(dev);
231 ALOGD("retval %d", retval);
232 }
233 return 0;
234}
235
236
237static int device__close(struct hw_device_t *dev) {
238 sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;
239 if (ctx != NULL) {
240 int retval = ctx->close();
241 delete ctx;
242 }
243 return 0;
244}
245
246static int device__activate(struct sensors_poll_device_t *dev, int handle,
247 int enabled) {
248 sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;
249 return ctx->activate(handle, enabled);
250}
251
252static int device__setDelay(struct sensors_poll_device_t *dev, int handle,
253 int64_t ns) {
254 sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;
255 return ctx->setDelay(handle, ns);
256}
257
258static int device__poll(struct sensors_poll_device_t *dev, sensors_event_t* data,
259 int count) {
260 sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;
261 return ctx->poll(data, count);
262}
263
264static int device__batch(struct sensors_poll_device_1 *dev, int handle,
265 int flags, int64_t period_ns, int64_t timeout) {
266 sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;
267 return ctx->batch(handle, flags, period_ns, timeout);
268}
269
270static int device__flush(struct sensors_poll_device_1 *dev, int handle) {
271 sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;
272 return ctx->flush(handle);
273}
274
275static int open_sensors(const struct hw_module_t* module, const char* name,
276 struct hw_device_t** device);
277
278static bool starts_with(const char* s, const char* prefix) {
279 if (s == NULL || prefix == NULL) {
280 return false;
281 }
282 size_t s_size = strlen(s);
283 size_t prefix_size = strlen(prefix);
284 return s_size >= prefix_size && strncmp(s, prefix, prefix_size) == 0;
285}
286
287/*
288 * Adds valid paths from the config file to the vector passed in.
289 * The vector must not be null.
290 */
291static void get_so_paths(std::vector<char*> *so_paths) {
292 FILE *conf_file = fopen(CONFIG_FILENAME, "r");
293 if (conf_file == NULL) {
294 ALOGD("No multihal config file found at %s", CONFIG_FILENAME);
295 return;
296 }
297 ALOGD("Multihal config file found at %s", CONFIG_FILENAME);
298 char *line = NULL;
299 size_t len = 0;
300 int line_count = 0;
301 while (getline(&line, &len, conf_file) != -1) {
302 // overwrite trailing eoln with null char
303 char* pch = strchr(line, '\n');
304 if (pch != NULL) {
305 *pch = '\0';
306 }
307 ALOGD("config file line #%d: '%s'", ++line_count, line);
308 char *real_path = realpath(line, NULL);
309 if (starts_with(real_path, LEGAL_SUBHAL_PATH_PREFIX)) {
310 ALOGD("accepting valid path '%s'", real_path);
311 char* compact_line = new char[strlen(real_path) + 1];
312 strcpy(compact_line, real_path);
313 so_paths->push_back(compact_line);
314 } else {
315 ALOGD("rejecting path '%s' because it does not start with '%s'",
316 real_path, LEGAL_SUBHAL_PATH_PREFIX);
317 }
318 free(real_path);
319 }
320 free(line);
321 fclose(conf_file);
322 ALOGD("hals.conf contained %d lines", line_count);
323}
324
325/*
326 * Ensures that the sub-module array is initialized.
327 * This can be first called from get_sensors_list or from open_sensors.
328 */
329static void lazy_init_modules() {
330 pthread_mutex_lock(&init_modules_mutex);
331 if (sub_hw_modules != NULL) {
332 pthread_mutex_unlock(&init_modules_mutex);
333 return;
334 }
335 std::vector<char*> *so_paths = new std::vector<char*>();
336 get_so_paths(so_paths);
337
338 // dlopen the module files and cache their module symbols in sub_hw_modules
339 sub_hw_modules = new std::vector<hw_module_t *>();
340 dlerror(); // clear any old errors
341 const char* sym = HAL_MODULE_INFO_SYM_AS_STR;
342 for (std::vector<char*>::iterator it = so_paths->begin(); it != so_paths->end(); it++) {
343 char* path = *it;
344 void* lib_handle = dlopen(path, RTLD_LAZY);
345 if (lib_handle == NULL) {
346 ALOGD("dlerror(): %s", dlerror());
347 } else {
348 ALOGD("hal lib was loaded: %s", path);
349 ALOGD("Opening symbol \"%s\"", sym);
350 // clear old errors
351 dlerror();
352 struct hw_module_t* module = (hw_module_t*) dlsym(lib_handle, sym);
353 const char* error;
354 if ((error = dlerror()) != NULL) {
355 ALOGD("Error calling dlsym: %s", error);
356 } else if (module == NULL) {
357 ALOGD("module == NULL");
358 } else {
359 ALOGD("OK, dlsym()'ed \"%s\"", sym);
360 sub_hw_modules->push_back(module);
361 }
362 }
363 }
364 pthread_mutex_unlock(&init_modules_mutex);
365}
366
367/*
368 * Lazy-initializes global_sensors_count, global_sensors_list, and module_sensor_handles.
369 */
370static void lazy_init_sensors_list() {
371 ALOGD("lazy_init_sensors_list");
372 pthread_mutex_lock(&init_sensors_mutex);
373 if (global_sensors_list != NULL) {
374 // already initialized
375 pthread_mutex_unlock(&init_sensors_mutex);
376 ALOGD("lazy_init_sensors_list - early return");
377 return;
378 }
379
380 ALOGD("lazy_init_sensors_list needs to do work");
381 lazy_init_modules();
382
383 // Count all the sensors, then allocate an array of blanks.
384 global_sensors_count = 0;
385 const struct sensor_t *subhal_sensors_list;
386 for (std::vector<hw_module_t*>::iterator it = sub_hw_modules->begin();
387 it != sub_hw_modules->end(); it++) {
388 struct sensors_module_t *module = (struct sensors_module_t*) *it;
389 global_sensors_count += module->get_sensors_list(module, &subhal_sensors_list);
390 ALOGD("increased global_sensors_count to %d", global_sensors_count);
391 }
392
393 // The global_sensors_list is full of consts.
394 // Manipulate this non-const list, and point the const one to it when we're done.
395 sensor_t* mutable_sensor_list = new sensor_t[global_sensors_count];
396
397 // index of the next sensor to set in mutable_sensor_list
398 int mutable_sensor_index = 0;
399 int module_index = 0;
400
401 for (std::vector<hw_module_t*>::iterator it = sub_hw_modules->begin();
402 it != sub_hw_modules->end(); it++) {
403 hw_module_t *hw_module = *it;
404 ALOGD("examine one module");
405 // Read the sub-module's sensor list.
406 struct sensors_module_t *module = (struct sensors_module_t*) hw_module;
407 int module_sensor_count = module->get_sensors_list(module, &subhal_sensors_list);
408 ALOGD("the module has %d sensors", module_sensor_count);
409
410 // Copy the HAL's sensor list into global_sensors_list,
411 // with the handle changed to be a global handle.
412 for (int i = 0; i < module_sensor_count; i++) {
413 ALOGD("examining one sensor");
414 const struct sensor_t *local_sensor = &subhal_sensors_list[i];
415 int local_handle = local_sensor->handle;
416 memcpy(&mutable_sensor_list[mutable_sensor_index], local_sensor,
417 sizeof(struct sensor_t));
418
419 // Overwrite the global version's handle with a global handle.
420 int global_handle = assign_global_handle(module_index, local_handle);
421
422 mutable_sensor_list[mutable_sensor_index].handle = global_handle;
423 ALOGD("module_index %d, local_handle %d, global_handle %d",
424 module_index, local_handle, global_handle);
425
426 mutable_sensor_index++;
427 }
428 module_index++;
429 }
430 // Set the const static global_sensors_list to the mutable one allocated by this function.
431 global_sensors_list = mutable_sensor_list;
432
433 pthread_mutex_unlock(&init_sensors_mutex);
434 ALOGD("end lazy_init_sensors_list");
435}
436
437static int module__get_sensors_list(struct sensors_module_t* module,
438 struct sensor_t const** list) {
439 ALOGD("module__get_sensors_list");
440 lazy_init_sensors_list();
441 *list = global_sensors_list;
442 return global_sensors_count;
443}
444
445static struct hw_module_methods_t sensors_module_methods = {
446 open : open_sensors
447};
448
449struct sensors_module_t HAL_MODULE_INFO_SYM = {
450 common :{
451 tag : HARDWARE_MODULE_TAG,
452 version_major : 1,
453 version_minor : 0,
454 id : SENSORS_HARDWARE_MODULE_ID,
455 name : "MultiHal Sensor Module",
456 author : "Google, Inc",
457 methods : &sensors_module_methods,
458 dso : NULL,
459 reserved : {0},
460 },
461 get_sensors_list : module__get_sensors_list
462};
463
464static int open_sensors(const struct hw_module_t* hw_module, const char* name,
465 struct hw_device_t** hw_device_out) {
466 ALOGD("open_sensors begin...");
467
468 lazy_init_modules();
469
470 // Create proxy device, to return later.
471 sensors_poll_context_t *dev = new sensors_poll_context_t();
472 memset(dev, 0, sizeof(sensors_poll_device_1_t));
473 dev->proxy_device.common.tag = HARDWARE_DEVICE_TAG;
474 dev->proxy_device.common.version = SENSORS_DEVICE_API_VERSION_1_0;
475 dev->proxy_device.common.module = const_cast<hw_module_t*>(hw_module);
476 dev->proxy_device.common.close = device__close;
477 dev->proxy_device.activate = device__activate;
478 dev->proxy_device.setDelay = device__setDelay;
479 dev->proxy_device.poll = device__poll;
480 dev->proxy_device.batch = device__batch;
481 dev->proxy_device.flush = device__flush;
482
483 // Open() the subhal modules. Remember their devices in a vector parallel to sub_hw_modules.
484 for (std::vector<hw_module_t*>::iterator it = sub_hw_modules->begin();
485 it != sub_hw_modules->end(); it++) {
486 sensors_module_t *sensors_module = (sensors_module_t*) *it;
487 struct hw_device_t* sub_hw_device;
488 int sub_open_result = sensors_module->common.methods->open(*it, name, &sub_hw_device);
489 dev->addSubHwDevice(sub_hw_device);
490 }
491
492 // Prepare the output param and return
493 *hw_device_out = &dev->proxy_device.common;
494 ALOGD("...open_sensors end");
495 return 0;
496}