diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2022-01-05 17:51:49 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2022-01-05 17:51:49 +0000 |
commit | d431c50355c94370a96ae5b32e720c75c68dba26 (patch) | |
tree | d601af664a95f92545f821304f89d8ae71fdbb57 | |
parent | 0a0b30499a407848d391a4f3eed497ff121c2533 (diff) | |
parent | bc2a1b7321149a08693c38177f05b6274d49f99c (diff) |
Merge changes from topic "sensors-hal-aidl"
* changes:
Adds sensors aidl default (cuttlefish) implementation
Adds sensors HAL AIDL interface
31 files changed, 4634 insertions, 0 deletions
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index c480c13554..c847ea37a1 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -626,6 +626,13 @@ <instance>strongbox</instance> </interface> </hal> + <hal format="aidl" optional="true"> + <name>android.hardware.sensors</name> + <interface> + <name>ISensors</name> + <instance>default</instance> + </interface> + </hal> <hal format="hidl" optional="true"> <name>android.hardware.sensors</name> <version>1.0</version> diff --git a/sensors/aidl/Android.bp b/sensors/aidl/Android.bp new file mode 100644 index 0000000000..fd1ac441e2 --- /dev/null +++ b/sensors/aidl/Android.bp @@ -0,0 +1,25 @@ +// This is the expected build file, but it may not be right in all cases + +aidl_interface { + name: "android.hardware.sensors", + vendor_available: true, + srcs: ["android/hardware/sensors/*.aidl"], + imports: [ + "android.hardware.common-V2", + "android.hardware.common.fmq-V1", + ], + stability: "vintf", + backend: { + cpp: { + enabled: false, + }, + java: { + enabled: false, + }, + ndk: { + vndk: { + enabled: true, + }, + }, + }, +} diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/AdditionalInfo.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/AdditionalInfo.aidl new file mode 100644 index 0000000000..518472305d --- /dev/null +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/AdditionalInfo.aidl @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2021 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.sensors; +@FixedSize @VintfStability +parcelable AdditionalInfo { + android.hardware.sensors.AdditionalInfo.AdditionalInfoType type; + int serial; + android.hardware.sensors.AdditionalInfo.AdditionalInfoPayload payload; + @FixedSize @VintfStability + union AdditionalInfoPayload { + android.hardware.sensors.AdditionalInfo.AdditionalInfoPayload.Int32Values dataInt32; + android.hardware.sensors.AdditionalInfo.AdditionalInfoPayload.FloatValues dataFloat; + @FixedSize @VintfStability + parcelable Int32Values { + int[14] values; + } + @FixedSize @VintfStability + parcelable FloatValues { + float[14] values; + } + } + @Backing(type="int") @VintfStability + enum AdditionalInfoType { + AINFO_BEGIN = 0, + AINFO_END = 1, + AINFO_UNTRACKED_DELAY = 65536, + AINFO_INTERNAL_TEMPERATURE = 65537, + AINFO_VEC3_CALIBRATION = 65538, + AINFO_SENSOR_PLACEMENT = 65539, + AINFO_SAMPLING = 65540, + AINFO_CHANNEL_NOISE = 131072, + AINFO_CHANNEL_SAMPLER = 131073, + AINFO_CHANNEL_FILTER = 131074, + AINFO_CHANNEL_LINEAR_TRANSFORM = 131075, + AINFO_CHANNEL_NONLINEAR_MAP = 131076, + AINFO_CHANNEL_RESAMPLER = 131077, + AINFO_LOCAL_GEOMAGNETIC_FIELD = 196608, + AINFO_LOCAL_GRAVITY = 196609, + AINFO_DOCK_STATE = 196610, + AINFO_HIGH_PERFORMANCE_MODE = 196611, + AINFO_MAGNETIC_FIELD_CALIBRATION = 196612, + AINFO_CUSTOM_START = 268435456, + AINFO_DEBUGGING_START = 1073741824, + } +} diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/DynamicSensorInfo.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/DynamicSensorInfo.aidl new file mode 100644 index 0000000000..0c9a493a91 --- /dev/null +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/DynamicSensorInfo.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.sensors; +@FixedSize @VintfStability +parcelable DynamicSensorInfo { + boolean connected; + int sensorHandle; + android.hardware.sensors.DynamicSensorInfo.Uuid uuid; + @FixedSize @VintfStability + parcelable Uuid { + byte[16] values; + } +} diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/Event.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/Event.aidl new file mode 100644 index 0000000000..186b2be8b3 --- /dev/null +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/Event.aidl @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2021 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.sensors; +@FixedSize @VintfStability +parcelable Event { + long timestamp; + int sensorHandle; + android.hardware.sensors.SensorType sensorType; + android.hardware.sensors.Event.EventPayload payload; + @FixedSize @VintfStability + union EventPayload { + android.hardware.sensors.Event.EventPayload.Vec3 vec3; + android.hardware.sensors.Event.EventPayload.Vec4 vec4; + android.hardware.sensors.Event.EventPayload.Uncal uncal; + android.hardware.sensors.Event.EventPayload.MetaData meta; + float scalar; + long stepCount; + android.hardware.sensors.Event.EventPayload.HeartRate heartRate; + android.hardware.sensors.Event.EventPayload.Pose6Dof pose6DOF; + android.hardware.sensors.DynamicSensorInfo dynamic; + android.hardware.sensors.AdditionalInfo additional; + android.hardware.sensors.Event.EventPayload.Data data; + @FixedSize @VintfStability + parcelable Vec4 { + float x; + float y; + float z; + float w; + } + @FixedSize @VintfStability + parcelable Vec3 { + float x; + float y; + float z; + android.hardware.sensors.SensorStatus status; + } + @FixedSize @VintfStability + parcelable Uncal { + float x; + float y; + float z; + float xBias; + float yBias; + float zBias; + } + @FixedSize @VintfStability + parcelable HeartRate { + float bpm; + android.hardware.sensors.SensorStatus status; + } + @FixedSize @VintfStability + parcelable MetaData { + android.hardware.sensors.Event.EventPayload.MetaData.MetaDataEventType what; + @Backing(type="int") @VintfStability + enum MetaDataEventType { + META_DATA_FLUSH_COMPLETE = 1, + } + } + @FixedSize @VintfStability + parcelable Pose6Dof { + float[15] values; + } + @FixedSize @VintfStability + parcelable Data { + float[16] values; + } + } +} diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl new file mode 100644 index 0000000000..f60f5bb247 --- /dev/null +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2021 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.sensors; +@VintfStability +interface ISensors { + void activate(in int sensorHandle, in boolean enabled); + void batch(in int sensorHandle, in long samplingPeriodNs, in long maxReportLatencyNs); + int configDirectReport(in int sensorHandle, in int channelHandle, in android.hardware.sensors.ISensors.RateLevel rate); + void flush(in int sensorHandle); + android.hardware.sensors.SensorInfo[] getSensorsList(); + void initialize(in android.hardware.common.fmq.MQDescriptor<android.hardware.sensors.Event,android.hardware.common.fmq.SynchronizedReadWrite> eventQueueDescriptor, in android.hardware.common.fmq.MQDescriptor<int,android.hardware.common.fmq.SynchronizedReadWrite> wakeLockDescriptor, in android.hardware.sensors.ISensorsCallback sensorsCallback); + void injectSensorData(in android.hardware.sensors.Event event); + int registerDirectChannel(in android.hardware.sensors.ISensors.SharedMemInfo mem); + void setOperationMode(in android.hardware.sensors.ISensors.OperationMode mode); + void unregisterDirectChannel(in int channelHandle); + const int ERROR_NO_MEMORY = -12; + const int ERROR_BAD_VALUE = -22; + const int WAKE_LOCK_TIMEOUT_SECONDS = 1; + const int EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS = 1; + const int EVENT_QUEUE_FLAG_BITS_EVENTS_READ = 2; + const int WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN = 1; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_FIELD = 0; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_REPORT_TOKEN = 4; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_SENSOR_TYPE = 8; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_ATOMIC_COUNTER = 12; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_TIMESTAMP = 16; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_DATA = 24; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_RESERVED = 88; + const int DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH = 104; + @Backing(type="int") @VintfStability + enum RateLevel { + STOP = 0, + NORMAL = 1, + FAST = 2, + VERY_FAST = 3, + } + @Backing(type="int") @VintfStability + enum OperationMode { + NORMAL = 0, + DATA_INJECTION = 1, + } + @VintfStability + parcelable SharedMemInfo { + android.hardware.sensors.ISensors.SharedMemInfo.SharedMemType type; + android.hardware.sensors.ISensors.SharedMemInfo.SharedMemFormat format; + int size; + android.hardware.common.NativeHandle memoryHandle; + @Backing(type="int") @VintfStability + enum SharedMemFormat { + SENSORS_EVENT = 1, + } + @Backing(type="int") @VintfStability + enum SharedMemType { + ASHMEM = 1, + GRALLOC = 2, + } + } +} diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensorsCallback.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensorsCallback.aidl new file mode 100644 index 0000000000..78ab56711b --- /dev/null +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensorsCallback.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.sensors; +@VintfStability +interface ISensorsCallback { + void onDynamicSensorsConnected(in android.hardware.sensors.SensorInfo[] sensorInfos); + void onDynamicSensorsDisconnected(in int[] sensorHandles); +} diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorInfo.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorInfo.aidl new file mode 100644 index 0000000000..996be3d4db --- /dev/null +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorInfo.aidl @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2021 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.sensors; +@VintfStability +parcelable SensorInfo { + int sensorHandle; + String name; + String vendor; + int version; + android.hardware.sensors.SensorType type; + String typeAsString; + float maxRange; + float resolution; + float power; + int minDelayUs; + int fifoReservedEventCount; + int fifoMaxEventCount; + String requiredPermission; + int maxDelayUs; + int flags; + const int SENSOR_FLAG_BITS_WAKE_UP = 1; + const int SENSOR_FLAG_BITS_CONTINUOUS_MODE = 0; + const int SENSOR_FLAG_BITS_ON_CHANGE_MODE = 2; + const int SENSOR_FLAG_BITS_ONE_SHOT_MODE = 4; + const int SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE = 6; + const int SENSOR_FLAG_BITS_DATA_INJECTION = 16; + const int SENSOR_FLAG_BITS_DYNAMIC_SENSOR = 32; + const int SENSOR_FLAG_BITS_ADDITIONAL_INFO = 64; + const int SENSOR_FLAG_BITS_DIRECT_CHANNEL_ASHMEM = 1024; + const int SENSOR_FLAG_BITS_DIRECT_CHANNEL_GRALLOC = 2048; + const int SENSOR_FLAG_BITS_MASK_REPORTING_MODE = 14; + const int SENSOR_FLAG_BITS_MASK_DIRECT_REPORT = 896; + const int SENSOR_FLAG_BITS_MASK_DIRECT_CHANNEL = 3072; + const int SENSOR_FLAG_SHIFT_REPORTING_MODE = 1; + const int SENSOR_FLAG_SHIFT_DATA_INJECTION = 4; + const int SENSOR_FLAG_SHIFT_DYNAMIC_SENSOR = 5; + const int SENSOR_FLAG_SHIFT_ADDITIONAL_INFO = 6; + const int SENSOR_FLAG_SHIFT_DIRECT_REPORT = 7; + const int SENSOR_FLAG_SHIFT_DIRECT_CHANNEL = 10; +} diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorStatus.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorStatus.aidl new file mode 100644 index 0000000000..45217107fc --- /dev/null +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorStatus.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.sensors; +@Backing(type="byte") @VintfStability +enum SensorStatus { + NO_CONTACT = -1, + UNRELIABLE = 0, + ACCURACY_LOW = 1, + ACCURACY_MEDIUM = 2, + ACCURACY_HIGH = 3, +} diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorType.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorType.aidl new file mode 100644 index 0000000000..4f3b5b2e79 --- /dev/null +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorType.aidl @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2021 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.sensors; +@Backing(type="int") @VintfStability +enum SensorType { + META_DATA = 0, + ACCELEROMETER = 1, + MAGNETIC_FIELD = 2, + ORIENTATION = 3, + GYROSCOPE = 4, + LIGHT = 5, + PRESSURE = 6, + PROXIMITY = 8, + GRAVITY = 9, + LINEAR_ACCELERATION = 10, + ROTATION_VECTOR = 11, + RELATIVE_HUMIDITY = 12, + AMBIENT_TEMPERATURE = 13, + MAGNETIC_FIELD_UNCALIBRATED = 14, + GAME_ROTATION_VECTOR = 15, + GYROSCOPE_UNCALIBRATED = 16, + SIGNIFICANT_MOTION = 17, + STEP_DETECTOR = 18, + STEP_COUNTER = 19, + GEOMAGNETIC_ROTATION_VECTOR = 20, + HEART_RATE = 21, + TILT_DETECTOR = 22, + WAKE_GESTURE = 23, + GLANCE_GESTURE = 24, + PICK_UP_GESTURE = 25, + WRIST_TILT_GESTURE = 26, + DEVICE_ORIENTATION = 27, + POSE_6DOF = 28, + STATIONARY_DETECT = 29, + MOTION_DETECT = 30, + HEART_BEAT = 31, + DYNAMIC_SENSOR_META = 32, + ADDITIONAL_INFO = 33, + LOW_LATENCY_OFFBODY_DETECT = 34, + ACCELEROMETER_UNCALIBRATED = 35, + HINGE_ANGLE = 36, + DEVICE_PRIVATE_BASE = 65536, +} diff --git a/sensors/aidl/android/hardware/sensors/AdditionalInfo.aidl b/sensors/aidl/android/hardware/sensors/AdditionalInfo.aidl new file mode 100644 index 0000000000..9fe2d39700 --- /dev/null +++ b/sensors/aidl/android/hardware/sensors/AdditionalInfo.aidl @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2021 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 android.hardware.sensors; + +@FixedSize +@VintfStability +parcelable AdditionalInfo { + /** + * type of payload data, see AdditionalInfoType + */ + AdditionalInfoType type; + + /** + * sequence number of this frame for this type + */ + int serial; + + AdditionalInfoPayload payload; + + @FixedSize + @VintfStability + union AdditionalInfoPayload { + Int32Values dataInt32; + FloatValues dataFloat; + + @FixedSize + @VintfStability + parcelable Int32Values { + int[14] values; + } + + @FixedSize + @VintfStability + parcelable FloatValues { + float[14] values; + } + } + + @VintfStability + @Backing(type="int") + enum AdditionalInfoType { + /** + * Marks the beginning of additional information frames + */ + AINFO_BEGIN = 0, + + /** + * Marks the end of additional information frames + */ + AINFO_END = 1, + + /** + * Estimation of the delay that is not tracked by sensor timestamps. This + * includes delay introduced by sensor front-end filtering, data transport, + * etc. + * float[2]: delay in seconds, standard deviation of estimated value + */ + AINFO_UNTRACKED_DELAY = 0x10000, + + /** + * float: Celsius temperature + */ + AINFO_INTERNAL_TEMPERATURE, + + /** + * First three rows of a homogeneous matrix, which represents calibration to + * a three-element vector raw sensor reading. + * float[12]: 3x4 matrix in row major order + */ + AINFO_VEC3_CALIBRATION, + + /** + * Provides the orientation and location of the sensor element in terms of + * the Android coordinate system. This data is given as a 3x4 matrix + * consisting of a 3x3 rotation matrix (R) concatenated with a 3x1 location + * vector (t). The rotation matrix provides the orientation of the Android + * device coordinate frame relative to the local coordinate frame of the + * sensor. Note that assuming the axes conventions of the sensor are the + * same as Android, this is the inverse of the matrix applied to raw + * samples read from the sensor to convert them into the Android + * representation. The location vector represents the translation from the + * origin of the Android sensor coordinate system to the geometric center + * of the sensor, specified in millimeters (mm). + * + * float[12]: 3x4 matrix in row major order [R; t] + * + * Example: + * This raw buffer: {0, 1, 0, 0, -1, 0, 0, 10, 0, 0, 1, -2.5} + * Corresponds to this 3x4 matrix: + * 0 1 0 0 + * -1 0 0 10 + * 0 0 1 -2.5 + * The sensor is oriented such that: + * - the device X axis corresponds to the sensor's local -Y axis + * - the device Y axis corresponds to the sensor's local X axis + * - the device Z axis and sensor's local Z axis are equivalent + * In other words, if viewing the origin of the Android coordinate + * system from the positive Z direction, the device coordinate frame is + * to be rotated 90 degrees counter-clockwise about the Z axis to align + * with the sensor's local coordinate frame. Equivalently, a vector in + * the Android coordinate frame may be multiplied with R to rotate it + * 90 degrees clockwise (270 degrees counter-clockwise), yielding its + * representation in the sensor's coordinate frame. + * Relative to the origin of the Android coordinate system, the physical + * center of the sensor is located 10mm in the positive Y direction, and + * 2.5mm in the negative Z direction. + */ + AINFO_SENSOR_PLACEMENT, + + /** + * float[2]: raw sample period in seconds, + * standard deviation of sampling period + */ + AINFO_SAMPLING, + + /** + * int32_t: noise type + * float[n]: parameters + */ + AINFO_CHANNEL_NOISE = 0x20000, + + /** + * float[3]: sample period, standard deviation of sample period, + * quantization unit + */ + AINFO_CHANNEL_SAMPLER, + + /** + * Represents a filter: + * \sum_j a_j y[n-j] == \sum_i b_i x[n-i] + * + * int32_t[3]: number of feedforward coeffients M, + * number of feedback coefficients N (for FIR filter, N = 1). + * bit mask that represents which element the filter is applied + * to. (bit 0==1 means this filter applies to vector element 0). + * float[M+N]: filter coefficients (b0, b1, ..., b_{M-1}), then + * (a0, a1, ..., a_{N-1}), a0 is always 1. + * + * Multiple frames may be needed for higher number of taps. + */ + AINFO_CHANNEL_FILTER, + + /** + * int32_t[2]: size in (row, column) ... 1st frame + * float[n]: matrix element values in row major order. + */ + AINFO_CHANNEL_LINEAR_TRANSFORM, + + /** + * int32_t[2]: extrapolate method, interpolate method + * float[n]: mapping key points in pairs, (in, out)... + * (may be used to model saturation). + */ + AINFO_CHANNEL_NONLINEAR_MAP, + + /** + * int32_t: resample method (0-th order, 1st order...) + * float[1]: resample ratio (upsampling if < 1.0, downsampling if > 1.0). + */ + AINFO_CHANNEL_RESAMPLER, + + /** + * Operation environment parameters section + * Types in the following section is sent down (instead of reported from) + * device as additional information to aid sensor operation. Data is sent + * via injectSensorData() function to sensor handle -1 denoting all sensors + * in device. + * + * + * Local geomagnetic field information based on device geo location. This + * type is primarily for for magnetic field calibration and rotation vector + * sensor fusion. + * float[3]: strength (uT), declination and inclination angle (rad). + */ + AINFO_LOCAL_GEOMAGNETIC_FIELD = 0x30000, + + /** + * Local gravitational acceleration strength at device geo location. + * float: gravitational acceleration norm in m/s^2. + */ + AINFO_LOCAL_GRAVITY, + + /** + * Device dock state. + * int32_t: dock state following Android API Intent.EXTRA_DOCK_STATE + * definition, undefined value is ignored. + */ + AINFO_DOCK_STATE, + + /** + * High performance mode hint. Device is able to use up more power and take + * more resources to improve throughput and latency in high performance mode. + * One possible use case is virtual reality, when sensor latency need to be + * carefully controlled. + * int32_t: 1 or 0, denote if device is in/out of high performance mode, + * other values is ignored. + */ + AINFO_HIGH_PERFORMANCE_MODE, + + /** + * Magnetic field calibration hint. Device is notified when manually + * triggered magnetic field calibration procedure is started or stopped. The + * calibration procedure is assumed timed out after 1 minute from start, + * even if an explicit stop is not received. + * + * int32_t: 1 for start, 0 for stop, other value is ignored. + */ + AINFO_MAGNETIC_FIELD_CALIBRATION, + + /** + * Custom information + */ + AINFO_CUSTOM_START = 0x10000000, + + /** + * Debugging + */ + AINFO_DEBUGGING_START = 0x40000000, + } +} diff --git a/sensors/aidl/android/hardware/sensors/DynamicSensorInfo.aidl b/sensors/aidl/android/hardware/sensors/DynamicSensorInfo.aidl new file mode 100644 index 0000000000..4b14ed0b20 --- /dev/null +++ b/sensors/aidl/android/hardware/sensors/DynamicSensorInfo.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 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 android.hardware.sensors; + +@VintfStability +@FixedSize +parcelable DynamicSensorInfo { + boolean connected; + + int sensorHandle; + + /** + * UUID of a dynamic sensor (using RFC 4122 byte order) + * For UUID 12345678-90AB-CDEF-1122-334455667788 the uuid field is + * initialized as: + * {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x11, ...} + */ + Uuid uuid; + + @FixedSize + @VintfStability + parcelable Uuid { + byte[16] values; + } +} diff --git a/sensors/aidl/android/hardware/sensors/Event.aidl b/sensors/aidl/android/hardware/sensors/Event.aidl new file mode 100644 index 0000000000..6ef9acbbda --- /dev/null +++ b/sensors/aidl/android/hardware/sensors/Event.aidl @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2021 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 android.hardware.sensors; + +import android.hardware.sensors.AdditionalInfo; +import android.hardware.sensors.DynamicSensorInfo; +import android.hardware.sensors.SensorStatus; +import android.hardware.sensors.SensorType; + +@VintfStability +@FixedSize +parcelable Event { + /** + * Time measured in nanoseconds, in "elapsedRealtimeNano()'s" timebase. + */ + long timestamp; + + /** + * sensor identifier + */ + int sensorHandle; + + SensorType sensorType; + + /** + * Union discriminated on sensorType + */ + EventPayload payload; + + /* + * acceleration values are in meter per second per second (m/s^2) + * magnetic vector values are in micro-Tesla (uT) + * orientation values are in degrees + * gyroscope values are in rad/s + * temperature is in degrees centigrade (Celsius) + * distance in centimeters + * light in SI lux units + * pressure in hectopascal (hPa) + * relative humidity in percent + */ + @VintfStability + @FixedSize + union EventPayload { + /** + * SensorType::ACCELEROMETER, SensorType::MAGNETIC_FIELD, + * SensorType::ORIENTATION, SensorType::GYROSCOPE, SensorType::GRAVITY, + * SensorType::LINEAR_ACCELERATION + */ + Vec3 vec3; + + /** + * SensorType::GAME_ROTATION_VECTOR + */ + Vec4 vec4; + + /** + * SensorType::MAGNETIC_FIELD_UNCALIBRATED, + * SensorType::GYROSCOPE_UNCALIBRATED + * SensorType::ACCELEROMETER_UNCALIBRATED + */ + Uncal uncal; + + /** + * SensorType::META_DATA + */ + MetaData meta; + + /** + * SensorType::DEVICE_ORIENTATION, SensorType::LIGHT, SensorType::PRESSURE, + * SensorType::TEMPERATURE, SensorType::PROXIMITY, + * SensorType::RELATIVE_HUMIDITY, SensorType::AMBIENT_TEMPERATURE, + * SensorType::SIGNIFICANT_MOTION, SensorType::STEP_DETECTOR, + * SensorType::TILT_DETECTOR, SensorType::WAKE_GESTURE, + * SensorType::GLANCE_GESTURE, SensorType::PICK_UP_GESTURE, + * SensorType::WRIST_TILT_GESTURE, SensorType::STATIONARY_DETECT, + * SensorType::MOTION_DETECT, SensorType::HEART_BEAT, + * SensorType::LOW_LATENCY_OFFBODY_DETECT + */ + float scalar; + + /** + * SensorType::STEP_COUNTER + */ + long stepCount; + + /** + * SensorType::HEART_RATE + */ + HeartRate heartRate; + + /** + * SensorType::POSE_6DOF + */ + Pose6Dof pose6DOF; + + /** + * SensorType::DYNAMIC_SENSOR_META + */ + DynamicSensorInfo dynamic; + + /** + * SensorType::ADDITIONAL_INFO + */ + AdditionalInfo additional; + + /** + * The following sensors should use the data field: + * - Undefined/custom sensor type >= SensorType::DEVICE_PRIVATE_BASE + * - SensorType::ROTATION_VECTOR, SensorType::GEOMAGNETIC_ROTATION_VECTOR: + * - These are Vec4 types with an additional float accuracy field, + * where data[4] is the estimated heading accuracy in radians + * (-1 if unavailable, and invalid if not in the range (0, 2 * pi]). + */ + Data data; + + @FixedSize + @VintfStability + parcelable Vec4 { + float x; + float y; + float z; + float w; + } + + @FixedSize + @VintfStability + parcelable Vec3 { + float x; + float y; + float z; + SensorStatus status; + } + + @FixedSize + @VintfStability + parcelable Uncal { + float x; + float y; + float z; + float xBias; + float yBias; + float zBias; + } + + @FixedSize + @VintfStability + parcelable HeartRate { + /** + * Heart rate in beats per minute. + * Set to 0 when status is SensorStatus::UNRELIABLE or + * SensorStatus::NO_CONTACT + */ + float bpm; + /** + * Status of the heart rate sensor for this reading. + */ + SensorStatus status; + } + + @FixedSize + @VintfStability + parcelable MetaData { + MetaDataEventType what; + + @VintfStability + @Backing(type="int") + enum MetaDataEventType { + META_DATA_FLUSH_COMPLETE = 1, + } + } + + @FixedSize + @VintfStability + parcelable Pose6Dof { + float[15] values; + } + + @FixedSize + @VintfStability + parcelable Data { + float[16] values; + } + } +} diff --git a/sensors/aidl/android/hardware/sensors/ISensors.aidl b/sensors/aidl/android/hardware/sensors/ISensors.aidl new file mode 100644 index 0000000000..2ac188454b --- /dev/null +++ b/sensors/aidl/android/hardware/sensors/ISensors.aidl @@ -0,0 +1,375 @@ +/* + * Copyright (C) 2021 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 android.hardware.sensors; + +import android.hardware.common.NativeHandle; +import android.hardware.common.fmq.MQDescriptor; +import android.hardware.common.fmq.SynchronizedReadWrite; +import android.hardware.sensors.Event; +import android.hardware.sensors.ISensorsCallback; +import android.hardware.sensors.SensorInfo; + +@VintfStability +interface ISensors { + /** + * Activate/de-activate one sensor. + * + * After sensor de-activation, existing sensor events that have not + * been written to the event queue must be abandoned immediately so that + * subsequent activations do not get stale sensor events (events + * that are generated prior to the latter activation). + * + * @param sensorHandle is the handle of the sensor to change. + * @param enabled set to true to enable, or false to disable the sensor. + * @return Status::ok on success + * EX_ILLEGAL_ARGUMENT if the sensorHandle is invalid. + */ + void activate(in int sensorHandle, in boolean enabled); + + /** + * Sets a sensor’s parameters, including sampling frequency and maximum + * report latency. This function can be called while the sensor is + * activated, in which case it must not cause any sensor measurements to + * be lost: transitioning from one sampling rate to the other cannot cause + * lost events, nor can transitioning from a high maximum report latency to + * a low maximum report latency. + * + * @param sensorHandle handle of sensor to be changed. + * @param samplingPeriodNs specifies sensor sample period in nanoseconds. + * @param maxReportLatencyNs allowed delay time before an event is sampled + * to time of report. + * @return Status::ok on success + * EX_ILLEGAL_ARGUMENT if any parameters are invalid. + */ + void batch(in int sensorHandle, in long samplingPeriodNs, in long maxReportLatencyNs); + + /** + * Configure direct sensor event report in direct channel. + * + * This function start, modify rate or stop direct report of a sensor in a + * certain direct channel. + * + * @param sensorHandle handle of sensor to be configured. When combined + * with STOP rate, sensorHandle can be -1 to denote all active sensors + * in the direct channel specified by channel Handle. + * @param channelHandle handle of direct channel to be configured. + * @param rate rate level, see RateLevel enum. + * @param out reportToken The report token, ignored if rate is STOP. + * See SharedMemFormat. + * @return The direct report token to identify multiple sensors of the same type in a single + * direct channel. + * @return Status::ok on success + * EX_ILLEGAL_ARGUMENT if the parameter is invalid (e.g. unsupported rate level + * for sensor, channelHandle does not exist, etc). + * EX_UNSUPPORTED_OPERATION if this functionality is unsupported. + */ + int configDirectReport(in int sensorHandle, in int channelHandle, in RateLevel rate); + + /** + * Trigger a flush of internal FIFO. + * + * Flush adds a FLUSH_COMPLETE metadata event to the end of the "batch mode" + * FIFO for the specified sensor and flushes the FIFO. If the FIFO is empty + * or if the sensor doesn't support batching (FIFO size zero), return + * SUCCESS and add a trivial FLUSH_COMPLETE event added to the event stream. + * This applies to all sensors other than one-shot sensors. If the sensor + * is a one-shot sensor, flush must return EX_ILLEGAL_ARGUMENT and not generate any + * flush complete metadata. If the sensor is not active at the time flush() + * is called, flush() return EX_ILLEGAL_ARGUMENT. + * + * @param sensorHandle handle of sensor to be flushed. + * @return Status::ok on success + * EX_ILLEGAL_ARGUMENT if the sensorHandle is invalid. + */ + void flush(in int sensorHandle); + + /** + * Enumerate all available (static) sensors. + * + * The SensorInfo for each sensor returned by getSensorsList must be stable + * from the initial call to getSensorsList after a device boot until the + * entire system restarts. The SensorInfo for each sensor must not change + * between subsequent calls to getSensorsList, even across restarts of the + * HAL and its dependencies (for example, the sensor handle for a given + * sensor must not change across HAL restarts). + */ + SensorInfo[] getSensorsList(); + + /** + * Initialize the Sensors HAL's Fast Message Queues (FMQ) and callback. + * + * The Fast Message Queues (FMQ) that are used to send data between the + * framework and the HAL. The callback is used by the HAL to notify the + * framework of asynchronous events, such as a dynamic sensor connection. + * + * The Event FMQ is used to transport sensor events from the HAL to the + * framework. The Event FMQ is created using the eventQueueDescriptor. + * Data may only be written to the Event FMQ. Data must not be read from + * the Event FMQ since the framework is the only reader. Upon receiving + * sensor events, the HAL writes the sensor events to the Event FMQ. + * + * Once the HAL is finished writing sensor events to the Event FMQ, the HAL + * must notify the framework that sensor events are available to be read and + * processed. This is accomplished by either: + * 1) Calling the Event FMQ’s EventFlag::wake() function with + * EventQueueFlagBits::READ_AND_PROCESS + * 2) Setting the write notification in the Event FMQ’s writeBlocking() + * function to EventQueueFlagBits::READ_AND_PROCESS. + * + * If the Event FMQ’s writeBlocking() function is used, the read + * notification must be set to EventQueueFlagBits::EVENTS_READ in order to + * be notified and unblocked when the framework has successfully read events + * from the Event FMQ. + * + * The Wake Lock FMQ is used by the framework to notify the HAL when it is + * safe to release its wake_lock. When the framework receives WAKE_UP events + * from the Event FMQ and the framework has acquired a wake_lock, the + * framework must write the number of WAKE_UP events processed to the Wake + * Lock FMQ. When the HAL reads the data from the Wake Lock FMQ, the HAL + * decrements its current count of unprocessed WAKE_UP events and releases + * its wake_lock if the current count of unprocessed WAKE_UP events is + * zero. It is important to note that the HAL must acquire the wake lock and + * update its internal state regarding the number of outstanding WAKE_UP + * events _before_ posting the event to the Wake Lock FMQ, in order to avoid + * a race condition that can lead to loss of wake lock synchronization with + * the framework. + * + * The framework must use the WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN value to + * notify the HAL that data has been written to the Wake Lock FMQ and must + * be read by HAL. + * + * The ISensorsCallback is used by the HAL to notify the framework of + * asynchronous events, such as a dynamic sensor connection. + * + * The name of any wake_lock acquired by the Sensors HAL for WAKE_UP events + * must begin with "SensorsHAL_WAKEUP". + * + * If WAKE_LOCK_TIMEOUT_SECONDS has elapsed since the most recent WAKE_UP + * event was written to the Event FMQ without receiving a message on the + * Wake Lock FMQ, then any held wake_lock for WAKE_UP events must be + * released. + * + * If either the Event FMQ or the Wake Lock FMQ is already initialized when + * initialize is invoked, then both existing FMQs must be discarded and the + * new descriptors must be used to create new FMQs within the HAL. The + * number of outstanding WAKE_UP events should also be reset to zero, and + * any outstanding wake_locks held as a result of WAKE_UP events should be + * released. + * + * All active sensor requests and direct channels must be closed and + * properly cleaned up when initialize is called in order to ensure that the + * HAL and framework's state is consistent (e.g. after a runtime restart). + * + * initialize must be thread safe and prevent concurrent calls + * to initialize from simultaneously modifying state. + * + * @param eventQueueDescriptor Fast Message Queue descriptor that is used to + * create the Event FMQ which is where sensor events are written. The + * descriptor is obtained from the framework's FMQ that is used to read + * sensor events. + * @param wakeLockDescriptor Fast Message Queue descriptor that is used to + * create the Wake Lock FMQ which is where wake_lock events are read + * from. The descriptor is obtained from the framework's FMQ that is + * used to write wake_lock events. + * @param sensorsCallback sensors callback that receives asynchronous data + * from the Sensors HAL. + * @return Status::ok on success + * EX_ILLEGAL_ARGUMENT if the descriptor is invalid (such as null). + */ + void initialize(in MQDescriptor<Event, SynchronizedReadWrite> eventQueueDescriptor, + in MQDescriptor<int, SynchronizedReadWrite> wakeLockDescriptor, + in ISensorsCallback sensorsCallback); + + /** + * Inject a single sensor event or push operation environment parameters to + * device. + * + * When device is in NORMAL mode, this function is called to push operation + * environment data to device. In this operation, Event is always of + * SensorType::AdditionalInfo type. See operation environment parameters + * section in AdditionalInfoType. + * + * When device is in DATA_INJECTION mode, this function is also used for + * injecting sensor events. + * + * Regardless of OperationMode, injected SensorType::ADDITIONAL_INFO + * type events should not be routed back to the sensor event queue. + * + * @see AdditionalInfoType + * @see OperationMode + * @param event sensor event to be injected + * @return Status::ok on success + * EX_UNSUPPORTED_OPERATION if this functionality is unsupported. + * EX_SECURITY if the operation is not allowed. + * EX_SERVICE_SPECIFIC on error + * - ERROR_BAD_VALUE if the sensor event cannot be injected. + */ + void injectSensorData(in Event event); + + /** + * Register direct report channel. + * + * Register a direct channel with supplied shared memory information. Upon + * return, the sensor hardware is responsible for resetting the memory + * content to initial value (depending on memory format settings). + * + * @param mem shared memory info data structure. + * @param out channelHandle The registered channel handle. + * @return The direct channel handle, which is positive if successfully registered, and -1 + * otherwise. + * @return Status::ok on success + * EX_ILLEGAL_ARGUMENT if the shared memory information is not consistent. + * EX_UNSUPPORTED_OPERATION if this functionality is unsupported. + * EX_SERVICE_SPECIFIC on error + * - ERROR_NO_MEMORY if shared memory cannot be used by sensor system. + */ + int registerDirectChannel(in SharedMemInfo mem); + + /** + * Place the module in a specific mode. + * + * @see OperationMode + * @param mode The operation mode. + * @return Status::ok on success + * EX_UNSUPPORTED_OPERATION if requested mode is not supported. + * EX_SECURITY if the operation is not allowed. + */ + void setOperationMode(in OperationMode mode); + + /** + * Unregister direct report channel. + * + * Unregister a direct channel previously registered using + * registerDirectChannel, and remove all active sensor report configured in + * still active sensor report configured in the direct channel. + * + * @param channelHandle handle of direct channel to be unregistered. + * @return Status::ok on success + * EX_UNSUPPORTED_OPERATION if direct report is not supported. + */ + void unregisterDirectChannel(in int channelHandle); + + /** + * Direct report rate level definition. Except for SENSOR_DIRECT_RATE_STOP, each + * rate level covers the range (55%, 220%] * nominal report rate. For example, + * if config direct report specify a rate level SENSOR_DIRECT_RATE_FAST, it is + * legal for sensor hardware to report event at a rate greater than 110Hz, and + * less or equal to 440Hz. Note that rate has to remain steady without variation + * before new rate level is configured, i.e. if a sensor is configured to + * SENSOR_DIRECT_RATE_FAST and starts to report event at 256Hz, it cannot + * change rate to 128Hz after a few seconds of running even if 128Hz is also in + * the legal range of SENSOR_DIRECT_RATE_FAST. Thus, it is recommended to + * associate report rate with RateLvel statically for single sensor. + */ + @VintfStability + @Backing(type="int") + enum RateLevel { + STOP, + NORMAL, + FAST, + VERY_FAST, + } + + @VintfStability + @Backing(type="int") + enum OperationMode { + // Normal operation. Default state of the module. + NORMAL = 0, + // Loopback mode. Data is injected for the supported sensors by the sensor service in this + // mode. + DATA_INJECTION = 1, + } + + @VintfStability + parcelable SharedMemInfo { + SharedMemType type; + SharedMemFormat format; + int size; + NativeHandle memoryHandle; + + @VintfStability + @Backing(type="int") + enum SharedMemFormat { + SENSORS_EVENT = 1, + } + + @VintfStability + @Backing(type="int") + enum SharedMemType { + ASHMEM = 1, + GRALLOC, + } + } + + /** + * Error codes that are used as service specific errors with the AIDL return + * value EX_SERVICE_SPECIFIC. + */ + const int ERROR_NO_MEMORY = -12; + const int ERROR_BAD_VALUE = -22; + + /** + * The maximum number of seconds to wait for a message on the Wake Lock FMQ + * before automatically releasing any wake_lock held for a WAKE_UP event. + */ + const int WAKE_LOCK_TIMEOUT_SECONDS = 1; + + /** + * Used to notify the Event FMQ that events should be read and processed. + */ + const int EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS = 1 << 0; + + /** + * Used by the framework to signal to the HAL when events have been + * successfully read from the Event FMQ. + * + * If the MessageQueue::writeBlocking function is being used to write sensor + * events to the Event FMQ, then the readNotification parameter must be set + * to EVENTS_READ. + */ + const int EVENT_QUEUE_FLAG_BITS_EVENTS_READ = 1 << 1; + + /** + * Used to notify the HAL that the framework has written data to the Wake + * Lock FMQ. + */ + const int WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN = 1 << 0; + + /** + * Constants related to direct sensor events. The following table illustrates the + * data format. + * + * Offset Type Name + * ----------------------------------- + * 0x0000 int32_t Size (always DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH) + * 0x0004 int32_t Sensor report token + * 0x0008 int32_t Type (see SensorType.aidl) + * 0x000C uint32_t Atomic counter + * 0x0010 int64_t Timestamp (see Event.aidl) + * 0x0018 float[16]/ Data + * int64_t[8] + * 0x0058 int32_t[4] Reserved (set to zero) + */ + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_FIELD = 0x0; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_REPORT_TOKEN = 0x4; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_SENSOR_TYPE = 0x8; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_ATOMIC_COUNTER = 0xC; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_TIMESTAMP = 0x10; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_DATA = 0x18; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_RESERVED = 0x58; + const int DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH = 104; +} diff --git a/sensors/aidl/android/hardware/sensors/ISensorsCallback.aidl b/sensors/aidl/android/hardware/sensors/ISensorsCallback.aidl new file mode 100644 index 0000000000..01bae52d24 --- /dev/null +++ b/sensors/aidl/android/hardware/sensors/ISensorsCallback.aidl @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2021 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 android.hardware.sensors; + +import android.hardware.sensors.SensorInfo; + +@VintfStability +interface ISensorsCallback { + /** + * Notify the framework that new dynamic sensors have been connected. + * + * If a dynamic sensor was previously connected and has not been + * disconnected, then that sensor must not be included in sensorInfos. + * + * @param sensorInfos vector of SensorInfo for each dynamic sensor that + * was connected. + */ + void onDynamicSensorsConnected(in SensorInfo[] sensorInfos); + + /** + * Notify the framework that previously connected dynamic sensors have been + * disconnected. + * + * If a dynamic sensor was previously disconnected and has not been + * reconnected, then that sensor must not be included in sensorHandles. + * + * The HAL must ensure that all sensor events from departing dynamic + * sensors have been written to the Event FMQ before calling + * onDynamicSensorsDisconnected. + * + * @param sensorHandles vector of sensor handles for each dynamic sensors + * that was disconnected. + */ + void onDynamicSensorsDisconnected(in int[] sensorHandles); +} diff --git a/sensors/aidl/android/hardware/sensors/SensorInfo.aidl b/sensors/aidl/android/hardware/sensors/SensorInfo.aidl new file mode 100644 index 0000000000..35caf8bd67 --- /dev/null +++ b/sensors/aidl/android/hardware/sensors/SensorInfo.aidl @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2021 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 android.hardware.sensors; + +import android.hardware.sensors.SensorType; + +@VintfStability +parcelable SensorInfo { + /** + * handle that identifies this sensors. This handle is used to reference + * this sensor throughout the HAL API. + */ + int sensorHandle; + + /** + * Name of this sensor. + * All sensors of the same "type" must have a different "name". + */ + String name; + + /** + * vendor of the hardware part + */ + String vendor; + + /** + * version of the hardware part + driver. The value of this field + * must increase when the driver is updated in a way that changes the + * output of this sensor. This is important for fused sensors when the + * fusion algorithm is updated. + */ + int version; + + /** + * this sensor's type. + */ + SensorType type; + + /** + * type of this sensor as a string. + * + * When defining an OEM specific sensor or sensor manufacturer specific + * sensor, use your reserve domain name as a prefix. + * e.g. com.google.glass.onheaddetector + * + * For sensors of known type defined in SensorType (value < + * SensorType::DEVICE_PRIVATE_BASE), this can be an empty string. + */ + String typeAsString; + + /** + * maximum range of this sensor's value in SI units + */ + float maxRange; + + /** + * smallest difference between two values reported by this sensor + */ + float resolution; + + /** + * rough estimate of this sensor's power consumption in mA + */ + float power; + + /** + * this value depends on the reporting mode: + * + * continuous: minimum sample period allowed in microseconds + * on-change : 0 + * one-shot :-1 + * special : 0, unless otherwise noted + */ + int minDelayUs; + + /** + * number of events reserved for this sensor in the batch mode FIFO. + * If there is a dedicated FIFO for this sensor, then this is the + * size of this FIFO. If the FIFO is shared with other sensors, + * this is the size reserved for that sensor and it can be zero. + */ + int fifoReservedEventCount; + + /** + * maximum number of events of this sensor that could be batched. + * This is especially relevant when the FIFO is shared between + * several sensors; this value is then set to the size of that FIFO. + */ + int fifoMaxEventCount; + + /** + * permission required to see this sensor, register to it and receive data. + * Set to "" if no permission is required. Some sensor types like the + * heart rate monitor have a mandatory require_permission. + * For sensors that always require a specific permission, like the heart + * rate monitor, the android framework might overwrite this string + * automatically. + */ + String requiredPermission; + + /** + * This value is defined only for continuous mode and on-change sensors. + * It is the delay between two sensor events corresponding to the lowest + * frequency that this sensor supports. When lower frequencies are requested + * through batch()/setDelay() the events will be generated at this frequency + * instead. + * It can be used by the framework or applications to estimate when the + * batch FIFO may be full. + * + * continuous, on-change: maximum sampling period allowed in microseconds. + * one-shot, special : 0 + */ + int maxDelayUs; + + /** + * Bitmasks defined in SENSOR_FLAG_BITS_* below. + */ + int flags; + + /** + * Whether this sensor wakes up the AP from suspend mode when data is + * available. Whenever sensor events are delivered from a wake_up sensor, + * the driver needs to hold a wake_lock till the events are read by the + * SensorService i.e. till ISensors::poll() is called the next time. + * Once poll is called again it means events have been read by the + * SensorService, the driver can safely release the wake_lock. SensorService + * will continue to hold a wake_lock till the app actually reads the events. + */ + const int SENSOR_FLAG_BITS_WAKE_UP = 1; + + /** + * Reporting modes for various sensors. Each sensor will have exactly one of + * these modes set. + * The least significant 2nd, 3rd and 4th bits are used to represent four + * possible reporting modes. + */ + const int SENSOR_FLAG_BITS_CONTINUOUS_MODE = 0; + const int SENSOR_FLAG_BITS_ON_CHANGE_MODE = 2; + const int SENSOR_FLAG_BITS_ONE_SHOT_MODE = 4; + const int SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE = 6; + + /** + * Set this flag if the sensor supports data_injection mode and allows data + * to be injected from the SensorService. When in data_injection ONLY + * sensors with this flag set are injected sensor data and only sensors with + * this flag set are activated. Eg: Accelerometer and Step Counter sensors + * can be set with this flag and SensorService will inject accelerometer + * data and read the corresponding step counts. + */ + const int SENSOR_FLAG_BITS_DATA_INJECTION = 0x10; + + /** + * Set this flag if the sensor is a dynamically connected sensor. See + * DynamicSensorInfo and DYNAMIC_SENSOR_META for details. + */ + const int SENSOR_FLAG_BITS_DYNAMIC_SENSOR = 0x20; + + /** + * Set this flag if sensor additional information is supported. + * See ADDITIONAL_INFO and AdditionalInfo for details. + */ + const int SENSOR_FLAG_BITS_ADDITIONAL_INFO = 0x40; + + /** + * Set this flag if sensor suppor direct channel backed by ashmem. + * See SharedMemType and registerDirectChannel for more details. + */ + const int SENSOR_FLAG_BITS_DIRECT_CHANNEL_ASHMEM = 0x400; + + /** + * Set this flag if sensor suppor direct channel backed by gralloc HAL memory. + * See SharedMemType and registerDirectChannel for more details. + */ + const int SENSOR_FLAG_BITS_DIRECT_CHANNEL_GRALLOC = 0x800; + + /** + * Flags mask for reporting mode of sensor. + */ + const int SENSOR_FLAG_BITS_MASK_REPORTING_MODE = 0xE; + + /** + * Flags mask for direct report maximum rate level support. + * See RateLevel. + */ + const int SENSOR_FLAG_BITS_MASK_DIRECT_REPORT = 0x380; + + /** + * Flags mask for all direct channel support bits. + * See SharedMemType. + */ + const int SENSOR_FLAG_BITS_MASK_DIRECT_CHANNEL = 0xC00; + + /** + * Defines the number of bits different pieces of information are shifted in the + * SENSOR_FLAG_BITS_* bitmask. + */ + const int SENSOR_FLAG_SHIFT_REPORTING_MODE = 1; + const int SENSOR_FLAG_SHIFT_DATA_INJECTION = 4; + const int SENSOR_FLAG_SHIFT_DYNAMIC_SENSOR = 5; + const int SENSOR_FLAG_SHIFT_ADDITIONAL_INFO = 6; + const int SENSOR_FLAG_SHIFT_DIRECT_REPORT = 7; + const int SENSOR_FLAG_SHIFT_DIRECT_CHANNEL = 10; +} diff --git a/sensors/aidl/android/hardware/sensors/SensorStatus.aidl b/sensors/aidl/android/hardware/sensors/SensorStatus.aidl new file mode 100644 index 0000000000..0fd86975f5 --- /dev/null +++ b/sensors/aidl/android/hardware/sensors/SensorStatus.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 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 android.hardware.sensors; + +@VintfStability +@Backing(type="byte") +enum SensorStatus { + NO_CONTACT = -1, + UNRELIABLE = 0, + ACCURACY_LOW = 1, + ACCURACY_MEDIUM = 2, + ACCURACY_HIGH = 3, +} diff --git a/sensors/aidl/android/hardware/sensors/SensorType.aidl b/sensors/aidl/android/hardware/sensors/SensorType.aidl new file mode 100644 index 0000000000..95c7a6a2ad --- /dev/null +++ b/sensors/aidl/android/hardware/sensors/SensorType.aidl @@ -0,0 +1,641 @@ +/* + * Copyright (C) 2021 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 android.hardware.sensors; + +@VintfStability +@Backing(type="int") +enum SensorType { + /** + * META_DATA is a special event type used to populate the MetaData + * structure. It doesn't correspond to a physical sensor. Events of this + * type exist only inside the HAL, their primary purpose is to signal the + * completion of a flush request. + */ + META_DATA = 0, + + /** + * ACCELEROMETER + * reporting-mode: continuous + * + * All values are in SI units (m/s^2) and measure the acceleration of the + * device minus the acceleration due to gravity. + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + ACCELEROMETER = 1, + + /** + * MAGNETIC_FIELD + * reporting-mode: continuous + * + * All values are in micro-Tesla (uT) and measure the geomagnetic + * field in the X, Y and Z axis. + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + MAGNETIC_FIELD = 2, + + /** + * ORIENTATION + * reporting-mode: continuous + * + * All values are angles in degrees. + * + * Orientation sensors return sensor events for all 3 axes at a constant + * rate defined by setDelay(). + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + ORIENTATION = 3, + + /** + * GYROSCOPE + * reporting-mode: continuous + * + * All values are in radians/second and measure the rate of rotation + * around the X, Y and Z axis. + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + GYROSCOPE = 4, + + /** + * LIGHT + * reporting-mode: on-change + * + * The light sensor value is returned in SI lux units. + * + * Both wake-up and non wake-up versions are useful. + */ + LIGHT = 5, + + /** + * PRESSURE + * reporting-mode: continuous + * + * The pressure sensor return the athmospheric pressure in hectopascal (hPa) + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + PRESSURE = 6, + + /** + * PROXIMITY + * reporting-mode: on-change + * + * The proximity sensor which turns the screen off and back on during calls + * is the wake-up proximity sensor. Implement wake-up proximity sensor + * before implementing a non wake-up proximity sensor. For the wake-up + * proximity sensor set the flag SENSOR_FLAG_WAKE_UP. + * The value corresponds to the distance to the nearest object in + * centimeters. + */ + PROXIMITY = 8, + + /** + * GRAVITY + * reporting-mode: continuous + * + * A gravity output indicates the direction of and magnitude of gravity in + * the devices's coordinates. + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + GRAVITY = 9, + + /** + * LINEAR_ACCELERATION + * reporting-mode: continuous + * + * Indicates the linear acceleration of the device in device coordinates, + * not including gravity. + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + LINEAR_ACCELERATION = 10, + + /** + * ROTATION_VECTOR + * reporting-mode: continuous + * + * The rotation vector symbolizes the orientation of the device relative to + * the East-North-Up coordinates frame. + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + ROTATION_VECTOR = 11, + + /** + * RELATIVE_HUMIDITY + * reporting-mode: on-change + * + * A relative humidity sensor measures relative ambient air humidity and + * returns a value in percent. + * + * Both wake-up and non wake-up versions are useful. + */ + RELATIVE_HUMIDITY = 12, + + /** + * AMBIENT_TEMPERATURE + * reporting-mode: on-change + * + * The ambient (room) temperature in degree Celsius. + * + * Both wake-up and non wake-up versions are useful. + */ + AMBIENT_TEMPERATURE = 13, + + /** + * MAGNETIC_FIELD_UNCALIBRATED + * reporting-mode: continuous + * + * Similar to MAGNETIC_FIELD, but the hard iron calibration is + * reported separately instead of being included in the measurement. + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + MAGNETIC_FIELD_UNCALIBRATED = 14, + + /** + * GAME_ROTATION_VECTOR + * reporting-mode: continuous + * + * Similar to ROTATION_VECTOR, but not using the geomagnetic + * field. + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + GAME_ROTATION_VECTOR = 15, + + /** + * GYROSCOPE_UNCALIBRATED + * reporting-mode: continuous + * + * All values are in radians/second and measure the rate of rotation + * around the X, Y and Z axis. + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + GYROSCOPE_UNCALIBRATED = 16, + + /** + * SIGNIFICANT_MOTION + * reporting-mode: one-shot + * + * A sensor of this type triggers an event each time significant motion + * is detected and automatically disables itself. + * For Significant Motion sensor to be useful, it must be defined as a + * wake-up sensor. (set SENSOR_FLAG_WAKE_UP). Implement the wake-up + * significant motion sensor. A non wake-up version is not useful. + * The only allowed value to return is 1.0. + */ + SIGNIFICANT_MOTION = 17, + + /** + * STEP_DETECTOR + * reporting-mode: special + * + * A sensor of this type triggers an event each time a step is taken + * by the user. The only allowed value to return is 1.0 and an event + * is generated for each step. + * + * Both wake-up and non wake-up versions are useful. + */ + STEP_DETECTOR = 18, + + /** + * STEP_COUNTER + * reporting-mode: on-change + * + * A sensor of this type returns the number of steps taken by the user since + * the last reboot while activated. The value is returned as a uint64_t and + * is reset to zero only on a system / android reboot. + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + STEP_COUNTER = 19, + + /** + * GEOMAGNETIC_ROTATION_VECTOR + * reporting-mode: continuous + * + * Similar to ROTATION_VECTOR, but using a magnetometer instead + * of using a gyroscope. + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + GEOMAGNETIC_ROTATION_VECTOR = 20, + + /** + * HEART_RATE + * reporting-mode: on-change + * + * A sensor of this type returns the current heart rate. + * The events contain the current heart rate in beats per minute (BPM) and + * the status of the sensor during the measurement. See "HeartRate" below + * for more details. + * + * Because this sensor is on-change, events must be generated when and only + * when heart_rate.bpm or heart_rate.status have changed since the last + * event. In particular, upon the first activation, unless the device is + * known to not be on the body, the status field of the first event must be + * set to SensorStatus::UNRELIABLE. The event should be generated no faster + * than every period_ns passed to setDelay() or to batch(). + * See the definition of the on-change reporting mode for more information. + * + * SensorInfo.requiredPermission must be set to + * SENSOR_PERMISSION_BODY_SENSORS. + * + * Both wake-up and non wake-up versions are useful. + */ + HEART_RATE = 21, + + /** + * WAKE_UP_TILT_DETECTOR + * reporting-mode: special (setDelay has no impact) + * + * A sensor of this type generates an event each time a tilt event is + * detected. A tilt event must be generated if the direction of the + * 2-seconds window average gravity changed by at least 35 degrees since the + * activation or the last trigger of the sensor. + * + * reference_estimated_gravity = average of accelerometer measurements over + * the first 1 second after activation or the estimated gravity at the last + * trigger. + * + * current_estimated_gravity = average of accelerometer measurements over + * the last 2 seconds. + * + * trigger when + * angle(reference_estimated_gravity, current_estimated_gravity) + * > 35 degrees + * + * Large accelerations without a change in phone orientation must not + * trigger a tilt event. + * For example, a sharp turn or strong acceleration while driving a car + * must not trigger a tilt event, even though the angle of the average + * acceleration might vary by more than 35 degrees. + * + * Typically, this sensor is implemented with the help of only an + * accelerometer. Other sensors can be used as well if they do not increase + * the power consumption significantly. This is a low power sensor that + * must allow the AP to go into suspend mode. Do not emulate this sensor + * in the HAL. + * Like other wake up sensors, the driver is expected to a hold a wake_lock + * with a timeout of 200 ms while reporting this event. The only allowed + * return value is 1.0. + * + * Implement only the wake-up version of this sensor. + */ + TILT_DETECTOR = 22, + + /** + * WAKE_GESTURE + * reporting-mode: one-shot + * + * A sensor enabling waking up the device based on a device specific motion. + * + * When this sensor triggers, the device behaves as if the power button was + * pressed, turning the screen on. This behavior (turning on the screen when + * this sensor triggers) might be deactivated by the user in the device + * settings. Changes in settings do not impact the behavior of the sensor: + * only whether the framework turns the screen on when it triggers. + * + * The actual gesture to be detected is not specified, and can be chosen by + * the manufacturer of the device. + * This sensor must be low power, as it is likely to be activated 24/7. + * The only allowed value to return is 1.0. + * + * Implement only the wake-up version of this sensor. + */ + WAKE_GESTURE = 23, + + /** + * GLANCE_GESTURE + * reporting-mode: one-shot + * + * A sensor enabling briefly turning the screen on to enable the user to + * glance content on screen based on a specific motion. The device must + * turn the screen off after a few moments. + * + * When this sensor triggers, the device turns the screen on momentarily + * to allow the user to glance notifications or other content while the + * device remains locked in a non-interactive state (dozing). This behavior + * (briefly turning on the screen when this sensor triggers) might be + * deactivated by the user in the device settings. + * Changes in settings do not impact the behavior of the sensor: only + * whether the framework briefly turns the screen on when it triggers. + * + * The actual gesture to be detected is not specified, and can be chosen by + * the manufacturer of the device. + * This sensor must be low power, as it is likely to be activated 24/7. + * The only allowed value to return is 1.0. + * + * Implement only the wake-up version of this sensor. + */ + GLANCE_GESTURE = 24, + + /** + * PICK_UP_GESTURE + * reporting-mode: one-shot + * + * A sensor of this type triggers when the device is picked up regardless of + * wherever is was before (desk, pocket, bag). The only allowed return value + * is 1.0. This sensor de-activates itself immediately after it triggers. + * + * Implement only the wake-up version of this sensor. + */ + PICK_UP_GESTURE = 25, + + /** + * WRIST_TILT_GESTURE + * trigger-mode: special + * wake-up sensor: yes + * + * A sensor of this type triggers an event each time a tilt of the + * wrist-worn device is detected. + * + * This sensor must be low power, as it is likely to be activated 24/7. + * The only allowed value to return is 1.0. + * + * Implement only the wake-up version of this sensor. + */ + WRIST_TILT_GESTURE = 26, + + /** + * DEVICE_ORIENTATION + * reporting-mode: on-change + * + * The current orientation of the device. The value is reported in + * the "scalar" element of the EventPayload in Event. The + * only values that can be reported are (please refer to Android Sensor + * Coordinate System to understand the X and Y axis direction with respect + * to default orientation): + * - 0: device is in default orientation (Y axis is vertical and points up) + * - 1: device is rotated 90 degrees counter-clockwise from default + * orientation (X axis is vertical and points up) + * - 2: device is rotated 180 degrees from default orientation (Y axis is + * vertical and points down) + * - 3: device is rotated 90 degrees clockwise from default orientation + * (X axis is vertical and points down) + * + * Moving the device to an orientation where the Z axis is vertical (either + * up or down) must not cause a new event to be reported. + * + * To improve the user experience of this sensor, it is recommended to + * implement some physical (i.e., rotation angle) and temporal (i.e., delay) + * hysteresis. In other words, minor or transient rotations must not cause + * a new event to be reported. + * + * This is a low power sensor that intended to reduce interrupts of + * application processor and thus allow it to go sleep. Use hardware + * implementation based on low power consumption sensors, such as + * accelerometer. Device must not emulate this sensor in the HAL. + * + * Both wake-up and non wake-up versions are useful. + */ + DEVICE_ORIENTATION = 27, + + /** + * POSE_6DOF + * trigger-mode: continuous + * + * A sensor of this type returns the pose of the device. + * Pose of the device is defined as the orientation of the device from a + * Earth Centered Earth Fixed frame and the translation from an arbitrary + * point at subscription. + * + * This sensor can be high power. It can use any and all of the following + * . Accelerometer + * . Gyroscope + * . Camera + * . Depth Camera + * + */ + POSE_6DOF = 28, + + /** + * STATIONARY_DETECT + * trigger mode: one shot + * + * A sensor of this type returns an event if the device is still/stationary + * for a while. The period of time to monitor for stationarity must be + * greater than 5 seconds. The latency must be less than 10 seconds. + * + * Stationarity here refers to absolute stationarity. eg: device on desk. + * + * The only allowed value to return is 1.0. + */ + STATIONARY_DETECT = 29, + + /** + * MOTION_DETECT + * trigger mode: one shot + * + * A sensor of this type returns an event if the device is not still for + * for a while. The period of time to monitor for stationarity must be + * greater than 5 seconds. The latency must be less than 10 seconds. + * + * Motion here refers to any mechanism in which the device is causes to be + * moved in its inertial frame. eg: Pickin up the device and walking with it + * to a nearby room may trigger motion wherewas keeping the device on a + * table on a smooth train moving at constant velocity may not trigger + * motion. + * + * The only allowed value to return is 1.0. + */ + MOTION_DETECT = 30, + + /** + * HEART_BEAT + * trigger mode: continuous + * + * A sensor of this type returns an event everytime a hear beat peak is + * detected. + * + * Peak here ideally corresponds to the positive peak in the QRS complex of + * and ECG signal. + * + * The sensor is not expected to be optimized for latency. As a guide, a + * latency of up to 10 seconds is acceptable. However, the timestamp attached + * to the event must be accuratly correspond to the time the peak occurred. + * + * The sensor event contains a parameter for the confidence in the detection + * of the peak where 0.0 represent no information at all, and 1.0 represents + * certainty. + */ + HEART_BEAT = 31, + + /** + * DYNAMIC_SENSOR_META + * trigger-mode: special + * wake-up sensor: yes + * + * A sensor event of this type is received when a dynamic sensor is added to + * or removed from the system. At most one sensor of this type can be + * present in one sensor HAL implementation and presence of a sensor of this + * type in sensor HAL implementation indicates that this sensor HAL supports + * dynamic sensor feature. Operations, such as batch, activate and setDelay, + * to this special purpose sensor must be treated as no-op and return + * successful; flush() also has to generate flush complete event as if this + * is a sensor that does not support batching. + * + * A dynamic sensor connection indicates connection of a physical device or + * instantiation of a virtual sensor backed by algorithm; and a dynamic + * sensor disconnection indicates the opposite. A sensor event of + * DYNAMIC_SENSOR_META type should be delivered regardless of + * the activation status of the sensor in the event of dynamic sensor + * connection and disconnection. In the sensor event, besides the common + * data entries, "dynamic_sensor_meta", which includes fields for connection + * status, handle of the sensor involved, pointer to sensor_t structure and + * a uuid field, must be populated. + * + * At a dynamic sensor connection event, fields of sensor_t structure + * referenced by a pointer in dynamic_sensor_meta must be filled as if it + * was regular sensors. Sensor HAL is responsible for recovery of memory if + * the corresponding data is dynamicially allocated. However, the + * pointer must be valid until the first activate call to the sensor + * reported in this connection event. At a dynamic sensor disconnection, + * the sensor_t pointer must be NULL. + * + * The sensor handle assigned to dynamic sensors must never be the same as + * that of any regular static sensors, and must be unique until next boot. + * In another word, if a handle h is used for a dynamic sensor A, that same + * number cannot be used for the same dynamic sensor A or another dynamic + * sensor B even after disconnection of A until reboot. + * + * The UUID field will be used for identifying the sensor in addition to + * name, vendor and version and type. For physical sensors of the same + * model, all sensors will have the same values in sensor_t, but the UUID + * must be unique and persistent for each individual unit. An all zero + * UUID indicates it is not possible to differentiate individual sensor + * unit. + * + */ + DYNAMIC_SENSOR_META = 32, + + /** + * ADDITIONAL_INFO + * reporting-mode: N/A + * + * This sensor type is for delivering additional sensor information aside + * from sensor event data. + * Additional information may include sensor front-end group delay, internal + * calibration parameters, noise level metrics, device internal temperature, + * etc. + * + * This type will never bind to a sensor. In other words, no sensor in the + * sensor list can have the type SENSOR_TYPE_ADDITIONAL_INFO. If a + * sensor HAL supports sensor additional information feature, it reports + * sensor_event_t with "sensor" field set to handle of the reporting sensor + * and "type" field set to ADDITIONAL_INFO. Delivery of + * additional information events is triggered under two conditions: an + * enable activate() call or a flush() call to the corresponding sensor. + * Besides, time varying parameters can update infrequently without being + * triggered. Device is responsible to control update rate. The recommend + * update rate is less than 1/1000 of sensor event rate or less than once + * per minute in average. + * + * A single additional information report consists of multiple frames. + * Sequences of these frames are ordered using timestamps, which means the + * timestamps of sequential frames have to be at least 1 nanosecond apart + * from each other. Each frame is a sensor_event_t delivered through the HAL + * interface, with related data stored in the "additional_info" field, which + * is of type additional_info_event_t. + * The "type" field of additional_info_event_t denotes the nature of the + * payload data (see additional_info_type_t). + * The "serial" field is used to keep the sequence of payload data that + * spans multiple frames. The first frame of the entire report is always of + * type AINFO_BEGIN, and the last frame is always AINFO_END. + * + * If flush() was triggering the report, all additional information frames + * must be delivered after flush complete event. + */ + ADDITIONAL_INFO = 33, + + /** + * LOW_LATENCY_OFFBODY_DETECT + * trigger-mode: on-change + * wake-up sensor: yes + * + * A sensor of this type is defined for devices that are supposed to be worn + * by the user in the normal use case (such as a watch, wristband, etc) and + * is not yet defined for other device. + * + * A sensor of this type triggers an event each time the wearable device + * is removed from the body and each time it's put back onto the body. + * It must be low-latency and be able to detect the on-body to off-body + * transition within one second (event delivery time included), + * and 3-second latency to determine the off-body to on-body transition + * (event delivery time included). + * + * There are only two valid event values for the sensor to return : + * 0.0 for off-body + * 1.0 for on-body + * + */ + LOW_LATENCY_OFFBODY_DETECT = 34, + + /** + * ACCELEROMETER_UNCALIBRATED + * reporting-mode: continuous + * + * All values are in SI units (m/s^2) and measure the acceleration of the + * device minus the acceleration due to gravity. + * + * Implement the non-wake-up version of this sensor and implement the + * wake-up version if the system possesses a wake up fifo. + */ + ACCELEROMETER_UNCALIBRATED = 35, + + /** + * HINGE_ANGLE + * reporting-mode: on-change + * wake-up sensor: yes + * + * A sensor of this type measures the angle, in degrees, between two + * integral parts of the device. Movement of a hinge measured by this sensor + * type is expected to alter the ways in which the user may interact with + * the device, for example by unfolding or revealing a display. + * + * Sensor data is output using EventPayload.scalar. + * + * Implement wake-up proximity sensor before implementing a non wake-up + * proximity sensor. + */ + HINGE_ANGLE = 36, + + /** + * Base for device manufacturers private sensor types. + * These sensor types can't be exposed in the SDK. + */ + DEVICE_PRIVATE_BASE = 0x10000, +} diff --git a/sensors/aidl/default/Android.bp b/sensors/aidl/default/Android.bp new file mode 100644 index 0000000000..49841a456b --- /dev/null +++ b/sensors/aidl/default/Android.bp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2021 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: "libsensorsexampleimpl", + vendor: true, + shared_libs: [ + "libbase", + "libfmq", + "libpower", + "libbinder_ndk", + "android.hardware.sensors-V1-ndk", + ], + export_include_dirs: ["include"], + srcs: [ + "Sensors.cpp", + "Sensor.cpp", + ], + visibility: [ + ":__subpackages__", + "//hardware/interfaces/tests/extension/sensors:__subpackages__", + ], +} + +cc_binary { + name: "android.hardware.sensors-service.example", + relative_install_path: "hw", + init_rc: ["sensors-default.rc"], + vintf_fragments: ["sensors-default.xml"], + vendor: true, + shared_libs: [ + "libbase", + "libbinder_ndk", + "libfmq", + "libpower", + "libcutils", + "liblog", + "libutils", + "android.hardware.sensors-V1-ndk", + ], + static_libs: [ + "libsensorsexampleimpl", + ], + srcs: ["main.cpp"], +} diff --git a/sensors/aidl/default/Sensor.cpp b/sensors/aidl/default/Sensor.cpp new file mode 100644 index 0000000000..50d8841b2a --- /dev/null +++ b/sensors/aidl/default/Sensor.cpp @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2021 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 "sensors-impl/Sensor.h" + +#include "utils/SystemClock.h" + +#include <cmath> + +using ::ndk::ScopedAStatus; + +namespace aidl { +namespace android { +namespace hardware { +namespace sensors { + +static constexpr int32_t kDefaultMaxDelayUs = 10 * 1000 * 1000; + +Sensor::Sensor(ISensorsEventCallback* callback) + : mIsEnabled(false), + mSamplingPeriodNs(0), + mLastSampleTimeNs(0), + mCallback(callback), + mMode(OperationMode::NORMAL) { + mRunThread = std::thread(startThread, this); +} + +Sensor::~Sensor() { + std::unique_lock<std::mutex> lock(mRunMutex); + mStopThread = true; + mIsEnabled = false; + mWaitCV.notify_all(); + lock.release(); + mRunThread.join(); +} + +const SensorInfo& Sensor::getSensorInfo() const { + return mSensorInfo; +} + +void Sensor::batch(int64_t samplingPeriodNs) { + if (samplingPeriodNs < mSensorInfo.minDelayUs * 1000ll) { + samplingPeriodNs = mSensorInfo.minDelayUs * 1000ll; + } else if (samplingPeriodNs > mSensorInfo.maxDelayUs * 1000ll) { + samplingPeriodNs = mSensorInfo.maxDelayUs * 1000ll; + } + + if (mSamplingPeriodNs != samplingPeriodNs) { + mSamplingPeriodNs = samplingPeriodNs; + // Wake up the 'run' thread to check if a new event should be generated now + mWaitCV.notify_all(); + } +} + +void Sensor::activate(bool enable) { + if (mIsEnabled != enable) { + std::unique_lock<std::mutex> lock(mRunMutex); + mIsEnabled = enable; + mWaitCV.notify_all(); + } +} + +ScopedAStatus Sensor::flush() { + // Only generate a flush complete event if the sensor is enabled and if the sensor is not a + // one-shot sensor. + if (!mIsEnabled || + (mSensorInfo.flags & static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE))) { + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(BnSensors::ERROR_BAD_VALUE)); + } + + // Note: If a sensor supports batching, write all of the currently batched events for the sensor + // to the Event FMQ prior to writing the flush complete event. + Event ev; + ev.sensorHandle = mSensorInfo.sensorHandle; + ev.sensorType = SensorType::META_DATA; + EventPayload::MetaData meta = { + .what = MetaDataEventType::META_DATA_FLUSH_COMPLETE, + }; + ev.payload.set<EventPayload::Tag::meta>(meta); + std::vector<Event> evs{ev}; + mCallback->postEvents(evs, isWakeUpSensor()); + + return ScopedAStatus::ok(); +} + +void Sensor::startThread(Sensor* sensor) { + sensor->run(); +} + +void Sensor::run() { + std::unique_lock<std::mutex> runLock(mRunMutex); + constexpr int64_t kNanosecondsInSeconds = 1000 * 1000 * 1000; + + while (!mStopThread) { + if (!mIsEnabled || mMode == OperationMode::DATA_INJECTION) { + mWaitCV.wait(runLock, [&] { + return ((mIsEnabled && mMode == OperationMode::NORMAL) || mStopThread); + }); + } else { + timespec curTime; + clock_gettime(CLOCK_BOOTTIME, &curTime); + int64_t now = (curTime.tv_sec * kNanosecondsInSeconds) + curTime.tv_nsec; + int64_t nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs; + + if (now >= nextSampleTime) { + mLastSampleTimeNs = now; + nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs; + mCallback->postEvents(readEvents(), isWakeUpSensor()); + } + + mWaitCV.wait_for(runLock, std::chrono::nanoseconds(nextSampleTime - now)); + } + } +} + +bool Sensor::isWakeUpSensor() { + return mSensorInfo.flags & static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_WAKE_UP); +} + +std::vector<Event> Sensor::readEvents() { + std::vector<Event> events; + Event event; + event.sensorHandle = mSensorInfo.sensorHandle; + event.sensorType = mSensorInfo.type; + event.timestamp = ::android::elapsedRealtimeNano(); + memset(&event.payload, 0, sizeof(event.payload)); + readEventPayload(event.payload); + events.push_back(event); + return events; +} + +void Sensor::setOperationMode(OperationMode mode) { + if (mMode != mode) { + std::unique_lock<std::mutex> lock(mRunMutex); + mMode = mode; + mWaitCV.notify_all(); + } +} + +bool Sensor::supportsDataInjection() const { + return mSensorInfo.flags & static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION); +} + +ScopedAStatus Sensor::injectEvent(const Event& event) { + if (event.sensorType == SensorType::ADDITIONAL_INFO) { + return ScopedAStatus::ok(); + // When in OperationMode::NORMAL, SensorType::ADDITIONAL_INFO is used to push operation + // environment data into the device. + } + + if (!supportsDataInjection()) { + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + } + + if (mMode == OperationMode::DATA_INJECTION) { + mCallback->postEvents(std::vector<Event>{event}, isWakeUpSensor()); + return ScopedAStatus::ok(); + } + + return ScopedAStatus::fromServiceSpecificError( + static_cast<int32_t>(BnSensors::ERROR_BAD_VALUE)); +} + +OnChangeSensor::OnChangeSensor(ISensorsEventCallback* callback) + : Sensor(callback), mPreviousEventSet(false) {} + +void OnChangeSensor::activate(bool enable) { + Sensor::activate(enable); + if (!enable) { + mPreviousEventSet = false; + } +} + +std::vector<Event> OnChangeSensor::readEvents() { + std::vector<Event> events = Sensor::readEvents(); + std::vector<Event> outputEvents; + + for (auto iter = events.begin(); iter != events.end(); ++iter) { + Event ev = *iter; + if (!mPreviousEventSet || + memcmp(&mPreviousEvent.payload, &ev.payload, sizeof(ev.payload)) != 0) { + outputEvents.push_back(ev); + mPreviousEvent = ev; + mPreviousEventSet = true; + } + } + return outputEvents; +} + +AccelSensor::AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Accel Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::ACCELEROMETER; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 78.4f; // +/- 8g + mSensorInfo.resolution = 1.52e-5; + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelayUs = 10 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION); +}; + +void AccelSensor::readEventPayload(EventPayload& payload) { + EventPayload::Vec3 vec3 = { + .x = 0, + .y = 0, + .z = -9.8, + .status = SensorStatus::ACCURACY_HIGH, + }; + payload.set<EventPayload::Tag::vec3>(vec3); +} + +PressureSensor::PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Pressure Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::PRESSURE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 1100.0f; // hPa + mSensorInfo.resolution = 0.005f; // hPa + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelayUs = 100 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; +}; + +void PressureSensor::readEventPayload(EventPayload& payload) { + payload.set<EventPayload::Tag::scalar>(1013.25f); +} + +MagnetometerSensor::MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Magnetic Field Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::MAGNETIC_FIELD; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 1300.0f; + mSensorInfo.resolution = 0.01f; + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelayUs = 20 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; +}; + +void MagnetometerSensor::readEventPayload(EventPayload& payload) { + EventPayload::Vec3 vec3 = { + .x = 100.0, + .y = 0, + .z = 50.0, + .status = SensorStatus::ACCURACY_HIGH, + }; + payload.set<EventPayload::Tag::vec3>(vec3); +} + +LightSensor::LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Light Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::LIGHT; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 43000.0f; + mSensorInfo.resolution = 10.0f; + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelayUs = 200 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE); +}; + +void LightSensor::readEventPayload(EventPayload& payload) { + payload.set<EventPayload::Tag::scalar>(80.0f); +} + +ProximitySensor::ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Proximity Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::PROXIMITY; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 5.0f; + mSensorInfo.resolution = 1.0f; + mSensorInfo.power = 0.012f; // mA + mSensorInfo.minDelayUs = 200 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE | + SensorInfo::SENSOR_FLAG_BITS_WAKE_UP); +}; + +void ProximitySensor::readEventPayload(EventPayload& payload) { + payload.set<EventPayload::Tag::scalar>(2.5f); +} + +GyroSensor::GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Gyro Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::GYROSCOPE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 1000.0f * M_PI / 180.0f; + mSensorInfo.resolution = 1000.0f * M_PI / (180.0f * 32768.0f); + mSensorInfo.power = 0.001f; + mSensorInfo.minDelayUs = 10 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; +}; + +void GyroSensor::readEventPayload(EventPayload& payload) { + EventPayload::Vec3 vec3 = { + .x = 0, + .y = 0, + .z = 0, + .status = SensorStatus::ACCURACY_HIGH, + }; + payload.set<EventPayload::Tag::vec3>(vec3); +} + +AmbientTempSensor::AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Ambient Temp Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::AMBIENT_TEMPERATURE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 80.0f; + mSensorInfo.resolution = 0.01f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelayUs = 40 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE); +}; + +void AmbientTempSensor::readEventPayload(EventPayload& payload) { + payload.set<EventPayload::Tag::scalar>(40.0f); +} + +RelativeHumiditySensor::RelativeHumiditySensor(int32_t sensorHandle, + ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Relative Humidity Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::RELATIVE_HUMIDITY; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 100.0f; + mSensorInfo.resolution = 0.1f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelayUs = 40 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE); +} + +void RelativeHumiditySensor::readEventPayload(EventPayload& payload) { + payload.set<EventPayload::Tag::scalar>(50.0f); +} + +HingeAngleSensor::HingeAngleSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Hinge Angle Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::HINGE_ANGLE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 360.0f; + mSensorInfo.resolution = 1.0f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelayUs = 40 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE | + SensorInfo::SENSOR_FLAG_BITS_WAKE_UP | + SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION); +} + +void HingeAngleSensor::readEventPayload(EventPayload& payload) { + payload.set<EventPayload::Tag::scalar>(180.0f); +} + +} // namespace sensors +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/sensors/aidl/default/Sensors.cpp b/sensors/aidl/default/Sensors.cpp new file mode 100644 index 0000000000..65dd304b2c --- /dev/null +++ b/sensors/aidl/default/Sensors.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2021 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 "sensors-impl/Sensors.h" + +#include <aidl/android/hardware/common/fmq/SynchronizedReadWrite.h> + +using ::aidl::android::hardware::common::fmq::MQDescriptor; +using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite; +using ::aidl::android::hardware::sensors::Event; +using ::aidl::android::hardware::sensors::ISensors; +using ::aidl::android::hardware::sensors::ISensorsCallback; +using ::aidl::android::hardware::sensors::SensorInfo; +using ::ndk::ScopedAStatus; + +namespace aidl { +namespace android { +namespace hardware { +namespace sensors { + +ScopedAStatus Sensors::activate(int32_t in_sensorHandle, bool in_enabled) { + auto sensor = mSensors.find(in_sensorHandle); + if (sensor != mSensors.end()) { + sensor->second->activate(in_enabled); + return ScopedAStatus::ok(); + } + + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); +} + +ScopedAStatus Sensors::batch(int32_t in_sensorHandle, int64_t in_samplingPeriodNs, + int64_t /* in_maxReportLatencyNs */) { + auto sensor = mSensors.find(in_sensorHandle); + if (sensor != mSensors.end()) { + sensor->second->batch(in_samplingPeriodNs); + return ScopedAStatus::ok(); + } + + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); +} + +ScopedAStatus Sensors::configDirectReport(int32_t /* in_sensorHandle */, + int32_t /* in_channelHandle */, + ISensors::RateLevel /* in_rate */, + int32_t* _aidl_return) { + *_aidl_return = EX_UNSUPPORTED_OPERATION; + + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + +ScopedAStatus Sensors::flush(int32_t in_sensorHandle) { + auto sensor = mSensors.find(in_sensorHandle); + if (sensor != mSensors.end()) { + return sensor->second->flush(); + } + + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); +} + +ScopedAStatus Sensors::getSensorsList(std::vector<SensorInfo>* _aidl_return) { + for (const auto& sensor : mSensors) { + _aidl_return->push_back(sensor.second->getSensorInfo()); + } + return ScopedAStatus::ok(); +} + +ScopedAStatus Sensors::initialize( + const MQDescriptor<Event, SynchronizedReadWrite>& in_eventQueueDescriptor, + const MQDescriptor<int32_t, SynchronizedReadWrite>& in_wakeLockDescriptor, + const std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback>& + in_sensorsCallback) { + ScopedAStatus result = ScopedAStatus::ok(); + + mEventQueue = std::make_unique<AidlMessageQueue<Event, SynchronizedReadWrite>>( + in_eventQueueDescriptor, true /* resetPointers */); + + // Ensure that all sensors are disabled. + for (auto sensor : mSensors) { + sensor.second->activate(false); + } + + // Stop the Wake Lock thread if it is currently running + if (mReadWakeLockQueueRun.load()) { + mReadWakeLockQueueRun = false; + mWakeLockThread.join(); + } + + // Save a reference to the callback + mCallback = in_sensorsCallback; + + // Ensure that any existing EventFlag is properly deleted + deleteEventFlag(); + + // Create the EventFlag that is used to signal to the framework that sensor events have been + // written to the Event FMQ + if (EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag) != OK) { + result = ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + // Create the Wake Lock FMQ that is used by the framework to communicate whenever WAKE_UP + // events have been successfully read and handled by the framework. + mWakeLockQueue = std::make_unique<AidlMessageQueue<int32_t, SynchronizedReadWrite>>( + in_wakeLockDescriptor, true /* resetPointers */); + + if (!mCallback || !mEventQueue || !mWakeLockQueue || mEventQueueFlag == nullptr) { + result = ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + // Start the thread to read events from the Wake Lock FMQ + mReadWakeLockQueueRun = true; + mWakeLockThread = std::thread(startReadWakeLockThread, this); + return result; +} + +ScopedAStatus Sensors::injectSensorData(const Event& in_event) { + auto sensor = mSensors.find(in_event.sensorHandle); + if (sensor != mSensors.end()) { + return sensor->second->injectEvent(in_event); + } + return ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(ERROR_BAD_VALUE)); +} + +ScopedAStatus Sensors::registerDirectChannel(const ISensors::SharedMemInfo& /* in_mem */, + int32_t* _aidl_return) { + *_aidl_return = EX_UNSUPPORTED_OPERATION; + + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + +ScopedAStatus Sensors::setOperationMode(OperationMode in_mode) { + for (auto sensor : mSensors) { + sensor.second->setOperationMode(in_mode); + } + return ScopedAStatus::ok(); +} + +ScopedAStatus Sensors::unregisterDirectChannel(int32_t /* in_channelHandle */) { + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + +} // namespace sensors +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/sensors/aidl/default/include/sensors-impl/Sensor.h b/sensors/aidl/default/include/sensors-impl/Sensor.h new file mode 100644 index 0000000000..e6cd3e6970 --- /dev/null +++ b/sensors/aidl/default/include/sensors-impl/Sensor.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2021 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 <thread> + +#include <aidl/android/hardware/sensors/BnSensors.h> + +namespace aidl { +namespace android { +namespace hardware { +namespace sensors { + +class ISensorsEventCallback { + public: + using Event = ::aidl::android::hardware::sensors::Event; + + virtual ~ISensorsEventCallback(){}; + virtual void postEvents(const std::vector<Event>& events, bool wakeup) = 0; +}; + +class Sensor { + public: + using OperationMode = ::aidl::android::hardware::sensors::ISensors::OperationMode; + using Event = ::aidl::android::hardware::sensors::Event; + using EventPayload = ::aidl::android::hardware::sensors::Event::EventPayload; + using SensorInfo = ::aidl::android::hardware::sensors::SensorInfo; + using SensorType = ::aidl::android::hardware::sensors::SensorType; + using MetaDataEventType = + ::aidl::android::hardware::sensors::Event::EventPayload::MetaData::MetaDataEventType; + + Sensor(ISensorsEventCallback* callback); + virtual ~Sensor(); + + const SensorInfo& getSensorInfo() const; + void batch(int64_t samplingPeriodNs); + virtual void activate(bool enable); + ndk::ScopedAStatus flush(); + + void setOperationMode(OperationMode mode); + bool supportsDataInjection() const; + ndk::ScopedAStatus injectEvent(const Event& event); + + protected: + void run(); + virtual std::vector<Event> readEvents(); + virtual void readEventPayload(EventPayload&) = 0; + static void startThread(Sensor* sensor); + + bool isWakeUpSensor(); + + bool mIsEnabled; + int64_t mSamplingPeriodNs; + int64_t mLastSampleTimeNs; + SensorInfo mSensorInfo; + + std::atomic_bool mStopThread; + std::condition_variable mWaitCV; + std::mutex mRunMutex; + std::thread mRunThread; + + ISensorsEventCallback* mCallback; + + OperationMode mMode; +}; + +class OnChangeSensor : public Sensor { + public: + OnChangeSensor(ISensorsEventCallback* callback); + + virtual void activate(bool enable) override; + + protected: + virtual std::vector<Event> readEvents() override; + + protected: + Event mPreviousEvent; + bool mPreviousEventSet; +}; + +class AccelSensor : public Sensor { + public: + AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class GyroSensor : public Sensor { + public: + GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class AmbientTempSensor : public OnChangeSensor { + public: + AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class PressureSensor : public Sensor { + public: + PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class MagnetometerSensor : public Sensor { + public: + MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class LightSensor : public OnChangeSensor { + public: + LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class ProximitySensor : public OnChangeSensor { + public: + ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class RelativeHumiditySensor : public OnChangeSensor { + public: + RelativeHumiditySensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class HingeAngleSensor : public OnChangeSensor { + public: + HingeAngleSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +} // namespace sensors +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/sensors/aidl/default/include/sensors-impl/Sensors.h b/sensors/aidl/default/include/sensors-impl/Sensors.h new file mode 100644 index 0000000000..e270d9682e --- /dev/null +++ b/sensors/aidl/default/include/sensors-impl/Sensors.h @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2021 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 <aidl/android/hardware/common/fmq/SynchronizedReadWrite.h> +#include <aidl/android/hardware/sensors/BnSensors.h> +#include <fmq/AidlMessageQueue.h> +#include <hardware_legacy/power.h> +#include <map> +#include "Sensor.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace sensors { + +using aidl::android::hardware::common::fmq::SynchronizedReadWrite; +using ::android::AidlMessageQueue; +using ::android::OK; +using ::android::status_t; +using ::android::hardware::EventFlag; + +class Sensors : public BnSensors, public ISensorsEventCallback { + static constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP"; + + public: + Sensors() + : mEventQueueFlag(nullptr), + mNextHandle(1), + mOutstandingWakeUpEvents(0), + mReadWakeLockQueueRun(false), + mAutoReleaseWakeLockTime(0), + mHasWakeLock(false) { + AddSensor<AccelSensor>(); + AddSensor<GyroSensor>(); + AddSensor<AmbientTempSensor>(); + AddSensor<PressureSensor>(); + AddSensor<MagnetometerSensor>(); + AddSensor<LightSensor>(); + AddSensor<ProximitySensor>(); + AddSensor<RelativeHumiditySensor>(); + AddSensor<HingeAngleSensor>(); + } + + virtual ~Sensors() { + deleteEventFlag(); + mReadWakeLockQueueRun = false; + mWakeLockThread.join(); + } + + ::ndk::ScopedAStatus activate(int32_t in_sensorHandle, bool in_enabled) override; + ::ndk::ScopedAStatus batch(int32_t in_sensorHandle, int64_t in_samplingPeriodNs, + int64_t in_maxReportLatencyNs) override; + ::ndk::ScopedAStatus configDirectReport( + int32_t in_sensorHandle, int32_t in_channelHandle, + ::aidl::android::hardware::sensors::ISensors::RateLevel in_rate, + int32_t* _aidl_return) override; + ::ndk::ScopedAStatus flush(int32_t in_sensorHandle) override; + ::ndk::ScopedAStatus getSensorsList( + std::vector<::aidl::android::hardware::sensors::SensorInfo>* _aidl_return) override; + ::ndk::ScopedAStatus initialize( + const ::aidl::android::hardware::common::fmq::MQDescriptor< + ::aidl::android::hardware::sensors::Event, + ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>& + in_eventQueueDescriptor, + const ::aidl::android::hardware::common::fmq::MQDescriptor< + int32_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>& + in_wakeLockDescriptor, + const std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback>& + in_sensorsCallback) override; + ::ndk::ScopedAStatus injectSensorData( + const ::aidl::android::hardware::sensors::Event& in_event) override; + ::ndk::ScopedAStatus registerDirectChannel( + const ::aidl::android::hardware::sensors::ISensors::SharedMemInfo& in_mem, + int32_t* _aidl_return) override; + ::ndk::ScopedAStatus setOperationMode( + ::aidl::android::hardware::sensors::ISensors::OperationMode in_mode) override; + ::ndk::ScopedAStatus unregisterDirectChannel(int32_t in_channelHandle) override; + + void postEvents(const std::vector<Event>& events, bool wakeup) override { + std::lock_guard<std::mutex> lock(mWriteLock); + if (mEventQueue == nullptr) { + return; + } + if (mEventQueue->write(&events.front(), events.size())) { + mEventQueueFlag->wake( + static_cast<uint32_t>(BnSensors::EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS)); + + if (wakeup) { + // Keep track of the number of outstanding WAKE_UP events in order to properly hold + // a wake lock until the framework has secured a wake lock + updateWakeLock(events.size(), 0 /* eventsHandled */); + } + } + } + + protected: + // Add a new sensor + template <class SensorType> + void AddSensor() { + std::shared_ptr<SensorType> sensor = + std::make_shared<SensorType>(mNextHandle++ /* sensorHandle */, this /* callback */); + mSensors[sensor->getSensorInfo().sensorHandle] = sensor; + } + + // Utility function to delete the Event Flag + void deleteEventFlag() { + if (mEventQueueFlag != nullptr) { + status_t status = EventFlag::deleteEventFlag(&mEventQueueFlag); + if (status != OK) { + ALOGI("Failed to delete event flag: %d", status); + } + } + } + + static void startReadWakeLockThread(Sensors* sensors) { sensors->readWakeLockFMQ(); } + + // Function to read the Wake Lock FMQ and release the wake lock when appropriate + void readWakeLockFMQ() { + while (mReadWakeLockQueueRun.load()) { + constexpr int64_t kReadTimeoutNs = 500 * 1000 * 1000; // 500 ms + int32_t eventsHandled = 0; + + // Read events from the Wake Lock FMQ. Timeout after a reasonable amount of time to + // ensure that any held wake lock is able to be released if it is held for too long. + mWakeLockQueue->readBlocking( + &eventsHandled, 1 /* count */, 0 /* readNotification */, + static_cast<uint32_t>(WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN), kReadTimeoutNs); + updateWakeLock(0 /* eventsWritten */, eventsHandled); + } + } + + /** + * Responsible for acquiring and releasing a wake lock when there are unhandled WAKE_UP events + */ + void updateWakeLock(int32_t eventsWritten, int32_t eventsHandled) { + std::lock_guard<std::mutex> lock(mWakeLockLock); + int32_t newVal = mOutstandingWakeUpEvents + eventsWritten - eventsHandled; + if (newVal < 0) { + mOutstandingWakeUpEvents = 0; + } else { + mOutstandingWakeUpEvents = newVal; + } + + if (eventsWritten > 0) { + // Update the time at which the last WAKE_UP event was sent + mAutoReleaseWakeLockTime = ::android::uptimeMillis() + + static_cast<uint32_t>(WAKE_LOCK_TIMEOUT_SECONDS) * 1000; + } + + if (!mHasWakeLock && mOutstandingWakeUpEvents > 0 && + acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName) == 0) { + mHasWakeLock = true; + } else if (mHasWakeLock) { + // Check if the wake lock should be released automatically if + // SensorTimeout::WAKE_LOCK_SECONDS has elapsed since the last WAKE_UP event was written + // to the Wake Lock FMQ. + if (::android::uptimeMillis() > mAutoReleaseWakeLockTime) { + ALOGD("No events read from wake lock FMQ for %d seconds, auto releasing wake lock", + WAKE_LOCK_TIMEOUT_SECONDS); + mOutstandingWakeUpEvents = 0; + } + + if (mOutstandingWakeUpEvents == 0 && release_wake_lock(kWakeLockName) == 0) { + mHasWakeLock = false; + } + } + } + + private: + // The Event FMQ where sensor events are written + std::unique_ptr<AidlMessageQueue<Event, SynchronizedReadWrite>> mEventQueue; + // The Wake Lock FMQ that is read to determine when the framework has handled WAKE_UP events + std::unique_ptr<AidlMessageQueue<int32_t, SynchronizedReadWrite>> mWakeLockQueue; + // Event Flag to signal to the framework when sensor events are available to be read + EventFlag* mEventQueueFlag; + // Callback for asynchronous events, such as dynamic sensor connections. + std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback> mCallback; + // A map of the available sensors. + std::map<int32_t, std::shared_ptr<Sensor>> mSensors; + // The next available sensor handle. + int32_t mNextHandle; + // Lock to protect writes to the FMQs. + std::mutex mWriteLock; + // Lock to protect acquiring and releasing the wake lock + std::mutex mWakeLockLock; + // Track the number of WAKE_UP events that have not been handled by the framework + uint32_t mOutstandingWakeUpEvents; + // A thread to read the Wake Lock FMQ + std::thread mWakeLockThread; + // Flag to indicate that the Wake Lock Thread should continue to run + std::atomic_bool mReadWakeLockQueueRun; + // Track the time when the wake lock should automatically be released + int64_t mAutoReleaseWakeLockTime; + // Flag to indicate if a wake lock has been acquired + bool mHasWakeLock; +}; + +} // namespace sensors +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/sensors/aidl/default/main.cpp b/sensors/aidl/default/main.cpp new file mode 100644 index 0000000000..8a5a7de124 --- /dev/null +++ b/sensors/aidl/default/main.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 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 "sensors-impl/Sensors.h" + +#include <android-base/logging.h> +#include <android/binder_manager.h> +#include <android/binder_process.h> + +using aidl::android::hardware::sensors::Sensors; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(0); + + // Make a default sensors service + auto sensor = ndk::SharedRefBase::make<Sensors>(); + const std::string sensorName = std::string() + Sensors::descriptor + "/default"; + binder_status_t status = + AServiceManager_addService(sensor->asBinder().get(), sensorName.c_str()); + CHECK_EQ(status, STATUS_OK); + + ABinderProcess_joinThreadPool(); + return EXIT_FAILURE; // should not reach +} diff --git a/sensors/aidl/default/sensors-default.rc b/sensors/aidl/default/sensors-default.rc new file mode 100644 index 0000000000..96da85dc29 --- /dev/null +++ b/sensors/aidl/default/sensors-default.rc @@ -0,0 +1,5 @@ +service vendor.sensors-default /vendor/bin/hw/android.hardware.sensors-service.example + class hal + user system + group system + rlimit rtprio 10 10 diff --git a/sensors/aidl/default/sensors-default.xml b/sensors/aidl/default/sensors-default.xml new file mode 100644 index 0000000000..7898a6bab0 --- /dev/null +++ b/sensors/aidl/default/sensors-default.xml @@ -0,0 +1,7 @@ +<manifest version="1.0" type="device"> + <hal format="aidl"> + <name>android.hardware.sensors</name> + <version>1</version> + <fqname>ISensors/default</fqname> + </hal> +</manifest> diff --git a/sensors/aidl/vts/Android.bp b/sensors/aidl/vts/Android.bp new file mode 100644 index 0000000000..5a519a5a1e --- /dev/null +++ b/sensors/aidl/vts/Android.bp @@ -0,0 +1,49 @@ +// Copyright 2021 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_test { + name: "VtsAidlHalSensorsTargetTest", + defaults: [ + "VtsHalTargetTestDefaults", + "use_libaidlvintf_gtest_helper_static", + ], + srcs: [ + "VtsAidlHalSensorsTargetTest.cpp", + "SensorsAidlEnvironment.cpp", + ], + shared_libs: [ + "libbinder", + "libbinder_ndk", + "libfmq", + "android.hardware.common-V2-ndk", + "android.hardware.common.fmq-V1-ndk", + ], + static_libs: [ + "android.hardware.sensors-V1-ndk", + "VtsHalSensorsTargetTestUtils", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/sensors/aidl/vts/OWNERS b/sensors/aidl/vts/OWNERS new file mode 100644 index 0000000000..90c233030e --- /dev/null +++ b/sensors/aidl/vts/OWNERS @@ -0,0 +1,3 @@ +arthuri@google.com +bduddie@google.com +stange@google.com diff --git a/sensors/aidl/vts/SensorsAidlEnvironment.cpp b/sensors/aidl/vts/SensorsAidlEnvironment.cpp new file mode 100644 index 0000000000..e71251f698 --- /dev/null +++ b/sensors/aidl/vts/SensorsAidlEnvironment.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2021 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 "SensorsAidlEnvironment.h" + +#include <android/binder_manager.h> +#include <log/log.h> + +#include <aidl/android/hardware/sensors/BnSensorsCallback.h> + +using aidl::android::hardware::sensors::BnSensorsCallback; +using aidl::android::hardware::sensors::SensorInfo; +using android::hardware::EventFlag; +using ndk::ScopedAStatus; +using ndk::SpAIBinder; + +namespace { + +void serviceDied(void* /* cookie */) { + ALOGE("Sensors HAL died (likely crashed) during test"); + FAIL() << "Sensors HAL died during test"; +} + +class NoOpSensorsCallback : public BnSensorsCallback { + public: + ScopedAStatus onDynamicSensorsConnected( + const std::vector<SensorInfo>& /* sensorInfos */) override { + return ScopedAStatus::ok(); + } + + ScopedAStatus onDynamicSensorsDisconnected( + const std::vector<int32_t>& /* sensorHandles */) override { + return ScopedAStatus::ok(); + } +}; + +} // anonymous namespace + +SensorsAidlEnvironment::SensorsAidlEnvironment(const std::string& service_name) + : SensorsVtsEnvironmentBase(service_name), + mCallback(ndk::SharedRefBase::make<NoOpSensorsCallback>()), + mDeathRecipient(AIBinder_DeathRecipient_new(serviceDied)) {} + +bool SensorsAidlEnvironment::resetHal() { + bool succeed = false; + do { + mSensors = ISensors::fromBinder( + SpAIBinder(AServiceManager_waitForService(mServiceName.c_str()))); + if (mSensors == nullptr) { + break; + } + + AIBinder_linkToDeath(mSensors->asBinder().get(), mDeathRecipient.get(), this); + + // Initialize FMQs + mWakeLockQueue = std::make_unique<WakeLockQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT, + true /* configureEventFlagWord */); + mEventQueue = std::make_unique<EventQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT, + true /* configureEventFlagWord */); + + if (mWakeLockQueue == nullptr || mEventQueue == nullptr) { + break; + } + + EventFlag::deleteEventFlag(&mEventQueueFlag); + EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag); + if (mEventQueueFlag == nullptr) { + break; + } + + mSensors->initialize(mEventQueue->dupeDesc(), mWakeLockQueue->dupeDesc(), mCallback); + + std::vector<SensorInfo> sensorList; + if (!mSensors->getSensorsList(&sensorList).isOk()) { + break; + } + + // stop each sensor individually + bool ok = true; + for (const auto& i : sensorList) { + if (!mSensors->activate(i.sensorHandle, false).isOk()) { + ok = false; + break; + } + } + + if (!ok) { + break; + } + + // mark it done + succeed = true; + } while (0); + + if (!succeed) { + mSensors = nullptr; + } + + return succeed; +} + +void SensorsAidlEnvironment::TearDown() { + mStopThread = true; + + if (mEventQueueFlag != nullptr) { + // Wake up the event queue so the poll thread can exit + mEventQueueFlag->wake(ISensors::EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS); + if (mPollThread.joinable()) { + mPollThread.join(); + } + + EventFlag::deleteEventFlag(&mEventQueueFlag); + } +} + +void SensorsAidlEnvironment::startPollingThread() { + mStopThread = false; + mEvents.reserve(MAX_RECEIVE_BUFFER_EVENT_COUNT); + mPollThread = std::thread(pollingThread, this); +} + +void SensorsAidlEnvironment::readEvents() { + size_t availableEvents = mEventQueue->availableToRead(); + + if (availableEvents == 0) { + uint32_t eventFlagState = 0; + + mEventQueueFlag->wait(ISensors::EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS, &eventFlagState); + availableEvents = mEventQueue->availableToRead(); + } + + size_t eventsToRead = std::min(availableEvents, mEventBuffer.size()); + if (eventsToRead > 0) { + if (mEventQueue->read(mEventBuffer.data(), eventsToRead)) { + mEventQueueFlag->wake(ISensors::EVENT_QUEUE_FLAG_BITS_EVENTS_READ); + for (size_t i = 0; i < eventsToRead; i++) { + addEvent(mEventBuffer[i]); + } + } + } +} + +void SensorsAidlEnvironment::pollingThread(SensorsAidlEnvironment* env) { + ALOGD("polling thread start"); + + while (!env->mStopThread.load()) { + env->readEvents(); + } + + ALOGD("polling thread end"); +} diff --git a/sensors/aidl/vts/SensorsAidlEnvironment.h b/sensors/aidl/vts/SensorsAidlEnvironment.h new file mode 100644 index 0000000000..2f5f28712b --- /dev/null +++ b/sensors/aidl/vts/SensorsAidlEnvironment.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2021 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_SENSORS_AIDL_ENVIRONMENT_H +#define ANDROID_SENSORS_AIDL_ENVIRONMENT_H + +#include "sensors-vts-utils/SensorsVtsEnvironmentBase.h" + +#include <atomic> +#include <memory> +#include <mutex> +#include <thread> +#include <vector> + +#include <aidl/android/hardware/sensors/ISensors.h> +#include <fmq/AidlMessageQueue.h> + +using aidl::android::hardware::common::fmq::SynchronizedReadWrite; +using aidl::android::hardware::sensors::Event; +using aidl::android::hardware::sensors::ISensors; +using aidl::android::hardware::sensors::ISensorsCallback; + +static constexpr size_t MAX_RECEIVE_BUFFER_EVENT_COUNT = 256; + +class SensorsAidlTest; + +class SensorsAidlEnvironment : public SensorsVtsEnvironmentBase<Event> { + public: + virtual void TearDown() override; + + protected: + friend SensorsAidlTest; + SensorsAidlEnvironment(const std::string& service_name); + + /** + * Resets the HAL with new FMQs and a new Event Flag + * + * @return bool true if successful, false otherwise + */ + bool resetHal() override; + + /** + * Starts the polling thread that reads sensor events from the Event FMQ + */ + void startPollingThread() override; + + /** + * Thread responsible for calling functions to read Event FMQ + * + * @param env SensorEnvironment to being polling for events on + */ + static void pollingThread(SensorsAidlEnvironment* env); + + /** + * Reads and saves sensor events from the Event FMQ + */ + void readEvents(); + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsAidlEnvironment); + + /** + * Pointer to the Sensors HAL Interface that allows the test to call HAL functions. + */ + std::shared_ptr<ISensors> mSensors; + std::shared_ptr<ISensorsCallback> mCallback; + + ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; + + /** + * Type used to simplify the creation of the Wake Lock FMQ + */ + typedef android::AidlMessageQueue<int32_t, SynchronizedReadWrite> WakeLockQueue; + typedef android::AidlMessageQueue<Event, SynchronizedReadWrite> EventQueue; + + /** + * The Wake Lock FMQ is used by the test to notify the Sensors HAL whenever it has processed + * WAKE_UP sensor events. + */ + std::unique_ptr<WakeLockQueue> mWakeLockQueue; + std::unique_ptr<EventQueue> mEventQueue; + + /** + * The Event Queue Flag notifies the test framework when sensor events have been written to the + * Event FMQ by the Sensors HAL. + */ + ::android::hardware::EventFlag* mEventQueueFlag; + + std::atomic_bool mStopThread; + std::thread mPollThread; + + /** + * An array that is used to store sensor events read from the Event FMQ + */ + std::array<Event, MAX_RECEIVE_BUFFER_EVENT_COUNT> mEventBuffer; +}; + +#endif // ANDROID_SENSORS_AIDL_ENVIRONMENT_H diff --git a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp new file mode 100644 index 0000000000..33645b2a95 --- /dev/null +++ b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp @@ -0,0 +1,871 @@ +/* + * Copyright (C) 2021 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/Gtest.h> +#include <aidl/Vintf.h> + +#include <aidl/android/hardware/sensors/BnSensors.h> +#include <aidl/android/hardware/sensors/ISensors.h> +#include <android/binder_manager.h> +#include <binder/IServiceManager.h> +#include <binder/ProcessState.h> +#include <hardware/sensors.h> +#include <log/log.h> +#include <utils/SystemClock.h> + +#include "SensorsAidlEnvironment.h" +#include "sensors-vts-utils/SensorsVtsEnvironmentBase.h" + +#include <cinttypes> +#include <condition_variable> +#include <map> +#include <unordered_map> +#include <unordered_set> +#include <vector> + +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; +using android::ProcessState; +using std::chrono::duration_cast; + +namespace { + +static void assertTypeMatchStringType(SensorType type, const std::string& stringType) { + if (type >= SensorType::DEVICE_PRIVATE_BASE) { + return; + } + + switch (type) { +#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \ + case SensorType::type: \ + ASSERT_STREQ(SENSOR_STRING_TYPE_##type, stringType.c_str()); \ + break; + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE); + default: + FAIL() << "Type " << static_cast<int>(type) + << " in android defined range is not checked, " + << "stringType = " << stringType; +#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE + } +} + +int expectedReportModeForType(SensorType type) { + switch (type) { + case SensorType::ACCELEROMETER: + case SensorType::ACCELEROMETER_UNCALIBRATED: + case SensorType::GYROSCOPE: + case SensorType::MAGNETIC_FIELD: + case SensorType::ORIENTATION: + case SensorType::PRESSURE: + case SensorType::GRAVITY: + case SensorType::LINEAR_ACCELERATION: + case SensorType::ROTATION_VECTOR: + case SensorType::MAGNETIC_FIELD_UNCALIBRATED: + case SensorType::GAME_ROTATION_VECTOR: + case SensorType::GYROSCOPE_UNCALIBRATED: + case SensorType::GEOMAGNETIC_ROTATION_VECTOR: + case SensorType::POSE_6DOF: + case SensorType::HEART_BEAT: + return SensorInfo::SENSOR_FLAG_BITS_CONTINUOUS_MODE; + + case SensorType::LIGHT: + case SensorType::PROXIMITY: + case SensorType::RELATIVE_HUMIDITY: + case SensorType::AMBIENT_TEMPERATURE: + case SensorType::HEART_RATE: + case SensorType::DEVICE_ORIENTATION: + case SensorType::STEP_COUNTER: + case SensorType::LOW_LATENCY_OFFBODY_DETECT: + return SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE; + + case SensorType::SIGNIFICANT_MOTION: + case SensorType::WAKE_GESTURE: + case SensorType::GLANCE_GESTURE: + case SensorType::PICK_UP_GESTURE: + case SensorType::MOTION_DETECT: + case SensorType::STATIONARY_DETECT: + return SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE; + + case SensorType::STEP_DETECTOR: + case SensorType::TILT_DETECTOR: + case SensorType::WRIST_TILT_GESTURE: + case SensorType::DYNAMIC_SENSOR_META: + return SensorInfo::SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE; + + default: + ALOGW("Type %d is not implemented in expectedReportModeForType", (int)type); + return INT32_MAX; + } +} + +void assertTypeMatchReportMode(SensorType type, int reportMode) { + if (type >= SensorType::DEVICE_PRIVATE_BASE) { + return; + } + + int expected = expectedReportModeForType(type); + + ASSERT_TRUE(expected == INT32_MAX || expected == reportMode) + << "reportMode=" << static_cast<int>(reportMode) + << "expected=" << static_cast<int>(expected); +} + +void assertDelayMatchReportMode(int32_t minDelayUs, int32_t maxDelayUs, int reportMode) { + switch (reportMode) { + case SensorInfo::SENSOR_FLAG_BITS_CONTINUOUS_MODE: + ASSERT_LT(0, minDelayUs); + ASSERT_LE(0, maxDelayUs); + break; + case SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE: + ASSERT_LE(0, minDelayUs); + ASSERT_LE(0, maxDelayUs); + break; + case SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE: + ASSERT_EQ(-1, minDelayUs); + ASSERT_EQ(0, maxDelayUs); + break; + case SensorInfo::SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE: + // do not enforce anything for special reporting mode + break; + default: + FAIL() << "Report mode " << static_cast<int>(reportMode) << " not checked"; + } +} + +void checkIsOk(ndk::ScopedAStatus status) { + ASSERT_TRUE(status.isOk()); +} + +} // namespace + +class EventCallback : public IEventCallback<Event> { + public: + void reset() { + mFlushMap.clear(); + mEventMap.clear(); + } + + void onEvent(const Event& event) override { + if (event.sensorType == SensorType::META_DATA && + event.payload.get<Event::EventPayload::Tag::meta>().what == + Event::EventPayload::MetaData::MetaDataEventType::META_DATA_FLUSH_COMPLETE) { + std::unique_lock<std::recursive_mutex> lock(mFlushMutex); + mFlushMap[event.sensorHandle]++; + mFlushCV.notify_all(); + } else if (event.sensorType != SensorType::ADDITIONAL_INFO) { + std::unique_lock<std::recursive_mutex> lock(mEventMutex); + mEventMap[event.sensorHandle].push_back(event); + mEventCV.notify_all(); + } + } + + int32_t getFlushCount(int32_t sensorHandle) { + std::unique_lock<std::recursive_mutex> lock(mFlushMutex); + return mFlushMap[sensorHandle]; + } + + void waitForFlushEvents(const std::vector<SensorInfo>& sensorsToWaitFor, + int32_t numCallsToFlush, std::chrono::milliseconds timeout) { + std::unique_lock<std::recursive_mutex> lock(mFlushMutex); + mFlushCV.wait_for(lock, timeout, + [&] { return flushesReceived(sensorsToWaitFor, numCallsToFlush); }); + } + + const std::vector<Event> getEvents(int32_t sensorHandle) { + std::unique_lock<std::recursive_mutex> lock(mEventMutex); + return mEventMap[sensorHandle]; + } + + void waitForEvents(const std::vector<SensorInfo>& sensorsToWaitFor, + std::chrono::milliseconds timeout) { + std::unique_lock<std::recursive_mutex> lock(mEventMutex); + mEventCV.wait_for(lock, timeout, [&] { return eventsReceived(sensorsToWaitFor); }); + } + + protected: + bool flushesReceived(const std::vector<SensorInfo>& sensorsToWaitFor, int32_t numCallsToFlush) { + for (const SensorInfo& sensor : sensorsToWaitFor) { + if (getFlushCount(sensor.sensorHandle) < numCallsToFlush) { + return false; + } + } + return true; + } + + bool eventsReceived(const std::vector<SensorInfo>& sensorsToWaitFor) { + for (const SensorInfo& sensor : sensorsToWaitFor) { + if (getEvents(sensor.sensorHandle).size() == 0) { + return false; + } + } + return true; + } + + std::map<int32_t, int32_t> mFlushMap; + std::recursive_mutex mFlushMutex; + std::condition_variable_any mFlushCV; + + std::map<int32_t, std::vector<Event>> mEventMap; + std::recursive_mutex mEventMutex; + std::condition_variable_any mEventCV; +}; + +class SensorsAidlTest : public testing::TestWithParam<std::string> { + public: + virtual void SetUp() override { + mEnvironment = new SensorsAidlEnvironment(GetParam()); + mEnvironment->SetUp(); + + // Ensure that we have a valid environment before performing tests + ASSERT_NE(getSensors(), nullptr); + } + + virtual void TearDown() override { + for (int32_t handle : mSensorHandles) { + activate(handle, false); + } + mSensorHandles.clear(); + + mEnvironment->TearDown(); + delete mEnvironment; + mEnvironment = nullptr; + } + + protected: + std::vector<SensorInfo> getNonOneShotSensors(); + std::vector<SensorInfo> getNonOneShotAndNonSpecialSensors(); + std::vector<SensorInfo> getNonOneShotAndNonOnChangeAndNonSpecialSensors(); + std::vector<SensorInfo> getOneShotSensors(); + std::vector<SensorInfo> getInjectEventSensors(); + + inline std::shared_ptr<ISensors>& getSensors() { return mEnvironment->mSensors; } + + inline SensorsAidlEnvironment* getEnvironment() { return mEnvironment; } + + inline bool isValidType(SensorType sensorType) { return (int)sensorType > 0; } + + std::vector<SensorInfo> getSensorsList(); + + int32_t getInvalidSensorHandle() { + // Find a sensor handle that does not exist in the sensor list + int32_t maxHandle = 0; + for (const SensorInfo& sensor : getSensorsList()) { + maxHandle = std::max(maxHandle, sensor.sensorHandle); + } + return maxHandle + 1; + } + + ndk::ScopedAStatus activate(int32_t sensorHandle, bool enable); + void activateAllSensors(bool enable); + + ndk::ScopedAStatus batch(int32_t sensorHandle, int64_t samplingPeriodNs, + int64_t maxReportLatencyNs) { + return getSensors()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs); + } + + ndk::ScopedAStatus flush(int32_t sensorHandle) { return getSensors()->flush(sensorHandle); } + + void runSingleFlushTest(const std::vector<SensorInfo>& sensors, bool activateSensor, + int32_t expectedFlushCount, bool expectedResult); + + void runFlushTest(const std::vector<SensorInfo>& sensors, bool activateSensor, + int32_t flushCalls, int32_t expectedFlushCount, bool expectedResult); + + inline static int32_t extractReportMode(int32_t flag) { + return (flag & (SensorInfo::SENSOR_FLAG_BITS_CONTINUOUS_MODE | + SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE | + SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE | + SensorInfo::SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE)); + } + + // All sensors and direct channnels used + std::unordered_set<int32_t> mSensorHandles; + std::unordered_set<int32_t> mDirectChannelHandles; + + private: + SensorsAidlEnvironment* mEnvironment; +}; + +std::vector<SensorInfo> SensorsAidlTest::getSensorsList() { + std::vector<SensorInfo> sensorInfoList; + checkIsOk(getSensors()->getSensorsList(&sensorInfoList)); + return sensorInfoList; +} + +ndk::ScopedAStatus SensorsAidlTest::activate(int32_t sensorHandle, bool enable) { + // If activating a sensor, add the handle in a set so that when test fails it can be turned off. + // The handle is not removed when it is deactivating on purpose so that it is not necessary to + // check the return value of deactivation. Deactivating a sensor more than once does not have + // negative effect. + if (enable) { + mSensorHandles.insert(sensorHandle); + } + return getSensors()->activate(sensorHandle, enable); +} + +void SensorsAidlTest::activateAllSensors(bool enable) { + for (const SensorInfo& sensorInfo : getSensorsList()) { + if (isValidType(sensorInfo.type)) { + checkIsOk(batch(sensorInfo.sensorHandle, sensorInfo.minDelayUs, + 0 /* maxReportLatencyNs */)); + checkIsOk(activate(sensorInfo.sensorHandle, enable)); + } + } +} + +std::vector<SensorInfo> SensorsAidlTest::getNonOneShotSensors() { + std::vector<SensorInfo> sensors; + for (const SensorInfo& info : getSensorsList()) { + if (extractReportMode(info.flags) != SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE) { + sensors.push_back(info); + } + } + return sensors; +} + +std::vector<SensorInfo> SensorsAidlTest::getNonOneShotAndNonSpecialSensors() { + std::vector<SensorInfo> sensors; + for (const SensorInfo& info : getSensorsList()) { + int reportMode = extractReportMode(info.flags); + if (reportMode != SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE && + reportMode != SensorInfo::SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE) { + sensors.push_back(info); + } + } + return sensors; +} + +std::vector<SensorInfo> SensorsAidlTest::getNonOneShotAndNonOnChangeAndNonSpecialSensors() { + std::vector<SensorInfo> sensors; + for (const SensorInfo& info : getSensorsList()) { + int reportMode = extractReportMode(info.flags); + if (reportMode != SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE && + reportMode != SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE && + reportMode != SensorInfo::SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE) { + sensors.push_back(info); + } + } + return sensors; +} + +std::vector<SensorInfo> SensorsAidlTest::getOneShotSensors() { + std::vector<SensorInfo> sensors; + for (const SensorInfo& info : getSensorsList()) { + if (extractReportMode(info.flags) == SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE) { + sensors.push_back(info); + } + } + return sensors; +} + +std::vector<SensorInfo> SensorsAidlTest::getInjectEventSensors() { + std::vector<SensorInfo> out; + std::vector<SensorInfo> sensorInfoList = getSensorsList(); + for (const SensorInfo& info : sensorInfoList) { + if (info.flags & SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION) { + out.push_back(info); + } + } + return out; +} + +void SensorsAidlTest::runSingleFlushTest(const std::vector<SensorInfo>& sensors, + bool activateSensor, int32_t expectedFlushCount, + bool expectedResult) { + runFlushTest(sensors, activateSensor, 1 /* flushCalls */, expectedFlushCount, expectedResult); +} + +void SensorsAidlTest::runFlushTest(const std::vector<SensorInfo>& sensors, bool activateSensor, + int32_t flushCalls, int32_t expectedFlushCount, + bool expectedResult) { + EventCallback callback; + getEnvironment()->registerCallback(&callback); + + for (const SensorInfo& sensor : sensors) { + // Configure and activate the sensor + batch(sensor.sensorHandle, sensor.maxDelayUs, 0 /* maxReportLatencyNs */); + activate(sensor.sensorHandle, activateSensor); + + // Flush the sensor + for (int32_t i = 0; i < flushCalls; i++) { + SCOPED_TRACE(::testing::Message() + << "Flush " << i << "/" << flushCalls << ": " + << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') + << sensor.sensorHandle << std::dec + << " type=" << static_cast<int>(sensor.type) << " name=" << sensor.name); + + EXPECT_EQ(flush(sensor.sensorHandle).isOk(), expectedResult); + } + } + + // Wait up to one second for the flush events + callback.waitForFlushEvents(sensors, flushCalls, std::chrono::milliseconds(1000) /* timeout */); + + // Deactivate all sensors after waiting for flush events so pending flush events are not + // abandoned by the HAL. + for (const SensorInfo& sensor : sensors) { + activate(sensor.sensorHandle, false); + } + getEnvironment()->unregisterCallback(); + + // Check that the correct number of flushes are present for each sensor + for (const SensorInfo& sensor : sensors) { + SCOPED_TRACE(::testing::Message() + << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') + << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type) + << " name=" << sensor.name); + ASSERT_EQ(callback.getFlushCount(sensor.sensorHandle), expectedFlushCount); + } +} + +TEST_P(SensorsAidlTest, SensorListValid) { + std::vector<SensorInfo> sensorInfoList = getSensorsList(); + std::unordered_map<int32_t, std::vector<std::string>> sensorTypeNameMap; + for (size_t i = 0; i < sensorInfoList.size(); ++i) { + const SensorInfo& info = sensorInfoList[i]; + SCOPED_TRACE(::testing::Message() + << i << "/" << sensorInfoList.size() << ": " + << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') + << info.sensorHandle << std::dec << " type=" << static_cast<int>(info.type) + << " name=" << info.name); + + // Test type string non-empty only for private sensor typeinfo. + if (info.type >= SensorType::DEVICE_PRIVATE_BASE) { + EXPECT_FALSE(info.typeAsString.empty()); + } else if (!info.typeAsString.empty()) { + // Test type string matches framework string if specified for non-private typeinfo. + EXPECT_NO_FATAL_FAILURE(assertTypeMatchStringType(info.type, info.typeAsString)); + } + + // Test if all sensor has name and vendor + EXPECT_FALSE(info.name.empty()); + EXPECT_FALSE(info.vendor.empty()); + + // Make sure that sensors of the same type have a unique name. + std::vector<std::string>& v = sensorTypeNameMap[static_cast<int32_t>(info.type)]; + bool isUniqueName = std::find(v.begin(), v.end(), info.name) == v.end(); + EXPECT_TRUE(isUniqueName) << "Duplicate sensor Name: " << info.name; + if (isUniqueName) { + v.push_back(info.name); + } + + EXPECT_LE(0, info.power); + EXPECT_LT(0, info.maxRange); + + // Info type, should have no sensor + EXPECT_FALSE(info.type == SensorType::ADDITIONAL_INFO || + info.type == SensorType::META_DATA); + + EXPECT_GE(info.fifoMaxEventCount, info.fifoReservedEventCount); + + // Test Reporting mode valid + EXPECT_NO_FATAL_FAILURE( + assertTypeMatchReportMode(info.type, extractReportMode(info.flags))); + + // Test min max are in the right order + EXPECT_LE(info.minDelayUs, info.maxDelayUs); + // Test min/max delay matches reporting mode + EXPECT_NO_FATAL_FAILURE(assertDelayMatchReportMode(info.minDelayUs, info.maxDelayUs, + extractReportMode(info.flags))); + } +} + +TEST_P(SensorsAidlTest, SetOperationMode) { + if (getInjectEventSensors().size() > 0) { + ASSERT_TRUE(getSensors()->setOperationMode(ISensors::OperationMode::NORMAL).isOk()); + ASSERT_TRUE(getSensors()->setOperationMode(ISensors::OperationMode::DATA_INJECTION).isOk()); + ASSERT_TRUE(getSensors()->setOperationMode(ISensors::OperationMode::NORMAL).isOk()); + } else { + ASSERT_EQ(getSensors() + ->setOperationMode(ISensors::OperationMode::DATA_INJECTION) + .getExceptionCode(), + EX_UNSUPPORTED_OPERATION); + } +} + +TEST_P(SensorsAidlTest, InjectSensorEventData) { + std::vector<SensorInfo> sensors = getInjectEventSensors(); + if (sensors.size() == 0) { + return; + } + + ASSERT_TRUE(getSensors()->setOperationMode(ISensors::OperationMode::DATA_INJECTION).isOk()); + + EventCallback callback; + getEnvironment()->registerCallback(&callback); + + // AdditionalInfo event should not be sent to Event FMQ + Event additionalInfoEvent; + additionalInfoEvent.sensorType = SensorType::ADDITIONAL_INFO; + additionalInfoEvent.timestamp = android::elapsedRealtimeNano(); + + Event injectedEvent; + injectedEvent.timestamp = android::elapsedRealtimeNano(); + Event::EventPayload::Vec3 data = {1, 2, 3, SensorStatus::ACCURACY_HIGH}; + injectedEvent.payload.set<Event::EventPayload::Tag::vec3>(data); + + for (const auto& s : sensors) { + additionalInfoEvent.sensorHandle = s.sensorHandle; + ASSERT_TRUE(getSensors()->injectSensorData(additionalInfoEvent).isOk()); + + injectedEvent.sensorType = s.type; + injectedEvent.sensorHandle = s.sensorHandle; + ASSERT_TRUE(getSensors()->injectSensorData(injectedEvent).isOk()); + } + + // Wait for events to be written back to the Event FMQ + callback.waitForEvents(sensors, std::chrono::milliseconds(1000) /* timeout */); + getEnvironment()->unregisterCallback(); + + for (const auto& s : sensors) { + auto events = callback.getEvents(s.sensorHandle); + if (events.empty()) { + FAIL() << "Received no events"; + } else { + auto lastEvent = events.back(); + SCOPED_TRACE(::testing::Message() + << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') + << s.sensorHandle << std::dec << " type=" << static_cast<int>(s.type) + << " name=" << s.name); + + // Verify that only a single event has been received + ASSERT_EQ(events.size(), 1); + + // Verify that the event received matches the event injected and is not the additional + // info event + ASSERT_EQ(lastEvent.sensorType, s.type); + ASSERT_EQ(lastEvent.timestamp, injectedEvent.timestamp); + ASSERT_EQ(lastEvent.payload.get<Event::EventPayload::Tag::vec3>().x, + injectedEvent.payload.get<Event::EventPayload::Tag::vec3>().x); + ASSERT_EQ(lastEvent.payload.get<Event::EventPayload::Tag::vec3>().y, + injectedEvent.payload.get<Event::EventPayload::Tag::vec3>().y); + ASSERT_EQ(lastEvent.payload.get<Event::EventPayload::Tag::vec3>().z, + injectedEvent.payload.get<Event::EventPayload::Tag::vec3>().z); + ASSERT_EQ(lastEvent.payload.get<Event::EventPayload::Tag::vec3>().status, + injectedEvent.payload.get<Event::EventPayload::Tag::vec3>().status); + } + } + + ASSERT_TRUE(getSensors()->setOperationMode(ISensors::OperationMode::NORMAL).isOk()); +} + +TEST_P(SensorsAidlTest, CallInitializeTwice) { + // Create a helper class so that a second environment is able to be instantiated + class SensorsAidlEnvironmentTest : public SensorsAidlEnvironment { + public: + SensorsAidlEnvironmentTest(const std::string& service_name) + : SensorsAidlEnvironment(service_name) {} + }; + + if (getSensorsList().size() == 0) { + // No sensors + return; + } + + constexpr useconds_t kCollectionTimeoutUs = 1000 * 1000; // 1s + constexpr int32_t kNumEvents = 1; + + // Create a new environment that calls initialize() + std::unique_ptr<SensorsAidlEnvironmentTest> newEnv = + std::make_unique<SensorsAidlEnvironmentTest>(GetParam()); + newEnv->SetUp(); + if (HasFatalFailure()) { + return; // Exit early if setting up the new environment failed + } + + activateAllSensors(true); + // Verify that the old environment does not receive any events + EXPECT_EQ(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), 0); + // Verify that the new event queue receives sensor events + EXPECT_GE(newEnv.get()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents); + activateAllSensors(false); + + // Cleanup the test environment + newEnv->TearDown(); + + // Restore the test environment for future tests + getEnvironment()->TearDown(); + getEnvironment()->SetUp(); + if (HasFatalFailure()) { + return; // Exit early if resetting the environment failed + } + + // Ensure that the original environment is receiving events + activateAllSensors(true); + EXPECT_GE(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents); + activateAllSensors(false); +} + +TEST_P(SensorsAidlTest, CleanupConnectionsOnInitialize) { + activateAllSensors(true); + + // Verify that events are received + constexpr useconds_t kCollectionTimeoutUs = 1000 * 1000; // 1s + constexpr int32_t kNumEvents = 1; + ASSERT_GE(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents); + + // Clear the active sensor handles so they are not disabled during TearDown + auto handles = mSensorHandles; + mSensorHandles.clear(); + getEnvironment()->TearDown(); + getEnvironment()->SetUp(); + if (HasFatalFailure()) { + return; // Exit early if resetting the environment failed + } + + // Verify no events are received until sensors are re-activated + ASSERT_EQ(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), 0); + activateAllSensors(true); + ASSERT_GE(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents); + + // Disable sensors + activateAllSensors(false); + + // Restore active sensors prior to clearing the environment + mSensorHandles = handles; +} + +TEST_P(SensorsAidlTest, FlushSensor) { + std::vector<SensorInfo> sensors = getNonOneShotSensors(); + if (sensors.size() == 0) { + return; + } + + constexpr int32_t kFlushes = 5; + runSingleFlushTest(sensors, true /* activateSensor */, 1 /* expectedFlushCount */, + true /* expectedResult */); + runFlushTest(sensors, true /* activateSensor */, kFlushes, kFlushes, true /* expectedResult */); +} + +TEST_P(SensorsAidlTest, FlushOneShotSensor) { + // Find a sensor that is a one-shot sensor + std::vector<SensorInfo> sensors = getOneShotSensors(); + if (sensors.size() == 0) { + return; + } + + runSingleFlushTest(sensors, true /* activateSensor */, 0 /* expectedFlushCount */, + false /* expectedResult */); +} + +TEST_P(SensorsAidlTest, FlushInactiveSensor) { + // Attempt to find a non-one shot sensor, then a one-shot sensor if necessary + std::vector<SensorInfo> sensors = getNonOneShotSensors(); + if (sensors.size() == 0) { + sensors = getOneShotSensors(); + if (sensors.size() == 0) { + return; + } + } + + runSingleFlushTest(sensors, false /* activateSensor */, 0 /* expectedFlushCount */, + false /* expectedResult */); +} + +TEST_P(SensorsAidlTest, Batch) { + if (getSensorsList().size() == 0) { + return; + } + + activateAllSensors(false /* enable */); + for (const SensorInfo& sensor : getSensorsList()) { + SCOPED_TRACE(::testing::Message() + << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') + << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type) + << " name=" << sensor.name); + + // Call batch on inactive sensor + // One shot sensors have minDelay set to -1 which is an invalid + // parameter. Use 0 instead to avoid errors. + int64_t samplingPeriodNs = + extractReportMode(sensor.flags) == SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE + ? 0 + : sensor.minDelayUs; + checkIsOk(batch(sensor.sensorHandle, samplingPeriodNs, 0 /* maxReportLatencyNs */)); + + // Activate the sensor + activate(sensor.sensorHandle, true /* enabled */); + + // Call batch on an active sensor + checkIsOk(batch(sensor.sensorHandle, sensor.maxDelayUs, 0 /* maxReportLatencyNs */)); + } + activateAllSensors(false /* enable */); + + // Call batch on an invalid sensor + SensorInfo sensor = getSensorsList().front(); + sensor.sensorHandle = getInvalidSensorHandle(); + ASSERT_EQ(batch(sensor.sensorHandle, sensor.minDelayUs, 0 /* maxReportLatencyNs */) + .getExceptionCode(), + EX_ILLEGAL_ARGUMENT); +} + +TEST_P(SensorsAidlTest, Activate) { + if (getSensorsList().size() == 0) { + return; + } + + // Verify that sensor events are generated when activate is called + for (const SensorInfo& sensor : getSensorsList()) { + SCOPED_TRACE(::testing::Message() + << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') + << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type) + << " name=" << sensor.name); + + checkIsOk(batch(sensor.sensorHandle, sensor.minDelayUs, 0 /* maxReportLatencyNs */)); + checkIsOk(activate(sensor.sensorHandle, true)); + + // Call activate on a sensor that is already activated + checkIsOk(activate(sensor.sensorHandle, true)); + + // Deactivate the sensor + checkIsOk(activate(sensor.sensorHandle, false)); + + // Call deactivate on a sensor that is already deactivated + checkIsOk(activate(sensor.sensorHandle, false)); + } + + // Attempt to activate an invalid sensor + int32_t invalidHandle = getInvalidSensorHandle(); + ASSERT_EQ(activate(invalidHandle, true).getExceptionCode(), EX_ILLEGAL_ARGUMENT); + ASSERT_EQ(activate(invalidHandle, false).getExceptionCode(), EX_ILLEGAL_ARGUMENT); +} + +TEST_P(SensorsAidlTest, NoStaleEvents) { + constexpr std::chrono::milliseconds kFiveHundredMs(500); + constexpr std::chrono::milliseconds kOneSecond(1000); + + // Register the callback to receive sensor events + EventCallback callback; + getEnvironment()->registerCallback(&callback); + + // This test is not valid for one-shot, on-change or special-report-mode sensors + const std::vector<SensorInfo> sensors = getNonOneShotAndNonOnChangeAndNonSpecialSensors(); + std::chrono::milliseconds maxMinDelay(0); + for (const SensorInfo& sensor : sensors) { + std::chrono::milliseconds minDelay = duration_cast<std::chrono::milliseconds>( + std::chrono::microseconds(sensor.minDelayUs)); + maxMinDelay = std::chrono::milliseconds(std::max(maxMinDelay.count(), minDelay.count())); + } + + // Activate the sensors so that they start generating events + activateAllSensors(true); + + // According to the CDD, the first sample must be generated within 400ms + 2 * sample_time + // and the maximum reporting latency is 100ms + 2 * sample_time. Wait a sufficient amount + // of time to guarantee that a sample has arrived. + callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay)); + activateAllSensors(false); + + // Save the last received event for each sensor + std::map<int32_t, int64_t> lastEventTimestampMap; + for (const SensorInfo& sensor : sensors) { + SCOPED_TRACE(::testing::Message() + << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') + << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type) + << " name=" << sensor.name); + + if (callback.getEvents(sensor.sensorHandle).size() >= 1) { + lastEventTimestampMap[sensor.sensorHandle] = + callback.getEvents(sensor.sensorHandle).back().timestamp; + } + } + + // Allow some time to pass, reset the callback, then reactivate the sensors + usleep(duration_cast<std::chrono::microseconds>(kOneSecond + (5 * maxMinDelay)).count()); + callback.reset(); + activateAllSensors(true); + callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay)); + activateAllSensors(false); + + getEnvironment()->unregisterCallback(); + + for (const SensorInfo& sensor : sensors) { + SCOPED_TRACE(::testing::Message() + << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') + << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type) + << " name=" << sensor.name); + + // Skip sensors that did not previously report an event + if (lastEventTimestampMap.find(sensor.sensorHandle) == lastEventTimestampMap.end()) { + continue; + } + + // Ensure that the first event received is not stale by ensuring that its timestamp is + // sufficiently different from the previous event + const Event newEvent = callback.getEvents(sensor.sensorHandle).front(); + std::chrono::milliseconds delta = + duration_cast<std::chrono::milliseconds>(std::chrono::nanoseconds( + newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle])); + std::chrono::milliseconds sensorMinDelay = duration_cast<std::chrono::milliseconds>( + std::chrono::microseconds(sensor.minDelayUs)); + ASSERT_GE(delta, kFiveHundredMs + (3 * sensorMinDelay)); + } +} + +TEST_P(SensorsAidlTest, DirectChannelAshmem) { + // TODO(b/195593357): Implement this +} + +TEST_P(SensorsAidlTest, DirectChannelGralloc) { + // TODO(b/195593357): Implement this +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SensorsAidlTest); +INSTANTIATE_TEST_SUITE_P(Sensors, SensorsAidlTest, + testing::ValuesIn(android::getAidlHalInstanceNames(ISensors::descriptor)), + android::PrintInstanceNameToString); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ProcessState::self()->setThreadPoolMaxThreadCount(1); + ProcessState::self()->startThreadPool(); + return RUN_ALL_TESTS(); +} |