Merge "resolve merge conflicts of 5c715dd65bc963cd6832f0b5c914f7c24fb273f5 to sc-dev" into sc-dev
diff --git a/audio/7.0/config/Android.bp b/audio/7.0/config/Android.bp
index f67cc7c..4a46795 100644
--- a/audio/7.0/config/Android.bp
+++ b/audio/7.0/config/Android.bp
@@ -4,3 +4,19 @@
package_name: "android.audio.policy.configuration.V7_0",
nullability: true,
}
+
+xsd_config {
+ name: "audio_policy_configuration_V7_0_enums",
+ srcs: ["audio_policy_configuration.xsd"],
+ package_name: "android.audio.policy.configuration.V7_0",
+ nullability: true,
+ enums_only: true,
+}
+
+xsd_config {
+ name: "audio_policy_configuration_V7_0_parser",
+ srcs: ["audio_policy_configuration.xsd"],
+ package_name: "android.audio.policy.configuration.V7_0",
+ nullability: true,
+ parser_only: true,
+}
diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd
index 31ec64b..ee51aa8 100644
--- a/audio/7.0/config/audio_policy_configuration.xsd
+++ b/audio/7.0/config/audio_policy_configuration.xsd
@@ -311,13 +311,17 @@
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="vendorExtension">
- <!-- Vendor extension names must be prefixed by "VX_" to distinguish them from AOSP values.
- Vendor are encouraged to namespace their module names to avoid conflicts.
- Example for an hypothetical Google virtual reality device:
- <devicePort tagName="VR" type="VX_GOOGLE_VR" role="sink">
+ <!-- Vendor extension names must be prefixed by "VX_" to distinguish them from
+ AOSP values. Vendors must namespace their names to avoid conflicts. The
+ namespace part must only use capital latin characters and decimal digits and
+ consist of at least 3 characters. The part of the extension name after the
+ namespace may in addition include underscores. Example for a hypothetical
+ Google virtual reality device:
+
+ <devicePort tagName="VR" type="VX_GOOGLE_VR" role="sink" />
-->
<xs:restriction base="xs:string">
- <xs:pattern value="VX_[_a-zA-Z0-9]+"/>
+ <xs:pattern value="VX_[A-Z0-9]{3,}_[_A-Z0-9]+"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="extendableAudioDevice">
diff --git a/audio/common/7.0/Android.bp b/audio/common/7.0/Android.bp
index 1c016b4..47f031f 100644
--- a/audio/common/7.0/Android.bp
+++ b/audio/common/7.0/Android.bp
@@ -16,15 +16,14 @@
cc_library {
name: "android.hardware.audio.common@7.0-enums",
vendor_available: true,
- generated_headers: ["audio_policy_configuration_V7_0"],
- generated_sources: ["audio_policy_configuration_V7_0"],
+ generated_headers: ["audio_policy_configuration_V7_0_enums"],
+ generated_sources: ["audio_policy_configuration_V7_0_enums"],
header_libs: ["libxsdc-utils"],
- export_generated_headers: ["audio_policy_configuration_V7_0"],
+ export_generated_headers: ["audio_policy_configuration_V7_0_enums"],
export_header_lib_headers: ["libxsdc-utils"],
export_include_dirs: ["enums/include"],
shared_libs: [
"libbase",
"liblog",
- "libxml2",
],
}
diff --git a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
index b427f3a..fe8eee1 100644
--- a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
+++ b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
-#define ANDROID_AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
+#ifndef ANDROID_AUDIO_POLICY_CONFIGURATION_V7_0__ENUMS_H
+#define ANDROID_AUDIO_POLICY_CONFIGURATION_V7_0__ENUMS_H
#include <sys/types.h>
-#include <algorithm>
-#include <cctype>
+#include <regex>
+#include <string>
-#include <android_audio_policy_configuration_V7_0.h>
+#include <android_audio_policy_configuration_V7_0_enums.h>
namespace android::audio::policy::configuration::V7_0 {
@@ -219,11 +219,9 @@
}
static inline bool isVendorExtension(const std::string& s) {
- // Must match the "vendorExtension" rule from the XSD file.
- static const std::string vendorPrefix = "VX_";
- return maybeVendorExtension(s) &&
- std::all_of(s.begin() + vendorPrefix.size(), s.end(),
- [](unsigned char c) { return c == '_' || std::isalnum(c); });
+ // Must be the same as the "vendorExtension" rule from the XSD file.
+ static const std::regex vendorExtension("VX_[A-Z0-9]{3,}_[_A-Z0-9]+");
+ return std::regex_match(s.begin(), s.end(), vendorExtension);
}
static inline bool isUnknownAudioChannelMask(const std::string& mask) {
@@ -264,4 +262,4 @@
} // namespace android::audio::policy::configuration::V7_0
-#endif // ANDROID_AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
+#endif // ANDROID_AUDIO_POLICY_CONFIGURATION_V7_0__ENUMS_H
diff --git a/audio/common/7.0/example/Android.bp b/audio/common/7.0/example/Android.bp
index 03c1cd8..a6ae560 100644
--- a/audio/common/7.0/example/Android.bp
+++ b/audio/common/7.0/example/Android.bp
@@ -35,7 +35,6 @@
"libcutils",
"libhidlbase",
"liblog",
- "libxml2",
"libutils",
"android.hardware.audio@7.0",
"android.hardware.audio.common@7.0",
diff --git a/audio/common/7.0/example/Effect.cpp b/audio/common/7.0/example/Effect.cpp
index 5788811..0621669 100644
--- a/audio/common/7.0/example/Effect.cpp
+++ b/audio/common/7.0/example/Effect.cpp
@@ -17,7 +17,7 @@
#define LOG_TAG "EffectsFactory7.0"
#include <log/log.h>
-#include <android_audio_policy_configuration_V7_0.h>
+#include <android_audio_policy_configuration_V7_0-enums.h>
#include "Effect.h"
diff --git a/audio/common/all-versions/default/Android.bp b/audio/common/all-versions/default/Android.bp
index 29a3d6f..9afc95a 100644
--- a/audio/common/all-versions/default/Android.bp
+++ b/audio/common/all-versions/default/Android.bp
@@ -140,7 +140,6 @@
"android.hardware.audio.common@7.0",
"android.hardware.audio.common@7.0-enums",
"libbase",
- "libxml2",
],
cflags: [
"-DMAJOR_VERSION=7",
diff --git a/audio/common/all-versions/default/tests/hidlutils_tests.cpp b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
index ec6bdf3..e154453 100644
--- a/audio/common/all-versions/default/tests/hidlutils_tests.cpp
+++ b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
@@ -432,10 +432,16 @@
// The enums module is too small to have unit tests on its own.
TEST(HidlUtils, VendorExtension) {
EXPECT_TRUE(xsd::isVendorExtension("VX_GOOGLE_VR_42"));
+ EXPECT_TRUE(xsd::isVendorExtension("VX_QCM_SPK"));
EXPECT_FALSE(xsd::isVendorExtension(""));
EXPECT_FALSE(xsd::isVendorExtension("random string"));
EXPECT_FALSE(xsd::isVendorExtension("VX_"));
+ EXPECT_FALSE(xsd::isVendorExtension("VX_X"));
+ EXPECT_FALSE(xsd::isVendorExtension("VX_X_"));
+ EXPECT_FALSE(xsd::isVendorExtension("VX_X_X"));
+ EXPECT_FALSE(xsd::isVendorExtension("VX_XX_X"));
EXPECT_FALSE(xsd::isVendorExtension("VX_GOOGLE_$$"));
+ EXPECT_FALSE(xsd::isVendorExtension("VX_$CM_SPK"));
}
TEST(HidlUtils, ConvertInvalidDeviceAddress) {
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index e0f0894..0222bee 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -138,7 +138,6 @@
"android.hardware.audio.common@7.0-enums",
"android.hardware.audio.common@7.0-util",
"libbase",
- "libxml2",
],
cflags: [
"-DMAJOR_VERSION=7",
diff --git a/audio/core/all-versions/default/util/Android.bp b/audio/core/all-versions/default/util/Android.bp
index 447184b..ee80bbb 100644
--- a/audio/core/all-versions/default/util/Android.bp
+++ b/audio/core/all-versions/default/util/Android.bp
@@ -95,7 +95,6 @@
"android.hardware.audio.common@7.0-util",
"android.hardware.audio@7.0",
"libbase",
- "libxml2",
],
cflags: [
"-DMAJOR_VERSION=7",
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index e8b704c..8cea3cb 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -146,6 +146,8 @@
srcs: [
"7.0/AudioPrimaryHidlHalTest.cpp",
],
+ generated_headers: ["audio_policy_configuration_V7_0_parser"],
+ generated_sources: ["audio_policy_configuration_V7_0_parser"],
static_libs: [
"android.hardware.audio@7.0",
"android.hardware.audio.common@7.0",
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
index 15a2fd9..23e7786 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
@@ -31,7 +31,6 @@
#include <android/hidl/memory/1.0/IMemory.h>
#if MAJOR_VERSION >= 7
#include <android_audio_policy_configuration_V7_0-enums.h>
-#include <android_audio_policy_configuration_V7_0.h>
#endif
#include <common/all-versions/VersionUtils.h>
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index ed75e1d..e3fd16d 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -354,6 +354,12 @@
/**
* Speed of the vehicle
*
+ * The value must be positive when the vehicle is moving forward and negative when
+ * the vehicle is moving backward. This value is independent of gear value
+ * (CURRENT_GEAR or GEAR_SELECTION), for example, if GEAR_SELECTION is GEAR_NEUTRAL,
+ * PERF_VEHICLE_SPEED is positive when the vehicle is moving forward, negative when moving
+ * backward, and zero when not moving.
+ *
* @change_mode VehiclePropertyChangeMode:CONTINUOUS
* @access VehiclePropertyAccess:READ
* @unit VehicleUnit:METER_PER_SEC
diff --git a/biometrics/fingerprint/aidl/default/Android.bp b/biometrics/fingerprint/aidl/default/Android.bp
index 24087cf..6b43bff 100644
--- a/biometrics/fingerprint/aidl/default/Android.bp
+++ b/biometrics/fingerprint/aidl/default/Android.bp
@@ -6,9 +6,11 @@
vintf_fragments: ["fingerprint-default.xml"],
local_include_dirs: ["include"],
srcs: [
- "main.cpp",
+ "CancellationSignal.cpp",
"Fingerprint.cpp",
"Session.cpp",
+ "WorkerThread.cpp",
+ "main.cpp",
],
shared_libs: [
"libbase",
diff --git a/biometrics/fingerprint/aidl/default/CancellationSignal.cpp b/biometrics/fingerprint/aidl/default/CancellationSignal.cpp
new file mode 100644
index 0000000..6598316
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/CancellationSignal.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CancellationSignal.h"
+
+#include <android-base/logging.h>
+#include <chrono>
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+CancellationSignal::CancellationSignal(std::promise<void>&& cancellationPromise)
+ : mCancellationPromise(std::move(cancellationPromise)) {}
+
+ndk::ScopedAStatus CancellationSignal::cancel() {
+ mCancellationPromise.set_value();
+ return ndk::ScopedAStatus::ok();
+}
+
+bool shouldCancel(const std::future<void>& f) {
+ CHECK(f.valid());
+ return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
+}
+
+} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
index 6f89346..67dc34f 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
@@ -15,11 +15,12 @@
*/
#include "Fingerprint.h"
+
#include "Session.h"
namespace aidl::android::hardware::biometrics::fingerprint {
namespace {
-
+constexpr size_t MAX_WORKER_QUEUE_SIZE = 5;
constexpr int SENSOR_ID = 1;
constexpr common::SensorStrength SENSOR_STRENGTH = common::SensorStrength::STRONG;
constexpr int MAX_ENROLLMENTS_PER_USER = 5;
@@ -32,7 +33,8 @@
} // namespace
-Fingerprint::Fingerprint() {}
+Fingerprint::Fingerprint()
+ : mEngine(std::make_unique<FakeFingerprintEngine>()), mWorker(MAX_WORKER_QUEUE_SIZE) {}
ndk::ScopedAStatus Fingerprint::getSensorProps(std::vector<SensorProps>* out) {
std::vector<common::HardwareInfo> hardwareInfos = {
@@ -52,14 +54,21 @@
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Fingerprint::createSession(int32_t /*sensorId*/, int32_t /*userId*/,
+ndk::ScopedAStatus Fingerprint::createSession(int32_t sensorId, int32_t userId,
const std::shared_ptr<ISessionCallback>& cb,
std::shared_ptr<ISession>* out) {
- *out = SharedRefBase::make<Session>(cb);
+ auto sessionSp = mSession.lock();
+ CHECK(sessionSp == nullptr || sessionSp->isClosed()) << "Open session already exists!";
+
+ auto session = SharedRefBase::make<Session>(sensorId, userId, cb, mEngine.get(), &mWorker);
+ mSession = session;
+ *out = session;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Fingerprint::reset() {
+ // Crash. The system will start a fresh instance of the HAL.
+ CHECK(false) << "Unable to reset. Crashing.";
return ndk::ScopedAStatus::ok();
}
diff --git a/biometrics/fingerprint/aidl/default/Session.cpp b/biometrics/fingerprint/aidl/default/Session.cpp
index c928df4..f6a0314 100644
--- a/biometrics/fingerprint/aidl/default/Session.cpp
+++ b/biometrics/fingerprint/aidl/default/Session.cpp
@@ -14,93 +14,216 @@
* limitations under the License.
*/
-#include <aidl/android/hardware/biometrics/common/BnCancellationSignal.h>
+#include "Session.h"
+
#include <android-base/logging.h>
-#include "Session.h"
+#include "CancellationSignal.h"
namespace aidl::android::hardware::biometrics::fingerprint {
-class CancellationSignal : public common::BnCancellationSignal {
- public:
- ndk::ScopedAStatus cancel() override { return ndk::ScopedAStatus::ok(); }
-};
+Session::Session(int sensorId, int userId, std::shared_ptr<ISessionCallback> cb,
+ FakeFingerprintEngine* engine, WorkerThread* worker)
+ : mSensorId(sensorId),
+ mUserId(userId),
+ mCb(std::move(cb)),
+ mEngine(engine),
+ mWorker(worker),
+ mScheduledState(SessionState::IDLING),
+ mCurrentState(SessionState::IDLING) {
+ CHECK_GE(mSensorId, 0);
+ CHECK_GE(mUserId, 0);
+ CHECK(mEngine);
+ CHECK(mWorker);
+ CHECK(mCb);
+}
-Session::Session(std::shared_ptr<ISessionCallback> cb) : mCb(std::move(cb)) {}
+void Session::scheduleStateOrCrash(SessionState state) {
+ CHECK(mScheduledState == SessionState::IDLING);
+ CHECK(mCurrentState == SessionState::IDLING);
+ mScheduledState = state;
+}
-ndk::ScopedAStatus Session::generateChallenge(int32_t /*cookie*/, int32_t /*timeoutSec*/) {
+void Session::enterStateOrCrash(int cookie, SessionState state) {
+ CHECK(mScheduledState == state);
+ mCurrentState = mScheduledState;
+ mScheduledState = SessionState::IDLING;
+ mCb->onStateChanged(cookie, mCurrentState);
+}
+
+void Session::enterIdling(int cookie) {
+ mCurrentState = SessionState::IDLING;
+ mCb->onStateChanged(cookie, mCurrentState);
+}
+
+bool Session::isClosed() {
+ return mCurrentState == SessionState::CLOSED;
+}
+
+ndk::ScopedAStatus Session::generateChallenge(int32_t cookie, int32_t timeoutSec) {
LOG(INFO) << "generateChallenge";
+ scheduleStateOrCrash(SessionState::GENERATING_CHALLENGE);
+
+ mWorker->schedule(Callable::from([this, cookie, timeoutSec] {
+ enterStateOrCrash(cookie, SessionState::GENERATING_CHALLENGE);
+ mEngine->generateChallengeImpl(mCb.get(), timeoutSec);
+ enterIdling(cookie);
+ }));
+
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::revokeChallenge(int32_t /*cookie*/, int64_t /*challenge*/) {
+ndk::ScopedAStatus Session::revokeChallenge(int32_t cookie, int64_t challenge) {
LOG(INFO) << "revokeChallenge";
+ scheduleStateOrCrash(SessionState::REVOKING_CHALLENGE);
+
+ mWorker->schedule(Callable::from([this, cookie, challenge] {
+ enterStateOrCrash(cookie, SessionState::REVOKING_CHALLENGE);
+ mEngine->revokeChallengeImpl(mCb.get(), challenge);
+ enterIdling(cookie);
+ }));
+
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::enroll(int32_t /*cookie*/, const keymaster::HardwareAuthToken& /*hat*/,
- std::shared_ptr<common::ICancellationSignal>* /*out*/) {
+ndk::ScopedAStatus Session::enroll(int32_t cookie, const keymaster::HardwareAuthToken& hat,
+ std::shared_ptr<common::ICancellationSignal>* out) {
LOG(INFO) << "enroll";
+ scheduleStateOrCrash(SessionState::ENROLLING);
+
+ std::promise<void> cancellationPromise;
+ auto cancFuture = cancellationPromise.get_future();
+
+ mWorker->schedule(Callable::from([this, cookie, hat, cancFuture = std::move(cancFuture)] {
+ enterStateOrCrash(cookie, SessionState::ENROLLING);
+ if (shouldCancel(cancFuture)) {
+ mCb->onError(Error::CANCELED, 0 /* vendorCode */);
+ } else {
+ mEngine->enrollImpl(mCb.get(), hat);
+ }
+ enterIdling(cookie);
+ }));
+
+ *out = SharedRefBase::make<CancellationSignal>(std::move(cancellationPromise));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::authenticate(int32_t /*cookie*/, int64_t /*keystoreOperationId*/,
+ndk::ScopedAStatus Session::authenticate(int32_t cookie, int64_t operationId,
std::shared_ptr<common::ICancellationSignal>* out) {
LOG(INFO) << "authenticate";
- if (mCb) {
- mCb->onStateChanged(0, SessionState::AUTHENTICATING);
- }
- *out = SharedRefBase::make<CancellationSignal>();
+ scheduleStateOrCrash(SessionState::AUTHENTICATING);
+
+ std::promise<void> cancPromise;
+ auto cancFuture = cancPromise.get_future();
+
+ mWorker->schedule(
+ Callable::from([this, cookie, operationId, cancFuture = std::move(cancFuture)] {
+ enterStateOrCrash(cookie, SessionState::AUTHENTICATING);
+ if (shouldCancel(cancFuture)) {
+ mCb->onError(Error::CANCELED, 0 /* vendorCode */);
+ } else {
+ mEngine->authenticateImpl(mCb.get(), operationId);
+ }
+ enterIdling(cookie);
+ }));
+
+ *out = SharedRefBase::make<CancellationSignal>(std::move(cancPromise));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::detectInteraction(
- int32_t /*cookie*/, std::shared_ptr<common::ICancellationSignal>* /*out*/) {
+ndk::ScopedAStatus Session::detectInteraction(int32_t cookie,
+ std::shared_ptr<common::ICancellationSignal>* out) {
LOG(INFO) << "detectInteraction";
+ scheduleStateOrCrash(SessionState::DETECTING_INTERACTION);
+
+ std::promise<void> cancellationPromise;
+ auto cancFuture = cancellationPromise.get_future();
+
+ mWorker->schedule(Callable::from([this, cookie, cancFuture = std::move(cancFuture)] {
+ enterStateOrCrash(cookie, SessionState::DETECTING_INTERACTION);
+ if (shouldCancel(cancFuture)) {
+ mCb->onError(Error::CANCELED, 0 /* vendorCode */);
+ } else {
+ mEngine->detectInteractionImpl(mCb.get());
+ }
+ enterIdling(cookie);
+ }));
+
+ *out = SharedRefBase::make<CancellationSignal>(std::move(cancellationPromise));
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::enumerateEnrollments(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::enumerateEnrollments(int32_t cookie) {
LOG(INFO) << "enumerateEnrollments";
- if (mCb) {
- mCb->onStateChanged(0, SessionState::ENUMERATING_ENROLLMENTS);
- mCb->onEnrollmentsEnumerated(std::vector<int32_t>());
- }
+ scheduleStateOrCrash(SessionState::ENUMERATING_ENROLLMENTS);
+
+ mWorker->schedule(Callable::from([this, cookie] {
+ enterStateOrCrash(cookie, SessionState::ENUMERATING_ENROLLMENTS);
+ mEngine->enumerateEnrollmentsImpl(mCb.get());
+ enterIdling(cookie);
+ }));
+
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::removeEnrollments(int32_t /*cookie*/,
- const std::vector<int32_t>& /*enrollmentIds*/) {
+ndk::ScopedAStatus Session::removeEnrollments(int32_t cookie,
+ const std::vector<int32_t>& enrollmentIds) {
LOG(INFO) << "removeEnrollments";
- if (mCb) {
- mCb->onStateChanged(0, SessionState::REMOVING_ENROLLMENTS);
- mCb->onEnrollmentsRemoved(std::vector<int32_t>());
- }
+ scheduleStateOrCrash(SessionState::REMOVING_ENROLLMENTS);
+
+ mWorker->schedule(Callable::from([this, cookie, enrollmentIds] {
+ enterStateOrCrash(cookie, SessionState::REMOVING_ENROLLMENTS);
+ mEngine->removeEnrollmentsImpl(mCb.get(), enrollmentIds);
+ enterIdling(cookie);
+ }));
+
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::getAuthenticatorId(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::getAuthenticatorId(int32_t cookie) {
LOG(INFO) << "getAuthenticatorId";
- if (mCb) {
- mCb->onStateChanged(0, SessionState::GETTING_AUTHENTICATOR_ID);
- mCb->onAuthenticatorIdRetrieved(0 /* authenticatorId */);
- }
+ scheduleStateOrCrash(SessionState::GETTING_AUTHENTICATOR_ID);
+
+ mWorker->schedule(Callable::from([this, cookie] {
+ enterStateOrCrash(cookie, SessionState::GETTING_AUTHENTICATOR_ID);
+ mEngine->getAuthenticatorIdImpl(mCb.get());
+ enterIdling(cookie);
+ }));
+
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::invalidateAuthenticatorId(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::invalidateAuthenticatorId(int32_t cookie) {
LOG(INFO) << "invalidateAuthenticatorId";
+ scheduleStateOrCrash(SessionState::INVALIDATING_AUTHENTICATOR_ID);
+
+ mWorker->schedule(Callable::from([this, cookie] {
+ enterStateOrCrash(cookie, SessionState::INVALIDATING_AUTHENTICATOR_ID);
+ mEngine->invalidateAuthenticatorIdImpl(mCb.get());
+ enterIdling(cookie);
+ }));
+
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::resetLockout(int32_t /*cookie*/,
- const keymaster::HardwareAuthToken& /*hat*/) {
+ndk::ScopedAStatus Session::resetLockout(int32_t cookie, const keymaster::HardwareAuthToken& hat) {
LOG(INFO) << "resetLockout";
+ scheduleStateOrCrash(SessionState::RESETTING_LOCKOUT);
+
+ mWorker->schedule(Callable::from([this, cookie, hat] {
+ enterStateOrCrash(cookie, SessionState::RESETTING_LOCKOUT);
+ mEngine->resetLockoutImpl(mCb.get(), hat);
+ enterIdling(cookie);
+ }));
+
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Session::close(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::close(int32_t cookie) {
LOG(INFO) << "close";
+ CHECK(mCurrentState == SessionState::IDLING) << "Can't close a non-idling session. Crashing.";
+ mCurrentState = SessionState::CLOSED;
+ mCb->onStateChanged(cookie, mCurrentState);
return ndk::ScopedAStatus::ok();
}
@@ -119,4 +242,5 @@
LOG(INFO) << "onUiReady";
return ndk::ScopedAStatus::ok();
}
+
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/WorkerThread.cpp b/biometrics/fingerprint/aidl/default/WorkerThread.cpp
index 512efb8..d1a63d0 100644
--- a/biometrics/fingerprint/aidl/default/WorkerThread.cpp
+++ b/biometrics/fingerprint/aidl/default/WorkerThread.cpp
@@ -36,7 +36,7 @@
mThread.join();
}
-bool WorkerThread::schedule(Task&& task) {
+bool WorkerThread::schedule(std::unique_ptr<Callable> task) {
if (mIsDestructing) {
return false;
}
@@ -58,10 +58,10 @@
if (mIsDestructing) {
return;
}
- Task task = std::move(mQueue.front());
+ std::unique_ptr<Callable> task = std::move(mQueue.front());
mQueue.pop_front();
lock.unlock();
- task();
+ (*task)();
}
}
diff --git a/biometrics/fingerprint/aidl/default/include/Callable.h b/biometrics/fingerprint/aidl/default/include/Callable.h
new file mode 100644
index 0000000..c629511
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/include/Callable.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+// Interface for representing parameterless functions. Unlike std::function<void()>, this can also
+// represent move-only lambdas.
+class Callable {
+ public:
+ virtual void operator()() = 0;
+ virtual ~Callable() = default;
+
+ // Creates a heap-allocated Callable instance from any function object.
+ template <typename T>
+ static std::unique_ptr<Callable> from(T func);
+
+ private:
+ template <typename T>
+ class AnyFuncWrapper;
+};
+
+// Private helper class for wrapping any function object into a Callable.
+template <typename T>
+class Callable::AnyFuncWrapper : public Callable {
+ public:
+ explicit AnyFuncWrapper(T func) : mFunc(std::move(func)) {}
+
+ void operator()() override { mFunc(); }
+
+ private:
+ T mFunc;
+};
+
+template <typename T>
+std::unique_ptr<Callable> Callable::from(T func) {
+ return std::make_unique<AnyFuncWrapper<T>>(std::move(func));
+}
+
+} // namespace aidl::android::hardware::biometrics::fingerprint
\ No newline at end of file
diff --git a/biometrics/fingerprint/aidl/default/include/CancellationSignal.h b/biometrics/fingerprint/aidl/default/include/CancellationSignal.h
new file mode 100644
index 0000000..99f2fba
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/include/CancellationSignal.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/biometrics/common/BnCancellationSignal.h>
+#include <aidl/android/hardware/biometrics/fingerprint/ISessionCallback.h>
+#include <functional>
+#include <future>
+
+#include "WorkerThread.h"
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+class CancellationSignal : public common::BnCancellationSignal {
+ public:
+ explicit CancellationSignal(std::promise<void>&& cancellationPromise);
+
+ ndk::ScopedAStatus cancel() override;
+
+ private:
+ std::promise<void> mCancellationPromise;
+};
+
+// Returns whether the given cancellation future is ready, i.e. whether the operation corresponding
+// to this future should be cancelled.
+bool shouldCancel(const std::future<void>& cancellationFuture);
+
+} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
new file mode 100644
index 0000000..9343316
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+class FakeFingerprintEngine {
+ public:
+ void generateChallengeImpl(ISessionCallback* cb, int32_t /*timeoutSec*/) {
+ LOG(INFO) << "generateChallengeImpl";
+ cb->onChallengeGenerated(0 /* challenge */);
+ }
+
+ void revokeChallengeImpl(ISessionCallback* cb, int64_t challenge) {
+ LOG(INFO) << "revokeChallengeImpl";
+ cb->onChallengeRevoked(challenge);
+ }
+
+ void enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& /*hat*/) {
+ LOG(INFO) << "enrollImpl";
+ cb->onEnrollmentProgress(0 /* enrollmentId */, 0 /* remaining */);
+ }
+
+ void authenticateImpl(ISessionCallback* cb, int64_t /*operationId*/) {
+ LOG(INFO) << "authenticateImpl";
+ cb->onAuthenticationSucceeded(0 /* enrollmentId */, {} /* hat */);
+ }
+
+ void detectInteractionImpl(ISessionCallback* cb) {
+ LOG(INFO) << "detectInteractionImpl";
+ cb->onInteractionDetected();
+ }
+
+ void enumerateEnrollmentsImpl(ISessionCallback* cb) {
+ LOG(INFO) << "enumerateEnrollmentsImpl";
+ cb->onEnrollmentsEnumerated({} /* enrollmentIds */);
+ }
+
+ void removeEnrollmentsImpl(ISessionCallback* cb, const std::vector<int32_t>& enrollmentIds) {
+ LOG(INFO) << "removeEnrollmentsImpl";
+ cb->onEnrollmentsRemoved(enrollmentIds);
+ }
+
+ void getAuthenticatorIdImpl(ISessionCallback* cb) {
+ LOG(INFO) << "getAuthenticatorIdImpl";
+ cb->onAuthenticatorIdRetrieved(0 /* authenticatorId */);
+ }
+
+ void invalidateAuthenticatorIdImpl(ISessionCallback* cb) {
+ LOG(INFO) << "invalidateAuthenticatorIdImpl";
+ cb->onAuthenticatorIdInvalidated(0 /* newAuthenticatorId */);
+ }
+
+ void resetLockoutImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& /*hat*/) {
+ LOG(INFO) << "resetLockoutImpl";
+ cb->onLockoutCleared();
+ }
+};
+
+} // namespace aidl::android::hardware::biometrics::fingerprint
\ No newline at end of file
diff --git a/biometrics/fingerprint/aidl/default/include/Fingerprint.h b/biometrics/fingerprint/aidl/default/include/Fingerprint.h
index ce1366c..9b8eef8 100644
--- a/biometrics/fingerprint/aidl/default/include/Fingerprint.h
+++ b/biometrics/fingerprint/aidl/default/include/Fingerprint.h
@@ -18,9 +18,13 @@
#include <aidl/android/hardware/biometrics/fingerprint/BnFingerprint.h>
+#include "FakeFingerprintEngine.h"
+#include "Session.h"
+#include "WorkerThread.h"
+
namespace aidl::android::hardware::biometrics::fingerprint {
-class Fingerprint final : public BnFingerprint {
+class Fingerprint : public BnFingerprint {
public:
Fingerprint();
@@ -31,6 +35,11 @@
std::shared_ptr<ISession>* out) override;
ndk::ScopedAStatus reset() override;
+
+ private:
+ std::unique_ptr<FakeFingerprintEngine> mEngine;
+ WorkerThread mWorker;
+ std::weak_ptr<Session> mSession;
};
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/include/Session.h b/biometrics/fingerprint/aidl/default/include/Session.h
index 99d806b..adda831 100644
--- a/biometrics/fingerprint/aidl/default/include/Session.h
+++ b/biometrics/fingerprint/aidl/default/include/Session.h
@@ -19,6 +19,9 @@
#include <aidl/android/hardware/biometrics/fingerprint/BnSession.h>
#include <aidl/android/hardware/biometrics/fingerprint/ISessionCallback.h>
+#include "FakeFingerprintEngine.h"
+#include "WorkerThread.h"
+
namespace aidl::android::hardware::biometrics::fingerprint {
namespace common = aidl::android::hardware::biometrics::common;
@@ -26,7 +29,8 @@
class Session : public BnSession {
public:
- explicit Session(std::shared_ptr<ISessionCallback> cb);
+ Session(int sensorId, int userId, std::shared_ptr<ISessionCallback> cb,
+ FakeFingerprintEngine* engine, WorkerThread* worker);
ndk::ScopedAStatus generateChallenge(int32_t cookie, int32_t timeoutSec) override;
@@ -35,7 +39,7 @@
ndk::ScopedAStatus enroll(int32_t cookie, const keymaster::HardwareAuthToken& hat,
std::shared_ptr<common::ICancellationSignal>* out) override;
- ndk::ScopedAStatus authenticate(int32_t cookie, int64_t keystoreOperationId,
+ ndk::ScopedAStatus authenticate(int32_t cookie, int64_t operationId,
std::shared_ptr<common::ICancellationSignal>* out) override;
ndk::ScopedAStatus detectInteraction(
@@ -62,8 +66,29 @@
ndk::ScopedAStatus onUiReady() override;
+ bool isClosed();
+
private:
+ // Crashes the HAL if it's not currently idling because that would be an invalid state machine
+ // transition. Otherwise, sets the scheduled state to the given state.
+ void scheduleStateOrCrash(SessionState state);
+
+ // Crashes the HAL if the provided state doesn't match the previously scheduled state.
+ // Otherwise, transitions into the provided state, clears the scheduled state, and notifies
+ // the client about the transition by calling ISessionCallback#onStateChanged.
+ void enterStateOrCrash(int cookie, SessionState state);
+
+ // Sets the current state to SessionState::IDLING and notifies the client about the transition
+ // by calling ISessionCallback#onStateChanged.
+ void enterIdling(int cookie);
+
+ int32_t mSensorId;
+ int32_t mUserId;
std::shared_ptr<ISessionCallback> mCb;
+ FakeFingerprintEngine* mEngine;
+ WorkerThread* mWorker;
+ SessionState mScheduledState;
+ SessionState mCurrentState;
};
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/include/WorkerThread.h b/biometrics/fingerprint/aidl/default/include/WorkerThread.h
index 49104c8..6fff4f2 100644
--- a/biometrics/fingerprint/aidl/default/include/WorkerThread.h
+++ b/biometrics/fingerprint/aidl/default/include/WorkerThread.h
@@ -21,9 +21,9 @@
#include <queue>
#include <thread>
-namespace aidl::android::hardware::biometrics::fingerprint {
+#include "Callable.h"
-using Task = std::function<void()>;
+namespace aidl::android::hardware::biometrics::fingerprint {
// A class that encapsulates a worker thread and a task queue, and provides a convenient interface
// for a Session to schedule its tasks for asynchronous execution.
@@ -47,7 +47,12 @@
// If the internal queue is not full, pushes a task at the end of the queue and returns true.
// Otherwise, returns false. If the queue is busy, blocks until it becomes available.
- bool schedule(Task&& task);
+ // This method expects heap-allocated tasks because it's the simplest way to represent function
+ // objects of any type. Stack-allocated std::function could be used instead, but it cannot
+ // represent functions with move-only captures because std::function is inherently copyable.
+ // Not being able to pass move-only lambdas is a major limitation for the HAL implementation,
+ // so heap-allocated tasks that share a common interface (Callable) were chosen instead.
+ bool schedule(std::unique_ptr<Callable> task);
private:
// The function that runs on the internal thread. Sequentially runs the available tasks from
@@ -63,7 +68,7 @@
std::atomic<bool> mIsDestructing;
// Queue that's guarded by mQueueMutex and mQueueCond.
- std::deque<Task> mQueue;
+ std::deque<std::unique_ptr<Callable>> mQueue;
std::mutex mQueueMutex;
std::condition_variable mQueueCond;
diff --git a/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
index ba901ad..0d5014bb 100644
--- a/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
@@ -25,13 +25,14 @@
namespace {
+using aidl::android::hardware::biometrics::fingerprint::Callable;
using aidl::android::hardware::biometrics::fingerprint::WorkerThread;
using namespace std::chrono_literals;
TEST(WorkerThreadTest, ScheduleReturnsTrueWhenQueueHasSpace) {
WorkerThread worker(1 /*maxQueueSize*/);
for (int i = 0; i < 100; ++i) {
- EXPECT_TRUE(worker.schedule([] {}));
+ EXPECT_TRUE(worker.schedule(Callable::from([] {})));
// Allow enough time for the previous task to be processed.
std::this_thread::sleep_for(2ms);
}
@@ -40,16 +41,16 @@
TEST(WorkerThreadTest, ScheduleReturnsFalseWhenQueueIsFull) {
WorkerThread worker(2 /*maxQueueSize*/);
// Add a long-running task.
- worker.schedule([] { std::this_thread::sleep_for(1s); });
+ worker.schedule(Callable::from([] { std::this_thread::sleep_for(1s); }));
// Allow enough time for the worker to start working on the previous task.
std::this_thread::sleep_for(2ms);
// Fill the worker's queue to the maximum.
- worker.schedule([] {});
- worker.schedule([] {});
+ worker.schedule(Callable::from([] {}));
+ worker.schedule(Callable::from([] {}));
- EXPECT_FALSE(worker.schedule([] {}));
+ EXPECT_FALSE(worker.schedule(Callable::from([] {})));
}
TEST(WorkerThreadTest, TasksExecuteInOrder) {
@@ -58,19 +59,19 @@
std::vector<int> results;
for (int i = 0; i < NUM_TASKS; ++i) {
- worker.schedule([&results, i] {
+ worker.schedule(Callable::from([&results, i] {
// Delay tasks differently to provoke races.
std::this_thread::sleep_for(std::chrono::nanoseconds(100 - i % 100));
// Unguarded write to results to provoke races.
results.push_back(i);
- });
+ }));
}
std::promise<void> promise;
auto future = promise.get_future();
// Schedule a special task to signal when all of the tasks are finished.
- worker.schedule([&promise] { promise.set_value(); });
+ worker.schedule(Callable::from([&promise] { promise.set_value(); }));
auto status = future.wait_for(1s);
ASSERT_EQ(status, std::future_status::ready);
@@ -86,11 +87,11 @@
{
WorkerThread worker(2 /*maxQueueSize*/);
- worker.schedule([&promise1] {
+ worker.schedule(Callable::from([&promise1] {
promise1.set_value();
std::this_thread::sleep_for(200ms);
- });
- worker.schedule([&promise2] { promise2.set_value(); });
+ }));
+ worker.schedule(Callable::from([&promise2] { promise2.set_value(); }));
// Make sure the first task is executing.
auto status1 = future1.wait_for(1s);
diff --git a/tv/tuner/1.1/default/Demux.cpp b/tv/tuner/1.1/default/Demux.cpp
index 66c95dc..f4e4a91 100644
--- a/tv/tuner/1.1/default/Demux.cpp
+++ b/tv/tuner/1.1/default/Demux.cpp
@@ -27,12 +27,16 @@
namespace implementation {
#define WAIT_TIMEOUT 3000000000
+
Demux::Demux(uint32_t demuxId, sp<Tuner> tuner) {
mDemuxId = demuxId;
mTunerService = tuner;
}
-Demux::~Demux() {}
+Demux::~Demux() {
+ mFrontendInputThreadRunning = false;
+ std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
+}
Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
ALOGV("%s", __FUNCTION__);
@@ -171,6 +175,8 @@
mFilters.clear();
mLastUsedFilterId = -1;
mTunerService->removeDemux(mDemuxId);
+ mFrontendInputThreadRunning = false;
+ std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
return Result::SUCCESS;
}
@@ -322,6 +328,7 @@
}
void Demux::startFrontendInputLoop() {
+ mFrontendInputThreadRunning = true;
pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
}
@@ -334,8 +341,6 @@
void Demux::frontendInputThreadLoop() {
std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
- mFrontendInputThreadRunning = true;
-
if (!mDvrPlayback) {
ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
mFrontendInputThreadRunning = false;
diff --git a/tv/tuner/1.1/default/Dvr.cpp b/tv/tuner/1.1/default/Dvr.cpp
index 3a4ef1b..93bb6a8 100644
--- a/tv/tuner/1.1/default/Dvr.cpp
+++ b/tv/tuner/1.1/default/Dvr.cpp
@@ -37,7 +37,10 @@
mDemux = demux;
}
-Dvr::~Dvr() {}
+Dvr::~Dvr() {
+ mDvrThreadRunning = false;
+ lock_guard<mutex> lock(mDvrThreadLock);
+}
Return<void> Dvr::getQueueDesc(getQueueDesc_cb _hidl_cb) {
ALOGV("%s", __FUNCTION__);
@@ -118,6 +121,9 @@
Return<Result> Dvr::start() {
ALOGV("%s", __FUNCTION__);
+ if (mDvrThreadRunning) {
+ return Result::SUCCESS;
+ }
if (!mCallback) {
return Result::NOT_INITIALIZED;
@@ -128,6 +134,7 @@
}
if (mType == DvrType::PLAYBACK) {
+ mDvrThreadRunning = true;
pthread_create(&mDvrThread, NULL, __threadLoopPlayback, this);
pthread_setname_np(mDvrThread, "playback_waiting_loop");
} else if (mType == DvrType::RECORD) {
@@ -144,7 +151,6 @@
ALOGV("%s", __FUNCTION__);
mDvrThreadRunning = false;
-
lock_guard<mutex> lock(mDvrThreadLock);
mIsRecordStarted = false;
@@ -164,6 +170,8 @@
Return<Result> Dvr::close() {
ALOGV("%s", __FUNCTION__);
+ mDvrThreadRunning = false;
+ lock_guard<mutex> lock(mDvrThreadLock);
return Result::SUCCESS;
}
@@ -199,7 +207,6 @@
void Dvr::playbackThreadLoop() {
ALOGD("[Dvr] playback threadLoop start.");
lock_guard<mutex> lock(mDvrThreadLock);
- mDvrThreadRunning = true;
while (mDvrThreadRunning) {
uint32_t efState = 0;
diff --git a/tv/tuner/1.1/default/Filter.cpp b/tv/tuner/1.1/default/Filter.cpp
index 6b2413c..2e29aa9 100644
--- a/tv/tuner/1.1/default/Filter.cpp
+++ b/tv/tuner/1.1/default/Filter.cpp
@@ -77,7 +77,10 @@
}
}
-Filter::~Filter() {}
+Filter::~Filter() {
+ mFilterThreadRunning = false;
+ std::lock_guard<std::mutex> lock(mFilterThreadLock);
+}
Return<void> Filter::getId64Bit(getId64Bit_cb _hidl_cb) {
ALOGV("%s", __FUNCTION__);
@@ -137,15 +140,14 @@
Return<Result> Filter::start() {
ALOGV("%s", __FUNCTION__);
-
+ mFilterThreadRunning = true;
return startFilterLoop();
}
Return<Result> Filter::stop() {
ALOGV("%s", __FUNCTION__);
-
mFilterThreadRunning = false;
-
+ std::lock_guard<std::mutex> lock(mFilterThreadLock);
return Result::SUCCESS;
}
@@ -185,6 +187,8 @@
Return<Result> Filter::close() {
ALOGV("%s", __FUNCTION__);
+ mFilterThreadRunning = false;
+ std::lock_guard<std::mutex> lock(mFilterThreadLock);
return mDemux->removeFilter(mFilterId);
}
@@ -331,9 +335,11 @@
}
void Filter::filterThreadLoop() {
- ALOGD("[Filter] filter %" PRIu64 " threadLoop start.", mFilterId);
+ if (!mFilterThreadRunning) {
+ return;
+ }
std::lock_guard<std::mutex> lock(mFilterThreadLock);
- mFilterThreadRunning = true;
+ ALOGD("[Filter] filter %" PRIu64 " threadLoop start.", mFilterId);
// For the first time of filter output, implementation needs to send the filter
// Event Callback without waiting for the DATA_CONSUMED to init the process.
@@ -382,6 +388,9 @@
// We do not wait for the last round of written data to be read to finish the thread
// because the VTS can verify the reading itself.
for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
+ if (!mFilterThreadRunning) {
+ break;
+ }
while (mFilterThreadRunning && mIsUsingFMQ) {
status_t status = mFilterEventFlag->wait(
static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
@@ -417,9 +426,8 @@
break;
}
}
- mFilterThreadRunning = false;
+ break;
}
-
ALOGD("[Filter] filter thread ended.");
}
diff --git a/tv/tuner/1.1/vts/functional/FilterTests.cpp b/tv/tuner/1.1/vts/functional/FilterTests.cpp
index d8fad3d..1617642 100644
--- a/tv/tuner/1.1/vts/functional/FilterTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FilterTests.cpp
@@ -274,6 +274,7 @@
AssertionResult FilterTests::stopFilter(uint64_t filterId) {
EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
Result status = mFilters[filterId]->stop();
+
return AssertionResult(status == Result::SUCCESS);
}
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.cpp b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
index 0948f74..887f8b8 100644
--- a/tv/tuner/1.1/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
@@ -305,6 +305,36 @@
return AssertionResult(status == Result::SUCCESS);
}
+AssertionResult FrontendTests::linkCiCam(uint32_t ciCamId) {
+ sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
+ frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
+ if (frontend_1_1 == nullptr) {
+ EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
+ return failure();
+ }
+
+ Result status;
+ uint32_t ltsId;
+ frontend_1_1->linkCiCam(ciCamId, [&](Result r, uint32_t id) {
+ status = r;
+ ltsId = id;
+ });
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::unlinkCiCam(uint32_t ciCamId) {
+ sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
+ frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
+ if (frontend_1_1 == nullptr) {
+ EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
+ return failure();
+ }
+
+ Result status = frontend_1_1->unlinkCiCam(ciCamId);
+ return AssertionResult(status == Result::SUCCESS);
+}
+
void FrontendTests::verifyFrontendStatusExt1_1(vector<FrontendStatusTypeExt1_1> statusTypes,
vector<FrontendStatusExt1_1> expectStatuses) {
ASSERT_TRUE(mFrontend) << "Frontend is not opened yet.";
@@ -465,6 +495,10 @@
ASSERT_TRUE(feId != INVALID_ID);
ASSERT_TRUE(openFrontendById(feId));
ASSERT_TRUE(setFrontendCallback());
+ if (frontendConf.canConnectToCiCam) {
+ ASSERT_TRUE(linkCiCam(frontendConf.ciCamId));
+ ASSERT_TRUE(unlinkCiCam(frontendConf.ciCamId));
+ }
ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
verifyFrontendStatusExt1_1(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.h b/tv/tuner/1.1/vts/functional/FrontendTests.h
index 243d9de..43c1579 100644
--- a/tv/tuner/1.1/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.h
@@ -123,6 +123,9 @@
AssertionResult closeFrontend();
AssertionResult getFrontendDtmbCaps(uint32_t);
+ AssertionResult linkCiCam(uint32_t ciCamId);
+ AssertionResult unlinkCiCam(uint32_t ciCamId);
+
void getFrontendIdByType(FrontendType feType, uint32_t& feId);
void tuneTest(FrontendConfig frontendConf);
void scanTest(FrontendConfig frontend, FrontendScanType type);
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
index 2dcb9a1..2e6c87f 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
@@ -211,6 +211,11 @@
mFrontendTests.getFrontendDtmbCapsTest();
}
+TEST_P(TunerFrontendHidlTest, LinkToCiCam) {
+ description("Test Frontend link to CiCam");
+ mFrontendTests.tuneTest(frontendArray[defaultFrontend]);
+}
+
INSTANTIATE_TEST_SUITE_P(
PerInstance, TunerBroadcastHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
index beae223..ecdf683 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
@@ -103,6 +103,8 @@
struct FrontendConfig {
bool isSoftwareFe;
+ bool canConnectToCiCam;
+ uint32_t ciCamId;
FrontendType type;
FrontendSettings settings;
FrontendSettingsExt1_1 settingsExt1_1;
@@ -121,6 +123,7 @@
static FrontendConfig frontendScanArray[SCAN_MAX];
static FilterConfig filterArray[FILTER_MAX];
static DvrConfig dvrArray[DVR_MAX];
+static int defaultFrontend = DVBT;
/** Configuration array for the frontend tune test */
inline void initFrontendConfig() {
@@ -150,6 +153,8 @@
frontendArray[DVBT].tuneStatusTypes = types;
frontendArray[DVBT].expectTuneStatuses = statuses;
frontendArray[DVBT].isSoftwareFe = true;
+ frontendArray[DVBT].canConnectToCiCam = true;
+ frontendArray[DVBT].ciCamId = 0;
frontendArray[DVBT].settingsExt1_1.settingExt.dvbt({
.transmissionMode =
android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode::MODE_8K_E,
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl
index 8cb259f..0995d2d 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl
@@ -1,14 +1,29 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// 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 changes to the AIDL files built
+// 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
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
index 3071dce3..0b4b527 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
@@ -1,14 +1,29 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// 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 changes to the AIDL files built
+// 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
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl
index 5ed4dc5..0d2b340 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl
@@ -1,14 +1,29 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// 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 changes to the AIDL files built
+// 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
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl
index 802d236..808644a 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl
@@ -1,14 +1,29 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// 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 changes to the AIDL files built
+// 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
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 2de1d7b..1f2d946 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
@@ -1,14 +1,29 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// 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 changes to the AIDL files built
+// 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
@@ -33,6 +48,8 @@
android.hardware.vibrator.Effect[] getSupportedAlwaysOnEffects();
void alwaysOnEnable(in int id, in android.hardware.vibrator.Effect effect, in android.hardware.vibrator.EffectStrength strength);
void alwaysOnDisable(in int id);
+ float getResonantFrequency();
+ float getQFactor();
const int CAP_ON_CALLBACK = 1;
const int CAP_PERFORM_CALLBACK = 2;
const int CAP_AMPLITUDE_CONTROL = 4;
@@ -40,4 +57,6 @@
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;
}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl
index 3a1e7d8..f99ecc1 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl
@@ -1,14 +1,29 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// 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 changes to the AIDL files built
+// 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
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 99cd448..8e3ac88 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
@@ -1,14 +1,29 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * Copyright (C) 2020 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 interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// 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 changes to the AIDL files built
+// 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
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index cd7b603..cba76dc 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -52,6 +52,14 @@
* Whether alwaysOnEnable/alwaysOnDisable is supported.
*/
const int CAP_ALWAYS_ON_CONTROL = 1 << 6;
+ /**
+ * Whether getResonantFrequency is supported.
+ */
+ const int CAP_GET_RESONANT_FREQUENCY = 1 << 7;
+ /**
+ * Whether getQFactor is supported.
+ */
+ const int CAP_GET_Q_FACTOR = 1 << 8;
/**
* Determine capabilities of the vibrator HAL (CAP_* mask)
@@ -230,4 +238,20 @@
* @param id The device-specific always-on source ID to disable.
*/
void alwaysOnDisable(in int id);
+
+ /**
+ * Retrieve the measured resonant frequency of the actuator. This may not be supported
+ * and this support is reflected in getCapabilities (CAP_GET_RESONANT_FREQUENCY)
+ *
+ * @return Measured resonant frequency in Hz.
+ */
+ float getResonantFrequency();
+
+ /**
+ * Retrieve the measured Q factor. This may not be supported
+ * and this support is reflected in getCapabilities (CAP_GET_Q_FACTOR)
+ *
+ * @return Measured Q factor.
+ */
+ float getQFactor();
}
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index 1021e62..bf61bfe 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -27,12 +27,16 @@
static constexpr int32_t kComposeDelayMaxMs = 1000;
static constexpr int32_t kComposeSizeMax = 256;
+static constexpr float kResonantFrequency = 150.0;
+static constexpr float kQFactor = 11.0;
+
ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
LOG(INFO) << "Vibrator reporting capabilities";
*_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL |
IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS |
- IVibrator::CAP_ALWAYS_ON_CONTROL;
+ IVibrator::CAP_ALWAYS_ON_CONTROL | IVibrator::CAP_GET_RESONANT_FREQUENCY |
+ IVibrator::CAP_GET_Q_FACTOR;
return ndk::ScopedAStatus::ok();
}
@@ -201,6 +205,16 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Vibrator::getResonantFrequency(float *resonantFreqHz) {
+ *resonantFreqHz = kResonantFrequency;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getQFactor(float *qFactor) {
+ *qFactor = kQFactor;
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace vibrator
} // namespace hardware
} // namespace android
diff --git a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
index c3f3616..a2af963 100644
--- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
+++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
@@ -44,6 +44,8 @@
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;
};
} // namespace vibrator
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index adbb0cf..2540d0b 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -538,6 +538,28 @@
}
}
+TEST_P(VibratorAidl, GetResonantFrequency) {
+ float resonantFrequency;
+ Status status = vibrator->getResonantFrequency(&resonantFrequency);
+ if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
+ ASSERT_NE(resonantFrequency, 0);
+ EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+ } else {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ }
+}
+
+TEST_P(VibratorAidl, GetQFactor) {
+ float qFactor;
+ Status status = vibrator->getQFactor(&qFactor);
+ if (capabilities & IVibrator::CAP_GET_Q_FACTOR) {
+ ASSERT_NE(qFactor, 0);
+ EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+ } else {
+ EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+ }
+}
+
std::vector<std::tuple<int32_t, int32_t>> GenerateVibratorMapping() {
std::vector<std::tuple<int32_t, int32_t>> tuples;
auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
diff --git a/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp
index 5ac747d..07f7f47 100644
--- a/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp
@@ -147,6 +147,7 @@
* setCoexUnsafeChannels
*/
TEST_P(WifiChipHidlTest, setCoexUnsafeChannels) {
+ configureChipForIfaceType(IfaceType::STA, true);
// Test with empty vector of CoexUnsafeChannels
std::vector<IWifiChip::CoexUnsafeChannel> vec;
const auto& statusEmpty =