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