|  | /* | 
|  | * 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); | 
|  | } | 
|  |  | 
|  | int SensorDevice::getHalDeviceVersion() const { | 
|  | if (!mSensorDevice) return -1; | 
|  |  | 
|  | return mSensorDevice->common.version; | 
|  | } | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | 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 | 
|  |  |