split libsensor our of libgui
Test: compile & run
Bug: treble cleanup
Change-Id: I5b2c2a14f7d3b364d25695cf0901c5b08cfb0fc9
diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp
new file mode 100644
index 0000000..171a627
--- /dev/null
+++ b/libs/sensor/Android.bp
@@ -0,0 +1,61 @@
+// Copyright 2010 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.
+
+cc_library_shared {
+ name: "libsensor",
+
+ clang: true,
+ cppflags: [
+ "-Weverything",
+ "-Werror",
+
+ // The static constructors and destructors in this library have not been noted to
+ // introduce significant overheads
+ "-Wno-exit-time-destructors",
+ "-Wno-global-constructors",
+
+ // We only care about compiling as C++14
+ "-Wno-c++98-compat-pedantic",
+
+ // android/sensors.h uses nested anonymous unions and anonymous structs
+ "-Wno-nested-anon-types",
+ "-Wno-gnu-anonymous-struct",
+
+ // Don't warn about struct padding
+ "-Wno-padded",
+ ],
+
+ srcs: [
+ "BitTube.cpp",
+ "ISensorEventConnection.cpp",
+ "ISensorServer.cpp",
+ "Sensor.cpp",
+ "SensorEventQueue.cpp",
+ "SensorManager.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "libutils",
+ "liblog",
+ "libhardware",
+ ],
+
+ export_include_dirs: ["include"],
+
+ export_shared_lib_headers: ["libbinder", "libhardware"],
+}
+
+subdirs = ["tests"]
diff --git a/libs/sensor/BitTube.cpp b/libs/sensor/BitTube.cpp
new file mode 100644
index 0000000..93555c8
--- /dev/null
+++ b/libs/sensor/BitTube.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2010 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 <sensor/BitTube.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <binder/Parcel.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+// Socket buffer size. The default is typically about 128KB, which is much larger than
+// we really need. So we make it smaller.
+static const size_t DEFAULT_SOCKET_BUFFER_SIZE = 4 * 1024;
+
+
+BitTube::BitTube()
+ : mSendFd(-1), mReceiveFd(-1)
+{
+ init(DEFAULT_SOCKET_BUFFER_SIZE, DEFAULT_SOCKET_BUFFER_SIZE);
+}
+
+BitTube::BitTube(size_t bufsize)
+ : mSendFd(-1), mReceiveFd(-1)
+{
+ init(bufsize, bufsize);
+}
+
+BitTube::BitTube(const Parcel& data)
+ : mSendFd(-1), mReceiveFd(-1)
+{
+ mReceiveFd = dup(data.readFileDescriptor());
+ if (mReceiveFd < 0) {
+ mReceiveFd = -errno;
+ ALOGE("BitTube(Parcel): can't dup filedescriptor (%s)",
+ strerror(-mReceiveFd));
+ }
+}
+
+BitTube::~BitTube()
+{
+ if (mSendFd >= 0)
+ close(mSendFd);
+
+ if (mReceiveFd >= 0)
+ close(mReceiveFd);
+}
+
+void BitTube::init(size_t rcvbuf, size_t sndbuf) {
+ int sockets[2];
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
+ size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
+ setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
+ setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
+ // sine we don't use the "return channel", we keep it small...
+ setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
+ setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
+ fcntl(sockets[0], F_SETFL, O_NONBLOCK);
+ fcntl(sockets[1], F_SETFL, O_NONBLOCK);
+ mReceiveFd = sockets[0];
+ mSendFd = sockets[1];
+ } else {
+ mReceiveFd = -errno;
+ ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
+ }
+}
+
+status_t BitTube::initCheck() const
+{
+ if (mReceiveFd < 0) {
+ return status_t(mReceiveFd);
+ }
+ return NO_ERROR;
+}
+
+int BitTube::getFd() const
+{
+ return mReceiveFd;
+}
+
+int BitTube::getSendFd() const
+{
+ return mSendFd;
+}
+
+ssize_t BitTube::write(void const* vaddr, size_t size)
+{
+ ssize_t err, len;
+ do {
+ len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
+ // cannot return less than size, since we're using SOCK_SEQPACKET
+ err = len < 0 ? errno : 0;
+ } while (err == EINTR);
+ return err == 0 ? len : -err;
+}
+
+ssize_t BitTube::read(void* vaddr, size_t size)
+{
+ ssize_t err, len;
+ do {
+ len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT);
+ err = len < 0 ? errno : 0;
+ } while (err == EINTR);
+ if (err == EAGAIN || err == EWOULDBLOCK) {
+ // EAGAIN means that we have non-blocking I/O but there was
+ // no data to be read. Nothing the client should care about.
+ return 0;
+ }
+ return err == 0 ? len : -err;
+}
+
+status_t BitTube::writeToParcel(Parcel* reply) const
+{
+ if (mReceiveFd < 0)
+ return -EINVAL;
+
+ status_t result = reply->writeDupFileDescriptor(mReceiveFd);
+ close(mReceiveFd);
+ mReceiveFd = -1;
+ return result;
+}
+
+
+ssize_t BitTube::sendObjects(const sp<BitTube>& tube,
+ void const* events, size_t count, size_t objSize)
+{
+ const char* vaddr = reinterpret_cast<const char*>(events);
+ ssize_t size = tube->write(vaddr, count*objSize);
+
+ // should never happen because of SOCK_SEQPACKET
+ LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
+ "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were sent!)",
+ count, objSize, size);
+
+ //ALOGE_IF(size<0, "error %d sending %d events", size, count);
+ return size < 0 ? size : size / static_cast<ssize_t>(objSize);
+}
+
+ssize_t BitTube::recvObjects(const sp<BitTube>& tube,
+ void* events, size_t count, size_t objSize)
+{
+ char* vaddr = reinterpret_cast<char*>(events);
+ ssize_t size = tube->read(vaddr, count*objSize);
+
+ // should never happen because of SOCK_SEQPACKET
+ LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
+ "BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were received!)",
+ count, objSize, size);
+
+ //ALOGE_IF(size<0, "error %d receiving %d events", size, count);
+ return size < 0 ? size : size / static_cast<ssize_t>(objSize);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/sensor/ISensorEventConnection.cpp b/libs/sensor/ISensorEventConnection.cpp
new file mode 100644
index 0000000..8a3a623
--- /dev/null
+++ b/libs/sensor/ISensorEventConnection.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2010 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 <sensor/ISensorEventConnection.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+#include <binder/Parcel.h>
+#include <binder/IInterface.h>
+
+#include <sensor/BitTube.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+enum {
+ GET_SENSOR_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
+ ENABLE_DISABLE,
+ SET_EVENT_RATE,
+ FLUSH_SENSOR,
+ CONFIGURE_CHANNEL
+};
+
+class BpSensorEventConnection : public BpInterface<ISensorEventConnection>
+{
+public:
+ explicit BpSensorEventConnection(const sp<IBinder>& impl)
+ : BpInterface<ISensorEventConnection>(impl)
+ {
+ }
+
+ virtual ~BpSensorEventConnection();
+
+ virtual sp<BitTube> getSensorChannel() const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
+ remote()->transact(GET_SENSOR_CHANNEL, data, &reply);
+ return new BitTube(reply);
+ }
+
+ virtual status_t enableDisable(int handle, bool enabled, nsecs_t samplingPeriodNs,
+ nsecs_t maxBatchReportLatencyNs, int reservedFlags)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
+ data.writeInt32(handle);
+ data.writeInt32(enabled);
+ data.writeInt64(samplingPeriodNs);
+ data.writeInt64(maxBatchReportLatencyNs);
+ data.writeInt32(reservedFlags);
+ remote()->transact(ENABLE_DISABLE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t setEventRate(int handle, nsecs_t ns)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
+ data.writeInt32(handle);
+ data.writeInt64(ns);
+ remote()->transact(SET_EVENT_RATE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t flush() {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
+ 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
+// translation unit (see clang warning -Wweak-vtables)
+BpSensorEventConnection::~BpSensorEventConnection() {}
+
+IMPLEMENT_META_INTERFACE(SensorEventConnection, "android.gui.SensorEventConnection");
+
+// ----------------------------------------------------------------------------
+
+status_t BnSensorEventConnection::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case GET_SENSOR_CHANNEL: {
+ CHECK_INTERFACE(ISensorEventConnection, data, reply);
+ sp<BitTube> channel(getSensorChannel());
+ channel->writeToParcel(reply);
+ return NO_ERROR;
+ }
+ case ENABLE_DISABLE: {
+ CHECK_INTERFACE(ISensorEventConnection, data, reply);
+ int handle = data.readInt32();
+ int enabled = data.readInt32();
+ nsecs_t samplingPeriodNs = data.readInt64();
+ nsecs_t maxBatchReportLatencyNs = data.readInt64();
+ int reservedFlags = data.readInt32();
+ status_t result = enableDisable(handle, enabled, samplingPeriodNs,
+ maxBatchReportLatencyNs, reservedFlags);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ }
+ case SET_EVENT_RATE: {
+ CHECK_INTERFACE(ISensorEventConnection, data, reply);
+ int handle = data.readInt32();
+ nsecs_t ns = data.readInt64();
+ status_t result = setEventRate(handle, ns);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ }
+ case FLUSH_SENSOR: {
+ CHECK_INTERFACE(ISensorEventConnection, data, reply);
+ status_t result = flush();
+ 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);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/sensor/ISensorServer.cpp b/libs/sensor/ISensorServer.cpp
new file mode 100644
index 0000000..f41f187
--- /dev/null
+++ b/libs/sensor/ISensorServer.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2010 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 <sensor/ISensorServer.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/native_handle.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+#include <utils/Timers.h>
+
+#include <binder/Parcel.h>
+#include <binder/IInterface.h>
+
+#include <sensor/Sensor.h>
+#include <sensor/ISensorEventConnection.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+enum {
+ GET_SENSOR_LIST = IBinder::FIRST_CALL_TRANSACTION,
+ CREATE_SENSOR_EVENT_CONNECTION,
+ ENABLE_DATA_INJECTION,
+ GET_DYNAMIC_SENSOR_LIST,
+ CREATE_SENSOR_DIRECT_CONNECTION,
+};
+
+class BpSensorServer : public BpInterface<ISensorServer>
+{
+public:
+ explicit BpSensorServer(const sp<IBinder>& impl)
+ : BpInterface<ISensorServer>(impl)
+ {
+ }
+
+ virtual ~BpSensorServer();
+
+ virtual Vector<Sensor> getSensorList(const String16& opPackageName)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+ data.writeString16(opPackageName);
+ remote()->transact(GET_SENSOR_LIST, data, &reply);
+ Sensor s;
+ Vector<Sensor> v;
+ uint32_t n = reply.readUint32();
+ v.setCapacity(n);
+ while (n--) {
+ reply.read(s);
+ v.add(s);
+ }
+ return v;
+ }
+
+ virtual Vector<Sensor> getDynamicSensorList(const String16& opPackageName)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+ data.writeString16(opPackageName);
+ remote()->transact(GET_DYNAMIC_SENSOR_LIST, data, &reply);
+ Sensor s;
+ Vector<Sensor> v;
+ uint32_t n = reply.readUint32();
+ v.setCapacity(n);
+ while (n--) {
+ reply.read(s);
+ v.add(s);
+ }
+ return v;
+ }
+
+ virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
+ int mode, const String16& opPackageName)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+ data.writeString8(packageName);
+ data.writeInt32(mode);
+ data.writeString16(opPackageName);
+ remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply);
+ return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
+ }
+
+ virtual int isDataInjectionEnabled() {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+ 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
+// translation unit (see clang warning -Wweak-vtables)
+BpSensorServer::~BpSensorServer() {}
+
+IMPLEMENT_META_INTERFACE(SensorServer, "android.gui.SensorServer");
+
+// ----------------------------------------------------------------------
+
+status_t BnSensorServer::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case GET_SENSOR_LIST: {
+ CHECK_INTERFACE(ISensorServer, data, reply);
+ const String16& opPackageName = data.readString16();
+ Vector<Sensor> v(getSensorList(opPackageName));
+ size_t n = v.size();
+ reply->writeUint32(static_cast<uint32_t>(n));
+ for (size_t i = 0; i < n; i++) {
+ reply->write(v[i]);
+ }
+ return NO_ERROR;
+ }
+ case CREATE_SENSOR_EVENT_CONNECTION: {
+ CHECK_INTERFACE(ISensorServer, data, reply);
+ String8 packageName = data.readString8();
+ int32_t mode = data.readInt32();
+ const String16& opPackageName = data.readString16();
+ sp<ISensorEventConnection> connection(createSensorEventConnection(packageName, mode,
+ opPackageName));
+ reply->writeStrongBinder(IInterface::asBinder(connection));
+ return NO_ERROR;
+ }
+ case ENABLE_DATA_INJECTION: {
+ CHECK_INTERFACE(ISensorServer, data, reply);
+ int32_t ret = isDataInjectionEnabled();
+ reply->writeInt32(static_cast<int32_t>(ret));
+ return NO_ERROR;
+ }
+ case GET_DYNAMIC_SENSOR_LIST: {
+ CHECK_INTERFACE(ISensorServer, data, reply);
+ const String16& opPackageName = data.readString16();
+ Vector<Sensor> v(getDynamicSensorList(opPackageName));
+ size_t n = v.size();
+ reply->writeUint32(static_cast<uint32_t>(n));
+ for (size_t i = 0; i < n; i++) {
+ reply->write(v[i]);
+ }
+ 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);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
new file mode 100644
index 0000000..c2d477e
--- /dev/null
+++ b/libs/sensor/Sensor.cpp
@@ -0,0 +1,578 @@
+/*
+ * Copyright (C) 2010 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 <sensor/Sensor.h>
+
+#include <inttypes.h>
+
+#include <binder/AppOpsManager.h>
+#include <binder/IPermissionController.h>
+#include <binder/IServiceManager.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+Sensor::Sensor(const char * name) :
+ mName(name), mHandle(0), mType(0),
+ mMinValue(0), mMaxValue(0), mResolution(0),
+ mPower(0), mMinDelay(0), mVersion(0), mFifoReservedEventCount(0),
+ mFifoMaxEventCount(0), mRequiredAppOp(0),
+ mMaxDelay(0), mFlags(0) {
+}
+
+Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) :
+ Sensor(*hwSensor, uuid_t(), halVersion) {
+}
+
+Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion) {
+ mName = hwSensor.name;
+ mVendor = hwSensor.vendor;
+ mVersion = hwSensor.version;
+ mHandle = hwSensor.handle;
+ mType = hwSensor.type;
+ mMinValue = 0; // FIXME: minValue
+ mMaxValue = hwSensor.maxRange; // FIXME: maxValue
+ mResolution = hwSensor.resolution;
+ mPower = hwSensor.power;
+ mMinDelay = hwSensor.minDelay;
+ mFlags = 0;
+ mUuid = uuid;
+
+ // Set fifo event count zero for older devices which do not support batching. Fused
+ // sensors also have their fifo counts set to zero.
+ if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) {
+ mFifoReservedEventCount = hwSensor.fifoReservedEventCount;
+ mFifoMaxEventCount = hwSensor.fifoMaxEventCount;
+ } else {
+ mFifoReservedEventCount = 0;
+ mFifoMaxEventCount = 0;
+ }
+
+ if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
+ if (hwSensor.maxDelay > INT_MAX) {
+ // Max delay is declared as a 64 bit integer for 64 bit architectures. But it should
+ // always fit in a 32 bit integer, log error and cap it to INT_MAX.
+ ALOGE("Sensor maxDelay overflow error %s %" PRId64, mName.string(),
+ static_cast<int64_t>(hwSensor.maxDelay));
+ mMaxDelay = INT_MAX;
+ } else {
+ mMaxDelay = static_cast<int32_t>(hwSensor.maxDelay);
+ }
+ } else {
+ // For older hals set maxDelay to 0.
+ mMaxDelay = 0;
+ }
+
+ // Ensure existing sensors have correct string type, required permissions and reporting mode.
+ // Set reportingMode for all android defined sensor types, set wake-up flag only for proximity
+ // sensor, significant motion, tilt, pick_up gesture, wake gesture and glance gesture on older
+ // HALs. Newer HALs can define both wake-up and non wake-up proximity sensors.
+ // All the OEM defined defined sensors have flags set to whatever is provided by the HAL.
+ switch (mType) {
+ case SENSOR_TYPE_ACCELEROMETER:
+ mStringType = SENSOR_STRING_TYPE_ACCELEROMETER;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_AMBIENT_TEMPERATURE:
+ mStringType = SENSOR_STRING_TYPE_AMBIENT_TEMPERATURE;
+ mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
+ break;
+ case SENSOR_TYPE_GAME_ROTATION_VECTOR:
+ mStringType = SENSOR_STRING_TYPE_GAME_ROTATION_VECTOR;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+ mStringType = SENSOR_STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_GRAVITY:
+ mStringType = SENSOR_STRING_TYPE_GRAVITY;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_GYROSCOPE:
+ mStringType = SENSOR_STRING_TYPE_GYROSCOPE;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+ mStringType = SENSOR_STRING_TYPE_GYROSCOPE_UNCALIBRATED;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_HEART_RATE: {
+ mStringType = SENSOR_STRING_TYPE_HEART_RATE;
+ mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS;
+ AppOpsManager appOps;
+ mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS));
+ mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
+ } break;
+ case SENSOR_TYPE_LIGHT:
+ mStringType = SENSOR_STRING_TYPE_LIGHT;
+ mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
+ break;
+ case SENSOR_TYPE_LINEAR_ACCELERATION:
+ mStringType = SENSOR_STRING_TYPE_LINEAR_ACCELERATION;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_MAGNETIC_FIELD:
+ mStringType = SENSOR_STRING_TYPE_MAGNETIC_FIELD;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+ mStringType = SENSOR_STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_ORIENTATION:
+ mStringType = SENSOR_STRING_TYPE_ORIENTATION;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_PRESSURE:
+ mStringType = SENSOR_STRING_TYPE_PRESSURE;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_PROXIMITY:
+ mStringType = SENSOR_STRING_TYPE_PROXIMITY;
+ mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
+ if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
+ mFlags |= SENSOR_FLAG_WAKE_UP;
+ }
+ break;
+ case SENSOR_TYPE_RELATIVE_HUMIDITY:
+ mStringType = SENSOR_STRING_TYPE_RELATIVE_HUMIDITY;
+ mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
+ break;
+ case SENSOR_TYPE_ROTATION_VECTOR:
+ mStringType = SENSOR_STRING_TYPE_ROTATION_VECTOR;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_SIGNIFICANT_MOTION:
+ mStringType = SENSOR_STRING_TYPE_SIGNIFICANT_MOTION;
+ mFlags |= SENSOR_FLAG_ONE_SHOT_MODE;
+ if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
+ mFlags |= SENSOR_FLAG_WAKE_UP;
+ }
+ break;
+ case SENSOR_TYPE_STEP_COUNTER:
+ mStringType = SENSOR_STRING_TYPE_STEP_COUNTER;
+ mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
+ break;
+ case SENSOR_TYPE_STEP_DETECTOR:
+ mStringType = SENSOR_STRING_TYPE_STEP_DETECTOR;
+ mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE;
+ break;
+ case SENSOR_TYPE_TEMPERATURE:
+ mStringType = SENSOR_STRING_TYPE_TEMPERATURE;
+ mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
+ break;
+ case SENSOR_TYPE_TILT_DETECTOR:
+ mStringType = SENSOR_STRING_TYPE_TILT_DETECTOR;
+ mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE;
+ if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
+ mFlags |= SENSOR_FLAG_WAKE_UP;
+ }
+ break;
+ case SENSOR_TYPE_WAKE_GESTURE:
+ mStringType = SENSOR_STRING_TYPE_WAKE_GESTURE;
+ mFlags |= SENSOR_FLAG_ONE_SHOT_MODE;
+ if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
+ mFlags |= SENSOR_FLAG_WAKE_UP;
+ }
+ break;
+ case SENSOR_TYPE_GLANCE_GESTURE:
+ mStringType = SENSOR_STRING_TYPE_GLANCE_GESTURE;
+ mFlags |= SENSOR_FLAG_ONE_SHOT_MODE;
+ if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
+ mFlags |= SENSOR_FLAG_WAKE_UP;
+ }
+ break;
+ case SENSOR_TYPE_PICK_UP_GESTURE:
+ mStringType = SENSOR_STRING_TYPE_PICK_UP_GESTURE;
+ mFlags |= SENSOR_FLAG_ONE_SHOT_MODE;
+ if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
+ mFlags |= SENSOR_FLAG_WAKE_UP;
+ }
+ break;
+ case SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT:
+ mStringType = SENSOR_STRING_TYPE_LOW_LATENCY_OFFBODY_DETECT;
+ mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
+ break;
+ case SENSOR_TYPE_WRIST_TILT_GESTURE:
+ mStringType = SENSOR_STRING_TYPE_WRIST_TILT_GESTURE;
+ mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE;
+ if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
+ mFlags |= SENSOR_FLAG_WAKE_UP;
+ }
+ break;
+ case SENSOR_TYPE_DYNAMIC_SENSOR_META:
+ mStringType = SENSOR_STRING_TYPE_DYNAMIC_SENSOR_META;
+ mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE; // special trigger
+ if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
+ mFlags |= SENSOR_FLAG_WAKE_UP;
+ }
+ break;
+ case SENSOR_TYPE_POSE_6DOF:
+ mStringType = SENSOR_STRING_TYPE_POSE_6DOF;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ case SENSOR_TYPE_STATIONARY_DETECT:
+ mStringType = SENSOR_STRING_TYPE_STATIONARY_DETECT;
+ mFlags |= SENSOR_FLAG_ONE_SHOT_MODE;
+ if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
+ mFlags |= SENSOR_FLAG_WAKE_UP;
+ }
+ break;
+ case SENSOR_TYPE_MOTION_DETECT:
+ mStringType = SENSOR_STRING_TYPE_MOTION_DETECT;
+ mFlags |= SENSOR_FLAG_ONE_SHOT_MODE;
+ if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
+ mFlags |= SENSOR_FLAG_WAKE_UP;
+ }
+ break;
+ case SENSOR_TYPE_HEART_BEAT:
+ mStringType = SENSOR_STRING_TYPE_HEART_BEAT;
+ mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE;
+ break;
+
+ // TODO: Placeholder for LLOB sensor type
+
+
+ case SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED:
+ mStringType = SENSOR_STRING_TYPE_ACCELEROMETER_UNCALIBRATED;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
+ default:
+ // Only pipe the stringType, requiredPermission and flags for custom sensors.
+ if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.stringType) {
+ mStringType = hwSensor.stringType;
+ }
+ if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.requiredPermission) {
+ mRequiredPermission = hwSensor.requiredPermission;
+ if (!strcmp(mRequiredPermission, SENSOR_PERMISSION_BODY_SENSORS)) {
+ AppOpsManager appOps;
+ mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS));
+ }
+ }
+
+ if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
+ mFlags = static_cast<uint32_t>(hwSensor.flags);
+ } else {
+ // This is an OEM defined sensor on an older HAL. Use minDelay to determine the
+ // reporting mode of the sensor.
+ if (mMinDelay > 0) {
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ } else if (mMinDelay == 0) {
+ mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
+ } else if (mMinDelay < 0) {
+ mFlags |= SENSOR_FLAG_ONE_SHOT_MODE;
+ }
+ }
+ break;
+ }
+
+ if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
+ // Wake-up flag of HAL 1.3 and above is set here
+ mFlags |= (hwSensor.flags & SENSOR_FLAG_WAKE_UP);
+
+ // Log error if the reporting mode is not as expected, but respect HAL setting.
+ int actualReportingMode = (hwSensor.flags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
+ int expectedReportingMode = (mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
+ if (actualReportingMode != expectedReportingMode) {
+ ALOGE("Reporting Mode incorrect: sensor %s handle=%#010" PRIx32 " type=%" PRId32 " "
+ "actual=%d expected=%d",
+ mName.string(), mHandle, mType, actualReportingMode, expectedReportingMode);
+ }
+ }
+
+ // 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);
+ }
+ // 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) {
+ mFlags |= (hwSensor.flags & DATA_INJECTION_MASK);
+ }
+
+ if (mRequiredPermission.length() > 0) {
+ // If the sensor is protected by a permission we need to know if it is
+ // a runtime one to determine whether we can use the permission cache.
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
+ if (binder != 0) {
+ sp<IPermissionController> permCtrl = interface_cast<IPermissionController>(binder);
+ mRequiredPermissionRuntime = permCtrl->isRuntimePermission(
+ String16(mRequiredPermission));
+ }
+ }
+}
+
+Sensor::~Sensor() {
+}
+
+const String8& Sensor::getName() const {
+ return mName;
+}
+
+const String8& Sensor::getVendor() const {
+ return mVendor;
+}
+
+int32_t Sensor::getHandle() const {
+ return mHandle;
+}
+
+int32_t Sensor::getType() const {
+ return mType;
+}
+
+float Sensor::getMinValue() const {
+ return mMinValue;
+}
+
+float Sensor::getMaxValue() const {
+ return mMaxValue;
+}
+
+float Sensor::getResolution() const {
+ return mResolution;
+}
+
+float Sensor::getPowerUsage() const {
+ return mPower;
+}
+
+int32_t Sensor::getMinDelay() const {
+ return mMinDelay;
+}
+
+nsecs_t Sensor::getMinDelayNs() const {
+ return getMinDelay() * 1000;
+}
+
+int32_t Sensor::getVersion() const {
+ return mVersion;
+}
+
+uint32_t Sensor::getFifoReservedEventCount() const {
+ return mFifoReservedEventCount;
+}
+
+uint32_t Sensor::getFifoMaxEventCount() const {
+ return mFifoMaxEventCount;
+}
+
+const String8& Sensor::getStringType() const {
+ return mStringType;
+}
+
+const String8& Sensor::getRequiredPermission() const {
+ return mRequiredPermission;
+}
+
+bool Sensor::isRequiredPermissionRuntime() const {
+ return mRequiredPermissionRuntime;
+}
+
+int32_t Sensor::getRequiredAppOp() const {
+ return mRequiredAppOp;
+}
+
+int32_t Sensor::getMaxDelay() const {
+ return mMaxDelay;
+}
+
+uint32_t Sensor::getFlags() const {
+ return mFlags;
+}
+
+bool Sensor::isWakeUpSensor() const {
+ return (mFlags & SENSOR_FLAG_WAKE_UP) != 0;
+}
+
+bool Sensor::isDynamicSensor() const {
+ return (mFlags & SENSOR_FLAG_DYNAMIC_SENSOR) != 0;
+}
+
+bool Sensor::hasAdditionalInfo() const {
+ 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);
+}
+
+const Sensor::uuid_t& Sensor::getUuid() const {
+ return mUuid;
+}
+
+void Sensor::setId(int32_t id) {
+ mUuid.i64[0] = id;
+ mUuid.i64[1] = 0;
+}
+
+int32_t Sensor::getId() const {
+ return int32_t(mUuid.i64[0]);
+}
+
+size_t Sensor::getFlattenedSize() const {
+ size_t fixedSize =
+ sizeof(mVersion) + sizeof(mHandle) + sizeof(mType) +
+ sizeof(mMinValue) + sizeof(mMaxValue) + sizeof(mResolution) +
+ sizeof(mPower) + sizeof(mMinDelay) + sizeof(mFifoMaxEventCount) +
+ sizeof(mFifoMaxEventCount) + sizeof(mRequiredPermissionRuntime) +
+ sizeof(mRequiredAppOp) + sizeof(mMaxDelay) + sizeof(mFlags) + sizeof(mUuid);
+
+ size_t variableSize =
+ sizeof(uint32_t) + FlattenableUtils::align<4>(mName.length()) +
+ sizeof(uint32_t) + FlattenableUtils::align<4>(mVendor.length()) +
+ sizeof(uint32_t) + FlattenableUtils::align<4>(mStringType.length()) +
+ sizeof(uint32_t) + FlattenableUtils::align<4>(mRequiredPermission.length());
+
+ return fixedSize + variableSize;
+}
+
+status_t Sensor::flatten(void* buffer, size_t size) const {
+ if (size < getFlattenedSize()) {
+ return NO_MEMORY;
+ }
+
+ flattenString8(buffer, size, mName);
+ flattenString8(buffer, size, mVendor);
+ FlattenableUtils::write(buffer, size, mVersion);
+ FlattenableUtils::write(buffer, size, mHandle);
+ FlattenableUtils::write(buffer, size, mType);
+ FlattenableUtils::write(buffer, size, mMinValue);
+ FlattenableUtils::write(buffer, size, mMaxValue);
+ FlattenableUtils::write(buffer, size, mResolution);
+ FlattenableUtils::write(buffer, size, mPower);
+ FlattenableUtils::write(buffer, size, mMinDelay);
+ FlattenableUtils::write(buffer, size, mFifoReservedEventCount);
+ FlattenableUtils::write(buffer, size, mFifoMaxEventCount);
+ flattenString8(buffer, size, mStringType);
+ flattenString8(buffer, size, mRequiredPermission);
+ FlattenableUtils::write(buffer, size, mRequiredPermissionRuntime);
+ FlattenableUtils::write(buffer, size, mRequiredAppOp);
+ FlattenableUtils::write(buffer, size, mMaxDelay);
+ FlattenableUtils::write(buffer, size, mFlags);
+ if (mUuid.i64[1] != 0) {
+ // We should never hit this case with our current API, but we
+ // could via a careless API change. If that happens,
+ // this code will keep us from leaking our UUID (while probably
+ // breaking dynamic sensors). See b/29547335.
+ ALOGW("Sensor with UUID being flattened; sending 0. Expect "
+ "bad dynamic sensor behavior");
+ uuid_t tmpUuid; // default constructor makes this 0.
+ FlattenableUtils::write(buffer, size, tmpUuid);
+ } else {
+ FlattenableUtils::write(buffer, size, mUuid);
+ }
+ return NO_ERROR;
+}
+
+status_t Sensor::unflatten(void const* buffer, size_t size) {
+ if (!unflattenString8(buffer, size, mName)) {
+ return NO_MEMORY;
+ }
+ if (!unflattenString8(buffer, size, mVendor)) {
+ return NO_MEMORY;
+ }
+
+ size_t fixedSize1 =
+ sizeof(mVersion) + sizeof(mHandle) + sizeof(mType) + sizeof(mMinValue) +
+ sizeof(mMaxValue) + sizeof(mResolution) + sizeof(mPower) + sizeof(mMinDelay) +
+ sizeof(mFifoMaxEventCount) + sizeof(mFifoMaxEventCount);
+ if (size < fixedSize1) {
+ return NO_MEMORY;
+ }
+
+ FlattenableUtils::read(buffer, size, mVersion);
+ FlattenableUtils::read(buffer, size, mHandle);
+ FlattenableUtils::read(buffer, size, mType);
+ FlattenableUtils::read(buffer, size, mMinValue);
+ FlattenableUtils::read(buffer, size, mMaxValue);
+ FlattenableUtils::read(buffer, size, mResolution);
+ FlattenableUtils::read(buffer, size, mPower);
+ FlattenableUtils::read(buffer, size, mMinDelay);
+ FlattenableUtils::read(buffer, size, mFifoReservedEventCount);
+ FlattenableUtils::read(buffer, size, mFifoMaxEventCount);
+
+ if (!unflattenString8(buffer, size, mStringType)) {
+ return NO_MEMORY;
+ }
+ if (!unflattenString8(buffer, size, mRequiredPermission)) {
+ return NO_MEMORY;
+ }
+
+ size_t fixedSize2 =
+ sizeof(mRequiredPermissionRuntime) + sizeof(mRequiredAppOp) + sizeof(mMaxDelay) +
+ sizeof(mFlags) + sizeof(mUuid);
+ if (size < fixedSize2) {
+ return NO_MEMORY;
+ }
+
+ FlattenableUtils::read(buffer, size, mRequiredPermissionRuntime);
+ FlattenableUtils::read(buffer, size, mRequiredAppOp);
+ FlattenableUtils::read(buffer, size, mMaxDelay);
+ FlattenableUtils::read(buffer, size, mFlags);
+ FlattenableUtils::read(buffer, size, mUuid);
+ return NO_ERROR;
+}
+
+void Sensor::flattenString8(void*& buffer, size_t& size,
+ const String8& string8) {
+ uint32_t len = static_cast<uint32_t>(string8.length());
+ FlattenableUtils::write(buffer, size, len);
+ memcpy(static_cast<char*>(buffer), string8.string(), len);
+ FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len));
+}
+
+bool Sensor::unflattenString8(void const*& buffer, size_t& size, String8& outputString8) {
+ uint32_t len;
+ if (size < sizeof(len)) {
+ return false;
+ }
+ FlattenableUtils::read(buffer, size, len);
+ if (size < len) {
+ return false;
+ }
+ outputString8.setTo(static_cast<char const*>(buffer), len);
+ FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len));
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/sensor/SensorEventQueue.cpp b/libs/sensor/SensorEventQueue.cpp
new file mode 100644
index 0000000..8ba3ebe
--- /dev/null
+++ b/libs/sensor/SensorEventQueue.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#define LOG_TAG "Sensors"
+
+#include <sensor/SensorEventQueue.h>
+
+#include <algorithm>
+#include <sys/socket.h>
+
+#include <utils/RefBase.h>
+#include <utils/Looper.h>
+
+#include <sensor/Sensor.h>
+#include <sensor/BitTube.h>
+#include <sensor/ISensorEventConnection.h>
+
+#include <android/sensor.h>
+
+using std::min;
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+SensorEventQueue::SensorEventQueue(const sp<ISensorEventConnection>& connection)
+ : mSensorEventConnection(connection), mRecBuffer(NULL), mAvailable(0), mConsumed(0),
+ mNumAcksToSend(0) {
+ mRecBuffer = new ASensorEvent[MAX_RECEIVE_BUFFER_EVENT_COUNT];
+}
+
+SensorEventQueue::~SensorEventQueue() {
+ delete [] mRecBuffer;
+}
+
+void SensorEventQueue::onFirstRef()
+{
+ mSensorChannel = mSensorEventConnection->getSensorChannel();
+}
+
+int SensorEventQueue::getFd() const
+{
+ return mSensorChannel->getFd();
+}
+
+
+ssize_t SensorEventQueue::write(const sp<BitTube>& tube,
+ ASensorEvent const* events, size_t numEvents) {
+ return BitTube::sendObjects(tube, events, numEvents);
+}
+
+ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) {
+ if (mAvailable == 0) {
+ ssize_t err = BitTube::recvObjects(mSensorChannel,
+ mRecBuffer, MAX_RECEIVE_BUFFER_EVENT_COUNT);
+ if (err < 0) {
+ return err;
+ }
+ mAvailable = static_cast<size_t>(err);
+ mConsumed = 0;
+ }
+ size_t count = min(numEvents, mAvailable);
+ memcpy(events, mRecBuffer + mConsumed, count * sizeof(ASensorEvent));
+ mAvailable -= count;
+ mConsumed += count;
+ return static_cast<ssize_t>(count);
+}
+
+sp<Looper> SensorEventQueue::getLooper() const
+{
+ Mutex::Autolock _l(mLock);
+ if (mLooper == 0) {
+ mLooper = new Looper(true);
+ mLooper->addFd(getFd(), getFd(), ALOOPER_EVENT_INPUT, NULL, NULL);
+ }
+ return mLooper;
+}
+
+status_t SensorEventQueue::waitForEvent() const
+{
+ const int fd = getFd();
+ sp<Looper> looper(getLooper());
+
+ int events;
+ int32_t result;
+ do {
+ result = looper->pollOnce(-1, NULL, &events, NULL);
+ if (result == ALOOPER_POLL_ERROR) {
+ ALOGE("SensorEventQueue::waitForEvent error (errno=%d)", errno);
+ result = -EPIPE; // unknown error, so we make up one
+ break;
+ }
+ if (events & ALOOPER_EVENT_HANGUP) {
+ // the other-side has died
+ ALOGE("SensorEventQueue::waitForEvent error HANGUP");
+ result = -EPIPE; // unknown error, so we make up one
+ break;
+ }
+ } while (result != fd);
+
+ return (result == fd) ? status_t(NO_ERROR) : result;
+}
+
+status_t SensorEventQueue::wake() const
+{
+ sp<Looper> looper(getLooper());
+ looper->wake();
+ return NO_ERROR;
+}
+
+status_t SensorEventQueue::enableSensor(Sensor const* sensor) const {
+ return enableSensor(sensor, SENSOR_DELAY_NORMAL);
+}
+
+status_t SensorEventQueue::enableSensor(Sensor const* sensor, int32_t samplingPeriodUs) const {
+ return mSensorEventConnection->enableDisable(sensor->getHandle(), true,
+ us2ns(samplingPeriodUs), 0, 0);
+}
+
+status_t SensorEventQueue::disableSensor(Sensor const* sensor) const {
+ return mSensorEventConnection->enableDisable(sensor->getHandle(), false, 0, 0, 0);
+}
+
+status_t SensorEventQueue::enableSensor(int32_t handle, int32_t samplingPeriodUs,
+ int maxBatchReportLatencyUs, int reservedFlags) const {
+ return mSensorEventConnection->enableDisable(handle, true, us2ns(samplingPeriodUs),
+ us2ns(maxBatchReportLatencyUs), reservedFlags);
+}
+
+status_t SensorEventQueue::flush() const {
+ return mSensorEventConnection->flush();
+}
+
+status_t SensorEventQueue::disableSensor(int32_t handle) const {
+ return mSensorEventConnection->enableDisable(handle, false, 0, 0, false);
+}
+
+status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const {
+ return mSensorEventConnection->setEventRate(sensor->getHandle(), ns);
+}
+
+status_t SensorEventQueue::injectSensorEvent(const ASensorEvent& event) {
+ do {
+ // Blocking call.
+ ssize_t size = ::send(mSensorChannel->getFd(), &event, sizeof(event), MSG_NOSIGNAL);
+ if (size >= 0) {
+ return NO_ERROR;
+ } else if (size < 0 && errno == EAGAIN) {
+ // If send is returning a "Try again" error, sleep for 100ms and try again. In all
+ // other cases log a failure and exit.
+ usleep(100000);
+ } else {
+ ALOGE("injectSensorEvent failure %s %zd", strerror(errno), size);
+ return INVALID_OPERATION;
+ }
+ } while (true);
+}
+
+void SensorEventQueue::sendAck(const ASensorEvent* events, int count) {
+ for (int i = 0; i < count; ++i) {
+ if (events[i].flags & WAKE_UP_SENSOR_EVENT_NEEDS_ACK) {
+ ++mNumAcksToSend;
+ }
+ }
+ // Send mNumAcksToSend to acknowledge for the wake up sensor events received.
+ if (mNumAcksToSend > 0) {
+ ssize_t size = ::send(mSensorChannel->getFd(), &mNumAcksToSend, sizeof(mNumAcksToSend),
+ MSG_DONTWAIT | MSG_NOSIGNAL);
+ if (size < 0) {
+ ALOGE("sendAck failure %zd %d", size, mNumAcksToSend);
+ } else {
+ mNumAcksToSend = 0;
+ }
+ }
+ return;
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
new file mode 100644
index 0000000..b6e9fa1
--- /dev/null
+++ b/libs/sensor/SensorManager.cpp
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#define LOG_TAG "Sensors"
+
+#include <sensor/SensorManager.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/native_handle.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Singleton.h>
+
+#include <binder/IBinder.h>
+#include <binder/IServiceManager.h>
+
+#include <sensor/ISensorServer.h>
+#include <sensor/ISensorEventConnection.h>
+#include <sensor/Sensor.h>
+#include <sensor/SensorEventQueue.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+android::Mutex android::SensorManager::sLock;
+std::map<String16, SensorManager*> android::SensorManager::sPackageInstances;
+
+SensorManager& SensorManager::getInstanceForPackage(const String16& packageName) {
+ Mutex::Autolock _l(sLock);
+ SensorManager* sensorManager;
+ std::map<String16, SensorManager*>::iterator iterator =
+ sPackageInstances.find(packageName);
+
+ if (iterator != sPackageInstances.end()) {
+ sensorManager = iterator->second;
+ } else {
+ String16 opPackageName = packageName;
+
+ // It is possible that the calling code has no access to the package name.
+ // In this case we will get the packages for the calling UID and pick the
+ // first one for attributing the app op. This will work correctly for
+ // runtime permissions as for legacy apps we will toggle the app op for
+ // all packages in the UID. The caveat is that the operation may be attributed
+ // to the wrong package and stats based on app ops may be slightly off.
+ if (opPackageName.size() <= 0) {
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
+ if (binder != 0) {
+ const uid_t uid = IPCThreadState::self()->getCallingUid();
+ Vector<String16> packages;
+ interface_cast<IPermissionController>(binder)->getPackagesForUid(uid, packages);
+ if (!packages.isEmpty()) {
+ opPackageName = packages[0];
+ } else {
+ ALOGE("No packages for calling UID");
+ }
+ } else {
+ ALOGE("Cannot get permission service");
+ }
+ }
+
+ sensorManager = new SensorManager(opPackageName);
+
+ // If we had no package name, we looked it up from the UID and the sensor
+ // manager instance we created should also be mapped to the empty package
+ // name, to avoid looking up the packages for a UID and get the same result.
+ if (packageName.size() <= 0) {
+ sPackageInstances.insert(std::make_pair(String16(), sensorManager));
+ }
+
+ // Stash the per package sensor manager.
+ sPackageInstances.insert(std::make_pair(opPackageName, sensorManager));
+ }
+
+ return *sensorManager;
+}
+
+SensorManager::SensorManager(const String16& opPackageName)
+ : mSensorList(0), mOpPackageName(opPackageName), mDirectConnectionHandle(1) {
+ // okay we're not locked here, but it's not needed during construction
+ assertStateLocked();
+}
+
+SensorManager::~SensorManager() {
+ free(mSensorList);
+}
+
+void SensorManager::sensorManagerDied() {
+ Mutex::Autolock _l(mLock);
+ mSensorServer.clear();
+ free(mSensorList);
+ mSensorList = NULL;
+ mSensors.clear();
+}
+
+status_t SensorManager::assertStateLocked() {
+ bool initSensorManager = false;
+ if (mSensorServer == NULL) {
+ initSensorManager = true;
+ } else {
+ // Ping binder to check if sensorservice is alive.
+ status_t err = IInterface::asBinder(mSensorServer)->pingBinder();
+ if (err != NO_ERROR) {
+ initSensorManager = true;
+ }
+ }
+ if (initSensorManager) {
+ // try for 300 seconds (60*5(getService() tries for 5 seconds)) before giving up ...
+ const String16 name("sensorservice");
+ for (int i = 0; i < 60; i++) {
+ status_t err = getService(name, &mSensorServer);
+ if (err == NAME_NOT_FOUND) {
+ sleep(1);
+ continue;
+ }
+ if (err != NO_ERROR) {
+ return err;
+ }
+ break;
+ }
+
+ class DeathObserver : public IBinder::DeathRecipient {
+ SensorManager& mSensorManager;
+ virtual void binderDied(const wp<IBinder>& who) {
+ ALOGW("sensorservice died [%p]", who.unsafe_get());
+ mSensorManager.sensorManagerDied();
+ }
+ public:
+ explicit DeathObserver(SensorManager& mgr) : mSensorManager(mgr) { }
+ };
+
+ LOG_ALWAYS_FATAL_IF(mSensorServer.get() == NULL, "getService(SensorService) NULL");
+
+ mDeathObserver = new DeathObserver(*const_cast<SensorManager *>(this));
+ IInterface::asBinder(mSensorServer)->linkToDeath(mDeathObserver);
+
+ mSensors = mSensorServer->getSensorList(mOpPackageName);
+ size_t count = mSensors.size();
+ mSensorList =
+ static_cast<Sensor const**>(malloc(count * sizeof(Sensor*)));
+ LOG_ALWAYS_FATAL_IF(mSensorList == NULL, "mSensorList NULL");
+
+ for (size_t i=0 ; i<count ; i++) {
+ mSensorList[i] = mSensors.array() + i;
+ }
+ }
+
+ return NO_ERROR;
+}
+
+ssize_t SensorManager::getSensorList(Sensor const* const** list) {
+ Mutex::Autolock _l(mLock);
+ status_t err = assertStateLocked();
+ if (err < 0) {
+ return static_cast<ssize_t>(err);
+ }
+ *list = mSensorList;
+ return static_cast<ssize_t>(mSensors.size());
+}
+
+ssize_t SensorManager::getDynamicSensorList(Vector<Sensor> & dynamicSensors) {
+ Mutex::Autolock _l(mLock);
+ status_t err = assertStateLocked();
+ if (err < 0) {
+ return static_cast<ssize_t>(err);
+ }
+
+ dynamicSensors = mSensorServer->getDynamicSensorList(mOpPackageName);
+ size_t count = dynamicSensors.size();
+
+ return static_cast<ssize_t>(count);
+}
+
+Sensor const* SensorManager::getDefaultSensor(int type)
+{
+ Mutex::Autolock _l(mLock);
+ if (assertStateLocked() == NO_ERROR) {
+ bool wakeUpSensor = false;
+ // For the following sensor types, return a wake-up sensor. These types are by default
+ // defined as wake-up sensors. For the rest of the sensor types defined in sensors.h return
+ // a non_wake-up version.
+ if (type == SENSOR_TYPE_PROXIMITY || type == SENSOR_TYPE_SIGNIFICANT_MOTION ||
+ type == SENSOR_TYPE_TILT_DETECTOR || type == SENSOR_TYPE_WAKE_GESTURE ||
+ type == SENSOR_TYPE_GLANCE_GESTURE || type == SENSOR_TYPE_PICK_UP_GESTURE ||
+ type == SENSOR_TYPE_WRIST_TILT_GESTURE ||
+ type == SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT) {
+ wakeUpSensor = true;
+ }
+ // For now we just return the first sensor of that type we find.
+ // in the future it will make sense to let the SensorService make
+ // that decision.
+ for (size_t i=0 ; i<mSensors.size() ; i++) {
+ if (mSensorList[i]->getType() == type &&
+ mSensorList[i]->isWakeUpSensor() == wakeUpSensor) {
+ return mSensorList[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName, int mode) {
+ sp<SensorEventQueue> queue;
+
+ Mutex::Autolock _l(mLock);
+ while (assertStateLocked() == NO_ERROR) {
+ sp<ISensorEventConnection> connection =
+ mSensorServer->createSensorEventConnection(packageName, mode, mOpPackageName);
+ if (connection == NULL) {
+ // SensorService just died or the app doesn't have required permissions.
+ ALOGE("createEventQueue: connection is NULL.");
+ return NULL;
+ }
+ queue = new SensorEventQueue(connection);
+ break;
+ }
+ return queue;
+}
+
+bool SensorManager::isDataInjectionEnabled() {
+ Mutex::Autolock _l(mLock);
+ if (assertStateLocked() == NO_ERROR) {
+ return mSensorServer->isDataInjectionEnabled();
+ }
+ 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/libs/sensor/include/sensor/BitTube.h b/libs/sensor/include/sensor/BitTube.h
new file mode 100644
index 0000000..c1fabe8
--- /dev/null
+++ b/libs/sensor/include/sensor/BitTube.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+class Parcel;
+
+class BitTube : public RefBase
+{
+public:
+
+ // creates a BitTube with a default (4KB) send buffer
+ BitTube();
+
+ // creates a BitTube with a a specified send and receive buffer size
+ explicit BitTube(size_t bufsize);
+
+ explicit BitTube(const Parcel& data);
+ virtual ~BitTube();
+
+ // check state after construction
+ status_t initCheck() const;
+
+ // get receive file-descriptor
+ int getFd() const;
+
+ // get the send file-descriptor.
+ int getSendFd() const;
+
+ // send objects (sized blobs). All objects are guaranteed to be written or the call fails.
+ template <typename T>
+ static ssize_t sendObjects(const sp<BitTube>& tube,
+ T const* events, size_t count) {
+ return sendObjects(tube, events, count, sizeof(T));
+ }
+
+ // receive objects (sized blobs). If the receiving buffer isn't large enough,
+ // excess messages are silently discarded.
+ template <typename T>
+ static ssize_t recvObjects(const sp<BitTube>& tube,
+ T* events, size_t count) {
+ return recvObjects(tube, events, count, sizeof(T));
+ }
+
+ // parcels this BitTube
+ status_t writeToParcel(Parcel* reply) const;
+
+private:
+ void init(size_t rcvbuf, size_t sndbuf);
+
+ // send a message. The write is guaranteed to send the whole message or fail.
+ ssize_t write(void const* vaddr, size_t size);
+
+ // receive a message. the passed buffer must be at least as large as the
+ // write call used to send the message, excess data is silently discarded.
+ ssize_t read(void* vaddr, size_t size);
+
+ int mSendFd;
+ mutable int mReceiveFd;
+
+ static ssize_t sendObjects(const sp<BitTube>& tube,
+ void const* events, size_t count, size_t objSize);
+
+ static ssize_t recvObjects(const sp<BitTube>& tube,
+ void* events, size_t count, size_t objSize);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/sensor/include/sensor/ISensorEventConnection.h b/libs/sensor/include/sensor/ISensorEventConnection.h
new file mode 100644
index 0000000..07cc7e8
--- /dev/null
+++ b/libs/sensor/include/sensor/ISensorEventConnection.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+#include <utils/Timers.h>
+
+#include <binder/IInterface.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class BitTube;
+class Parcel;
+
+class ISensorEventConnection : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(SensorEventConnection)
+
+ virtual sp<BitTube> getSensorChannel() const = 0;
+ virtual status_t enableDisable(int handle, bool enabled, nsecs_t samplingPeriodNs,
+ 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;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnSensorEventConnection : public BnInterface<ISensorEventConnection>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/sensor/include/sensor/ISensorServer.h b/libs/sensor/include/sensor/ISensorServer.h
new file mode 100644
index 0000000..f922307
--- /dev/null
+++ b/libs/sensor/include/sensor/ISensorServer.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+#include <utils/Vector.h>
+
+#include <binder/IInterface.h>
+
+struct native_handle;
+typedef struct native_handle native_handle_t;
+namespace android {
+// ----------------------------------------------------------------------------
+
+class ISensorEventConnection;
+class Parcel;
+class Sensor;
+class String8;
+class String16;
+
+class ISensorServer : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(SensorServer)
+
+ virtual Vector<Sensor> getSensorList(const String16& opPackageName) = 0;
+ virtual Vector<Sensor> getDynamicSensorList(const String16& opPackageName) = 0;
+
+ 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;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnSensorServer : public BnInterface<ISensorServer>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/sensor/include/sensor/Sensor.h b/libs/sensor/include/sensor/Sensor.h
new file mode 100644
index 0000000..043e635
--- /dev/null
+++ b/libs/sensor/include/sensor/Sensor.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/Flattenable.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+
+// FIXME: including from android/ breaks layering, as libandroid ultimately depends on libsensors
+#include <android/sensor.h>
+
+#include <hardware/sensors.h>
+
+// ----------------------------------------------------------------------------
+// Concrete types for the NDK
+struct ASensor { };
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class Parcel;
+
+// ----------------------------------------------------------------------------
+
+class Sensor : public ASensor, public LightFlattenable<Sensor>
+{
+public:
+ enum {
+ TYPE_ACCELEROMETER = ASENSOR_TYPE_ACCELEROMETER,
+ TYPE_MAGNETIC_FIELD = ASENSOR_TYPE_MAGNETIC_FIELD,
+ TYPE_GYROSCOPE = ASENSOR_TYPE_GYROSCOPE,
+ TYPE_LIGHT = ASENSOR_TYPE_LIGHT,
+ TYPE_PROXIMITY = ASENSOR_TYPE_PROXIMITY
+ };
+
+ struct uuid_t{
+ union {
+ uint8_t b[16];
+ int64_t i64[2];
+ };
+ uuid_t(const uint8_t (&uuid)[16]) { memcpy(b, uuid, sizeof(b));}
+ uuid_t() : b{0} {}
+ };
+
+ Sensor(const Sensor&) = default;
+ Sensor& operator=(const Sensor&) = default;
+
+ Sensor(const char * name = "");
+ Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
+ Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion = 0);
+ ~Sensor();
+
+ const String8& getName() const;
+ const String8& getVendor() const;
+ int32_t getHandle() const;
+ int32_t getType() const;
+ float getMinValue() const;
+ float getMaxValue() const;
+ float getResolution() const;
+ float getPowerUsage() const;
+ int32_t getMinDelay() const;
+ nsecs_t getMinDelayNs() const;
+ int32_t getVersion() const;
+ uint32_t getFifoReservedEventCount() const;
+ uint32_t getFifoMaxEventCount() const;
+ const String8& getStringType() const;
+ const String8& getRequiredPermission() const;
+ bool isRequiredPermissionRuntime() const;
+ int32_t getRequiredAppOp() const;
+ int32_t getMaxDelay() const;
+ uint32_t getFlags() const;
+ 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
+ // returns the UUID.
+ // TODO(b/29547335): Remove getUuid(), add getUuidIndex(), and
+ // make sure setId() doesn't change the UuidIndex.
+ const uuid_t& getUuid() const;
+ int32_t getId() const;
+ void setId(int32_t id);
+
+ // LightFlattenable protocol
+ inline bool isFixedSize() const { return false; }
+ size_t getFlattenedSize() const;
+ status_t flatten(void* buffer, size_t size) const;
+ status_t unflatten(void const* buffer, size_t size);
+
+private:
+ String8 mName;
+ String8 mVendor;
+ int32_t mHandle;
+ int32_t mType;
+ float mMinValue;
+ float mMaxValue;
+ float mResolution;
+ float mPower;
+ int32_t mMinDelay;
+ int32_t mVersion;
+ uint32_t mFifoReservedEventCount;
+ uint32_t mFifoMaxEventCount;
+ String8 mStringType;
+ String8 mRequiredPermission;
+ bool mRequiredPermissionRuntime = false;
+ int32_t mRequiredAppOp;
+ int32_t mMaxDelay;
+ uint32_t mFlags;
+ // TODO(b/29547335): Get rid of this field and replace with an index.
+ // The index will be into a separate global vector of UUIDs.
+ // Also add an mId field (and change flatten/unflatten appropriately).
+ uuid_t mUuid;
+ static void flattenString8(void*& buffer, size_t& size, const String8& string8);
+ static bool unflattenString8(void const*& buffer, size_t& size, String8& outputString8);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/sensor/include/sensor/SensorEventQueue.h b/libs/sensor/include/sensor/SensorEventQueue.h
new file mode 100644
index 0000000..84b6ab2
--- /dev/null
+++ b/libs/sensor/include/sensor/SensorEventQueue.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/Mutex.h>
+
+#include <sensor/BitTube.h>
+
+// ----------------------------------------------------------------------------
+#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1U << 31)
+struct ALooper;
+struct ASensorEvent;
+
+// Concrete types for the NDK
+struct ASensorEventQueue {
+ ALooper* looper;
+};
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class ISensorEventConnection;
+class Sensor;
+class Looper;
+
+// ----------------------------------------------------------------------------
+
+class SensorEventQueue : public ASensorEventQueue, public RefBase
+{
+public:
+
+ enum { MAX_RECEIVE_BUFFER_EVENT_COUNT = 256 };
+
+ /**
+ * Typical sensor delay (sample period) in microseconds.
+ */
+ // Fastest sampling, system will bound it to minDelay
+ static constexpr int32_t SENSOR_DELAY_FASTEST = 0;
+ // Typical sample period for game, 50Hz;
+ static constexpr int32_t SENSOR_DELAY_GAME = 20000;
+ // Typical sample period for UI, 15Hz
+ static constexpr int32_t SENSOR_DELAY_UI = 66667;
+ // Default sensor sample period
+ static constexpr int32_t SENSOR_DELAY_NORMAL = 200000;
+
+ SensorEventQueue(const sp<ISensorEventConnection>& connection);
+ virtual ~SensorEventQueue();
+ virtual void onFirstRef();
+
+ int getFd() const;
+
+ static ssize_t write(const sp<BitTube>& tube,
+ ASensorEvent const* events, size_t numEvents);
+
+ ssize_t read(ASensorEvent* events, size_t numEvents);
+
+ status_t waitForEvent() const;
+ status_t wake() const;
+
+ status_t enableSensor(Sensor const* sensor) const;
+ status_t enableSensor(Sensor const* sensor, int32_t samplingPeriodUs) const;
+ status_t disableSensor(Sensor const* sensor) const;
+ status_t setEventRate(Sensor const* sensor, nsecs_t ns) const;
+
+ // these are here only to support SensorManager.java
+ status_t enableSensor(int32_t handle, int32_t samplingPeriodUs, int maxBatchReportLatencyUs,
+ int reservedFlags) const;
+ status_t disableSensor(int32_t handle) const;
+ status_t flush() const;
+ // Send an ack for every wake_up sensor event that is set to WAKE_UP_SENSOR_EVENT_NEEDS_ACK.
+ void sendAck(const ASensorEvent* events, int count);
+
+ status_t injectSensorEvent(const ASensorEvent& event);
+private:
+ sp<Looper> getLooper() const;
+ sp<ISensorEventConnection> mSensorEventConnection;
+ sp<BitTube> mSensorChannel;
+ mutable Mutex mLock;
+ mutable sp<Looper> mLooper;
+ ASensorEvent* mRecBuffer;
+ size_t mAvailable;
+ size_t mConsumed;
+ uint32_t mNumAcksToSend;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/sensor/include/sensor/SensorManager.h b/libs/sensor/include/sensor/SensorManager.h
new file mode 100644
index 0000000..a3d9741
--- /dev/null
+++ b/libs/sensor/include/sensor/SensorManager.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010 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_GUI_SENSOR_MANAGER_H
+#define ANDROID_GUI_SENSOR_MANAGER_H
+
+#include <map>
+#include <unordered_map>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+#include <utils/Vector.h>
+#include <utils/String8.h>
+
+#include <sensor/SensorEventQueue.h>
+
+// ----------------------------------------------------------------------------
+// Concrete types for the NDK
+struct ASensorManager { };
+
+struct native_handle;
+typedef struct native_handle native_handle_t;
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class ISensorServer;
+class Sensor;
+class SensorEventQueue;
+// ----------------------------------------------------------------------------
+
+class SensorManager : public ASensorManager
+{
+public:
+ static SensorManager& getInstanceForPackage(const String16& packageName);
+ ~SensorManager();
+
+ ssize_t getSensorList(Sensor const* const** list);
+ ssize_t getDynamicSensorList(Vector<Sensor>& list);
+ 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
+ void sensorManagerDied();
+
+ SensorManager(const String16& opPackageName);
+ status_t assertStateLocked();
+
+private:
+ static Mutex sLock;
+ static std::map<String16, SensorManager*> sPackageInstances;
+
+ Mutex mLock;
+ sp<ISensorServer> mSensorServer;
+ Sensor const** mSensorList;
+ Vector<Sensor> mSensors;
+ sp<IBinder::DeathRecipient> mDeathObserver;
+ const String16 mOpPackageName;
+ std::unordered_map<int, sp<ISensorEventConnection>> mDirectConnection;
+ int32_t mDirectConnectionHandle;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_SENSOR_MANAGER_H
diff --git a/libs/sensor/tests/Android.bp b/libs/sensor/tests/Android.bp
new file mode 100644
index 0000000..9d530fc
--- /dev/null
+++ b/libs/sensor/tests/Android.bp
@@ -0,0 +1,29 @@
+// Copyright 2017 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.
+
+cc_test {
+ name: "libsensor_test",
+
+ clang: true,
+
+ srcs: [
+ "Sensor_test.cpp",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libsensor",
+ "libutils",
+ ],
+}
diff --git a/libs/sensor/tests/Sensor_test.cpp b/libs/sensor/tests/Sensor_test.cpp
new file mode 100644
index 0000000..ede20c9
--- /dev/null
+++ b/libs/sensor/tests/Sensor_test.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#define LOG_TAG "Sensor_test"
+
+#include <sensor/Sensor.h>
+#include <hardware/sensors.h>
+#include <utils/Errors.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+
+// Returns true if the two sensors have the same attributes. Does not compare
+// UUID since that should not be transmitted via flatten/unflatten.
+static bool sensorsMatch(const Sensor& a, const Sensor& b) {
+ return a.getName() == b.getName () &&
+ a.getVendor() == b.getVendor () &&
+ a.getHandle() == b.getHandle () &&
+ a.getType() == b.getType () &&
+ a.getMinValue() == b.getMinValue () &&
+ a.getMaxValue() == b.getMaxValue () &&
+ a.getResolution() == b.getResolution () &&
+ a.getPowerUsage() == b.getPowerUsage () &&
+ a.getMinDelay() == b.getMinDelay () &&
+ a.getMinDelayNs() == b.getMinDelayNs () &&
+ a.getVersion() == b.getVersion () &&
+ a.getFifoReservedEventCount() == b.getFifoReservedEventCount () &&
+ a.getFifoMaxEventCount() == b.getFifoMaxEventCount () &&
+ a.getStringType() == b.getStringType () &&
+ a.getRequiredPermission() == b.getRequiredPermission () &&
+ a.isRequiredPermissionRuntime() == b.isRequiredPermissionRuntime () &&
+ a.getRequiredAppOp() == b.getRequiredAppOp () &&
+ a.getMaxDelay() == b.getMaxDelay () &&
+ a.getFlags() == b.getFlags () &&
+ a.isWakeUpSensor() == b.isWakeUpSensor () &&
+ a.isDynamicSensor() == b.isDynamicSensor () &&
+ a.hasAdditionalInfo() == b.hasAdditionalInfo () &&
+ a.getReportingMode() == b.getReportingMode();
+}
+
+// Creates and returns a sensor_t struct with some default values filled in.
+static sensor_t getTestSensorT() {
+ sensor_t hwSensor = {};
+ hwSensor.name = "Test Sensor";
+ hwSensor.vendor = "Test Vendor";
+ hwSensor.version = 1;
+ hwSensor.handle = 2;
+ hwSensor.type = SENSOR_TYPE_ACCELEROMETER;
+ hwSensor.maxRange = 10.f;
+ hwSensor.resolution = 1.f;
+ hwSensor.power = 5.f;
+ hwSensor.minDelay = 1000;
+ hwSensor.fifoReservedEventCount = 50;
+ hwSensor.fifoMaxEventCount = 100;
+ hwSensor.stringType = SENSOR_STRING_TYPE_ACCELEROMETER;
+ hwSensor.requiredPermission = "";
+ hwSensor.maxDelay = 5000;
+ hwSensor.flags = SENSOR_FLAG_CONTINUOUS_MODE;
+ return hwSensor;
+}
+
+TEST(SensorTest, FlattenAndUnflatten) {
+ sensor_t hwSensor = getTestSensorT();
+ Sensor sensor1(&hwSensor, SENSORS_DEVICE_API_VERSION_1_4);
+ Sensor sensor2;
+
+ std::vector<uint8_t> buffer(sensor1.getFlattenedSize());
+ ASSERT_EQ(OK, sensor1.flatten(buffer.data(), buffer.size()));
+ ASSERT_EQ(OK, sensor2.unflatten(buffer.data(), buffer.size()));
+
+ EXPECT_TRUE(sensorsMatch(sensor1, sensor2));
+}
+
+} // namespace android