diff --git a/include/gui/ISensorServer.h b/include/gui/ISensorServer.h index 9c8afc5a0..9a29cb567 100644 --- a/include/gui/ISensorServer.h +++ b/include/gui/ISensorServer.h @@ -30,6 +30,7 @@ namespace android { class Sensor; class ISensorEventConnection; +class String8; class ISensorServer : public IInterface { @@ -37,7 +38,7 @@ public: DECLARE_META_INTERFACE(SensorServer); virtual Vector getSensorList() = 0; - virtual sp createSensorEventConnection() = 0; + virtual sp createSensorEventConnection(const String8& packageName) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h index 3176462db..7d4327394 100644 --- a/include/gui/SensorManager.h +++ b/include/gui/SensorManager.h @@ -40,7 +40,7 @@ namespace android { class ISensorServer; class Sensor; class SensorEventQueue; - +class String8; // ---------------------------------------------------------------------------- class SensorManager : @@ -53,7 +53,7 @@ public: ssize_t getSensorList(Sensor const* const** list) const; Sensor const* getDefaultSensor(int type); - sp createEventQueue(); + sp createEventQueue(String8 packageName = String8("")); private: // DeathRecipient interface diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp index 8e09e7ca7..3c85ec0f9 100644 --- a/libs/gui/ISensorServer.cpp +++ b/libs/gui/ISensorServer.cpp @@ -63,10 +63,11 @@ public: return v; } - virtual sp createSensorEventConnection() + virtual sp createSensorEventConnection(const String8& packageName) { Parcel data, reply; data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor()); + data.writeString8(packageName); remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply); return interface_cast(reply.readStrongBinder()); } @@ -96,7 +97,8 @@ status_t BnSensorServer::onTransact( } case CREATE_SENSOR_EVENT_CONNECTION: { CHECK_INTERFACE(ISensorServer, data, reply); - sp connection(createSensorEventConnection()); + String8 packageName = data.readString8(); + sp connection(createSensorEventConnection(packageName)); reply->writeStrongBinder(IInterface::asBinder(connection)); return NO_ERROR; } diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp index d6df40407..142c6ec09 100644 --- a/libs/gui/SensorManager.cpp +++ b/libs/gui/SensorManager.cpp @@ -139,14 +139,14 @@ Sensor const* SensorManager::getDefaultSensor(int type) return NULL; } -sp SensorManager::createEventQueue() +sp SensorManager::createEventQueue(String8 packageName) { sp queue; Mutex::Autolock _l(mLock); while (assertStateLocked() == NO_ERROR) { sp connection = - mSensorServer->createSensorEventConnection(); + mSensorServer->createSensorEventConnection(packageName); if (connection == NULL) { // SensorService just died. ALOGE("createEventQueue: connection is NULL. SensorService died."); diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index 80845a287..30a244b32 100644 --- a/services/sensorservice/SensorDevice.cpp +++ b/services/sensorservice/SensorDevice.cpp @@ -85,6 +85,7 @@ void SensorDevice::dump(String8& result) Mutex::Autolock _l(mLock); for (size_t i=0 ; i= 0) { - if (info.batchParams.size() == 1) { + if (info.numActiveClients() == 1) { // This is the first connection, we need to activate the underlying h/w sensor. actuateHardware = true; } @@ -160,7 +165,7 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled) ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident)); if (info.removeBatchParamsForIdent(ident) >= 0) { - if (info.batchParams.size() == 0) { + if (info.numActiveClients() == 0) { // This is the last connection, we need to de-activate the underlying h/w sensor. actuateHardware = true; } else { @@ -181,10 +186,15 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled) } else { // sensor wasn't enabled for this ident } + + if (isClientDisabledLocked(ident)) { + return NO_ERROR; + } } if (actuateHardware) { - ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle, enabled); + ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle, + enabled); err = mSensorDevice->activate( reinterpret_cast (mSensorDevice), handle, enabled); ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle, @@ -197,7 +207,7 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled) } // On older devices which do not support batch, call setDelay(). - if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.batchParams.size() > 0) { + if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.numActiveClients() > 0) { ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w setDelay %d %" PRId64, handle, info.bestBatchParams.batchDelay); mSensorDevice->setDelay( @@ -279,6 +289,7 @@ status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodN samplingPeriodNs = MINIMUM_EVENTS_PERIOD; } Mutex::Autolock _l(mLock); + if (isClientDisabledLocked(ident)) return INVALID_OPERATION; Info& info( mActivationCount.editValueFor(handle) ); // If the underlying sensor is NOT in continuous mode, setDelay() should return an error. // Calling setDelay() in batch mode is an invalid operation. @@ -298,7 +309,6 @@ status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodN int SensorDevice::getHalDeviceVersion() const { if (!mSensorDevice) return -1; - return mSensorDevice->common.version; } @@ -306,12 +316,89 @@ status_t SensorDevice::flush(void* ident, int handle) { if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) { return INVALID_OPERATION; } + if (isClientDisabled(ident)) return INVALID_OPERATION; ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle); return mSensorDevice->flush(mSensorDevice, handle); } +bool SensorDevice::isClientDisabled(void* ident) { + Mutex::Autolock _l(mLock); + return isClientDisabledLocked(ident); +} + +bool SensorDevice::isClientDisabledLocked(void* ident) { + return mDisabledClients.indexOf(ident) >= 0; +} + +void SensorDevice::enableAllSensors() { + Mutex::Autolock _l(mLock); + mDisabledClients.clear(); + const int halVersion = getHalDeviceVersion(); + for (size_t i = 0; i< mActivationCount.size(); ++i) { + Info& info = mActivationCount.editValueAt(i); + if (info.batchParams.isEmpty()) continue; + info.selectBatchParams(); + const int sensor_handle = mActivationCount.keyAt(i); + ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ", + sensor_handle); + status_t err(NO_ERROR); + if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) { + err = mSensorDevice->batch(mSensorDevice, sensor_handle, + info.bestBatchParams.flags, info.bestBatchParams.batchDelay, + info.bestBatchParams.batchTimeout); + ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err)); + } + + if (err == NO_ERROR) { + err = mSensorDevice->activate( + reinterpret_cast(mSensorDevice), + sensor_handle, 1); + ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err)); + } + + if (halVersion <= SENSORS_DEVICE_API_VERSION_1_0) { + err = mSensorDevice->setDelay( + reinterpret_cast(mSensorDevice), + sensor_handle, info.bestBatchParams.batchDelay); + ALOGE_IF(err, "Error calling setDelay sensor %d (%s)", sensor_handle, strerror(-err)); + } + } +} + +void SensorDevice::disableAllSensors() { + Mutex::Autolock _l(mLock); + 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) { + const int sensor_handle = mActivationCount.keyAt(i); + ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ", + sensor_handle); + mSensorDevice->activate( + reinterpret_cast (mSensorDevice), + sensor_handle, 0); + // Add all the connections that were registered for this sensor to the disabled + // clients list. + for (int j = 0; j < info.batchParams.size(); ++j) { + mDisabledClients.add(info.batchParams.keyAt(j)); + } + } + } +} + // --------------------------------------------------------------------------- +int SensorDevice::Info::numActiveClients() { + SensorDevice& device(SensorDevice::getInstance()); + int num = 0; + for (size_t i = 0; i < batchParams.size(); ++i) { + if (!device.isClientDisabledLocked(batchParams.keyAt(i))) { + ++num; + } + } + return num; +} + status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags, int64_t samplingPeriodNs, int64_t maxBatchReportLatencyNs) { @@ -329,19 +416,16 @@ status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags, } void SensorDevice::Info::selectBatchParams() { - BatchParams bestParams(-1, -1, -1); + BatchParams bestParams(0, -1, -1); + SensorDevice& device(SensorDevice::getInstance()); - if (batchParams.size() > 0) { - BatchParams params = batchParams.valueAt(0); - bestParams = params; - } - - for (size_t i = 1; i < batchParams.size(); ++i) { + for (size_t i = 0; i < batchParams.size(); ++i) { + if (device.isClientDisabledLocked(batchParams.keyAt(i))) continue; BatchParams params = batchParams.valueAt(i); - if (params.batchDelay < bestParams.batchDelay) { + if (bestParams.batchDelay == -1 || params.batchDelay < bestParams.batchDelay) { bestParams.batchDelay = params.batchDelay; } - if (params.batchTimeout < bestParams.batchTimeout) { + if (bestParams.batchTimeout == -1 || params.batchTimeout < bestParams.batchTimeout) { bestParams.batchTimeout = params.batchTimeout; } } diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h index 761b48cf5..cf33a5992 100644 --- a/services/sensorservice/SensorDevice.h +++ b/services/sensorservice/SensorDevice.h @@ -42,6 +42,7 @@ class SensorDevice : public Singleton { // Struct to store all the parameters(samplingPeriod, maxBatchReportLatency and flags) from // batch call. For continous mode clients, maxBatchReportLatency is set to zero. struct BatchParams { + // TODO: Get rid of flags parameter everywhere. int flags; nsecs_t batchDelay, batchTimeout; BatchParams() : flags(0), batchDelay(0), batchTimeout(0) {} @@ -65,7 +66,7 @@ class SensorDevice : public Singleton { // requested by the client. KeyedVector batchParams; - Info() : bestBatchParams(-1, -1, -1) {} + Info() : bestBatchParams(0, -1, -1) {} // Sets batch parameters for this ident. Returns error if this ident is not already present // in the KeyedVector above. status_t setBatchParamsForIdent(void* ident, int flags, int64_t samplingPeriodNs, @@ -75,10 +76,17 @@ class SensorDevice : public Singleton { // Removes batchParams for an ident and re-computes bestBatchParams. Returns the index of // the removed ident. If index >=0, ident is present and successfully removed. ssize_t removeBatchParamsForIdent(void* ident); + + int numActiveClients(); }; DefaultKeyedVector mActivationCount; + // Use this vector to determine which client is activated or deactivated. + SortedVector mDisabledClients; SensorDevice(); + + bool isClientDisabled(void* ident); + bool isClientDisabledLocked(void* ident); public: ssize_t getSensorList(sensor_t const** list); status_t initCheck() const; @@ -90,6 +98,8 @@ 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); + void disableAllSensors(); + void enableAllSensors(); void autoDisable(void *ident, int handle); void dump(String8& result); }; diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index a857366fb..2336d881a 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -190,6 +190,7 @@ void SensorService::onFirstRef() mSensorEventBuffer = new sensors_event_t[minBufferSize]; mSensorEventScratch = new sensors_event_t[minBufferSize]; mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize]; + mMode = NORMAL; mAckReceiver = new SensorEventAckReceiver(this); mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY); @@ -230,7 +231,7 @@ SensorService::~SensorService() static const String16 sDump("android.permission.DUMP"); -status_t SensorService::dump(int fd, const Vector& /*args*/) +status_t SensorService::dump(int fd, const Vector& args) { String8 result; if (!PermissionCache::checkCallingPermission(sDump)) { @@ -238,6 +239,26 @@ status_t SensorService::dump(int fd, const Vector& /*args*/) "can't dump SensorService from pid=%d, uid=%d\n", IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid()); + } else if (args.size() > 0) { + if (args.size() > 1) { + return INVALID_OPERATION; + } + Mutex::Autolock _l(mLock); + SensorDevice& dev(SensorDevice::getInstance()); + if (args[0] == String16("restrict") && mMode == NORMAL) { + mMode = 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 + // flush complete event is returned, we need to remove the connection from this queue. + for (size_t i=0 ; i< mActiveSensors.size(); ++i) { + mActiveSensors.valueAt(i)->clearAllPendingFlushConnections(); + } + } else if (args[0] == String16("enable") && mMode == RESTRICTED) { + mMode = NORMAL; + dev.enableAllSensors(); + } + return status_t(NO_ERROR); } else { Mutex::Autolock _l(mLock); result.append("Sensor List:\n"); @@ -341,6 +362,17 @@ status_t SensorService::dump(int fd, const Vector& /*args*/) result.appendFormat("Socket Buffer size = %d events\n", mSocketBufferSize/sizeof(sensors_event_t)); result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held"); + result.appendFormat("Mode :"); + switch(mMode) { + case NORMAL: + result.appendFormat(" NORMAL\n"); + break; + case RESTRICTED: + result.appendFormat(" RESTRICTED\n"); + break; + case DATA_INJECTION: + result.appendFormat(" DATA_INJECTION\n"); + } result.appendFormat("%zd active connections\n", mActiveConnections.size()); for (size_t i=0 ; i < mActiveConnections.size() ; i++) { @@ -554,7 +586,6 @@ void SensorService::setWakeLockAcquiredLocked(bool acquire) { } } - bool SensorService::isWakeLockAcquired() { Mutex::Autolock _l(mLock); return mWakeLockAcquired; @@ -630,7 +661,6 @@ bool SensorService::isWakeUpSensorEvent(const sensors_event_t& event) const { return sensor != NULL && sensor->getSensor().isWakeUpSensor(); } - SensorService::SensorRecord * SensorService::getSensorRecord(int handle) { return mActiveSensors.valueFor(handle); } @@ -655,10 +685,10 @@ Vector SensorService::getSensorList() return accessibleSensorList; } -sp SensorService::createSensorEventConnection() +sp SensorService::createSensorEventConnection(const String8& packageName) { uid_t uid = IPCThreadState::self()->getCallingUid(); - sp result(new SensorEventConnection(this, uid)); + sp result(new SensorEventConnection(this, uid, packageName)); return result; } @@ -708,7 +738,7 @@ Sensor SensorService::getSensorFromHandle(int handle) const { } status_t SensorService::enable(const sp& connection, - int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags) + int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags) { if (mInitCheck != NO_ERROR) return mInitCheck; @@ -723,6 +753,10 @@ status_t SensorService::enable(const sp& connection, } Mutex::Autolock _l(mLock); + if (mMode == RESTRICTED && !isWhiteListedPackage(connection->getPackageName())) { + return INVALID_OPERATION; + } + SensorRecord* rec = mActiveSensors.valueFor(handle); if (rec == 0) { rec = new SensorRecord(connection); @@ -773,7 +807,7 @@ status_t SensorService::enable(const sp& connection, "rate=%" PRId64 " timeout== %" PRId64"", handle, reservedFlags, samplingPeriodNs, maxBatchReportLatencyNs); - status_t err = sensor->batch(connection.get(), handle, reservedFlags, samplingPeriodNs, + status_t err = sensor->batch(connection.get(), handle, 0, samplingPeriodNs, maxBatchReportLatencyNs); // Call flush() before calling activate() on the sensor. Wait for a first flush complete @@ -969,6 +1003,11 @@ void SensorService::populateActiveConnections( } } +bool SensorService::isWhiteListedPackage(const String8& packageName) { + // TODO: Come up with a list of packages. + return (packageName.find(".cts.") != -1); +} + // --------------------------------------------------------------------------- SensorService::SensorRecord::SensorRecord( const sp& connection) @@ -1025,12 +1064,16 @@ SensorService::SensorRecord::getFirstPendingFlushConnection() { return NULL; } +void SensorService::SensorRecord::clearAllPendingFlushConnections() { + mPendingFlushConnections.clear(); +} + // --------------------------------------------------------------------------- SensorService::SensorEventConnection::SensorEventConnection( - const sp& service, uid_t uid) + const sp& service, uid_t uid, String8 packageName) : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false), - mDead(false), mEventCache(NULL), mCacheSize(0), mMaxCacheSize(0) { + mDead(false), mEventCache(NULL), mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName) { mChannel = new BitTube(mService->mSocketBufferSize); #if DEBUG_CONNECTIONS mEventsReceived = mEventsSentFromCache = mEventsSent = 0; @@ -1062,8 +1105,8 @@ void SensorService::SensorEventConnection::resetWakeLockRefCount() { void SensorService::SensorEventConnection::dump(String8& result) { Mutex::Autolock _l(mConnectionLock); - result.appendFormat("\t WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n", - mWakeLockRefCount, mUid, mCacheSize, mMaxCacheSize); + 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) { const FlushInfo& flushInfo = mSensorInfo.valueAt(i); result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d \n", @@ -1126,6 +1169,10 @@ bool SensorService::SensorEventConnection::hasOneShotSensors() const { return false; } +String8 SensorService::SensorEventConnection::getPackageName() const { + return mPackageName; +} + void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle, bool value) { Mutex::Autolock _l(mConnectionLock); diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index e9ca3a59f..b31eaf398 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -65,6 +66,27 @@ class SensorService : { friend class BinderService; + enum Mode { + // The regular operating mode where any application can register/unregister/call flush on + // sensors. + NORMAL = 0, + // 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 + // 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 + }; + static const char* WAKE_LOCK_NAME; static char const* getServiceName() ANDROID_API { return "sensorservice"; } @@ -78,7 +100,7 @@ class SensorService : // ISensorServer interface virtual Vector getSensorList(); - virtual sp createSensorEventConnection(); + virtual sp createSensorEventConnection(const String8& packageName); virtual status_t dump(int fd, const Vector& args); class SensorEventConnection : public BnSensorEventConnection, public LooperCallback { @@ -133,7 +155,6 @@ class SensorService : // connection FD may be added to the Looper. The flags to set are determined by the internal // state of the connection. FDs are added to the looper when wake-up sensors are registered // (to poll for acknowledgements) and when write fails on the socket when there are too many - // events (to poll when the FD is available for writing). FDs are removed when there is an // error and the other end hangs up or when this client unregisters for this connection. void updateLooperRegistration(const sp& looper); void updateLooperRegistrationLocked(const sp& looper); @@ -169,6 +190,7 @@ class SensorService : KeyedVector mSensorInfo; sensors_event_t *mEventCache; int mCacheSize, mMaxCacheSize; + String8 mPackageName; #if DEBUG_CONNECTIONS int mEventsReceived, mEventsSent, mEventsSentFromCache; @@ -176,7 +198,7 @@ class SensorService : #endif public: - SensorEventConnection(const sp& service, uid_t uid); + SensorEventConnection(const sp& service, uid_t uid, String8 packageName); status_t sendEvents(sensors_event_t const* buffer, size_t count, sensors_event_t* scratch, @@ -190,6 +212,7 @@ class SensorService : void dump(String8& result); bool needsWakeLock(); void resetWakeLockRefCount(); + String8 getPackageName() const; uid_t getUid() const { return mUid; } }; @@ -208,6 +231,7 @@ class SensorService : void addPendingFlushConnection(const sp& connection); void removeFirstPendingFlushConnection(); SensorEventConnection * getFirstPendingFlushConnection(); + void clearAllPendingFlushConnections(); }; class SensorEventAckReceiver : public Thread { @@ -261,6 +285,11 @@ class SensorService : // to the output vector. void populateActiveConnections(SortedVector< sp >* activeConnections); + // If SensorService is operating in RESTRICTED mode, only select whitelisted packages are + // allowed to register for or call flush on sensors. Typically only cts test packages are + // allowed. + bool isWhiteListedPackage(const String8& packageName); + // constants Vector mSensorList; Vector mUserSensorListDebug; @@ -282,6 +311,7 @@ class SensorService : bool mWakeLockAcquired; sensors_event_t *mSensorEventBuffer, *mSensorEventScratch; SensorEventConnection const **mMapFlushEventsToConnections; + Mode mMode; // The size of this vector is constant, only the items are mutable KeyedVector mLastEventSeen;