/* * 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 #include #include #include #include #include #include #include #include #include #include "SensorDevice.h" #include "SensorService.h" namespace android { // --------------------------------------------------------------------------- class BatteryService : public Singleton { static const int TRANSACTION_noteStartSensor = IBinder::FIRST_CALL_TRANSACTION + 3; static const int TRANSACTION_noteStopSensor = IBinder::FIRST_CALL_TRANSACTION + 4; static const String16 DESCRIPTOR; friend class Singleton; sp mBatteryStatService; BatteryService() { const sp sm(defaultServiceManager()); if (sm != NULL) { const String16 name("batteryinfo"); mBatteryStatService = sm->getService(name); } } status_t noteStartSensor(int uid, int handle) { Parcel data, reply; data.writeInterfaceToken(DESCRIPTOR); data.writeInt32(uid); data.writeInt32(handle); status_t err = mBatteryStatService->transact( TRANSACTION_noteStartSensor, data, &reply, 0); err = reply.readExceptionCode(); return err; } status_t noteStopSensor(int uid, int handle) { Parcel data, reply; data.writeInterfaceToken(DESCRIPTOR); data.writeInt32(uid); data.writeInt32(handle); status_t err = mBatteryStatService->transact( TRANSACTION_noteStopSensor, data, &reply, 0); err = reply.readExceptionCode(); return err; } public: void enableSensor(int handle) { if (mBatteryStatService != 0) { int uid = IPCThreadState::self()->getCallingUid(); int64_t identity = IPCThreadState::self()->clearCallingIdentity(); noteStartSensor(uid, handle); IPCThreadState::self()->restoreCallingIdentity(identity); } } void disableSensor(int handle) { if (mBatteryStatService != 0) { int uid = IPCThreadState::self()->getCallingUid(); int64_t identity = IPCThreadState::self()->clearCallingIdentity(); noteStopSensor(uid, handle); IPCThreadState::self()->restoreCallingIdentity(identity); } } }; const String16 BatteryService::DESCRIPTOR("com.android.internal.app.IBatteryStats"); ANDROID_SINGLETON_STATIC_INSTANCE(BatteryService) // --------------------------------------------------------------------------- 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); LOGE_IF(err, "couldn't load %s module (%s)", SENSORS_HARDWARE_MODULE_ID, strerror(-err)); if (mSensorModule) { err = sensors_open(&mSensorModule->common, &mSensorDevice); LOGE_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 ; iactivate(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 ; iget_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); if (enabled) { LOGE_IF(err, "Error activating sensor %d (%s)", handle, strerror(-err)); if (err == 0) { BatteryService::getInstance().enableSensor(handle); } } else { if (err == 0) { BatteryService::getInstance().disableSensor(handle); } } } { // 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) { LOGE("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