diff --git a/include/gui/ISensorServer.h b/include/gui/ISensorServer.h index 9a29cb567..ee3484cc5 100644 --- a/include/gui/ISensorServer.h +++ b/include/gui/ISensorServer.h @@ -38,7 +38,9 @@ public: DECLARE_META_INTERFACE(SensorServer); virtual Vector getSensorList() = 0; - virtual sp createSensorEventConnection(const String8& packageName) = 0; + virtual sp 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 02b3d385b..b70957b2c 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 getLooper() const; sp mSensorEventConnection; diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h index 1afff6858..19c2bdccd 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 createEventQueue(String8 packageName = String8("")); + sp 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 3c85ec0f9..140712eb2 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 @@ -63,14 +64,24 @@ public: return v; } - virtual sp createSensorEventConnection(const String8& packageName) + virtual sp 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(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 connection(createSensorEventConnection(packageName)); + int32_t mode = data.readInt32(); + sp 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(ret)); + return NO_ERROR; + } } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp index 76ae47034..b5b5d684d 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 142c6ec09..cedcf5637 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 SensorManager::createEventQueue(String8 packageName) -{ +sp SensorManager::createEventQueue(String8 packageName, int mode) { sp queue; Mutex::Autolock _l(mLock); while (assertStateLocked() == NO_ERROR) { sp 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 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 30a244b32..3bcbd5834 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 cf33a5992..4b3fe85dc 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 2336d881a..c8dc6eccf 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& args) { String8 result; @@ -245,8 +245,8 @@ status_t SensorService::dump(int fd, const Vector& 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& 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& 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 spautoDisable(connection.get(), handle); cleanupWithoutDisableLocked(connection, handle); } + } - } + } } bool SensorService::threadLoop() @@ -685,13 +686,76 @@ Vector SensorService::getSensorList() return accessibleSensorList; } -sp SensorService::createSensorEventConnection(const String8& packageName) -{ +sp 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 result(new SensorEventConnection(this, uid, packageName)); + sp 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& 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& service, uid_t uid, String8 packageName) + const sp& 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& 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 b31eaf398..4d34471ac 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 getSensorList(); - virtual sp createSensorEventConnection(const String8& packageName); + virtual sp createSensorEventConnection(const String8& packageName, + int requestedMode); + virtual status_t enableDataInjection(int enable); virtual status_t dump(int fd, const Vector& 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& service, uid_t uid, String8 packageName); + SensorEventConnection(const sp& 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 mSensorList; Vector 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 mLastEventSeen;