Enable wakeup sensors.

SensorService should hold a wakelock till the app reads events from a wakeup sensor. Currently drivers hold a wakelock with a
timeout while delivering events from a wake up sensor like Significant Motion. This hack can be removed now.

Bug: 9774884
Change-Id: If3b5acb99c9cf0cd29012fcfa9d6b04c74133d01
This commit is contained in:
Aravind Akella 2014-02-11 18:58:52 -08:00
parent 4cbf3c5344
commit 9a844cf78f
10 changed files with 263 additions and 68 deletions

View File

@ -157,7 +157,9 @@ typedef struct ASensorEvent {
uint64_t step_counter; uint64_t step_counter;
} u64; } u64;
}; };
int32_t reserved1[4];
uint32_t flags;
int32_t reserved1[3];
} ASensorEvent; } ASensorEvent;
struct ASensorManager; struct ASensorManager;

View File

@ -40,6 +40,7 @@ public:
nsecs_t maxBatchReportLatencyNs, int reservedFlags) = 0; nsecs_t maxBatchReportLatencyNs, int reservedFlags) = 0;
virtual status_t setEventRate(int handle, nsecs_t ns) = 0; virtual status_t setEventRate(int handle, nsecs_t ns) = 0;
virtual status_t flush() = 0; virtual status_t flush() = 0;
virtual void decreaseWakeLockRefCount() = 0;
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -71,6 +71,7 @@ public:
int32_t getFifoMaxEventCount() const; int32_t getFifoMaxEventCount() const;
const String8& getStringType() const; const String8& getStringType() const;
const String8& getRequiredPermission() const; const String8& getRequiredPermission() const;
bool isWakeUpSensor() const;
// LightFlattenable protocol // LightFlattenable protocol
inline bool isFixedSize() const { return false; } inline bool isFixedSize() const { return false; }
@ -93,6 +94,8 @@ private:
int32_t mFifoMaxEventCount; int32_t mFifoMaxEventCount;
String8 mStringType; String8 mStringType;
String8 mRequiredPermission; String8 mRequiredPermission;
// Todo: Surface this in java SDK.
bool mWakeUpSensor;
static void flattenString8(void*& buffer, size_t& size, const String8& string8); static void flattenString8(void*& buffer, size_t& size, const String8& string8);
static bool unflattenString8(void const*& buffer, size_t& size, String8& outputString8); static bool unflattenString8(void const*& buffer, size_t& size, String8& outputString8);
}; };

View File

@ -27,7 +27,7 @@
#include <gui/BitTube.h> #include <gui/BitTube.h>
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1 << 31)
struct ALooper; struct ALooper;
struct ASensorEvent; struct ASensorEvent;
@ -75,7 +75,8 @@ public:
int reservedFlags) const; int reservedFlags) const;
status_t disableSensor(int32_t handle) const; status_t disableSensor(int32_t handle) const;
status_t flush() const; status_t flush() const;
// Send an ack for every wake_up sensor event that is set to WAKE_UP_SENSOR_EVENT_NEEDS_ACK.
void sendAck(const ASensorEvent* events, int count);
private: private:
sp<Looper> getLooper() const; sp<Looper> getLooper() const;
sp<ISensorEventConnection> mSensorEventConnection; sp<ISensorEventConnection> mSensorEventConnection;

View File

@ -34,7 +34,8 @@ enum {
GET_SENSOR_CHANNEL = IBinder::FIRST_CALL_TRANSACTION, GET_SENSOR_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
ENABLE_DISABLE, ENABLE_DISABLE,
SET_EVENT_RATE, SET_EVENT_RATE,
FLUSH_SENSOR FLUSH_SENSOR,
DECREASE_WAKE_LOCK_REFCOUNT
}; };
class BpSensorEventConnection : public BpInterface<ISensorEventConnection> class BpSensorEventConnection : public BpInterface<ISensorEventConnection>
@ -83,6 +84,13 @@ public:
remote()->transact(FLUSH_SENSOR, data, &reply); remote()->transact(FLUSH_SENSOR, data, &reply);
return reply.readInt32(); return reply.readInt32();
} }
virtual void decreaseWakeLockRefCount() {
Parcel data, reply;
data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
remote()->transact(DECREASE_WAKE_LOCK_REFCOUNT, data, &reply, IBinder::FLAG_ONEWAY);
return;
}
}; };
IMPLEMENT_META_INTERFACE(SensorEventConnection, "android.gui.SensorEventConnection"); IMPLEMENT_META_INTERFACE(SensorEventConnection, "android.gui.SensorEventConnection");
@ -125,6 +133,11 @@ status_t BnSensorEventConnection::onTransact(
reply->writeInt32(result); reply->writeInt32(result);
return NO_ERROR; return NO_ERROR;
} break; } break;
case DECREASE_WAKE_LOCK_REFCOUNT: {
CHECK_INTERFACE(ISensorEventConnection, data, reply);
decreaseWakeLockRefCount();
return NO_ERROR;
} break;
} }
return BBinder::onTransact(code, data, reply, flags); return BBinder::onTransact(code, data, reply, flags);
} }

View File

@ -32,7 +32,8 @@ namespace android {
Sensor::Sensor() Sensor::Sensor()
: mHandle(0), mType(0), : mHandle(0), mType(0),
mMinValue(0), mMaxValue(0), mResolution(0), mMinValue(0), mMaxValue(0), mResolution(0),
mPower(0), mMinDelay(0), mFifoReservedEventCount(0), mFifoMaxEventCount(0) mPower(0), mMinDelay(0), mFifoReservedEventCount(0), mFifoMaxEventCount(0),
mWakeUpSensor(false)
{ {
} }
@ -48,6 +49,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion)
mResolution = hwSensor->resolution; mResolution = hwSensor->resolution;
mPower = hwSensor->power; mPower = hwSensor->power;
mMinDelay = hwSensor->minDelay; mMinDelay = hwSensor->minDelay;
mWakeUpSensor = false;
// Set fifo event count zero for older devices which do not support batching. Fused // Set fifo event count zero for older devices which do not support batching. Fused
// sensors also have their fifo counts set to zero. // sensors also have their fifo counts set to zero.
@ -104,6 +106,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion)
break; break;
case SENSOR_TYPE_PROXIMITY: case SENSOR_TYPE_PROXIMITY:
mStringType = SENSOR_STRING_TYPE_PROXIMITY; mStringType = SENSOR_STRING_TYPE_PROXIMITY;
mWakeUpSensor = true;
break; break;
case SENSOR_TYPE_RELATIVE_HUMIDITY: case SENSOR_TYPE_RELATIVE_HUMIDITY:
mStringType = SENSOR_STRING_TYPE_RELATIVE_HUMIDITY; mStringType = SENSOR_STRING_TYPE_RELATIVE_HUMIDITY;
@ -113,6 +116,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion)
break; break;
case SENSOR_TYPE_SIGNIFICANT_MOTION: case SENSOR_TYPE_SIGNIFICANT_MOTION:
mStringType = SENSOR_STRING_TYPE_SIGNIFICANT_MOTION; mStringType = SENSOR_STRING_TYPE_SIGNIFICANT_MOTION;
mWakeUpSensor = true;
break; break;
case SENSOR_TYPE_STEP_COUNTER: case SENSOR_TYPE_STEP_COUNTER:
mStringType = SENSOR_STRING_TYPE_STEP_COUNTER; mStringType = SENSOR_STRING_TYPE_STEP_COUNTER;
@ -123,14 +127,93 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion)
case SENSOR_TYPE_TEMPERATURE: case SENSOR_TYPE_TEMPERATURE:
mStringType = SENSOR_STRING_TYPE_TEMPERATURE; mStringType = SENSOR_STRING_TYPE_TEMPERATURE;
break; break;
case SENSOR_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR:
mStringType = SENSOR_STRING_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR;
break;
case SENSOR_TYPE_WAKE_UP_ACCELEROMETER:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_ACCELEROMETER;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_MAGNETIC_FIELD:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_MAGNETIC_FIELD;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_ORIENTATION:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_ORIENTATION;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_GYROSCOPE:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_GYROSCOPE;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_LIGHT:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_LIGHT;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_PRESSURE:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_PRESSURE;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_GRAVITY:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_GRAVITY;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_LINEAR_ACCELERATION:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_LINEAR_ACCELERATION;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_ROTATION_VECTOR:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_ROTATION_VECTOR;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_RELATIVE_HUMIDITY:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_RELATIVE_HUMIDITY;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_AMBIENT_TEMPERATURE:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_AMBIENT_TEMPERATURE;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_GAME_ROTATION_VECTOR:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_GAME_ROTATION_VECTOR;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_STEP_DETECTOR:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_STEP_DETECTOR;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_STEP_COUNTER:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_STEP_COUNTER;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR;
mWakeUpSensor = true;
break;
case SENSOR_TYPE_WAKE_UP_HEART_RATE:
mStringType = SENSOR_STRING_TYPE_WAKE_UP_HEART_RATE;
mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS;
mWakeUpSensor = true;
break;
default: default:
// Only pipe the stringType and requiredPermission for custom sensors. // Only pipe the stringType, requiredPermission and flags for custom sensors.
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->stringType) { if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->stringType) {
mStringType = hwSensor->stringType; mStringType = hwSensor->stringType;
} }
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->requiredPermission) { if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->requiredPermission) {
mRequiredPermission = hwSensor->requiredPermission; mRequiredPermission = hwSensor->requiredPermission;
} }
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
mWakeUpSensor = hwSensor->flags & SENSOR_FLAG_WAKE_UP;
}
break; break;
} }
} }
@ -199,6 +282,10 @@ const String8& Sensor::getRequiredPermission() const {
return mRequiredPermission; return mRequiredPermission;
} }
bool Sensor::isWakeUpSensor() const {
return mWakeUpSensor;
}
size_t Sensor::getFlattenedSize() const size_t Sensor::getFlattenedSize() const
{ {
size_t fixedSize = size_t fixedSize =

View File

@ -144,6 +144,15 @@ status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const
return mSensorEventConnection->setEventRate(sensor->getHandle(), ns); return mSensorEventConnection->setEventRate(sensor->getHandle(), ns);
} }
void SensorEventQueue::sendAck(const ASensorEvent* events, int count) {
for (int i = 0; i < count; ++i) {
if (events[i].flags & WAKE_UP_SENSOR_EVENT_NEEDS_ACK) {
mSensorEventConnection->decreaseWakeLockRefCount();
}
}
return;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
}; // namespace android }; // namespace android

View File

@ -309,7 +309,7 @@ int SensorDevice::getHalDeviceVersion() const {
return mSensorDevice->common.version; return mSensorDevice->common.version;
} }
status_t SensorDevice::flush(void* /*ident*/, int handle) { status_t SensorDevice::flush(void* ident, int handle) {
if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) { if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) {
return INVALID_OPERATION; return INVALID_OPERATION;
} }

View File

@ -164,6 +164,7 @@ void SensorService::onFirstRef()
fclose(fp); fclose(fp);
} }
mWakeLockAcquired = false;
run("SensorService", PRIORITY_URGENT_DISPLAY); run("SensorService", PRIORITY_URGENT_DISPLAY);
mInitCheck = NO_ERROR; mInitCheck = NO_ERROR;
} }
@ -284,6 +285,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& /*args*/)
} }
result.appendFormat("%zu Max Socket Buffer size\n", mSocketBufferSize); result.appendFormat("%zu Max Socket Buffer size\n", mSocketBufferSize);
result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held");
result.appendFormat("%zd active connections\n", mActiveConnections.size()); result.appendFormat("%zd active connections\n", mActiveConnections.size());
for (size_t i=0 ; i < mActiveConnections.size() ; i++) { for (size_t i=0 ; i < mActiveConnections.size() ; i++) {
@ -298,7 +300,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& /*args*/)
return NO_ERROR; return NO_ERROR;
} }
void SensorService::cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection, void SensorService::cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
sensors_event_t const* buffer, const int count) { sensors_event_t const* buffer, const int count) {
SensorInterface* sensor; SensorInterface* sensor;
status_t err = NO_ERROR; status_t err = NO_ERROR;
@ -311,7 +313,7 @@ void SensorService::cleanupAutoDisabledSensor(const sp<SensorEventConnection>& c
if (sensor != NULL) { if (sensor != NULL) {
sensor->autoDisable(connection.get(), handle); sensor->autoDisable(connection.get(), handle);
} }
cleanupWithoutDisable(connection, handle); cleanupWithoutDisableLocked(connection, handle);
} }
} }
} }
@ -333,7 +335,6 @@ bool SensorService::threadLoop()
const size_t vcount = mVirtualSensorList.size(); const size_t vcount = mVirtualSensorList.size();
ssize_t count; ssize_t count;
bool wakeLockAcquired = false;
const int halVersion = device.getHalDeviceVersion(); const int halVersion = device.getHalDeviceVersion();
do { do {
count = device.poll(buffer, numEventMax); count = device.poll(buffer, numEventMax);
@ -341,26 +342,31 @@ bool SensorService::threadLoop()
ALOGE("sensor poll failed (%s)", strerror(-count)); ALOGE("sensor poll failed (%s)", strerror(-count));
break; break;
} }
Mutex::Autolock _l(mLock);
// Poll has returned. Hold a wakelock. // Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The
// Todo(): add a flag to the sensors definitions to indicate // rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock,
// the sensors which can wake up the AP // sending events to clients (incrementing SensorEventConnection::mWakeLockRefCount) should
// not be interleaved with decrementing SensorEventConnection::mWakeLockRefCount and
// releasing the wakelock.
bool bufferHasWakeUpEvent = false;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
if (buffer[i].type == SENSOR_TYPE_SIGNIFICANT_MOTION) { if (isWakeUpSensorEvent(buffer[i])) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); bufferHasWakeUpEvent = true;
wakeLockAcquired = true; break;
break;
} }
} }
recordLastValue(buffer, count); if (bufferHasWakeUpEvent && !mWakeLockAcquired) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
mWakeLockAcquired = true;
ALOGD_IF(DEBUG_CONNECTIONS, "acquired wakelock %s", WAKE_LOCK_NAME);
}
recordLastValueLocked(buffer, count);
// handle virtual sensors // handle virtual sensors
if (count && vcount) { if (count && vcount) {
sensors_event_t const * const event = buffer; sensors_event_t const * const event = buffer;
const DefaultKeyedVector<int, SensorInterface*> virtualSensors( const size_t activeVirtualSensorCount = mActiveVirtualSensors.size();
getActiveVirtualSensors());
const size_t activeVirtualSensorCount = virtualSensors.size();
if (activeVirtualSensorCount) { if (activeVirtualSensorCount) {
size_t k = 0; size_t k = 0;
SensorFusion& fusion(SensorFusion::getInstance()); SensorFusion& fusion(SensorFusion::getInstance());
@ -378,7 +384,7 @@ bool SensorService::threadLoop()
break; break;
} }
sensors_event_t out; sensors_event_t out;
SensorInterface* si = virtualSensors.valueAt(j); SensorInterface* si = mActiveVirtualSensors.valueAt(j);
if (si->process(&out, event[i])) { if (si->process(&out, event[i])) {
buffer[count + k] = out; buffer[count + k] = out;
k++; k++;
@ -387,7 +393,7 @@ bool SensorService::threadLoop()
} }
if (k) { if (k) {
// record the last synthesized values // record the last synthesized values
recordLastValue(&buffer[count], k); recordLastValueLocked(&buffer[count], k);
count += k; count += k;
// sort the buffer by time-stamps // sort the buffer by time-stamps
sortEventBuffer(buffer, count); sortEventBuffer(buffer, count);
@ -406,22 +412,24 @@ bool SensorService::threadLoop()
} }
} }
// send our events to clients... // Send our events to clients. Check the state of wake lock for each client and release the
const SortedVector< wp<SensorEventConnection> > activeConnections( // lock if none of the clients need it.
getActiveConnections()); bool needsWakeLock = false;
size_t numConnections = activeConnections.size(); for (size_t i=0 ; i < mActiveConnections.size(); i++) {
for (size_t i=0 ; i<numConnections ; i++) { sp<SensorEventConnection> connection(mActiveConnections[i].promote());
sp<SensorEventConnection> connection(
activeConnections[i].promote());
if (connection != 0) { if (connection != 0) {
connection->sendEvents(buffer, count, scratch); connection->sendEvents(buffer, count, scratch);
needsWakeLock |= connection->needsWakeLock();
// Some sensors need to be auto disabled after the trigger // Some sensors need to be auto disabled after the trigger
cleanupAutoDisabledSensor(connection, buffer, count); cleanupAutoDisabledSensorLocked(connection, buffer, count);
} }
} }
// We have read the data, upper layers should hold the wakelock. if (mWakeLockAcquired && !needsWakeLock) {
if (wakeLockAcquired) release_wake_lock(WAKE_LOCK_NAME); release_wake_lock(WAKE_LOCK_NAME);
mWakeLockAcquired = false;
ALOGD_IF(DEBUG_CONNECTIONS, "released wakelock %s", WAKE_LOCK_NAME);
}
} while (count >= 0 || Thread::exitPending()); } while (count >= 0 || Thread::exitPending());
ALOGW("Exiting SensorService::threadLoop => aborting..."); ALOGW("Exiting SensorService::threadLoop => aborting...");
@ -429,9 +437,8 @@ bool SensorService::threadLoop()
return false; return false;
} }
void SensorService::recordLastValue( void SensorService::recordLastValueLocked(
const sensors_event_t* buffer, size_t count) { const sensors_event_t* buffer, size_t count) {
Mutex::Autolock _l(mLock);
const sensors_event_t* last = NULL; const sensors_event_t* last = NULL;
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
const sensors_event_t* event = &buffer[i]; const sensors_event_t* event = &buffer[i];
@ -459,20 +466,6 @@ void SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count)
qsort(buffer, count, sizeof(sensors_event_t), compar::cmp); qsort(buffer, count, sizeof(sensors_event_t), compar::cmp);
} }
SortedVector< wp<SensorService::SensorEventConnection> >
SensorService::getActiveConnections() const
{
Mutex::Autolock _l(mLock);
return mActiveConnections;
}
DefaultKeyedVector<int, SensorInterface*>
SensorService::getActiveVirtualSensors() const
{
Mutex::Autolock _l(mLock);
return mActiveVirtualSensors;
}
String8 SensorService::getSensorName(int handle) const { String8 SensorService::getSensorName(int handle) const {
size_t count = mUserSensorList.size(); size_t count = mUserSensorList.size();
for (size_t i=0 ; i<count ; i++) { for (size_t i=0 ; i<count ; i++) {
@ -490,6 +483,11 @@ bool SensorService::isVirtualSensor(int handle) const {
return sensor->isVirtual(); return sensor->isVirtual();
} }
bool SensorService::isWakeUpSensorEvent(const sensors_event_t& event) const {
SensorInterface* sensor = mSensorMap.valueFor(event.sensor);
return sensor->getSensor().isWakeUpSensor();
}
Vector<Sensor> SensorService::getSensorList() Vector<Sensor> SensorService::getSensorList()
{ {
char value[PROPERTY_VALUE_MAX]; char value[PROPERTY_VALUE_MAX];
@ -554,6 +552,9 @@ void SensorService::cleanupConnection(SensorEventConnection* c)
} }
mActiveConnections.remove(connection); mActiveConnections.remove(connection);
BatteryService::cleanup(c->getUid()); BatteryService::cleanup(c->getUid());
if (c->needsWakeLock()) {
checkWakeLockStateLocked();
}
} }
Sensor SensorService::getSensorFromHandle(int handle) const { Sensor SensorService::getSensorFromHandle(int handle) const {
@ -585,15 +586,24 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection,
} }
} else { } else {
if (rec->addConnection(connection)) { if (rec->addConnection(connection)) {
// this sensor is already activated, but we are adding a // this sensor is already activated, but we are adding a connection that uses it.
// connection that uses it. Immediately send down the last // Immediately send down the last known value of the requested sensor if it's not a
// known value of the requested sensor if it's not a
// "continuous" sensor. // "continuous" sensor.
if (sensor->getSensor().getMinDelay() == 0) { if (sensor->getSensor().getMinDelay() == 0) {
sensors_event_t scratch; // NOTE: The wake_up flag of this event may get set to
// WAKE_UP_SENSOR_EVENT_NEEDS_ACK if this is a wake_up event.
sensors_event_t& event(mLastEventSeen.editValueFor(handle)); sensors_event_t& event(mLastEventSeen.editValueFor(handle));
if (event.version == sizeof(sensors_event_t)) { if (event.version == sizeof(sensors_event_t)) {
connection->sendEvents(&event, 1); if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
mWakeLockAcquired = true;
ALOGD_IF(DEBUG_CONNECTIONS, "acquired wakelock for on_change sensor %s",
WAKE_LOCK_NAME);
}
connection->sendEvents(&event, 1, NULL);
if (!connection->needsWakeLock() && mWakeLockAcquired) {
checkWakeLockStateLocked();
}
} }
} }
} }
@ -751,6 +761,31 @@ bool SensorService::verifyCanAccessSensor(const Sensor& sensor, const char* oper
} }
} }
void SensorService::checkWakeLockState() {
Mutex::Autolock _l(mLock);
checkWakeLockStateLocked();
}
void SensorService::checkWakeLockStateLocked() {
if (!mWakeLockAcquired) {
return;
}
bool releaseLock = true;
for (size_t i=0 ; i<mActiveConnections.size() ; i++) {
sp<SensorEventConnection> connection(mActiveConnections[i].promote());
if (connection != 0) {
if (connection->needsWakeLock()) {
releaseLock = false;
break;
}
}
}
if (releaseLock) {
ALOGD_IF(DEBUG_CONNECTIONS, "releasing wakelock %s", WAKE_LOCK_NAME);
release_wake_lock(WAKE_LOCK_NAME);
mWakeLockAcquired = false;
}
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
SensorService::SensorRecord::SensorRecord( SensorService::SensorRecord::SensorRecord(
@ -783,7 +818,7 @@ bool SensorService::SensorRecord::removeConnection(
SensorService::SensorEventConnection::SensorEventConnection( SensorService::SensorEventConnection::SensorEventConnection(
const sp<SensorService>& service, uid_t uid) const sp<SensorService>& service, uid_t uid)
: mService(service), mUid(uid) : mService(service), mUid(uid), mWakeLockRefCount(0)
{ {
const SensorDevice& device(SensorDevice::getInstance()); const SensorDevice& device(SensorDevice::getInstance());
if (device.getHalDeviceVersion() >= SENSORS_DEVICE_API_VERSION_1_1) { if (device.getHalDeviceVersion() >= SENSORS_DEVICE_API_VERSION_1_1) {
@ -804,8 +839,14 @@ void SensorService::SensorEventConnection::onFirstRef()
{ {
} }
bool SensorService::SensorEventConnection::needsWakeLock() {
Mutex::Autolock _l(mConnectionLock);
return mWakeLockRefCount > 0;
}
void SensorService::SensorEventConnection::dump(String8& result) { void SensorService::SensorEventConnection::dump(String8& result) {
Mutex::Autolock _l(mConnectionLock); Mutex::Autolock _l(mConnectionLock);
result.appendFormat("%d WakeLockRefCount\n", mWakeLockRefCount);
for (size_t i = 0; i < mSensorInfo.size(); ++i) { for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const FlushInfo& flushInfo = mSensorInfo.valueAt(i); const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
result.appendFormat("\t %s | status: %s | pending flush events %d | uid %d\n", result.appendFormat("\t %s | status: %s | pending flush events %d | uid %d\n",
@ -863,9 +904,8 @@ status_t SensorService::SensorEventConnection::sendEvents(
{ {
// filter out events not for this connection // filter out events not for this connection
size_t count = 0; size_t count = 0;
Mutex::Autolock _l(mConnectionLock);
if (scratch) { if (scratch) {
Mutex::Autolock _l(mConnectionLock);
size_t i=0; size_t i=0;
while (i<numEvents) { while (i<numEvents) {
int32_t curr = buffer[i].sensor; int32_t curr = buffer[i].sensor;
@ -905,7 +945,6 @@ status_t SensorService::SensorEventConnection::sendEvents(
ASensorEvent flushCompleteEvent; ASensorEvent flushCompleteEvent;
flushCompleteEvent.type = SENSOR_TYPE_META_DATA; flushCompleteEvent.type = SENSOR_TYPE_META_DATA;
flushCompleteEvent.sensor = 0; flushCompleteEvent.sensor = 0;
Mutex::Autolock _l(mConnectionLock);
// Loop through all the sensors for this connection and check if there are any pending // Loop through all the sensors for this connection and check if there are any pending
// flush complete events to be sent. // flush complete events to be sent.
for (size_t i = 0; i < mSensorInfo.size(); ++i) { for (size_t i = 0; i < mSensorInfo.size(); ++i) {
@ -930,6 +969,7 @@ status_t SensorService::SensorEventConnection::sendEvents(
return status_t(NO_ERROR); return status_t(NO_ERROR);
} }
int numWakeUpSensorEvents = countWakeUpSensorEventsLocked(scratch, count);
// NOTE: ASensorEvent and sensors_event_t are the same type // NOTE: ASensorEvent and sensors_event_t are the same type
ssize_t size = SensorEventQueue::write(mChannel, ssize_t size = SensorEventQueue::write(mChannel,
reinterpret_cast<ASensorEvent const*>(scratch), count); reinterpret_cast<ASensorEvent const*>(scratch), count);
@ -937,11 +977,10 @@ status_t SensorService::SensorEventConnection::sendEvents(
// the destination doesn't accept events anymore, it's probably // the destination doesn't accept events anymore, it's probably
// full. For now, we just drop the events on the floor. // full. For now, we just drop the events on the floor.
// ALOGW("dropping %d events on the floor", count); // ALOGW("dropping %d events on the floor", count);
Mutex::Autolock _l(mConnectionLock);
countFlushCompleteEventsLocked(scratch, count); countFlushCompleteEventsLocked(scratch, count);
mWakeLockRefCount -= numWakeUpSensorEvents;
return size; return size;
} }
return size < 0 ? status_t(size) : status_t(NO_ERROR); return size < 0 ? status_t(size) : status_t(NO_ERROR);
} }
@ -961,6 +1000,18 @@ void SensorService::SensorEventConnection::countFlushCompleteEventsLocked(
return; return;
} }
int SensorService::SensorEventConnection::countWakeUpSensorEventsLocked(
sensors_event_t* scratch, const int count) {
for (int i = 0; i < count; ++i) {
if (mService->isWakeUpSensorEvent(scratch[i])) {
scratch[i].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
++mWakeLockRefCount;
return 1;
}
}
return 0;
}
sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const
{ {
return mChannel; return mChannel;
@ -1010,6 +1061,17 @@ status_t SensorService::SensorEventConnection::flush() {
return err; return err;
} }
void SensorService::SensorEventConnection::decreaseWakeLockRefCount() {
{
Mutex::Autolock _l(mConnectionLock);
--mWakeLockRefCount;
}
// Release the lock before calling checkWakeLockState which also needs the same connectionLock.
if (mWakeLockRefCount == 0) {
mService->checkWakeLockState();
}
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
}; // namespace android }; // namespace android

View File

@ -41,6 +41,7 @@
// Max size is 1 MB which is enough to accept a batch of about 10k events. // Max size is 1 MB which is enough to accept a batch of about 10k events.
#define MAX_SOCKET_BUFFER_SIZE_BATCHED 1024 * 1024 #define MAX_SOCKET_BUFFER_SIZE_BATCHED 1024 * 1024
#define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024 #define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024
#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1 << 31)
struct sensors_poll_device_t; struct sensors_poll_device_t;
struct sensors_module_t; struct sensors_module_t;
@ -71,7 +72,6 @@ class SensorService :
virtual sp<ISensorEventConnection> createSensorEventConnection(); virtual sp<ISensorEventConnection> createSensorEventConnection();
virtual status_t dump(int fd, const Vector<String16>& args); virtual status_t dump(int fd, const Vector<String16>& args);
class SensorEventConnection : public BnSensorEventConnection { class SensorEventConnection : public BnSensorEventConnection {
virtual ~SensorEventConnection(); virtual ~SensorEventConnection();
virtual void onFirstRef(); virtual void onFirstRef();
@ -80,15 +80,26 @@ class SensorService :
nsecs_t maxBatchReportLatencyNs, int reservedFlags); nsecs_t maxBatchReportLatencyNs, int reservedFlags);
virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs); virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs);
virtual status_t flush(); virtual status_t flush();
void decreaseWakeLockRefCount();
// Count the number of flush complete events which are about to be dropped in the buffer. // Count the number of flush complete events which are about to be dropped in the buffer.
// Increment mPendingFlushEventsToSend in mSensorInfo. These flush complete events will be // Increment mPendingFlushEventsToSend in mSensorInfo. These flush complete events will be
// sent separately before the next batch of events. // sent separately before the next batch of events.
void countFlushCompleteEventsLocked(sensors_event_t* scratch, int numEventsDropped); void countFlushCompleteEventsLocked(sensors_event_t* scratch, int numEventsDropped);
// Check if there are any wake up events in the buffer. If yes, increment the ref count.
// Increment it by exactly one unit for each packet sent on the socket. SOCK_SEQPACKET for
// the socket ensures that either the entire packet is read or dropped.
// Return 1 if mWakeLockRefCount has been incremented, zero if not.
int countWakeUpSensorEventsLocked(sensors_event_t* scratch, const int count);
sp<SensorService> const mService; sp<SensorService> const mService;
sp<BitTube> mChannel; sp<BitTube> mChannel;
uid_t mUid; uid_t mUid;
mutable Mutex mConnectionLock; mutable Mutex mConnectionLock;
// Number of events from wake up sensors which are still pending and haven't been delivered
// to the corresponding application. It is incremented by one unit for each write to the
// socket.
int mWakeLockRefCount;
struct FlushInfo { struct FlushInfo {
// The number of flush complete events dropped for this sensor is stored here. // The number of flush complete events dropped for this sensor is stored here.
@ -106,13 +117,14 @@ class SensorService :
SensorEventConnection(const sp<SensorService>& service, uid_t uid); SensorEventConnection(const sp<SensorService>& service, uid_t uid);
status_t sendEvents(sensors_event_t const* buffer, size_t count, status_t sendEvents(sensors_event_t const* buffer, size_t count,
sensors_event_t* scratch = NULL); sensors_event_t* scratch);
bool hasSensor(int32_t handle) const; bool hasSensor(int32_t handle) const;
bool hasAnySensor() const; bool hasAnySensor() const;
bool addSensor(int32_t handle); bool addSensor(int32_t handle);
bool removeSensor(int32_t handle); bool removeSensor(int32_t handle);
void setFirstFlushPending(int32_t handle, bool value); void setFirstFlushPending(int32_t handle, bool value);
void dump(String8& result); void dump(String8& result);
bool needsWakeLock();
uid_t getUid() const { return mUid; } uid_t getUid() const { return mUid; }
}; };
@ -126,13 +138,11 @@ class SensorService :
size_t getNumConnections() const { return mConnections.size(); } size_t getNumConnections() const { return mConnections.size(); }
}; };
SortedVector< wp<SensorEventConnection> > getActiveConnections() const;
DefaultKeyedVector<int, SensorInterface*> getActiveVirtualSensors() const;
String8 getSensorName(int handle) const; String8 getSensorName(int handle) const;
bool isVirtualSensor(int handle) const; bool isVirtualSensor(int handle) const;
Sensor getSensorFromHandle(int handle) const; Sensor getSensorFromHandle(int handle) const;
void recordLastValue(const sensors_event_t* buffer, size_t count); bool isWakeUpSensor(int type) const;
void recordLastValueLocked(const sensors_event_t* buffer, size_t count);
static void sortEventBuffer(sensors_event_t* buffer, size_t count); static void sortEventBuffer(sensors_event_t* buffer, size_t count);
Sensor registerSensor(SensorInterface* sensor); Sensor registerSensor(SensorInterface* sensor);
Sensor registerVirtualSensor(SensorInterface* sensor); Sensor registerVirtualSensor(SensorInterface* sensor);
@ -140,10 +150,16 @@ class SensorService :
const sp<SensorEventConnection>& connection, int handle); const sp<SensorEventConnection>& connection, int handle);
status_t cleanupWithoutDisableLocked( status_t cleanupWithoutDisableLocked(
const sp<SensorEventConnection>& connection, int handle); const sp<SensorEventConnection>& connection, int handle);
void cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection, void cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
sensors_event_t const* buffer, const int count); sensors_event_t const* buffer, const int count);
static bool canAccessSensor(const Sensor& sensor); static bool canAccessSensor(const Sensor& sensor);
static bool verifyCanAccessSensor(const Sensor& sensor, const char* operation); static bool verifyCanAccessSensor(const Sensor& sensor, const char* operation);
// SensorService acquires a partial wakelock for delivering events from wake up sensors. This
// method checks whether all the events from these wake up sensors have been delivered to the
// corresponding applications, if yes the wakelock is released.
void checkWakeLockState();
void checkWakeLockStateLocked();
bool isWakeUpSensorEvent(const sensors_event_t& event) const;
// constants // constants
Vector<Sensor> mSensorList; Vector<Sensor> mSensorList;
Vector<Sensor> mUserSensorListDebug; Vector<Sensor> mUserSensorListDebug;
@ -158,6 +174,7 @@ class SensorService :
DefaultKeyedVector<int, SensorRecord*> mActiveSensors; DefaultKeyedVector<int, SensorRecord*> mActiveSensors;
DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors; DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors;
SortedVector< wp<SensorEventConnection> > mActiveConnections; SortedVector< wp<SensorEventConnection> > mActiveConnections;
bool mWakeLockAcquired;
// The size of this vector is constant, only the items are mutable // The size of this vector is constant, only the items are mutable
KeyedVector<int32_t, sensors_event_t> mLastEventSeen; KeyedVector<int32_t, sensors_event_t> mLastEventSeen;