No sensor access to idle UIDs - native framework
Idle UIDs are ones that were in the background for long enough time.
Currently such apps can access sensor data even though they have no
user perceptible components running. This affects the user's privacy
since an app in the background can use sensor data to infer location,
activity, habits, etc.
The goal is to restrict sensor access for all apps in the ecosystem
regardless of target SDK which means the solution should be backwards
compatible. At the high level the sesnor service observes UID state
changes and applies policy like this:
Continuous sensors: for sensros in this reporting mode when the UID
goes in the background we will stop dispatching events. Once the UID
goes active we will start reporting the events. While this is an
app visible behavior change we would rather do that vs delivering
fake events.
Flush events: there is no change in behavior based on the UID state.
Hence, idle apps can request a flush and would get the completion
callback. From an app perspective flushing works at any point.
Trigger events: for sensors in this reporting mode when the UID
goes in the background we will not report any trigger events. From
an app perspective the sensor just did not pick up any events.
On-change events: for sensors in this reporting mode when the UID
goes in the background we will not report any change events. From
an app perspective the sensor just did not pick up any events.
Wake locks: since UIDs in idle state cannot acquire wakelocks we
will not be grabbing a wakelock on behalf of apps in that state.
Test: Added - SensorTest#testSanitizedContinuousEventsUidIdle
Added - SensorTest#testBatchAndFlushUidIdle
Pass - cts-tradefed run cts-dev -m CtsSensorTestCases
bug:63938985
Change-Id: I156803610ad6d86afaae641ebbb0e84f16d2344b
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 0a05dd1..956844f 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -29,11 +29,11 @@
SensorService::SensorEventConnection::SensorEventConnection(
const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode,
- const String16& opPackageName)
+ const String16& opPackageName, bool hasSensorAccess)
: mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(NULL),
mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName), mOpPackageName(opPackageName),
- mDestroyed(false) {
+ mDestroyed(false), mHasSensorAccess(hasSensorAccess) {
mChannel = new BitTube(mService->mSocketBufferSize);
#if DEBUG_CONNECTIONS
mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@@ -223,6 +223,9 @@
sensors_event_t* scratch,
wp<const SensorEventConnection> const * mapFlushEventsToConnections) {
// filter out events not for this connection
+
+ sensors_event_t* sanitizedBuffer = nullptr;
+
int count = 0;
Mutex::Autolock _l(mConnectionLock);
if (scratch) {
@@ -273,24 +276,36 @@
if (mapFlushEventsToConnections[i] == this) {
scratch[count++] = buffer[i];
}
- ++i;
} else {
// Regular sensor event, just copy it to the scratch buffer.
- scratch[count++] = buffer[i++];
+ if (mHasSensorAccess) {
+ scratch[count++] = buffer[i];
+ }
}
+ i++;
} while ((i<numEvents) && ((buffer[i].sensor == sensor_handle &&
buffer[i].type != SENSOR_TYPE_META_DATA) ||
(buffer[i].type == SENSOR_TYPE_META_DATA &&
buffer[i].meta_data.sensor == sensor_handle)));
}
} else {
- scratch = const_cast<sensors_event_t *>(buffer);
- count = numEvents;
+ if (mHasSensorAccess) {
+ scratch = const_cast<sensors_event_t *>(buffer);
+ count = numEvents;
+ } else {
+ scratch = sanitizedBuffer = new sensors_event_t[numEvents];
+ for (size_t i = 0; i < numEvents; i++) {
+ if (buffer[i].type == SENSOR_TYPE_META_DATA) {
+ scratch[count++] = buffer[i++];
+ }
+ }
+ }
}
sendPendingFlushEventsLocked();
// Early return if there are no events for this connection.
if (count == 0) {
+ delete sanitizedBuffer;
return status_t(NO_ERROR);
}
@@ -308,6 +323,7 @@
// the max cache size that is desired.
if (mCacheSize + count < computeMaxCacheSizeLocked()) {
reAllocateCacheLocked(scratch, count);
+ delete sanitizedBuffer;
return status_t(NO_ERROR);
}
// Some events need to be dropped.
@@ -326,16 +342,20 @@
memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize,
numEventsDropped * sizeof(sensors_event_t));
}
+ delete sanitizedBuffer;
return status_t(NO_ERROR);
}
- int index_wake_up_event = findWakeUpSensorEventLocked(scratch, count);
- if (index_wake_up_event >= 0) {
- scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
- ++mWakeLockRefCount;
+ int index_wake_up_event = -1;
+ if (mHasSensorAccess) {
+ index_wake_up_event = findWakeUpSensorEventLocked(scratch, count);
+ if (index_wake_up_event >= 0) {
+ scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+ ++mWakeLockRefCount;
#if DEBUG_CONNECTIONS
- ++mTotalAcksNeeded;
+ ++mTotalAcksNeeded;
#endif
+ }
}
// NOTE: ASensorEvent and sensors_event_t are the same type.
@@ -364,6 +384,7 @@
// Add this file descriptor to the looper to get a callback when this fd is available for
// writing.
updateLooperRegistrationLocked(mService->getLooper());
+ delete sanitizedBuffer;
return size;
}
@@ -373,9 +394,15 @@
}
#endif
+ delete sanitizedBuffer;
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
+void SensorService::SensorEventConnection::setSensorAccess(const bool hasAccess) {
+ Mutex::Autolock _l(mConnectionLock);
+ mHasSensorAccess = hasAccess;
+}
+
void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t const* scratch,
int count) {
sensors_event_t *eventCache_new;
@@ -437,15 +464,18 @@
sendPendingFlushEventsLocked();
for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
const int numEventsToWrite = helpers::min(mCacheSize - numEventsSent, maxWriteSize);
- int index_wake_up_event =
- findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite);
- if (index_wake_up_event >= 0) {
- mEventCache[index_wake_up_event + numEventsSent].flags |=
- WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
- ++mWakeLockRefCount;
+ int index_wake_up_event = -1;
+ if (mHasSensorAccess) {
+ index_wake_up_event =
+ findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite);
+ if (index_wake_up_event >= 0) {
+ mEventCache[index_wake_up_event + numEventsSent].flags |=
+ WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+ ++mWakeLockRefCount;
#if DEBUG_CONNECTIONS
- ++mTotalAcksNeeded;
+ ++mTotalAcksNeeded;
#endif
+ }
}
ssize_t size = SensorEventQueue::write(mChannel,