summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/gui/ISensorServer.h4
-rw-r--r--include/gui/SensorEventQueue.h2
-rw-r--r--include/gui/SensorManager.h3
-rw-r--r--libs/gui/ISensorServer.cpp23
-rw-r--r--libs/gui/SensorEventQueue.cpp10
-rw-r--r--libs/gui/SensorManager.cpp21
-rw-r--r--services/sensorservice/SensorDevice.cpp23
-rw-r--r--services/sensorservice/SensorDevice.h2
-rw-r--r--services/sensorservice/SensorService.cpp164
-rw-r--r--services/sensorservice/SensorService.h37
10 files changed, 239 insertions, 50 deletions
diff --git a/include/gui/ISensorServer.h b/include/gui/ISensorServer.h
index 9a29cb5..ee3484c 100644
--- a/include/gui/ISensorServer.h
+++ b/include/gui/ISensorServer.h
@@ -38,7 +38,9 @@ public:
DECLARE_META_INTERFACE(SensorServer);
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;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h
index 02b3d38..b70957b 100644
--- a/include/gui/SensorEventQueue.h
+++ b/include/gui/SensorEventQueue.h
@@ -77,6 +77,8 @@ public:
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);
+
+ status_t injectSensorEvent(const ASensorEvent& event);
private:
sp<Looper> getLooper() const;
sp<ISensorEventConnection> mSensorEventConnection;
diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h
index 1afff68..19c2bdc 100644
--- a/include/gui/SensorManager.h
+++ b/include/gui/SensorManager.h
@@ -53,7 +53,8 @@ public:
ssize_t getSensorList(Sensor const* const** list) const;
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:
// DeathRecipient interface
diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp
index 3c85ec0..140712e 100644
--- a/libs/gui/ISensorServer.cpp
+++ b/libs/gui/ISensorServer.cpp
@@ -35,6 +35,7 @@ namespace android {
enum {
GET_SENSOR_LIST = IBinder::FIRST_CALL_TRANSACTION,
CREATE_SENSOR_EVENT_CONNECTION,
+ ENABLE_DATA_INJECTION
};
class BpSensorServer : public BpInterface<ISensorServer>
@@ -63,14 +64,24 @@ public:
return v;
}
- virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName)
+ virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
+ int mode)
{
Parcel data, reply;
data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
data.writeString8(packageName);
+ data.writeInt32(mode);
remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply);
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
@@ -98,10 +109,18 @@ status_t BnSensorServer::onTransact(
case CREATE_SENSOR_EVENT_CONNECTION: {
CHECK_INTERFACE(ISensorServer, data, reply);
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));
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);
}
diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp
index 76ae470..b5b5d68 100644
--- a/libs/gui/SensorEventQueue.cpp
+++ b/libs/gui/SensorEventQueue.cpp
@@ -149,6 +149,16 @@ status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const
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) {
for (int i = 0; i < count; ++i) {
if (events[i].flags & WAKE_UP_SENSOR_EVENT_NEEDS_ACK) {
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 142c6ec..cedcf56 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -100,8 +100,6 @@ status_t SensorManager::assertStateLocked() const {
return NO_ERROR;
}
-
-
ssize_t SensorManager::getSensorList(Sensor const* const** list) const
{
Mutex::Autolock _l(mLock);
@@ -139,18 +137,17 @@ Sensor const* SensorManager::getDefaultSensor(int type)
return NULL;
}
-sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName)
-{
+sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName, int mode) {
sp<SensorEventQueue> queue;
Mutex::Autolock _l(mLock);
while (assertStateLocked() == NO_ERROR) {
sp<ISensorEventConnection> connection =
- mSensorServer->createSensorEventConnection(packageName);
+ mSensorServer->createSensorEventConnection(packageName, mode);
if (connection == NULL) {
- // SensorService just died.
- ALOGE("createEventQueue: connection is NULL. SensorService died.");
- continue;
+ // SensorService just died or the app doesn't have required permissions.
+ ALOGE("createEventQueue: connection is NULL.");
+ return NULL;
}
queue = new SensorEventQueue(connection);
break;
@@ -158,5 +155,13 @@ sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName)
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
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 30a244b..3bcbd58 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -367,7 +367,7 @@ void SensorDevice::enableAllSensors() {
void SensorDevice::disableAllSensors() {
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);
// Check if this sensor has been activated previously and disable it.
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() {
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index cf33a59..4b3fe85 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -98,9 +98,11 @@ public:
// Call batch with timeout zero instead of calling setDelay() for newer devices.
status_t setDelay(void* ident, int handle, int64_t ns);
status_t flush(void* ident, int handle);
+ status_t setMode(uint32_t mode);
void disableAllSensors();
void enableAllSensors();
void autoDisable(void *ident, int handle);
+ status_t injectSensorData(const sensors_event_t *event, size_t count);
void dump(String8& result);
};
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 2336d88..c8dc6ec 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -64,6 +64,9 @@ namespace android {
*/
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()
: mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),
@@ -74,7 +77,6 @@ SensorService::SensorService()
void SensorService::onFirstRef()
{
ALOGD("nuSensorService starting...");
-
SensorDevice& dev(SensorDevice::getInstance());
if (dev.initCheck() == NO_ERROR) {
@@ -190,7 +192,7 @@ void SensorService::onFirstRef()
mSensorEventBuffer = new sensors_event_t[minBufferSize];
mSensorEventScratch = new sensors_event_t[minBufferSize];
mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
- mMode = NORMAL;
+ mCurrentOperatingMode = NORMAL;
mAckReceiver = new SensorEventAckReceiver(this);
mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
@@ -229,8 +231,6 @@ SensorService::~SensorService()
delete mSensorMap.valueAt(i);
}
-static const String16 sDump("android.permission.DUMP");
-
status_t SensorService::dump(int fd, const Vector<String16>& args)
{
String8 result;
@@ -245,8 +245,8 @@ status_t SensorService::dump(int fd, const Vector<String16>& args)
}
Mutex::Autolock _l(mLock);
SensorDevice& dev(SensorDevice::getInstance());
- if (args[0] == String16("restrict") && mMode == NORMAL) {
- mMode = RESTRICTED;
+ if (args[0] == String16("restrict") && mCurrentOperatingMode == NORMAL) {
+ mCurrentOperatingMode = RESTRICTED;
dev.disableAllSensors();
// 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
@@ -254,8 +254,8 @@ status_t SensorService::dump(int fd, const Vector<String16>& args)
for (size_t i=0 ; i< mActiveSensors.size(); ++i) {
mActiveSensors.valueAt(i)->clearAllPendingFlushConnections();
}
- } else if (args[0] == String16("enable") && mMode == RESTRICTED) {
- mMode = NORMAL;
+ } else if (args[0] == String16("enable") && mCurrentOperatingMode == RESTRICTED) {
+ mCurrentOperatingMode = NORMAL;
dev.enableAllSensors();
}
return status_t(NO_ERROR);
@@ -363,7 +363,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& args)
mSocketBufferSize/sizeof(sensors_event_t));
result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held");
result.appendFormat("Mode :");
- switch(mMode) {
+ switch(mCurrentOperatingMode) {
case NORMAL:
result.appendFormat(" NORMAL\n");
break;
@@ -403,8 +403,9 @@ void SensorService::cleanupAutoDisabledSensorLocked(const sp<SensorEventConnecti
sensor->autoDisable(connection.get(), handle);
cleanupWithoutDisableLocked(connection, handle);
}
+
}
- }
+ }
}
bool SensorService::threadLoop()
@@ -685,13 +686,76 @@ Vector<Sensor> SensorService::getSensorList()
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();
- 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;
}
+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)
{
Mutex::Autolock _l(mLock);
@@ -753,7 +817,7 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection,
}
Mutex::Autolock _l(mLock);
- if (mMode == RESTRICTED && !isWhiteListedPackage(connection->getPackageName())) {
+ if (mCurrentOperatingMode == RESTRICTED && !isWhiteListedPackage(connection->getPackageName())) {
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() {
Mutex::Autolock _l(mLock);
checkWakeLockStateLocked();
@@ -1071,9 +1144,10 @@ void SensorService::SensorRecord::clearAllPendingFlushConnections() {
// ---------------------------------------------------------------------------
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),
- 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);
#if DEBUG_CONNECTIONS
mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@@ -1105,6 +1179,7 @@ void SensorService::SensorEventConnection::resetWakeLockRefCount() {
void SensorService::SensorEventConnection::dump(String8& result) {
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",
mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize, mMaxCacheSize);
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
@@ -1190,7 +1265,8 @@ void SensorService::SensorEventConnection::updateLooperRegistration(const sp<Loo
void SensorService::SensorEventConnection::updateLooperRegistrationLocked(
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
// can remove the Fd from the Looper if it has been previously added.
if (!isConnectionActive || mDead) {
@@ -1204,6 +1280,7 @@ void SensorService::SensorEventConnection::updateLooperRegistrationLocked(
int looper_flags = 0;
if (mCacheSize > 0) looper_flags |= ALOOPER_EVENT_OUTPUT;
+ if (mDataInjectionMode) looper_flags |= ALOOPER_EVENT_INPUT;
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const int handle = mSensorInfo.keyAt(i);
if (mService->getSensorFromHandle(handle).isWakeUpSensor()) {
@@ -1570,26 +1647,55 @@ int SensorService::SensorEventConnection::handleEvent(int fd, int events, void*
updateLooperRegistrationLocked(mService->getLooper());
}
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;
}
if (events & ALOOPER_EVENT_INPUT) {
- uint32_t numAcks = 0;
- ssize_t ret = ::recv(fd, &numAcks, sizeof(numAcks), MSG_DONTWAIT);
+ unsigned char buf[sizeof(sensors_event_t)];
+ ssize_t numBytesRead = ::recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
{
Mutex::Autolock _l(mConnectionLock);
- // 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 (ret != sizeof(numAcks) || numAcks > mWakeLockRefCount || numAcks == 0) {
- ALOGE("Looper read error ret=%d numAcks=%d", ret, numAcks);
- mWakeLockRefCount = 0;
- } else {
- mWakeLockRefCount -= numAcks;
- }
+ if (numBytesRead == sizeof(sensors_event_t)) {
+ if (!mDataInjectionMode) {
+ ALOGE("Data injected in normal mode, dropping event"
+ "package=%s uid=%d", mPackageName.string(), mUid);
+ // Unregister call backs.
+ return 0;
+ }
+ 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
- mTotalAcksReceived += numAcks;
+ ++mEventsReceived;
#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
// here as checkWakeLockState() will need it.
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index b31eaf3..4d34471 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -70,21 +70,33 @@ class SensorService :
// The regular operating mode where any application can register/unregister/call flush on
// sensors.
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
// 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
// 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
// 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
// corresponding paramaters if the application hasn't unregistered for sensors in the mean
// time.
// NOTE: Non whitelisted app whose sensors were previously deactivated may still receive
// events if a whitelisted app requests data from the same sensor.
- RESTRICTED,
- // TODO: This mode hasn't been implemented yet.
- DATA_INJECTION
+ RESTRICTED = 2
+
+ // State Transitions supported.
+ // RESTRICTED <--- NORMAL ---> DATA_INJECTION
+ // ---> <---
};
static const char* WAKE_LOCK_NAME;
@@ -100,7 +112,9 @@ class SensorService :
// ISensorServer interface
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);
class SensorEventConnection : public BnSensorEventConnection, public LooperCallback {
@@ -177,6 +191,8 @@ class SensorService :
// mWakeLockRefCount is reset to zero. needsWakeLock method will always return false, if
// this flag is set.
bool mDead;
+
+ bool mDataInjectionMode;
struct FlushInfo {
// The number of flush complete events dropped for this sensor is stored here.
// They are sent separately before the next batch of events.
@@ -191,14 +207,14 @@ class SensorService :
sensors_event_t *mEventCache;
int mCacheSize, mMaxCacheSize;
String8 mPackageName;
-
#if DEBUG_CONNECTIONS
int mEventsReceived, mEventsSent, mEventsSentFromCache;
int mTotalAcksNeeded, mTotalAcksReceived;
#endif
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,
sensors_event_t* scratch,
@@ -257,6 +273,7 @@ class SensorService :
sensors_event_t const* buffer, const int count);
static bool canAccessSensor(const Sensor& sensor);
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
// method checks whether all the events from these wake up sensors have been delivered to the
// corresponding applications, if yes the wakelock is released.
@@ -290,6 +307,10 @@ class SensorService :
// allowed.
bool isWhiteListedPackage(const String8& packageName);
+ // Reset the state of SensorService to NORMAL mode.
+ status_t resetToNormalMode();
+ status_t resetToNormalModeLocked();
+
// constants
Vector<Sensor> mSensorList;
Vector<Sensor> mUserSensorListDebug;
@@ -311,7 +332,7 @@ class SensorService :
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
SensorEventConnection const **mMapFlushEventsToConnections;
- Mode mMode;
+ Mode mCurrentOperatingMode;
// The size of this vector is constant, only the items are mutable
KeyedVector<int32_t, sensors_event_t> mLastEventSeen;