health/2.1/default/Android.bp: Reformat with bpfmt -s -w am: ce06c8ba6f am: 8d43de4cdb
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/3188339
Change-Id: Ic422926b594b41ac99f0e3ed7b25e60437f86e5e
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/automotive/TEST_MAPPING b/automotive/TEST_MAPPING
index c64c880..483a85f 100644
--- a/automotive/TEST_MAPPING
+++ b/automotive/TEST_MAPPING
@@ -19,10 +19,58 @@
"name": "CtsCarBuiltinApiHostTestCases"
},
{
- "name": "CarServiceTest"
+ "name": "CarServiceAudioTest"
+ },
+ {
+ "name": "CarServiceCarTest"
+ },
+ {
+ "name": "CarServiceClusterTest"
+ },
+ {
+ "name": "CarServiceDiagnosticTest"
+ },
+ {
+ "name": "CarServiceDrivingStateTest"
+ },
+ {
+ "name": "CarServiceEvsTest"
+ },
+ {
+ "name": "CarServiceGarageModeTest"
+ },
+ {
+ "name": "CarServiceInputTest"
+ },
+ {
+ "name": "CarServiceOsTest"
+ },
+ {
+ "name": "CarServicePmTest"
+ },
+ {
+ "name": "CarServicePowerTest"
+ },
+ {
+ "name": "CarServicePropertyTest"
+ },
+ {
+ "name": "CarServiceRemoteAccessTest"
+ },
+ {
+ "name": "CarServiceStorageMonitoringTest"
+ },
+ {
+ "name": "CarServiceTelemetryTest"
},
{
"name": "CarServiceUnitTest"
+ },
+ {
+ "name": "CarServiceVmsTest"
+ },
+ {
+ "name": "CarServiceWatchdogTest"
}
]
}
\ No newline at end of file
diff --git a/automotive/evs/aidl/Android.bp b/automotive/evs/aidl/Android.bp
index dfb15c6..5b2f82f 100644
--- a/automotive/evs/aidl/Android.bp
+++ b/automotive/evs/aidl/Android.bp
@@ -44,6 +44,9 @@
ndk: {
min_sdk_version: "29",
},
+ rust: {
+ enabled: true,
+ },
},
versions_with_info: [
{
diff --git a/automotive/evs/aidl/impl/default/manifest_evs-default-service.xml b/automotive/evs/aidl/impl/default/manifest_evs-default-service.xml
index 50692f7..9ddc6ad 100644
--- a/automotive/evs/aidl/impl/default/manifest_evs-default-service.xml
+++ b/automotive/evs/aidl/impl/default/manifest_evs-default-service.xml
@@ -2,6 +2,6 @@
<hal format="aidl">
<name>android.hardware.automotive.evs</name>
<fqname>IEvsEnumerator/hw/0</fqname>
- <version>1</version>
+ <version>2</version>
</hal>
</manifest>
diff --git a/automotive/evs/aidl/rust_impl/Android.bp b/automotive/evs/aidl/rust_impl/Android.bp
new file mode 100644
index 0000000..ac8b90f
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/Android.bp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+rust_binary {
+ name: "android.hardware.automotive.evs-aidl-rust-service",
+ relative_install_path: "hw",
+ vendor: true,
+ srcs: ["src/*.rs"],
+ crate_root: "src/main.rs",
+ vintf_fragments: ["manifest_evs-rust-service.xml"],
+ init_rc: ["evs-rust-service.rc"],
+ rustlibs: [
+ "android.hardware.automotive.evs-V2-rust",
+ "libbinder_rs",
+ "liblog_rust",
+ ],
+}
diff --git a/automotive/evs/aidl/rust_impl/README.md b/automotive/evs/aidl/rust_impl/README.md
new file mode 100644
index 0000000..bf00aed
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/README.md
@@ -0,0 +1,21 @@
+# Rust Skeleton EVS HAL implementation.
+
+WARNING: This is not a reference EVS HAL implementation and therefore does not
+provide any actual functionality.
+
+This folder contains a skeleton EVS HAL implementation in Rust to demonstrate
+how vendors could implement their EVS HAL in Rust. To compile and run this
+implementation, please include below package to the device build script:
+
+* `android.hardware.automotive.evs-aidl-rust-service`
+
+Please note that this service will attempt to register the service as
+`IEvsEnumerator/rust/0` and therefore is also required to be declared in the
+service context by adding below line to a proper `service_contexts` file:
+
+> android.hardware.automotive.evs.IEvsEnumerator/rust/0 u:object_r:hal_evs_service:s0
+
+This implementation intentionally returns `binder::StatusCode::UNKNOWN_ERROR`
+for any API call except deprecated API for ultrasonics; the process will be
+panicked on these methods instead. Hence, this implementation does not comply
+with VTS tests and vendors must replace each method with actual implementation.
diff --git a/automotive/evs/aidl/rust_impl/evs-rust-service.rc b/automotive/evs/aidl/rust_impl/evs-rust-service.rc
new file mode 100644
index 0000000..3741b21
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/evs-rust-service.rc
@@ -0,0 +1,8 @@
+service vendor.evs-hal-rust-default /vendor/bin/hw/android.hardware.automotive.evs-aidl-rust-service
+ class early_hal
+ priority -20
+ user graphics
+ group automotive_evs camera
+ onrestart restart cardisplayproxyd
+ onrestart restart evsmanagerd
+ disabled
diff --git a/automotive/evs/aidl/rust_impl/manifest_evs-rust-service.xml b/automotive/evs/aidl/rust_impl/manifest_evs-rust-service.xml
new file mode 100644
index 0000000..813cbb2
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/manifest_evs-rust-service.xml
@@ -0,0 +1,7 @@
+<manifest version="2.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.automotive.evs</name>
+ <version>2</version>
+ <fqname>IEvsEnumerator/rust/0</fqname>
+ </hal>
+</manifest>
diff --git a/automotive/evs/aidl/rust_impl/src/default_evs_hal.rs b/automotive/evs/aidl/rust_impl/src/default_evs_hal.rs
new file mode 100644
index 0000000..72b2d53
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/src/default_evs_hal.rs
@@ -0,0 +1,113 @@
+//
+// Copyright (C) 2024 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.
+//
+
+use android_hardware_automotive_evs::aidl::android::hardware::automotive::evs::{
+ CameraDesc::CameraDesc, DisplayState::DisplayState, IEvsCamera::IEvsCamera,
+ IEvsDisplay::IEvsDisplay, IEvsEnumerator::IEvsEnumerator,
+ IEvsEnumeratorStatusCallback::IEvsEnumeratorStatusCallback,
+ IEvsUltrasonicsArray::IEvsUltrasonicsArray, Stream::Stream,
+ UltrasonicsArrayDesc::UltrasonicsArrayDesc,
+};
+
+pub struct DefaultEvsHal {}
+
+impl binder::Interface for DefaultEvsHal {}
+
+impl IEvsEnumerator for DefaultEvsHal {
+ fn closeCamera(
+ &self,
+ _: &binder::Strong<(dyn IEvsCamera + 'static)>,
+ ) -> std::result::Result<(), binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn closeDisplay(
+ &self,
+ _: &binder::Strong<(dyn IEvsDisplay + 'static)>,
+ ) -> std::result::Result<(), binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn closeUltrasonicsArray(
+ &self,
+ _: &binder::Strong<(dyn IEvsUltrasonicsArray + 'static)>,
+ ) -> std::result::Result<(), binder::Status> {
+ unimplemented!()
+ }
+
+ fn getCameraList(&self) -> std::result::Result<std::vec::Vec<CameraDesc>, binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn getDisplayIdList(&self) -> std::result::Result<std::vec::Vec<u8>, binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn getDisplayState(&self) -> std::result::Result<DisplayState, binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn getStreamList(
+ &self,
+ _: &CameraDesc,
+ ) -> std::result::Result<std::vec::Vec<Stream>, binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn getUltrasonicsArrayList(
+ &self,
+ ) -> std::result::Result<std::vec::Vec<UltrasonicsArrayDesc>, binder::Status> {
+ unimplemented!()
+ }
+
+ fn isHardware(&self) -> std::result::Result<bool, binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn openCamera(
+ &self,
+ _: &str,
+ _: &Stream,
+ ) -> std::result::Result<binder::Strong<(dyn IEvsCamera + 'static)>, binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn openDisplay(
+ &self,
+ _: i32,
+ ) -> std::result::Result<binder::Strong<(dyn IEvsDisplay + 'static)>, binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn openUltrasonicsArray(
+ &self,
+ _: &str,
+ ) -> std::result::Result<binder::Strong<(dyn IEvsUltrasonicsArray + 'static)>, binder::Status>
+ {
+ unimplemented!()
+ }
+
+ fn registerStatusCallback(
+ &self,
+ _: &binder::Strong<(dyn IEvsEnumeratorStatusCallback + 'static)>,
+ ) -> std::result::Result<(), binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn getDisplayStateById(&self, _: i32) -> std::result::Result<DisplayState, binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+}
diff --git a/automotive/evs/aidl/rust_impl/src/main.rs b/automotive/evs/aidl/rust_impl/src/main.rs
new file mode 100644
index 0000000..df312c0
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/src/main.rs
@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2024 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.
+//
+
+mod default_evs_hal;
+
+use crate::default_evs_hal::DefaultEvsHal;
+
+use android_hardware_automotive_evs::aidl::android::hardware::automotive::evs::IEvsEnumerator::BnEvsEnumerator;
+
+use log::info;
+
+fn main() {
+ binder::ProcessState::start_thread_pool();
+
+ let service = DefaultEvsHal {};
+
+ // Register HAL implementation as rust/0 instance.
+ let service_name = "android.hardware.automotive.evs.IEvsEnumerator/rust/0";
+ let service_binder = BnEvsEnumerator::new_binder(service, binder::BinderFeatures::default());
+
+ binder::add_service(service_name, service_binder.as_binder())
+ .expect(format!("Failed to register {}.", service_name).as_str());
+ info!("EVS Hardware Enumerator is ready");
+
+ binder::ProcessState::join_thread_pool();
+
+ // In normal operation, we don't expect the thread pool to exit.
+ info!("EVS Hardware Enumerator is shutting down");
+}
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
index 73bb521..201ddb0 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
@@ -83,6 +83,17 @@
return configs;
}
+std::optional<aidlvhal::VehiclePropConfig> GRPCVehicleHardware::getPropertyConfig(
+ int32_t propId) const {
+ // TODO(b/354055835): Use GRPC call to get one config instead of getting all the configs.
+ for (const auto& config : getAllPropertyConfigs()) {
+ if (config.prop == propId) {
+ return config;
+ }
+ }
+ return std::nullopt;
+}
+
aidlvhal::StatusCode GRPCVehicleHardware::setValues(
std::shared_ptr<const SetValuesCallback> callback,
const std::vector<aidlvhal::SetValueRequest>& requests) {
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
index 1edf658..15f473c 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
@@ -50,6 +50,10 @@
// Get all the property configs.
std::vector<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const override;
+ // Get the config for the specified propId.
+ std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+ getPropertyConfig(int32_t propId) const override;
+
// Set property values asynchronously. Server could return before the property set requests
// are sent to vehicle bus or before property set confirmation is received. The callback is
// safe to be called after the function returns and is safe to be called in a different thread.
diff --git a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
index f49d91b..0684655 100644
--- a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
@@ -20,6 +20,7 @@
#include <VehicleHalTypes.h>
#include <memory>
+#include <optional>
#include <vector>
namespace android {
@@ -46,33 +47,53 @@
int32_t areaId;
};
+namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
+
// An abstract interface to access vehicle hardware.
// For virtualized VHAL, GrpcVehicleHardware would communicate with a VehicleHardware
// implementation in another VM through GRPC. For non-virtualzied VHAL, VHAL directly communicates
// with a VehicleHardware through this interface.
class IVehicleHardware {
public:
- using SetValuesCallback = std::function<void(
- std::vector<aidl::android::hardware::automotive::vehicle::SetValueResult>)>;
- using GetValuesCallback = std::function<void(
- std::vector<aidl::android::hardware::automotive::vehicle::GetValueResult>)>;
- using PropertyChangeCallback = std::function<void(
- std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>)>;
+ using SetValuesCallback = std::function<void(std::vector<aidlvhal::SetValueResult>)>;
+ using GetValuesCallback = std::function<void(std::vector<aidlvhal::GetValueResult>)>;
+ using PropertyChangeCallback = std::function<void(std::vector<aidlvhal::VehiclePropValue>)>;
using PropertySetErrorCallback = std::function<void(std::vector<SetValueErrorEvent>)>;
virtual ~IVehicleHardware() = default;
// Get all the property configs.
- virtual std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
- getAllPropertyConfigs() const = 0;
+ virtual std::vector<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const = 0;
+
+ // Get the property configs for the specified propId. This is used for early-boot
+ // native VHAL clients to access certain property configs when not all property configs are
+ // available. For example, a config discovery process might be required to determine the
+ // property config for HVAC. However, for early boot properties, e.g. VHAL_HEARTBEAT, it
+ // could return before the config discovery process.
+ //
+ // Currently Android system may try to access the following properties during early boot:
+ // STORAGE_ENCRYPTION_BINDING_SEED, WATCHDOG_ALIVE, WATCHDOG_TERMINATE_PROCESS, VHAL_HEARTBEAT,
+ // CURRENT_POWER_POLICY, POWER_POLICY_REQ, POWER_POLICY_GROUP_REQ. They should return
+ // quickly otherwise the whole bootup process might be blocked.
+ virtual std::optional<aidlvhal::VehiclePropConfig> getPropertyConfig(int32_t propId) const {
+ // The default implementation is to use getAllPropertyConfigs(). This should be
+ // overridden if getAllPropertyConfigs() takes a while to return for initial boot or
+ // relies on ethernet or other communication channel that is not available during early
+ // boot.
+ for (const auto& config : getAllPropertyConfigs()) {
+ if (config.prop == propId) {
+ return config;
+ }
+ }
+ return std::nullopt;
+ }
// Set property values asynchronously. Server could return before the property set requests
// are sent to vehicle bus or before property set confirmation is received. The callback is
// safe to be called after the function returns and is safe to be called in a different thread.
- virtual aidl::android::hardware::automotive::vehicle::StatusCode setValues(
+ virtual aidlvhal::StatusCode setValues(
std::shared_ptr<const SetValuesCallback> callback,
- const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
- requests) = 0;
+ const std::vector<aidlvhal::SetValueRequest>& requests) = 0;
// Get property values asynchronously. Server could return before the property values are ready.
// The callback is safe to be called after the function returns and is safe to be called in a
@@ -86,7 +107,7 @@
virtual DumpResult dump(const std::vector<std::string>& options) = 0;
// Check whether the system is healthy, return {@code StatusCode::OK} for healthy.
- virtual aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() = 0;
+ virtual aidlvhal::StatusCode checkHealth() = 0;
// Register a callback that would be called when there is a property change event from vehicle.
// This function must only be called once during initialization.
@@ -179,16 +200,14 @@
// 5. The second subscriber is removed, 'unsubscribe' is called.
// The impl can optionally disable the polling for vehicle speed.
//
- virtual aidl::android::hardware::automotive::vehicle::StatusCode subscribe(
- [[maybe_unused]] aidl::android::hardware::automotive::vehicle::SubscribeOptions
- options) {
- return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+ virtual aidlvhal::StatusCode subscribe([[maybe_unused]] aidlvhal::SubscribeOptions options) {
+ return aidlvhal::StatusCode::OK;
}
// A [propId, areaId] is unsubscribed. This applies for both continuous or on-change property.
- virtual aidl::android::hardware::automotive::vehicle::StatusCode unsubscribe(
- [[maybe_unused]] int32_t propId, [[maybe_unused]] int32_t areaId) {
- return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+ virtual aidlvhal::StatusCode unsubscribe([[maybe_unused]] int32_t propId,
+ [[maybe_unused]] int32_t areaId) {
+ return aidlvhal::StatusCode::OK;
}
// This function is deprecated, subscribe/unsubscribe should be used instead.
@@ -216,10 +235,10 @@
//
// If the impl is always polling at {@code maxSampleRate} as specified in config, then this
// function can be a no-op.
- virtual aidl::android::hardware::automotive::vehicle::StatusCode updateSampleRate(
- [[maybe_unused]] int32_t propId, [[maybe_unused]] int32_t areaId,
- [[maybe_unused]] float sampleRate) {
- return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+ virtual aidlvhal::StatusCode updateSampleRate([[maybe_unused]] int32_t propId,
+ [[maybe_unused]] int32_t areaId,
+ [[maybe_unused]] float sampleRate) {
+ return aidlvhal::StatusCode::OK;
}
};
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index fa2a310..932a2e2 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -31,6 +31,7 @@
#include <android-base/thread_annotations.h>
#include <android/binder_auto_utils.h>
+#include <functional>
#include <memory>
#include <mutex>
#include <shared_mutex>
@@ -138,12 +139,11 @@
// Only used for testing.
int32_t mTestInterfaceVersion = 0;
- // mConfigsByPropId and mConfigFile is lazy initialized.
- mutable std::mutex mConfigInitLock;
- mutable bool mConfigInit GUARDED_BY(mConfigInitLock) = false;
+ mutable std::atomic<bool> mConfigInit = false;
+ mutable std::shared_timed_mutex mConfigLock;
mutable std::unordered_map<int32_t, aidlvhal::VehiclePropConfig> mConfigsByPropId
- GUARDED_BY(mConfigInitLock);
- mutable std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile GUARDED_BY(mConfigInitLock);
+ GUARDED_BY(mConfigLock);
+ mutable std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile GUARDED_BY(mConfigLock);
std::mutex mLock;
std::unordered_map<const AIBinder*, std::unique_ptr<OnBinderDiedContext>> mOnBinderDiedContexts
@@ -175,7 +175,10 @@
android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
const std::vector<aidlvhal::SetValueRequest>& requests);
- VhalResult<void> checkSubscribeOptions(const std::vector<aidlvhal::SubscribeOptions>& options);
+ VhalResult<void> checkSubscribeOptions(
+ const std::vector<aidlvhal::SubscribeOptions>& options,
+ const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& configsByPropId)
+ REQUIRES_SHARED(mConfigLock);
VhalResult<void> checkPermissionHelper(const aidlvhal::VehiclePropValue& value,
aidlvhal::VehiclePropertyAccess accessToTest) const;
@@ -184,7 +187,7 @@
VhalResult<void> checkWritePermission(const aidlvhal::VehiclePropValue& value) const;
- android::base::Result<const aidlvhal::VehiclePropConfig*> getConfig(int32_t propId) const;
+ android::base::Result<aidlvhal::VehiclePropConfig> getConfig(int32_t propId) const;
void onBinderDiedWithContext(const AIBinder* clientId);
@@ -196,7 +199,9 @@
bool checkDumpPermission();
- bool getAllPropConfigsFromHardwareLocked() const REQUIRES(mConfigInitLock);
+ bool isConfigSupportedForCurrentVhalVersion(const aidlvhal::VehiclePropConfig& config) const;
+
+ bool getAllPropConfigsFromHardwareLocked() const EXCLUDES(mConfigLock);
// The looping handler function to process all onBinderDied or onBinderUnlinked events in
// mBinderEvents.
@@ -209,10 +214,12 @@
int32_t getVhalInterfaceVersion() const;
- // Gets mConfigsByPropId, lazy init it if necessary.
- const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& getConfigsByPropId() const;
- // Gets mConfigFile, lazy init it if necessary.
- const ndk::ScopedFileDescriptor* getConfigFile() const;
+ // Gets mConfigsByPropId, lazy init it if necessary. Note that the reference is only valid in
+ // the scope of the callback and it is guaranteed that read lock is obtained during the
+ // callback.
+ void getConfigsByPropId(
+ std::function<void(const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>&)>
+ callback) const EXCLUDES(mConfigLock);
// Puts the property change events into a queue so that they can handled in batch.
static void batchPropertyChangeEvent(
@@ -239,6 +246,12 @@
static void onBinderUnlinked(void* cookie);
+ static void parseSubscribeOptions(
+ const std::vector<aidlvhal::SubscribeOptions>& options,
+ const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& configsByPropId,
+ std::vector<aidlvhal::SubscribeOptions>& onChangeSubscriptions,
+ std::vector<aidlvhal::SubscribeOptions>& continuousSubscriptions);
+
// Test-only
// Set the default timeout for pending requests.
void setTimeout(int64_t timeoutInNano);
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index 9dc039d..0ead819 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -95,6 +95,18 @@
return sampleRateHz;
}
+class SCOPED_CAPABILITY SharedScopedLockAssertion {
+ public:
+ SharedScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE_SHARED(mutex) {}
+ ~SharedScopedLockAssertion() RELEASE() {}
+};
+
+class SCOPED_CAPABILITY UniqueScopedLockAssertion {
+ public:
+ UniqueScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE(mutex) {}
+ ~UniqueScopedLockAssertion() RELEASE() {}
+};
+
} // namespace
DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
@@ -328,95 +340,127 @@
return myVersion;
}
-bool DefaultVehicleHal::getAllPropConfigsFromHardwareLocked() const {
- ALOGD("Get all property configs from hardware");
- auto configs = mVehicleHardware->getAllPropertyConfigs();
- std::vector<VehiclePropConfig> filteredConfigs;
+bool DefaultVehicleHal::isConfigSupportedForCurrentVhalVersion(
+ const VehiclePropConfig& config) const {
int32_t myVersion = getVhalInterfaceVersion();
- for (auto& config : configs) {
- if (!isSystemProp(config.prop)) {
- filteredConfigs.push_back(std::move(config));
- continue;
- }
- VehicleProperty property = static_cast<VehicleProperty>(config.prop);
- std::string propertyName = aidl::android::hardware::automotive::vehicle::toString(property);
- auto it = VersionForVehicleProperty.find(property);
- if (it == VersionForVehicleProperty.end()) {
- ALOGE("The property: %s is not a supported system property, ignore",
- propertyName.c_str());
- continue;
- }
- int requiredVersion = it->second;
- if (myVersion < requiredVersion) {
- ALOGE("The property: %s is not supported for current client VHAL version, "
- "require %d, current version: %d, ignore",
- propertyName.c_str(), requiredVersion, myVersion);
- continue;
- }
- filteredConfigs.push_back(std::move(config));
+ if (!isSystemProp(config.prop)) {
+ return true;
}
- for (auto& config : filteredConfigs) {
- mConfigsByPropId[config.prop] = config;
- }
- VehiclePropConfigs vehiclePropConfigs;
- vehiclePropConfigs.payloads = std::move(filteredConfigs);
- auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
- if (!result.ok()) {
- ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
- result.error().message().c_str(), static_cast<int>(result.error().code()));
- mConfigFile = nullptr;
+ VehicleProperty property = static_cast<VehicleProperty>(config.prop);
+ std::string propertyName = aidl::android::hardware::automotive::vehicle::toString(property);
+ auto it = VersionForVehicleProperty.find(property);
+ if (it == VersionForVehicleProperty.end()) {
+ ALOGE("The property: %s is not a supported system property, ignore", propertyName.c_str());
return false;
}
-
- if (result.value() != nullptr) {
- mConfigFile = std::move(result.value());
+ int requiredVersion = it->second;
+ if (myVersion < requiredVersion) {
+ ALOGE("The property: %s is not supported for current client VHAL version, "
+ "require %d, current version: %d, ignore",
+ propertyName.c_str(), requiredVersion, myVersion);
+ return false;
}
return true;
}
-const ScopedFileDescriptor* DefaultVehicleHal::getConfigFile() const {
- std::scoped_lock lockGuard(mConfigInitLock);
- if (!mConfigInit) {
- CHECK(getAllPropConfigsFromHardwareLocked())
- << "Failed to get property configs from hardware";
- mConfigInit = true;
+bool DefaultVehicleHal::getAllPropConfigsFromHardwareLocked() const {
+ ALOGD("Get all property configs from hardware");
+ auto configs = mVehicleHardware->getAllPropertyConfigs();
+ std::vector<VehiclePropConfig> filteredConfigs;
+ for (const auto& config : configs) {
+ if (isConfigSupportedForCurrentVhalVersion(config)) {
+ filteredConfigs.push_back(std::move(config));
+ }
}
- return mConfigFile.get();
+
+ {
+ std::unique_lock<std::shared_timed_mutex> configWriteLock(mConfigLock);
+ UniqueScopedLockAssertion lockAssertion(mConfigLock);
+
+ for (auto& config : filteredConfigs) {
+ mConfigsByPropId[config.prop] = config;
+ }
+ VehiclePropConfigs vehiclePropConfigs;
+ vehiclePropConfigs.payloads = std::move(filteredConfigs);
+ auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
+ if (!result.ok()) {
+ ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
+ result.error().message().c_str(), static_cast<int>(result.error().code()));
+ mConfigFile = nullptr;
+ return false;
+ }
+
+ if (result.value() != nullptr) {
+ mConfigFile = std::move(result.value());
+ }
+ }
+
+ mConfigInit = true;
+ return true;
}
-const std::unordered_map<int32_t, VehiclePropConfig>& DefaultVehicleHal::getConfigsByPropId()
- const {
- std::scoped_lock lockGuard(mConfigInitLock);
+void DefaultVehicleHal::getConfigsByPropId(
+ std::function<void(const std::unordered_map<int32_t, VehiclePropConfig>&)> callback) const {
if (!mConfigInit) {
CHECK(getAllPropConfigsFromHardwareLocked())
<< "Failed to get property configs from hardware";
- mConfigInit = true;
}
- return mConfigsByPropId;
+
+ std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ callback(mConfigsByPropId);
}
ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
- const ScopedFileDescriptor* configFile = getConfigFile();
- const auto& configsByPropId = getConfigsByPropId();
- if (configFile != nullptr) {
+ if (!mConfigInit) {
+ CHECK(getAllPropConfigsFromHardwareLocked())
+ << "Failed to get property configs from hardware";
+ }
+
+ std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ if (mConfigFile != nullptr) {
output->payloads.clear();
- output->sharedMemoryFd.set(dup(configFile->get()));
+ output->sharedMemoryFd.set(dup(mConfigFile->get()));
return ScopedAStatus::ok();
}
- output->payloads.reserve(configsByPropId.size());
- for (const auto& [_, config] : configsByPropId) {
+
+ output->payloads.reserve(mConfigsByPropId.size());
+ for (const auto& [_, config] : mConfigsByPropId) {
output->payloads.push_back(config);
}
return ScopedAStatus::ok();
}
-Result<const VehiclePropConfig*> DefaultVehicleHal::getConfig(int32_t propId) const {
- const auto& configsByPropId = getConfigsByPropId();
- auto it = configsByPropId.find(propId);
- if (it == configsByPropId.end()) {
- return Error() << "no config for property, ID: " << propId;
+Result<VehiclePropConfig> DefaultVehicleHal::getConfig(int32_t propId) const {
+ Result<VehiclePropConfig> result;
+
+ if (!mConfigInit) {
+ std::optional<VehiclePropConfig> config = mVehicleHardware->getPropertyConfig(propId);
+ if (!config.has_value()) {
+ return Error() << "no config for property, ID: " << propId;
+ }
+ if (!isConfigSupportedForCurrentVhalVersion(config.value())) {
+ return Error() << "property not supported for current VHAL interface, ID: " << propId;
+ }
+
+ return config.value();
}
- return &(it->second);
+
+ getConfigsByPropId([this, &result, propId](const auto& configsByPropId) {
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ auto it = configsByPropId.find(propId);
+ if (it == configsByPropId.end()) {
+ result = Error() << "no config for property, ID: " << propId;
+ return;
+ }
+ // Copy the VehiclePropConfig
+ result = it->second;
+ });
+ return result;
}
Result<void> DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) {
@@ -425,15 +469,15 @@
if (!result.ok()) {
return result.error();
}
- const VehiclePropConfig* config = result.value();
- const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, *config);
+ const VehiclePropConfig& config = result.value();
+ const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, config);
if (!isGlobalProp(propId) && areaConfig == nullptr) {
// Ignore areaId for global property. For non global property, check whether areaId is
// allowed. areaId must appear in areaConfig.
return Error() << "invalid area ID: " << propValue.areaId << " for prop ID: " << propId
<< ", not listed in config";
}
- if (auto result = checkPropValue(propValue, config); !result.ok()) {
+ if (auto result = checkPropValue(propValue, &config); !result.ok()) {
return Error() << "invalid property value: " << propValue.toString()
<< ", error: " << getErrorMsg(result);
}
@@ -659,17 +703,43 @@
ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
VehiclePropConfigs* output) {
std::vector<VehiclePropConfig> configs;
- const auto& configsByPropId = getConfigsByPropId();
- for (int32_t prop : props) {
- auto it = configsByPropId.find(prop);
- if (it != configsByPropId.end()) {
- configs.push_back(it->second);
- } else {
- return ScopedAStatus::fromServiceSpecificErrorWithMessage(
- toInt(StatusCode::INVALID_ARG),
- StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
+
+ if (!mConfigInit) {
+ for (int32_t prop : props) {
+ auto maybeConfig = mVehicleHardware->getPropertyConfig(prop);
+ if (!maybeConfig.has_value() ||
+ !isConfigSupportedForCurrentVhalVersion(maybeConfig.value())) {
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ toInt(StatusCode::INVALID_ARG),
+ StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
+ }
+ configs.push_back(maybeConfig.value());
}
+
+ return vectorToStableLargeParcelable(std::move(configs), output);
}
+
+ ScopedAStatus status = ScopedAStatus::ok();
+ getConfigsByPropId([this, &configs, &status, &props](const auto& configsByPropId) {
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ for (int32_t prop : props) {
+ auto it = configsByPropId.find(prop);
+ if (it != configsByPropId.end()) {
+ configs.push_back(it->second);
+ } else {
+ status = ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ toInt(StatusCode::INVALID_ARG),
+ StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
+ return;
+ }
+ }
+ });
+
+ if (!status.isOk()) {
+ return status;
+ }
+
return vectorToStableLargeParcelable(std::move(configs), output);
}
@@ -691,8 +761,8 @@
}
VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
- const std::vector<SubscribeOptions>& options) {
- const auto& configsByPropId = getConfigsByPropId();
+ const std::vector<SubscribeOptions>& options,
+ const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId) {
for (const auto& option : options) {
int32_t propId = option.propId;
auto it = configsByPropId.find(propId);
@@ -757,23 +827,15 @@
}
}
}
+
return {};
}
-ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
- const std::vector<SubscribeOptions>& options,
- [[maybe_unused]] int32_t maxSharedMemoryFileCount) {
- // TODO(b/205189110): Use shared memory file count.
- if (callback == nullptr) {
- return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
- }
- if (auto result = checkSubscribeOptions(options); !result.ok()) {
- ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
- return toScopedAStatus(result);
- }
- std::vector<SubscribeOptions> onChangeSubscriptions;
- std::vector<SubscribeOptions> continuousSubscriptions;
- const auto& configsByPropId = getConfigsByPropId();
+void DefaultVehicleHal::parseSubscribeOptions(
+ const std::vector<SubscribeOptions>& options,
+ const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId,
+ std::vector<SubscribeOptions>& onChangeSubscriptions,
+ std::vector<SubscribeOptions>& continuousSubscriptions) {
for (const auto& option : options) {
int32_t propId = option.propId;
// We have already validate config exists.
@@ -831,6 +893,34 @@
onChangeSubscriptions.push_back(std::move(optionCopy));
}
}
+}
+
+ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
+ const std::vector<SubscribeOptions>& options,
+ [[maybe_unused]] int32_t maxSharedMemoryFileCount) {
+ // TODO(b/205189110): Use shared memory file count.
+ if (callback == nullptr) {
+ return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+ }
+ std::vector<SubscribeOptions> onChangeSubscriptions;
+ std::vector<SubscribeOptions> continuousSubscriptions;
+ ScopedAStatus returnStatus = ScopedAStatus::ok();
+ getConfigsByPropId([this, &returnStatus, &options, &onChangeSubscriptions,
+ &continuousSubscriptions](const auto& configsByPropId) {
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ if (auto result = checkSubscribeOptions(options, configsByPropId); !result.ok()) {
+ ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
+ returnStatus = toScopedAStatus(result);
+ return;
+ }
+ parseSubscribeOptions(options, configsByPropId, onChangeSubscriptions,
+ continuousSubscriptions);
+ });
+
+ if (!returnStatus.isOk()) {
+ return returnStatus;
+ }
{
// Lock to make sure onBinderDied would not be called concurrently.
@@ -891,13 +981,13 @@
return StatusError(StatusCode::INVALID_ARG) << getErrorMsg(result);
}
- const VehiclePropConfig* config = result.value();
- const VehicleAreaConfig* areaConfig = getAreaConfig(value, *config);
+ const VehiclePropConfig& config = result.value();
+ const VehicleAreaConfig* areaConfig = getAreaConfig(value, config);
if (areaConfig == nullptr && !isGlobalProp(propId)) {
return StatusError(StatusCode::INVALID_ARG) << "no config for area ID: " << value.areaId;
}
- if (!hasRequiredAccess(config->access, accessToTest) &&
+ if (!hasRequiredAccess(config.access, accessToTest) &&
(areaConfig == nullptr || !hasRequiredAccess(areaConfig->access, accessToTest))) {
return StatusError(StatusCode::ACCESS_DENIED)
<< StringPrintf("Property %" PRId32 " does not have the following access: %" PRId32,
@@ -966,7 +1056,6 @@
}
DumpResult result = mVehicleHardware->dump(options);
if (result.refreshPropertyConfigs) {
- std::scoped_lock lockGuard(mConfigInitLock);
getAllPropConfigsFromHardwareLocked();
}
dprintf(fd, "%s", (result.buffer + "\n").c_str());
@@ -974,11 +1063,16 @@
return STATUS_OK;
}
dprintf(fd, "Vehicle HAL State: \n");
- const auto& configsByPropId = getConfigsByPropId();
+ std::unordered_map<int32_t, VehiclePropConfig> configsByPropIdCopy;
+ getConfigsByPropId([this, &configsByPropIdCopy](const auto& configsByPropId) {
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ configsByPropIdCopy = configsByPropId;
+ });
{
std::scoped_lock<std::mutex> lockGuard(mLock);
dprintf(fd, "Interface version: %" PRId32 "\n", getVhalInterfaceVersion());
- dprintf(fd, "Containing %zu property configs\n", configsByPropId.size());
+ dprintf(fd, "Containing %zu property configs\n", configsByPropIdCopy.size());
dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
dprintf(fd, "Currently have %zu subscribe clients\n", countSubscribeClients());
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index 11a8fc7..4891bf5 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -650,6 +650,8 @@
auto hardware = std::make_unique<MockVehicleHardware>();
hardware->setPropertyConfigs(testConfigs);
+ // Store the pointer for testing. We are sure it is valid.
+ MockVehicleHardware* hardwarePtr = hardware.get();
auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
@@ -658,6 +660,7 @@
ASSERT_TRUE(status.isOk()) << "getPropConfigs failed: " << status.getMessage();
ASSERT_EQ(output.payloads, testConfigs);
+ ASSERT_FALSE(hardwarePtr->getAllPropertyConfigsCalled());
}
TEST_F(DefaultVehicleHalTest, testGetPropConfigsInvalidArg) {
@@ -704,6 +707,34 @@
ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch";
EXPECT_EQ(countClients(), static_cast<size_t>(1));
+ ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesSmall_AfterGetAllPropConfigs) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> expectedHardwareRequests;
+
+ // If we already called getAllPropConfigs, the configs will be cached.
+ VehiclePropConfigs output;
+ getClient()->getAllPropConfigs(&output);
+
+ ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+ getHardware()->addGetValueResponses(expectedResults);
+
+ auto status = getClient()->getValues(getCallbackClient(), requests);
+
+ ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
+
+ EXPECT_EQ(getHardware()->nextGetValueRequests(), expectedHardwareRequests)
+ << "requests to hardware mismatch";
+
+ auto maybeGetValueResults = getCallback()->nextGetValueResults();
+ ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
+ EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch";
+ EXPECT_EQ(countClients(), static_cast<size_t>(1));
+ ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled());
}
TEST_F(DefaultVehicleHalTest, testGetValuesLarge) {
@@ -1016,6 +1047,34 @@
ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
ASSERT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch";
EXPECT_EQ(countClients(), static_cast<size_t>(1));
+ ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesSmall_AfterGetAllPropConfigs) {
+ SetValueRequests requests;
+ std::vector<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> expectedHardwareRequests;
+
+ // If we already called getAllPropConfigs, the configs will be cached.
+ VehiclePropConfigs output;
+ getClient()->getAllPropConfigs(&output);
+
+ ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+ getHardware()->addSetValueResponses(expectedResults);
+
+ auto status = getClient()->setValues(getCallbackClient(), requests);
+
+ ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
+
+ EXPECT_EQ(getHardware()->nextSetValueRequests(), expectedHardwareRequests)
+ << "requests to hardware mismatch";
+
+ auto maybeSetValueResults = getCallback()->nextSetValueResults();
+ ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
+ ASSERT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch";
+ EXPECT_EQ(countClients(), static_cast<size_t>(1));
+ ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled());
}
TEST_F(DefaultVehicleHalTest, testSetValuesLarge) {
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
index db15c89..e796ce5 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
@@ -45,9 +45,20 @@
std::vector<VehiclePropConfig> MockVehicleHardware::getAllPropertyConfigs() const {
std::scoped_lock<std::mutex> lockGuard(mLock);
+ mGetAllPropertyConfigsCalled = true;
return mPropertyConfigs;
}
+std::optional<VehiclePropConfig> MockVehicleHardware::getPropertyConfig(int32_t propId) const {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ for (const auto& config : mPropertyConfigs) {
+ if (config.prop == propId) {
+ return config;
+ }
+ }
+ return std::nullopt;
+}
+
StatusCode MockVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback,
const std::vector<SetValueRequest>& requests) {
std::scoped_lock<std::mutex> lockGuard(mLock);
@@ -336,6 +347,11 @@
(*mPropertySetErrorCallback)(errorEvents);
}
+bool MockVehicleHardware::getAllPropertyConfigsCalled() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mGetAllPropertyConfigsCalled;
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
index eeca582..06e01a8 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
@@ -47,6 +47,8 @@
std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
getAllPropertyConfigs() const override;
+ std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+ getPropertyConfig(int32_t propId) const override;
aidl::android::hardware::automotive::vehicle::StatusCode setValues(
std::shared_ptr<const SetValuesCallback> callback,
const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
@@ -98,6 +100,9 @@
std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>
getSubscribeOptions();
void clearSubscribeOptions();
+ // Whether getAllPropertyConfigs() has been called, which blocks all all property configs
+ // being ready.
+ bool getAllPropertyConfigsCalled();
private:
mutable std::mutex mLock;
@@ -143,6 +148,8 @@
DumpResult mDumpResult;
+ mutable bool mGetAllPropertyConfigsCalled GUARDED_BY(mLock) = false;
+
// RecurrentTimer is thread-safe.
std::shared_ptr<RecurrentTimer> mRecurrentTimer;
std::unordered_map<int32_t, std::unordered_map<int32_t, std::shared_ptr<std::function<void()>>>>
diff --git a/camera/common/aidl/Android.bp b/camera/common/aidl/Android.bp
index 8f7d19d..b59c92e 100644
--- a/camera/common/aidl/Android.bp
+++ b/camera/common/aidl/Android.bp
@@ -10,6 +10,7 @@
aidl_interface {
name: "android.hardware.camera.common",
+ host_supported: true,
vendor_available: true,
srcs: ["android/hardware/camera/common/*.aidl"],
frozen: true,
diff --git a/camera/device/aidl/Android.bp b/camera/device/aidl/Android.bp
index 78aefac..f3a3681 100644
--- a/camera/device/aidl/Android.bp
+++ b/camera/device/aidl/Android.bp
@@ -10,6 +10,7 @@
aidl_interface {
name: "android.hardware.camera.device",
+ host_supported: true,
vendor_available: true,
srcs: ["android/hardware/camera/device/*.aidl"],
frozen: true,
diff --git a/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl b/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl
index 62a19cf..63ae320 100644
--- a/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl
+++ b/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl
@@ -575,6 +575,11 @@
* This can be called at any point after 'processCaptureRequest' in response
* to camera clients disabling an active repeating request.
*
+ * Note: The frame number parameter is the latest possible frame number at which the
+ * ongoing repeating request will end. It is possible that the repeating request may end
+ * before the specified frame number due to reasons such as the camera client abandoning
+ * buffers, which is timing dependent.
+ *
* Performance requirements:
* The call must not be blocked for extensive periods and should be extremely lightweight. There
* must be no frame rate degradation or frame jitter introduced.
diff --git a/camera/metadata/aidl/Android.bp b/camera/metadata/aidl/Android.bp
index ae8ba14..a9c1a1a 100644
--- a/camera/metadata/aidl/Android.bp
+++ b/camera/metadata/aidl/Android.bp
@@ -10,6 +10,7 @@
aidl_interface {
name: "android.hardware.camera.metadata",
+ host_supported: true,
vendor_available: true,
srcs: ["android/hardware/camera/metadata/*.aidl"],
frozen: true,
diff --git a/camera/provider/aidl/Android.bp b/camera/provider/aidl/Android.bp
index 38a8936..c055caa 100644
--- a/camera/provider/aidl/Android.bp
+++ b/camera/provider/aidl/Android.bp
@@ -10,6 +10,7 @@
aidl_interface {
name: "android.hardware.camera.provider",
+ host_supported: true,
vendor_available: true,
srcs: [
"android/hardware/camera/provider/*.aidl",
diff --git a/compatibility_matrices/compatibility_matrix.202504.xml b/compatibility_matrices/compatibility_matrix.202504.xml
index 5f9d41f..8ec3649 100644
--- a/compatibility_matrices/compatibility_matrix.202504.xml
+++ b/compatibility_matrices/compatibility_matrix.202504.xml
@@ -630,7 +630,7 @@
</hal>
<hal format="aidl">
<name>android.hardware.vibrator</name>
- <version>1-2</version>
+ <version>1-3</version>
<interface>
<name>IVibrator</name>
<instance>default</instance>
@@ -638,7 +638,7 @@
</hal>
<hal format="aidl">
<name>android.hardware.vibrator</name>
- <version>1-2</version>
+ <version>1-3</version>
<interface>
<name>IVibratorManager</name>
<instance>default</instance>
diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl
index 8a22d6e..aaafe7f 100644
--- a/gnss/aidl/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl
@@ -217,10 +217,6 @@
* Starts a location output stream using the IGnssCallback gnssLocationCb(), following the
* settings from the most recent call to setPositionMode().
*
- * When a location output stream is in progress, calling setPositionMode() does not change the
- * settings of the current location output stream. stop() and start() must be called to make the
- * new settings effective.
- *
* This output must operate independently of any GNSS location batching operations,
* see the IGnssBatching for details.
*/
@@ -310,10 +306,6 @@
/**
* Sets the GnssPositionMode parameter, its associated recurrence value, the time between fixes,
* requested fix accuracy, time to first fix.
- *
- * If a location output stream is in progress, calling this method does not affect the settings
- * of current location output stream. stop() and start() must be called to make the new settings
- * effective.
*/
void setPositionMode(in PositionModeOptions options);
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
index 7157862..3b0a597 100644
--- a/graphics/composer/2.2/utils/vts/Android.bp
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -39,6 +39,7 @@
shared_libs: [
"libui",
"server_configurable_flags",
+ "libtracing_perfetto",
],
static_libs: [
"android.hardware.graphics.composer@2.1-vts",
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index bda4198..431b1b6 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -55,6 +55,7 @@
"libui",
"android.hardware.common-V2-ndk",
"server_configurable_flags",
+ "libtracing_perfetto",
],
static_libs: [
"android.hardware.graphics.common@1.1",
diff --git a/graphics/composer/aidl/vts/Android.bp b/graphics/composer/aidl/vts/Android.bp
index 3464fe9..a2ab3d6 100644
--- a/graphics/composer/aidl/vts/Android.bp
+++ b/graphics/composer/aidl/vts/Android.bp
@@ -57,6 +57,7 @@
"libprocessgroup",
"libvndksupport",
"server_configurable_flags",
+ "libtracing_perfetto",
],
header_libs: [
"android.hardware.graphics.composer3-command-buffer",
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index bae362f..f398c53 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -719,6 +719,38 @@
}
/**
+ * Test IMapper::lock and IMapper::unlock with no CPU usage requested.
+ */
+TEST_P(GraphicsMapperHidlTest, LockUnlockNoCPUUsage) {
+ const auto& info = mDummyDescriptorInfo;
+
+ const native_handle_t* bufferHandle;
+ uint32_t stride;
+ ASSERT_NO_FATAL_FAILURE(
+ bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride));
+
+ // lock buffer with 0 usage
+ const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+ static_cast<int32_t>(info.height)};
+
+ hidl_handle acquireFenceHandle;
+
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+ mGralloc->getMapper()->lock(buffer, 0, region, acquireFenceHandle,
+ [&](const auto& tmpError, const auto& /*tmpData*/) {
+ EXPECT_EQ(Error::BAD_VALUE, tmpError)
+ << "Locking with 0 access succeeded";
+ });
+
+ mGralloc->getMapper()->unlock(buffer, [&](const auto& tmpError, const auto&) {
+ EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+ << "Unlocking not locked buffer succeeded";
+ });
+
+ mGralloc->freeBuffer(bufferHandle);
+}
+
+/**
* Test multiple operations associated with different color formats
*/
TEST_P(GraphicsMapperHidlTest, Lock_YCRCB_420_SP) {
diff --git a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
index 1e0c427..bdbe4d0 100644
--- a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
+++ b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
@@ -750,6 +750,42 @@
}
/**
+ * Test IMapper::lock and IMapper::unlock with no CPU usage requested.
+ */
+TEST_P(GraphicsMapperStableCTests, LockUnlockNoCPUUsage) {
+ constexpr auto usage = BufferUsage::CPU_READ_NEVER | BufferUsage::CPU_WRITE_NEVER;
+ auto buffer = allocate({
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::RGBA_8888,
+ .usage = usage,
+ .reservedSize = 0,
+ });
+ ASSERT_NE(nullptr, buffer.get());
+
+ // lock buffer for writing
+ const auto& info = buffer->info();
+ const ARect region{0, 0, info.width, info.height};
+ auto handle = buffer->import();
+ uint8_t* data = nullptr;
+
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_VALUE,
+ mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
+ region, -1,(void**)&data))
+ << "Locking with 0 access succeeded";
+
+ int releaseFence = -1;
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER,
+ mapper()->v5.unlock(*handle, &releaseFence))
+ << "Unlocking not locked buffer succeeded";
+ if (releaseFence != -1) {
+ close(releaseFence);
+ }
+}
+
+/**
* Test multiple operations associated with different color formats
*/
TEST_P(GraphicsMapperStableCTests, Lock_YCRCB_420_SP) {
diff --git a/nfc/aidl/vts/functional/Android.bp b/nfc/aidl/vts/functional/Android.bp
index 82ce026..f97405e 100644
--- a/nfc/aidl/vts/functional/Android.bp
+++ b/nfc/aidl/vts/functional/Android.bp
@@ -49,6 +49,7 @@
cc_test {
name: "VtsNfcBehaviorChangesTest",
defaults: [
+ "aconfig_lib_cc_shared_link.defaults",
"VtsHalTargetTestDefaults",
"use_libaidlvintf_gtest_helper_static",
],
@@ -65,6 +66,7 @@
"system/nfc/utils/include",
],
shared_libs: [
+ "liblog",
"libbinder",
"libbinder_ndk",
"libnativehelper",
diff --git a/radio/aidl/vts/Android.bp b/radio/aidl/vts/Android.bp
index e83a7c1..9521068 100644
--- a/radio/aidl/vts/Android.bp
+++ b/radio/aidl/vts/Android.bp
@@ -25,6 +25,7 @@
cc_test {
name: "VtsHalRadioTargetTest",
defaults: [
+ "aconfig_lib_cc_shared_link.defaults",
"VtsHalTargetTestDefaults",
"use_libaidlvintf_gtest_helper_static",
],
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
index ec2a29c..914cad0 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -2171,6 +2171,14 @@
// exit emergency mode for other tests
serial = GetRandomSerialNumber();
radio_network->exitEmergencyMode(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
+ RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
}
/*
diff --git a/radio/aidl/vts/radio_sim_test.cpp b/radio/aidl/vts/radio_sim_test.cpp
index 06654c2..9d1c356 100644
--- a/radio/aidl/vts/radio_sim_test.cpp
+++ b/radio/aidl/vts/radio_sim_test.cpp
@@ -118,7 +118,14 @@
EXPECT_EQ(CardStatus::STATE_PRESENT, slotStatus.cardState);
if (CardStatus::STATE_PRESENT == slotStatus.cardState) {
ASSERT_TRUE(slotStatus.portInfo[0].portActive);
- EXPECT_EQ(0, cardStatus.slotMap.portId);
+ if (cardStatus.supportedMepMode == aidl::android::hardware::radio::config::
+ MultipleEnabledProfilesMode::MEP_A1 ||
+ cardStatus.supportedMepMode == aidl::android::hardware::radio::config::
+ MultipleEnabledProfilesMode::MEP_A2) {
+ EXPECT_EQ(1, cardStatus.slotMap.portId);
+ } else {
+ EXPECT_EQ(0, cardStatus.slotMap.portId);
+ }
}
}
}
@@ -453,14 +460,41 @@
serial = GetRandomSerialNumber();
CarrierRestrictions carrierRestrictions;
memset(&carrierRestrictions, 0, sizeof(carrierRestrictions));
- carrierRestrictions.allowedCarriers.resize(1);
- carrierRestrictions.excludedCarriers.resize(0);
- carrierRestrictions.allowedCarriers[0].mcc = std::string("123");
- carrierRestrictions.allowedCarriers[0].mnc = std::string("456");
- carrierRestrictions.allowedCarriers[0].matchType = Carrier::MATCH_TYPE_ALL;
- carrierRestrictions.allowedCarriers[0].matchData = std::string();
- carrierRestrictions.allowedCarriersPrioritized = true;
+ int32_t aidl_version;
+ ndk::ScopedAStatus aidl_status = radio_sim->getInterfaceVersion(&aidl_version);
+ ASSERT_OK(aidl_status);
+
+ // Changes start
+
SimLockMultiSimPolicy multisimPolicy = SimLockMultiSimPolicy::NO_MULTISIM_POLICY;
+ ALOGI("VTSAllowedCarriers Current AIDL version is %d ", aidl_version);
+ if (aidl_version <= 2) {
+ ALOGI("VTSAllowedCarriers If aidl_version is below 3 then , it will consider old AIDLs");
+ carrierRestrictions.allowedCarrierInfoList.resize(1);
+ if ((carrierRestrictions.allowedCarrierInfoList.size() > 0)) {
+ ALOGI("VTSAllowedCarriers If size of allowedCarrierInfoList is greater than 0");
+ }
+ carrierRestrictions.allowedCarriers.resize(1);
+ carrierRestrictions.excludedCarriers.resize(0);
+ carrierRestrictions.allowedCarriers[0].mcc = std::string("123");
+ carrierRestrictions.allowedCarriers[0].mnc = std::string("456");
+ carrierRestrictions.allowedCarriers[0].matchType = Carrier::MATCH_TYPE_ALL;
+ carrierRestrictions.allowedCarriers[0].matchData = std::string();
+ carrierRestrictions.allowedCarriersPrioritized = true;
+ multisimPolicy = SimLockMultiSimPolicy::NO_MULTISIM_POLICY;
+ } else {
+ carrierRestrictions.allowedCarrierInfoList.resize(1);
+ carrierRestrictions.excludedCarrierInfoList.resize(0);
+ carrierRestrictions.allowedCarrierInfoList[0].mcc = std::string("321");
+ carrierRestrictions.allowedCarrierInfoList[0].mnc = std::string("654");
+ carrierRestrictions.allowedCarrierInfoList[0].spn = std::string("TestNetwork");
+ carrierRestrictions.allowedCarrierInfoList[0].gid1 = std::string("BAE000000000000");
+ carrierRestrictions.allowedCarrierInfoList[0].gid2 = std::string("AE0000000000000");
+ carrierRestrictions.allowedCarrierInfoList[0].imsiPrefix = std::string("9987");
+ carrierRestrictions.allowedCarriersPrioritized = true;
+ carrierRestrictions.status = CarrierRestrictions::CarrierRestrictionStatus::RESTRICTED;
+ multisimPolicy = SimLockMultiSimPolicy::NO_MULTISIM_POLICY;
+ }
radio_sim->setAllowedCarriers(serial, carrierRestrictions, multisimPolicy);
EXPECT_EQ(std::cv_status::no_timeout, wait());
@@ -496,17 +530,36 @@
EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
- EXPECT_EQ(1, radioRsp_sim->carrierRestrictionsResp.allowedCarriers.size());
- EXPECT_EQ(0, radioRsp_sim->carrierRestrictionsResp.excludedCarriers.size());
- ASSERT_TRUE(std::string("123") ==
- radioRsp_sim->carrierRestrictionsResp.allowedCarriers[0].mcc);
- ASSERT_TRUE(std::string("456") ==
- radioRsp_sim->carrierRestrictionsResp.allowedCarriers[0].mnc);
- EXPECT_EQ(Carrier::MATCH_TYPE_ALL,
- radioRsp_sim->carrierRestrictionsResp.allowedCarriers[0].matchType);
- ASSERT_TRUE(radioRsp_sim->carrierRestrictionsResp.allowedCarriersPrioritized);
- EXPECT_EQ(SimLockMultiSimPolicy::NO_MULTISIM_POLICY, radioRsp_sim->multiSimPolicyResp);
+ if (aidl_version <= 2) {
+ EXPECT_EQ(1, radioRsp_sim->carrierRestrictionsResp.allowedCarriers.size());
+ EXPECT_EQ(0, radioRsp_sim->carrierRestrictionsResp.excludedCarriers.size());
+ ASSERT_TRUE(std::string("123") ==
+ radioRsp_sim->carrierRestrictionsResp.allowedCarriers[0].mcc);
+ ASSERT_TRUE(std::string("456") ==
+ radioRsp_sim->carrierRestrictionsResp.allowedCarriers[0].mnc);
+ EXPECT_EQ(Carrier::MATCH_TYPE_ALL,
+ radioRsp_sim->carrierRestrictionsResp.allowedCarriers[0].matchType);
+ ASSERT_TRUE(radioRsp_sim->carrierRestrictionsResp.allowedCarriersPrioritized);
+ EXPECT_EQ(SimLockMultiSimPolicy::NO_MULTISIM_POLICY, radioRsp_sim->multiSimPolicyResp);
+ } else {
+ EXPECT_EQ(1, radioRsp_sim->carrierRestrictionsResp.allowedCarrierInfoList.size());
+ EXPECT_EQ(0, radioRsp_sim->carrierRestrictionsResp.excludedCarrierInfoList.size());
+ ASSERT_TRUE(std::string("321") ==
+ radioRsp_sim->carrierRestrictionsResp.allowedCarrierInfoList[0].mcc);
+ ASSERT_TRUE(std::string("654") ==
+ radioRsp_sim->carrierRestrictionsResp.allowedCarrierInfoList[0].mnc);
+ ASSERT_TRUE(std::string("BAE000000000000") ==
+ radioRsp_sim->carrierRestrictionsResp.allowedCarrierInfoList[0].gid1);
+ ASSERT_TRUE(std::string("AE0000000000000") ==
+ radioRsp_sim->carrierRestrictionsResp.allowedCarrierInfoList[0].gid2);
+ ASSERT_TRUE(std::string("9987") ==
+ radioRsp_sim->carrierRestrictionsResp.allowedCarrierInfoList[0].imsiPrefix);
+ ASSERT_TRUE(radioRsp_sim->carrierRestrictionsResp.allowedCarriersPrioritized);
+ EXPECT_EQ(CarrierRestrictions::CarrierRestrictionStatus::RESTRICTED,
+ radioRsp_sim->carrierRestrictionsResp.status);
+ EXPECT_EQ(SimLockMultiSimPolicy::NO_MULTISIM_POLICY, radioRsp_sim->multiSimPolicyResp);
+ }
sleep(10);
/**
@@ -515,9 +568,15 @@
* status for cardStatus.
*/
memset(&carrierRestrictions, 0, sizeof(carrierRestrictions));
- carrierRestrictions.allowedCarriers.resize(0);
- carrierRestrictions.excludedCarriers.resize(0);
- carrierRestrictions.allowedCarriersPrioritized = false;
+ if (aidl_version <= 2) {
+ carrierRestrictions.allowedCarriers.resize(0);
+ carrierRestrictions.excludedCarriers.resize(0);
+ carrierRestrictions.allowedCarriersPrioritized = false;
+ } else {
+ carrierRestrictions.allowedCarrierInfoList.resize(0);
+ carrierRestrictions.excludedCarrierInfoList.resize(0);
+ carrierRestrictions.allowedCarriersPrioritized = false;
+ }
serial = GetRandomSerialNumber();
radio_sim->setAllowedCarriers(serial, carrierRestrictions, multisimPolicy);
diff --git a/sensors/aidl/android/hardware/sensors/SensorType.aidl b/sensors/aidl/android/hardware/sensors/SensorType.aidl
index 9098894..4904c3f 100644
--- a/sensors/aidl/android/hardware/sensors/SensorType.aidl
+++ b/sensors/aidl/android/hardware/sensors/SensorType.aidl
@@ -718,8 +718,8 @@
HEADING = 42,
/**
- * Base for device manufacturers private sensor types.
- * These sensor types can't be exposed in the SDK.
+ * Base of the range reserved for device manufacturers' private sensor
+ * types. These sensor types aren't documented in the SDK.
*/
DEVICE_PRIVATE_BASE = 0x10000,
}
diff --git a/sensors/aidl/default/include/sensors-impl/Sensors.h b/sensors/aidl/default/include/sensors-impl/Sensors.h
index 2adbc9d..c90db69 100644
--- a/sensors/aidl/default/include/sensors-impl/Sensors.h
+++ b/sensors/aidl/default/include/sensors-impl/Sensors.h
@@ -97,9 +97,13 @@
return;
}
if (mEventQueue->write(&events.front(), events.size())) {
+ if (mEventQueueFlag == nullptr) {
+ // Don't take the wake lock if we can't wake the receiver to avoid holding it
+ // indefinitely.
+ return;
+ }
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
diff --git a/tests/extension/vibrator/aidl/Android.bp b/tests/extension/vibrator/aidl/Android.bp
index 0306dca..3ef8749 100644
--- a/tests/extension/vibrator/aidl/Android.bp
+++ b/tests/extension/vibrator/aidl/Android.bp
@@ -37,6 +37,15 @@
java: {
enabled: false,
},
+ ndk: {
+ enabled: true,
+ },
+ cpp: {
+ enabled: false,
+ },
+ rust: {
+ enabled: false,
+ },
},
frozen: true,
versions_with_info: [
diff --git a/tests/extension/vibrator/aidl/client/Android.bp b/tests/extension/vibrator/aidl/client/Android.bp
index 284ac74..00510b7 100644
--- a/tests/extension/vibrator/aidl/client/Android.bp
+++ b/tests/extension/vibrator/aidl/client/Android.bp
@@ -16,16 +16,10 @@
srcs: [
// system code has the option to use the unstable C++ libbinder API
// or the NDK one. For maximum code portability, using the ndk client
- // makes the most sense, but both are provided here as an example.
- "test-cpp-client.cpp",
+ // makes the most sense.
"test-ndk-client.cpp",
],
shared_libs: [
- "libbinder",
- "libutils",
- "android.hardware.vibrator-V2-cpp",
- "android.hardware.tests.extension.vibrator-V1-cpp",
-
"libbinder_ndk",
"android.hardware.vibrator-V2-ndk",
"android.hardware.tests.extension.vibrator-V1-ndk",
diff --git a/tests/extension/vibrator/aidl/client/test-cpp-client.cpp b/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
deleted file mode 100644
index 015a345..0000000
--- a/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2019 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 <android/hardware/tests/extension/vibrator/ICustomVibrator.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <binder/IInterface.h>
-#include <binder/IServiceManager.h>
-#include <gtest/gtest.h>
-
-using android::checked_interface_cast;
-using android::IBinder;
-using android::IInterface;
-using android::OK;
-using android::sp;
-using android::waitForVintfService;
-using android::hardware::tests::extension::vibrator::Directionality;
-using android::hardware::tests::extension::vibrator::ICustomVibrator;
-using android::hardware::vibrator::IVibrator;
-
-TEST(Cpp, CallRootMethod) {
- sp<IVibrator> vib = waitForVintfService<IVibrator>();
- ASSERT_NE(nullptr, vib.get());
- ASSERT_TRUE(vib->off().isOk());
-}
-
-TEST(Cpp, CallExtMethod) {
- // normally you would want to cache this
- sp<IVibrator> vib = waitForVintfService<IVibrator>();
- ASSERT_NE(nullptr, vib.get());
-
- // getting the extension
- sp<IBinder> ext;
- ASSERT_EQ(OK, IInterface::asBinder(vib)->getExtension(&ext));
- sp<ICustomVibrator> cvib = checked_interface_cast<ICustomVibrator>(ext);
- ASSERT_NE(nullptr, cvib.get());
-
- // calling extension method
- ASSERT_TRUE(cvib->setDirectionality(Directionality::TRANSVERSE).isOk());
-}
diff --git a/tests/extension/vibrator/aidl/client/test-ndk-client.cpp b/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
index c846495..4dd86e8 100644
--- a/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
+++ b/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
@@ -28,7 +28,7 @@
static const std::string kInstance = std::string() + IVibrator::descriptor + "/default";
TEST(Ndk, CallRootMethod) {
- SpAIBinder vibBinder = SpAIBinder(AServiceManager_getService(kInstance.c_str()));
+ SpAIBinder vibBinder = SpAIBinder(AServiceManager_waitForService(kInstance.c_str()));
ASSERT_NE(nullptr, vibBinder.get());
std::shared_ptr<IVibrator> vib = IVibrator::fromBinder(vibBinder);
ASSERT_NE(nullptr, vib.get());
@@ -38,7 +38,7 @@
TEST(Ndk, CallExtMethod) {
// normally you would want to cache this
//
- SpAIBinder vibBinder = SpAIBinder(AServiceManager_getService(kInstance.c_str()));
+ SpAIBinder vibBinder = SpAIBinder(AServiceManager_waitForService(kInstance.c_str()));
ASSERT_NE(nullptr, vibBinder.get());
std::shared_ptr<IVibrator> vib = IVibrator::fromBinder(vibBinder);
ASSERT_NE(nullptr, vib.get());
diff --git a/tests/extension/vibrator/aidl/default/Android.bp b/tests/extension/vibrator/aidl/default/Android.bp
index 5e156af..479b4fd 100644
--- a/tests/extension/vibrator/aidl/default/Android.bp
+++ b/tests/extension/vibrator/aidl/default/Android.bp
@@ -10,11 +10,6 @@
cc_binary {
name: "android.hardware.tests.extension.vibrator-service.example",
relative_install_path: "hw",
- // normally you implement a service directly, but we are using an implementation
- // from a library to attach our extension to.
- static_libs: [
- "libvibratorexampleimpl",
- ],
// need to add this in the manifest and to init as well to use, see
// android.hardware.vibrator-service.example. This binary is being tested
@@ -23,6 +18,7 @@
vendor: true,
srcs: [
"service.cpp",
+ "Vibrator.cpp",
"CustomVibrator.cpp",
],
shared_libs: [
diff --git a/tests/extension/vibrator/aidl/default/Vibrator.cpp b/tests/extension/vibrator/aidl/default/Vibrator.cpp
new file mode 100644
index 0000000..5084096
--- /dev/null
+++ b/tests/extension/vibrator/aidl/default/Vibrator.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2024 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 "Vibrator.h"
+
+#include <android-base/logging.h>
+
+namespace aidl::android::hardware::vibrator {
+
+ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
+ // basic example with only amplitude control capability
+ *_aidl_return = IVibrator::CAP_AMPLITUDE_CONTROL;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::off() {
+ LOG(INFO) << "Vibrator off";
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs, const std::shared_ptr<IVibratorCallback>&) {
+ LOG(INFO) << "Vibrator on for timeoutMs: " << timeoutMs;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
+ LOG(INFO) << "Vibrator set amplitude: " << amplitude;
+ if (amplitude <= 0.0f || amplitude > 1.0f) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::perform(Effect, EffectStrength,
+ const std::shared_ptr<IVibratorCallback>&, int32_t*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect>* _aidl_return) {
+ *_aidl_return = {};
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::setExternalControl(bool) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive>*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive, int32_t*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect>&,
+ const std::shared_ptr<IVibratorCallback>&) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect>*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t, Effect, EffectStrength) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getResonantFrequency(float*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getQFactor(float*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getFrequencyResolution(float*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float>*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking>*) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle>&,
+ const std::shared_ptr<IVibratorCallback>&) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+} // namespace aidl::android::hardware::vibrator
diff --git a/tests/extension/vibrator/aidl/default/Vibrator.h b/tests/extension/vibrator/aidl/default/Vibrator.h
new file mode 100644
index 0000000..80916ae
--- /dev/null
+++ b/tests/extension/vibrator/aidl/default/Vibrator.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 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/vibrator/BnVibrator.h>
+
+namespace aidl::android::hardware::vibrator {
+
+class Vibrator : public BnVibrator {
+ ndk::ScopedAStatus getCapabilities(int32_t* _aidl_return) override;
+ ndk::ScopedAStatus off() override;
+ ndk::ScopedAStatus on(int32_t timeoutMs,
+ const std::shared_ptr<IVibratorCallback>& callback) override;
+ ndk::ScopedAStatus perform(Effect effect, EffectStrength strength,
+ const std::shared_ptr<IVibratorCallback>& callback,
+ int32_t* _aidl_return) override;
+ ndk::ScopedAStatus getSupportedEffects(std::vector<Effect>* _aidl_return) override;
+ ndk::ScopedAStatus setAmplitude(float amplitude) override;
+ ndk::ScopedAStatus setExternalControl(bool enabled) override;
+ ndk::ScopedAStatus getCompositionDelayMax(int32_t* maxDelayMs);
+ ndk::ScopedAStatus getCompositionSizeMax(int32_t* maxSize);
+ ndk::ScopedAStatus getSupportedPrimitives(std::vector<CompositePrimitive>* supported) override;
+ ndk::ScopedAStatus getPrimitiveDuration(CompositePrimitive primitive,
+ int32_t* durationMs) override;
+ ndk::ScopedAStatus compose(const std::vector<CompositeEffect>& composite,
+ const std::shared_ptr<IVibratorCallback>& callback) override;
+ ndk::ScopedAStatus getSupportedAlwaysOnEffects(std::vector<Effect>* _aidl_return) override;
+ ndk::ScopedAStatus alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) override;
+ ndk::ScopedAStatus alwaysOnDisable(int32_t id) override;
+ ndk::ScopedAStatus getResonantFrequency(float* resonantFreqHz) override;
+ ndk::ScopedAStatus getQFactor(float* qFactor) override;
+ ndk::ScopedAStatus getFrequencyResolution(float* freqResolutionHz) override;
+ ndk::ScopedAStatus getFrequencyMinimum(float* freqMinimumHz) override;
+ ndk::ScopedAStatus getBandwidthAmplitudeMap(std::vector<float>* _aidl_return) override;
+ ndk::ScopedAStatus getPwlePrimitiveDurationMax(int32_t* durationMs) override;
+ ndk::ScopedAStatus getPwleCompositionSizeMax(int32_t* maxSize) override;
+ ndk::ScopedAStatus getSupportedBraking(std::vector<Braking>* supported) override;
+ ndk::ScopedAStatus composePwle(const std::vector<PrimitivePwle>& composite,
+ const std::shared_ptr<IVibratorCallback>& callback) override;
+};
+
+} // namespace aidl::android::hardware::vibrator
diff --git a/tests/extension/vibrator/aidl/default/service.cpp b/tests/extension/vibrator/aidl/default/service.cpp
index 16290df..5917d0f 100644
--- a/tests/extension/vibrator/aidl/default/service.cpp
+++ b/tests/extension/vibrator/aidl/default/service.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include <vibrator-impl/Vibrator.h>
#include "CustomVibrator.h"
+#include "Vibrator.h"
#include <android-base/logging.h>
#include <android/binder_manager.h>
diff --git a/vibrator/aidl/Android.bp b/vibrator/aidl/Android.bp
index b5199e2..b2d98f5 100644
--- a/vibrator/aidl/Android.bp
+++ b/vibrator/aidl/Android.bp
@@ -15,14 +15,33 @@
srcs: [
"android/hardware/vibrator/*.aidl",
],
+ headers: [
+ "PersistableBundle_aidl",
+ ],
stability: "vintf",
backend: {
java: {
sdk_version: "system_current",
},
+ ndk: {
+ enabled: true,
+ },
+ cpp: {
+ enabled: false,
+ },
+ rust: {
+ enabled: false,
+ },
},
- versions: [
- "1",
- "2",
+ versions_with_info: [
+ {
+ version: "1",
+ imports: [],
+ },
+ {
+ version: "2",
+ imports: [],
+ },
],
+ frozen: false,
}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
index b7afb66..af619c6 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
@@ -58,15 +58,17 @@
int getPwleCompositionSizeMax();
android.hardware.vibrator.Braking[] getSupportedBraking();
void composePwle(in android.hardware.vibrator.PrimitivePwle[] composite, in android.hardware.vibrator.IVibratorCallback callback);
- const int CAP_ON_CALLBACK = 1;
- const int CAP_PERFORM_CALLBACK = 2;
- const int CAP_AMPLITUDE_CONTROL = 4;
- const int CAP_EXTERNAL_CONTROL = 8;
- const int CAP_EXTERNAL_AMPLITUDE_CONTROL = 16;
- const int CAP_COMPOSE_EFFECTS = 32;
- const int CAP_ALWAYS_ON_CONTROL = 64;
- const int CAP_GET_RESONANT_FREQUENCY = 128;
- const int CAP_GET_Q_FACTOR = 256;
- const int CAP_FREQUENCY_CONTROL = 512;
- const int CAP_COMPOSE_PWLE_EFFECTS = 1024;
+ void performVendorEffect(in android.hardware.vibrator.VendorEffect vendorEffect, in android.hardware.vibrator.IVibratorCallback callback);
+ const int CAP_ON_CALLBACK = (1 << 0) /* 1 */;
+ const int CAP_PERFORM_CALLBACK = (1 << 1) /* 2 */;
+ const int CAP_AMPLITUDE_CONTROL = (1 << 2) /* 4 */;
+ const int CAP_EXTERNAL_CONTROL = (1 << 3) /* 8 */;
+ const int CAP_EXTERNAL_AMPLITUDE_CONTROL = (1 << 4) /* 16 */;
+ const int CAP_COMPOSE_EFFECTS = (1 << 5) /* 32 */;
+ const int CAP_ALWAYS_ON_CONTROL = (1 << 6) /* 64 */;
+ const int CAP_GET_RESONANT_FREQUENCY = (1 << 7) /* 128 */;
+ const int CAP_GET_Q_FACTOR = (1 << 8) /* 256 */;
+ const int CAP_FREQUENCY_CONTROL = (1 << 9) /* 512 */;
+ const int CAP_COMPOSE_PWLE_EFFECTS = (1 << 10) /* 1024 */;
+ const int CAP_PERFORM_VENDOR_EFFECTS = (1 << 11) /* 2048 */;
}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
index 290c68d..ef5794c 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
@@ -40,12 +40,12 @@
void prepareSynced(in int[] vibratorIds);
void triggerSynced(in android.hardware.vibrator.IVibratorCallback callback);
void cancelSynced();
- const int CAP_SYNC = 1;
- const int CAP_PREPARE_ON = 2;
- const int CAP_PREPARE_PERFORM = 4;
- const int CAP_PREPARE_COMPOSE = 8;
- const int CAP_MIXED_TRIGGER_ON = 16;
- const int CAP_MIXED_TRIGGER_PERFORM = 32;
- const int CAP_MIXED_TRIGGER_COMPOSE = 64;
- const int CAP_TRIGGER_CALLBACK = 128;
+ const int CAP_SYNC = (1 << 0) /* 1 */;
+ const int CAP_PREPARE_ON = (1 << 1) /* 2 */;
+ const int CAP_PREPARE_PERFORM = (1 << 2) /* 4 */;
+ const int CAP_PREPARE_COMPOSE = (1 << 3) /* 8 */;
+ const int CAP_MIXED_TRIGGER_ON = (1 << 4) /* 16 */;
+ const int CAP_MIXED_TRIGGER_PERFORM = (1 << 5) /* 32 */;
+ const int CAP_MIXED_TRIGGER_COMPOSE = (1 << 6) /* 64 */;
+ const int CAP_TRIGGER_CALLBACK = (1 << 7) /* 128 */;
}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/VendorEffect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/VendorEffect.aidl
new file mode 100644
index 0000000..1900084
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/VendorEffect.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 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.vibrator;
+@VintfStability
+parcelable VendorEffect {
+ android.os.PersistableBundle vendorData;
+ android.hardware.vibrator.EffectStrength strength = android.hardware.vibrator.EffectStrength.MEDIUM;
+ float scale;
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/Braking.aidl b/vibrator/aidl/android/hardware/vibrator/Braking.aidl
index 2bc51db..f934ff2 100644
--- a/vibrator/aidl/android/hardware/vibrator/Braking.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/Braking.aidl
@@ -23,12 +23,12 @@
* No braking mechanism used.
* This is the default if the hardware does not support any braking mechanism.
*/
- NONE,
+ NONE = 0,
/**
* Closed-loop active braking.
*
* This effect should produce a sharp, crisp end to the waveform
* Support is optional.
*/
- CLAB,
+ CLAB = 1,
}
diff --git a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
index 5314898..5f8ee8d 100644
--- a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
@@ -24,13 +24,13 @@
*
* Support is required.
*/
- NOOP,
+ NOOP = 0,
/**
* This effect should produce a sharp, crisp click sensation.
*
* Support is required.
*/
- CLICK,
+ CLICK = 1,
/**
* A haptic effect that simulates downwards movement with gravity. Often
* followed by extra energy of hitting and reverberation to augment
@@ -38,43 +38,43 @@
*
* Support is optional.
*/
- THUD,
+ THUD = 2,
/**
* A haptic effect that simulates spinning momentum.
*
* Support is optional.
*/
- SPIN,
+ SPIN = 3,
/**
* A haptic effect that simulates quick upward movement against gravity.
*
* Support is required.
*/
- QUICK_RISE,
+ QUICK_RISE = 4,
/**
* A haptic effect that simulates slow upward movement against gravity.
*
* Support is required.
*/
- SLOW_RISE,
+ SLOW_RISE = 5,
/**
* A haptic effect that simulates quick downwards movement with gravity.
*
* Support is required.
*/
- QUICK_FALL,
+ QUICK_FALL = 6,
/**
* This very short effect should produce a light crisp sensation intended
* to be used repetitively for dynamic feedback.
*
* Support is required.
*/
- LIGHT_TICK,
+ LIGHT_TICK = 7,
/**
* This very short low frequency effect should produce a light crisp sensation intended
* to be used repetitively for dynamic feedback.
*
* Support is required.
*/
- LOW_TICK,
+ LOW_TICK = 8,
}
diff --git a/vibrator/aidl/android/hardware/vibrator/Effect.aidl b/vibrator/aidl/android/hardware/vibrator/Effect.aidl
index c60bfe9..f5cf9e3 100644
--- a/vibrator/aidl/android/hardware/vibrator/Effect.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/Effect.aidl
@@ -24,57 +24,57 @@
*
* This effect should produce a sharp, crisp click sensation.
*/
- CLICK,
+ CLICK = 0,
/**
* A double click effect.
*
* This effect should produce two sequential sharp, crisp click sensations with a minimal
* amount of time between them.
*/
- DOUBLE_CLICK,
+ DOUBLE_CLICK = 1,
/**
* A tick effect.
*
* This effect should produce a soft, short sensation, like the tick of a clock.
*/
- TICK,
+ TICK = 2,
/**
* A thud effect.
*
* This effect should solid feeling bump, like the depression of a heavy mechanical button.
*/
- THUD,
+ THUD = 3,
/**
* A pop effect.
*
* A short, quick burst effect.
*/
- POP,
+ POP = 4,
/**
* A heavy click effect.
*
* This should produce a sharp striking sensation, like a click but stronger.
*/
- HEAVY_CLICK,
+ HEAVY_CLICK = 5,
/**
* Ringtone patterns. They may correspond with the device's ringtone audio, or may just be a
* pattern that can be played as a ringtone with any audio, depending on the device.
*/
- RINGTONE_1,
- RINGTONE_2,
- RINGTONE_3,
- RINGTONE_4,
- RINGTONE_5,
- RINGTONE_6,
- RINGTONE_7,
- RINGTONE_8,
- RINGTONE_9,
- RINGTONE_10,
- RINGTONE_11,
- RINGTONE_12,
- RINGTONE_13,
- RINGTONE_14,
- RINGTONE_15,
+ RINGTONE_1 = 6,
+ RINGTONE_2 = 7,
+ RINGTONE_3 = 8,
+ RINGTONE_4 = 9,
+ RINGTONE_5 = 10,
+ RINGTONE_6 = 11,
+ RINGTONE_7 = 12,
+ RINGTONE_8 = 13,
+ RINGTONE_9 = 14,
+ RINGTONE_10 = 15,
+ RINGTONE_11 = 16,
+ RINGTONE_12 = 17,
+ RINGTONE_13 = 18,
+ RINGTONE_14 = 19,
+ RINGTONE_15 = 20,
/**
* A soft tick effect meant to be played as a texture.
*
@@ -82,5 +82,5 @@
* are expected to be played multiple times in quick succession, replicating a specific
* texture to the user as a form of haptic feedback.
*/
- TEXTURE_TICK,
+ TEXTURE_TICK = 21,
}
diff --git a/vibrator/aidl/android/hardware/vibrator/EffectStrength.aidl b/vibrator/aidl/android/hardware/vibrator/EffectStrength.aidl
index 66f70e5..c6a78d4 100644
--- a/vibrator/aidl/android/hardware/vibrator/EffectStrength.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/EffectStrength.aidl
@@ -19,7 +19,7 @@
@VintfStability
@Backing(type="byte")
enum EffectStrength {
- LIGHT,
- MEDIUM,
- STRONG,
+ LIGHT = 0,
+ MEDIUM = 1,
+ STRONG = 2,
}
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index b4e7e44..768ec4f 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -16,13 +16,14 @@
package android.hardware.vibrator;
-import android.hardware.vibrator.IVibratorCallback;
import android.hardware.vibrator.Braking;
-import android.hardware.vibrator.Effect;
-import android.hardware.vibrator.EffectStrength;
import android.hardware.vibrator.CompositeEffect;
import android.hardware.vibrator.CompositePrimitive;
+import android.hardware.vibrator.Effect;
+import android.hardware.vibrator.EffectStrength;
+import android.hardware.vibrator.IVibratorCallback;
import android.hardware.vibrator.PrimitivePwle;
+import android.hardware.vibrator.VendorEffect;
@VintfStability
interface IVibrator {
@@ -70,6 +71,10 @@
* Whether composePwle is supported.
*/
const int CAP_COMPOSE_PWLE_EFFECTS = 1 << 10;
+ /**
+ * Whether perform w/ vendor effect is supported.
+ */
+ const int CAP_PERFORM_VENDOR_EFFECTS = 1 << 11;
/**
* Determine capabilities of the vibrator HAL (CAP_* mask)
@@ -359,4 +364,25 @@
* @param composite Array of PWLEs.
*/
void composePwle(in PrimitivePwle[] composite, in IVibratorCallback callback);
+
+ /**
+ * Fire off a vendor-defined haptic event.
+ *
+ * This may not be supported and this support is reflected in
+ * getCapabilities (CAP_PERFORM_VENDOR_EFFECTS).
+ *
+ * The duration of the effect is unknown and can be undefined for looping effects.
+ * IVibratorCallback.onComplete() support is required for this API.
+ *
+ * Doing this operation while the vibrator is already on is undefined behavior. Clients should
+ * explicitly call off.
+ *
+ * @param effect The vendor data representing the effect to be performed.
+ * @param callback A callback used to inform Frameworks of state change.
+ * @throws :
+ * - EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities.
+ * - EX_ILLEGAL_ARGUMENT for bad framework parameters, e.g. scale or effect strength.
+ * - EX_SERVICE_SPECIFIC for bad vendor data, vibration is not triggered.
+ */
+ void performVendorEffect(in VendorEffect vendorEffect, in IVibratorCallback callback);
}
diff --git a/vibrator/aidl/android/hardware/vibrator/VendorEffect.aidl b/vibrator/aidl/android/hardware/vibrator/VendorEffect.aidl
new file mode 100644
index 0000000..2155aca
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/VendorEffect.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 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.vibrator;
+
+import android.hardware.vibrator.EffectStrength;
+import android.os.PersistableBundle;
+
+@VintfStability
+parcelable VendorEffect {
+ /**
+ * Vendor data describing the haptic effect. Expected fields should be defined by the vendor.
+ *
+ * Vendors can use this as a platform extension point for experimental hardware capabilities,
+ * but they are strongly discouraged from using it as an alternative to the AOSP support for
+ * stable vibrator APIs. Implemenitng vendor-specific custom effects outside the platform APIs
+ * will hinder portability for the code and overall user experience.
+ *
+ * Vendors are encouraged to upstream new capabilities to the IVibrator surface once it has
+ * matured into a stable interface.
+ */
+ PersistableBundle vendorData;
+
+ /**
+ * The intensity of the haptic effect.
+ */
+ EffectStrength strength = EffectStrength.MEDIUM;
+
+ /**
+ * A scale to be applied to the haptic effect intensity.
+ *
+ * This value represents a linear scale that should be applied on top of the effect strength to
+ * dynamically adapt to the device state.
+ *
+ * Values in [0,1) should scale down. Values > 1 should scale up within hardware bounds.
+ */
+ float scale;
+}
diff --git a/vibrator/aidl/default/Android.bp b/vibrator/aidl/default/Android.bp
index 0f342db..4b26640 100644
--- a/vibrator/aidl/default/Android.bp
+++ b/vibrator/aidl/default/Android.bp
@@ -15,7 +15,7 @@
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.vibrator-V2-ndk",
+ "android.hardware.vibrator-V3-ndk",
],
export_include_dirs: ["include"],
srcs: [
@@ -49,7 +49,7 @@
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.vibrator-V2-ndk",
+ "android.hardware.vibrator-V3-ndk",
],
static_libs: [
"libvibratorexampleimpl",
@@ -62,7 +62,7 @@
host_supported: true,
defaults: ["service_fuzzer_defaults"],
static_libs: [
- "android.hardware.vibrator-V2-ndk",
+ "android.hardware.vibrator-V3-ndk",
"liblog",
"libvibratorexampleimpl",
],
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index 01602ab..acf7d34 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -39,6 +39,9 @@
static constexpr float PWLE_BW_MAP_SIZE =
1 + ((PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ);
+// Service specific error code used for vendor vibration effects.
+static constexpr int32_t ERROR_CODE_INVALID_DURATION = 1;
+
ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
LOG(VERBOSE) << "Vibrator reporting capabilities";
*_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
@@ -46,7 +49,7 @@
IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS |
IVibrator::CAP_ALWAYS_ON_CONTROL | IVibrator::CAP_GET_RESONANT_FREQUENCY |
IVibrator::CAP_GET_Q_FACTOR | IVibrator::CAP_FREQUENCY_CONTROL |
- IVibrator::CAP_COMPOSE_PWLE_EFFECTS;
+ IVibrator::CAP_COMPOSE_PWLE_EFFECTS | IVibrator::CAP_PERFORM_VENDOR_EFFECTS;
return ndk::ScopedAStatus::ok();
}
@@ -102,6 +105,36 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Vibrator::performVendorEffect(
+ const VendorEffect& effect, const std::shared_ptr<IVibratorCallback>& callback) {
+ LOG(VERBOSE) << "Vibrator perform vendor effect";
+ EffectStrength strength = effect.strength;
+ if (strength != EffectStrength::LIGHT && strength != EffectStrength::MEDIUM &&
+ strength != EffectStrength::STRONG) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
+ }
+ float scale = effect.scale;
+ if (scale <= 0) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ int32_t durationMs = 0;
+ if (!effect.vendorData.getInt("DURATION_MS", &durationMs) || durationMs <= 0) {
+ return ndk::ScopedAStatus::fromServiceSpecificError(ERROR_CODE_INVALID_DURATION);
+ }
+
+ if (callback != nullptr) {
+ std::thread([callback, durationMs] {
+ LOG(VERBOSE) << "Starting perform on another thread for durationMs:" << durationMs;
+ usleep(durationMs * 1000);
+ LOG(VERBOSE) << "Notifying perform vendor effect complete";
+ callback->onComplete();
+ }).detach();
+ }
+
+ return ndk::ScopedAStatus::ok();
+}
+
ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect>* _aidl_return) {
*_aidl_return = {Effect::CLICK, Effect::TICK};
return ndk::ScopedAStatus::ok();
diff --git a/vibrator/aidl/default/android.hardware.vibrator.xml b/vibrator/aidl/default/android.hardware.vibrator.xml
index b5bd3dd..b730046 100644
--- a/vibrator/aidl/default/android.hardware.vibrator.xml
+++ b/vibrator/aidl/default/android.hardware.vibrator.xml
@@ -1,12 +1,12 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.vibrator</name>
- <version>2</version>
+ <version>3</version>
<fqname>IVibrator/default</fqname>
</hal>
<hal format="aidl">
<name>android.hardware.vibrator</name>
- <version>2</version>
+ <version>3</version>
<fqname>IVibratorManager/default</fqname>
</hal>
</manifest>
diff --git a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
index 4203bf2..e8f64ca 100644
--- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
+++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
@@ -31,6 +31,9 @@
ndk::ScopedAStatus perform(Effect effect, EffectStrength strength,
const std::shared_ptr<IVibratorCallback>& callback,
int32_t* _aidl_return) override;
+ ndk::ScopedAStatus performVendorEffect(
+ const VendorEffect& effect,
+ const std::shared_ptr<IVibratorCallback>& callback) override;
ndk::ScopedAStatus getSupportedEffects(std::vector<Effect>* _aidl_return) override;
ndk::ScopedAStatus setAmplitude(float amplitude) override;
ndk::ScopedAStatus setExternalControl(bool enabled) override;
diff --git a/vibrator/aidl/vts/Android.bp b/vibrator/aidl/vts/Android.bp
index b6d2fb2..a48bb2e 100644
--- a/vibrator/aidl/vts/Android.bp
+++ b/vibrator/aidl/vts/Android.bp
@@ -17,10 +17,10 @@
tidy_timeout_srcs: ["VtsHalVibratorTargetTest.cpp"],
srcs: ["VtsHalVibratorTargetTest.cpp"],
shared_libs: [
- "libbinder",
+ "libbinder_ndk",
],
static_libs: [
- "android.hardware.vibrator-V2-cpp",
+ "android.hardware.vibrator-V3-ndk",
],
test_suites: [
"general-tests",
@@ -36,10 +36,10 @@
],
srcs: ["VtsHalVibratorManagerTargetTest.cpp"],
shared_libs: [
- "libbinder",
+ "libbinder_ndk",
],
static_libs: [
- "android.hardware.vibrator-V2-cpp",
+ "android.hardware.vibrator-V3-ndk",
],
test_suites: [
"general-tests",
diff --git a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
index e8ed26a..3c2a360 100644
--- a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
@@ -15,42 +15,40 @@
*/
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
+#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+#include <aidl/android/hardware/vibrator/IVibratorManager.h>
-#include <android/hardware/vibrator/BnVibratorCallback.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <android/hardware/vibrator/IVibratorManager.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
#include <cmath>
#include <future>
-using android::ProcessState;
-using android::sp;
-using android::String16;
-using android::binder::Status;
-using android::hardware::vibrator::BnVibratorCallback;
-using android::hardware::vibrator::CompositeEffect;
-using android::hardware::vibrator::CompositePrimitive;
-using android::hardware::vibrator::Effect;
-using android::hardware::vibrator::EffectStrength;
-using android::hardware::vibrator::IVibrator;
-using android::hardware::vibrator::IVibratorManager;
+#include "test_utils.h"
+
+using aidl::android::hardware::vibrator::BnVibratorCallback;
+using aidl::android::hardware::vibrator::CompositeEffect;
+using aidl::android::hardware::vibrator::CompositePrimitive;
+using aidl::android::hardware::vibrator::Effect;
+using aidl::android::hardware::vibrator::EffectStrength;
+using aidl::android::hardware::vibrator::IVibrator;
+using aidl::android::hardware::vibrator::IVibratorManager;
using std::chrono::high_resolution_clock;
-const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
- android::enum_range<Effect>().end()};
-const std::vector<EffectStrength> kEffectStrengths{android::enum_range<EffectStrength>().begin(),
- android::enum_range<EffectStrength>().end()};
-const std::vector<CompositePrimitive> kPrimitives{android::enum_range<CompositePrimitive>().begin(),
- android::enum_range<CompositePrimitive>().end()};
+const std::vector<Effect> kEffects{ndk::enum_range<Effect>().begin(),
+ ndk::enum_range<Effect>().end()};
+const std::vector<EffectStrength> kEffectStrengths{ndk::enum_range<EffectStrength>().begin(),
+ ndk::enum_range<EffectStrength>().end()};
+const std::vector<CompositePrimitive> kPrimitives{ndk::enum_range<CompositePrimitive>().begin(),
+ ndk::enum_range<CompositePrimitive>().end()};
class CompletionCallback : public BnVibratorCallback {
public:
CompletionCallback(const std::function<void()>& callback) : mCallback(callback) {}
- Status onComplete() override {
+ ndk::ScopedAStatus onComplete() override {
mCallback();
- return Status::ok();
+ return ndk::ScopedAStatus::ok();
}
private:
@@ -60,55 +58,50 @@
class VibratorAidl : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
- manager = android::waitForDeclaredService<IVibratorManager>(String16(GetParam().c_str()));
+ auto serviceName = GetParam().c_str();
+ manager = IVibratorManager::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(serviceName)));
ASSERT_NE(manager, nullptr);
- ASSERT_TRUE(manager->getCapabilities(&capabilities).isOk());
- EXPECT_TRUE(manager->getVibratorIds(&vibratorIds).isOk());
+ EXPECT_OK(manager->getCapabilities(&capabilities));
+ EXPECT_OK(manager->getVibratorIds(&vibratorIds));
}
- sp<IVibratorManager> manager;
+ std::shared_ptr<IVibratorManager> manager;
int32_t capabilities;
std::vector<int32_t> vibratorIds;
};
-inline bool isUnknownOrUnsupported(Status status) {
- return status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
- status.transactionError() == android::UNKNOWN_TRANSACTION;
-}
-
TEST_P(VibratorAidl, ValidateExistingVibrators) {
- sp<IVibrator> vibrator;
- for (auto& id : vibratorIds) {
- EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+ std::shared_ptr<IVibrator> vibrator;
+ for (int32_t id : vibratorIds) {
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
ASSERT_NE(vibrator, nullptr);
}
}
TEST_P(VibratorAidl, GetVibratorWithInvalidId) {
int32_t invalidId = *max_element(vibratorIds.begin(), vibratorIds.end()) + 1;
- sp<IVibrator> vibrator;
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
- manager->getVibrator(invalidId, &vibrator).exceptionCode());
+ std::shared_ptr<IVibrator> vibrator;
+ EXPECT_ILLEGAL_ARGUMENT(manager->getVibrator(invalidId, &vibrator));
ASSERT_EQ(vibrator, nullptr);
}
TEST_P(VibratorAidl, ValidatePrepareSyncedExistingVibrators) {
if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
if (vibratorIds.empty()) return;
- EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
- EXPECT_TRUE(manager->cancelSynced().isOk());
+ EXPECT_OK(manager->prepareSynced(vibratorIds));
+ EXPECT_OK(manager->cancelSynced());
}
TEST_P(VibratorAidl, PrepareSyncedEmptySetIsInvalid) {
if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
std::vector<int32_t> emptyIds;
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, manager->prepareSynced(emptyIds).exceptionCode());
+ EXPECT_ILLEGAL_ARGUMENT(manager->prepareSynced(emptyIds));
}
TEST_P(VibratorAidl, PrepareSyncedNotSupported) {
if (!(capabilities & IVibratorManager::CAP_SYNC)) {
- Status status = manager->prepareSynced(vibratorIds);
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(manager->prepareSynced(vibratorIds));
}
}
@@ -117,15 +110,14 @@
if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) {
uint32_t durationMs = 250;
- EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
- sp<IVibrator> vibrator;
- for (auto& id : vibratorIds) {
- EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+ EXPECT_OK(manager->prepareSynced(vibratorIds));
+ std::shared_ptr<IVibrator> vibrator;
+ for (int32_t id : vibratorIds) {
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
ASSERT_NE(vibrator, nullptr);
- Status status = vibrator->on(durationMs, nullptr);
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->on(durationMs, nullptr));
}
- EXPECT_TRUE(manager->cancelSynced().isOk());
+ EXPECT_OK(manager->cancelSynced());
}
}
@@ -133,16 +125,16 @@
if (vibratorIds.empty()) return;
if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) {
- EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
- sp<IVibrator> vibrator;
- for (auto& id : vibratorIds) {
- EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+ EXPECT_OK(manager->prepareSynced(vibratorIds));
+ std::shared_ptr<IVibrator> vibrator;
+ for (int32_t id : vibratorIds) {
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
ASSERT_NE(vibrator, nullptr);
int32_t lengthMs = 0;
- Status status = vibrator->perform(kEffects[0], kEffectStrengths[0], nullptr, &lengthMs);
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(
+ vibrator->perform(kEffects[0], kEffectStrengths[0], nullptr, &lengthMs));
}
- EXPECT_TRUE(manager->cancelSynced().isOk());
+ EXPECT_OK(manager->cancelSynced());
}
}
@@ -157,15 +149,14 @@
effect.scale = 1.0f;
composite.emplace_back(effect);
- EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
- sp<IVibrator> vibrator;
- for (auto& id : vibratorIds) {
- EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+ EXPECT_OK(manager->prepareSynced(vibratorIds));
+ std::shared_ptr<IVibrator> vibrator;
+ for (int32_t id : vibratorIds) {
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
ASSERT_NE(vibrator, nullptr);
- Status status = vibrator->compose(composite, nullptr);
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->compose(composite, nullptr));
}
- EXPECT_TRUE(manager->cancelSynced().isOk());
+ EXPECT_OK(manager->cancelSynced());
}
}
@@ -177,51 +168,58 @@
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
- sp<CompletionCallback> callback =
- new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+ auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&completionPromise] { completionPromise.set_value(); });
uint32_t durationMs = 250;
std::chrono::milliseconds timeout{durationMs * 2};
- EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
- sp<IVibrator> vibrator;
- for (auto& id : vibratorIds) {
- EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+ EXPECT_OK(manager->prepareSynced(vibratorIds));
+ std::shared_ptr<IVibrator> vibrator;
+ for (int32_t id : vibratorIds) {
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
ASSERT_NE(vibrator, nullptr);
- EXPECT_TRUE(vibrator->on(durationMs, nullptr).isOk());
+ EXPECT_OK(vibrator->on(durationMs, nullptr));
}
- EXPECT_TRUE(manager->triggerSynced(callback).isOk());
+ EXPECT_OK(manager->triggerSynced(callback));
EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
- EXPECT_TRUE(manager->cancelSynced().isOk());
+ EXPECT_OK(manager->cancelSynced());
}
TEST_P(VibratorAidl, TriggerSyncNotSupported) {
if (!(capabilities & IVibratorManager::CAP_SYNC)) {
- Status status = manager->triggerSynced(nullptr);
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(manager->triggerSynced(nullptr));
}
}
TEST_P(VibratorAidl, TriggerCallbackNotSupported) {
if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
if (!(capabilities & IVibratorManager::CAP_TRIGGER_CALLBACK)) {
- sp<CompletionCallback> callback = new CompletionCallback([] {});
- EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
- Status status = manager->triggerSynced(callback);
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
- EXPECT_TRUE(manager->cancelSynced().isOk());
+ auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
+ EXPECT_OK(manager->prepareSynced(vibratorIds));
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(manager->triggerSynced(callback));
+ EXPECT_OK(manager->cancelSynced());
}
}
+std::vector<std::string> FindVibratorManagerNames() {
+ std::vector<std::string> names;
+ constexpr auto callback = [](const char* instance, void* context) {
+ std::string fullName = std::string(IVibratorManager::descriptor) + "/" + instance;
+ static_cast<std::vector<std::string>*>(context)->emplace_back(fullName);
+ };
+ AServiceManager_forEachDeclaredInstance(IVibratorManager::descriptor,
+ static_cast<void*>(&names), callback);
+ return names;
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorAidl);
-INSTANTIATE_TEST_SUITE_P(
- Vibrator, VibratorAidl,
- testing::ValuesIn(android::getAidlHalInstanceNames(IVibratorManager::descriptor)),
- android::PrintInstanceNameToString);
+INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl, testing::ValuesIn(FindVibratorManagerNames()),
+ android::PrintInstanceNameToString);
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
- ProcessState::self()->setThreadPoolMaxThreadCount(1);
- ProcessState::self()->startThreadPool();
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
}
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index db474d6..706ab41 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -15,38 +15,43 @@
*/
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
-#include <android/hardware/vibrator/BnVibratorCallback.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <android/hardware/vibrator/IVibratorManager.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
+#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+#include <aidl/android/hardware/vibrator/IVibratorManager.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/persistable_bundle_aidl.h>
#include <cmath>
+#include <cstdlib>
+#include <ctime>
#include <future>
-using android::ProcessState;
-using android::sp;
-using android::String16;
-using android::binder::Status;
-using android::hardware::vibrator::ActivePwle;
-using android::hardware::vibrator::BnVibratorCallback;
-using android::hardware::vibrator::Braking;
-using android::hardware::vibrator::BrakingPwle;
-using android::hardware::vibrator::CompositeEffect;
-using android::hardware::vibrator::CompositePrimitive;
-using android::hardware::vibrator::Effect;
-using android::hardware::vibrator::EffectStrength;
-using android::hardware::vibrator::IVibrator;
-using android::hardware::vibrator::IVibratorManager;
-using android::hardware::vibrator::PrimitivePwle;
+#include "persistable_bundle_utils.h"
+#include "test_utils.h"
+
+using aidl::android::hardware::vibrator::ActivePwle;
+using aidl::android::hardware::vibrator::BnVibratorCallback;
+using aidl::android::hardware::vibrator::Braking;
+using aidl::android::hardware::vibrator::BrakingPwle;
+using aidl::android::hardware::vibrator::CompositeEffect;
+using aidl::android::hardware::vibrator::CompositePrimitive;
+using aidl::android::hardware::vibrator::Effect;
+using aidl::android::hardware::vibrator::EffectStrength;
+using aidl::android::hardware::vibrator::IVibrator;
+using aidl::android::hardware::vibrator::IVibratorManager;
+using aidl::android::hardware::vibrator::PrimitivePwle;
+using aidl::android::hardware::vibrator::VendorEffect;
+using aidl::android::os::PersistableBundle;
using std::chrono::high_resolution_clock;
using namespace ::std::chrono_literals;
-const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
- android::enum_range<Effect>().end()};
-const std::vector<EffectStrength> kEffectStrengths{android::enum_range<EffectStrength>().begin(),
- android::enum_range<EffectStrength>().end()};
+const std::vector<Effect> kEffects{ndk::enum_range<Effect>().begin(),
+ ndk::enum_range<Effect>().end()};
+const std::vector<EffectStrength> kEffectStrengths{ndk::enum_range<EffectStrength>().begin(),
+ ndk::enum_range<EffectStrength>().end()};
const std::vector<Effect> kInvalidEffects = {
static_cast<Effect>(static_cast<int32_t>(kEffects.front()) - 1),
@@ -59,8 +64,7 @@
};
const std::vector<CompositePrimitive> kCompositePrimitives{
- android::enum_range<CompositePrimitive>().begin(),
- android::enum_range<CompositePrimitive>().end()};
+ ndk::enum_range<CompositePrimitive>().begin(), ndk::enum_range<CompositePrimitive>().end()};
const std::vector<CompositePrimitive> kRequiredPrimitives = {
CompositePrimitive::CLICK, CompositePrimitive::LIGHT_TICK,
@@ -74,14 +78,36 @@
};
// Timeout to wait for vibration callback completion.
-static constexpr auto VIBRATION_CALLBACK_TIMEOUT = 100ms;
+static constexpr std::chrono::milliseconds VIBRATION_CALLBACK_TIMEOUT = 100ms;
+
+static std::vector<std::string> findVibratorManagerNames() {
+ std::vector<std::string> names;
+ constexpr auto callback = [](const char* instance, void* context) {
+ auto fullName = std::string(IVibratorManager::descriptor) + "/" + instance;
+ static_cast<std::vector<std::string>*>(context)->emplace_back(fullName);
+ };
+ AServiceManager_forEachDeclaredInstance(IVibratorManager::descriptor,
+ static_cast<void*>(&names), callback);
+ return names;
+}
+
+static std::vector<std::string> findUnmanagedVibratorNames() {
+ std::vector<std::string> names;
+ constexpr auto callback = [](const char* instance, void* context) {
+ auto fullName = std::string(IVibrator::descriptor) + "/" + instance;
+ static_cast<std::vector<std::string>*>(context)->emplace_back(fullName);
+ };
+ AServiceManager_forEachDeclaredInstance(IVibrator::descriptor, static_cast<void*>(&names),
+ callback);
+ return names;
+}
class CompletionCallback : public BnVibratorCallback {
public:
CompletionCallback(const std::function<void()> &callback) : mCallback(callback) {}
- Status onComplete() override {
+ ndk::ScopedAStatus onComplete() override {
mCallback();
- return Status::ok();
+ return ndk::ScopedAStatus::ok();
}
private:
@@ -93,88 +119,87 @@
virtual void SetUp() override {
int32_t managerIdx = std::get<0>(GetParam());
int32_t vibratorId = std::get<1>(GetParam());
- auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
if (managerIdx < 0) {
// Testing a unmanaged vibrator, using vibratorId as index from registered HALs
- auto vibratorAidlNames = android::getAidlHalInstanceNames(IVibrator::descriptor);
- ASSERT_LT(vibratorId, vibratorAidlNames.size());
- auto vibratorName = String16(vibratorAidlNames[vibratorId].c_str());
- vibrator = android::waitForDeclaredService<IVibrator>(vibratorName);
+ std::vector<std::string> vibratorNames = findUnmanagedVibratorNames();
+ ASSERT_LT(vibratorId, vibratorNames.size());
+ vibrator = IVibrator::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService(vibratorNames[vibratorId].c_str())));
} else {
// Testing a managed vibrator, using vibratorId to retrieve it from the manager
- ASSERT_LT(managerIdx, managerAidlNames.size());
- auto managerName = String16(managerAidlNames[managerIdx].c_str());
- auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
- auto vibratorResult = vibratorManager->getVibrator(vibratorId, &vibrator);
- ASSERT_TRUE(vibratorResult.isOk());
+ std::vector<std::string> managerNames = findVibratorManagerNames();
+ ASSERT_LT(managerIdx, managerNames.size());
+ auto vibratorManager = IVibratorManager::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService(managerNames[managerIdx].c_str())));
+ EXPECT_OK(vibratorManager->getVibrator(vibratorId, &vibrator))
+ << "\n For vibrator id: " << vibratorId;
}
ASSERT_NE(vibrator, nullptr);
- ASSERT_TRUE(vibrator->getCapabilities(&capabilities).isOk());
+ EXPECT_OK(vibrator->getCapabilities(&capabilities));
}
virtual void TearDown() override {
// Reset vibrator state between tests.
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->off());
}
- sp<IVibrator> vibrator;
+ std::shared_ptr<IVibrator> vibrator;
int32_t capabilities;
};
-inline bool isUnknownOrUnsupported(Status status) {
- return status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
- status.transactionError() == android::UNKNOWN_TRANSACTION;
-}
-
-static float getResonantFrequencyHz(sp<IVibrator> vibrator, int32_t capabilities) {
+static float getResonantFrequencyHz(const std::shared_ptr<IVibrator>& vibrator,
+ int32_t capabilities) {
float resonantFrequencyHz;
- Status status = vibrator->getResonantFrequency(&resonantFrequencyHz);
+ ndk::ScopedAStatus status = vibrator->getResonantFrequency(&resonantFrequencyHz);
if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
+ EXPECT_OK(std::move(status));
EXPECT_GT(resonantFrequencyHz, 0);
- EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
}
return resonantFrequencyHz;
}
-static float getFrequencyResolutionHz(sp<IVibrator> vibrator, int32_t capabilities) {
+static float getFrequencyResolutionHz(const std::shared_ptr<IVibrator>& vibrator,
+ int32_t capabilities) {
float freqResolutionHz;
- Status status = vibrator->getFrequencyResolution(&freqResolutionHz);
+ ndk::ScopedAStatus status = vibrator->getFrequencyResolution(&freqResolutionHz);
if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+ EXPECT_OK(std::move(status));
EXPECT_GT(freqResolutionHz, 0);
- EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
}
return freqResolutionHz;
}
-static float getFrequencyMinimumHz(sp<IVibrator> vibrator, int32_t capabilities) {
+static float getFrequencyMinimumHz(const std::shared_ptr<IVibrator>& vibrator,
+ int32_t capabilities) {
float freqMinimumHz;
- Status status = vibrator->getFrequencyMinimum(&freqMinimumHz);
+ ndk::ScopedAStatus status = vibrator->getFrequencyMinimum(&freqMinimumHz);
if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
- EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+ EXPECT_OK(std::move(status));
float resonantFrequencyHz = getResonantFrequencyHz(vibrator, capabilities);
EXPECT_GT(freqMinimumHz, 0);
EXPECT_LE(freqMinimumHz, resonantFrequencyHz);
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
}
return freqMinimumHz;
}
-static float getFrequencyMaximumHz(sp<IVibrator> vibrator, int32_t capabilities) {
+static float getFrequencyMaximumHz(const std::shared_ptr<IVibrator>& vibrator,
+ int32_t capabilities) {
std::vector<float> bandwidthAmplitudeMap;
- Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
+ ndk::ScopedAStatus status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
- EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+ EXPECT_OK(std::move(status));
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
}
float freqMaximumHz = ((bandwidthAmplitudeMap.size() - 1) *
@@ -191,7 +216,8 @@
return 1.0;
}
-static ActivePwle composeValidActivePwle(sp<IVibrator> vibrator, int32_t capabilities) {
+static ActivePwle composeValidActivePwle(const std::shared_ptr<IVibrator>& vibrator,
+ int32_t capabilities) {
float frequencyHz;
if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
frequencyHz = getResonantFrequencyHz(vibrator, capabilities);
@@ -212,9 +238,9 @@
}
TEST_P(VibratorAidl, OnThenOffBeforeTimeout) {
- EXPECT_TRUE(vibrator->on(2000, nullptr /*callback*/).isOk());
+ EXPECT_OK(vibrator->on(2000, nullptr /*callback*/));
sleep(1);
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->off());
}
TEST_P(VibratorAidl, OnWithCallback) {
@@ -223,26 +249,25 @@
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
- sp<CompletionCallback> callback =
- new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+ auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&completionPromise] { completionPromise.set_value(); });
uint32_t durationMs = 250;
auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT;
- EXPECT_TRUE(vibrator->on(durationMs, callback).isOk());
+ EXPECT_OK(vibrator->on(durationMs, callback));
EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->off());
}
TEST_P(VibratorAidl, OnCallbackNotSupported) {
if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) {
- sp<CompletionCallback> callback = new CompletionCallback([] {});
- Status status = vibrator->on(250, callback);
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->on(250, callback));
}
}
TEST_P(VibratorAidl, ValidateEffect) {
std::vector<Effect> supported;
- ASSERT_TRUE(vibrator->getSupportedEffects(&supported).isOk());
+ EXPECT_OK(vibrator->getSupportedEffects(&supported));
for (Effect effect : kEffects) {
bool isEffectSupported =
@@ -250,15 +275,18 @@
for (EffectStrength strength : kEffectStrengths) {
int32_t lengthMs = 0;
- Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
+ ndk::ScopedAStatus status =
+ vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
if (isEffectSupported) {
- EXPECT_TRUE(status.isOk()) << toString(effect) << " " << toString(strength);
+ EXPECT_OK(std::move(status))
+ << "\n For effect: " << toString(effect) << " " << toString(strength);
EXPECT_GT(lengthMs, 0);
usleep(lengthMs * 1000);
+ EXPECT_OK(vibrator->off());
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status))
- << status << " " << toString(effect) << " " << toString(strength);
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status))
+ << "\n For effect: " << toString(effect) << " " << toString(strength);
}
}
}
@@ -269,7 +297,7 @@
return;
std::vector<Effect> supported;
- ASSERT_TRUE(vibrator->getSupportedEffects(&supported).isOk());
+ EXPECT_OK(vibrator->getSupportedEffects(&supported));
for (Effect effect : kEffects) {
bool isEffectSupported =
@@ -278,25 +306,26 @@
for (EffectStrength strength : kEffectStrengths) {
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
- sp<CompletionCallback> callback =
- new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+ auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&completionPromise] { completionPromise.set_value(); });
int lengthMs = 0;
- Status status = vibrator->perform(effect, strength, callback, &lengthMs);
+ ndk::ScopedAStatus status = vibrator->perform(effect, strength, callback, &lengthMs);
if (isEffectSupported) {
- EXPECT_TRUE(status.isOk());
+ EXPECT_OK(std::move(status))
+ << "\n For effect: " << toString(effect) << " " << toString(strength);
EXPECT_GT(lengthMs, 0);
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status))
+ << "\n For effect: " << toString(effect) << " " << toString(strength);
}
- if (!status.isOk())
- continue;
+ if (lengthMs <= 0) continue;
auto timeout = std::chrono::milliseconds(lengthMs) + VIBRATION_CALLBACK_TIMEOUT;
EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->off());
}
}
}
@@ -307,10 +336,10 @@
for (Effect effect : kEffects) {
for (EffectStrength strength : kEffectStrengths) {
- sp<CompletionCallback> callback = new CompletionCallback([] {});
+ auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
int lengthMs;
- Status status = vibrator->perform(effect, strength, callback, &lengthMs);
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->perform(effect, strength, callback, &lengthMs))
+ << "\n For effect: " << toString(effect) << " " << toString(strength);
}
}
}
@@ -319,53 +348,168 @@
for (Effect effect : kInvalidEffects) {
for (EffectStrength strength : kEffectStrengths) {
int32_t lengthMs;
- Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
- EXPECT_TRUE(isUnknownOrUnsupported(status))
- << status << toString(effect) << " " << toString(strength);
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(
+ vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs))
+ << "\n For effect: " << toString(effect) << " " << toString(strength);
}
}
for (Effect effect : kEffects) {
for (EffectStrength strength : kInvalidEffectStrengths) {
int32_t lengthMs;
- Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
- EXPECT_TRUE(isUnknownOrUnsupported(status))
- << status << " " << toString(effect) << " " << toString(strength);
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(
+ vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs))
+ << "\n For effect: " << toString(effect) << " " << toString(strength);
}
}
}
+TEST_P(VibratorAidl, PerformVendorEffectSupported) {
+ if ((capabilities & IVibrator::CAP_PERFORM_VENDOR_EFFECTS) == 0) return;
+
+ float scale = 0.5f;
+ for (EffectStrength strength : kEffectStrengths) {
+ PersistableBundle vendorData;
+ ::aidl::android::hardware::vibrator::testing::fillBasicData(&vendorData);
+
+ PersistableBundle nestedData;
+ ::aidl::android::hardware::vibrator::testing::fillBasicData(&nestedData);
+ vendorData.putPersistableBundle("test_nested_bundle", nestedData);
+
+ VendorEffect effect;
+ effect.vendorData = vendorData;
+ effect.strength = strength;
+ effect.scale = scale;
+ scale *= 1.5f;
+
+ auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
+ ndk::ScopedAStatus status = vibrator->performVendorEffect(effect, callback);
+
+ // No expectations on the actual status, the effect might be refused with illegal argument
+ // or the vendor might return a service-specific error code.
+ EXPECT_TRUE(status.getExceptionCode() != EX_UNSUPPORTED_OPERATION &&
+ status.getStatus() != STATUS_UNKNOWN_TRANSACTION)
+ << status << "\n For vendor effect with strength" << toString(strength)
+ << " and scale " << effect.scale;
+
+ if (status.isOk()) {
+ // Generic vendor data should not trigger vibrations, but if it does trigger one
+ // then we make sure the vibrator is reset by triggering off().
+ EXPECT_OK(vibrator->off());
+ }
+ }
+}
+
+TEST_P(VibratorAidl, PerformVendorEffectStability) {
+ if ((capabilities & IVibrator::CAP_PERFORM_VENDOR_EFFECTS) == 0) return;
+
+ // Run some iterations of performVendorEffect with randomized vendor data to check basic
+ // stability of the implementation.
+ uint8_t iterations = 200;
+
+ for (EffectStrength strength : kEffectStrengths) {
+ float scale = 0.5f;
+ for (uint8_t i = 0; i < iterations; i++) {
+ PersistableBundle vendorData;
+ ::aidl::android::hardware::vibrator::testing::fillRandomData(&vendorData);
+
+ VendorEffect effect;
+ effect.vendorData = vendorData;
+ effect.strength = strength;
+ effect.scale = scale;
+ scale *= 2;
+
+ auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
+ ndk::ScopedAStatus status = vibrator->performVendorEffect(effect, callback);
+
+ // No expectations on the actual status, the effect might be refused with illegal
+ // argument or the vendor might return a service-specific error code.
+ EXPECT_TRUE(status.getExceptionCode() != EX_UNSUPPORTED_OPERATION &&
+ status.getStatus() != STATUS_UNKNOWN_TRANSACTION)
+ << status << "\n For random vendor effect with strength " << toString(strength)
+ << " and scale " << effect.scale;
+
+ if (status.isOk()) {
+ // Random vendor data should not trigger vibrations, but if it does trigger one
+ // then we make sure the vibrator is reset by triggering off().
+ EXPECT_OK(vibrator->off());
+ }
+ }
+ }
+}
+
+TEST_P(VibratorAidl, PerformVendorEffectEmptyVendorData) {
+ if ((capabilities & IVibrator::CAP_PERFORM_VENDOR_EFFECTS) == 0) return;
+
+ for (EffectStrength strength : kEffectStrengths) {
+ VendorEffect effect;
+ effect.strength = strength;
+ effect.scale = 1.0f;
+
+ ndk::ScopedAStatus status = vibrator->performVendorEffect(effect, nullptr /*callback*/);
+
+ EXPECT_TRUE(status.getExceptionCode() == EX_SERVICE_SPECIFIC)
+ << status << "\n For vendor effect with strength " << toString(strength)
+ << " and scale " << effect.scale;
+ }
+}
+
+TEST_P(VibratorAidl, PerformVendorEffectInvalidScale) {
+ if ((capabilities & IVibrator::CAP_PERFORM_VENDOR_EFFECTS) == 0) return;
+
+ VendorEffect effect;
+ effect.strength = EffectStrength::MEDIUM;
+
+ effect.scale = 0.0f;
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->performVendorEffect(effect, nullptr /*callback*/));
+
+ effect.scale = -1.0f;
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->performVendorEffect(effect, nullptr /*callback*/));
+}
+
+TEST_P(VibratorAidl, PerformVendorEffectUnsupported) {
+ if (capabilities & IVibrator::CAP_PERFORM_VENDOR_EFFECTS) return;
+
+ for (EffectStrength strength : kEffectStrengths) {
+ VendorEffect effect;
+ effect.strength = strength;
+ effect.scale = 1.0f;
+
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->performVendorEffect(effect, nullptr /*callback*/))
+ << "\n For vendor effect with strength " << toString(strength);
+ }
+}
+
TEST_P(VibratorAidl, ChangeVibrationAmplitude) {
if (capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) {
- EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(0.1f).exceptionCode());
- EXPECT_TRUE(vibrator->on(2000, nullptr /*callback*/).isOk());
- EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(0.5f).exceptionCode());
+ EXPECT_OK(vibrator->setAmplitude(0.1f));
+ EXPECT_OK(vibrator->on(2000, nullptr /*callback*/));
+ EXPECT_OK(vibrator->setAmplitude(0.5f));
sleep(1);
- EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(1.0f).exceptionCode());
+ EXPECT_OK(vibrator->setAmplitude(1.0f));
sleep(1);
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->off());
}
}
TEST_P(VibratorAidl, AmplitudeOutsideRangeFails) {
if (capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) {
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(-1).exceptionCode());
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(0).exceptionCode());
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(1.1).exceptionCode());
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->setAmplitude(-1));
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->setAmplitude(0));
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->setAmplitude(1.1));
}
}
TEST_P(VibratorAidl, AmplitudeReturnsUnsupportedMatchingCapabilities) {
if ((capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) == 0) {
- Status status = vibrator->setAmplitude(1);
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->setAmplitude(1));
}
}
TEST_P(VibratorAidl, ChangeVibrationExternalControl) {
if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
- EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
+ EXPECT_OK(vibrator->setExternalControl(true));
sleep(1);
- EXPECT_TRUE(vibrator->setExternalControl(false).isOk());
+ EXPECT_OK(vibrator->setExternalControl(false));
sleep(1);
}
}
@@ -375,15 +519,15 @@
(capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0;
if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
- EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
+ EXPECT_OK(vibrator->setExternalControl(true));
- Status amplitudeStatus = vibrator->setAmplitude(0.5);
if (supportsExternalAmplitudeControl) {
- EXPECT_TRUE(amplitudeStatus.isOk());
+ EXPECT_OK(vibrator->setAmplitude(0.5));
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(amplitudeStatus)) << amplitudeStatus;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->setAmplitude(0.5));
}
- EXPECT_TRUE(vibrator->setExternalControl(false).isOk());
+
+ EXPECT_OK(vibrator->setExternalControl(false));
} else {
EXPECT_FALSE(supportsExternalAmplitudeControl);
}
@@ -391,18 +535,16 @@
TEST_P(VibratorAidl, ExternalControlUnsupportedMatchingCapabilities) {
if ((capabilities & IVibrator::CAP_EXTERNAL_CONTROL) == 0) {
- Status status = vibrator->setExternalControl(true);
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->setExternalControl(true));
}
}
TEST_P(VibratorAidl, GetSupportedPrimitives) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
std::vector<CompositePrimitive> supported;
+ EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
- EXPECT_EQ(Status::EX_NONE, vibrator->getSupportedPrimitives(&supported).exceptionCode());
-
- for (auto primitive : kCompositePrimitives) {
+ for (CompositePrimitive primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
std::find(supported.begin(), supported.end(), primitive) != supported.end();
bool isPrimitiveRequired =
@@ -417,22 +559,23 @@
TEST_P(VibratorAidl, GetPrimitiveDuration) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
std::vector<CompositePrimitive> supported;
- ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
+ EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
- for (auto primitive : kCompositePrimitives) {
+ for (CompositePrimitive primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
std::find(supported.begin(), supported.end(), primitive) != supported.end();
int32_t duration;
- Status status = vibrator->getPrimitiveDuration(primitive, &duration);
-
if (isPrimitiveSupported) {
- EXPECT_EQ(Status::EX_NONE, status.exceptionCode());
+ EXPECT_OK(vibrator->getPrimitiveDuration(primitive, &duration))
+ << "\n For primitive: " << toString(primitive) << " " << duration;
if (primitive != CompositePrimitive::NOOP) {
- ASSERT_GT(duration, 0) << toString(primitive) << " " << duration;
+ ASSERT_GT(duration, 0)
+ << "\n For primitive: " << toString(primitive) << " " << duration;
}
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->getPrimitiveDuration(primitive, &duration))
+ << "\n For primitive: " << toString(primitive);
}
}
}
@@ -446,14 +589,14 @@
std::vector<CompositePrimitive> supported;
int32_t maxDelay, maxSize;
- ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
- EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
- EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
+ EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
+ EXPECT_OK(vibrator->getCompositionDelayMax(&maxDelay));
+ EXPECT_OK(vibrator->getCompositionSizeMax(&maxSize));
std::vector<CompositeEffect> composite;
for (int i = 0; i < supported.size(); i++) {
- auto primitive = supported[i];
+ CompositePrimitive primitive = supported[i];
float t = static_cast<float>(i + 1) / supported.size();
CompositeEffect effect;
@@ -467,8 +610,8 @@
}
if (composite.size() != 0) {
- EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->compose(composite, nullptr));
+ EXPECT_OK(vibrator->off());
}
}
@@ -477,12 +620,12 @@
GTEST_SKIP() << "CAP_COMPOSE_EFFECTS not supported";
}
- auto unsupported = kInvalidPrimitives;
+ std::vector<CompositePrimitive> unsupported(kInvalidPrimitives);
std::vector<CompositePrimitive> supported;
- ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
+ EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
- for (auto primitive : kCompositePrimitives) {
+ for (CompositePrimitive primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
std::find(supported.begin(), supported.end(), primitive) != supported.end();
@@ -491,16 +634,15 @@
}
}
- for (auto primitive : unsupported) {
+ for (CompositePrimitive primitive : unsupported) {
std::vector<CompositeEffect> composite(1);
- for (auto& effect : composite) {
+ for (CompositeEffect& effect : composite) {
effect.delayMs = 0;
effect.primitive = primitive;
effect.scale = 1.0f;
}
- Status status = vibrator->compose(composite, nullptr);
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->compose(composite, nullptr));
}
}
@@ -516,18 +658,18 @@
effect.primitive = CompositePrimitive::CLICK;
effect.scale = std::nextafter(0.0f, -1.0f);
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->compose(composite, nullptr));
effect.scale = 0.0f;
- EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->compose(composite, nullptr));
+ EXPECT_OK(vibrator->off());
effect.scale = 1.0f;
- EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->compose(composite, nullptr));
+ EXPECT_OK(vibrator->off());
effect.scale = std::nextafter(1.0f, 2.0f);
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->compose(composite, nullptr));
}
TEST_P(VibratorAidl, ComposeDelayBoundary) {
@@ -537,7 +679,7 @@
int32_t maxDelay;
- EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
+ EXPECT_OK(vibrator->getCompositionDelayMax(&maxDelay));
std::vector<CompositeEffect> composite(1);
CompositeEffect& effect = composite[0];
@@ -546,19 +688,19 @@
effect.scale = 1.0f;
effect.delayMs = 0;
- EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->compose(composite, nullptr));
+ EXPECT_OK(vibrator->off());
effect.delayMs = 1;
- EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->compose(composite, nullptr));
+ EXPECT_OK(vibrator->off());
effect.delayMs = maxDelay;
- EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->compose(composite, nullptr));
+ EXPECT_OK(vibrator->off());
effect.delayMs = maxDelay + 1;
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->compose(composite, nullptr));
}
TEST_P(VibratorAidl, ComposeSizeBoundary) {
@@ -568,7 +710,7 @@
int32_t maxSize;
- EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
+ EXPECT_OK(vibrator->getCompositionSizeMax(&maxSize));
std::vector<CompositeEffect> composite(maxSize);
CompositeEffect effect;
@@ -578,11 +720,11 @@
effect.scale = 1.0f;
std::fill(composite.begin(), composite.end(), effect);
- EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->compose(composite, nullptr));
+ EXPECT_OK(vibrator->off());
composite.emplace_back(effect);
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->compose(composite, nullptr));
}
TEST_P(VibratorAidl, ComposeCallback) {
@@ -591,18 +733,17 @@
}
std::vector<CompositePrimitive> supported;
+ EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
- ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
-
- for (auto primitive : supported) {
+ for (CompositePrimitive primitive : supported) {
if (primitive == CompositePrimitive::NOOP) {
continue;
}
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
- sp<CompletionCallback> callback =
- new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+ auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&completionPromise] { completionPromise.set_value(); });
CompositeEffect effect;
std::vector<CompositeEffect> composite;
int32_t durationMs;
@@ -615,50 +756,50 @@
effect.scale = 1.0f;
composite.emplace_back(effect);
- EXPECT_EQ(Status::EX_NONE,
- vibrator->getPrimitiveDuration(primitive, &durationMs).exceptionCode())
- << toString(primitive);
+ EXPECT_OK(vibrator->getPrimitiveDuration(primitive, &durationMs))
+ << "\n For primitive: " << toString(primitive);
duration = std::chrono::milliseconds(durationMs);
start = high_resolution_clock::now();
- EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
- << toString(primitive);
+ EXPECT_OK(vibrator->compose(composite, callback))
+ << "\n For primitive: " << toString(primitive);
EXPECT_EQ(completionFuture.wait_for(duration + VIBRATION_CALLBACK_TIMEOUT),
std::future_status::ready)
- << toString(primitive);
+ << "\n For primitive: " << toString(primitive);
end = high_resolution_clock::now();
elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
- EXPECT_GE(elapsed.count(), duration.count()) << toString(primitive);
+ EXPECT_GE(elapsed.count(), duration.count())
+ << "\n For primitive: " << toString(primitive);
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->off()) << "\n For primitive: " << toString(primitive);
}
}
TEST_P(VibratorAidl, AlwaysOn) {
if (capabilities & IVibrator::CAP_ALWAYS_ON_CONTROL) {
std::vector<Effect> supported;
- ASSERT_TRUE(vibrator->getSupportedAlwaysOnEffects(&supported).isOk());
+ EXPECT_OK(vibrator->getSupportedAlwaysOnEffects(&supported));
for (Effect effect : kEffects) {
bool isEffectSupported =
std::find(supported.begin(), supported.end(), effect) != supported.end();
for (EffectStrength strength : kEffectStrengths) {
- Status status = vibrator->alwaysOnEnable(0, effect, strength);
+ ndk::ScopedAStatus status = vibrator->alwaysOnEnable(0, effect, strength);
if (isEffectSupported) {
- EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
- << toString(effect) << " " << toString(strength);
+ EXPECT_OK(std::move(status))
+ << "\n For effect: " << toString(effect) << " " << toString(strength);
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status))
- << status << " " << toString(effect) << " " << toString(strength);
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status))
+ << "\n For effect: " << toString(effect) << " " << toString(strength);
}
}
}
- EXPECT_EQ(Status::EX_NONE, vibrator->alwaysOnDisable(0).exceptionCode());
+ EXPECT_OK(vibrator->alwaysOnDisable(0));
}
}
@@ -668,12 +809,12 @@
TEST_P(VibratorAidl, GetQFactor) {
float qFactor;
- Status status = vibrator->getQFactor(&qFactor);
+ ndk::ScopedAStatus status = vibrator->getQFactor(&qFactor);
if (capabilities & IVibrator::CAP_GET_Q_FACTOR) {
+ EXPECT_OK(std::move(status));
ASSERT_GT(qFactor, 0);
- EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
}
}
@@ -687,9 +828,9 @@
TEST_P(VibratorAidl, GetBandwidthAmplitudeMap) {
std::vector<float> bandwidthAmplitudeMap;
- Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
+ ndk::ScopedAStatus status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
- EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+ EXPECT_OK(std::move(status));
ASSERT_FALSE(bandwidthAmplitudeMap.empty());
int minMapSize = (getResonantFrequencyHz(vibrator, capabilities) -
@@ -702,42 +843,42 @@
ASSERT_LE(e, 1.0);
}
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
}
}
TEST_P(VibratorAidl, GetPwlePrimitiveDurationMax) {
int32_t durationMs;
- Status status = vibrator->getPwlePrimitiveDurationMax(&durationMs);
+ ndk::ScopedAStatus status = vibrator->getPwlePrimitiveDurationMax(&durationMs);
if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+ EXPECT_OK(std::move(status));
ASSERT_NE(durationMs, 0);
- EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
}
}
TEST_P(VibratorAidl, GetPwleCompositionSizeMax) {
int32_t maxSize;
- Status status = vibrator->getPwleCompositionSizeMax(&maxSize);
+ ndk::ScopedAStatus status = vibrator->getPwleCompositionSizeMax(&maxSize);
if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+ EXPECT_OK(std::move(status));
ASSERT_NE(maxSize, 0);
- EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
}
}
TEST_P(VibratorAidl, GetSupportedBraking) {
std::vector<Braking> supported;
- Status status = vibrator->getSupportedBraking(&supported);
+ ndk::ScopedAStatus status = vibrator->getSupportedBraking(&supported);
if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
bool isDefaultNoneSupported =
std::find(supported.begin(), supported.end(), Braking::NONE) != supported.end();
+ EXPECT_OK(std::move(status));
ASSERT_TRUE(isDefaultNoneSupported);
- EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
- EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+ EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
}
}
@@ -746,7 +887,7 @@
ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities);
std::vector<Braking> supported;
- ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
+ EXPECT_OK(vibrator->getSupportedBraking(&supported));
bool isClabSupported =
std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
BrakingPwle firstBraking;
@@ -765,11 +906,11 @@
secondBraking.braking = Braking::NONE;
secondBraking.duration = 10;
- auto pwleQueue =
- std::vector<PrimitivePwle>{firstActive, firstBraking, secondActive, secondBraking};
+ std::vector<PrimitivePwle> pwleQueue = {firstActive, firstBraking, secondActive,
+ secondBraking};
- EXPECT_EQ(Status::EX_NONE, vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->composePwle(pwleQueue, nullptr));
+ EXPECT_OK(vibrator->off());
}
}
@@ -780,8 +921,8 @@
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
- sp<CompletionCallback> callback =
- new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+ auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&completionPromise] { completionPromise.set_value(); });
int32_t segmentDurationMaxMs;
vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
uint32_t durationMs = segmentDurationMaxMs * 2 + 100; // Sum of 2 active and 1 braking below
@@ -790,27 +931,25 @@
ActivePwle active = composeValidActivePwle(vibrator, capabilities);
std::vector<Braking> supported;
- ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
+ EXPECT_OK(vibrator->getSupportedBraking(&supported));
bool isClabSupported =
std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
BrakingPwle braking;
braking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
braking.duration = 100;
- auto pwleQueue = std::vector<PrimitivePwle>{active, braking, active};
+ std::vector<PrimitivePwle> pwleQueue = {active, braking, active};
- EXPECT_TRUE(vibrator->composePwle(pwleQueue, callback).isOk());
+ EXPECT_OK(vibrator->composePwle(pwleQueue, callback));
EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_OK(vibrator->off());
}
TEST_P(VibratorAidl, ComposePwleSegmentBoundary) {
if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
std::vector<PrimitivePwle> pwleQueue;
// test empty queue
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
- vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueue, nullptr));
ActivePwle active = composeValidActivePwle(vibrator, capabilities);
@@ -824,9 +963,7 @@
pwleQueue.emplace_back(std::move(pwle));
}
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
- vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueue, nullptr));
}
}
@@ -836,20 +973,16 @@
active.startAmplitude = getAmplitudeMax() + 1.0; // Amplitude greater than allowed
active.endAmplitude = getAmplitudeMax() + 1.0; // Amplitude greater than allowed
- auto pwleQueueGreater = std::vector<PrimitivePwle>{active};
+ std::vector<PrimitivePwle> pwleQueueGreater = {active};
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
- vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueueGreater, nullptr));
active.startAmplitude = getAmplitudeMin() - 1.0; // Amplitude less than allowed
active.endAmplitude = getAmplitudeMin() - 1.0; // Amplitude less than allowed
- auto pwleQueueLess = std::vector<PrimitivePwle>{active};
+ std::vector<PrimitivePwle> pwleQueueLess = {active};
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
- vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueueLess, nullptr));
}
}
@@ -865,20 +998,16 @@
freqMaximumHz + freqResolutionHz; // Frequency greater than allowed
active.endFrequency = freqMaximumHz + freqResolutionHz; // Frequency greater than allowed
- auto pwleQueueGreater = std::vector<PrimitivePwle>{active};
+ std::vector<PrimitivePwle> pwleQueueGreater = {active};
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
- vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueueGreater, nullptr));
active.startFrequency = freqMinimumHz - freqResolutionHz; // Frequency less than allowed
active.endFrequency = freqMinimumHz - freqResolutionHz; // Frequency less than allowed
- auto pwleQueueLess = std::vector<PrimitivePwle>{active};
+ std::vector<PrimitivePwle> pwleQueueLess = {active};
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
- vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueueLess, nullptr));
}
}
@@ -890,32 +1019,30 @@
vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
active.duration = segmentDurationMaxMs + 10; // Segment duration greater than allowed
- auto pwleQueue = std::vector<PrimitivePwle>{active};
+ std::vector<PrimitivePwle> pwleQueue = {active};
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
- vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
- EXPECT_TRUE(vibrator->off().isOk());
+ EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueue, nullptr));
}
}
std::vector<std::tuple<int32_t, int32_t>> GenerateVibratorMapping() {
std::vector<std::tuple<int32_t, int32_t>> tuples;
- auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
- std::vector<int32_t> vibratorIds;
- for (int i = 0; i < managerAidlNames.size(); i++) {
- auto managerName = String16(managerAidlNames[i].c_str());
- auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
+ std::vector<std::string> managerNames = findVibratorManagerNames();
+ std::vector<int32_t> vibratorIds;
+ for (int i = 0; i < managerNames.size(); i++) {
+ auto vibratorManager = IVibratorManager::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(managerNames[i].c_str())));
if (vibratorManager->getVibratorIds(&vibratorIds).isOk()) {
- for (auto &vibratorId : vibratorIds) {
- tuples.push_back(std::make_tuple(i, vibratorId));
+ for (int32_t vibratorId : vibratorIds) {
+ tuples.emplace_back(i, vibratorId);
}
}
}
- auto vibratorAidlNames = android::getAidlHalInstanceNames(IVibrator::descriptor);
- for (int i = 0; i < vibratorAidlNames.size(); i++) {
- tuples.push_back(std::make_tuple(-1, i));
+ std::vector<std::string> vibratorNames = findUnmanagedVibratorNames();
+ for (int i = 0; i < vibratorNames.size(); i++) {
+ tuples.emplace_back(-1, i);
}
return tuples;
@@ -935,8 +1062,11 @@
PrintGeneratedTest);
int main(int argc, char **argv) {
+ // Random values are used in the implementation.
+ std::srand(std::time(nullptr));
+
::testing::InitGoogleTest(&argc, argv);
- ProcessState::self()->setThreadPoolMaxThreadCount(1);
- ProcessState::self()->startThreadPool();
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
}
diff --git a/vibrator/aidl/vts/persistable_bundle_utils.h b/vibrator/aidl/vts/persistable_bundle_utils.h
new file mode 100644
index 0000000..a765a49
--- /dev/null
+++ b/vibrator/aidl/vts/persistable_bundle_utils.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2024 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 VIBRATOR_HAL_PERSISTABLE_BUNDLE_UTILS_H
+#define VIBRATOR_HAL_PERSISTABLE_BUNDLE_UTILS_H
+
+#include <android/persistable_bundle_aidl.h>
+
+#include <cstdlib>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace vibrator {
+namespace testing {
+
+using aidl::android::os::PersistableBundle;
+
+namespace {
+
+template <typename T>
+T nextValue() {
+ return static_cast<T>(std::rand());
+}
+
+template <>
+std::string nextValue() {
+ std::string str;
+ uint8_t entryCount = nextValue<uint8_t>();
+ for (uint8_t i = 0; i < entryCount; i++) {
+ str.push_back(nextValue<char>());
+ }
+ return str;
+}
+
+template <typename T>
+T nextValue(T limit) {
+ assert(limit > 0);
+ return static_cast<T>(std::rand()) / (static_cast<T>(RAND_MAX / limit));
+}
+
+template <typename T>
+void fillVector(std::vector<T>* values) {
+ uint8_t entryCount = nextValue<uint8_t>();
+ for (uint8_t i = 0; i < entryCount; i++) {
+ values->push_back(nextValue<T>());
+ }
+}
+
+const std::vector<std::function<void(PersistableBundle*, const std::string&)>>
+ sPersistableBundleSetters = {[](PersistableBundle* bundle, const std::string& key) -> void {
+ bundle->putBoolean(key, nextValue<bool>());
+ },
+ [](PersistableBundle* bundle, const std::string& key) -> void {
+ bundle->putInt(key, nextValue<int32_t>());
+ },
+ [](PersistableBundle* bundle, const std::string& key) -> void {
+ bundle->putLong(key, nextValue<int64_t>());
+ },
+ [](PersistableBundle* bundle, const std::string& key) -> void {
+ bundle->putDouble(key, nextValue<double>());
+ },
+ [](PersistableBundle* bundle, const std::string& key) -> void {
+ bundle->putString(key, nextValue<std::string>());
+ },
+ [](PersistableBundle* bundle, const std::string& key) -> void {
+ std::vector<bool> value;
+ fillVector<bool>(&value);
+ bundle->putBooleanVector(key, value);
+ },
+ [](PersistableBundle* bundle, const std::string& key) -> void {
+ std::vector<int32_t> value;
+ fillVector<int32_t>(&value);
+ bundle->putIntVector(key, value);
+ },
+ [](PersistableBundle* bundle, const std::string& key) -> void {
+ std::vector<int64_t> value;
+ fillVector<int64_t>(&value);
+ bundle->putLongVector(key, value);
+ },
+ [](PersistableBundle* bundle, const std::string& key) -> void {
+ std::vector<double> value;
+ fillVector<double>(&value);
+ bundle->putDoubleVector(key, value);
+ },
+ [](PersistableBundle* bundle, const std::string& key) -> void {
+ std::vector<std::string> value;
+ fillVector<std::string>(&value);
+ bundle->putStringVector(key, value);
+ }};
+
+} // namespace
+
+void fillBasicData(PersistableBundle* bundle) {
+ bundle->putBoolean("test_bool", true);
+ bundle->putInt("test_int", 2147483647);
+ bundle->putLong("test_long", 2147483647L);
+ bundle->putDouble("test_double", 1.23);
+ bundle->putString("test_string", "test data");
+ bundle->putBooleanVector("test_bool_vector", {true, false, false});
+ bundle->putIntVector("test_int_vector", {1, 2, 3, 4});
+ bundle->putLongVector("test_long_vector", {100L, 200L, 300L});
+ bundle->putDoubleVector("test_double_vector", {1.1, 2.2});
+ bundle->putStringVector("test_string_vector", {"test", "val"});
+}
+
+void fillRandomData(PersistableBundle* bundle) {
+ uint8_t entryCount = nextValue<uint8_t>();
+ for (uint8_t i = 0; i < entryCount; i++) {
+ std::string key(nextValue<std::string>());
+ uint8_t setterIdx = nextValue<uint8_t>(sPersistableBundleSetters.size() - 1);
+ sPersistableBundleSetters[setterIdx](bundle, key);
+ }
+}
+
+} // namespace testing
+} // namespace vibrator
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // VIBRATOR_HAL_PERSISTABLE_BUNDLE_UTILS_H
diff --git a/vibrator/aidl/vts/test_utils.h b/vibrator/aidl/vts/test_utils.h
new file mode 100644
index 0000000..aaf3211
--- /dev/null
+++ b/vibrator/aidl/vts/test_utils.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 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 VIBRATOR_HAL_TEST_UTILS_H
+#define VIBRATOR_HAL_TEST_UTILS_H
+
+#include <android/binder_auto_utils.h>
+#include <gtest/gtest.h>
+
+#if !defined(EXPECT_OK)
+#define EXPECT_OK(expression) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (const ::ndk::ScopedAStatus&& _status = (expression); _status.isOk()) \
+ ; \
+ else \
+ ADD_FAILURE() << "Expected STATUS_OK for: " << #expression << "\n Actual: " << _status
+#else
+#error Macro EXPECT_OK already defined unexpectedly
+#endif
+
+#if !defined(EXPECT_UNKNOWN_OR_UNSUPPORTED)
+#define EXPECT_UNKNOWN_OR_UNSUPPORTED(expression) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (const ::ndk::ScopedAStatus&& _status = (expression); \
+ _status.getExceptionCode() == EX_UNSUPPORTED_OPERATION || \
+ _status.getStatus() == STATUS_UNKNOWN_TRANSACTION) \
+ ; \
+ else \
+ ADD_FAILURE() << "Expected STATUS_UNKNOWN_TRANSACTION or EX_UNSUPPORTED_OPERATION for: " \
+ << #expression << "\n Actual: " << _status
+#else
+#error Macro EXPECT_UNKNOWN_OR_UNSUPPORTED already defined unexpectedly
+#endif
+
+#if !defined(EXPECT_ILLEGAL_ARGUMENT)
+#define EXPECT_ILLEGAL_ARGUMENT(expression) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (const ::ndk::ScopedAStatus&& _status = (expression); \
+ _status.getExceptionCode() == EX_ILLEGAL_ARGUMENT) \
+ ; \
+ else \
+ ADD_FAILURE() << "Expected EX_ILLEGAL_ARGUMENT for: " << #expression \
+ << "\n Actual: " << _status
+#else
+#error Macro EXPECT_ILLEGAL_ARGUMENT already defined unexpectedly
+#endif
+
+#endif // VIBRATOR_HAL_TEST_UTILS_H
diff --git a/vibrator/bench/Android.bp b/vibrator/bench/Android.bp
index 87bdab4..cd56516 100644
--- a/vibrator/bench/Android.bp
+++ b/vibrator/bench/Android.bp
@@ -30,12 +30,12 @@
"benchmark.cpp",
],
shared_libs: [
- "android.hardware.vibrator-V2-cpp",
+ "android.hardware.vibrator-V3-ndk",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
"android.hardware.vibrator@1.3",
- "libbinder",
+ "libbinder_ndk",
"libhardware",
"libhidlbase",
"libutils",
diff --git a/vibrator/bench/benchmark.cpp b/vibrator/bench/benchmark.cpp
index deaa6f2..8fe9cf7 100644
--- a/vibrator/bench/benchmark.cpp
+++ b/vibrator/bench/benchmark.cpp
@@ -16,15 +16,14 @@
#include "benchmark/benchmark.h"
+#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
#include <android/hardware/vibrator/1.3/IVibrator.h>
-#include <android/hardware/vibrator/BnVibratorCallback.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
#include <future>
-using ::android::enum_range;
-using ::android::sp;
using ::android::hardware::hidl_enum_range;
using ::android::hardware::Return;
using ::android::hardware::details::hidl_enum_values;
@@ -33,10 +32,11 @@
using ::benchmark::kMicrosecond;
using ::benchmark::State;
using ::benchmark::internal::Benchmark;
+using ::ndk::enum_range;
using namespace ::std::chrono_literals;
-namespace Aidl = ::android::hardware::vibrator;
+namespace Aidl = ::aidl::android::hardware::vibrator;
namespace V1_0 = ::android::hardware::vibrator::V1_0;
namespace V1_1 = ::android::hardware::vibrator::V1_1;
namespace V1_2 = ::android::hardware::vibrator::V1_2;
@@ -56,8 +56,8 @@
class BaseBench : public Fixture {
public:
void SetUp(State& /*state*/) override {
- android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
- android::ProcessState::self()->startThreadPool();
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
}
void TearDown(State& /*state*/) override {
@@ -75,7 +75,7 @@
auto getOtherArg(const State& state, std::size_t index) const { return state.range(index + 0); }
protected:
- sp<I> mVibrator;
+ std::shared_ptr<I> mVibrator;
};
template <typename I>
@@ -83,7 +83,12 @@
public:
void SetUp(State& state) override {
BaseBench<I>::SetUp(state);
- this->mVibrator = I::getService();
+ auto service = I::getService();
+ if (service) {
+ this->mVibrator = std::shared_ptr<I>(service.release());
+ } else {
+ this->mVibrator = nullptr;
+ }
}
protected:
@@ -356,7 +361,9 @@
public:
void SetUp(State& state) override {
BaseBench::SetUp(state);
- this->mVibrator = android::waitForVintfService<Aidl::IVibrator>();
+ auto serviceName = std::string(Aidl::IVibrator::descriptor) + "/default";
+ this->mVibrator = Aidl::IVibrator::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
}
void TearDown(State& state) override {
@@ -373,14 +380,24 @@
return (deviceCapabilities & capabilities) == capabilities;
}
- bool shouldSkipWithError(State& state, const android::binder::Status&& status) {
+ bool shouldSkipWithError(State& state, const ndk::ScopedAStatus&& status) {
if (!status.isOk()) {
- state.SkipWithError(status.toString8().c_str());
+ state.SkipWithError(status.getMessage());
return true;
}
return false;
}
+ void waitForComplete(std::future<void>& callbackFuture) {
+ // Wait until the HAL has finished processing previous vibration before starting a new one,
+ // so the HAL state is consistent on each run and metrics are less noisy. Some of the newest
+ // HAL implementations are waiting on previous vibration cleanup and might be significantly
+ // slower, so make sure we measure vibrations on a clean slate.
+ if (callbackFuture.valid()) {
+ callbackFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT);
+ }
+ }
+
static void SlowBenchConfig(Benchmark* b) { b->Iterations(VIBRATION_ITERATIONS); }
};
@@ -397,18 +414,12 @@
HalCallback() = default;
~HalCallback() = default;
- android::binder::Status onComplete() override {
+ ndk::ScopedAStatus onComplete() override {
mPromise.set_value();
- return android::binder::Status::ok();
+ return ndk::ScopedAStatus::ok();
}
- void waitForComplete() {
- // Wait until the HAL has finished processing previous vibration before starting a new one,
- // so the HAL state is consistent on each run and metrics are less noisy. Some of the newest
- // HAL implementations are waiting on previous vibration cleanup and might be significantly
- // slower, so make sure we measure vibrations on a clean slate.
- mPromise.get_future().wait_for(VIBRATION_CALLBACK_TIMEOUT);
- }
+ std::future<void> getFuture() { return mPromise.get_future(); }
private:
std::promise<void> mPromise;
@@ -418,7 +429,11 @@
auto ms = MAX_ON_DURATION_MS;
for (auto _ : state) {
- auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+ auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
+ ? ndk::SharedRefBase::make<HalCallback>()
+ : nullptr;
+ // Grab the future before callback promise is destroyed by the HAL.
+ auto cbFuture = cb ? cb->getFuture() : std::future<void>();
// Test
if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
@@ -430,9 +445,7 @@
if (shouldSkipWithError(state, mVibrator->off())) {
return;
}
- if (cb) {
- cb->waitForComplete();
- }
+ waitForComplete(cbFuture);
state.ResumeTiming();
}
});
@@ -441,7 +454,11 @@
auto ms = MAX_ON_DURATION_MS;
for (auto _ : state) {
- auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+ auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
+ ? ndk::SharedRefBase::make<HalCallback>()
+ : nullptr;
+ // Grab the future before callback promise is destroyed by the HAL.
+ auto cbFuture = cb ? cb->getFuture() : std::future<void>();
// Setup
state.PauseTiming();
@@ -457,9 +474,7 @@
// Cleanup
state.PauseTiming();
- if (cb) {
- cb->waitForComplete();
- }
+ waitForComplete(cbFuture);
state.ResumeTiming();
}
});
@@ -483,7 +498,9 @@
return;
}
- auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+ auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
+ ? ndk::SharedRefBase::make<HalCallback>()
+ : nullptr;
if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
return;
}
@@ -685,8 +702,11 @@
int32_t lengthMs = 0;
for (auto _ : state) {
- auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback()
- : nullptr;
+ auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK)
+ ? ndk::SharedRefBase::make<HalCallback>()
+ : nullptr;
+ // Grab the future before callback promise is destroyed by the HAL.
+ auto cbFuture = cb ? cb->getFuture() : std::future<void>();
// Test
if (shouldSkipWithError(state, mVibrator->perform(effect, strength, cb, &lengthMs))) {
@@ -698,9 +718,7 @@
if (shouldSkipWithError(state, mVibrator->off())) {
return;
}
- if (cb) {
- cb->waitForComplete();
- }
+ waitForComplete(cbFuture);
state.ResumeTiming();
}
});
@@ -799,7 +817,9 @@
effects.push_back(effect);
for (auto _ : state) {
- auto cb = new HalCallback();
+ auto cb = ndk::SharedRefBase::make<HalCallback>();
+ // Grab the future before callback promise is moved and destroyed by the HAL.
+ auto cbFuture = cb->getFuture();
// Test
if (shouldSkipWithError(state, mVibrator->compose(effects, cb))) {
@@ -811,7 +831,7 @@
if (shouldSkipWithError(state, mVibrator->off())) {
return;
}
- cb->waitForComplete();
+ waitForComplete(cbFuture);
state.ResumeTiming();
}
});
diff --git a/wifi/aidl/default/wifi_chip.cpp b/wifi/aidl/default/wifi_chip.cpp
index 9b9c565..fccfc15 100644
--- a/wifi/aidl/default/wifi_chip.cpp
+++ b/wifi/aidl/default/wifi_chip.cpp
@@ -62,7 +62,9 @@
std::vector<std::string> getNames(std::vector<std::shared_ptr<Iface>>& ifaces) {
std::vector<std::string> names;
for (const auto& iface : ifaces) {
- names.emplace_back(iface->getName());
+ if (iface) {
+ names.emplace_back(iface->getName());
+ }
}
return names;
}
@@ -971,6 +973,10 @@
}
std::shared_ptr<WifiNanIface> iface =
WifiNanIface::create(ifname, is_dedicated_iface, legacy_hal_, iface_util_);
+ if (!iface) {
+ LOG(ERROR) << "Unable to create NAN iface";
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
nan_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceAdded(IfaceType::NAN_IFACE, ifname).isOk()) {
diff --git a/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp b/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
index 21d50ac..c68d8fd 100644
--- a/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
+++ b/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
@@ -177,8 +177,7 @@
return iface;
}
-std::shared_ptr<IWifiApIface> getWifiApIface(const char* instance_name) {
- std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(instance_name);
+std::shared_ptr<IWifiApIface> getWifiApIface(std::shared_ptr<IWifiChip> wifi_chip) {
if (!wifi_chip.get()) {
return nullptr;
}
@@ -193,6 +192,11 @@
return iface;
}
+std::shared_ptr<IWifiApIface> getWifiApIface(const char* instance_name) {
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(instance_name);
+ return getWifiApIface(wifi_chip);
+}
+
std::shared_ptr<IWifiApIface> getBridgedWifiApIface(std::shared_ptr<IWifiChip> wifi_chip) {
if (!wifi_chip.get()) {
return nullptr;
diff --git a/wifi/aidl/vts/functional/wifi_aidl_test_utils.h b/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
index 1369dd4..9b47a9f 100644
--- a/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
+++ b/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
@@ -40,6 +40,7 @@
std::shared_ptr<IWifiStaIface> getWifiStaIface(const char* instance_name);
std::shared_ptr<IWifiNanIface> getWifiNanIface(const char* instance_name);
std::shared_ptr<IWifiApIface> getWifiApIface(const char* instance_name);
+std::shared_ptr<IWifiApIface> getWifiApIface(std::shared_ptr<IWifiChip> wifi_chip);
std::shared_ptr<IWifiApIface> getBridgedWifiApIface(const char* instance_name);
std::shared_ptr<IWifiApIface> getBridgedWifiApIface(std::shared_ptr<IWifiChip> wifi_chip);
// Configure the chip in a mode to support the creation of the provided iface type.
diff --git a/wifi/aidl/vts/functional/wifi_ap_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_ap_iface_aidl_test.cpp
index d39cfb4..a58fd5b 100644
--- a/wifi/aidl/vts/functional/wifi_ap_iface_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_ap_iface_aidl_test.cpp
@@ -37,12 +37,21 @@
"/system/bin/cmd wifi get-softap-supported-features",
"wifi_softap_bridged_ap_supported");
stopWifiService(getInstanceName());
+
+ wifi_chip_ = getWifiChip(getInstanceName());
+ ASSERT_NE(nullptr, wifi_chip_.get());
+
+ bool isApSupported = doesChipSupportConcurrencyType(wifi_chip_, IfaceConcurrencyType::AP);
+ if (!isApSupported) {
+ GTEST_SKIP() << "AP interfaces are not supported";
+ }
}
void TearDown() override { stopWifiService(getInstanceName()); }
protected:
bool isBridgedSupport_ = false;
+ std::shared_ptr<IWifiChip> wifi_chip_;
const char* getInstanceName() { return GetParam().c_str(); }
};
@@ -50,7 +59,7 @@
* SetMacAddress
*/
TEST_P(WifiApIfaceAidlTest, SetMacAddress) {
- std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(wifi_chip_);
ASSERT_NE(nullptr, wifi_ap_iface.get());
std::array<uint8_t, 6> mac = {0x12, 0x22, 0x33, 0x52, 0x10, 0x44};
EXPECT_TRUE(wifi_ap_iface->setMacAddress(mac).isOk());
@@ -60,7 +69,7 @@
* SetCountryCode
*/
TEST_P(WifiApIfaceAidlTest, SetCountryCode) {
- std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(wifi_chip_);
ASSERT_NE(nullptr, wifi_ap_iface.get());
const std::array<uint8_t, 2> country_code = {0x55, 0x53};
@@ -71,7 +80,7 @@
* GetFactoryMacAddress
*/
TEST_P(WifiApIfaceAidlTest, GetFactoryMacAddress) {
- std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(wifi_chip_);
ASSERT_NE(nullptr, wifi_ap_iface.get());
std::array<uint8_t, 6> mac;
@@ -84,7 +93,7 @@
* GetBridgedInstances - non-bridged mode
*/
TEST_P(WifiApIfaceAidlTest, GetBridgedInstances) {
- std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(wifi_chip_);
ASSERT_NE(nullptr, wifi_ap_iface.get());
std::vector<std::string> instances;
@@ -99,7 +108,7 @@
if (!isBridgedSupport_) {
GTEST_SKIP() << "Missing Bridged AP support";
}
- std::shared_ptr<IWifiApIface> wifi_ap_iface = getBridgedWifiApIface(getInstanceName());
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getBridgedWifiApIface(wifi_chip_);
ASSERT_NE(nullptr, wifi_ap_iface.get());
std::vector<std::string> instances;
@@ -111,7 +120,7 @@
* ResetToFactoryMacAddress - non-bridged mode
*/
TEST_P(WifiApIfaceAidlTest, ResetToFactoryMacAddress) {
- std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(wifi_chip_);
ASSERT_NE(nullptr, wifi_ap_iface.get());
EXPECT_TRUE(wifi_ap_iface->resetToFactoryMacAddress().isOk());
}
@@ -123,7 +132,7 @@
if (!isBridgedSupport_) {
GTEST_SKIP() << "Missing Bridged AP support";
}
- std::shared_ptr<IWifiApIface> wifi_ap_iface = getBridgedWifiApIface(getInstanceName());
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getBridgedWifiApIface(wifi_chip_);
ASSERT_NE(nullptr, wifi_ap_iface.get());
EXPECT_TRUE(wifi_ap_iface->resetToFactoryMacAddress().isOk());
}