replicant-frameworks_native/services/sensorservice/SensorDevice.cpp
Mathias Agopian 787ac1b388 improve sensor battery usage tracking
until now we were tracking when a sensors was
physically enabled or disabled and we were reporting
that to the BattaryService.

this wasn incorrect because we could have several different
apps enabling the same sensor, so the accounting by the
battery service would be incorrect in that case (depending
on the order in which these apps disabled said sensor).

BatteryService tracks sensors per uid, however SensorService
does this per binder connection, so we could have several
binder connections for the same uid, to solve this we keep
a list of sensor/uid -> count, which is the bulk of this
change.

Bug: 6661604
Change-Id: I561c198c42ba1736a8671bdacda4c76d72b9dd6f
2012-09-18 23:33:36 -07:00

214 lines
6.4 KiB
C++

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