Handle backgrounded apps for direct sensor connections
Uses the stopAll()/recoverAll() logic to temporarily stop/enable
sensors for direct connections when an app becomes idle/active.
Bug: 74395023
Test: CTS SensorDirectReportTest and verify pass
Test: 1) Subscribe to sensor on sensorlogger
2) Put app to background and wait
3) Verify subscription is disabled once app is idle
4) Put app to foreground and verify app can receive sensor samples
Test: Verify above test while a_sns_test streaming samples
Test: Verify above test with sensor service restrict and privacy mode
Change-Id: Id1981213fc13a9012fa756b8cd35fae6f144c105
diff --git a/services/sensorservice/SensorDirectConnection.cpp b/services/sensorservice/SensorDirectConnection.cpp
index 106efd6..e4c33da 100644
--- a/services/sensorservice/SensorDirectConnection.cpp
+++ b/services/sensorservice/SensorDirectConnection.cpp
@@ -93,6 +93,18 @@
return nullptr;
}
+void SensorService::SensorDirectConnection::onSensorAccessChanged(bool hasAccess) {
+ if (!hasAccess) {
+ stopAll(true /* backupRecord */);
+ } else {
+ recoverAll();
+ }
+}
+
+bool SensorService::SensorDirectConnection::hasSensorAccess() const {
+ return mService->hasSensorAccess(mUid, mOpPackageName);
+}
+
status_t SensorService::SensorDirectConnection::enableDisable(
int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,
int reservedFlags) {
@@ -125,7 +137,7 @@
return NO_ERROR;
}
- if (!mService->isOperationPermitted(mOpPackageName)) {
+ if (!hasSensorAccess()) {
return PERMISSION_DENIED;
}
@@ -169,12 +181,15 @@
}
void SensorService::SensorDirectConnection::stopAll(bool backupRecord) {
+ Mutex::Autolock _l(mConnectionLock);
+ stopAllLocked(backupRecord);
+}
+void SensorService::SensorDirectConnection::stopAllLocked(bool backupRecord) {
struct sensors_direct_cfg_t config = {
.rate_level = SENSOR_DIRECT_RATE_STOP
};
- Mutex::Autolock _l(mConnectionLock);
SensorDevice& dev(SensorDevice::getInstance());
for (auto &i : mActivated) {
dev.configureDirectChannel(i.first, getHalChannelHandle(), &config);
@@ -187,21 +202,25 @@
}
void SensorService::SensorDirectConnection::recoverAll() {
- stopAll(false);
-
Mutex::Autolock _l(mConnectionLock);
- SensorDevice& dev(SensorDevice::getInstance());
+ if (!mActivatedBackup.empty()) {
+ stopAllLocked(false);
- // recover list of report from backup
- mActivated = mActivatedBackup;
- mActivatedBackup.clear();
+ SensorDevice& dev(SensorDevice::getInstance());
- // re-enable them
- for (auto &i : mActivated) {
- struct sensors_direct_cfg_t config = {
- .rate_level = i.second
- };
- dev.configureDirectChannel(i.first, getHalChannelHandle(), &config);
+ // recover list of report from backup
+ ALOG_ASSERT(mActivated.empty(),
+ "mActivated must be empty if mActivatedBackup was non-empty");
+ mActivated = mActivatedBackup;
+ mActivatedBackup.clear();
+
+ // re-enable them
+ for (auto &i : mActivated) {
+ struct sensors_direct_cfg_t config = {
+ .rate_level = i.second
+ };
+ dev.configureDirectChannel(i.first, getHalChannelHandle(), &config);
+ }
}
}
diff --git a/services/sensorservice/SensorDirectConnection.h b/services/sensorservice/SensorDirectConnection.h
index ead08d3..4181b65 100644
--- a/services/sensorservice/SensorDirectConnection.h
+++ b/services/sensorservice/SensorDirectConnection.h
@@ -42,17 +42,14 @@
void dump(String8& result) const;
void dump(util::ProtoOutputStream* proto) const;
uid_t getUid() const { return mUid; }
+ const String16& getOpPackageName() const { return mOpPackageName; }
int32_t getHalChannelHandle() const;
bool isEquivalent(const sensors_direct_mem_t *mem) const;
- // stop all active sensor report. if backupRecord is set to false,
- // those report can be recovered by recoverAll
- // called by SensorService when enter restricted mode
- void stopAll(bool backupRecord = false);
-
- // recover sensor reports previously stopped by stopAll(true)
- // called by SensorService when return to NORMAL mode.
- void recoverAll();
+ // Invoked when access to sensors for this connection has changed, e.g. lost or
+ // regained due to changes in the sensor restricted/privacy mode or the
+ // app changed to idle/active status.
+ void onSensorAccessChanged(bool hasAccess);
protected:
virtual ~SensorDirectConnection();
@@ -66,6 +63,25 @@
virtual int32_t configureChannel(int handle, int rateLevel);
virtual void destroy();
private:
+ bool hasSensorAccess() const;
+
+ // Stops all active sensor direct report requests.
+ //
+ // If backupRecord is true, stopped requests can be recovered
+ // by a subsequent recoverAll() call (e.g. when temporarily stopping
+ // sensors for sensor privacy/restrict mode or when an app becomes
+ // idle).
+ void stopAll(bool backupRecord = false);
+ // Same as stopAll() but with mConnectionLock held.
+ void stopAllLocked(bool backupRecord);
+
+ // Recover sensor requests previously stopped by stopAll(true).
+ // This method can be called when a sensor access resumes (e.g.
+ // sensor privacy/restrict mode lifted or app becomes active).
+ //
+ // If no requests are backed up by stopAll(), this method is no-op.
+ void recoverAll();
+
const sp<SensorService> mService;
const uid_t mUid;
const sensors_direct_mem_t mMem;
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index a5dafd5..ffcd0a0 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -308,6 +308,24 @@
dev.setUidStateForConnection(conn.get(), state);
}
}
+
+ for (const sp<SensorDirectConnection>& conn : connLock.getDirectConnections()) {
+ if (conn->getUid() == uid) {
+ // Update sensor subscriptions if needed
+ bool hasAccess = hasSensorAccessLocked(conn->getUid(), conn->getOpPackageName());
+ conn->onSensorAccessChanged(hasAccess);
+ }
+ }
+}
+
+bool SensorService::hasSensorAccess(uid_t uid, const String16& opPackageName) {
+ Mutex::Autolock _l(mLock);
+ return hasSensorAccessLocked(uid, opPackageName);
+}
+
+bool SensorService::hasSensorAccessLocked(uid_t uid, const String16& opPackageName) {
+ return !mSensorPrivacyPolicy->isSensorPrivacyEnabled()
+ && isUidActive(uid) && !isOperationRestrictedLocked(opPackageName);
}
const Sensor& SensorService::registerSensor(SensorInterface* s, bool isDebug, bool isVirtual) {
@@ -640,8 +658,9 @@
void SensorService::disableAllSensorsLocked(ConnectionSafeAutolock* connLock) {
SensorDevice& dev(SensorDevice::getInstance());
- for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
- connection->stopAll(true /* backupRecord */);
+ for (const sp<SensorDirectConnection>& conn : connLock->getDirectConnections()) {
+ bool hasAccess = hasSensorAccessLocked(conn->getUid(), conn->getOpPackageName());
+ conn->onSensorAccessChanged(hasAccess);
}
dev.disableAllSensors();
// Clear all pending flush connections for all active sensors. If one of the active
@@ -668,8 +687,9 @@
}
SensorDevice& dev(SensorDevice::getInstance());
dev.enableAllSensors();
- for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
- connection->recoverAll();
+ for (const sp<SensorDirectConnection>& conn : connLock->getDirectConnections()) {
+ bool hasAccess = hasSensorAccessLocked(conn->getUid(), conn->getOpPackageName());
+ conn->onSensorAccessChanged(hasAccess);
}
}
@@ -1888,13 +1908,12 @@
return (packageName.contains(mWhiteListedPackage.string()));
}
-bool SensorService::isOperationPermitted(const String16& opPackageName) {
- Mutex::Autolock _l(mLock);
+bool SensorService::isOperationRestrictedLocked(const String16& opPackageName) {
if (mCurrentOperatingMode == RESTRICTED) {
String8 package(opPackageName);
- return isWhiteListedPackage(package);
+ return !isWhiteListedPackage(package);
}
- return true;
+ return false;
}
void SensorService::UidPolicy::registerSelf() {
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index abd881c..3bb8421 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -339,7 +339,11 @@
// allowed to register for or call flush on sensors. Typically only cts test packages are
// allowed.
bool isWhiteListedPackage(const String8& packageName);
- bool isOperationPermitted(const String16& opPackageName);
+
+ // Returns true if a connection with the specified opPackageName has no access to sensors
+ // in the RESTRICTED mode (i.e. the service is in RESTRICTED mode, and the package is not
+ // whitelisted). mLock must be held to invoke this method.
+ bool isOperationRestrictedLocked(const String16& opPackageName);
// Reset the state of SensorService to NORMAL mode.
status_t resetToNormalMode();
@@ -358,6 +362,12 @@
// Sets whether the given UID can get sensor data
void onUidStateChanged(uid_t uid, UidState state);
+ // Returns true if a connection with the given uid and opPackageName
+ // currently has access to sensors.
+ bool hasSensorAccess(uid_t uid, const String16& opPackageName);
+ // Same as hasSensorAccess but with mLock held.
+ bool hasSensorAccessLocked(uid_t uid, const String16& opPackageName);
+
// Overrides the UID state as if it is idle
status_t handleSetUidState(Vector<String16>& args, int err);
// Clears the override for the UID state