Merge "libradiocompat CallbackManager: add extra logging" into main
diff --git a/camera/device/default/ExternalCameraDeviceSession.cpp b/camera/device/default/ExternalCameraDeviceSession.cpp
index abd5d7e..9c55ea9 100644
--- a/camera/device/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/default/ExternalCameraDeviceSession.cpp
@@ -1185,6 +1185,7 @@
             if (numAttempt == MAX_RETRY) {
                 break;
             }
+            numAttempt++;
             if (ret < 0) {
                 ALOGW("%s: VIDIOC_STREAMON failed, wait 33ms and try again", __FUNCTION__);
                 usleep(IOCTL_RETRY_SLEEP_US);  // sleep 100 ms and try again
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index 1fd21d8..a0510ce 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -91,6 +91,52 @@
     if (!status.isOk()) {
         ALOGE("%s: Unable to invoke callback.gnssSetSignalTypeCapabilitiesCb", __func__);
     }
+
+    // In case when the setCallback() and close() calls are not balanced
+    mIsInitialized = false;
+    mIsActive = false;
+    mThreadBlocker.notify();
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+
+    mIsInitialized = true;
+    mThreadBlocker.reset();
+    mThread = std::thread([this]() {
+        while (mIsInitialized) {
+            if (mIsActive) {
+                if (mReportedLocationCount == 0) {
+                    if (!mGnssMeasurementEnabled || mMinIntervalMs <= mGnssMeasurementIntervalMs) {
+                        this->reportSvStatus();
+                    }
+                    if (!mFirstFixReceived) {
+                        // Simulate the code start TTFF
+                        std::this_thread::sleep_for(std::chrono::milliseconds(TTFF_MILLIS));
+                        mFirstFixReceived = true;
+                    }
+                }
+                if (!mGnssMeasurementEnabled || mMinIntervalMs <= mGnssMeasurementIntervalMs) {
+                    this->reportSvStatus();
+                }
+                this->reportNmea();
+
+                auto currentLocation = getLocationFromHW();
+                mGnssPowerIndication->notePowerConsumption();
+                if (currentLocation != nullptr) {
+                    this->reportLocation(*currentLocation);
+                } else {
+                    const auto location = Utils::getMockLocation();
+                    this->reportLocation(location);
+                }
+                mReportedLocationCount += 1;
+                mThreadBlocker.wait_for(std::chrono::milliseconds(mMinIntervalMs));
+            } else {
+                // Wait indefinitely until start() or close() is called
+                mThreadBlocker.wait();
+            }
+        }
+    });
+
     return ScopedAStatus::ok();
 }
 
@@ -104,48 +150,16 @@
 }
 
 ScopedAStatus Gnss::start() {
-    ALOGD("start()");
+    ALOGD("start");
     if (mIsActive) {
         ALOGW("Gnss has started. Restarting...");
         stop();
     }
-
     mIsActive = true;
-    mThreadBlocker.reset();
     // notify measurement engine to update measurement interval
     mGnssMeasurementInterface->setLocationEnabled(true);
     this->reportGnssStatusValue(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
-    mThread = std::thread([this]() {
-        if (!mGnssMeasurementEnabled || mMinIntervalMs <= mGnssMeasurementIntervalMs) {
-            this->reportSvStatus();
-        }
-        if (!mFirstFixReceived) {
-            std::this_thread::sleep_for(std::chrono::milliseconds(TTFF_MILLIS));
-            mFirstFixReceived = true;
-        }
-        int reportGnssCount = 0;
-        do {
-            if (!mIsActive) {
-                ALOGD("Do not report location. mIsActive is false");
-                break;
-            }
-            reportGnssCount += 1;
-            if (!mGnssMeasurementEnabled || mMinIntervalMs <= mGnssMeasurementIntervalMs) {
-                this->reportSvStatus();
-            }
-            this->reportNmea();
-
-            auto currentLocation = getLocationFromHW();
-            mGnssPowerIndication->notePowerConsumption();
-            if (currentLocation != nullptr) {
-                this->reportLocation(*currentLocation);
-            } else {
-                const auto location = Utils::getMockLocation();
-                this->reportLocation(location);
-            }
-        } while (mIsActive && mThreadBlocker.wait_for(std::chrono::milliseconds(mMinIntervalMs)));
-        ALOGD("reportGnssCount: %d", reportGnssCount);
-    });
+    mThreadBlocker.notify();
     return ScopedAStatus::ok();
 }
 
@@ -154,16 +168,22 @@
     mIsActive = false;
     mGnssMeasurementInterface->setLocationEnabled(false);
     this->reportGnssStatusValue(IGnssCallback::GnssStatusValue::SESSION_END);
+
+    int reportedLocationCount = mReportedLocationCount;
+    ALOGD("reportedLocationCount: %d", reportedLocationCount);
+    mReportedLocationCount = 0;
     mThreadBlocker.notify();
-    if (mThread.joinable()) {
-        mThread.join();
-    }
     return ScopedAStatus::ok();
 }
 
 ScopedAStatus Gnss::close() {
     ALOGD("close");
     sGnssCallback = nullptr;
+    mIsInitialized = false;
+    mThreadBlocker.notify();
+    if (mThread.joinable()) {
+        mThread.join();
+    }
     return ScopedAStatus::ok();
 }
 
diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h
index 56fe399..aea9eb9 100644
--- a/gnss/aidl/default/Gnss.h
+++ b/gnss/aidl/default/Gnss.h
@@ -110,10 +110,12 @@
     std::atomic<long> mMinIntervalMs;
     std::atomic<long> mGnssMeasurementIntervalMs;
     std::atomic<bool> mIsActive;
+    std::atomic<bool> mIsInitialized;
     std::atomic<bool> mIsSvStatusActive;
     std::atomic<bool> mIsNmeaActive;
     std::atomic<bool> mFirstFixReceived;
     std::atomic<bool> mGnssMeasurementEnabled;
+    std::atomic<int> mReportedLocationCount;
     std::shared_ptr<GnssLocation> mLastLocation;
     std::thread mThread;
     ::android::hardware::gnss::common::ThreadBlocker mThreadBlocker;
diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h
index 9be4a19..55960fd 100644
--- a/gnss/common/utils/default/include/Utils.h
+++ b/gnss/common/utils/default/include/Utils.h
@@ -61,9 +61,16 @@
     template <class R, class P>
     bool wait_for(std::chrono::duration<R, P> const& time) {
         std::unique_lock<std::mutex> lock(m);
+        terminate = false;
         return !cv.wait_for(lock, time, [&] { return terminate; });
     }
 
+    void wait() {
+        std::unique_lock<std::mutex> lock(m);
+        terminate = false;
+        cv.wait(lock, [&] { return terminate; });
+    }
+
     void notify() {
         std::unique_lock<std::mutex> lock(m);
         terminate = true;
diff --git a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
index b1590f9..77e2916 100644
--- a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
+++ b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
@@ -616,8 +616,18 @@
 }
 
 TEST_P(SensorsAidlTest, InjectSensorEventData) {
-    std::vector<SensorInfo> sensors = getInjectEventSensors();
-    if (sensors.size() == 0) {
+    std::vector<SensorInfo> sensorsAll = getInjectEventSensors();
+    std::vector<SensorInfo> sensors3d;
+
+    for (const auto& s : sensorsAll) {
+        if ((s.type == SensorType::ACCELEROMETER) || (s.type == SensorType::GYROSCOPE) ||
+            (s.type == SensorType::MAGNETIC_FIELD)) {
+            sensors3d.push_back(s);
+        }
+    }
+
+    // Here we only test for the sensors with vec3 data type
+    if (sensors3d.size() == 0) {
         return;
     }
 
@@ -645,7 +655,7 @@
     Event::EventPayload::Vec3 data = {1, 2, 3, SensorStatus::ACCURACY_HIGH};
     injectedEvent.payload.set<Event::EventPayload::Tag::vec3>(data);
 
-    for (const auto& s : sensors) {
+    for (const auto& s : sensors3d) {
         additionalInfoEvent.sensorHandle = s.sensorHandle;
         ASSERT_TRUE(getSensors()->injectSensorData(additionalInfoEvent).isOk());
 
@@ -655,10 +665,10 @@
     }
 
     // Wait for events to be written back to the Event FMQ
-    callback.waitForEvents(sensors, std::chrono::milliseconds(1000) /* timeout */);
+    callback.waitForEvents(sensors3d, std::chrono::milliseconds(1000) /* timeout */);
     getEnvironment()->unregisterCallback();
 
-    for (const auto& s : sensors) {
+    for (const auto& s : sensors3d) {
         auto events = callback.getEvents(s.sensorHandle);
         if (events.empty()) {
             FAIL() << "Received no events";
diff --git a/uwb/aidl/vts/VtsHalUwbTargetTest.cpp b/uwb/aidl/vts/VtsHalUwbTargetTest.cpp
index 2b09f7e..c75160c 100644
--- a/uwb/aidl/vts/VtsHalUwbTargetTest.cpp
+++ b/uwb/aidl/vts/VtsHalUwbTargetTest.cpp
@@ -202,8 +202,26 @@
 }
 
 TEST_P(UwbAidl, ChipSendUciMessage_GetDeviceInfo) {
-    const auto iuwb_chip = getAnyChipAndOpen();
+    std::promise<void> open_cb_promise;
+    std::future<void> open_cb_future{open_cb_promise.get_future()};
+    std::promise<void> init_cb_promise;
+    std::future<void> init_cb_future{init_cb_promise.get_future()};
+    std::shared_ptr<UwbClientCallback> callback = ndk::SharedRefBase::make<UwbClientCallback>(
+            [](auto /* data */) {},
+            [&init_cb_promise, &open_cb_promise](auto event, auto /* status */) {
+                if (event == UwbEvent::OPEN_CPLT) {
+                    open_cb_promise.set_value();
+                }
+                if (event == UwbEvent::POST_INIT_CPLT) {
+                    init_cb_promise.set_value();
+                }
+            });
+    std::chrono::milliseconds timeout{1000};
+    const auto iuwb_chip = getAnyChip();
+    EXPECT_TRUE(iuwb_chip->open(callback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
     EXPECT_TRUE(iuwb_chip->coreInit().isOk());
+    EXPECT_EQ(init_cb_future.wait_for(timeout), std::future_status::ready);
 
     std::vector<uint8_t> uciMessage = {0x20, 0x02, 0x00, 0x00}; /** CoreGetDeviceInfo */
     int32_t* return_status = new int32_t;
diff --git a/vibrator/bench/Android.bp b/vibrator/bench/Android.bp
index cd56516..9100d40 100644
--- a/vibrator/bench/Android.bp
+++ b/vibrator/bench/Android.bp
@@ -25,19 +25,12 @@
 
 cc_benchmark {
     name: "VibratorHalIntegrationBenchmark",
-    defaults: ["hidl_defaults"],
     srcs: [
         "benchmark.cpp",
     ],
     shared_libs: [
         "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_ndk",
-        "libhardware",
-        "libhidlbase",
         "libutils",
     ],
     test_suites: ["device-tests"],
diff --git a/vibrator/bench/benchmark.cpp b/vibrator/bench/benchmark.cpp
index 8fe9cf7..76d67ef 100644
--- a/vibrator/bench/benchmark.cpp
+++ b/vibrator/bench/benchmark.cpp
@@ -21,12 +21,8 @@
 
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
-#include <android/hardware/vibrator/1.3/IVibrator.h>
 #include <future>
 
-using ::android::hardware::hidl_enum_range;
-using ::android::hardware::Return;
-using ::android::hardware::details::hidl_enum_values;
 using ::benchmark::Counter;
 using ::benchmark::Fixture;
 using ::benchmark::kMicrosecond;
@@ -34,14 +30,9 @@
 using ::benchmark::internal::Benchmark;
 using ::ndk::enum_range;
 
+using namespace ::aidl::android::hardware::vibrator;
 using namespace ::std::chrono_literals;
 
-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;
-namespace V1_3 = ::android::hardware::vibrator::V1_3;
-
 // Fixed number of iterations for benchmarks that trigger a vibration on the loop.
 // They require slow cleanup to ensure a stable state on each run and less noisy metrics.
 static constexpr auto VIBRATION_ITERATIONS = 500;
@@ -52,328 +43,32 @@
 // Max duration the vibrator can be turned on, in milliseconds.
 static constexpr uint32_t MAX_ON_DURATION_MS = UINT16_MAX;
 
-template <typename I>
-class BaseBench : public Fixture {
+class VibratorBench : public Fixture {
   public:
     void SetUp(State& /*state*/) override {
         ABinderProcess_setThreadPoolMaxThreadCount(1);
         ABinderProcess_startThreadPool();
+        auto serviceName = std::string(IVibrator::descriptor) + "/default";
+        this->mVibrator = IVibrator::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
     }
 
     void TearDown(State& /*state*/) override {
         if (mVibrator) {
             mVibrator->off();
+            mVibrator->setExternalControl(false);
         }
     }
 
     static void DefaultConfig(Benchmark* b) { b->Unit(kMicrosecond); }
 
-    static void DefaultArgs(Benchmark* /*b*/) { /* none */
-    }
+    static void DefaultArgs(Benchmark* /*b*/) { /* none */ }
 
   protected:
+    std::shared_ptr<IVibrator> mVibrator;
+
     auto getOtherArg(const State& state, std::size_t index) const { return state.range(index + 0); }
 
-  protected:
-    std::shared_ptr<I> mVibrator;
-};
-
-template <typename I>
-class VibratorBench : public BaseBench<I> {
-  public:
-    void SetUp(State& state) override {
-        BaseBench<I>::SetUp(state);
-        auto service = I::getService();
-        if (service) {
-            this->mVibrator = std::shared_ptr<I>(service.release());
-        } else {
-            this->mVibrator = nullptr;
-        }
-    }
-
-  protected:
-    bool shouldSkipWithError(State& state, const android::hardware::Return<V1_0::Status>&& ret) {
-        if (!ret.isOk()) {
-            state.SkipWithError(ret.description());
-            return true;
-        }
-        return false;
-    }
-};
-
-enum class EmptyEnum : uint32_t;
-template <>
-inline constexpr std::array<EmptyEnum, 0> hidl_enum_values<EmptyEnum> = {};
-
-template <typename T, typename U>
-std::set<T> difference(const hidl_enum_range<T>& t, const hidl_enum_range<U>& u) {
-    class Compare {
-      public:
-        bool operator()(const T& a, const U& b) { return a < static_cast<T>(b); }
-        bool operator()(const U& a, const T& b) { return static_cast<T>(a) < b; }
-    };
-    std::set<T> ret;
-
-    std::set_difference(t.begin(), t.end(), u.begin(), u.end(),
-                        std::insert_iterator<decltype(ret)>(ret, ret.begin()), Compare());
-
-    return ret;
-}
-
-template <typename I, typename E1, typename E2 = EmptyEnum>
-class VibratorEffectsBench : public VibratorBench<I> {
-  public:
-    using Effect = E1;
-    using EffectStrength = V1_0::EffectStrength;
-    using Status = V1_0::Status;
-
-  public:
-    static void DefaultArgs(Benchmark* b) {
-        b->ArgNames({"Effect", "Strength"});
-        for (const auto& effect : difference(hidl_enum_range<E1>(), hidl_enum_range<E2>())) {
-            for (const auto& strength : hidl_enum_range<EffectStrength>()) {
-                b->Args({static_cast<long>(effect), static_cast<long>(strength)});
-            }
-        }
-    }
-
-    void performBench(State* state, Return<void> (I::*performApi)(Effect, EffectStrength,
-                                                                  typename I::perform_cb)) {
-        auto effect = getEffect(*state);
-        auto strength = getStrength(*state);
-        bool supported = true;
-
-        (*this->mVibrator.*performApi)(effect, strength, [&](Status status, uint32_t /*lengthMs*/) {
-            if (status == Status::UNSUPPORTED_OPERATION) {
-                supported = false;
-            }
-        });
-
-        if (!supported) {
-            state->SkipWithMessage("effect unsupported");
-            return;
-        }
-
-        for (auto _ : *state) {
-            // Test
-            auto ret = (*this->mVibrator.*performApi)(
-                    effect, strength, [](Status /*status*/, uint32_t /*lengthMs*/) {});
-
-            // Cleanup
-            state->PauseTiming();
-            if (!ret.isOk()) {
-                state->SkipWithError(ret.description());
-                return;
-            }
-            if (this->shouldSkipWithError(*state, this->mVibrator->off())) {
-                return;
-            }
-            state->ResumeTiming();
-        }
-    }
-
-  protected:
-    auto getEffect(const State& state) const {
-        return static_cast<Effect>(this->getOtherArg(state, 0));
-    }
-
-    auto getStrength(const State& state) const {
-        return static_cast<EffectStrength>(this->getOtherArg(state, 1));
-    }
-};
-
-#define BENCHMARK_WRAPPER(fixt, test, code)           \
-    BENCHMARK_DEFINE_F(fixt, test)                    \
-    /* NOLINTNEXTLINE */                              \
-    (State & state) {                                 \
-        if (!mVibrator) {                             \
-            state.SkipWithMessage("HAL unavailable"); \
-            return;                                   \
-        }                                             \
-                                                      \
-        code                                          \
-    }                                                 \
-    BENCHMARK_REGISTER_F(fixt, test)->Apply(fixt::DefaultConfig)->Apply(fixt::DefaultArgs)
-
-using VibratorBench_V1_0 = VibratorBench<V1_0::IVibrator>;
-
-BENCHMARK_WRAPPER(VibratorBench_V1_0, on, {
-    auto ms = MAX_ON_DURATION_MS;
-
-    for (auto _ : state) {
-        // Test
-        if (shouldSkipWithError(state, mVibrator->on(ms))) {
-            return;
-        }
-
-        // Cleanup
-        state.PauseTiming();
-        if (shouldSkipWithError(state, mVibrator->off())) {
-            return;
-        }
-        state.ResumeTiming();
-    }
-});
-
-BENCHMARK_WRAPPER(VibratorBench_V1_0, off, {
-    auto ms = MAX_ON_DURATION_MS;
-
-    for (auto _ : state) {
-        // Setup
-        state.PauseTiming();
-        if (shouldSkipWithError(state, mVibrator->on(ms))) {
-            return;
-        }
-        state.ResumeTiming();
-
-        // Test
-        if (shouldSkipWithError(state, mVibrator->off())) {
-            return;
-        }
-    }
-});
-
-BENCHMARK_WRAPPER(VibratorBench_V1_0, supportsAmplitudeControl, {
-    for (auto _ : state) {
-        mVibrator->supportsAmplitudeControl();
-    }
-});
-
-BENCHMARK_WRAPPER(VibratorBench_V1_0, setAmplitude, {
-    auto ms = MAX_ON_DURATION_MS;
-    uint8_t amplitude = UINT8_MAX;
-
-    if (!mVibrator->supportsAmplitudeControl()) {
-        state.SkipWithMessage("amplitude control unavailable");
-        return;
-    }
-
-    if (shouldSkipWithError(state, mVibrator->on(ms))) {
-        return;
-    }
-
-    for (auto _ : state) {
-        if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
-            return;
-        }
-    }
-});
-
-using VibratorEffectsBench_V1_0 = VibratorEffectsBench<V1_0::IVibrator, V1_0::Effect>;
-
-BENCHMARK_WRAPPER(VibratorEffectsBench_V1_0, perform,
-                  { performBench(&state, &V1_0::IVibrator::perform); });
-
-using VibratorEffectsBench_V1_1 =
-        VibratorEffectsBench<V1_1::IVibrator, V1_1::Effect_1_1, V1_0::Effect>;
-
-BENCHMARK_WRAPPER(VibratorEffectsBench_V1_1, perform_1_1,
-                  { performBench(&state, &V1_1::IVibrator::perform_1_1); });
-
-using VibratorEffectsBench_V1_2 =
-        VibratorEffectsBench<V1_2::IVibrator, V1_2::Effect, V1_1::Effect_1_1>;
-
-BENCHMARK_WRAPPER(VibratorEffectsBench_V1_2, perform_1_2,
-                  { performBench(&state, &V1_2::IVibrator::perform_1_2); });
-
-class VibratorBench_V1_3 : public VibratorBench<V1_3::IVibrator> {
-  public:
-    void TearDown(State& state) override {
-        VibratorBench::TearDown(state);
-        if (mVibrator) {
-            mVibrator->setExternalControl(false);
-        }
-    }
-};
-
-BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, {
-    for (auto _ : state) {
-        mVibrator->supportsExternalControl();
-    }
-});
-
-BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalControl, {
-    if (!mVibrator->supportsExternalControl()) {
-        state.SkipWithMessage("external control unavailable");
-        return;
-    }
-
-    for (auto _ : state) {
-        // Test
-        if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
-            return;
-        }
-
-        // Cleanup
-        state.PauseTiming();
-        if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) {
-            return;
-        }
-        state.ResumeTiming();
-    }
-});
-
-BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalAmplitudeControl, {
-    if (!mVibrator->supportsExternalControl()) {
-        state.SkipWithMessage("external control unavailable");
-        return;
-    }
-
-    if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
-        return;
-    }
-
-    for (auto _ : state) {
-        mVibrator->supportsAmplitudeControl();
-    }
-});
-
-BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, {
-    uint8_t amplitude = UINT8_MAX;
-
-    if (!mVibrator->supportsExternalControl()) {
-        state.SkipWithMessage("external control unavailable");
-        return;
-    }
-
-    if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
-        return;
-    }
-
-    if (!mVibrator->supportsAmplitudeControl()) {
-        state.SkipWithMessage("amplitude control unavailable");
-        return;
-    }
-
-    for (auto _ : state) {
-        if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
-            return;
-        }
-    }
-});
-
-using VibratorEffectsBench_V1_3 = VibratorEffectsBench<V1_3::IVibrator, V1_3::Effect, V1_2::Effect>;
-
-BENCHMARK_WRAPPER(VibratorEffectsBench_V1_3, perform_1_3,
-                  { performBench(&state, &V1_3::IVibrator::perform_1_3); });
-
-class VibratorBench_Aidl : public BaseBench<Aidl::IVibrator> {
-  public:
-    void SetUp(State& state) override {
-        BaseBench::SetUp(state);
-        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 {
-        BaseBench::TearDown(state);
-        if (mVibrator) {
-            mVibrator->setExternalControl(false);
-        }
-    }
-
-  protected:
     int32_t hasCapabilities(int32_t capabilities) {
         int32_t deviceCapabilities = 0;
         this->mVibrator->getCapabilities(&deviceCapabilities);
@@ -401,15 +96,15 @@
     static void SlowBenchConfig(Benchmark* b) { b->Iterations(VIBRATION_ITERATIONS); }
 };
 
-class SlowVibratorBench_Aidl : public VibratorBench_Aidl {
+class SlowVibratorBench : public VibratorBench {
   public:
     static void DefaultConfig(Benchmark* b) {
-        VibratorBench_Aidl::DefaultConfig(b);
+        VibratorBench::DefaultConfig(b);
         SlowBenchConfig(b);
     }
 };
 
-class HalCallback : public Aidl::BnVibratorCallback {
+class HalCallback : public BnVibratorCallback {
   public:
     HalCallback() = default;
     ~HalCallback() = default;
@@ -425,11 +120,24 @@
     std::promise<void> mPromise;
 };
 
-BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, on, {
+#define BENCHMARK_WRAPPER(fixt, test, code)           \
+    BENCHMARK_DEFINE_F(fixt, test)                    \
+    /* NOLINTNEXTLINE */                              \
+    (State & state) {                                 \
+        if (!mVibrator) {                             \
+            state.SkipWithMessage("HAL unavailable"); \
+            return;                                   \
+        }                                             \
+                                                      \
+        code                                          \
+    }                                                 \
+    BENCHMARK_REGISTER_F(fixt, test)->Apply(fixt::DefaultConfig)->Apply(fixt::DefaultArgs)
+
+BENCHMARK_WRAPPER(SlowVibratorBench, on, {
     auto ms = MAX_ON_DURATION_MS;
 
     for (auto _ : state) {
-        auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
+        auto cb = hasCapabilities(IVibrator::CAP_ON_CALLBACK)
                           ? ndk::SharedRefBase::make<HalCallback>()
                           : nullptr;
         // Grab the future before callback promise is destroyed by the HAL.
@@ -450,11 +158,11 @@
     }
 });
 
-BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, off, {
+BENCHMARK_WRAPPER(SlowVibratorBench, off, {
     auto ms = MAX_ON_DURATION_MS;
 
     for (auto _ : state) {
-        auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
+        auto cb = hasCapabilities(IVibrator::CAP_ON_CALLBACK)
                           ? ndk::SharedRefBase::make<HalCallback>()
                           : nullptr;
         // Grab the future before callback promise is destroyed by the HAL.
@@ -479,7 +187,7 @@
     }
 });
 
-BENCHMARK_WRAPPER(VibratorBench_Aidl, getCapabilities, {
+BENCHMARK_WRAPPER(VibratorBench, getCapabilities, {
     int32_t capabilities = 0;
 
     for (auto _ : state) {
@@ -489,16 +197,16 @@
     }
 });
 
-BENCHMARK_WRAPPER(VibratorBench_Aidl, setAmplitude, {
+BENCHMARK_WRAPPER(VibratorBench, setAmplitude, {
     auto ms = MAX_ON_DURATION_MS;
     float amplitude = 1.0f;
 
-    if (!hasCapabilities(Aidl::IVibrator::CAP_AMPLITUDE_CONTROL)) {
+    if (!hasCapabilities(IVibrator::CAP_AMPLITUDE_CONTROL)) {
         state.SkipWithMessage("amplitude control unavailable");
         return;
     }
 
-    auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
+    auto cb = hasCapabilities(IVibrator::CAP_ON_CALLBACK)
                       ? ndk::SharedRefBase::make<HalCallback>()
                       : nullptr;
     if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
@@ -512,8 +220,8 @@
     }
 });
 
-BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalControl, {
-    if (!hasCapabilities(Aidl::IVibrator::CAP_EXTERNAL_CONTROL)) {
+BENCHMARK_WRAPPER(VibratorBench, setExternalControl, {
+    if (!hasCapabilities(IVibrator::CAP_EXTERNAL_CONTROL)) {
         state.SkipWithMessage("external control unavailable");
         return;
     }
@@ -533,10 +241,10 @@
     }
 });
 
-BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalAmplitude, {
-    auto externalControl = static_cast<int32_t>(Aidl::IVibrator::CAP_EXTERNAL_CONTROL);
+BENCHMARK_WRAPPER(VibratorBench, setExternalAmplitude, {
+    auto externalControl = static_cast<int32_t>(IVibrator::CAP_EXTERNAL_CONTROL);
     auto externalAmplitudeControl =
-            static_cast<int32_t>(Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL);
+            static_cast<int32_t>(IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL);
     if (!hasCapabilities(externalControl | externalAmplitudeControl)) {
         state.SkipWithMessage("external amplitude control unavailable");
         return;
@@ -554,8 +262,8 @@
     }
 });
 
-BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedEffects, {
-    std::vector<Aidl::Effect> supportedEffects;
+BENCHMARK_WRAPPER(VibratorBench, getSupportedEffects, {
+    std::vector<Effect> supportedEffects;
 
     for (auto _ : state) {
         if (shouldSkipWithError(state, mVibrator->getSupportedEffects(&supportedEffects))) {
@@ -564,13 +272,13 @@
     }
 });
 
-BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedAlwaysOnEffects, {
-    if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) {
+BENCHMARK_WRAPPER(VibratorBench, getSupportedAlwaysOnEffects, {
+    if (!hasCapabilities(IVibrator::CAP_ALWAYS_ON_CONTROL)) {
         state.SkipWithMessage("always on control unavailable");
         return;
     }
 
-    std::vector<Aidl::Effect> supportedEffects;
+    std::vector<Effect> supportedEffects;
 
     for (auto _ : state) {
         if (shouldSkipWithError(state, mVibrator->getSupportedAlwaysOnEffects(&supportedEffects))) {
@@ -579,8 +287,8 @@
     }
 });
 
-BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedPrimitives, {
-    std::vector<Aidl::CompositePrimitive> supportedPrimitives;
+BENCHMARK_WRAPPER(VibratorBench, getSupportedPrimitives, {
+    std::vector<CompositePrimitive> supportedPrimitives;
 
     for (auto _ : state) {
         if (shouldSkipWithError(state, mVibrator->getSupportedPrimitives(&supportedPrimitives))) {
@@ -589,12 +297,12 @@
     }
 });
 
-class VibratorEffectsBench_Aidl : public VibratorBench_Aidl {
+class EffectsVibratorBench : public VibratorBench {
   public:
     static void DefaultArgs(Benchmark* b) {
         b->ArgNames({"Effect", "Strength"});
-        for (const auto& effect : enum_range<Aidl::Effect>()) {
-            for (const auto& strength : enum_range<Aidl::EffectStrength>()) {
+        for (const auto& effect : enum_range<Effect>()) {
+            for (const auto& strength : enum_range<EffectStrength>()) {
                 b->Args({static_cast<long>(effect), static_cast<long>(strength)});
             }
         }
@@ -602,36 +310,36 @@
 
   protected:
     auto getEffect(const State& state) const {
-        return static_cast<Aidl::Effect>(this->getOtherArg(state, 0));
+        return static_cast<Effect>(this->getOtherArg(state, 0));
     }
 
     auto getStrength(const State& state) const {
-        return static_cast<Aidl::EffectStrength>(this->getOtherArg(state, 1));
+        return static_cast<EffectStrength>(this->getOtherArg(state, 1));
     }
 
-    bool isEffectSupported(const Aidl::Effect& effect) {
-        std::vector<Aidl::Effect> supported;
+    bool isEffectSupported(const Effect& effect) {
+        std::vector<Effect> supported;
         mVibrator->getSupportedEffects(&supported);
         return std::find(supported.begin(), supported.end(), effect) != supported.end();
     }
 
-    bool isAlwaysOnEffectSupported(const Aidl::Effect& effect) {
-        std::vector<Aidl::Effect> supported;
+    bool isAlwaysOnEffectSupported(const Effect& effect) {
+        std::vector<Effect> supported;
         mVibrator->getSupportedAlwaysOnEffects(&supported);
         return std::find(supported.begin(), supported.end(), effect) != supported.end();
     }
 };
 
-class SlowVibratorEffectsBench_Aidl : public VibratorEffectsBench_Aidl {
+class SlowEffectsVibratorBench : public EffectsVibratorBench {
   public:
     static void DefaultConfig(Benchmark* b) {
-        VibratorEffectsBench_Aidl::DefaultConfig(b);
+        EffectsVibratorBench::DefaultConfig(b);
         SlowBenchConfig(b);
     }
 };
 
-BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnEnable, {
-    if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) {
+BENCHMARK_WRAPPER(EffectsVibratorBench, alwaysOnEnable, {
+    if (!hasCapabilities(IVibrator::CAP_ALWAYS_ON_CONTROL)) {
         state.SkipWithMessage("always on control unavailable");
         return;
     }
@@ -660,8 +368,8 @@
     }
 });
 
-BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnDisable, {
-    if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) {
+BENCHMARK_WRAPPER(EffectsVibratorBench, alwaysOnDisable, {
+    if (!hasCapabilities(IVibrator::CAP_ALWAYS_ON_CONTROL)) {
         state.SkipWithMessage("always on control unavailable");
         return;
     }
@@ -690,7 +398,7 @@
     }
 });
 
-BENCHMARK_WRAPPER(SlowVibratorEffectsBench_Aidl, perform, {
+BENCHMARK_WRAPPER(SlowEffectsVibratorBench, perform, {
     auto effect = getEffect(state);
     auto strength = getStrength(state);
 
@@ -702,7 +410,7 @@
     int32_t lengthMs = 0;
 
     for (auto _ : state) {
-        auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK)
+        auto cb = hasCapabilities(IVibrator::CAP_PERFORM_CALLBACK)
                           ? ndk::SharedRefBase::make<HalCallback>()
                           : nullptr;
         // Grab the future before callback promise is destroyed by the HAL.
@@ -723,36 +431,36 @@
     }
 });
 
-class VibratorPrimitivesBench_Aidl : public VibratorBench_Aidl {
+class PrimitivesVibratorBench : public VibratorBench {
   public:
     static void DefaultArgs(Benchmark* b) {
         b->ArgNames({"Primitive"});
-        for (const auto& primitive : enum_range<Aidl::CompositePrimitive>()) {
+        for (const auto& primitive : enum_range<CompositePrimitive>()) {
             b->Args({static_cast<long>(primitive)});
         }
     }
 
   protected:
     auto getPrimitive(const State& state) const {
-        return static_cast<Aidl::CompositePrimitive>(this->getOtherArg(state, 0));
+        return static_cast<CompositePrimitive>(this->getOtherArg(state, 0));
     }
 
-    bool isPrimitiveSupported(const Aidl::CompositePrimitive& primitive) {
-        std::vector<Aidl::CompositePrimitive> supported;
+    bool isPrimitiveSupported(const CompositePrimitive& primitive) {
+        std::vector<CompositePrimitive> supported;
         mVibrator->getSupportedPrimitives(&supported);
         return std::find(supported.begin(), supported.end(), primitive) != supported.end();
     }
 };
 
-class SlowVibratorPrimitivesBench_Aidl : public VibratorPrimitivesBench_Aidl {
+class SlowPrimitivesVibratorBench : public PrimitivesVibratorBench {
   public:
     static void DefaultConfig(Benchmark* b) {
-        VibratorPrimitivesBench_Aidl::DefaultConfig(b);
-        SlowBenchConfig(b);
+      PrimitivesVibratorBench::DefaultConfig(b);
+      SlowBenchConfig(b);
     }
 };
 
-BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionDelayMax, {
+BENCHMARK_WRAPPER(PrimitivesVibratorBench, getCompositionDelayMax, {
     int32_t ms = 0;
 
     for (auto _ : state) {
@@ -762,7 +470,7 @@
     }
 });
 
-BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionSizeMax, {
+BENCHMARK_WRAPPER(PrimitivesVibratorBench, getCompositionSizeMax, {
     int32_t size = 0;
 
     for (auto _ : state) {
@@ -772,8 +480,8 @@
     }
 });
 
-BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, getPrimitiveDuration, {
-    if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) {
+BENCHMARK_WRAPPER(PrimitivesVibratorBench, getPrimitiveDuration, {
+    if (!hasCapabilities(IVibrator::CAP_COMPOSE_EFFECTS)) {
         state.SkipWithMessage("compose effects unavailable");
         return;
     }
@@ -793,18 +501,18 @@
     }
 });
 
-BENCHMARK_WRAPPER(SlowVibratorPrimitivesBench_Aidl, compose, {
-    if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) {
+BENCHMARK_WRAPPER(SlowPrimitivesVibratorBench, compose, {
+    if (!hasCapabilities(IVibrator::CAP_COMPOSE_EFFECTS)) {
         state.SkipWithMessage("compose effects unavailable");
         return;
     }
 
-    Aidl::CompositeEffect effect;
+    CompositeEffect effect;
     effect.primitive = getPrimitive(state);
     effect.scale = 1.0f;
     effect.delayMs = 0;
 
-    if (effect.primitive == Aidl::CompositePrimitive::NOOP) {
+    if (effect.primitive == CompositePrimitive::NOOP) {
         state.SkipWithMessage("skipping primitive NOOP");
         return;
     }
@@ -813,7 +521,7 @@
         return;
     }
 
-    std::vector<Aidl::CompositeEffect> effects;
+    std::vector<CompositeEffect> effects;
     effects.push_back(effect);
 
     for (auto _ : state) {
diff --git a/virtualization/capabilities_service/default/Android.bp b/virtualization/capabilities_service/default/Android.bp
new file mode 100644
index 0000000..08f9136
--- /dev/null
+++ b/virtualization/capabilities_service/default/Android.bp
@@ -0,0 +1,35 @@
+package {
+    default_team: "trendy_team_virtualization",
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_binary {
+    name: "android.hardware.virtualization.capabilities.capabilities_service-default",
+    relative_install_path: "hw",
+    vendor: true,
+    installable: true,
+    prefer_rlib: true,
+    rustlibs: [
+        "android.hardware.virtualization.capabilities.capabilities_service-V1-rust",
+        "libanyhow",
+        "libandroid_logger",
+        "libbinder_rs",
+        "liblog_rust",
+        "liblibc",
+    ],
+    srcs: [
+        "src/main.rs",
+    ],
+    init_rc: [
+        "android.hardware.virtualization.capabilities.vm_capabilities_service.rc",
+    ],
+    vintf_fragment_modules: [
+        "android.hardware.virtualization.capabilities.vm_capabilities_service.xml",
+    ],
+}
+
+vintf_fragment {
+    name: "android.hardware.virtualization.capabilities.vm_capabilities_service.xml",
+    src: "android.hardware.virtualization.capabilities.vm_capabilities_service.xml",
+    vendor: true,
+}
diff --git a/virtualization/capabilities_service/default/android.hardware.virtualization.capabilities.vm_capabilities_service.rc b/virtualization/capabilities_service/default/android.hardware.virtualization.capabilities.vm_capabilities_service.rc
new file mode 100644
index 0000000..854e34f
--- /dev/null
+++ b/virtualization/capabilities_service/default/android.hardware.virtualization.capabilities.vm_capabilities_service.rc
@@ -0,0 +1,6 @@
+service vendor.vm_capabilities_service /vendor/bin/hw/android.hardware.virtualization.capabilities.capabilities_service-default
+  interface aidl android.hardware.virtualization.capabilities.IVmCapabilitiesService/default
+  class hal
+  # This HAL needs to talk to a kernel driver, hence it runs as root
+  user root
+  group root
diff --git a/virtualization/capabilities_service/default/android.hardware.virtualization.capabilities.vm_capabilities_service.xml b/virtualization/capabilities_service/default/android.hardware.virtualization.capabilities.vm_capabilities_service.xml
new file mode 100644
index 0000000..f02469c
--- /dev/null
+++ b/virtualization/capabilities_service/default/android.hardware.virtualization.capabilities.vm_capabilities_service.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.virtualization.capabilities</name>
+        <version>1</version>
+        <interface>
+            <name>IVmCapabilitiesService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/virtualization/capabilities_service/default/src/aidl.rs b/virtualization/capabilities_service/default/src/aidl.rs
new file mode 100644
index 0000000..d70b57b
--- /dev/null
+++ b/virtualization/capabilities_service/default/src/aidl.rs
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2025 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.
+ */
+
+//! Default implementation of the IVmCapabilitiesService AIDL interface.
+
+use android_hardware_virtualization_capabilities_capabilities_service::aidl::android::hardware::virtualization::capabilities::IVmCapabilitiesService::IVmCapabilitiesService;
+use binder::{Interface, ParcelFileDescriptor};
+use log::info;
+
+/// Default implementation of IVmCapabilitiesService
+pub struct VmCapabilitiesService {}
+
+impl VmCapabilitiesService {
+    pub fn init() -> VmCapabilitiesService {
+        let service = VmCapabilitiesService {};
+        service
+    }
+}
+
+impl Interface for VmCapabilitiesService {}
+
+impl IVmCapabilitiesService for VmCapabilitiesService {
+
+    fn grantAccessToVendorTeeServices(&self, vm_fd: &ParcelFileDescriptor, tee_services: &[String]) -> binder::Result<()> {
+        info!("received {vm_fd:?} {tee_services:?}");
+        // TODO(b/360102915): implement
+        Ok(())
+    }
+}
diff --git a/virtualization/capabilities_service/default/src/main.rs b/virtualization/capabilities_service/default/src/main.rs
new file mode 100644
index 0000000..bede4e3
--- /dev/null
+++ b/virtualization/capabilities_service/default/src/main.rs
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2025 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.
+ */
+
+//! Default implementation of the IVmCapabilitiesService.
+
+mod aidl;
+
+use crate::aidl::VmCapabilitiesService;
+use anyhow::{bail, Context, Result};
+use log::{error, info, LevelFilter};
+use binder::{register_lazy_service, BinderFeatures, ProcessState};
+use android_hardware_virtualization_capabilities_capabilities_service::aidl::android::hardware::virtualization::capabilities::IVmCapabilitiesService::BnVmCapabilitiesService;
+
+const SERVICE_NAME: &str = "android.hardware.virtualization.capabilities.IVmCapabilitiesService/default";
+
+fn try_main() -> Result<()> {
+    // Initialize Android logging.
+    android_logger::init_once(
+        android_logger::Config::default()
+            .with_tag("IVmCapabilitiesService")
+            .with_max_level(LevelFilter::Info)
+            .with_log_buffer(android_logger::LogId::System),
+    );
+
+    ProcessState::start_thread_pool();
+    let service_impl = VmCapabilitiesService::init();
+    let service = BnVmCapabilitiesService::new_binder(service_impl, BinderFeatures::default());
+    register_lazy_service(SERVICE_NAME, service.as_binder())
+        .with_context(|| format!("failed to register {SERVICE_NAME}"))?;
+    info!("Registered Binder service, joining threadpool.");
+    ProcessState::join_thread_pool();
+    bail!("thread pool unexpectedly ended");
+}
+
+fn main() {
+    if let Err(e) = try_main() {
+        error!("failed with {e:?}");
+        std::process::exit(1);
+    }
+}