SensorDevice.cpp revision 92dc3fc52cf097bd105460cf377779bdcf146d62
1/*
2 * Copyright (C) 2010 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 <stdint.h>
18#include <math.h>
19#include <sys/types.h>
20
21#include <utils/Atomic.h>
22#include <utils/Errors.h>
23#include <utils/Singleton.h>
24
25#include <binder/BinderService.h>
26#include <binder/Parcel.h>
27#include <binder/IServiceManager.h>
28
29#include <hardware/sensors.h>
30
31#include "SensorDevice.h"
32#include "SensorService.h"
33
34namespace android {
35// ---------------------------------------------------------------------------
36
37ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
38
39SensorDevice::SensorDevice()
40    :  mSensorDevice(0),
41       mSensorModule(0)
42{
43    status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
44            (hw_module_t const**)&mSensorModule);
45
46    ALOGE_IF(err, "couldn't load %s module (%s)",
47            SENSORS_HARDWARE_MODULE_ID, strerror(-err));
48
49    if (mSensorModule) {
50        err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
51
52        ALOGE_IF(err, "couldn't open device for module %s (%s)",
53                SENSORS_HARDWARE_MODULE_ID, strerror(-err));
54
55        if (mSensorDevice) {
56            sensor_t const* list;
57            ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
58            mActivationCount.setCapacity(count);
59            Info model;
60            for (size_t i=0 ; i<size_t(count) ; i++) {
61                mActivationCount.add(list[i].handle, model);
62                mSensorDevice->activate(
63                        reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
64                        list[i].handle, 0);
65            }
66        }
67    }
68}
69
70void SensorDevice::dump(String8& result)
71{
72    if (!mSensorModule) return;
73    sensor_t const* list;
74    ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
75
76    result.appendFormat("%d h/w sensors:\n", int(count));
77
78    Mutex::Autolock _l(mLock);
79    for (size_t i=0 ; i<size_t(count) ; i++) {
80        const Info& info = mActivationCount.valueFor(list[i].handle);
81        result.appendFormat("handle=0x%08x, active-count=%zu, batch_period(ms)={ ", list[i].handle,
82                            info.batchParams.size());
83        for (size_t j = 0; j < info.batchParams.size(); j++) {
84            BatchParams params = info.batchParams.valueAt(j);
85            result.appendFormat("%4.1f%s", params.batchDelay / 1e6f,
86                                j < info.batchParams.size() - 1 ? ", " : "");
87        }
88        result.appendFormat(" }, selected=%4.1f ms\n", info.bestBatchParams.batchDelay / 1e6f);
89
90        result.appendFormat("handle=0x%08x, active-count=%zu, batch_timeout(ms)={ ", list[i].handle,
91                            info.batchParams.size());
92        for (size_t j = 0; j < info.batchParams.size(); j++) {
93            BatchParams params = info.batchParams.valueAt(j);
94            result.appendFormat("%4.1f%s", params.batchTimeout / 1e6f,
95                                j < info.batchParams.size() - 1 ? ", " : "");
96        }
97        result.appendFormat(" }, selected=%4.1f ms\n", info.bestBatchParams.batchTimeout / 1e6f);
98    }
99}
100
101ssize_t SensorDevice::getSensorList(sensor_t const** list) {
102    if (!mSensorModule) return NO_INIT;
103    ssize_t count = mSensorModule->get_sensors_list(mSensorModule, list);
104    return count;
105}
106
107status_t SensorDevice::initCheck() const {
108    return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT;
109}
110
111ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
112    if (!mSensorDevice) return NO_INIT;
113    ssize_t c;
114    do {
115        c = mSensorDevice->poll(reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
116                                buffer, count);
117    } while (c == -EINTR);
118    return c;
119}
120
121void SensorDevice::autoDisable(void *ident, int handle) {
122    Info& info( mActivationCount.editValueFor(handle) );
123    Mutex::Autolock _l(mLock);
124    info.removeBatchParamsForIdent(ident);
125}
126
127status_t SensorDevice::activate(void* ident, int handle, int enabled)
128{
129    if (!mSensorDevice) return NO_INIT;
130    status_t err(NO_ERROR);
131    bool actuateHardware = false;
132
133    Mutex::Autolock _l(mLock);
134    Info& info( mActivationCount.editValueFor(handle) );
135
136    ALOGD_IF(DEBUG_CONNECTIONS,
137             "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%d",
138             ident, handle, enabled, info.batchParams.size());
139
140    if (enabled) {
141        ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%d", info.batchParams.indexOfKey(ident));
142
143        if (info.batchParams.indexOfKey(ident) >= 0) {
144          if (info.batchParams.size() == 1) {
145              // This is the first connection, we need to activate the underlying h/w sensor.
146              actuateHardware = true;
147          }
148        } else {
149            // Log error. Every activate call should be preceded by a batch() call.
150            ALOGE("\t >>>ERROR: activate called without batch");
151        }
152    } else {
153        ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%d", info.batchParams.indexOfKey(ident));
154
155        if (info.removeBatchParamsForIdent(ident) >= 0) {
156            if (info.batchParams.size() == 0) {
157                // This is the last connection, we need to de-activate the underlying h/w sensor.
158                actuateHardware = true;
159            } else {
160                const int halVersion = getHalDeviceVersion();
161                if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
162                    // Call batch for this sensor with the previously calculated best effort
163                    // batch_rate and timeout. One of the apps has unregistered for sensor
164                    // events, and the best effort batch parameters might have changed.
165                    ALOGD_IF(DEBUG_CONNECTIONS,
166                             "\t>>> actuating h/w batch %d %d %lld %lld ", handle,
167                             info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
168                             info.bestBatchParams.batchTimeout);
169                    mSensorDevice->batch(mSensorDevice, handle,info.bestBatchParams.flags,
170                                         info.bestBatchParams.batchDelay,
171                                         info.bestBatchParams.batchTimeout);
172                }
173            }
174        } else {
175            // sensor wasn't enabled for this ident
176        }
177    }
178
179    if (actuateHardware) {
180        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle, enabled);
181        err = mSensorDevice->activate(
182                reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), handle, enabled);
183        ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
184                 strerror(-err));
185
186        if (err != NO_ERROR && enabled) {
187            // Failure when enabling the sensor. Clean up on failure.
188            info.removeBatchParamsForIdent(ident);
189        }
190    }
191
192    // On older devices which do not support batch, call setDelay().
193    if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.batchParams.size() > 0) {
194        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w setDelay %d %lld ", handle,
195                 info.bestBatchParams.batchDelay);
196        mSensorDevice->setDelay(
197                reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
198                handle, info.bestBatchParams.batchDelay);
199    }
200    return err;
201}
202
203status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
204                             int64_t maxBatchReportLatencyNs) {
205    if (!mSensorDevice) return NO_INIT;
206
207    if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
208        samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
209    }
210
211    const int halVersion = getHalDeviceVersion();
212    if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
213        if (flags & SENSORS_BATCH_DRY_RUN) {
214            return mSensorDevice->batch(mSensorDevice, handle, flags, samplingPeriodNs,
215                                        maxBatchReportLatencyNs);
216        } else {
217            // Call h/w with dry run to see if the given parameters are feasible or not. Return if
218            // there is an error.
219            status_t errDryRun(NO_ERROR);
220            errDryRun = mSensorDevice->batch(mSensorDevice, handle, flags | SENSORS_BATCH_DRY_RUN,
221                                             samplingPeriodNs, maxBatchReportLatencyNs);
222            if (errDryRun != NO_ERROR) {
223                ALOGD_IF(DEBUG_CONNECTIONS, "SensorDevice::batch dry run error %s",
224                         strerror(-errDryRun));
225                return errDryRun;
226            }
227        }
228    } else if (maxBatchReportLatencyNs != 0) {
229        // Batch is not supported on older devices.
230        return INVALID_OPERATION;
231    }
232
233    ALOGD_IF(DEBUG_CONNECTIONS,
234             "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%lld timeout=%lld",
235             ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
236
237    Mutex::Autolock _l(mLock);
238    Info& info(mActivationCount.editValueFor(handle));
239
240    if (info.batchParams.indexOfKey(ident) < 0) {
241        BatchParams params(flags, samplingPeriodNs, maxBatchReportLatencyNs);
242        info.batchParams.add(ident, params);
243    } else {
244        // A batch has already been called with this ident. Update the batch parameters.
245        info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs);
246    }
247
248    BatchParams prevBestBatchParams = info.bestBatchParams;
249    // Find the minimum of all timeouts and batch_rates for this sensor.
250    info.selectBatchParams();
251
252    ALOGD_IF(DEBUG_CONNECTIONS,
253             "\t>>> curr_period=%lld min_period=%lld curr_timeout=%lld min_timeout=%lld",
254             prevBestBatchParams.batchDelay, info.bestBatchParams.batchDelay,
255             prevBestBatchParams.batchTimeout, info.bestBatchParams.batchTimeout);
256
257    status_t err(NO_ERROR);
258    // If the min period or min timeout has changed since the last batch call, call batch.
259    if (prevBestBatchParams != info.bestBatchParams) {
260        if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
261            ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %lld %lld ", handle,
262                     info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
263                     info.bestBatchParams.batchTimeout);
264            err = mSensorDevice->batch(mSensorDevice, handle, info.bestBatchParams.flags,
265                                       info.bestBatchParams.batchDelay,
266                                       info.bestBatchParams.batchTimeout);
267        } else {
268            // For older devices which do not support batch, call setDelay() after activate() is
269            // called. Some older devices may not support calling setDelay before activate(), so
270            // call setDelay in SensorDevice::activate() method.
271        }
272        if (err != NO_ERROR) {
273            ALOGE("sensor batch failed %p %d %d %lld %lld err=%s", mSensorDevice, handle,
274                  info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
275                  info.bestBatchParams.batchTimeout, strerror(-err));
276            info.removeBatchParamsForIdent(ident);
277        }
278    }
279    return err;
280}
281
282status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs)
283{
284    if (!mSensorDevice) return NO_INIT;
285    if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
286        samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
287    }
288    Mutex::Autolock _l(mLock);
289    Info& info( mActivationCount.editValueFor(handle) );
290    // If the underlying sensor is NOT in continuous mode, setDelay() should return an error.
291    // Calling setDelay() in batch mode is an invalid operation.
292    if (info.bestBatchParams.batchTimeout != 0) {
293      return INVALID_OPERATION;
294    }
295    ssize_t index = info.batchParams.indexOfKey(ident);
296    if (index < 0) {
297        return BAD_INDEX;
298    }
299    BatchParams& params = info.batchParams.editValueAt(index);
300    params.batchDelay = samplingPeriodNs;
301    info.selectBatchParams();
302    return mSensorDevice->setDelay(reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
303                                   handle, info.bestBatchParams.batchDelay);
304}
305
306int SensorDevice::getHalDeviceVersion() const {
307    if (!mSensorDevice) return -1;
308
309    return mSensorDevice->common.version;
310}
311
312status_t SensorDevice::flush(void* /*ident*/, int handle) {
313    if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) {
314        return INVALID_OPERATION;
315    }
316    ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
317    return mSensorDevice->flush(mSensorDevice, handle);
318}
319
320// ---------------------------------------------------------------------------
321
322status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags,
323                                                    int64_t samplingPeriodNs,
324                                                    int64_t maxBatchReportLatencyNs) {
325    ssize_t index = batchParams.indexOfKey(ident);
326    if (index < 0) {
327        ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%lld timeout=%lld) failed (%s)",
328              ident, samplingPeriodNs, maxBatchReportLatencyNs, strerror(-index));
329        return BAD_INDEX;
330    }
331    BatchParams& params = batchParams.editValueAt(index);
332    params.flags = flags;
333    params.batchDelay = samplingPeriodNs;
334    params.batchTimeout = maxBatchReportLatencyNs;
335    return NO_ERROR;
336}
337
338void SensorDevice::Info::selectBatchParams() {
339    BatchParams bestParams(-1, -1, -1);
340
341    if (batchParams.size() > 0) {
342        BatchParams params = batchParams.valueAt(0);
343        bestParams = params;
344    }
345
346    for (size_t i = 1; i < batchParams.size(); ++i) {
347        BatchParams params = batchParams.valueAt(i);
348        if (params.batchDelay < bestParams.batchDelay) {
349            bestParams.batchDelay = params.batchDelay;
350        }
351        if (params.batchTimeout < bestParams.batchTimeout) {
352            bestParams.batchTimeout = params.batchTimeout;
353        }
354    }
355    bestBatchParams = bestParams;
356}
357
358ssize_t SensorDevice::Info::removeBatchParamsForIdent(void* ident) {
359    ssize_t idx = batchParams.removeItem(ident);
360    if (idx >= 0) {
361        selectBatchParams();
362    }
363    return idx;
364}
365
366// ---------------------------------------------------------------------------
367}; // namespace android
368
369