Direct report mode support in sensor service and client
Added SensorDirectConnection to represent the direct channel.
The life-cycle is similar to that of SensorEventConnection.
Modified SensorDevice and SensorDeviceTreble to support new
HAL API. Added support in SensorManager, SensorService, binder
classes. Also added related helper functions in Sensor and dumpsys
support in SensorList.
Test: manual test with demo app
Bug: 30985702
Change-Id: I8750294b6aab717ed7f525299be642f1f0b85558
diff --git a/include/gui/ISensorEventConnection.h b/include/gui/ISensorEventConnection.h
index 857444b..2ccd832 100644
--- a/include/gui/ISensorEventConnection.h
+++ b/include/gui/ISensorEventConnection.h
@@ -40,6 +40,7 @@
nsecs_t maxBatchReportLatencyNs, int reservedFlags) = 0;
virtual status_t setEventRate(int handle, nsecs_t ns) = 0;
virtual status_t flush() = 0;
+ virtual int32_t configureChannel(int32_t handle, int32_t rateLevel) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/ISensorServer.h b/include/gui/ISensorServer.h
index 737c430..0c36c99 100644
--- a/include/gui/ISensorServer.h
+++ b/include/gui/ISensorServer.h
@@ -25,6 +25,8 @@
#include <binder/IInterface.h>
+struct native_handle;
+typedef struct native_handle native_handle_t;
namespace android {
// ----------------------------------------------------------------------------
@@ -43,6 +45,9 @@
virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
int mode, const String16& opPackageName) = 0;
virtual int32_t isDataInjectionEnabled() = 0;
+
+ virtual sp<ISensorEventConnection> createSensorDirectConnection(const String16& opPackageName,
+ uint32_t size, int32_t type, int32_t format, const native_handle_t *resource) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
index 7506835..d886b2b 100644
--- a/include/gui/Sensor.h
+++ b/include/gui/Sensor.h
@@ -91,6 +91,8 @@
bool isWakeUpSensor() const;
bool isDynamicSensor() const;
bool hasAdditionalInfo() const;
+ int32_t getHighestDirectReportRateLevel() const;
+ bool isDirectChannelTypeSupported(int32_t sharedMemType) const;
int32_t getReportingMode() const;
// Note that after setId() has been called, getUuid() no longer
diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h
index 6c6230f..5b34ff4 100644
--- a/include/gui/SensorManager.h
+++ b/include/gui/SensorManager.h
@@ -34,10 +34,15 @@
#include <gui/SensorEventQueue.h>
+#include <unordered_map>
+
// ----------------------------------------------------------------------------
// Concrete types for the NDK
struct ASensorManager { };
+struct native_handle;
+typedef struct native_handle native_handle_t;
+
// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
@@ -59,6 +64,9 @@
Sensor const* getDefaultSensor(int type);
sp<SensorEventQueue> createEventQueue(String8 packageName = String8(""), int mode = 0);
bool isDataInjectionEnabled();
+ int createDirectChannel(size_t size, int channelType, const native_handle_t *channelData);
+ void destroyDirectChannel(int channelNativeHandle);
+ int configureDirectChannel(int channelNativeHandle, int sensorHandle, int rateLevel);
private:
// DeathRecipient interface
@@ -77,6 +85,8 @@
Vector<Sensor> mSensors;
sp<IBinder::DeathRecipient> mDeathObserver;
const String16 mOpPackageName;
+ std::unordered_map<int, sp<ISensorEventConnection>> mDirectConnection;
+ int32_t mDirectConnectionHandle;
};
// ----------------------------------------------------------------------------
diff --git a/libs/gui/ISensorEventConnection.cpp b/libs/gui/ISensorEventConnection.cpp
index 59ecee7..8af51c5 100644
--- a/libs/gui/ISensorEventConnection.cpp
+++ b/libs/gui/ISensorEventConnection.cpp
@@ -34,7 +34,8 @@
GET_SENSOR_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
ENABLE_DISABLE,
SET_EVENT_RATE,
- FLUSH_SENSOR
+ FLUSH_SENSOR,
+ CONFIGURE_CHANNEL
};
class BpSensorEventConnection : public BpInterface<ISensorEventConnection>
@@ -85,6 +86,15 @@
remote()->transact(FLUSH_SENSOR, data, &reply);
return reply.readInt32();
}
+
+ virtual int32_t configureChannel(int32_t handle, int32_t rateLevel) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
+ data.writeInt32(handle);
+ data.writeInt32(rateLevel);
+ remote()->transact(CONFIGURE_CHANNEL, data, &reply);
+ return reply.readInt32();
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -131,6 +141,15 @@
reply->writeInt32(result);
return NO_ERROR;
}
+ case CONFIGURE_CHANNEL: {
+ CHECK_INTERFACE(ISensorEventConnection, data, reply);
+ int handle = data.readInt32();
+ int rateLevel = data.readInt32();
+ status_t result = configureChannel(handle, rateLevel);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ }
+
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp
index 07c507a..aea7403 100644
--- a/libs/gui/ISensorServer.cpp
+++ b/libs/gui/ISensorServer.cpp
@@ -17,6 +17,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <cutils/native_handle.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Vector.h>
@@ -37,6 +38,7 @@
CREATE_SENSOR_EVENT_CONNECTION,
ENABLE_DATA_INJECTION,
GET_DYNAMIC_SENSOR_LIST,
+ CREATE_SENSOR_DIRECT_CONNECTION,
};
class BpSensorServer : public BpInterface<ISensorServer>
@@ -101,6 +103,19 @@
remote()->transact(ENABLE_DATA_INJECTION, data, &reply);
return reply.readInt32();
}
+
+ virtual sp<ISensorEventConnection> createSensorDirectConnection(const String16& opPackageName,
+ uint32_t size, int32_t type, int32_t format, const native_handle_t *resource) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+ data.writeString16(opPackageName);
+ data.writeUint32(size);
+ data.writeInt32(type);
+ data.writeInt32(format);
+ data.writeNativeHandle(resource);
+ remote()->transact(CREATE_SENSOR_DIRECT_CONNECTION, data, &reply);
+ return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -153,6 +168,20 @@
}
return NO_ERROR;
}
+ case CREATE_SENSOR_DIRECT_CONNECTION: {
+ CHECK_INTERFACE(ISensorServer, data, reply);
+ const String16& opPackageName = data.readString16();
+ uint32_t size = data.readUint32();
+ int32_t type = data.readInt32();
+ int32_t format = data.readInt32();
+ native_handle_t *resource = data.readNativeHandle();
+ sp<ISensorEventConnection> ch =
+ createSensorDirectConnection(opPackageName, size, type, format, resource);
+ native_handle_close(resource);
+ native_handle_delete(resource);
+ reply->writeStrongBinder(IInterface::asBinder(ch));
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 9cb2035..2fd29d5 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -300,7 +300,15 @@
// Feature flags
// Set DYNAMIC_SENSOR_MASK and ADDITIONAL_INFO_MASK flag here. Compatible with HAL 1_3.
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
- mFlags |= (hwSensor.flags & (DYNAMIC_SENSOR_MASK | ADDITIONAL_INFO_MASK));
+ mFlags |= hwSensor.flags & (DYNAMIC_SENSOR_MASK | ADDITIONAL_INFO_MASK);
+ }
+ // Set DIRECT_REPORT_MASK and DIRECT_CHANNEL_MASK flags. Compatible with HAL 1_3.
+ if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
+ // only on continuous sensors direct report mode is defined
+ if ((mFlags & REPORTING_MODE_MASK) == SENSOR_FLAG_CONTINUOUS_MODE) {
+ mFlags |= hwSensor.flags
+ & (SENSOR_FLAG_MASK_DIRECT_REPORT | SENSOR_FLAG_MASK_DIRECT_CHANNEL);
+ }
}
// Set DATA_INJECTION flag here. Defined in HAL 1_4.
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_4) {
@@ -410,6 +418,21 @@
return (mFlags & SENSOR_FLAG_ADDITIONAL_INFO) != 0;
}
+int32_t Sensor::getHighestDirectReportRateLevel() const {
+ return ((mFlags & SENSOR_FLAG_MASK_DIRECT_REPORT) >> SENSOR_FLAG_SHIFT_DIRECT_REPORT);
+}
+
+bool Sensor::isDirectChannelTypeSupported(int32_t sharedMemType) const {
+ switch (sharedMemType) {
+ case SENSOR_DIRECT_MEM_TYPE_ASHMEM:
+ return mFlags & SENSOR_FLAG_DIRECT_CHANNEL_ASHMEM;
+ case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
+ return mFlags & SENSOR_FLAG_DIRECT_CHANNEL_GRALLOC;
+ default:
+ return false;
+ }
+}
+
int32_t Sensor::getReportingMode() const {
return ((mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT);
}
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 57c3073..46eaf28 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <cutils/native_handle.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Singleton.h>
@@ -89,7 +90,7 @@
}
SensorManager::SensorManager(const String16& opPackageName)
- : mSensorList(0), mOpPackageName(opPackageName) {
+ : mSensorList(0), mOpPackageName(opPackageName), mDirectConnectionHandle(1) {
// okay we're not locked here, but it's not needed during construction
assertStateLocked();
}
@@ -237,5 +238,62 @@
return false;
}
+int SensorManager::createDirectChannel(
+ size_t size, int channelType, const native_handle_t *resourceHandle) {
+ Mutex::Autolock _l(mLock);
+ if (assertStateLocked() != NO_ERROR) {
+ return NO_INIT;
+ }
+
+ switch (channelType) {
+ case SENSOR_DIRECT_MEM_TYPE_ASHMEM: {
+ sp<ISensorEventConnection> conn =
+ mSensorServer->createSensorDirectConnection(mOpPackageName,
+ static_cast<uint32_t>(size),
+ static_cast<int32_t>(channelType),
+ SENSOR_DIRECT_FMT_SENSORS_EVENT, resourceHandle);
+ if (conn == nullptr) {
+ return NO_MEMORY;
+ }
+ int nativeHandle = mDirectConnectionHandle++;
+ mDirectConnection.emplace(nativeHandle, conn);
+ return nativeHandle;
+ }
+ case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
+ LOG_FATAL("%s: Finish implementation of ION and GRALLOC or remove", __FUNCTION__);
+ return BAD_VALUE;
+ default:
+ ALOGE("Bad channel shared memory type %d", channelType);
+ return BAD_VALUE;
+ }
+}
+
+void SensorManager::destroyDirectChannel(int channelNativeHandle) {
+ Mutex::Autolock _l(mLock);
+ if (assertStateLocked() == NO_ERROR) {
+ mDirectConnection.erase(channelNativeHandle);
+ }
+}
+
+int SensorManager::configureDirectChannel(int channelNativeHandle, int sensorHandle, int rateLevel) {
+ Mutex::Autolock _l(mLock);
+ if (assertStateLocked() != NO_ERROR) {
+ return NO_INIT;
+ }
+
+ auto i = mDirectConnection.find(channelNativeHandle);
+ if (i == mDirectConnection.end()) {
+ ALOGE("Cannot find the handle in client direct connection table");
+ return BAD_VALUE;
+ }
+
+ int ret;
+ ret = i->second->configureChannel(sensorHandle, rateLevel);
+ ALOGE_IF(ret < 0, "SensorManager::configureChannel (%d, %d) returns %d",
+ static_cast<int>(sensorHandle), static_cast<int>(rateLevel),
+ static_cast<int>(ret));
+ return ret;
+}
+
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index 86af0ef..c41630a 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -10,6 +10,7 @@
OrientationSensor.cpp \
RecentEventLogger.cpp \
RotationVectorSensor.cpp \
+ SensorDirectConnection.cpp \
SensorEventConnection.cpp \
SensorFusion.cpp \
SensorInterface.cpp \
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 0245b26..41ad918 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -14,23 +14,27 @@
* limitations under the License.
*/
-#include <inttypes.h>
-#include <math.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/Atomic.h>
-#include <utils/Errors.h>
-#include <utils/Singleton.h>
+#include "SensorDevice.h"
+#include "SensorService.h"
+
#include <binder/BinderService.h>
#include <binder/Parcel.h>
#include <binder/IServiceManager.h>
-
+#include <cutils/ashmem.h>
#include <hardware/sensors.h>
+#include <utils/Atomic.h>
+#include <utils/Errors.h>
+#include <utils/Singleton.h>
-#include "SensorDevice.h"
-#include "SensorService.h"
+#include <inttypes.h>
+#include <math.h>
+#include <sys/mman.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sstream>
+#include <unistd.h>
namespace android {
// ---------------------------------------------------------------------------
@@ -386,7 +390,7 @@
void SensorDevice::disableAllSensors() {
Mutex::Autolock _l(mLock);
- for (size_t i = 0; i< mActivationCount.size(); ++i) {
+ for (size_t i = 0; i< mActivationCount.size(); ++i) {
const Info& info = mActivationCount.valueAt(i);
// Check if this sensor has been activated previously and disable it.
if (info.batchParams.size() > 0) {
@@ -486,6 +490,29 @@
mDisabledClients.remove(ident);
}
+int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
+ Mutex::Autolock _l(mLock);
+
+ int32_t channelHandle = mSensorDevice->register_direct_channel(
+ mSensorDevice, memory, -1 /*channel_handle*/);
+ return channelHandle;
+}
+
+void SensorDevice::unregisterDirectChannel(int32_t channelHandle) {
+ Mutex::Autolock _l(mLock);
+
+ mSensorDevice->register_direct_channel(mSensorDevice, nullptr, channelHandle);
+}
+
+int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
+ const struct sensors_direct_cfg_t *config) {
+ Mutex::Autolock _l(mLock);
+
+ int32_t ret = mSensorDevice->config_direct_report(
+ mSensorDevice, sensorHandle, channelHandle, config);
+ ALOGE_IF(ret < 0, "SensorDevice::configureDirectChannel ret %d", ret);
+ return ret;
+}
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 0bb0752..b6886a2 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -26,6 +26,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <string>
#ifdef ENABLE_TREBLE
#include <map>
@@ -57,6 +58,12 @@
status_t setDelay(void* ident, int handle, int64_t ns);
status_t flush(void* ident, int handle);
status_t setMode(uint32_t mode);
+
+ int32_t registerDirectChannel(const sensors_direct_mem_t *memory);
+ void unregisterDirectChannel(int32_t channelHandle);
+ int32_t configureDirectChannel(int32_t sensorHandle,
+ int32_t channelHandle, const struct sensors_direct_cfg_t *config);
+
void disableAllSensors();
void enableAllSensors();
void autoDisable(void *ident, int handle);
diff --git a/services/sensorservice/SensorDeviceTreble.cpp b/services/sensorservice/SensorDeviceTreble.cpp
index 37f0f6c..2877589 100644
--- a/services/sensorservice/SensorDeviceTreble.cpp
+++ b/services/sensorservice/SensorDeviceTreble.cpp
@@ -29,16 +29,9 @@
#include <sensors/convert.h>
-using android::hardware::sensors::V1_0::ISensors;
using android::hardware::hidl_vec;
-using Event = android::hardware::sensors::V1_0::Event;
-using SensorInfo = android::hardware::sensors::V1_0::SensorInfo;
-using SensorType = android::hardware::sensors::V1_0::SensorType;
-using DynamicSensorInfo = android::hardware::sensors::V1_0::DynamicSensorInfo;
-using SensorInfo = android::hardware::sensors::V1_0::SensorInfo;
-using Result = android::hardware::sensors::V1_0::Result;
-
+using namespace android::hardware::sensors::V1_0;
using namespace android::hardware::sensors::V1_0::implementation;
namespace android {
@@ -504,6 +497,90 @@
mDisabledClients.remove(ident);
}
+int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
+ Mutex::Autolock _l(mLock);
+
+ SharedMemType type;
+ switch (memory->type) {
+ case SENSOR_DIRECT_MEM_TYPE_ASHMEM:
+ type = SharedMemType::ASHMEM;
+ break;
+ case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
+ type = SharedMemType::GRALLOC;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+
+ SharedMemFormat format;
+ if (memory->format != SENSOR_DIRECT_FMT_SENSORS_EVENT) {
+ return BAD_VALUE;
+ }
+ format = SharedMemFormat::SENSORS_EVENT;
+
+ SharedMemInfo mem = {
+ .type = type,
+ .format = format,
+ .size = static_cast<uint32_t>(memory->size),
+ .memoryHandle = memory->handle,
+ };
+
+ int32_t ret;
+ mSensors->registerDirectChannel(mem,
+ [&ret](auto result, auto channelHandle) {
+ if (result == Result::OK) {
+ ret = channelHandle;
+ } else {
+ ret = StatusFromResult(result);
+ }
+ });
+ return ret;
+}
+
+void SensorDevice::unregisterDirectChannel(int32_t channelHandle) {
+ Mutex::Autolock _l(mLock);
+ mSensors->unregisterDirectChannel(channelHandle);
+}
+
+int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle,
+ int32_t channelHandle, const struct sensors_direct_cfg_t *config) {
+ Mutex::Autolock _l(mLock);
+
+ RateLevel rate;
+ switch(config->rate_level) {
+ case SENSOR_DIRECT_RATE_STOP:
+ rate = RateLevel::STOP;
+ break;
+ case SENSOR_DIRECT_RATE_NORMAL:
+ rate = RateLevel::NORMAL;
+ break;
+ case SENSOR_DIRECT_RATE_FAST:
+ rate = RateLevel::FAST;
+ break;
+ case SENSOR_DIRECT_RATE_VERY_FAST:
+ rate = RateLevel::VERY_FAST;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+
+ int32_t ret;
+ mSensors->configDirectReport(sensorHandle, channelHandle, rate,
+ [&ret, rate] (auto result, auto token) {
+ if (rate == RateLevel::STOP) {
+ ret = StatusFromResult(result);
+ } else {
+ if (result == Result::OK) {
+ ret = token;
+ } else {
+ ret = StatusFromResult(result);
+ }
+ }
+ });
+
+ return ret;
+}
+
void SensorDevice::convertToSensorEvent(
const Event &src, sensors_event_t *dst) {
::android::hardware::sensors::V1_0::implementation::convertToSensorEvent(
diff --git a/services/sensorservice/SensorDirectConnection.cpp b/services/sensorservice/SensorDirectConnection.cpp
new file mode 100644
index 0000000..662f320
--- /dev/null
+++ b/services/sensorservice/SensorDirectConnection.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SensorDevice.h"
+#include "SensorDirectConnection.h"
+#include <hardware/sensors.h>
+
+#include <sys/stat.h>
+
+#define UNUSED(x) (void)(x)
+
+namespace android {
+
+SensorService::SensorDirectConnection::SensorDirectConnection(const sp<SensorService>& service,
+ uid_t uid, const sensors_direct_mem_t *mem, int32_t halChannelHandle,
+ const String16& opPackageName)
+ : mService(service), mUid(uid), mMem(*mem),
+ mHalChannelHandle(halChannelHandle),
+ mOpPackageName(opPackageName) {
+ ALOGD_IF(DEBUG_CONNECTIONS, "Created SensorDirectConnection");
+}
+
+SensorService::SensorDirectConnection::~SensorDirectConnection() {
+ ALOGD_IF(DEBUG_CONNECTIONS, "~SensorDirectConnection %p", this);
+
+ stopAll();
+ mService->cleanupConnection(this);
+ if (mMem.handle != nullptr) {
+ native_handle_close(mMem.handle);
+ native_handle_delete(const_cast<struct native_handle*>(mMem.handle));
+ }
+}
+
+void SensorService::SensorDirectConnection::onFirstRef() {
+}
+
+void SensorService::SensorDirectConnection::dump(String8& result) const {
+ Mutex::Autolock _l(mConnectionLock);
+ result.appendFormat("\tPackage %s, HAL channel handle %d, total sensor activated %zu\n",
+ String8(mOpPackageName).string(), getHalChannelHandle(), mActivated.size());
+ for (auto &i : mActivated) {
+ result.appendFormat("\t\tSensor %#08x, rate %d\n", i.first, i.second);
+ }
+}
+
+sp<BitTube> SensorService::SensorDirectConnection::getSensorChannel() const {
+ return nullptr;
+}
+
+status_t SensorService::SensorDirectConnection::enableDisable(
+ int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,
+ int reservedFlags) {
+ // SensorDirectConnection does not support enableDisable, parameters not used
+ UNUSED(handle);
+ UNUSED(enabled);
+ UNUSED(samplingPeriodNs);
+ UNUSED(maxBatchReportLatencyNs);
+ UNUSED(reservedFlags);
+ return INVALID_OPERATION;
+}
+
+status_t SensorService::SensorDirectConnection::setEventRate(
+ int handle, nsecs_t samplingPeriodNs) {
+ // SensorDirectConnection does not support setEventRate, parameters not used
+ UNUSED(handle);
+ UNUSED(samplingPeriodNs);
+ return INVALID_OPERATION;
+}
+
+status_t SensorService::SensorDirectConnection::flush() {
+ // SensorDirectConnection does not support flush
+ return INVALID_OPERATION;
+}
+
+int32_t SensorService::SensorDirectConnection::configureChannel(int handle, int rateLevel) {
+
+ if (handle == -1 && rateLevel == SENSOR_DIRECT_RATE_STOP) {
+ stopAll();
+ return NO_ERROR;
+ }
+
+ if (mService->isOperationRestricted(mOpPackageName)) {
+ return PERMISSION_DENIED;
+ }
+
+ sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+ if (si == nullptr) {
+ return NAME_NOT_FOUND;
+ }
+
+ const Sensor& s = si->getSensor();
+ if (!SensorService::canAccessSensor(s, "config direct channel", mOpPackageName)) {
+ return PERMISSION_DENIED;
+ }
+
+ if (s.getHighestDirectReportRateLevel() == 0
+ || rateLevel > s.getHighestDirectReportRateLevel()
+ || !s.isDirectChannelTypeSupported(mMem.type)) {
+ return INVALID_OPERATION;
+ }
+
+ struct sensors_direct_cfg_t config = {
+ .rate_level = rateLevel
+ };
+
+ Mutex::Autolock _l(mConnectionLock);
+ SensorDevice& dev(SensorDevice::getInstance());
+ int ret = dev.configureDirectChannel(handle, getHalChannelHandle(), &config);
+
+ if (rateLevel == SENSOR_DIRECT_RATE_STOP) {
+ if (ret == NO_ERROR) {
+ mActivated.erase(handle);
+ } else if (ret > 0) {
+ ret = UNKNOWN_ERROR;
+ }
+ } else {
+ if (ret > 0) {
+ mActivated[handle] = rateLevel;
+ }
+ }
+
+ return ret;
+}
+
+void SensorService::SensorDirectConnection::stopAll(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);
+ }
+
+ if (backupRecord && mActivatedBackup.empty()) {
+ mActivatedBackup = mActivated;
+ }
+ mActivated.clear();
+}
+
+void SensorService::SensorDirectConnection::recoverAll() {
+ stopAll(false);
+
+ Mutex::Autolock _l(mConnectionLock);
+ SensorDevice& dev(SensorDevice::getInstance());
+
+ // recover list of report from backup
+ 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);
+ }
+}
+
+int32_t SensorService::SensorDirectConnection::getHalChannelHandle() const {
+ return mHalChannelHandle;
+}
+
+bool SensorService::SensorDirectConnection::isEquivalent(const sensors_direct_mem_t *mem) const {
+ bool ret = false;
+
+ if (mMem.type == mem->type) {
+ switch (mMem.type) {
+ case SENSOR_DIRECT_MEM_TYPE_ASHMEM: {
+ struct stat s1, s2;
+ int fd1, fd2;
+ fd1 = mMem.handle->data[0];
+ fd2 = mem->handle->data[1];
+ if (fstat(fd1, &s1) < 0 || fstat(fd2, &s2) < 0 || s1.st_ino == s2.st_ino) {
+ ret = true;
+ }
+ }
+ case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
+ LOG_FATAL("%s: Implement GRALLOC or remove", __FUNCTION__);
+ ret = true;
+ default:
+ ALOGE("Unexpected mem type %d", mMem.type);
+ ret = true;
+ }
+ }
+ return ret;
+}
+
+} // namespace android
+
diff --git a/services/sensorservice/SensorDirectConnection.h b/services/sensorservice/SensorDirectConnection.h
new file mode 100644
index 0000000..692ef0d
--- /dev/null
+++ b/services/sensorservice/SensorDirectConnection.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSOR_DIRECT_CONNECTION_H
+#define ANDROID_SENSOR_DIRECT_CONNECTION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/BinderService.h>
+
+#include <gui/Sensor.h>
+#include <gui/BitTube.h>
+#include <gui/ISensorServer.h>
+#include <gui/ISensorEventConnection.h>
+
+#include "SensorService.h"
+
+namespace android {
+
+class SensorService;
+class BitTube;
+
+class SensorService::SensorDirectConnection: public BnSensorEventConnection {
+public:
+ SensorDirectConnection(const sp<SensorService>& service, uid_t uid,
+ const sensors_direct_mem_t *mem, int32_t halChannelHandle,
+ const String16& opPackageName);
+ void dump(String8& result) const;
+ uid_t getUid() const { return mUid; }
+ 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 clearRecord = false);
+
+ // recover sensor reports previously stopped by stopAll(true)
+ // called by SensorService when return to NORMAL mode.
+ void recoverAll();
+
+protected:
+ virtual ~SensorDirectConnection();
+ // ISensorEventConnection functions
+ virtual void onFirstRef();
+ virtual sp<BitTube> getSensorChannel() const;
+ virtual status_t enableDisable(int handle, bool enabled, nsecs_t samplingPeriodNs,
+ nsecs_t maxBatchReportLatencyNs, int reservedFlags);
+ virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs);
+ virtual status_t flush();
+ virtual int32_t configureChannel(int handle, int rateLevel);
+
+private:
+ const sp<SensorService> mService;
+ const uid_t mUid;
+ const sensors_direct_mem_t mMem;
+ const int32_t mHalChannelHandle;
+ const String16 mOpPackageName;
+
+ mutable Mutex mConnectionLock;
+ std::unordered_map<int, int> mActivated;
+ std::unordered_map<int, int> mActivatedBackup;
+};
+
+} // namepsace android
+
+#endif // ANDROID_SENSOR_DIRECT_CONNECTION_H
+
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index f2f1444..d84d36e 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -23,6 +23,8 @@
#include "SensorEventConnection.h"
#include "SensorDevice.h"
+#define UNUSED(x) (void)(x)
+
namespace android {
SensorService::SensorEventConnection::SensorEventConnection(
@@ -524,6 +526,13 @@
return mService->flushSensor(this, mOpPackageName);
}
+int32_t SensorService::SensorEventConnection::configureChannel(int handle, int rateLevel) {
+ // SensorEventConnection does not support configureChannel, parameters not used
+ UNUSED(handle);
+ UNUSED(rateLevel);
+ return INVALID_OPERATION;
+}
+
int SensorService::SensorEventConnection::handleEvent(int fd, int events, void* /*data*/) {
if (events & ALOOPER_EVENT_HANGUP || events & ALOOPER_EVENT_ERROR) {
{
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index 883c16e..cd81ddd 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -74,6 +74,8 @@
nsecs_t maxBatchReportLatencyNs, int reservedFlags);
virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs);
virtual status_t flush();
+ virtual int32_t configureChannel(int handle, int rateLevel);
+
// Count the number of flush complete events which are about to be dropped in the buffer.
// Increment mPendingFlushEventsToSend in mSensorInfo. These flush complete events will be sent
// separately before the next batch of events.
diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp
index e0101c1..31c8251 100644
--- a/services/sensorservice/SensorList.cpp
+++ b/services/sensorservice/SensorList.cpp
@@ -124,7 +124,7 @@
forEachSensor([&result] (const Sensor& s) -> bool {
result.appendFormat(
"%#010x) %-25s | %-15s | ver: %" PRId32 " | type: %20s(%" PRId32
- ") | perm: %s\n\t",
+ ") | perm: %s\n",
s.getHandle(),
s.getName().string(),
s.getVendor().string(),
@@ -133,17 +133,18 @@
s.getType(),
s.getRequiredPermission().size() ? s.getRequiredPermission().string() : "n/a");
+ result.append("\t");
const int reportingMode = s.getReportingMode();
if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
- result.append(" continuous | ");
+ result.append("continuous | ");
} else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
- result.append(" on-change | ");
+ result.append("on-change | ");
} else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
- result.append(" one-shot | ");
+ result.append("one-shot | ");
} else if (reportingMode == AREPORTING_MODE_SPECIAL_TRIGGER) {
- result.append(" special-trigger | ");
+ result.append("special-trigger | ");
} else {
- result.append(" unknown-mode | ");
+ result.append("unknown-mode | ");
}
if (s.getMaxDelay() > 0) {
@@ -178,8 +179,19 @@
if (s.hasAdditionalInfo()) {
result.appendFormat("has-additional-info, ");
}
-
result.append("\n");
+
+ if (s.getHighestDirectReportRateLevel() > SENSOR_DIRECT_RATE_STOP) {
+ result.appendFormat("\thighest rate level = %d, support shared mem: ",
+ s.getHighestDirectReportRateLevel());
+ if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM)) {
+ result.append("ashmem, ");
+ }
+ if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC)) {
+ result.append("gralloc, ");
+ }
+ result.append("\n");
+ }
return true;
});
return std::string(result.string());
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 2e44736..143a3c5 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -21,6 +21,7 @@
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
+#include <cutils/ashmem.h>
#include <gui/SensorEventQueue.h>
#include <hardware/sensors.h>
@@ -40,6 +41,7 @@
#include "SensorInterface.h"
#include "SensorService.h"
+#include "SensorDirectConnection.h"
#include "SensorEventAckReceiver.h"
#include "SensorEventConnection.h"
#include "SensorRecord.h"
@@ -337,7 +339,16 @@
if (mCurrentOperatingMode != NORMAL) {
return INVALID_OPERATION;
}
+
mCurrentOperatingMode = RESTRICTED;
+ // temporarily stop all sensor direct report
+ for (auto &i : mDirectConnections) {
+ sp<SensorDirectConnection> connection(i.promote());
+ if (connection != nullptr) {
+ connection->stopAll(true /* backupRecord */);
+ }
+ }
+
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
@@ -352,6 +363,13 @@
if (mCurrentOperatingMode == RESTRICTED) {
mCurrentOperatingMode = NORMAL;
dev.enableAllSensors();
+ // recover all sensor direct report
+ for (auto &i : mDirectConnections) {
+ sp<SensorDirectConnection> connection(i.promote());
+ if (connection != nullptr) {
+ connection->recoverAll();
+ }
+ }
}
if (mCurrentOperatingMode == DATA_INJECTION) {
resetToNormalModeLocked();
@@ -430,8 +448,8 @@
case DATA_INJECTION:
result.appendFormat(" DATA_INJECTION : %s\n", mWhiteListedPackage.string());
}
- result.appendFormat("%zd active connections\n", mActiveConnections.size());
+ result.appendFormat("%zd active connections\n", mActiveConnections.size());
for (size_t i=0 ; i < mActiveConnections.size() ; i++) {
sp<SensorEventConnection> connection(mActiveConnections[i].promote());
if (connection != 0) {
@@ -440,6 +458,15 @@
}
}
+ result.appendFormat("%zd direct connections\n", mDirectConnections.size());
+ for (size_t i = 0 ; i < mDirectConnections.size() ; i++) {
+ sp<SensorDirectConnection> connection(mDirectConnections[i].promote());
+ if (connection != nullptr) {
+ result.appendFormat("Direct connection %zu:\n", i);
+ connection->dump(result);
+ }
+ }
+
result.appendFormat("Previous Registrations:\n");
// Log in the reverse chronological order.
int currentIndex = (mNextSensorRegIndex - 1 + SENSOR_REGISTRATIONS_BUF_SIZE) %
@@ -936,6 +963,85 @@
return (mCurrentOperatingMode == DATA_INJECTION);
}
+sp<ISensorEventConnection> SensorService::createSensorDirectConnection(
+ const String16& opPackageName, uint32_t size, int32_t type, int32_t format,
+ const native_handle *resource) {
+ Mutex::Autolock _l(mLock);
+
+ struct sensors_direct_mem_t mem = {
+ .type = type,
+ .format = format,
+ .size = size,
+ .handle = resource,
+ };
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+
+ if (mem.handle == nullptr) {
+ ALOGE("Failed to clone resource handle");
+ return nullptr;
+ }
+
+ // check format
+ if (format != SENSOR_DIRECT_FMT_SENSORS_EVENT) {
+ ALOGE("Direct channel format %d is unsupported!", format);
+ return nullptr;
+ }
+
+ // check for duplication
+ for (auto &i : mDirectConnections) {
+ sp<SensorDirectConnection> connection(i.promote());
+ if (connection != nullptr && connection->isEquivalent(&mem)) {
+ return nullptr;
+ }
+ }
+
+ // check specific to memory type
+ switch(type) {
+ case SENSOR_DIRECT_MEM_TYPE_ASHMEM: { // channel backed by ashmem
+ int fd = resource->data[0];
+ int size2 = ashmem_get_size_region(fd);
+ // check size consistency
+ if (size2 != static_cast<int>(size)) {
+ ALOGE("Ashmem direct channel size mismatch, %" PRIu32 " vs %d", size, size2);
+ return nullptr;
+ }
+ break;
+ }
+ case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
+ LOG_FATAL("%s: Finish implementation of ION and GRALLOC or remove", __FUNCTION__);
+ break;
+ default:
+ ALOGE("Unknown direct connection memory type %d", type);
+ return nullptr;
+ }
+
+ native_handle_t *clone = native_handle_clone(resource);
+ if (!clone) {
+ return nullptr;
+ }
+
+ SensorDirectConnection* conn = nullptr;
+ SensorDevice& dev(SensorDevice::getInstance());
+ int channelHandle = dev.registerDirectChannel(&mem);
+
+ if (channelHandle <= 0) {
+ ALOGE("SensorDevice::registerDirectChannel returns %d", channelHandle);
+ } else {
+ mem.handle = clone;
+ conn = new SensorDirectConnection(this, uid, &mem, channelHandle, opPackageName);
+ }
+
+ if (conn == nullptr) {
+ native_handle_close(clone);
+ native_handle_delete(clone);
+ } else {
+ // add to list of direct connections
+ // sensor service should never hold pointer or sp of SensorDirectConnection object.
+ mDirectConnections.add(wp<SensorDirectConnection>(conn));
+ }
+ return conn;
+}
+
status_t SensorService::resetToNormalMode() {
Mutex::Autolock _l(mLock);
return resetToNormalModeLocked();
@@ -995,11 +1101,18 @@
dev.notifyConnectionDestroyed(c);
}
+void SensorService::cleanupConnection(SensorDirectConnection* c) {
+ Mutex::Autolock _l(mLock);
+
+ SensorDevice& dev(SensorDevice::getInstance());
+ dev.unregisterDirectChannel(c->getHalChannelHandle());
+ mDirectConnections.remove(c);
+}
+
sp<SensorInterface> SensorService::getSensorInterfaceFromHandle(int handle) const {
return mSensors.getInterface(handle);
}
-
status_t SensorService::enable(const sp<SensorEventConnection>& connection,
int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags,
const String16& opPackageName) {
@@ -1013,7 +1126,7 @@
}
Mutex::Autolock _l(mLock);
- if ((mCurrentOperatingMode == RESTRICTED || mCurrentOperatingMode == DATA_INJECTION)
+ if (mCurrentOperatingMode != NORMAL
&& !isWhiteListedPackage(connection->getPackageName())) {
return INVALID_OPERATION;
}
@@ -1331,5 +1444,14 @@
return (packageName.contains(mWhiteListedPackage.string()));
}
+bool SensorService::isOperationRestricted(const String16& opPackageName) {
+ Mutex::Autolock _l(mLock);
+ if (mCurrentOperatingMode != RESTRICTED) {
+ String8 package(opPackageName);
+ return !isWhiteListedPackage(package);
+ }
+ return false;
+}
+
}; // namespace android
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index e969d8a..eeedd4a 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -67,9 +67,11 @@
{
// nested class/struct for internal use
class SensorEventConnection;
+ class SensorDirectConnection;
public:
void cleanupConnection(SensorEventConnection* connection);
+ void cleanupConnection(SensorDirectConnection* c);
status_t enable(const sp<SensorEventConnection>& connection, int handle,
nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags,
@@ -154,6 +156,8 @@
const String8& packageName,
int requestedMode, const String16& opPackageName);
virtual int isDataInjectionEnabled();
+ virtual sp<ISensorEventConnection> createSensorDirectConnection(const String16& opPackageName,
+ uint32_t size, int32_t type, int32_t format, const native_handle *resource);
virtual status_t dump(int fd, const Vector<String16>& args);
String8 getSensorName(int handle) const;
@@ -203,6 +207,7 @@
// allowed to register for or call flush on sensors. Typically only cts test packages are
// allowed.
bool isWhiteListedPackage(const String8& packageName);
+ bool isOperationRestricted(const String16& opPackageName);
// Reset the state of SensorService to NORMAL mode.
status_t resetToNormalMode();
@@ -239,6 +244,7 @@
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
wp<const SensorEventConnection> * mMapFlushEventsToConnections;
std::unordered_map<int, RecentEventLogger*> mRecentEvent;
+ SortedVector< wp<SensorDirectConnection> > mDirectConnections;
Mode mCurrentOperatingMode;
// This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only