diff --git a/sensors/aidl/Android.bp b/sensors/aidl/Android.bp index d04017ccd0..9673190731 100644 --- a/sensors/aidl/Android.bp +++ b/sensors/aidl/Android.bp @@ -11,6 +11,7 @@ aidl_interface { name: "android.hardware.sensors", vendor_available: true, srcs: ["android/hardware/sensors/*.aidl"], + host_supported: true, imports: [ "android.hardware.common-V2", "android.hardware.common.fmq-V1", diff --git a/sensors/aidl/convert/Android.bp b/sensors/aidl/convert/Android.bp new file mode 100644 index 0000000000..8e2146d90a --- /dev/null +++ b/sensors/aidl/convert/Android.bp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 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. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_static { + name: "android.hardware.sensors-V1-convert", + vendor_available: true, + srcs: ["convert.cpp"], + export_include_dirs: ["include"], + shared_libs: [ + "liblog", + "libcutils", + "libhardware", + "libbase", + "libutils", + "android.hardware.sensors-V1-ndk", + ], + local_include_dirs: ["include/aidl/sensors"], + export_shared_lib_headers: [ + "libhardware", + ], +} diff --git a/sensors/aidl/convert/convert.cpp b/sensors/aidl/convert/convert.cpp new file mode 100644 index 0000000000..415f4352f5 --- /dev/null +++ b/sensors/aidl/convert/convert.cpp @@ -0,0 +1,496 @@ +/* + * Copyright (C) 2022 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 "aidl/sensors/convert.h" +#include "android-base/logging.h" + +namespace android { +namespace hardware { +namespace sensors { +namespace implementation { + +using aidl::android::hardware::sensors::AdditionalInfo; +using aidl::android::hardware::sensors::DynamicSensorInfo; +using aidl::android::hardware::sensors::Event; +using aidl::android::hardware::sensors::ISensors; +using aidl::android::hardware::sensors::SensorInfo; +using aidl::android::hardware::sensors::SensorStatus; +using aidl::android::hardware::sensors::SensorType; + +status_t convertToStatus(ndk::ScopedAStatus status) { + if (status.isOk()) { + return OK; + } else { + switch (status.getExceptionCode()) { + case EX_ILLEGAL_ARGUMENT: { + return BAD_VALUE; + } + case EX_SECURITY: { + return PERMISSION_DENIED; + } + case EX_UNSUPPORTED_OPERATION: { + return INVALID_OPERATION; + } + case EX_SERVICE_SPECIFIC: { + switch (status.getServiceSpecificError()) { + case ISensors::ERROR_BAD_VALUE: { + return BAD_VALUE; + } + case ISensors::ERROR_NO_MEMORY: { + return NO_MEMORY; + } + default: { + return UNKNOWN_ERROR; + } + } + } + default: { + return UNKNOWN_ERROR; + } + } + } +} + +void convertToSensor(const SensorInfo& src, sensor_t* dst) { + dst->name = strdup(src.name.c_str()); + dst->vendor = strdup(src.vendor.c_str()); + dst->version = src.version; + dst->handle = src.sensorHandle; + dst->type = (int)src.type; + dst->maxRange = src.maxRange; + dst->resolution = src.resolution; + dst->power = src.power; + dst->minDelay = src.minDelayUs; + dst->fifoReservedEventCount = src.fifoReservedEventCount; + dst->fifoMaxEventCount = src.fifoMaxEventCount; + dst->stringType = strdup(src.typeAsString.c_str()); + dst->requiredPermission = strdup(src.requiredPermission.c_str()); + dst->maxDelay = src.maxDelayUs; + dst->flags = src.flags; + dst->reserved[0] = dst->reserved[1] = 0; +} + +void convertToSensorEvent(const Event& src, sensors_event_t* dst) { + *dst = {.version = sizeof(sensors_event_t), + .sensor = src.sensorHandle, + .type = (int32_t)src.sensorType, + .reserved0 = 0, + .timestamp = src.timestamp}; + + switch (src.sensorType) { + case SensorType::META_DATA: { + // Legacy HALs expect the handle reference in the meta data field. + // Copy it over from the handle of the event. + dst->meta_data.what = (int32_t)src.payload.get().what; + dst->meta_data.sensor = src.sensorHandle; + // Set the sensor handle to 0 to maintain compatibility. + dst->sensor = 0; + break; + } + + case SensorType::ACCELEROMETER: + case SensorType::MAGNETIC_FIELD: + case SensorType::ORIENTATION: + case SensorType::GYROSCOPE: + case SensorType::GRAVITY: + case SensorType::LINEAR_ACCELERATION: { + dst->acceleration.x = src.payload.get().x; + dst->acceleration.y = src.payload.get().y; + dst->acceleration.z = src.payload.get().z; + dst->acceleration.status = (int32_t)src.payload.get().status; + break; + } + + case SensorType::GAME_ROTATION_VECTOR: { + dst->data[0] = src.payload.get().x; + dst->data[1] = src.payload.get().y; + dst->data[2] = src.payload.get().z; + dst->data[3] = src.payload.get().w; + break; + } + + case SensorType::ROTATION_VECTOR: + case SensorType::GEOMAGNETIC_ROTATION_VECTOR: { + dst->data[0] = src.payload.get().values[0]; + dst->data[1] = src.payload.get().values[1]; + dst->data[2] = src.payload.get().values[2]; + dst->data[3] = src.payload.get().values[3]; + dst->data[4] = src.payload.get().values[4]; + break; + } + + case SensorType::MAGNETIC_FIELD_UNCALIBRATED: + case SensorType::GYROSCOPE_UNCALIBRATED: + case SensorType::ACCELEROMETER_UNCALIBRATED: { + dst->uncalibrated_gyro.x_uncalib = src.payload.get().x; + dst->uncalibrated_gyro.y_uncalib = src.payload.get().y; + dst->uncalibrated_gyro.z_uncalib = src.payload.get().z; + dst->uncalibrated_gyro.x_bias = src.payload.get().xBias; + dst->uncalibrated_gyro.y_bias = src.payload.get().yBias; + dst->uncalibrated_gyro.z_bias = src.payload.get().zBias; + break; + } + + case SensorType::HINGE_ANGLE: + case SensorType::DEVICE_ORIENTATION: + case SensorType::LIGHT: + case SensorType::PRESSURE: + case SensorType::PROXIMITY: + case SensorType::RELATIVE_HUMIDITY: + case SensorType::AMBIENT_TEMPERATURE: + case SensorType::SIGNIFICANT_MOTION: + case SensorType::STEP_DETECTOR: + case SensorType::TILT_DETECTOR: + case SensorType::WAKE_GESTURE: + case SensorType::GLANCE_GESTURE: + case SensorType::PICK_UP_GESTURE: + case SensorType::WRIST_TILT_GESTURE: + case SensorType::STATIONARY_DETECT: + case SensorType::MOTION_DETECT: + case SensorType::HEART_BEAT: + case SensorType::LOW_LATENCY_OFFBODY_DETECT: { + dst->data[0] = src.payload.get(); + break; + } + + case SensorType::STEP_COUNTER: { + dst->u64.step_counter = src.payload.get(); + break; + } + + case SensorType::HEART_RATE: { + dst->heart_rate.bpm = src.payload.get().bpm; + dst->heart_rate.status = + (int8_t)src.payload.get().status; + break; + } + + case SensorType::POSE_6DOF: { // 15 floats + for (size_t i = 0; i < 15; ++i) { + dst->data[i] = src.payload.get().values[i]; + } + break; + } + + case SensorType::DYNAMIC_SENSOR_META: { + dst->dynamic_sensor_meta.connected = + src.payload.get().connected; + dst->dynamic_sensor_meta.handle = + src.payload.get().sensorHandle; + dst->dynamic_sensor_meta.sensor = NULL; // to be filled in later + + memcpy(dst->dynamic_sensor_meta.uuid, + src.payload.get().uuid.values.data(), 16); + + break; + } + + case SensorType::ADDITIONAL_INFO: { + const AdditionalInfo& srcInfo = src.payload.get(); + + additional_info_event_t* dstInfo = &dst->additional_info; + dstInfo->type = (int32_t)srcInfo.type; + dstInfo->serial = srcInfo.serial; + + switch (srcInfo.payload.getTag()) { + case AdditionalInfo::AdditionalInfoPayload::Tag::dataInt32: { + const auto& values = + srcInfo.payload.get() + .values; + CHECK_EQ(values.size() * sizeof(int32_t), sizeof(dstInfo->data_int32)); + memcpy(dstInfo->data_int32, values.data(), sizeof(dstInfo->data_int32)); + break; + } + case AdditionalInfo::AdditionalInfoPayload::Tag::dataFloat: { + const auto& values = + srcInfo.payload.get() + .values; + CHECK_EQ(values.size() * sizeof(float), sizeof(dstInfo->data_float)); + memcpy(dstInfo->data_float, values.data(), sizeof(dstInfo->data_float)); + break; + } + default: { + LOG(ERROR) << "Invalid sensor additional info tag: ", + (int)srcInfo.payload.getTag(); + } + } + break; + } + + case SensorType::HEAD_TRACKER: { + const auto& ht = src.payload.get(); + dst->head_tracker.rx = ht.rx; + dst->head_tracker.ry = ht.ry; + dst->head_tracker.rz = ht.rz; + dst->head_tracker.vx = ht.vx; + dst->head_tracker.vy = ht.vy; + dst->head_tracker.vz = ht.vz; + dst->head_tracker.discontinuity_count = ht.discontinuityCount; + break; + } + + case SensorType::ACCELEROMETER_LIMITED_AXES: + case SensorType::GYROSCOPE_LIMITED_AXES: + dst->limited_axes_imu.x = src.payload.get().x; + dst->limited_axes_imu.y = src.payload.get().y; + dst->limited_axes_imu.z = src.payload.get().z; + dst->limited_axes_imu.x_supported = + src.payload.get().xSupported; + dst->limited_axes_imu.y_supported = + src.payload.get().ySupported; + dst->limited_axes_imu.z_supported = + src.payload.get().zSupported; + break; + + case SensorType::ACCELEROMETER_LIMITED_AXES_UNCALIBRATED: + case SensorType::GYROSCOPE_LIMITED_AXES_UNCALIBRATED: + dst->limited_axes_imu_uncalibrated.x_uncalib = + src.payload.get().x; + dst->limited_axes_imu_uncalibrated.y_uncalib = + src.payload.get().y; + dst->limited_axes_imu_uncalibrated.z_uncalib = + src.payload.get().z; + dst->limited_axes_imu_uncalibrated.x_bias = + src.payload.get().xBias; + dst->limited_axes_imu_uncalibrated.y_bias = + src.payload.get().yBias; + dst->limited_axes_imu_uncalibrated.z_bias = + src.payload.get().zBias; + dst->limited_axes_imu_uncalibrated.x_supported = + src.payload.get().xSupported; + dst->limited_axes_imu_uncalibrated.y_supported = + src.payload.get().ySupported; + dst->limited_axes_imu_uncalibrated.z_supported = + src.payload.get().zSupported; + break; + + case SensorType::HEADING: + dst->heading.heading = src.payload.get().heading; + dst->heading.accuracy = src.payload.get().accuracy; + break; + + default: { + CHECK_GE((int32_t)src.sensorType, (int32_t)SensorType::DEVICE_PRIVATE_BASE); + + memcpy(dst->data, src.payload.get().values.data(), + 16 * sizeof(float)); + break; + } + } +} + +void convertFromSensorEvent(const sensors_event_t& src, Event* dst) { + *dst = { + .timestamp = src.timestamp, + .sensorHandle = src.sensor, + .sensorType = (SensorType)src.type, + }; + + switch (dst->sensorType) { + case SensorType::META_DATA: { + Event::EventPayload::MetaData meta; + meta.what = (Event::EventPayload::MetaData::MetaDataEventType)src.meta_data.what; + // Legacy HALs contain the handle reference in the meta data field. + // Copy that over to the handle of the event. In legacy HALs this + // field was expected to be 0. + dst->sensorHandle = src.meta_data.sensor; + dst->payload.set(meta); + break; + } + + case SensorType::ACCELEROMETER: + case SensorType::MAGNETIC_FIELD: + case SensorType::ORIENTATION: + case SensorType::GYROSCOPE: + case SensorType::GRAVITY: + case SensorType::LINEAR_ACCELERATION: { + Event::EventPayload::Vec3 vec3; + vec3.x = src.acceleration.x; + vec3.y = src.acceleration.y; + vec3.z = src.acceleration.z; + vec3.status = (SensorStatus)src.acceleration.status; + dst->payload.set(vec3); + break; + } + + case SensorType::GAME_ROTATION_VECTOR: { + Event::EventPayload::Vec4 vec4; + vec4.x = src.data[0]; + vec4.y = src.data[1]; + vec4.z = src.data[2]; + vec4.w = src.data[3]; + dst->payload.set(vec4); + break; + } + + case SensorType::ROTATION_VECTOR: + case SensorType::GEOMAGNETIC_ROTATION_VECTOR: { + Event::EventPayload::Data data; + memcpy(data.values.data(), src.data, 5 * sizeof(float)); + dst->payload.set(data); + break; + } + + case SensorType::MAGNETIC_FIELD_UNCALIBRATED: + case SensorType::GYROSCOPE_UNCALIBRATED: + case SensorType::ACCELEROMETER_UNCALIBRATED: { + Event::EventPayload::Uncal uncal; + uncal.x = src.uncalibrated_gyro.x_uncalib; + uncal.y = src.uncalibrated_gyro.y_uncalib; + uncal.z = src.uncalibrated_gyro.z_uncalib; + uncal.xBias = src.uncalibrated_gyro.x_bias; + uncal.yBias = src.uncalibrated_gyro.y_bias; + uncal.zBias = src.uncalibrated_gyro.z_bias; + dst->payload.set(uncal); + break; + } + + case SensorType::DEVICE_ORIENTATION: + case SensorType::LIGHT: + case SensorType::PRESSURE: + case SensorType::PROXIMITY: + case SensorType::RELATIVE_HUMIDITY: + case SensorType::AMBIENT_TEMPERATURE: + case SensorType::SIGNIFICANT_MOTION: + case SensorType::STEP_DETECTOR: + case SensorType::TILT_DETECTOR: + case SensorType::WAKE_GESTURE: + case SensorType::GLANCE_GESTURE: + case SensorType::PICK_UP_GESTURE: + case SensorType::WRIST_TILT_GESTURE: + case SensorType::STATIONARY_DETECT: + case SensorType::MOTION_DETECT: + case SensorType::HEART_BEAT: + case SensorType::LOW_LATENCY_OFFBODY_DETECT: + case SensorType::HINGE_ANGLE: { + dst->payload.set((float)src.data[0]); + break; + } + + case SensorType::STEP_COUNTER: { + dst->payload.set(src.u64.step_counter); + break; + } + + case SensorType::HEART_RATE: { + Event::EventPayload::HeartRate heartRate; + heartRate.bpm = src.heart_rate.bpm; + heartRate.status = (SensorStatus)src.heart_rate.status; + dst->payload.set(heartRate); + break; + } + + case SensorType::POSE_6DOF: { // 15 floats + Event::EventPayload::Pose6Dof pose6DOF; + for (size_t i = 0; i < 15; ++i) { + pose6DOF.values[i] = src.data[i]; + } + dst->payload.set(pose6DOF); + break; + } + + case SensorType::DYNAMIC_SENSOR_META: { + DynamicSensorInfo dynamic; + dynamic.connected = src.dynamic_sensor_meta.connected; + dynamic.sensorHandle = src.dynamic_sensor_meta.handle; + + memcpy(dynamic.uuid.values.data(), src.dynamic_sensor_meta.uuid, 16); + dst->payload.set(dynamic); + break; + } + + case SensorType::ADDITIONAL_INFO: { + AdditionalInfo info; + const additional_info_event_t& srcInfo = src.additional_info; + info.type = (AdditionalInfo::AdditionalInfoType)srcInfo.type; + info.serial = srcInfo.serial; + + AdditionalInfo::AdditionalInfoPayload::Int32Values data; + CHECK_EQ(data.values.size() * sizeof(int32_t), sizeof(srcInfo.data_int32)); + memcpy(data.values.data(), srcInfo.data_int32, sizeof(srcInfo.data_int32)); + info.payload.set(data); + + dst->payload.set(info); + break; + } + + case SensorType::HEAD_TRACKER: { + Event::EventPayload::HeadTracker headTracker; + headTracker.rx = src.head_tracker.rx; + headTracker.ry = src.head_tracker.ry; + headTracker.rz = src.head_tracker.rz; + headTracker.vx = src.head_tracker.vx; + headTracker.vy = src.head_tracker.vy; + headTracker.vz = src.head_tracker.vz; + headTracker.discontinuityCount = src.head_tracker.discontinuity_count; + + dst->payload.set(headTracker); + break; + } + + case SensorType::ACCELEROMETER_LIMITED_AXES: + case SensorType::GYROSCOPE_LIMITED_AXES: { + Event::EventPayload::LimitedAxesImu limitedAxesImu; + limitedAxesImu.x = src.limited_axes_imu.x; + limitedAxesImu.y = src.limited_axes_imu.y; + limitedAxesImu.z = src.limited_axes_imu.z; + limitedAxesImu.xSupported = src.limited_axes_imu.x_supported; + limitedAxesImu.ySupported = src.limited_axes_imu.y_supported; + limitedAxesImu.zSupported = src.limited_axes_imu.z_supported; + dst->payload.set(limitedAxesImu); + break; + } + + case SensorType::ACCELEROMETER_LIMITED_AXES_UNCALIBRATED: + case SensorType::GYROSCOPE_LIMITED_AXES_UNCALIBRATED: { + Event::EventPayload::LimitedAxesImuUncal limitedAxesImuUncal; + limitedAxesImuUncal.x = src.limited_axes_imu_uncalibrated.x_uncalib; + limitedAxesImuUncal.y = src.limited_axes_imu_uncalibrated.y_uncalib; + limitedAxesImuUncal.z = src.limited_axes_imu_uncalibrated.z_uncalib; + limitedAxesImuUncal.xBias = src.limited_axes_imu_uncalibrated.x_bias; + limitedAxesImuUncal.yBias = src.limited_axes_imu_uncalibrated.y_bias; + limitedAxesImuUncal.yBias = src.limited_axes_imu_uncalibrated.y_bias; + limitedAxesImuUncal.zBias = src.limited_axes_imu_uncalibrated.z_bias; + limitedAxesImuUncal.xSupported = src.limited_axes_imu_uncalibrated.x_supported; + limitedAxesImuUncal.ySupported = src.limited_axes_imu_uncalibrated.y_supported; + limitedAxesImuUncal.zSupported = src.limited_axes_imu_uncalibrated.z_supported; + dst->payload.set(limitedAxesImuUncal); + break; + } + + case SensorType::HEADING: { + Event::EventPayload::Heading heading; + heading.heading = src.heading.heading; + heading.accuracy = src.heading.accuracy; + dst->payload.set(heading); + break; + } + + default: { + CHECK_GE((int32_t)dst->sensorType, (int32_t)SensorType::DEVICE_PRIVATE_BASE); + + Event::EventPayload::Data data; + memcpy(data.values.data(), src.data, 16 * sizeof(float)); + dst->payload.set(data); + break; + } + } +} + +} // namespace implementation +} // namespace sensors +} // namespace hardware +} // namespace android diff --git a/sensors/aidl/convert/include/aidl/sensors/convert.h b/sensors/aidl/convert/include/aidl/sensors/convert.h new file mode 100644 index 0000000000..702b2266ba --- /dev/null +++ b/sensors/aidl/convert/include/aidl/sensors/convert.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 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 +#include + +namespace android { +namespace hardware { +namespace sensors { +namespace implementation { + +status_t convertToStatus(ndk::ScopedAStatus status); +void convertToSensor(const aidl::android::hardware::sensors::SensorInfo& src, sensor_t* dst); +void convertToSensorEvent(const aidl::android::hardware::sensors::Event& src, sensors_event_t* dst); +void convertFromSensorEvent(const sensors_event_t& src, + aidl::android::hardware::sensors::Event* dst); + +} // namespace implementation +} // namespace sensors +} // namespace hardware +} // namespace android