Disable sensors when an app goes to background

Bug: 74395023
Test: 1) Enable sensor on SensorLogger
      2) Put app to background and wait; verify sensor gets disabled.
      3) Put app to foreground and wait; verify sensor gets re-enabled.
Change-Id: Icf6ab253fad4133431c86bb9a49275f9190ad2e8
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index e799372..77d8c11 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <cinttypes>
 #include <sys/socket.h>
 #include <utils/threads.h>
 
@@ -69,17 +70,17 @@
 }
 
 bool SensorService::SensorEventConnection::needsWakeLock() {
-    Mutex::Autolock _l(mConnectionLock);
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
     return !mDead && mWakeLockRefCount > 0;
 }
 
 void SensorService::SensorEventConnection::resetWakeLockRefCount() {
-    Mutex::Autolock _l(mConnectionLock);
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
     mWakeLockRefCount = 0;
 }
 
 void SensorService::SensorEventConnection::dump(String8& result) {
-    Mutex::Autolock _l(mConnectionLock);
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
     result.appendFormat("\tOperating Mode: ");
     if (!mService->isWhiteListedPackage(getPackageName())) {
         result.append("RESTRICTED\n");
@@ -92,7 +93,7 @@
             "max cache size %d\n", mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize,
             mMaxCacheSize);
     for (auto& it : mSensorInfo) {
-        const FlushInfo& flushInfo = it.second;
+        const FlushInfo& flushInfo = it.second.flushInfo;
         result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d \n",
                             mService->getSensorName(it.first).string(),
                             it.first,
@@ -121,7 +122,7 @@
  */
 void SensorService::SensorEventConnection::dump(util::ProtoOutputStream* proto) const {
     using namespace service::SensorEventConnectionProto;
-    Mutex::Autolock _l(mConnectionLock);
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
 
     if (!mService->isWhiteListedPackage(getPackageName())) {
         proto->write(OPERATING_MODE, OP_MODE_RESTRICTED);
@@ -136,7 +137,7 @@
     proto->write(CACHE_SIZE, int32_t(mCacheSize));
     proto->write(MAX_CACHE_SIZE, int32_t(mMaxCacheSize));
     for (auto& it : mSensorInfo) {
-        const FlushInfo& flushInfo = it.second;
+        const FlushInfo& flushInfo = it.second.flushInfo;
         const uint64_t token = proto->start(FLUSH_INFOS);
         proto->write(FlushInfoProto::SENSOR_NAME,
                 std::string(mService->getSensorName(it.first)));
@@ -157,28 +158,33 @@
 #endif
 }
 
-bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
-    Mutex::Autolock _l(mConnectionLock);
+bool SensorService::SensorEventConnection::addSensor(
+    int32_t handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags) {
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
     sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
     if (si == nullptr ||
         !canAccessSensor(si->getSensor(), "Tried adding", mOpPackageName) ||
         mSensorInfo.count(handle) > 0) {
         return false;
     }
-    mSensorInfo[handle] = FlushInfo();
+
+    SensorRequest request = {
+      .samplingPeriodNs = samplingPeriodNs,
+      .maxBatchReportLatencyNs = maxBatchReportLatencyNs,
+      .reservedFlags = reservedFlags
+    };
+
+    mSensorInfo[handle] = request;
     return true;
 }
 
 bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
-    Mutex::Autolock _l(mConnectionLock);
-    if (mSensorInfo.erase(handle) >= 0) {
-        return true;
-    }
-    return false;
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+    return mSensorInfo.erase(handle) > 0;
 }
 
 std::vector<int32_t> SensorService::SensorEventConnection::getActiveSensorHandles() const {
-    Mutex::Autolock _l(mConnectionLock);
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
     std::vector<int32_t> list;
     for (auto& it : mSensorInfo) {
         list.push_back(it.first);
@@ -187,17 +193,17 @@
 }
 
 bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
-    Mutex::Autolock _l(mConnectionLock);
-    return mSensorInfo.count(handle) > 0;
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+    return mSensorInfo.count(handle) + mSensorInfoBackup.count(handle) > 0;
 }
 
 bool SensorService::SensorEventConnection::hasAnySensor() const {
-    Mutex::Autolock _l(mConnectionLock);
-    return mSensorInfo.size() ? true : false;
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+    return mSensorInfo.size() + mSensorInfoBackup.size() ? true : false;
 }
 
 bool SensorService::SensorEventConnection::hasOneShotSensors() const {
-    Mutex::Autolock _l(mConnectionLock);
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
     for (auto &it : mSensorInfo) {
         const int handle = it.first;
         sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
@@ -214,15 +220,15 @@
 
 void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
                                 bool value) {
-    Mutex::Autolock _l(mConnectionLock);
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
     if (mSensorInfo.count(handle) > 0) {
-        FlushInfo& flushInfo = mSensorInfo[handle];
+        FlushInfo& flushInfo = mSensorInfo[handle].flushInfo;
         flushInfo.mFirstFlushPending = value;
     }
 }
 
 void SensorService::SensorEventConnection::updateLooperRegistration(const sp<Looper>& looper) {
-    Mutex::Autolock _l(mConnectionLock);
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
     updateLooperRegistrationLocked(looper);
 }
 
@@ -273,9 +279,9 @@
 }
 
 void SensorService::SensorEventConnection::incrementPendingFlushCount(int32_t handle) {
-    Mutex::Autolock _l(mConnectionLock);
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
     if (mSensorInfo.count(handle) > 0) {
-        FlushInfo& flushInfo = mSensorInfo[handle];
+        FlushInfo& flushInfo = mSensorInfo[handle].flushInfo;
         flushInfo.mPendingFlushEventsToSend++;
     }
 }
@@ -289,7 +295,7 @@
     std::unique_ptr<sensors_event_t[]> sanitizedBuffer;
 
     int count = 0;
-    Mutex::Autolock _l(mConnectionLock);
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
     if (scratch) {
         size_t i=0;
         while (i<numEvents) {
@@ -310,7 +316,7 @@
                 continue;
             }
 
-            FlushInfo& flushInfo = mSensorInfo[sensor_handle];
+            FlushInfo& flushInfo = mSensorInfo[sensor_handle].flushInfo;
             // Check if there is a pending flush_complete event for this sensor on this connection.
             if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&
                     mapFlushEventsToConnections[i] == this) {
@@ -431,9 +437,55 @@
     return size < 0 ? status_t(size) : status_t(NO_ERROR);
 }
 
+void SensorService::SensorEventConnection::updateSensorSubscriptions() {
+    if (!hasSensorAccess()) {
+        stopAll();
+    } else {
+        recoverAll();
+    }
+}
+
 void SensorService::SensorEventConnection::setSensorAccess(const bool hasAccess) {
-    Mutex::Autolock _l(mConnectionLock);
-    mHasSensorAccess = hasAccess;
+    if (mHasSensorAccess != hasAccess) {
+        mHasSensorAccess = hasAccess;
+        updateSensorSubscriptions();
+    }
+}
+
+void SensorService::SensorEventConnection::stopAll() {
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+    if (!mSensorInfo.empty()) {
+        mSensorInfoBackup = mSensorInfo;
+        mSensorInfo.clear();
+
+        for (auto& it : mSensorInfoBackup) {
+            int32_t handle = it.first;
+
+            status_t err =  mService->disable(this, handle);
+
+            if (err != NO_ERROR) {
+                ALOGE("Error disabling sensor %d", handle);
+            }
+        }
+    }
+}
+
+void SensorService::SensorEventConnection::recoverAll() {
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+    for (auto& it : mSensorInfoBackup) {
+        int32_t handle = it.first;
+        SensorRequest &request = it.second;
+
+        status_t err =  mService->enable(
+            this, handle, request.samplingPeriodNs, request.maxBatchReportLatencyNs,
+            request.reservedFlags, mOpPackageName);
+
+        if (err != NO_ERROR) {
+            ALOGE("Error recovering sensor %d", handle);
+        }
+    }
+
+    mSensorInfoBackup.clear();
 }
 
 bool SensorService::SensorEventConnection::hasSensorAccess() {
@@ -535,7 +587,7 @@
             continue;
         }
 
-        FlushInfo& flushInfo = it.second;
+        FlushInfo& flushInfo = it.second.flushInfo;
         while (flushInfo.mPendingFlushEventsToSend > 0) {
             flushCompleteEvent.meta_data.sensor = handle;
             bool wakeUpSensor = si->getSensor().isWakeUpSensor();
@@ -560,7 +612,7 @@
     // half the size of the socket buffer allocated in BitTube whichever is smaller.
     const int maxWriteSize = helpers::min(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2,
             int(mService->mSocketBufferSize/(sizeof(sensors_event_t)*2)));
-    Mutex::Autolock _l(mConnectionLock);
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
     // Send pending flush complete events (if any)
     sendPendingFlushEventsLocked();
     for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
@@ -627,7 +679,7 @@
                 continue;
             }
 
-            FlushInfo& flushInfo = mSensorInfo[scratch[j].meta_data.sensor];
+            FlushInfo& flushInfo = mSensorInfo[scratch[j].meta_data.sensor].flushInfo;
             flushInfo.mPendingFlushEventsToSend++;
             ALOGD_IF(DEBUG_CONNECTIONS, "increment pendingFlushCount %d",
                      flushInfo.mPendingFlushEventsToSend);
@@ -663,13 +715,21 @@
     } else {
         err = mService->disable(this, handle);
     }
+
     return err;
 }
 
 status_t SensorService::SensorEventConnection::setEventRate(
         int handle, nsecs_t samplingPeriodNs)
 {
-    return mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
+    status_t err = mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
+
+    std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+    if (err == NO_ERROR && mSensorInfo.count(handle) > 0) {
+        mSensorInfo[handle].samplingPeriodNs = samplingPeriodNs;
+    }
+
+    return err;
 }
 
 status_t  SensorService::SensorEventConnection::flush() {
@@ -690,7 +750,7 @@
             // and remove the fd from Looper. Call checkWakeLockState to know if SensorService
             // can release the wake-lock.
             ALOGD_IF(DEBUG_CONNECTIONS, "%p Looper error %d", this, fd);
-            Mutex::Autolock _l(mConnectionLock);
+            std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
             mDead = true;
             mWakeLockRefCount = 0;
             updateLooperRegistrationLocked(mService->getLooper());
@@ -709,7 +769,7 @@
         unsigned char buf[sizeof(sensors_event_t)];
         ssize_t numBytesRead = ::recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
         {
-            Mutex::Autolock _l(mConnectionLock);
+            std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
             if (numBytesRead == sizeof(sensors_event_t)) {
                 if (!mDataInjectionMode) {
                     ALOGE("Data injected in normal mode, dropping event"
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index 1ca35c0..3ba5c07 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -57,7 +57,8 @@
     bool hasSensor(int32_t handle) const;
     bool hasAnySensor() const;
     bool hasOneShotSensors() const;
-    bool addSensor(int32_t handle);
+    bool addSensor(
+        int32_t handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags);
     bool removeSensor(int32_t handle);
     std::vector<int32_t> getActiveSensorHandles() const;
     void setFirstFlushPending(int32_t handle, bool value);
@@ -70,7 +71,7 @@
     uid_t getUid() const { return mUid; }
 
     void setSensorAccess(const bool hasAccess);
-
+    void updateSensorSubscriptions();
 private:
     virtual ~SensorEventConnection();
     virtual void onFirstRef();
@@ -136,13 +137,16 @@
     // privacy not being enabled.
     bool hasSensorAccess();
 
+    void stopAll();
+    void recoverAll();
+
     // Call noteOp for the sensor if the sensor requires a permission
     bool noteOpIfRequired(const sensors_event_t& event);
 
     sp<SensorService> const mService;
     sp<BitTube> mChannel;
     uid_t mUid;
-    mutable Mutex mConnectionLock;
+    mutable std::recursive_mutex mConnectionLock;
     // Number of events from wake up sensors which are still pending and haven't been delivered to
     // the corresponding application. It is incremented by one unit for each write to the socket.
     uint32_t mWakeLockRefCount;
@@ -169,8 +173,17 @@
 
         FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false) {}
     };
+
+    struct SensorRequest {
+      nsecs_t samplingPeriodNs;
+      nsecs_t maxBatchReportLatencyNs;
+      int reservedFlags;
+      FlushInfo flushInfo;
+    };
+
     // protected by SensorService::mLock. Key for this map is the sensor handle.
-    std::unordered_map<int32_t, FlushInfo> mSensorInfo;
+    std::unordered_map<int32_t, SensorRequest> mSensorInfo;
+    std::unordered_map<int32_t, SensorRequest> mSensorInfoBackup;
 
     sensors_event_t *mEventCache;
     int mCacheSize, mMaxCacheSize;
@@ -185,7 +198,7 @@
 
     mutable Mutex mDestroyLock;
     bool mDestroyed;
-    bool mHasSensorAccess;
+    std::atomic_bool mHasSensorAccess;
 
     // Store a mapping of sensor handles to required AppOp for a sensor. This map only contains a
     // valid mapping for sensors that require a permission in order to reduce the lookup time.
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 5fdc74f..9ed6fc2 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -301,7 +301,10 @@
 
 void SensorService::setSensorAccess(uid_t uid, bool hasAccess) {
     ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
-    for (const sp<SensorEventConnection>& conn : connLock.getActiveConnections()) {
+    const auto& connections = connLock.getActiveConnections();
+
+    mLock.unlock();
+    for (const sp<SensorEventConnection>& conn : connections) {
         if (conn->getUid() == uid) {
             conn->setSensorAccess(hasAccess);
         }
@@ -638,6 +641,9 @@
 
 void SensorService::disableAllSensorsLocked(ConnectionSafeAutolock* connLock) {
     SensorDevice& dev(SensorDevice::getInstance());
+    for (const sp<SensorEventConnection>& connection : connLock->getActiveConnections()) {
+        connection->updateSensorSubscriptions();
+    }
     for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
         connection->stopAll(true /* backupRecord */);
     }
@@ -666,6 +672,9 @@
     }
     SensorDevice& dev(SensorDevice::getInstance());
     dev.enableAllSensors();
+    for (const sp<SensorEventConnection>& connection : connLock->getActiveConnections()) {
+        connection->updateSensorSubscriptions();
+    }
     for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
         connection->recoverAll();
     }
@@ -1589,7 +1598,7 @@
         }
     }
 
-    if (connection->addSensor(handle)) {
+    if (connection->addSensor(handle, samplingPeriodNs, maxBatchReportLatencyNs, reservedFlags)) {
         BatteryService::enableSensor(connection->getUid(), handle);
         // the sensor was added (which means it wasn't already there)
         // so, see if this connection becomes active