blob: 36345f922882173a8d9197e2120028c2b37b0337 [file] [log] [blame]
Mike Lockwoodf8477622013-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 <cutils/atomic.h>
25
26#define LOG_NDEBUG 1
27#include <cutils/log.h>
28
29#include <vector>
30#include <map>
31
32#include <stdio.h>
33#include <dlfcn.h>
34#include <SensorEventQueue.h>
35
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// This mutex is shared by all queues
45static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;
46
47// Used to pause the multihal poll(). Broadcasted by sub-polling tasks if waiting_for_data.
48static pthread_cond_t data_available_cond = PTHREAD_COND_INITIALIZER;
49bool waiting_for_data = false;
50
51/*
52 * Vector of sub modules, whose indexes are referred to ni this file as module_index.
53 */
54static std::vector<hw_module_t *> *sub_hw_modules = NULL;
55
56/*
57 * Comparable class that globally identifies a sensor, by module index and local handle.
58 * A module index is the module's index in sub_hw_modules.
59 * A local handle is the handle the sub-module assigns to a sensor.
60 */
61struct FullHandle {
62 int moduleIndex;
63 int localHandle;
64
65 bool operator<(const FullHandle &that) const {
66 if (moduleIndex < that.moduleIndex) {
67 return true;
68 }
69 if (moduleIndex > that.moduleIndex) {
70 return false;
71 }
72 return localHandle < that.localHandle;
73 }
74
75 bool operator==(const FullHandle &that) const {
76 return moduleIndex == that.moduleIndex && localHandle == that.localHandle;
77 }
78};
79
80std::map<int, FullHandle> global_to_full;
81std::map<FullHandle, int> full_to_global;
82int next_global_handle = 1;
83
84static int assign_global_handle(int module_index, int local_handle) {
85 int global_handle = next_global_handle++;
86 FullHandle full_handle;
87 full_handle.moduleIndex = module_index;
88 full_handle.localHandle = local_handle;
89 full_to_global[full_handle] = global_handle;
90 global_to_full[global_handle] = full_handle;
91 return global_handle;
92}
93
94static int get_local_handle(int global_handle) {
95 return global_to_full[global_handle].localHandle;
96}
97
98static int get_module_index(int global_handle) {
99 FullHandle f = global_to_full[global_handle];
100 ALOGV("FullHandle for global_handle %d: moduleIndex %d, localHandle %d",
101 global_handle, f.moduleIndex, f.localHandle);
102 return f.moduleIndex;
103}
104
105static const int SENSOR_EVENT_QUEUE_CAPACITY = 20;
106
107struct TaskContext {
108 sensors_poll_device_t* device;
109 SensorEventQueue* queue;
110};
111
112void *writerTask(void* ptr) {
113 ALOGV("writerTask STARTS");
114 TaskContext* ctx = (TaskContext*)ptr;
115 sensors_poll_device_t* device = ctx->device;
116 SensorEventQueue* queue = ctx->queue;
117 sensors_event_t* buffer;
118 int eventsPolled;
119 while (1) {
120 pthread_mutex_lock(&queue_mutex);
121 if (queue->waitForSpace(&queue_mutex)) {
122 ALOGV("writerTask waited for space");
123 }
124 int bufferSize = queue->getWritableRegion(SENSOR_EVENT_QUEUE_CAPACITY, &buffer);
125 // Do blocking poll outside of lock
126 pthread_mutex_unlock(&queue_mutex);
127
128 ALOGV("writerTask before poll() - bufferSize = %d", bufferSize);
129 eventsPolled = device->poll(device, buffer, bufferSize);
130 ALOGV("writerTask poll() got %d events.", eventsPolled);
131 if (eventsPolled == 0) {
132 continue;
133 }
134 pthread_mutex_lock(&queue_mutex);
135 queue->markAsWritten(eventsPolled);
136 ALOGV("writerTask wrote %d events", eventsPolled);
137 if (waiting_for_data) {
138 ALOGV("writerTask - broadcast data_available_cond");
139 pthread_cond_broadcast(&data_available_cond);
140 }
141 pthread_mutex_unlock(&queue_mutex);
142 }
143 // never actually returns
144 return NULL;
145}
146
147/*
148 * Cache of all sensors, with original handles replaced by global handles.
149 * This will be handled to get_sensors_list() callers.
150 */
151static struct sensor_t const* global_sensors_list = NULL;
152static int global_sensors_count = -1;
153
154/*
155 * Extends a sensors_poll_device_1 by including all the sub-module's devices.
156 */
157struct sensors_poll_context_t {
158 /*
159 * This is the device that SensorDevice.cpp uses to make API calls
160 * to the multihal, which fans them out to sub-HALs.
161 */
162 sensors_poll_device_1 proxy_device; // must be first
163
164 void addSubHwDevice(struct hw_device_t*);
165
166 int activate(int handle, int enabled);
167 int setDelay(int handle, int64_t ns);
168 int poll(sensors_event_t* data, int count);
169 int batch(int handle, int flags, int64_t period_ns, int64_t timeout);
170 int flush(int handle);
171 int close();
172
173 std::vector<hw_device_t*> sub_hw_devices;
174 std::vector<SensorEventQueue*> queues;
175 std::vector<pthread_t> threads;
176 int nextReadIndex;
177
178 sensors_poll_device_t* get_v0_device_by_handle(int global_handle);
179 sensors_poll_device_1_t* get_v1_device_by_handle(int global_handle);
180 int get_device_version_by_handle(int global_handle);
181
182 void copy_event_remap_handle(sensors_event_t* src, sensors_event_t* dest, int sub_index);
183};
184
185void sensors_poll_context_t::addSubHwDevice(struct hw_device_t* sub_hw_device) {
186 ALOGV("addSubHwDevice");
187 this->sub_hw_devices.push_back(sub_hw_device);
188
189 SensorEventQueue *queue = new SensorEventQueue(SENSOR_EVENT_QUEUE_CAPACITY);
190 this->queues.push_back(queue);
191
192 TaskContext* taskContext = new TaskContext();
193 taskContext->device = (sensors_poll_device_t*) sub_hw_device;
194 taskContext->queue = queue;
195
196 pthread_t writerThread;
197 pthread_create(&writerThread, NULL, writerTask, taskContext);
198 this->threads.push_back(writerThread);
199}
200
201sensors_poll_device_t* sensors_poll_context_t::get_v0_device_by_handle(int handle) {
202 int sub_index = get_module_index(handle);
203 return (sensors_poll_device_t*) this->sub_hw_devices[sub_index];
204}
205
206sensors_poll_device_1_t* sensors_poll_context_t::get_v1_device_by_handle(int handle) {
207 int sub_index = get_module_index(handle);
208 return (sensors_poll_device_1_t*) this->sub_hw_devices[sub_index];
209}
210
211int sensors_poll_context_t::get_device_version_by_handle(int handle) {
212 sensors_poll_device_t* v0 = this->get_v0_device_by_handle(handle);
213 return v0->common.version;
214}
215
216int sensors_poll_context_t::activate(int handle, int enabled) {
Nick Vaccaro93bf9962014-03-17 13:05:09 -0700217 int retval = -EINVAL;
Mike Lockwoodf8477622013-10-17 08:05:00 -0700218 ALOGV("activate");
219 sensors_poll_device_t* v0 = this->get_v0_device_by_handle(handle);
Nick Vaccaro93bf9962014-03-17 13:05:09 -0700220 if (v0)
221 retval = v0->activate(v0, get_local_handle(handle), enabled);
Mike Lockwoodf8477622013-10-17 08:05:00 -0700222 ALOGV("retval %d", retval);
223 return retval;
224}
225
226int sensors_poll_context_t::setDelay(int handle, int64_t ns) {
227 ALOGV("setDelay");
228 sensors_poll_device_t* v0 = this->get_v0_device_by_handle(handle);
229 int retval = v0->setDelay(v0, get_local_handle(handle), ns);
230 ALOGV("retval %d", retval);
231 return retval;
232}
233
234void sensors_poll_context_t::copy_event_remap_handle(sensors_event_t* dest, sensors_event_t* src,
235 int sub_index) {
236 memcpy(dest, src, sizeof(struct sensors_event_t));
237 // A normal event's "sensor" field is a local handle. Convert it to a global handle.
238 // A meta-data event must have its sensor set to 0, but it has a nested event
239 // with a local handle that needs to be converted to a global handle.
240 FullHandle full_handle;
241 full_handle.moduleIndex = sub_index;
242 // If it's a metadata event, rewrite the inner payload, not the sensor field.
243 if (dest->type == SENSOR_TYPE_META_DATA) {
244 full_handle.localHandle = dest->meta_data.sensor;
245 dest->meta_data.sensor = full_to_global[full_handle];
246 } else {
247 full_handle.localHandle = dest->sensor;
248 dest->sensor = full_to_global[full_handle];
249 }
250}
251
252int sensors_poll_context_t::poll(sensors_event_t *data, int maxReads) {
253 ALOGV("poll");
254 int empties = 0;
255 int queueCount = (int)this->queues.size();
256 int eventsRead = 0;
257
258 pthread_mutex_lock(&queue_mutex);
259 while (eventsRead == 0) {
260 while (empties < queueCount && eventsRead < maxReads) {
261 SensorEventQueue* queue = this->queues.at(this->nextReadIndex);
262 sensors_event_t* event = queue->peek();
263 if (event == NULL) {
264 empties++;
265 } else {
266 empties = 0;
267 this->copy_event_remap_handle(&data[eventsRead++], event, nextReadIndex);
268 queue->dequeue();
269 }
270 this->nextReadIndex = (this->nextReadIndex + 1) % queueCount;
271 }
272 if (eventsRead == 0) {
273 // The queues have been scanned and none contain data, so wait.
274 ALOGV("poll stopping to wait for data");
275 waiting_for_data = true;
276 pthread_cond_wait(&data_available_cond, &queue_mutex);
277 waiting_for_data = false;
278 empties = 0;
279 }
280 }
281 pthread_mutex_unlock(&queue_mutex);
282 ALOGV("poll returning %d events.", eventsRead);
283
284 return eventsRead;
285}
286
287int sensors_poll_context_t::batch(int handle, int flags, int64_t period_ns, int64_t timeout) {
288 ALOGV("batch");
289 int retval = -EINVAL;
290 int version = this->get_device_version_by_handle(handle);
291 if (version >= SENSORS_DEVICE_API_VERSION_1_0) {
292 sensors_poll_device_1_t* v1 = this->get_v1_device_by_handle(handle);
293 retval = v1->batch(v1, get_local_handle(handle), flags, period_ns, timeout);
294 }
295 ALOGV("retval %d", retval);
296 return retval;
297}
298
299int sensors_poll_context_t::flush(int handle) {
300 ALOGV("flush");
301 int retval = -EINVAL;
302 int version = this->get_device_version_by_handle(handle);
303 if (version >= SENSORS_DEVICE_API_VERSION_1_0) {
304 sensors_poll_device_1_t* v1 = this->get_v1_device_by_handle(handle);
305 retval = v1->flush(v1, get_local_handle(handle));
306 }
307 ALOGV("retval %d", retval);
308 return retval;
309}
310
311int sensors_poll_context_t::close() {
312 ALOGV("close");
313 for (std::vector<hw_device_t*>::iterator it = this->sub_hw_devices.begin();
314 it != this->sub_hw_devices.end(); it++) {
315 hw_device_t* dev = *it;
316 int retval = dev->close(dev);
317 ALOGV("retval %d", retval);
318 }
319 return 0;
320}
321
322
323static int device__close(struct hw_device_t *dev) {
324 sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;
325 if (ctx != NULL) {
326 int retval = ctx->close();
327 delete ctx;
328 }
329 return 0;
330}
331
332static int device__activate(struct sensors_poll_device_t *dev, int handle,
333 int enabled) {
334 sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;
335 return ctx->activate(handle, enabled);
336}
337
338static int device__setDelay(struct sensors_poll_device_t *dev, int handle,
339 int64_t ns) {
340 sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;
341 return ctx->setDelay(handle, ns);
342}
343
344static int device__poll(struct sensors_poll_device_t *dev, sensors_event_t* data,
345 int count) {
346 sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;
347 return ctx->poll(data, count);
348}
349
350static int device__batch(struct sensors_poll_device_1 *dev, int handle,
351 int flags, int64_t period_ns, int64_t timeout) {
352 sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;
353 return ctx->batch(handle, flags, period_ns, timeout);
354}
355
356static int device__flush(struct sensors_poll_device_1 *dev, int handle) {
357 sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;
358 return ctx->flush(handle);
359}
360
361static int open_sensors(const struct hw_module_t* module, const char* name,
362 struct hw_device_t** device);
363
364static bool starts_with(const char* s, const char* prefix) {
365 if (s == NULL || prefix == NULL) {
366 return false;
367 }
368 size_t s_size = strlen(s);
369 size_t prefix_size = strlen(prefix);
370 return s_size >= prefix_size && strncmp(s, prefix, prefix_size) == 0;
371}
372
373/*
374 * Adds valid paths from the config file to the vector passed in.
375 * The vector must not be null.
376 */
377static void get_so_paths(std::vector<char*> *so_paths) {
378 FILE *conf_file = fopen(CONFIG_FILENAME, "r");
379 if (conf_file == NULL) {
380 ALOGW("No multihal config file found at %s", CONFIG_FILENAME);
381 return;
382 }
383 ALOGI("Multihal config file found at %s", CONFIG_FILENAME);
384 char *line = NULL;
385 size_t len = 0;
386 int line_count = 0;
387 while (getline(&line, &len, conf_file) != -1) {
388 // overwrite trailing eoln with null char
389 char* pch = strchr(line, '\n');
390 if (pch != NULL) {
391 *pch = '\0';
392 }
393 ALOGV("config file line #%d: '%s'", ++line_count, line);
394 char *real_path = realpath(line, NULL);
395 if (starts_with(real_path, LEGAL_SUBHAL_PATH_PREFIX)) {
396 ALOGI("accepting valid path '%s'", real_path);
397 char* compact_line = new char[strlen(real_path) + 1];
398 strcpy(compact_line, real_path);
399 so_paths->push_back(compact_line);
400 } else {
401 ALOGW("rejecting path '%s' because it does not start with '%s'",
402 real_path, LEGAL_SUBHAL_PATH_PREFIX);
403 }
404 free(real_path);
405 }
406 free(line);
407 fclose(conf_file);
408 ALOGV("hals.conf contained %d lines", line_count);
409}
410
411/*
412 * Ensures that the sub-module array is initialized.
413 * This can be first called from get_sensors_list or from open_sensors.
414 */
415static void lazy_init_modules() {
416 pthread_mutex_lock(&init_modules_mutex);
417 if (sub_hw_modules != NULL) {
418 pthread_mutex_unlock(&init_modules_mutex);
419 return;
420 }
421 std::vector<char*> *so_paths = new std::vector<char*>();
422 get_so_paths(so_paths);
423
424 // dlopen the module files and cache their module symbols in sub_hw_modules
425 sub_hw_modules = new std::vector<hw_module_t *>();
426 dlerror(); // clear any old errors
427 const char* sym = HAL_MODULE_INFO_SYM_AS_STR;
428 for (std::vector<char*>::iterator it = so_paths->begin(); it != so_paths->end(); it++) {
429 char* path = *it;
430 void* lib_handle = dlopen(path, RTLD_LAZY);
431 if (lib_handle == NULL) {
432 ALOGW("dlerror(): %s", dlerror());
433 } else {
434 ALOGI("hal lib was loaded: %s", path);
435 ALOGV("Opening symbol \"%s\"", sym);
436 // clear old errors
437 dlerror();
438 struct hw_module_t* module = (hw_module_t*) dlsym(lib_handle, sym);
439 const char* error;
440 if ((error = dlerror()) != NULL) {
441 ALOGW("Error calling dlsym: %s", error);
442 } else if (module == NULL) {
443 ALOGW("module == NULL");
444 } else {
445 ALOGI("OK, dlsym()'ed \"%s\"", sym);
446 sub_hw_modules->push_back(module);
447 }
448 }
449 }
450 pthread_mutex_unlock(&init_modules_mutex);
451}
452
453/*
454 * Lazy-initializes global_sensors_count, global_sensors_list, and module_sensor_handles.
455 */
456static void lazy_init_sensors_list() {
457 ALOGV("lazy_init_sensors_list");
458 pthread_mutex_lock(&init_sensors_mutex);
459 if (global_sensors_list != NULL) {
460 // already initialized
461 pthread_mutex_unlock(&init_sensors_mutex);
462 ALOGV("lazy_init_sensors_list - early return");
463 return;
464 }
465
466 ALOGV("lazy_init_sensors_list needs to do work");
467 lazy_init_modules();
468
469 // Count all the sensors, then allocate an array of blanks.
470 global_sensors_count = 0;
471 const struct sensor_t *subhal_sensors_list;
472 for (std::vector<hw_module_t*>::iterator it = sub_hw_modules->begin();
473 it != sub_hw_modules->end(); it++) {
474 struct sensors_module_t *module = (struct sensors_module_t*) *it;
475 global_sensors_count += module->get_sensors_list(module, &subhal_sensors_list);
476 ALOGV("increased global_sensors_count to %d", global_sensors_count);
477 }
478
479 // The global_sensors_list is full of consts.
480 // Manipulate this non-const list, and point the const one to it when we're done.
481 sensor_t* mutable_sensor_list = new sensor_t[global_sensors_count];
482
483 // index of the next sensor to set in mutable_sensor_list
484 int mutable_sensor_index = 0;
485 int module_index = 0;
486
487 for (std::vector<hw_module_t*>::iterator it = sub_hw_modules->begin();
488 it != sub_hw_modules->end(); it++) {
489 hw_module_t *hw_module = *it;
490 ALOGV("examine one module");
491 // Read the sub-module's sensor list.
492 struct sensors_module_t *module = (struct sensors_module_t*) hw_module;
493 int module_sensor_count = module->get_sensors_list(module, &subhal_sensors_list);
494 ALOGV("the module has %d sensors", module_sensor_count);
495
496 // Copy the HAL's sensor list into global_sensors_list,
497 // with the handle changed to be a global handle.
498 for (int i = 0; i < module_sensor_count; i++) {
499 ALOGV("examining one sensor");
500 const struct sensor_t *local_sensor = &subhal_sensors_list[i];
501 int local_handle = local_sensor->handle;
502 memcpy(&mutable_sensor_list[mutable_sensor_index], local_sensor,
503 sizeof(struct sensor_t));
504
505 // Overwrite the global version's handle with a global handle.
506 int global_handle = assign_global_handle(module_index, local_handle);
507
508 mutable_sensor_list[mutable_sensor_index].handle = global_handle;
509 ALOGI("module_index %d, local_handle %d, global_handle %d",
510 module_index, local_handle, global_handle);
511
512 mutable_sensor_index++;
513 }
514 module_index++;
515 }
516 // Set the const static global_sensors_list to the mutable one allocated by this function.
517 global_sensors_list = mutable_sensor_list;
518
519 pthread_mutex_unlock(&init_sensors_mutex);
520 ALOGV("end lazy_init_sensors_list");
521}
522
523static int module__get_sensors_list(struct sensors_module_t* module,
524 struct sensor_t const** list) {
525 ALOGV("module__get_sensors_list start");
526 lazy_init_sensors_list();
527 *list = global_sensors_list;
528 ALOGV("global_sensors_count: %d", global_sensors_count);
529 for (int i = 0; i < global_sensors_count; i++) {
530 ALOGV("sensor type: %d", global_sensors_list[i].type);
531 }
532 return global_sensors_count;
533}
534
535static struct hw_module_methods_t sensors_module_methods = {
536 open : open_sensors
537};
538
539struct sensors_module_t HAL_MODULE_INFO_SYM = {
540 common :{
541 tag : HARDWARE_MODULE_TAG,
542 version_major : 1,
543 version_minor : 0,
544 id : SENSORS_HARDWARE_MODULE_ID,
545 name : "MultiHal Sensor Module",
546 author : "Google, Inc",
547 methods : &sensors_module_methods,
548 dso : NULL,
549 reserved : {0},
550 },
551 get_sensors_list : module__get_sensors_list
552};
553
554static int open_sensors(const struct hw_module_t* hw_module, const char* name,
555 struct hw_device_t** hw_device_out) {
556 ALOGI("open_sensors begin...");
557
558 lazy_init_modules();
559
560 // Create proxy device, to return later.
561 sensors_poll_context_t *dev = new sensors_poll_context_t();
562 memset(dev, 0, sizeof(sensors_poll_device_1_t));
563 dev->proxy_device.common.tag = HARDWARE_DEVICE_TAG;
564 dev->proxy_device.common.version = SENSORS_DEVICE_API_VERSION_1_0;
565 dev->proxy_device.common.module = const_cast<hw_module_t*>(hw_module);
566 dev->proxy_device.common.close = device__close;
567 dev->proxy_device.activate = device__activate;
568 dev->proxy_device.setDelay = device__setDelay;
569 dev->proxy_device.poll = device__poll;
570 dev->proxy_device.batch = device__batch;
571 dev->proxy_device.flush = device__flush;
572
573 dev->nextReadIndex = 0;
574
575 // Open() the subhal modules. Remember their devices in a vector parallel to sub_hw_modules.
576 for (std::vector<hw_module_t*>::iterator it = sub_hw_modules->begin();
577 it != sub_hw_modules->end(); it++) {
578 sensors_module_t *sensors_module = (sensors_module_t*) *it;
579 struct hw_device_t* sub_hw_device;
580 int sub_open_result = sensors_module->common.methods->open(*it, name, &sub_hw_device);
Nick Vaccaro93bf9962014-03-17 13:05:09 -0700581 if (!sub_open_result)
582 dev->addSubHwDevice(sub_hw_device);
Mike Lockwoodf8477622013-10-17 08:05:00 -0700583 }
584
585 // Prepare the output param and return
586 *hw_device_out = &dev->proxy_device.common;
587 ALOGI("...open_sensors end");
588 return 0;
589}