| /* |
| * 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 |
| |