diff options
Diffstat (limited to 'services/sensorservice/SensorDevice.cpp')
-rw-r--r-- | services/sensorservice/SensorDevice.cpp | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp new file mode 100644 index 0000000..a9e3ef4 --- /dev/null +++ b/services/sensorservice/SensorDevice.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdint.h> +#include <math.h> +#include <sys/types.h> + +#include <utils/Atomic.h> +#include <utils/Errors.h> +#include <utils/Singleton.h> + +#include <binder/BinderService.h> +#include <binder/Parcel.h> +#include <binder/IServiceManager.h> + +#include <hardware/sensors.h> + +#include "SensorDevice.h" +#include "SensorService.h" + +namespace android { +// --------------------------------------------------------------------------- + +ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice) + +SensorDevice::SensorDevice() + : mSensorDevice(0), + mSensorModule(0) +{ + status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, + (hw_module_t const**)&mSensorModule); + + ALOGE_IF(err, "couldn't load %s module (%s)", + SENSORS_HARDWARE_MODULE_ID, strerror(-err)); + + if (mSensorModule) { + err = sensors_open(&mSensorModule->common, &mSensorDevice); + + ALOGE_IF(err, "couldn't open device for module %s (%s)", + SENSORS_HARDWARE_MODULE_ID, strerror(-err)); + + if (mSensorDevice) { + sensor_t const* list; + ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list); + mActivationCount.setCapacity(count); + Info model; + for (size_t i=0 ; i<size_t(count) ; i++) { + mActivationCount.add(list[i].handle, model); + mSensorDevice->activate(mSensorDevice, list[i].handle, 0); + } + } + } +} + +void SensorDevice::dump(String8& result, char* buffer, size_t SIZE) +{ + if (!mSensorModule) return; + sensor_t const* list; + ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list); + + snprintf(buffer, SIZE, "%d h/w sensors:\n", int(count)); + result.append(buffer); + + Mutex::Autolock _l(mLock); + for (size_t i=0 ; i<size_t(count) ; i++) { + const Info& info = mActivationCount.valueFor(list[i].handle); + snprintf(buffer, SIZE, "handle=0x%08x, active-count=%d, rates(ms)={ ", + list[i].handle, + info.rates.size()); + result.append(buffer); + for (size_t j=0 ; j<info.rates.size() ; j++) { + snprintf(buffer, SIZE, "%4.1f%s", + info.rates.valueAt(j) / 1e6f, + j<info.rates.size()-1 ? ", " : ""); + result.append(buffer); + } + snprintf(buffer, SIZE, " }, selected=%4.1f ms\n", info.delay / 1e6f); + result.append(buffer); + } +} + +ssize_t SensorDevice::getSensorList(sensor_t const** list) { + if (!mSensorModule) return NO_INIT; + ssize_t count = mSensorModule->get_sensors_list(mSensorModule, list); + return count; +} + +status_t SensorDevice::initCheck() const { + return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT; +} + +ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) { + if (!mSensorDevice) return NO_INIT; + ssize_t c; + do { + c = mSensorDevice->poll(mSensorDevice, buffer, count); + } while (c == -EINTR); + return c; +} + +status_t SensorDevice::activate(void* ident, int handle, int enabled) +{ + if (!mSensorDevice) return NO_INIT; + status_t err(NO_ERROR); + bool actuateHardware = false; + + Info& info( mActivationCount.editValueFor(handle) ); + + + ALOGD_IF(DEBUG_CONNECTIONS, + "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%d", + ident, handle, enabled, info.rates.size()); + + if (enabled) { + Mutex::Autolock _l(mLock); + ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld", + info.rates.indexOfKey(ident)); + + if (info.rates.indexOfKey(ident) < 0) { + info.rates.add(ident, DEFAULT_EVENTS_PERIOD); + if (info.rates.size() == 1) { + actuateHardware = true; + } + } else { + // sensor was already activated for this ident + } + } else { + Mutex::Autolock _l(mLock); + ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld", + info.rates.indexOfKey(ident)); + + ssize_t idx = info.rates.removeItem(ident); + if (idx >= 0) { + if (info.rates.size() == 0) { + actuateHardware = true; + } + } else { + // sensor wasn't enabled for this ident + } + } + + if (actuateHardware) { + ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w"); + + err = mSensorDevice->activate(mSensorDevice, handle, enabled); + ALOGE_IF(err, "Error %s sensor %d (%s)", + enabled ? "activating" : "disabling", + handle, strerror(-err)); + } + + { // scope for the lock + Mutex::Autolock _l(mLock); + nsecs_t ns = info.selectDelay(); + mSensorDevice->setDelay(mSensorDevice, handle, ns); + } + + return err; +} + +status_t SensorDevice::setDelay(void* ident, int handle, int64_t ns) +{ + if (!mSensorDevice) return NO_INIT; + Mutex::Autolock _l(mLock); + Info& info( mActivationCount.editValueFor(handle) ); + status_t err = info.setDelayForIdent(ident, ns); + if (err < 0) return err; + ns = info.selectDelay(); + return mSensorDevice->setDelay(mSensorDevice, handle, ns); +} + +// --------------------------------------------------------------------------- + +status_t SensorDevice::Info::setDelayForIdent(void* ident, int64_t ns) +{ + ssize_t index = rates.indexOfKey(ident); + if (index < 0) { + ALOGE("Info::setDelayForIdent(ident=%p, ns=%lld) failed (%s)", + ident, ns, strerror(-index)); + return BAD_INDEX; + } + rates.editValueAt(index) = ns; + return NO_ERROR; +} + +nsecs_t SensorDevice::Info::selectDelay() +{ + nsecs_t ns = rates.valueAt(0); + for (size_t i=1 ; i<rates.size() ; i++) { + nsecs_t cur = rates.valueAt(i); + if (cur < ns) { + ns = cur; + } + } + delay = ns; + return ns; +} + +// --------------------------------------------------------------------------- +}; // namespace android + |