Enable data injection mode in SensorService.

Change-Id: I0cd32a017235c31c54816e4a357ce3b988350ed6
This commit is contained in:
Aravind Akella 2015-04-16 18:57:31 -07:00
parent 3804378e6a
commit a9e6cc3870
10 changed files with 239 additions and 50 deletions

View File

@ -38,7 +38,9 @@ public:
DECLARE_META_INTERFACE(SensorServer); DECLARE_META_INTERFACE(SensorServer);
virtual Vector<Sensor> getSensorList() = 0; virtual Vector<Sensor> getSensorList() = 0;
virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName) = 0; virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
int mode) = 0;
virtual status_t enableDataInjection(int enable) = 0;
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -77,6 +77,8 @@ public:
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. // 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); void sendAck(const ASensorEvent* events, int count);
status_t injectSensorEvent(const ASensorEvent& event);
private: private:
sp<Looper> getLooper() const; sp<Looper> getLooper() const;
sp<ISensorEventConnection> mSensorEventConnection; sp<ISensorEventConnection> mSensorEventConnection;

View File

@ -53,7 +53,8 @@ public:
ssize_t getSensorList(Sensor const* const** list) const; ssize_t getSensorList(Sensor const* const** list) const;
Sensor const* getDefaultSensor(int type); Sensor const* getDefaultSensor(int type);
sp<SensorEventQueue> createEventQueue(String8 packageName = String8("")); sp<SensorEventQueue> createEventQueue(String8 packageName = String8(""), int mode = 0);
ssize_t enableDataInjection(bool enable);
private: private:
// DeathRecipient interface // DeathRecipient interface

View File

@ -35,6 +35,7 @@ namespace android {
enum { enum {
GET_SENSOR_LIST = IBinder::FIRST_CALL_TRANSACTION, GET_SENSOR_LIST = IBinder::FIRST_CALL_TRANSACTION,
CREATE_SENSOR_EVENT_CONNECTION, CREATE_SENSOR_EVENT_CONNECTION,
ENABLE_DATA_INJECTION
}; };
class BpSensorServer : public BpInterface<ISensorServer> class BpSensorServer : public BpInterface<ISensorServer>
@ -63,14 +64,24 @@ public:
return v; return v;
} }
virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName) virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
int mode)
{ {
Parcel data, reply; Parcel data, reply;
data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor()); data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
data.writeString8(packageName); data.writeString8(packageName);
data.writeInt32(mode);
remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply); remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply);
return interface_cast<ISensorEventConnection>(reply.readStrongBinder()); return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
} }
virtual status_t enableDataInjection(int enable) {
Parcel data, reply;
data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
data.writeInt32(enable);
remote()->transact(ENABLE_DATA_INJECTION, data, &reply);
return reply.readInt32();
}
}; };
// Out-of-line virtual method definition to trigger vtable emission in this // Out-of-line virtual method definition to trigger vtable emission in this
@ -98,10 +109,18 @@ status_t BnSensorServer::onTransact(
case CREATE_SENSOR_EVENT_CONNECTION: { case CREATE_SENSOR_EVENT_CONNECTION: {
CHECK_INTERFACE(ISensorServer, data, reply); CHECK_INTERFACE(ISensorServer, data, reply);
String8 packageName = data.readString8(); String8 packageName = data.readString8();
sp<ISensorEventConnection> connection(createSensorEventConnection(packageName)); int32_t mode = data.readInt32();
sp<ISensorEventConnection> connection(createSensorEventConnection(packageName, mode));
reply->writeStrongBinder(IInterface::asBinder(connection)); reply->writeStrongBinder(IInterface::asBinder(connection));
return NO_ERROR; return NO_ERROR;
} }
case ENABLE_DATA_INJECTION: {
CHECK_INTERFACE(ISensorServer, data, reply);
int32_t enable = data.readInt32();
status_t ret = enableDataInjection(enable);
reply->writeInt32(static_cast<int32_t>(ret));
return NO_ERROR;
}
} }
return BBinder::onTransact(code, data, reply, flags); return BBinder::onTransact(code, data, reply, flags);
} }

View File

@ -149,6 +149,16 @@ status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const
return mSensorEventConnection->setEventRate(sensor->getHandle(), ns); return mSensorEventConnection->setEventRate(sensor->getHandle(), ns);
} }
status_t SensorEventQueue::injectSensorEvent(const ASensorEvent& event) {
// Blocking call.
ssize_t size = ::send(mSensorChannel->getFd(), &event, sizeof(event), MSG_NOSIGNAL);
if (size < 0) {
ALOGE("injectSensorEvent failure %zd %d", size, mSensorChannel->getFd());
return size;
}
return NO_ERROR;
}
void SensorEventQueue::sendAck(const ASensorEvent* events, int count) { void SensorEventQueue::sendAck(const ASensorEvent* events, int count) {
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
if (events[i].flags & WAKE_UP_SENSOR_EVENT_NEEDS_ACK) { if (events[i].flags & WAKE_UP_SENSOR_EVENT_NEEDS_ACK) {

View File

@ -100,8 +100,6 @@ status_t SensorManager::assertStateLocked() const {
return NO_ERROR; return NO_ERROR;
} }
ssize_t SensorManager::getSensorList(Sensor const* const** list) const ssize_t SensorManager::getSensorList(Sensor const* const** list) const
{ {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
@ -139,18 +137,17 @@ Sensor const* SensorManager::getDefaultSensor(int type)
return NULL; return NULL;
} }
sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName) sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName, int mode) {
{
sp<SensorEventQueue> queue; sp<SensorEventQueue> queue;
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
while (assertStateLocked() == NO_ERROR) { while (assertStateLocked() == NO_ERROR) {
sp<ISensorEventConnection> connection = sp<ISensorEventConnection> connection =
mSensorServer->createSensorEventConnection(packageName); mSensorServer->createSensorEventConnection(packageName, mode);
if (connection == NULL) { if (connection == NULL) {
// SensorService just died. // SensorService just died or the app doesn't have required permissions.
ALOGE("createEventQueue: connection is NULL. SensorService died."); ALOGE("createEventQueue: connection is NULL.");
continue; return NULL;
} }
queue = new SensorEventQueue(connection); queue = new SensorEventQueue(connection);
break; break;
@ -158,5 +155,13 @@ sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName)
return queue; return queue;
} }
status_t SensorManager::enableDataInjection(bool enable) {
Mutex::Autolock _l(mLock);
if (assertStateLocked() == NO_ERROR) {
return mSensorServer->enableDataInjection(enable);
}
return INVALID_OPERATION;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
}; // namespace android }; // namespace android

View File

@ -367,7 +367,7 @@ void SensorDevice::enableAllSensors() {
void SensorDevice::disableAllSensors() { void SensorDevice::disableAllSensors() {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
for (size_t i = 0; i< mActivationCount.size(); ++i) { for (size_t i = 0; i< mActivationCount.size(); ++i) {
const Info& info = mActivationCount.valueAt(i); const Info& info = mActivationCount.valueAt(i);
// Check if this sensor has been activated previously and disable it. // Check if this sensor has been activated previously and disable it.
if (info.batchParams.size() > 0) { if (info.batchParams.size() > 0) {
@ -386,6 +386,27 @@ void SensorDevice::disableAllSensors() {
} }
} }
status_t SensorDevice::injectSensorData(const sensors_event_t *injected_sensor_event, size_t count) {
ALOGD_IF(DEBUG_CONNECTIONS,
"sensor_event handle=%d ts=%lld data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
injected_sensor_event->sensor,
injected_sensor_event->timestamp, injected_sensor_event->data[0],
injected_sensor_event->data[1], injected_sensor_event->data[2],
injected_sensor_event->data[3], injected_sensor_event->data[4],
injected_sensor_event->data[5]);
if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
return INVALID_OPERATION;
}
return mSensorDevice->inject_sensor_data(mSensorDevice, injected_sensor_event);
}
status_t SensorDevice::setMode(uint32_t mode) {
if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
return INVALID_OPERATION;
}
return mSensorModule->set_operation_mode(mode);
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
int SensorDevice::Info::numActiveClients() { int SensorDevice::Info::numActiveClients() {

View File

@ -98,9 +98,11 @@ public:
// Call batch with timeout zero instead of calling setDelay() for newer devices. // Call batch with timeout zero instead of calling setDelay() for newer devices.
status_t setDelay(void* ident, int handle, int64_t ns); status_t setDelay(void* ident, int handle, int64_t ns);
status_t flush(void* ident, int handle); status_t flush(void* ident, int handle);
status_t setMode(uint32_t mode);
void disableAllSensors(); void disableAllSensors();
void enableAllSensors(); void enableAllSensors();
void autoDisable(void *ident, int handle); void autoDisable(void *ident, int handle);
status_t injectSensorData(const sensors_event_t *event, size_t count);
void dump(String8& result); void dump(String8& result);
}; };

View File

@ -64,6 +64,9 @@ namespace android {
*/ */
const char* SensorService::WAKE_LOCK_NAME = "SensorService"; const char* SensorService::WAKE_LOCK_NAME = "SensorService";
// Permissions.
static const String16 sDataInjectionPermission("android.permission.HARDWARE_TEST");
static const String16 sDump("android.permission.DUMP");
SensorService::SensorService() SensorService::SensorService()
: mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED), : mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),
@ -74,7 +77,6 @@ SensorService::SensorService()
void SensorService::onFirstRef() void SensorService::onFirstRef()
{ {
ALOGD("nuSensorService starting..."); ALOGD("nuSensorService starting...");
SensorDevice& dev(SensorDevice::getInstance()); SensorDevice& dev(SensorDevice::getInstance());
if (dev.initCheck() == NO_ERROR) { if (dev.initCheck() == NO_ERROR) {
@ -190,7 +192,7 @@ void SensorService::onFirstRef()
mSensorEventBuffer = new sensors_event_t[minBufferSize]; mSensorEventBuffer = new sensors_event_t[minBufferSize];
mSensorEventScratch = new sensors_event_t[minBufferSize]; mSensorEventScratch = new sensors_event_t[minBufferSize];
mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize]; mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
mMode = NORMAL; mCurrentOperatingMode = NORMAL;
mAckReceiver = new SensorEventAckReceiver(this); mAckReceiver = new SensorEventAckReceiver(this);
mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY); mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
@ -229,8 +231,6 @@ SensorService::~SensorService()
delete mSensorMap.valueAt(i); delete mSensorMap.valueAt(i);
} }
static const String16 sDump("android.permission.DUMP");
status_t SensorService::dump(int fd, const Vector<String16>& args) status_t SensorService::dump(int fd, const Vector<String16>& args)
{ {
String8 result; String8 result;
@ -245,8 +245,8 @@ status_t SensorService::dump(int fd, const Vector<String16>& args)
} }
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
SensorDevice& dev(SensorDevice::getInstance()); SensorDevice& dev(SensorDevice::getInstance());
if (args[0] == String16("restrict") && mMode == NORMAL) { if (args[0] == String16("restrict") && mCurrentOperatingMode == NORMAL) {
mMode = RESTRICTED; mCurrentOperatingMode = RESTRICTED;
dev.disableAllSensors(); dev.disableAllSensors();
// Clear all pending flush connections for all active sensors. If one of the active // Clear all pending flush connections for all active sensors. If one of the active
// connections has called flush() and the underlying sensor has been disabled before a // connections has called flush() and the underlying sensor has been disabled before a
@ -254,8 +254,8 @@ status_t SensorService::dump(int fd, const Vector<String16>& args)
for (size_t i=0 ; i< mActiveSensors.size(); ++i) { for (size_t i=0 ; i< mActiveSensors.size(); ++i) {
mActiveSensors.valueAt(i)->clearAllPendingFlushConnections(); mActiveSensors.valueAt(i)->clearAllPendingFlushConnections();
} }
} else if (args[0] == String16("enable") && mMode == RESTRICTED) { } else if (args[0] == String16("enable") && mCurrentOperatingMode == RESTRICTED) {
mMode = NORMAL; mCurrentOperatingMode = NORMAL;
dev.enableAllSensors(); dev.enableAllSensors();
} }
return status_t(NO_ERROR); return status_t(NO_ERROR);
@ -363,7 +363,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& args)
mSocketBufferSize/sizeof(sensors_event_t)); mSocketBufferSize/sizeof(sensors_event_t));
result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held"); result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held");
result.appendFormat("Mode :"); result.appendFormat("Mode :");
switch(mMode) { switch(mCurrentOperatingMode) {
case NORMAL: case NORMAL:
result.appendFormat(" NORMAL\n"); result.appendFormat(" NORMAL\n");
break; break;
@ -403,8 +403,9 @@ void SensorService::cleanupAutoDisabledSensorLocked(const sp<SensorEventConnecti
sensor->autoDisable(connection.get(), handle); sensor->autoDisable(connection.get(), handle);
cleanupWithoutDisableLocked(connection, handle); cleanupWithoutDisableLocked(connection, handle);
} }
} }
} }
} }
bool SensorService::threadLoop() bool SensorService::threadLoop()
@ -685,13 +686,76 @@ Vector<Sensor> SensorService::getSensorList()
return accessibleSensorList; return accessibleSensorList;
} }
sp<ISensorEventConnection> SensorService::createSensorEventConnection(const String8& packageName) sp<ISensorEventConnection> SensorService::createSensorEventConnection(const String8& packageName,
{ int requestedMode) {
// Only 2 modes supported for a SensorEventConnection ... NORMAL and DATA_INJECTION.
if (requestedMode != NORMAL && requestedMode != DATA_INJECTION) {
return NULL;
}
// DATA_INJECTION mode needs to have the required permissions set.
if (requestedMode == DATA_INJECTION && !hasDataInjectionPermissions()) {
return NULL;
}
Mutex::Autolock _l(mLock);
uid_t uid = IPCThreadState::self()->getCallingUid(); uid_t uid = IPCThreadState::self()->getCallingUid();
sp<SensorEventConnection> result(new SensorEventConnection(this, uid, packageName)); sp<SensorEventConnection> result(new SensorEventConnection(this, uid, packageName,
requestedMode == DATA_INJECTION));
if (requestedMode == DATA_INJECTION) {
if (mActiveConnections.indexOf(result) < 0) {
mActiveConnections.add(result);
}
// Add the associated file descriptor to the Looper for polling whenever there is data to
// be injected.
result->updateLooperRegistration(mLooper);
}
return result; return result;
} }
status_t SensorService::enableDataInjection(int requestedMode) {
if (!hasDataInjectionPermissions()) {
return INVALID_OPERATION;
}
Mutex::Autolock _l(mLock);
ALOGD_IF(DEBUG_CONNECTIONS, "SensorService::enableDataInjection %d", requestedMode);
SensorDevice& dev(SensorDevice::getInstance());
status_t err(NO_ERROR);
if (requestedMode == DATA_INJECTION) {
if (mCurrentOperatingMode == NORMAL) {
dev.disableAllSensors();
err = dev.setMode(requestedMode);
if (err == NO_ERROR) {
mCurrentOperatingMode = DATA_INJECTION;
} else {
// Re-enable sensors.
dev.enableAllSensors();
}
} else if (mCurrentOperatingMode == DATA_INJECTION) {
// Already in DATA_INJECTION mode. Treat this as a no_op.
return NO_ERROR;
} else {
// Transition to data injection mode supported only from NORMAL mode.
return INVALID_OPERATION;
}
} else if (requestedMode == NORMAL && mCurrentOperatingMode != NORMAL) {
err = resetToNormalModeLocked();
}
return err;
}
status_t SensorService::resetToNormalMode() {
Mutex::Autolock _l(mLock);
return resetToNormalModeLocked();
}
status_t SensorService::resetToNormalModeLocked() {
SensorDevice& dev(SensorDevice::getInstance());
dev.enableAllSensors();
status_t err = dev.setMode(NORMAL);
mCurrentOperatingMode = NORMAL;
return err;
}
void SensorService::cleanupConnection(SensorEventConnection* c) void SensorService::cleanupConnection(SensorEventConnection* c)
{ {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
@ -753,7 +817,7 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection,
} }
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
if (mMode == RESTRICTED && !isWhiteListedPackage(connection->getPackageName())) { if (mCurrentOperatingMode == RESTRICTED && !isWhiteListedPackage(connection->getPackageName())) {
return INVALID_OPERATION; return INVALID_OPERATION;
} }
@ -960,6 +1024,15 @@ bool SensorService::verifyCanAccessSensor(const Sensor& sensor, const char* oper
} }
} }
bool SensorService::hasDataInjectionPermissions() {
if (!PermissionCache::checkCallingPermission(sDataInjectionPermission)) {
ALOGE("Permission Denial trying to activate data injection without"
" the required permission");
return false;
}
return true;
}
void SensorService::checkWakeLockState() { void SensorService::checkWakeLockState() {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
checkWakeLockStateLocked(); checkWakeLockStateLocked();
@ -1071,9 +1144,10 @@ void SensorService::SensorRecord::clearAllPendingFlushConnections() {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
SensorService::SensorEventConnection::SensorEventConnection( SensorService::SensorEventConnection::SensorEventConnection(
const sp<SensorService>& service, uid_t uid, String8 packageName) const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode)
: mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false), : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
mDead(false), mEventCache(NULL), mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName) { mDead(false), mEventCache(NULL), mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName),
mDataInjectionMode(isDataInjectionMode) {
mChannel = new BitTube(mService->mSocketBufferSize); mChannel = new BitTube(mService->mSocketBufferSize);
#if DEBUG_CONNECTIONS #if DEBUG_CONNECTIONS
mEventsReceived = mEventsSentFromCache = mEventsSent = 0; mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@ -1105,6 +1179,7 @@ void SensorService::SensorEventConnection::resetWakeLockRefCount() {
void SensorService::SensorEventConnection::dump(String8& result) { void SensorService::SensorEventConnection::dump(String8& result) {
Mutex::Autolock _l(mConnectionLock); Mutex::Autolock _l(mConnectionLock);
result.appendFormat("Operating Mode: %s\n", mDataInjectionMode ? "DATA_INJECTION" : "NORMAL");
result.appendFormat("\t%s | WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n", result.appendFormat("\t%s | WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n",
mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize, mMaxCacheSize); mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize, mMaxCacheSize);
for (size_t i = 0; i < mSensorInfo.size(); ++i) { for (size_t i = 0; i < mSensorInfo.size(); ++i) {
@ -1190,7 +1265,8 @@ void SensorService::SensorEventConnection::updateLooperRegistration(const sp<Loo
void SensorService::SensorEventConnection::updateLooperRegistrationLocked( void SensorService::SensorEventConnection::updateLooperRegistrationLocked(
const sp<Looper>& looper) { const sp<Looper>& looper) {
bool isConnectionActive = mSensorInfo.size() > 0; bool isConnectionActive = (mSensorInfo.size() > 0 && !mDataInjectionMode) ||
mDataInjectionMode;
// If all sensors are unregistered OR Looper has encountered an error, we // If all sensors are unregistered OR Looper has encountered an error, we
// can remove the Fd from the Looper if it has been previously added. // can remove the Fd from the Looper if it has been previously added.
if (!isConnectionActive || mDead) { if (!isConnectionActive || mDead) {
@ -1204,6 +1280,7 @@ void SensorService::SensorEventConnection::updateLooperRegistrationLocked(
int looper_flags = 0; int looper_flags = 0;
if (mCacheSize > 0) looper_flags |= ALOOPER_EVENT_OUTPUT; if (mCacheSize > 0) looper_flags |= ALOOPER_EVENT_OUTPUT;
if (mDataInjectionMode) looper_flags |= ALOOPER_EVENT_INPUT;
for (size_t i = 0; i < mSensorInfo.size(); ++i) { for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const int handle = mSensorInfo.keyAt(i); const int handle = mSensorInfo.keyAt(i);
if (mService->getSensorFromHandle(handle).isWakeUpSensor()) { if (mService->getSensorFromHandle(handle).isWakeUpSensor()) {
@ -1570,26 +1647,55 @@ int SensorService::SensorEventConnection::handleEvent(int fd, int events, void*
updateLooperRegistrationLocked(mService->getLooper()); updateLooperRegistrationLocked(mService->getLooper());
} }
mService->checkWakeLockState(); mService->checkWakeLockState();
if (mDataInjectionMode) {
// If the Looper has encountered some error in data injection mode, reset SensorService
// back to normal mode.
mService->resetToNormalMode();
mDataInjectionMode = false;
}
return 1; return 1;
} }
if (events & ALOOPER_EVENT_INPUT) { if (events & ALOOPER_EVENT_INPUT) {
uint32_t numAcks = 0; unsigned char buf[sizeof(sensors_event_t)];
ssize_t ret = ::recv(fd, &numAcks, sizeof(numAcks), MSG_DONTWAIT); ssize_t numBytesRead = ::recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
{ {
Mutex::Autolock _l(mConnectionLock); Mutex::Autolock _l(mConnectionLock);
// Sanity check to ensure there are no read errors in recv, numAcks is always if (numBytesRead == sizeof(sensors_event_t)) {
// within the range and not zero. If any of the above don't hold reset mWakeLockRefCount if (!mDataInjectionMode) {
// to zero. ALOGE("Data injected in normal mode, dropping event"
if (ret != sizeof(numAcks) || numAcks > mWakeLockRefCount || numAcks == 0) { "package=%s uid=%d", mPackageName.string(), mUid);
ALOGE("Looper read error ret=%d numAcks=%d", ret, numAcks); // Unregister call backs.
mWakeLockRefCount = 0; return 0;
} else { }
mWakeLockRefCount -= numAcks; SensorDevice& dev(SensorDevice::getInstance());
} sensors_event_t sensor_event;
memset(&sensor_event, 0, sizeof(sensor_event));
memcpy(&sensor_event, buf, sizeof(sensors_event_t));
Sensor sensor = mService->getSensorFromHandle(sensor_event.sensor);
sensor_event.type = sensor.getType();
dev.injectSensorData(&sensor_event, 1);
#if DEBUG_CONNECTIONS #if DEBUG_CONNECTIONS
mTotalAcksReceived += numAcks; ++mEventsReceived;
#endif #endif
} else if (numBytesRead == sizeof(uint32_t)) {
uint32_t numAcks = 0;
memcpy(&numAcks, buf, sizeof(numBytesRead));
// Sanity check to ensure there are no read errors in recv, numAcks is always
// within the range and not zero. If any of the above don't hold reset
// mWakeLockRefCount to zero.
if (numAcks > 0 && numAcks < mWakeLockRefCount) {
mWakeLockRefCount -= numAcks;
} else {
mWakeLockRefCount = 0;
}
#if DEBUG_CONNECTIONS
mTotalAcksReceived += numAcks;
#endif
} else {
// Read error, reset wakelock refcount.
mWakeLockRefCount = 0;
}
} }
// Check if wakelock can be released by sensorservice. mConnectionLock needs to be released // Check if wakelock can be released by sensorservice. mConnectionLock needs to be released
// here as checkWakeLockState() will need it. // here as checkWakeLockState() will need it.

View File

@ -70,21 +70,33 @@ class SensorService :
// The regular operating mode where any application can register/unregister/call flush on // The regular operating mode where any application can register/unregister/call flush on
// sensors. // sensors.
NORMAL = 0, NORMAL = 0,
// This mode is only used for testing purposes. Not all HALs support this mode. In this
// mode, the HAL ignores the sensor data provided by physical sensors and accepts the data
// that is injected from the SensorService as if it were the real sensor data. This mode
// is primarily used for testing various algorithms like vendor provided SensorFusion,
// Step Counter and Step Detector etc. Typically in this mode, there will be a client
// (a SensorEventConnection) which will be injecting sensor data into the HAL. Normal apps
// can unregister and register for any sensor that supports injection. Registering to sensors
// that do not support injection will give an error.
// TODO(aakella) : Allow exactly one client to inject sensor data at a time.
DATA_INJECTION = 1,
// This mode is used only for testing sensors. Each sensor can be tested in isolation with // This mode is used only for testing sensors. Each sensor can be tested in isolation with
// the required sampling_rate and maxReportLatency parameters without having to think about // the required sampling_rate and maxReportLatency parameters without having to think about
// the data rates requested by other applications. End user devices are always expected to be // the data rates requested by other applications. End user devices are always expected to be
// in NORMAL mode. When this mode is first activated, all active sensors from all connections // in NORMAL mode. When this mode is first activated, all active sensors from all connections
// are disabled. Calling flush() will return an error. In this mode, only the requests from // are disabled. Calling flush() will return an error. In this mode, only the requests from
// selected apps whose package names are whitelisted are allowed (typically CTS apps). Only // selected apps whose package names are whitelisted are allowed (typically CTS apps). Only
// these apps can register/unregister/call flush() on sensors. If SensorService switches to // these apps can register/unregister/call flush() on sensors. If SensorService switches to
// NORMAL mode again, all sensors that were previously registered to are activated with the // NORMAL mode again, all sensors that were previously registered to are activated with the
// corresponding paramaters if the application hasn't unregistered for sensors in the mean // corresponding paramaters if the application hasn't unregistered for sensors in the mean
// time. // time.
// NOTE: Non whitelisted app whose sensors were previously deactivated may still receive // NOTE: Non whitelisted app whose sensors were previously deactivated may still receive
// events if a whitelisted app requests data from the same sensor. // events if a whitelisted app requests data from the same sensor.
RESTRICTED, RESTRICTED = 2
// TODO: This mode hasn't been implemented yet.
DATA_INJECTION // State Transitions supported.
// RESTRICTED <--- NORMAL ---> DATA_INJECTION
// ---> <---
}; };
static const char* WAKE_LOCK_NAME; static const char* WAKE_LOCK_NAME;
@ -100,7 +112,9 @@ class SensorService :
// ISensorServer interface // ISensorServer interface
virtual Vector<Sensor> getSensorList(); virtual Vector<Sensor> getSensorList();
virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName); virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
int requestedMode);
virtual status_t enableDataInjection(int enable);
virtual status_t dump(int fd, const Vector<String16>& args); virtual status_t dump(int fd, const Vector<String16>& args);
class SensorEventConnection : public BnSensorEventConnection, public LooperCallback { class SensorEventConnection : public BnSensorEventConnection, public LooperCallback {
@ -177,6 +191,8 @@ class SensorService :
// mWakeLockRefCount is reset to zero. needsWakeLock method will always return false, if // mWakeLockRefCount is reset to zero. needsWakeLock method will always return false, if
// this flag is set. // this flag is set.
bool mDead; bool mDead;
bool mDataInjectionMode;
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.
// They are sent separately before the next batch of events. // They are sent separately before the next batch of events.
@ -191,14 +207,14 @@ class SensorService :
sensors_event_t *mEventCache; sensors_event_t *mEventCache;
int mCacheSize, mMaxCacheSize; int mCacheSize, mMaxCacheSize;
String8 mPackageName; String8 mPackageName;
#if DEBUG_CONNECTIONS #if DEBUG_CONNECTIONS
int mEventsReceived, mEventsSent, mEventsSentFromCache; int mEventsReceived, mEventsSent, mEventsSentFromCache;
int mTotalAcksNeeded, mTotalAcksReceived; int mTotalAcksNeeded, mTotalAcksReceived;
#endif #endif
public: public:
SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName); SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName,
bool isDataInjectionMode);
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, sensors_event_t* scratch,
@ -257,6 +273,7 @@ class SensorService :
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);
static bool hasDataInjectionPermissions();
// SensorService acquires a partial wakelock for delivering events from wake up sensors. This // 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 // method checks whether all the events from these wake up sensors have been delivered to the
// corresponding applications, if yes the wakelock is released. // corresponding applications, if yes the wakelock is released.
@ -290,6 +307,10 @@ class SensorService :
// allowed. // allowed.
bool isWhiteListedPackage(const String8& packageName); bool isWhiteListedPackage(const String8& packageName);
// Reset the state of SensorService to NORMAL mode.
status_t resetToNormalMode();
status_t resetToNormalModeLocked();
// constants // constants
Vector<Sensor> mSensorList; Vector<Sensor> mSensorList;
Vector<Sensor> mUserSensorListDebug; Vector<Sensor> mUserSensorListDebug;
@ -311,7 +332,7 @@ class SensorService :
bool mWakeLockAcquired; bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch; sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
SensorEventConnection const **mMapFlushEventsToConnections; SensorEventConnection const **mMapFlushEventsToConnections;
Mode mMode; Mode mCurrentOperatingMode;
// 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;