1 /*
2  * Copyright (C) 2015 Intel Corporation
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 <cutils/log.h>
18 #include <sys/epoll.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <hardware/sensors.h>
22 #include "AcquisitionThread.hpp"
23 #include "Utils.hpp"
24 
acquisitionRoutine(void * param)25 void* AcquisitionThread::acquisitionRoutine(void *param) {
26   AcquisitionThread *acquisitionThread = reinterpret_cast<AcquisitionThread *>(param);
27   Sensor *sensor = nullptr;
28   int64_t timestamp = 0;
29   struct timespec target_time;
30   int rc = 0;
31   sensors_event_t data;
32 
33   if (acquisitionThread == nullptr) {
34     ALOGE("%s: The acquisition thread was not initialized", __func__);
35     return nullptr;
36   }
37 
38   sensor = acquisitionThread->sensor;
39   if (sensor == nullptr) {
40     ALOGE("%s: The acquisition thread doesn't have an associated sensor", __func__);
41     return nullptr;
42   }
43 
44   /* initialize sensor data structure */
45   memset(&data, 0, sizeof(sensors_event_t));
46   data.version = sizeof(sensors_event_t);
47   data.sensor = sensor->getHandle();
48   data.type = sensor->getType();
49 
50   pthread_mutex_lock(&acquisitionThread->pthreadMutex);
51 
52   /* get current timestamp */
53   timestamp = get_timestamp_monotonic();
54 
55   /* loop until the thread is canceled */
56   while(acquisitionThread->getWritePipeFd() != -1) {
57     /* get one event from the sensor */
58     if (sensor->pollEvents(&data, 1) != 1) {
59       ALOGE("%s: Sensor %d: Cannot read data", __func__, data.sensor);
60       goto exit;
61     }
62 
63     /* send the data over the pipe to the main thread */
64     rc = write(acquisitionThread->getWritePipeFd(), &data, sizeof(sensors_event_t));
65     if (rc != sizeof(sensors_event_t)) {
66       ALOGE("%s: Sensor %d: Cannot write data to pipe", __func__, data.sensor);
67       goto exit;
68     }
69 
70     if (acquisitionThread->getWritePipeFd() == -1) {
71       ALOGE("%s: Sensor %d: The write pipe file descriptor is invalid", __func__, data.sensor);
72       goto exit;
73     }
74 
75     timestamp += sensor->getDelay();
76     set_timestamp(&target_time, timestamp);
77     pthread_cond_timedwait(&acquisitionThread->pthreadCond, &acquisitionThread->pthreadMutex, &target_time);
78   }
79 
80 exit:
81   pthread_mutex_unlock(&acquisitionThread->pthreadMutex);
82   return nullptr;
83 }
84 
AcquisitionThread(int pollFd,Sensor * sensor)85 AcquisitionThread::AcquisitionThread(int pollFd, Sensor *sensor)
86     : pollFd(pollFd), sensor(sensor), initialized(false) {
87   pipeFds[0] = pipeFds[1] = -1;
88 }
89 
init()90 bool AcquisitionThread::init() {
91   struct epoll_event ev;
92   int rc;
93 
94   memset(&ev, 0, sizeof(ev));
95 
96   if (initialized) {
97     ALOGE("%s: acquisition thread already initialized", __func__);
98     return false;
99   }
100 
101   /* create condition variable & mutex for quick thread release */
102   rc = pthread_condattr_init(&pthreadCondAttr);
103   if (rc != 0) {
104     ALOGE("%s: Cannot initialize the pthread condattr", __func__);
105     return false;
106   }
107   rc = pthread_condattr_setclock(&pthreadCondAttr, CLOCK_MONOTONIC);
108   if (rc != 0) {
109     ALOGE("%s: Cannot set the clock of condattr to monotonic", __func__);
110     return false;
111   }
112   rc = pthread_cond_init(&pthreadCond, &pthreadCondAttr);
113   if (rc != 0) {
114     ALOGE("%s: Cannot intialize the pthread structure", __func__);
115     return false;
116   }
117   rc = pthread_mutex_init(&pthreadMutex, nullptr);
118   if (rc != 0) {
119     ALOGE("%s: Cannot initialize the mutex associated with the pthread cond", __func__);
120     goto mutex_err;
121   }
122 
123   /* create pipe to signal events to the main thread */
124   rc = pipe2(pipeFds, O_NONBLOCK);
125   if (rc != 0) {
126     ALOGE("%s: Cannot initialize pipe", __func__);
127     goto pipe_err;
128   }
129 
130   ev.events = EPOLLIN;
131   ev.data.u32 = sensor->getHandle();
132 
133   /* add read pipe fd to pollFd */
134   rc = epoll_ctl(pollFd, EPOLL_CTL_ADD, pipeFds[0] , &ev);
135   if (rc != 0) {
136     ALOGE("%s: Cannot add the read file descriptor to poll set", __func__);
137     goto epoll_err;
138   }
139 
140   /* launch the thread */
141   rc = pthread_create(&pthread, nullptr, acquisitionRoutine, (void *)this);
142   if (rc != 0) {
143     ALOGE("%s: Cannot create acquisition pthread", __func__);
144     goto thread_create_err;
145   }
146 
147   initialized = true;
148   return true;
149 
150 thread_create_err:
151   epoll_ctl(pollFd, EPOLL_CTL_DEL, pipeFds[0], nullptr);
152 epoll_err:
153   close(pipeFds[0]);
154   close(pipeFds[1]);
155   pipeFds[0] = pipeFds[1] = -1;
156 pipe_err:
157   pthread_mutex_destroy(&pthreadMutex);
158 mutex_err:
159   pthread_cond_destroy(&pthreadCond);
160   return false;
161 }
162 
generateFlushCompleteEvent()163 bool AcquisitionThread::generateFlushCompleteEvent() {
164   sensors_event_t data;
165   int rc;
166 
167   if (!initialized) {
168     return false;
169   }
170 
171   /* batching is not supported; return one META_DATA_FLUSH_COMPLETE event */
172   memset(&data, 0, sizeof(sensors_event_t));
173   data.version = META_DATA_VERSION;
174   data.type = SENSOR_TYPE_META_DATA;
175   data.meta_data.sensor = sensor->getHandle();
176   data.meta_data.what = META_DATA_FLUSH_COMPLETE;
177 
178   /*
179    * Send the event via the associated pipe. It doesn't need to be in a loop
180    * as O_NONBLOCK is enabled and the number of bytes is <= PIPE_BUF.
181    * If there is room to write n bytes to the pipe, then write succeeds
182    * immediately, writing all n bytes; otherwise write fails.
183    */
184   rc = write(getWritePipeFd(), &data, sizeof(sensors_event_t));
185   if (rc != sizeof(sensors_event_t)) {
186     ALOGE("%s: not all data has been sent over the pipe", __func__);
187     return false;
188   }
189 
190   return true;
191 }
192 
wakeup()193 int AcquisitionThread::wakeup() {
194   if (initialized) {
195     return pthread_cond_signal(&pthreadCond);
196   }
197 
198   return -EINVAL;
199 }
200 
~AcquisitionThread()201 AcquisitionThread::~AcquisitionThread() {
202   int readPipeEnd, writePipeEnd;
203 
204   if (initialized) {
205     readPipeEnd = pipeFds[0];
206     writePipeEnd = pipeFds[1];
207     epoll_ctl(pollFd, EPOLL_CTL_DEL, readPipeEnd, nullptr);
208 
209     /* take the mutex to correctly signal the thread */
210     pthread_mutex_lock(&pthreadMutex);
211     pipeFds[0] = pipeFds[1] = -1;
212     close(readPipeEnd);
213     close(writePipeEnd);
214 
215     /* wakeup and wait for the thread */
216     pthread_cond_signal(&pthreadCond);
217     pthread_mutex_unlock(&pthreadMutex);
218     pthread_join(pthread, nullptr);
219 
220     pthread_cond_destroy(&pthreadCond);
221     pthread_mutex_destroy(&pthreadMutex);
222   }
223 }
224