Automatically reconnect sensors

Automatically reenable sensor connections for static sensors after a
Sensors HAL crash.

Bug: 111070257
Test: Request sensor events via a_sns_test, kill the sensors HAL,
      verify that events are no longer received, restart the HAL and
      verify that a_sns_test receives new sensor events.

Change-Id: I2baa7745cf07e29c186ac4b80679393d6e48bd56
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index f813fe5..f2336cb 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -59,11 +59,22 @@
     }
 }
 
+template<typename EnumType>
+constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
+    return static_cast<typename std::underlying_type<EnumType>::type>(value);
+}
+
+// Used internally by the framework to wake the Event FMQ. These values must start after
+// the last value of EventQueueFlagBits
+enum EventQueueFlagBitsInternal : uint32_t {
+    INTERNAL_WAKE =  1 << 16,
+};
+
 void SensorsHalDeathReceivier::serviceDied(
         uint64_t /* cookie */,
         const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
     ALOGW("Sensors HAL died, attempting to reconnect.");
-    // TODO: Attempt reconnect
+    SensorDevice::getInstance().prepareForReconnect();
 }
 
 struct SensorsCallback : public ISensorsCallback {
@@ -81,11 +92,20 @@
 };
 
 SensorDevice::SensorDevice()
-        : mHidlTransportErrors(20), mRestartWaiter(new HidlServiceRegistrationWaiter()) {
+        : mHidlTransportErrors(20),
+          mRestartWaiter(new HidlServiceRegistrationWaiter()),
+          mReconnecting(false) {
     if (!connectHidlService()) {
         return;
     }
 
+    initializeSensorList();
+
+    mIsDirectReportSupported =
+           (checkReturn(mSensors->unregisterDirectChannel(-1)) != Result::INVALID_OPERATION);
+}
+
+void SensorDevice::initializeSensorList() {
     float minPowerMa = 0.001; // 1 microAmp
 
     checkReturn(mSensors->getSensorsList(
@@ -110,9 +130,6 @@
                     checkReturn(mSensors->activate(list[i].sensorHandle, 0 /* enabled */));
                 }
             }));
-
-    mIsDirectReportSupported =
-           (checkReturn(mSensors->unregisterDirectChannel(-1)) != Result::INVALID_OPERATION);
 }
 
 SensorDevice::~SensorDevice() {
@@ -204,6 +221,108 @@
     return connectionStatus;
 }
 
+void SensorDevice::prepareForReconnect() {
+    mReconnecting = true;
+
+    // Wake up the polling thread so it returns and allows the SensorService to initiate
+    // a reconnect.
+    mEventQueueFlag->wake(asBaseType(INTERNAL_WAKE));
+}
+
+void SensorDevice::reconnect() {
+    Mutex::Autolock _l(mLock);
+    mSensors = nullptr;
+
+    auto previousActivations = mActivationCount;
+    auto previousSensorList = mSensorList;
+
+    mActivationCount.clear();
+    mSensorList.clear();
+
+    if (connectHidlServiceV2_0() == HalConnectionStatus::CONNECTED) {
+        initializeSensorList();
+
+        if (sensorHandlesChanged(previousSensorList, mSensorList)) {
+            LOG_ALWAYS_FATAL("Sensor handles changed, cannot re-enable sensors.");
+        } else {
+            reactivateSensors(previousActivations);
+        }
+    }
+    mReconnecting = false;
+}
+
+bool SensorDevice::sensorHandlesChanged(const Vector<sensor_t>& oldSensorList,
+                                        const Vector<sensor_t>& newSensorList) {
+    bool didChange = false;
+
+    if (oldSensorList.size() != newSensorList.size()) {
+        didChange = true;
+    }
+
+    for (size_t i = 0; i < newSensorList.size() && !didChange; i++) {
+        bool found = false;
+        const sensor_t& newSensor = newSensorList[i];
+        for (size_t j = 0; j < oldSensorList.size() && !found; j++) {
+            const sensor_t& prevSensor = oldSensorList[j];
+            if (prevSensor.handle == newSensor.handle) {
+                found = true;
+                if (!sensorIsEquivalent(prevSensor, newSensor)) {
+                    didChange = true;
+                }
+            }
+        }
+
+        if (!found) {
+            // Could not find the new sensor in the old list of sensors, the lists must
+            // have changed.
+            didChange = true;
+        }
+    }
+    return didChange;
+}
+
+bool SensorDevice::sensorIsEquivalent(const sensor_t& prevSensor, const sensor_t& newSensor) {
+    bool equivalent = true;
+    if (prevSensor.handle != newSensor.handle ||
+            (strcmp(prevSensor.vendor, newSensor.vendor) != 0) ||
+            (strcmp(prevSensor.stringType, newSensor.stringType) != 0) ||
+            (strcmp(prevSensor.requiredPermission, newSensor.requiredPermission) != 0) ||
+            (prevSensor.version != newSensor.version) ||
+            (prevSensor.type != newSensor.type) ||
+            (std::abs(prevSensor.maxRange - newSensor.maxRange) > 0.001f) ||
+            (std::abs(prevSensor.resolution - newSensor.resolution) > 0.001f) ||
+            (std::abs(prevSensor.power - newSensor.power) > 0.001f) ||
+            (prevSensor.minDelay != newSensor.minDelay) ||
+            (prevSensor.fifoReservedEventCount != newSensor.fifoReservedEventCount) ||
+            (prevSensor.fifoMaxEventCount != newSensor.fifoMaxEventCount) ||
+            (prevSensor.maxDelay != newSensor.maxDelay) ||
+            (prevSensor.flags != newSensor.flags)) {
+        equivalent = false;
+    }
+    return equivalent;
+}
+
+void SensorDevice::reactivateSensors(const DefaultKeyedVector<int, Info>& previousActivations) {
+    for (size_t i = 0; i < mSensorList.size(); i++) {
+        int handle = mSensorList[i].handle;
+        ssize_t activationIndex = previousActivations.indexOfKey(handle);
+        if (activationIndex < 0 || previousActivations[activationIndex].numActiveClients() <= 0) {
+            continue;
+        }
+
+        const Info& info = previousActivations[activationIndex];
+        for (size_t j = 0; j < info.batchParams.size(); j++) {
+            const BatchParams& batchParams = info.batchParams[j];
+            status_t res = batchLocked(info.batchParams.keyAt(j), handle, 0 /* flags */,
+                    batchParams.mTSample, batchParams.mTBatch);
+
+            if (res == NO_ERROR) {
+                activateLocked(info.batchParams.keyAt(j), handle, true /* enabled */);
+            }
+        }
+    }
+}
+
 void SensorDevice::handleDynamicSensorConnection(int handle, bool connected) {
     // not need to check mSensors because this is is only called after successful poll()
     if (connected) {
@@ -261,6 +380,8 @@
 }
 
 ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
+    if (mSensors == nullptr) return NO_INIT;
+
     ssize_t eventsRead = 0;
     if (mSensors->supportsMessageQueues()) {
         eventsRead = pollFmq(buffer, count);
@@ -274,8 +395,6 @@
 }
 
 ssize_t SensorDevice::pollHal(sensors_event_t* buffer, size_t count) {
-    if (mSensors == nullptr) return NO_INIT;
-
     ssize_t err;
     int numHidlTransportErrors = 0;
     bool hidlTransportError = false;
@@ -320,10 +439,6 @@
 }
 
 ssize_t SensorDevice::pollFmq(sensors_event_t* buffer, size_t maxNumEventsToRead) {
-    if (mSensors == nullptr) {
-        return NO_INIT;
-    }
-
     ssize_t eventsRead = 0;
     size_t availableEvents = mEventQueue->availableToRead();
 
@@ -334,13 +449,19 @@
         // able to be called with the correct number of events to read. If the specified number of
         // events is not available, then read() would return no events, possibly introducing
         // additional latency in delivering events to applications.
-        mEventQueueFlag->wait(static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS),
-                              &eventFlagState);
+        mEventQueueFlag->wait(asBaseType(EventQueueFlagBits::READ_AND_PROCESS) |
+                              asBaseType(INTERNAL_WAKE), &eventFlagState);
         availableEvents = mEventQueue->availableToRead();
 
-        if (availableEvents == 0) {
+        if ((eventFlagState & asBaseType(EventQueueFlagBits::READ_AND_PROCESS)) &&
+                availableEvents == 0) {
             ALOGW("Event FMQ wake without any events");
         }
+
+        if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mReconnecting) {
+            ALOGD("Event FMQ internal wake, returning from poll with no events");
+            return DEAD_OBJECT;
+        }
     }
 
     size_t eventsToRead = std::min({availableEvents, maxNumEventsToRead, mEventBuffer.size()});
@@ -387,7 +508,8 @@
 }
 
 void SensorDevice::writeWakeLockHandled(uint32_t count) {
-    if (mSensors->supportsMessageQueues() && !mWakeLockQueue->write(&count)) {
+    if (mSensors != nullptr && mSensors->supportsMessageQueues() &&
+            !mWakeLockQueue->write(&count)) {
         ALOGW("Failed to write wake lock handled");
     }
 }
@@ -406,10 +528,15 @@
 status_t SensorDevice::activate(void* ident, int handle, int enabled) {
     if (mSensors == nullptr) return NO_INIT;
 
-    status_t err(NO_ERROR);
+    Mutex::Autolock _l(mLock);
+    return activateLocked(ident, handle, enabled);
+}
+
+status_t SensorDevice::activateLocked(void* ident, int handle, int enabled) {
     bool actuateHardware = false;
 
-    Mutex::Autolock _l(mLock);
+    status_t err(NO_ERROR);
+
     ssize_t activationIndex = mActivationCount.indexOfKey(handle);
     if (activationIndex < 0) {
         ALOGW("Handle %d cannot be found in activation record", handle);
@@ -509,6 +636,11 @@
              ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
 
     Mutex::Autolock _l(mLock);
+    return batchLocked(ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
+}
+
+status_t SensorDevice::batchLocked(void* ident, int handle, int flags, int64_t samplingPeriodNs,
+                                   int64_t maxBatchReportLatencyNs) {
     ssize_t activationIndex = mActivationCount.indexOfKey(handle);
     if (activationIndex < 0) {
         ALOGW("Handle %d cannot be found in activation record", handle);
@@ -739,7 +871,7 @@
 
 // ---------------------------------------------------------------------------
 
-int SensorDevice::Info::numActiveClients() {
+int SensorDevice::Info::numActiveClients() const {
     SensorDevice& device(SensorDevice::getInstance());
     int num = 0;
     for (size_t i = 0; i < batchParams.size(); ++i) {
@@ -838,8 +970,12 @@
 }
 
 void SensorDevice::handleHidlDeath(const std::string & detail) {
-    // restart is the only option at present.
-    LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
+    if (!SensorDevice::getInstance().mSensors->supportsMessageQueues()) {
+        // restart is the only option at present.
+        LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
+    } else {
+        ALOGD("ISensors HAL died, death recipient will attempt reconnect");
+    }
 }
 
 // ---------------------------------------------------------------------------