sensorservice: Add proximity active callback APIs.

Bug: 175793106
Test: Tested using a temporary debug line in onProximityActiveLocked()
      and checking the counter going and up and down using the sensor
      test app plus the sensor_test CLI.
      Also tested willDisableAllSensors/didEnableAllSensors path by
      putting the service into restricted mode at various times.

Change-Id: Ic44d29f8f9de681cc6abaf722d6dca5266e358a3
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
index 73a6db5..560834f 100644
--- a/services/sensorservice/SensorInterface.cpp
+++ b/services/sensorservice/SensorInterface.cpp
@@ -17,6 +17,7 @@
 #include "SensorInterface.h"
 #include "SensorDevice.h"
 #include "SensorFusion.h"
+#include "SensorService.h"
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -85,4 +86,35 @@
 }
 
 // ---------------------------------------------------------------------------
+
+ProximitySensor::ProximitySensor(const sensor_t& sensor, SensorService& service)
+        : HardwareSensor(sensor), mSensorService(service) {
+}
+
+status_t ProximitySensor::activate(void* ident, bool enabled) {
+    bool wasActive = mActive;
+    status_t status = HardwareSensor::activate(ident, enabled);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    mActive = enabled;
+    if (wasActive != enabled) {
+        mSensorService.onProximityActiveLocked(enabled);
+    }
+    return NO_ERROR;
+}
+
+void ProximitySensor::willDisableAllSensors() {
+    if (mSensorDevice.isSensorActive(mSensor.getHandle())) {
+        mSensorService.onProximityActiveLocked(false);
+    }
+}
+
+void ProximitySensor::didEnableAllSensors() {
+    if (mSensorDevice.isSensorActive(mSensor.getHandle())) {
+        mSensorService.onProximityActiveLocked(true);
+    }
+}
+
+// ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
index b5375cb..ea181c9 100644
--- a/services/sensorservice/SensorInterface.h
+++ b/services/sensorservice/SensorInterface.h
@@ -26,6 +26,7 @@
 // ---------------------------------------------------------------------------
 class SensorDevice;
 class SensorFusion;
+class SensorService;
 
 class SensorInterface : public VirtualLightRefBase {
 public:
@@ -43,6 +44,9 @@
     virtual const Sensor& getSensor() const = 0;
     virtual bool isVirtual() const = 0;
     virtual void autoDisable(void* /*ident*/, int /*handle*/) = 0;
+
+    virtual void willDisableAllSensors() = 0;
+    virtual void didEnableAllSensors() = 0;
 };
 
 class BaseSensor : public SensorInterface {
@@ -65,6 +69,9 @@
 
     virtual const Sensor& getSensor() const override { return mSensor; }
     virtual void autoDisable(void* /*ident*/, int /*handle*/) override { }
+
+    virtual void willDisableAllSensors() override { }
+    virtual void didEnableAllSensors() override { }
 protected:
     SensorDevice& mSensorDevice;
     Sensor mSensor;
@@ -100,6 +107,20 @@
     SensorFusion& mSensorFusion;
 };
 
+// ---------------------------------------------------------------------------
+
+class ProximitySensor : public HardwareSensor {
+public:
+    explicit ProximitySensor(const sensor_t& sensor, SensorService& service);
+
+    status_t activate(void* ident, bool enabled) override;
+
+    void willDisableAllSensors() override;
+    void didEnableAllSensors() override;
+private:
+    SensorService& mSensorService;
+    bool mActive;
+};
 
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/sensorservice/SensorList.h b/services/sensorservice/SensorList.h
index 617ceef..049ae7c 100644
--- a/services/sensorservice/SensorList.h
+++ b/services/sensorservice/SensorList.h
@@ -36,6 +36,15 @@
 
 class SensorList : public Dumpable {
 public:
+    struct Entry {
+        sp<SensorInterface> si;
+        const bool isForDebug;
+        const bool isVirtual;
+        Entry(SensorInterface* si_, bool debug_, bool virtual_) :
+            si(si_), isForDebug(debug_), isVirtual(virtual_) {
+        }
+    };
+
     // After SensorInterface * is added into SensorList, it can be assumed that SensorList own the
     // object it pointed to and the object should not be released elsewhere.
     bool add(int handle, SensorInterface* si, bool isForDebug = false, bool isVirtual = false);
@@ -69,25 +78,6 @@
     template <typename TF>
     void forEachSensor(const TF& f) const;
 
-    const Sensor& getNonSensor() const { return mNonSensor;}
-
-    // Dumpable interface
-    virtual std::string dump() const override;
-    virtual void dump(util::ProtoOutputStream* proto) const override;
-
-    virtual ~SensorList();
-private:
-    struct Entry {
-        sp<SensorInterface> si;
-        const bool isForDebug;
-        const bool isVirtual;
-        Entry(SensorInterface* si_, bool debug_, bool virtual_) :
-            si(si_), isForDebug(debug_), isVirtual(virtual_) {
-        }
-    };
-
-    const static Sensor mNonSensor; //.getName() == "unknown",
-
     // Iterate through Entry in sensor list and perform operation f on each Entry.
     //
     // TF is a function with the signature:
@@ -99,6 +89,16 @@
     template <typename TF>
     void forEachEntry(const TF& f) const;
 
+    const Sensor& getNonSensor() const { return mNonSensor;}
+
+    // Dumpable interface
+    virtual std::string dump() const override;
+    virtual void dump(util::ProtoOutputStream* proto) const override;
+
+    virtual ~SensorList();
+private:
+    const static Sensor mNonSensor; //.getName() == "unknown",
+
     template <typename T, typename TF>
     T getOne(int handle, const TF& accessor, T def = T()) const;
 
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index f949196..9df020d 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -51,7 +51,6 @@
 #include "SensorRecord.h"
 #include "SensorRegistrationInfo.h"
 
-#include <ctime>
 #include <inttypes.h>
 #include <math.h>
 #include <sched.h>
@@ -61,8 +60,13 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <ctime>
+#include <future>
+
 #include <private/android_filesystem_config.h>
 
+using namespace std::chrono_literals;
+
 namespace android {
 // ---------------------------------------------------------------------------
 
@@ -83,6 +87,8 @@
 String16 SensorService::sSensorInterfaceDescriptorPrefix =
         String16("android.frameworks.sensorservice@");
 AppOpsManager SensorService::sAppOpsManager;
+std::atomic_uint64_t SensorService::curProxCallbackSeq(0);
+std::atomic_uint64_t SensorService::completedCallbackSeq(0);
 
 #define SENSOR_SERVICE_DIR "/data/system/sensor_service"
 #define SENSOR_SERVICE_HMAC_KEY_FILE  SENSOR_SERVICE_DIR "/hmac_key"
@@ -97,7 +103,7 @@
 
 SensorService::SensorService()
     : mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),
-      mWakeLockAcquired(false) {
+      mWakeLockAcquired(false), mProximityActiveCount(0) {
     mUidPolicy = new UidPolicy(this);
     mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
 }
@@ -168,7 +174,7 @@
                     (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR);
 
             for (ssize_t i=0 ; i<count ; i++) {
-                bool useThisSensor=true;
+                bool useThisSensor = true;
 
                 switch (list[i].type) {
                     case SENSOR_TYPE_ACCELEROMETER:
@@ -197,7 +203,11 @@
                         break;
                 }
                 if (useThisSensor) {
-                    registerSensor( new HardwareSensor(list[i]) );
+                    if (list[i].type == SENSOR_TYPE_PROXIMITY) {
+                        registerSensor(new ProximitySensor(list[i], *this));
+                    } else {
+                        registerSensor( new HardwareSensor(list[i]) );
+                    }
                 }
             }
 
@@ -670,6 +680,10 @@
         bool hasAccess = hasSensorAccessLocked(conn->getUid(), conn->getOpPackageName());
         conn->onSensorAccessChanged(hasAccess);
     }
+    mSensors.forEachEntry([](const SensorServiceUtil::SensorList::Entry& e) {
+        e.si->willDisableAllSensors();
+        return true;
+    });
     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
@@ -695,6 +709,10 @@
     }
     SensorDevice& dev(SensorDevice::getInstance());
     dev.enableAllSensors();
+    mSensors.forEachEntry([](const SensorServiceUtil::SensorList::Entry& e) {
+        e.si->didEnableAllSensors();
+        return true;
+    });
     for (const sp<SensorDirectConnection>& conn : connLock->getDirectConnections()) {
         bool hasAccess = hasSensorAccessLocked(conn->getUid(), conn->getOpPackageName());
         conn->onSensorAccessChanged(hasAccess);
@@ -1520,6 +1538,10 @@
     if (err == NO_ERROR) {
         mCurrentOperatingMode = NORMAL;
         dev.enableAllSensors();
+        mSensors.forEachEntry([](const SensorServiceUtil::SensorList::Entry& e) {
+            e.si->didEnableAllSensors();
+            return true;
+        });
     }
     return err;
 }
@@ -1584,6 +1606,80 @@
     mConnectionHolder.removeDirectConnection(c);
 }
 
+void SensorService::onProximityActiveLocked(bool isActive) {
+    int prevCount = mProximityActiveCount;
+    bool activeStateChanged = false;
+    if (isActive) {
+        mProximityActiveCount++;
+        activeStateChanged = prevCount == 0;
+    } else {
+        mProximityActiveCount--;
+        if (mProximityActiveCount < 0) {
+            ALOGE("Proximity active count is negative (%d)!", mProximityActiveCount);
+        }
+        activeStateChanged = prevCount > 0 && mProximityActiveCount <= 0;
+    }
+
+    if (activeStateChanged) {
+        notifyProximityStateLocked(mProximityActiveListeners);
+    }
+}
+
+void SensorService::notifyProximityStateLocked(
+        const std::vector<sp<ProximityActiveListener>>& listnrs) {
+    std::async(
+        std::launch::async,
+        [](uint64_t mySeq, bool isActive, std::vector<sp<ProximityActiveListener>> listeners) {
+            while (completedCallbackSeq.load() != mySeq - 1)
+                std::this_thread::sleep_for(1ms);
+            for (auto& listener : listeners)
+                listener->onProximityActive(isActive);
+            completedCallbackSeq++;
+        },
+        ++curProxCallbackSeq, mProximityActiveCount > 0,
+        listnrs /* (this is meant to be a copy) */
+    );
+}
+
+status_t SensorService::addProximityActiveListener(const sp<ProximityActiveListener>& callback) {
+    if (callback == nullptr) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mLock);
+
+    // Check if the callback was already added.
+    for (const auto& cb : mProximityActiveListeners) {
+        if (cb == callback) {
+            return ALREADY_EXISTS;
+        }
+    }
+
+    mProximityActiveListeners.push_back(callback);
+    std::vector<sp<ProximityActiveListener>> listener(1, callback);
+    notifyProximityStateLocked(listener);
+    return OK;
+}
+
+status_t SensorService::removeProximityActiveListener(
+        const sp<ProximityActiveListener>& callback) {
+    if (callback == nullptr) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mLock);
+
+    for (auto iter = mProximityActiveListeners.begin();
+         iter != mProximityActiveListeners.end();
+         ++iter) {
+        if (*iter == callback) {
+            mProximityActiveListeners.erase(iter);
+            return OK;
+        }
+    }
+    return NAME_NOT_FOUND;
+}
+
 sp<SensorInterface> SensorService::getSensorInterfaceFromHandle(int handle) const {
     return mSensors.getInterface(handle);
 }
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index a563a60..def6611 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -89,9 +89,23 @@
       UID_STATE_IDLE,
     };
 
+    class ProximityActiveListener : public virtual RefBase {
+    public:
+        // Note that the callback is invoked from an async thread and can interact with the
+        // SensorService directly.
+        virtual void onProximityActive(bool isActive) = 0;
+    };
+
+    static char const* getServiceName() ANDROID_API { return "sensorservice"; }
+    SensorService() ANDROID_API;
+
     void cleanupConnection(SensorEventConnection* connection);
     void cleanupConnection(SensorDirectConnection* c);
 
+    // Call with mLock held.
+    void onProximityActiveLocked(bool isActive);
+    void notifyProximityStateLocked(const std::vector<sp<ProximityActiveListener>>& listeners);
+
     status_t enable(const sp<SensorEventConnection>& connection, int handle,
                     nsecs_t samplingPeriodNs,  nsecs_t maxBatchReportLatencyNs, int reservedFlags,
                     const String16& opPackageName);
@@ -104,6 +118,9 @@
     status_t flushSensor(const sp<SensorEventConnection>& connection,
                          const String16& opPackageName);
 
+    status_t addProximityActiveListener(const sp<ProximityActiveListener>& callback) ANDROID_API;
+    status_t removeProximityActiveListener(const sp<ProximityActiveListener>& callback) ANDROID_API;
+
     // Returns true if a sensor should be throttled according to our rate-throttling rules.
     static bool isSensorInCappedSet(int sensorType);
 
@@ -305,8 +322,6 @@
     };
 
     static const char* WAKE_LOCK_NAME;
-    static char const* getServiceName() ANDROID_API { return "sensorservice"; }
-    SensorService() ANDROID_API;
     virtual ~SensorService();
 
     virtual void onFirstRef();
@@ -326,6 +341,7 @@
     virtual int setOperationParameter(
             int32_t handle, int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints);
     virtual status_t dump(int fd, const Vector<String16>& args);
+
     status_t dumpProtoLocked(int fd, ConnectionSafeAutolock* connLock) const;
     String8 getSensorName(int handle) const;
     String8 getSensorStringType(int handle) const;
@@ -433,6 +449,9 @@
     static uint8_t sHmacGlobalKey[128];
     static bool sHmacGlobalKeyIsValid;
 
+    static std::atomic_uint64_t curProxCallbackSeq;
+    static std::atomic_uint64_t completedCallbackSeq;
+
     SensorServiceUtil::SensorList mSensors;
     status_t mInitCheck;
 
@@ -476,6 +495,10 @@
     std::map<userid_t, sp<SensorPrivacyPolicy>> mMicSensorPrivacyPolicies;
     // Checks if the mic sensor privacy is enabled for the uid
     bool isMicSensorPrivacyEnabledForUid(uid_t uid);
+
+    // Counts how many proximity sensors are currently active.
+    int mProximityActiveCount;
+    std::vector<sp<ProximityActiveListener>> mProximityActiveListeners;
 };
 
 } // namespace android