Merge "Create loader for Power HAL services"
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index 402767a..64bfdf9 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -37,10 +37,16 @@
     defaults: ["idlcli-defaults"],
     srcs: [
         "CommandVibrator.cpp",
+        "vibrator/CommandAlwaysOnDisable.cpp",
+        "vibrator/CommandAlwaysOnEnable.cpp",
         "vibrator/CommandCompose.cpp",
         "vibrator/CommandGetCapabilities.cpp",
         "vibrator/CommandGetCompositionDelayMax.cpp",
         "vibrator/CommandGetCompositionSizeMax.cpp",
+        "vibrator/CommandGetPrimitiveDuration.cpp",
+        "vibrator/CommandGetSupportedAlwaysOnEffects.cpp",
+        "vibrator/CommandGetSupportedEffects.cpp",
+        "vibrator/CommandGetSupportedPrimitives.cpp",
         "vibrator/CommandOff.cpp",
         "vibrator/CommandOn.cpp",
         "vibrator/CommandPerform.cpp",
diff --git a/cmds/idlcli/utils.h b/cmds/idlcli/utils.h
index a8e5954..b874455 100644
--- a/cmds/idlcli/utils.h
+++ b/cmds/idlcli/utils.h
@@ -17,6 +17,7 @@
 #ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
 #define FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
 
+#include <android/binder_enums.h>
 #include <hidl/HidlSupport.h>
 
 #include <iomanip>
@@ -66,7 +67,7 @@
 
 } // namespace overrides
 
-template <typename T, typename R = hardware::hidl_enum_range<T>>
+template <typename T, typename R = ndk::enum_range<T>>
 inline std::istream &operator>>(std::istream &stream, T &out) {
     using overrides::operator>>;
     auto validRange = R();
diff --git a/cmds/idlcli/vibrator.h b/cmds/idlcli/vibrator.h
index ca5142d..6c30a9e 100644
--- a/cmds/idlcli/vibrator.h
+++ b/cmds/idlcli/vibrator.h
@@ -16,8 +16,12 @@
 #ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
 #define FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
 
+#include <future>
+
+#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
 #include <aidl/android/hardware/vibrator/IVibrator.h>
 #include <android/binder_manager.h>
+#include <android/binder_process.h>
 #include <android/hardware/vibrator/1.3/IVibrator.h>
 
 #include "utils.h"
@@ -101,6 +105,18 @@
 namespace V1_3 = ::android::hardware::vibrator::V1_3;
 namespace aidl = ::aidl::android::hardware::vibrator;
 
+class VibratorCallback : public aidl::BnVibratorCallback {
+public:
+    ndk::ScopedAStatus onComplete() override {
+        mPromise.set_value();
+        return ndk::ScopedAStatus::ok();
+    }
+    void waitForComplete() { mPromise.get_future().wait(); }
+
+private:
+    std::promise<void> mPromise;
+};
+
 } // namespace vibrator
 } // namespace idlcli
 
diff --git a/cmds/idlcli/vibrator/CommandAlwaysOnDisable.cpp b/cmds/idlcli/vibrator/CommandAlwaysOnDisable.cpp
new file mode 100644
index 0000000..9afa300
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandAlwaysOnDisable.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandAlwaysOnDisable : public Command {
+    std::string getDescription() const override { return "Disarm always-on haptic source."; }
+
+    std::string getUsageSummary() const override { return "<id>"; }
+
+    UsageDetails getUsageDetails() const override {
+        UsageDetails details{
+                {"<id>", {"Source ID (device-specific)."}},
+        };
+        return details;
+    }
+
+    Status doArgs(Args &args) override {
+        if (auto id = args.pop<decltype(mId)>()) {
+            mId = *id;
+            std::cout << "Source ID: " << mId << std::endl;
+        } else {
+            std::cerr << "Missing or Invalid Source ID!" << std::endl;
+            return USAGE;
+        }
+        if (!args.empty()) {
+            std::cerr << "Unexpected Arguments!" << std::endl;
+            return USAGE;
+        }
+        return OK;
+    }
+
+    Status doMain(Args && /*args*/) override {
+        std::string statusStr;
+        Status ret;
+
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::alwaysOnDisable, mId);
+
+            statusStr = status.getDescription();
+            ret = status.isOk() ? OK : ERROR;
+        } else {
+            return UNAVAILABLE;
+        }
+
+        std::cout << "Status: " << statusStr << std::endl;
+
+        return ret;
+    }
+
+    int32_t mId;
+};
+
+static const auto Command =
+        CommandRegistry<CommandVibrator>::Register<CommandAlwaysOnDisable>("alwaysOnDisable");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandAlwaysOnEnable.cpp b/cmds/idlcli/vibrator/CommandAlwaysOnEnable.cpp
new file mode 100644
index 0000000..bb7f9f2
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandAlwaysOnEnable.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+using aidl::Effect;
+using aidl::EffectStrength;
+
+class CommandAlwaysOnEnable : public Command {
+    std::string getDescription() const override {
+        return "Arm always-on haptic source with an effect.";
+    }
+
+    std::string getUsageSummary() const override { return "<id> <effect> <strength>"; }
+
+    UsageDetails getUsageDetails() const override {
+        UsageDetails details{
+                {"<id>", {"Source ID (device-specific)."}},
+                {"<effect>", {"Effect ID."}},
+                {"<strength>", {"0-2."}},
+        };
+        return details;
+    }
+
+    Status doArgs(Args &args) override {
+        if (auto id = args.pop<decltype(mId)>()) {
+            mId = *id;
+            std::cout << "Source ID: " << mId << std::endl;
+        } else {
+            std::cerr << "Missing or Invalid Source ID!" << std::endl;
+            return USAGE;
+        }
+        if (auto effect = args.pop<decltype(mEffect)>()) {
+            mEffect = *effect;
+            std::cout << "Effect: " << toString(mEffect) << std::endl;
+        } else {
+            std::cerr << "Missing or Invalid Effect!" << std::endl;
+            return USAGE;
+        }
+        if (auto strength = args.pop<decltype(mStrength)>()) {
+            mStrength = *strength;
+            std::cout << "Strength: " << toString(mStrength) << std::endl;
+        } else {
+            std::cerr << "Missing or Invalid Strength!" << std::endl;
+            return USAGE;
+        }
+        if (!args.empty()) {
+            std::cerr << "Unexpected Arguments!" << std::endl;
+            return USAGE;
+        }
+        return OK;
+    }
+
+    Status doMain(Args && /*args*/) override {
+        std::string statusStr;
+        Status ret;
+
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::alwaysOnEnable, mId, mEffect, mStrength);
+
+            statusStr = status.getDescription();
+            ret = status.isOk() ? OK : ERROR;
+        } else {
+            return UNAVAILABLE;
+        }
+
+        std::cout << "Status: " << statusStr << std::endl;
+
+        return ret;
+    }
+
+    int32_t mId;
+    Effect mEffect;
+    EffectStrength mStrength;
+};
+
+static const auto Command =
+        CommandRegistry<CommandVibrator>::Register<CommandAlwaysOnEnable>("alwaysOnEnable");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandCompose.cpp b/cmds/idlcli/vibrator/CommandCompose.cpp
index 4721a5f..97c057f 100644
--- a/cmds/idlcli/vibrator/CommandCompose.cpp
+++ b/cmds/idlcli/vibrator/CommandCompose.cpp
@@ -28,10 +28,13 @@
 class CommandCompose : public Command {
     std::string getDescription() const override { return "Compose vibration."; }
 
-    std::string getUsageSummary() const override { return "<delay> <primitive> <scale> ..."; }
+    std::string getUsageSummary() const override {
+        return "[options] <delay> <primitive> <scale> ...";
+    }
 
     UsageDetails getUsageDetails() const override {
         UsageDetails details{
+                {"-b", {"Block for duration of vibration."}},
                 {"<delay>", {"In milliseconds"}},
                 {"<primitive>", {"Primitive ID."}},
                 {"<scale>", {"0.0 (exclusive) - 1.0 (inclusive)."}},
@@ -41,6 +44,17 @@
     }
 
     Status doArgs(Args &args) override {
+        while (args.get<std::string>().value_or("").find("-") == 0) {
+            auto opt = *args.pop<std::string>();
+            if (opt == "--") {
+                break;
+            } else if (opt == "-b") {
+                mBlocking = true;
+            } else {
+                std::cerr << "Invalid Option '" << opt << "'!" << std::endl;
+                return USAGE;
+            }
+        }
         while (!args.empty()) {
             CompositeEffect effect;
             if (auto delay = args.pop<decltype(effect.delayMs)>()) {
@@ -50,9 +64,8 @@
                 std::cerr << "Missing or Invalid Delay!" << std::endl;
                 return USAGE;
             }
-            // TODO: Use range validation when supported by AIDL
-            if (auto primitive = args.pop<std::underlying_type_t<decltype(effect.primitive)>>()) {
-                effect.primitive = static_cast<decltype(effect.primitive)>(*primitive);
+            if (auto primitive = args.pop<decltype(effect.primitive)>()) {
+                effect.primitive = *primitive;
                 std::cout << "Primitive: " << toString(effect.primitive) << std::endl;
             } else {
                 std::cerr << "Missing or Invalid Primitive!" << std::endl;
@@ -76,21 +89,33 @@
     }
 
     Status doMain(Args && /*args*/) override {
-        std::string statusStr;
-        Status ret;
-        if (auto hal = getHal<aidl::IVibrator>()) {
-            auto status = hal->call(&aidl::IVibrator::compose, mComposite, nullptr);
-            statusStr = status.getDescription();
-            ret = status.isOk() ? OK : ERROR;
-        } else {
+        auto hal = getHal<aidl::IVibrator>();
+
+        if (!hal) {
             return UNAVAILABLE;
         }
 
-        std::cout << "Status: " << statusStr << std::endl;
+        ABinderProcess_setThreadPoolMaxThreadCount(1);
+        ABinderProcess_startThreadPool();
 
-        return ret;
+        std::shared_ptr<VibratorCallback> callback;
+
+        if (mBlocking) {
+            callback = ndk::SharedRefBase::make<VibratorCallback>();
+        }
+
+        auto status = hal->call(&aidl::IVibrator::compose, mComposite, callback);
+
+        if (status.isOk() && callback) {
+            callback->waitForComplete();
+        }
+
+        std::cout << "Status: " << status.getDescription() << std::endl;
+
+        return status.isOk() ? OK : ERROR;
     }
 
+    bool mBlocking;
     std::vector<CompositeEffect> mComposite;
 };
 
diff --git a/cmds/idlcli/vibrator/CommandGetPrimitiveDuration.cpp b/cmds/idlcli/vibrator/CommandGetPrimitiveDuration.cpp
new file mode 100644
index 0000000..460d39e
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandGetPrimitiveDuration.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#include <future>
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+using aidl::CompositePrimitive;
+
+class CommandGetPrimitiveDuration : public Command {
+    std::string getDescription() const override {
+        return "Retrieve effect primitive's duration in milliseconds.";
+    }
+
+    std::string getUsageSummary() const override { return "<primitive>"; }
+
+    UsageDetails getUsageDetails() const override {
+        UsageDetails details{
+                {"<primitive>", {"Primitive ID."}},
+        };
+        return details;
+    }
+
+    Status doArgs(Args &args) override {
+        if (auto primitive = args.pop<decltype(mPrimitive)>()) {
+            mPrimitive = *primitive;
+            std::cout << "Primitive: " << toString(mPrimitive) << std::endl;
+        } else {
+            std::cerr << "Missing or Invalid Primitive!" << std::endl;
+            return USAGE;
+        }
+        if (!args.empty()) {
+            std::cerr << "Unexpected Arguments!" << std::endl;
+            return USAGE;
+        }
+        return OK;
+    }
+
+    Status doMain(Args && /*args*/) override {
+        std::string statusStr;
+        int32_t duration;
+        Status ret;
+
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::getPrimitiveDuration, mPrimitive, &duration);
+            statusStr = status.getDescription();
+            ret = status.isOk() ? OK : ERROR;
+        } else {
+            return UNAVAILABLE;
+        }
+
+        std::cout << "Status: " << statusStr << std::endl;
+        std::cout << "Duration: " << duration << std::endl;
+
+        return ret;
+    }
+
+    CompositePrimitive mPrimitive;
+};
+
+static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandGetPrimitiveDuration>(
+        "getPrimitiveDuration");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandGetSupportedAlwaysOnEffects.cpp b/cmds/idlcli/vibrator/CommandGetSupportedAlwaysOnEffects.cpp
new file mode 100644
index 0000000..edfcd91
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandGetSupportedAlwaysOnEffects.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+using aidl::Effect;
+
+class CommandGetSupportedAlwaysOnEffects : public Command {
+    std::string getDescription() const override { return "List of supported always-on effects."; }
+
+    std::string getUsageSummary() const override { return ""; }
+
+    UsageDetails getUsageDetails() const override {
+        UsageDetails details{};
+        return details;
+    }
+
+    Status doArgs(Args &args) override {
+        if (!args.empty()) {
+            std::cerr << "Unexpected Arguments!" << std::endl;
+            return USAGE;
+        }
+        return OK;
+    }
+
+    Status doMain(Args && /*args*/) override {
+        std::string statusStr;
+        std::vector<Effect> effects;
+        Status ret;
+
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::getSupportedAlwaysOnEffects, &effects);
+            statusStr = status.getDescription();
+            ret = status.isOk() ? OK : ERROR;
+        } else {
+            return UNAVAILABLE;
+        }
+
+        std::cout << "Status: " << statusStr << std::endl;
+        std::cout << "Effects:" << std::endl;
+        for (auto &e : effects) {
+            std::cout << "  " << toString(e) << std::endl;
+        }
+
+        return ret;
+    }
+};
+
+static const auto Command =
+        CommandRegistry<CommandVibrator>::Register<CommandGetSupportedAlwaysOnEffects>(
+                "getSupportedAlwaysOnEffects");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandGetSupportedEffects.cpp b/cmds/idlcli/vibrator/CommandGetSupportedEffects.cpp
new file mode 100644
index 0000000..7658f22
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandGetSupportedEffects.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+using aidl::Effect;
+
+class CommandGetSupportedEffects : public Command {
+    std::string getDescription() const override { return "List supported effects."; }
+
+    std::string getUsageSummary() const override { return ""; }
+
+    UsageDetails getUsageDetails() const override {
+        UsageDetails details{};
+        return details;
+    }
+
+    Status doArgs(Args &args) override {
+        if (!args.empty()) {
+            std::cerr << "Unexpected Arguments!" << std::endl;
+            return USAGE;
+        }
+        return OK;
+    }
+
+    Status doMain(Args && /*args*/) override {
+        std::string statusStr;
+        std::vector<Effect> effects;
+        Status ret;
+
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::getSupportedEffects, &effects);
+            statusStr = status.getDescription();
+            ret = status.isOk() ? OK : ERROR;
+        } else {
+            return UNAVAILABLE;
+        }
+
+        std::cout << "Status: " << statusStr << std::endl;
+        std::cout << "Effects:" << std::endl;
+        for (auto &e : effects) {
+            std::cout << "  " << toString(e) << std::endl;
+        }
+
+        return ret;
+    }
+};
+
+static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandGetSupportedEffects>(
+        "getSupportedEffects");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandGetSupportedPrimitives.cpp b/cmds/idlcli/vibrator/CommandGetSupportedPrimitives.cpp
new file mode 100644
index 0000000..d101681
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandGetSupportedPrimitives.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+using aidl::CompositePrimitive;
+
+class CommandGetSupportedPrimitives : public Command {
+    std::string getDescription() const override { return "List of supported effect primitive."; }
+
+    std::string getUsageSummary() const override { return ""; }
+
+    UsageDetails getUsageDetails() const override {
+        UsageDetails details{};
+        return details;
+    }
+
+    Status doArgs(Args &args) override {
+        if (!args.empty()) {
+            std::cerr << "Unexpected Arguments!" << std::endl;
+            return USAGE;
+        }
+        return OK;
+    }
+
+    Status doMain(Args && /*args*/) override {
+        std::string statusStr;
+        std::vector<CompositePrimitive> primitives;
+        Status ret;
+
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::getSupportedPrimitives, &primitives);
+            statusStr = status.getDescription();
+            ret = status.isOk() ? OK : ERROR;
+        } else {
+            return UNAVAILABLE;
+        }
+
+        std::cout << "Status: " << statusStr << std::endl;
+        std::cout << "Primitives:" << std::endl;
+        for (auto &e : primitives) {
+            std::cout << "  " << toString(e) << std::endl;
+        }
+
+        return ret;
+    }
+};
+
+static const auto Command =
+        CommandRegistry<CommandVibrator>::Register<CommandGetSupportedPrimitives>(
+                "getSupportedPrimitives");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandOn.cpp b/cmds/idlcli/vibrator/CommandOn.cpp
index 4e7e493..8212fc1 100644
--- a/cmds/idlcli/vibrator/CommandOn.cpp
+++ b/cmds/idlcli/vibrator/CommandOn.cpp
@@ -13,9 +13,14 @@
  * limitations under the License.
  */
 
+#include <thread>
+
 #include "utils.h"
 #include "vibrator.h"
 
+using std::chrono::milliseconds;
+using std::this_thread::sleep_for;
+
 namespace android {
 namespace idlcli {
 
@@ -26,16 +31,28 @@
 class CommandOn : public Command {
     std::string getDescription() const override { return "Turn on vibrator."; }
 
-    std::string getUsageSummary() const override { return "<duration>"; }
+    std::string getUsageSummary() const override { return "[options] <duration>"; }
 
     UsageDetails getUsageDetails() const override {
         UsageDetails details{
+                {"-b", {"Block for duration of vibration."}},
                 {"<duration>", {"In milliseconds."}},
         };
         return details;
     }
 
     Status doArgs(Args &args) override {
+        while (args.get<std::string>().value_or("").find("-") == 0) {
+            auto opt = *args.pop<std::string>();
+            if (opt == "--") {
+                break;
+            } else if (opt == "-b") {
+                mBlocking = true;
+            } else {
+                std::cerr << "Invalid Option '" << opt << "'!" << std::endl;
+                return USAGE;
+            }
+        }
         if (auto duration = args.pop<decltype(mDuration)>()) {
             mDuration = *duration;
         } else {
@@ -52,9 +69,21 @@
     Status doMain(Args && /*args*/) override {
         std::string statusStr;
         Status ret;
+        std::shared_ptr<VibratorCallback> callback;
 
         if (auto hal = getHal<aidl::IVibrator>()) {
-            auto status = hal->call(&aidl::IVibrator::on, mDuration, nullptr);
+            ABinderProcess_setThreadPoolMaxThreadCount(1);
+            ABinderProcess_startThreadPool();
+
+            int32_t cap;
+            hal->call(&aidl::IVibrator::getCapabilities, &cap);
+
+            if (mBlocking && (cap & aidl::IVibrator::CAP_ON_CALLBACK)) {
+                callback = ndk::SharedRefBase::make<VibratorCallback>();
+            }
+
+            auto status = hal->call(&aidl::IVibrator::on, mDuration, callback);
+
             statusStr = status.getDescription();
             ret = status.isOk() ? OK : ERROR;
         } else if (auto hal = getHal<V1_0::IVibrator>()) {
@@ -65,11 +94,20 @@
             return UNAVAILABLE;
         }
 
+        if (ret == OK && mBlocking) {
+            if (callback) {
+                callback->waitForComplete();
+            } else {
+                sleep_for(milliseconds(mDuration));
+            }
+        }
+
         std::cout << "Status: " << statusStr << std::endl;
 
         return ret;
     }
 
+    bool mBlocking;
     uint32_t mDuration;
 };
 
diff --git a/cmds/idlcli/vibrator/CommandPerform.cpp b/cmds/idlcli/vibrator/CommandPerform.cpp
index 69c7e37..c897686 100644
--- a/cmds/idlcli/vibrator/CommandPerform.cpp
+++ b/cmds/idlcli/vibrator/CommandPerform.cpp
@@ -13,9 +13,14 @@
  * limitations under the License.
  */
 
+#include <thread>
+
 #include "utils.h"
 #include "vibrator.h"
 
+using std::chrono::milliseconds;
+using std::this_thread::sleep_for;
+
 namespace android {
 namespace idlcli {
 
@@ -51,16 +56,17 @@
 static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) ==
               static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK));
 
-using V1_0::EffectStrength;
-using V1_3::Effect;
+using aidl::Effect;
+using aidl::EffectStrength;
 
 class CommandPerform : public Command {
     std::string getDescription() const override { return "Perform vibration effect."; }
 
-    std::string getUsageSummary() const override { return "<effect> <strength>"; }
+    std::string getUsageSummary() const override { return "[options] <effect> <strength>"; }
 
     UsageDetails getUsageDetails() const override {
         UsageDetails details{
+                {"-b", {"Block for duration of vibration."}},
                 {"<effect>", {"Effect ID."}},
                 {"<strength>", {"0-2."}},
         };
@@ -68,6 +74,17 @@
     }
 
     Status doArgs(Args &args) override {
+        while (args.get<std::string>().value_or("").find("-") == 0) {
+            auto opt = *args.pop<std::string>();
+            if (opt == "--") {
+                break;
+            } else if (opt == "-b") {
+                mBlocking = true;
+            } else {
+                std::cerr << "Invalid Option '" << opt << "'!" << std::endl;
+                return USAGE;
+            }
+        }
         if (auto effect = args.pop<decltype(mEffect)>()) {
             mEffect = *effect;
             std::cout << "Effect: " << toString(mEffect) << std::endl;
@@ -93,12 +110,23 @@
         std::string statusStr;
         uint32_t lengthMs;
         Status ret;
+        std::shared_ptr<VibratorCallback> callback;
 
         if (auto hal = getHal<aidl::IVibrator>()) {
+            ABinderProcess_setThreadPoolMaxThreadCount(1);
+            ABinderProcess_startThreadPool();
+
+            int32_t cap;
+            hal->call(&aidl::IVibrator::getCapabilities, &cap);
+
+            if (mBlocking && (cap & aidl::IVibrator::CAP_PERFORM_CALLBACK)) {
+                callback = ndk::SharedRefBase::make<VibratorCallback>();
+            }
+
             int32_t aidlLengthMs;
-            auto status =
-                    hal->call(&aidl::IVibrator::perform, static_cast<aidl::Effect>(mEffect),
-                              static_cast<aidl::EffectStrength>(mStrength), nullptr, &aidlLengthMs);
+            auto status = hal->call(&aidl::IVibrator::perform, mEffect, mStrength, callback,
+                                    &aidlLengthMs);
+
             statusStr = status.getDescription();
             lengthMs = static_cast<uint32_t>(aidlLengthMs);
             ret = status.isOk() ? OK : ERROR;
@@ -111,17 +139,20 @@
             };
 
             if (auto hal = getHal<V1_3::IVibrator>()) {
-                hidlRet = hal->call(&V1_3::IVibrator::perform_1_3,
-                                    static_cast<V1_3::Effect>(mEffect), mStrength, callback);
+                hidlRet =
+                        hal->call(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(mEffect),
+                                  static_cast<V1_0::EffectStrength>(mStrength), callback);
             } else if (auto hal = getHal<V1_2::IVibrator>()) {
-                hidlRet = hal->call(&V1_2::IVibrator::perform_1_2,
-                                    static_cast<V1_2::Effect>(mEffect), mStrength, callback);
+                hidlRet =
+                        hal->call(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(mEffect),
+                                  static_cast<V1_0::EffectStrength>(mStrength), callback);
             } else if (auto hal = getHal<V1_1::IVibrator>()) {
                 hidlRet = hal->call(&V1_1::IVibrator::perform_1_1,
-                                    static_cast<V1_1::Effect_1_1>(mEffect), mStrength, callback);
+                                    static_cast<V1_1::Effect_1_1>(mEffect),
+                                    static_cast<V1_0::EffectStrength>(mStrength), callback);
             } else if (auto hal = getHal<V1_0::IVibrator>()) {
                 hidlRet = hal->call(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(mEffect),
-                                    mStrength, callback);
+                                    static_cast<V1_0::EffectStrength>(mStrength), callback);
             } else {
                 return UNAVAILABLE;
             }
@@ -130,12 +161,21 @@
             ret = hidlRet.isOk() && status == V1_0::Status::OK ? OK : ERROR;
         }
 
+        if (ret == OK && mBlocking) {
+            if (callback) {
+                callback->waitForComplete();
+            } else {
+                sleep_for(milliseconds(lengthMs));
+            }
+        }
+
         std::cout << "Status: " << statusStr << std::endl;
         std::cout << "Length: " << lengthMs << std::endl;
 
         return ret;
     }
 
+    bool mBlocking;
     Effect mEffect;
     EffectStrength mStrength;
 };
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 9566cf6..3c04435 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -429,8 +429,17 @@
             MapPropertyToArg("dalvik.vm.dex2oat-very-large", "--very-large-app-threshold=%s");
 
 
+
+        // Decide whether to use dex2oat64.
+        bool use_dex2oat64 = false;
+        // Check whether the device even supports 64-bit ABIs.
+        if (!GetProperty("ro.product.cpu.abilist64", "").empty()) {
+          use_dex2oat64 = GetBoolProperty("dalvik.vm.dex2oat64.enabled", false);
+        }
         const char* dex2oat_bin = select_execution_binary(
-            kDex2oatPath, kDex2oatDebugPath, background_job_compile);
+            (use_dex2oat64 ? kDex2oat64Path : kDex2oat32Path),
+            (use_dex2oat64 ? kDex2oatDebug64Path : kDex2oatDebug32Path),
+            background_job_compile);
 
         bool generate_minidebug_info = kEnableMinidebugInfo &&
                 GetBoolProperty(kMinidebugInfoSystemProperty, kMinidebugInfoSystemPropertyDefault);
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index 92b13c7..d35953c 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -36,8 +36,10 @@
 
 #define ANDROID_ART_APEX_BIN "/apex/com.android.art/bin"
 // Location of binaries in the Android Runtime APEX.
-static constexpr const char* kDex2oatPath = ANDROID_ART_APEX_BIN "/dex2oat";
-static constexpr const char* kDex2oatDebugPath = ANDROID_ART_APEX_BIN "/dex2oatd";
+static constexpr const char* kDex2oat32Path = ANDROID_ART_APEX_BIN "/dex2oat32";
+static constexpr const char* kDex2oat64Path = ANDROID_ART_APEX_BIN "/dex2oat64";
+static constexpr const char* kDex2oatDebug32Path = ANDROID_ART_APEX_BIN "/dex2oatd32";
+static constexpr const char* kDex2oatDebug64Path = ANDROID_ART_APEX_BIN "/dex2oatd64";
 static constexpr const char* kProfmanPath = ANDROID_ART_APEX_BIN "/profman";
 static constexpr const char* kProfmanDebugPath = ANDROID_ART_APEX_BIN "/profmand";
 static constexpr const char* kDexoptanalyzerPath = ANDROID_ART_APEX_BIN "/dexoptanalyzer";
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 9a1888c..96f5e44 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -749,6 +749,36 @@
     EXPECT_TRUE(found_enable);
 }
 
+TEST_F(DexoptTest, DexoptDex2oat64Enabled) {
+    LOG(INFO) << "DexoptDex2oat64Enabled";
+    const std::string property = "dalvik.vm.dex2oat64.enabled";
+    const std::string previous_value = android::base::GetProperty(property, "");
+    auto restore_property = android::base::make_scope_guard([=]() {
+        android::base::SetProperty(property, previous_value);
+    });
+    std::string odex = GetPrimaryDexArtifact(app_oat_dir_.c_str(), apk_path_, "odex");
+    // Disable the property and use dex2oat32.
+    ASSERT_TRUE(android::base::SetProperty(property, "false")) << property;
+    CompilePrimaryDexOk("speed-profile",
+                        DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
+                                DEXOPT_GENERATE_APP_IMAGE,
+                        app_oat_dir_.c_str(),
+                        kTestAppGid,
+                        DEX2OAT_FROM_SCRATCH,
+                        /*binder_result=*/nullptr,
+                        empty_dm_file_.c_str());
+    // Enable the property and use dex2oat64.
+    ASSERT_TRUE(android::base::SetProperty(property, "true")) << property;
+    CompilePrimaryDexOk("speed-profile",
+                        DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
+                                DEXOPT_GENERATE_APP_IMAGE,
+                        app_oat_dir_.c_str(),
+                        kTestAppGid,
+                        DEX2OAT_FROM_SCRATCH,
+                        /*binder_result=*/nullptr,
+                        empty_dm_file_.c_str());
+}
+
 class PrimaryDexReCompilationTest : public DexoptTest {
   public:
     virtual void SetUp() {
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index e6cfeb4..7298282 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -170,6 +170,7 @@
 
 aidl_interface {
     name: "libbinder_aidl_test_stub",
+    unstable: true,
     local_include_dir: "aidl",
     srcs: [":libbinder_aidl"],
     vendor_available: true,
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index cb4b20f..5f5265c 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -92,6 +92,7 @@
 
 aidl_interface {
     name: "IBinderVendorDoubleLoadTest",
+    unstable: true,
     vendor: true,
     srcs: [
         "IBinderVendorDoubleLoadTest.aidl",
@@ -100,6 +101,7 @@
 
 aidl_interface {
     name: "IBinderNdkUnitTest",
+    unstable: true,
     srcs: [
         "IBinderNdkUnitTest.aidl",
         "IEmpty.aidl",
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index c7b7551..69fdd7c 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -137,6 +137,7 @@
 
 aidl_interface {
     name: "binderStabilityTestIface",
+    unstable: true,
     srcs: [
         "IBinderStabilityTest.aidl",
     ],
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
index c186110..5eb509c 100644
--- a/libs/binderthreadstate/Android.bp
+++ b/libs/binderthreadstate/Android.bp
@@ -39,6 +39,7 @@
 
 aidl_interface {
     name: "binderthreadstateutilstest.aidl",
+    unstable: true,
     srcs: ["IAidlStuff.aidl"],
 }