Merge "example AIDL HAL extension"
diff --git a/tests/extension/vibrator/aidl/Android.bp b/tests/extension/vibrator/aidl/Android.bp
new file mode 100644
index 0000000..ef9b39b
--- /dev/null
+++ b/tests/extension/vibrator/aidl/Android.bp
@@ -0,0 +1,29 @@
+aidl_interface {
+    // This is an example test interface showing how to add functionality
+    // with setExtension/getExtension
+    name: "test-vintf-vibrator-ext",
+    vendor_available: true,
+    srcs: [
+        // Using android.hardware as the package because this is in
+        // hardware/interfaces. For custom interfaces, normally you
+        // would use a different package.
+        "android/hardware/tests/extension/vibrator/Directionality.aidl",
+        "android/hardware/tests/extension/vibrator/ICustomVibrator.aidl",
+        "android/hardware/tests/extension/vibrator/VendorEffect.aidl",
+    ],
+
+    // This is agreeing to keep the interface stable.
+    stability: "vintf",
+
+    // This happens to use types from a core interface, so we import it, but
+    // this won't always be needed.
+    imports: [
+        "vintf-vibrator",
+    ],
+
+    backend: {
+        java: {
+            enabled: false,
+        },
+    },
+}
diff --git a/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/Directionality.aidl b/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/Directionality.aidl
new file mode 100644
index 0000000..72bfd66
--- /dev/null
+++ b/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/Directionality.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+package android.hardware.tests.extension.vibrator;
+
+/**
+ * Can add custom enums. If these need to be extended further, new values can
+ * simply be added.
+ */
+@Backing(type="int")
+@VintfStability
+enum Directionality {
+    NONE,
+    /** vibrations should be transverse wrt primary screen */
+    TRANSVERSE,
+    /** vibrations should be longitudinal wrt primary screen */
+    LONGITUDINAL,
+}
diff --git a/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl b/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl
new file mode 100644
index 0000000..0b21f46
--- /dev/null
+++ b/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package android.hardware.tests.extension.vibrator;
+
+// it's fine to use types from other interfaces
+import android.hardware.vibrator.IVibratorCallback;
+import android.hardware.tests.extension.vibrator.Directionality;
+import android.hardware.tests.extension.vibrator.VendorEffect;
+
+/**
+ * This is an example of an AIDL interface extension. Notice that it does not
+ * inherit from any other extension. Instead, it will be tagged onto that
+ * extension at runtime.
+ */
+@VintfStability
+interface ICustomVibrator {
+    /**
+     * Avoid conflicting with vendor properties. Giving this as an example
+     * because the core vibrator interface uses capabilities. In reality,
+     * since this is only one capability, it's probably not needed to construct
+     * a bitfield.
+     *
+     * This is for longitudinal/transverse waves, see setDirectionality.
+     */
+    const int CAP_VENDOR_DIRECTIONALITY = 1 << 0;
+
+    /**
+     * Any new methods can be added, this returns CAP_VENDOR_*.
+     */
+    int getVendorCapabilities();
+
+    /**
+     * Arbitrary new functionality can be added.
+     */
+    void setDirectionality(Directionality directionality);
+
+    /**
+     * Perform a custom vendor effect. Note, this is a separate effect enum to
+     * avoid conflicting with core types.
+     */
+    int perform(VendorEffect effect, IVibratorCallback callback);
+}
diff --git a/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/VendorEffect.aidl b/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/VendorEffect.aidl
new file mode 100644
index 0000000..968532c
--- /dev/null
+++ b/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/VendorEffect.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+package android.hardware.tests.extension.vibrator;
+
+/**
+ * Extending enum separately to avoid conflicts w/ upstream.
+ */
+@Backing(type="int")
+@VintfStability
+enum VendorEffect {
+    CRACKLE,
+    WIGGLE,
+}
diff --git a/tests/extension/vibrator/aidl/client/Android.bp b/tests/extension/vibrator/aidl/client/Android.bp
new file mode 100644
index 0000000..f7b71f7
--- /dev/null
+++ b/tests/extension/vibrator/aidl/client/Android.bp
@@ -0,0 +1,26 @@
+
+// This example client is written as a test, but it is executing from a system
+// context. All this code would look the same if it was running in system
+// server for example.
+
+cc_test {
+    name: "test-vintf-vibrator-ext-client",
+    srcs: [
+         // system code has the option to use the unstable C++ libbinder API
+         // or the NDK one. For maximum code portability, using the ndk client
+         // makes the most sense, but both are provided here as an example.
+         "test-cpp-client.cpp",
+         "test-ndk-client.cpp",
+    ],
+    shared_libs: [
+         "libbinder",
+         "libutils",
+         "vintf-vibrator-cpp",
+         "test-vintf-vibrator-ext-cpp",
+
+         "libbinder_ndk",
+         "vintf-vibrator-ndk_platform",
+         "test-vintf-vibrator-ext-ndk_platform",
+    ],
+}
+
diff --git a/tests/extension/vibrator/aidl/client/test-cpp-client.cpp b/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
new file mode 100644
index 0000000..f6f5537
--- /dev/null
+++ b/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/tests/extension/vibrator/ICustomVibrator.h>
+#include <android/hardware/vibrator/IVibrator.h>
+#include <binder/IInterface.h>
+#include <binder/IServiceManager.h>
+#include <gtest/gtest.h>
+
+using android::IBinder;
+using android::IInterface;
+using android::interface_cast;
+using android::OK;
+using android::sp;
+using android::waitForVintfService;
+using android::hardware::tests::extension::vibrator::Directionality;
+using android::hardware::tests::extension::vibrator::ICustomVibrator;
+using android::hardware::vibrator::IVibrator;
+
+TEST(Cpp, CallRootMethod) {
+    sp<IVibrator> vib = waitForVintfService<IVibrator>();
+    ASSERT_NE(nullptr, vib.get());
+    ASSERT_TRUE(vib->off().isOk());
+}
+
+TEST(Cpp, CallExtMethod) {
+    // normally you would want to cache this
+    sp<IVibrator> vib = waitForVintfService<IVibrator>();
+    ASSERT_NE(nullptr, vib.get());
+
+    // getting the extension
+    sp<IBinder> ext;
+    ASSERT_EQ(OK, IInterface::asBinder(vib)->getExtension(&ext));
+    sp<ICustomVibrator> cvib = interface_cast<ICustomVibrator>(ext);
+    ASSERT_NE(nullptr, cvib.get());
+
+    // calling extension method
+    ASSERT_TRUE(cvib->setDirectionality(Directionality::TRANSVERSE).isOk());
+}
diff --git a/tests/extension/vibrator/aidl/client/test-ndk-client.cpp b/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
new file mode 100644
index 0000000..c846495
--- /dev/null
+++ b/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/tests/extension/vibrator/ICustomVibrator.h>
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+#include <android/binder_manager.h>
+
+#include <gtest/gtest.h>
+
+using aidl::android::hardware::tests::extension::vibrator::Directionality;
+using aidl::android::hardware::tests::extension::vibrator::ICustomVibrator;
+using aidl::android::hardware::vibrator::IVibrator;
+using ndk::SpAIBinder;
+
+static const std::string kInstance = std::string() + IVibrator::descriptor + "/default";
+
+TEST(Ndk, CallRootMethod) {
+    SpAIBinder vibBinder = SpAIBinder(AServiceManager_getService(kInstance.c_str()));
+    ASSERT_NE(nullptr, vibBinder.get());
+    std::shared_ptr<IVibrator> vib = IVibrator::fromBinder(vibBinder);
+    ASSERT_NE(nullptr, vib.get());
+    ASSERT_TRUE(vib->off().isOk());
+}
+
+TEST(Ndk, CallExtMethod) {
+    // normally you would want to cache this
+    //
+    SpAIBinder vibBinder = SpAIBinder(AServiceManager_getService(kInstance.c_str()));
+    ASSERT_NE(nullptr, vibBinder.get());
+    std::shared_ptr<IVibrator> vib = IVibrator::fromBinder(vibBinder);
+    ASSERT_NE(nullptr, vib.get());
+
+    // getting the extension
+    SpAIBinder cvibBinder;
+    ASSERT_EQ(STATUS_OK, AIBinder_getExtension(vibBinder.get(), cvibBinder.getR()));
+    ASSERT_NE(nullptr, cvibBinder.get());
+    std::shared_ptr<ICustomVibrator> cvib = ICustomVibrator::fromBinder(cvibBinder);
+    ASSERT_NE(nullptr, cvib.get());
+
+    // calling extension method
+    ASSERT_TRUE(cvib->setDirectionality(Directionality::TRANSVERSE).isOk());
+}
diff --git a/tests/extension/vibrator/aidl/default/Android.bp b/tests/extension/vibrator/aidl/default/Android.bp
new file mode 100644
index 0000000..9869657
--- /dev/null
+++ b/tests/extension/vibrator/aidl/default/Android.bp
@@ -0,0 +1,25 @@
+cc_binary {
+    name: "android.hardware.tests.extension.vibrator-service.example",
+    relative_install_path: "hw",
+    // normally you implement a service directly, but we are using an implementation
+    // from a library to attach our extension to.
+    static_libs: [
+        "libvibratorexampleimpl",
+    ],
+
+    // need to add this in the manifest and to init as well to use, see
+    // android.hardware.vibrator-service.example. This binary is being tested
+    // by running it manually as root.
+
+    vendor: true,
+    srcs: [
+        "service.cpp",
+        "CustomVibrator.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "vintf-vibrator-ndk_platform",
+        "test-vintf-vibrator-ext-ndk_platform",
+    ],
+}
diff --git a/tests/extension/vibrator/aidl/default/CustomVibrator.cpp b/tests/extension/vibrator/aidl/default/CustomVibrator.cpp
new file mode 100644
index 0000000..2f3dfcb
--- /dev/null
+++ b/tests/extension/vibrator/aidl/default/CustomVibrator.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CustomVibrator.h"
+
+#include <android-base/logging.h>
+#include <thread>
+
+namespace aidl::android::hardware::tests::extension::vibrator {
+
+ndk::ScopedAStatus CustomVibrator::getVendorCapabilities(int32_t* _aidl_return) {
+    *_aidl_return = ICustomVibrator::CAP_VENDOR_DIRECTIONALITY;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus CustomVibrator::setDirectionality(Directionality directionality) {
+    LOG(INFO) << "Custom vibrator set directionality";
+    // do something cool in hardware
+    (void)directionality;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus CustomVibrator::perform(VendorEffect effect,
+                                           const std::shared_ptr<IVibratorCallback>& callback,
+                                           int32_t* _aidl_return) {
+    LOG(INFO) << "Custom vibrator perform";
+
+    if (effect != VendorEffect::CRACKLE && effect != VendorEffect::WIGGLE) {
+        return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+    }
+
+    constexpr size_t kEffectMillis = 100;
+
+    if (callback != nullptr) {
+        std::thread([=] {
+            LOG(INFO) << "Starting vendor perform on another thread";
+            usleep(kEffectMillis * 1000);
+            LOG(INFO) << "Notifying vendor perform complete";
+            callback->onComplete();
+        }).detach();
+    }
+
+    *_aidl_return = kEffectMillis;
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::tests::extension::vibrator
diff --git a/tests/extension/vibrator/aidl/default/CustomVibrator.h b/tests/extension/vibrator/aidl/default/CustomVibrator.h
new file mode 100644
index 0000000..6dc5743
--- /dev/null
+++ b/tests/extension/vibrator/aidl/default/CustomVibrator.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tests/extension/vibrator/BnCustomVibrator.h>
+#include <aidl/android/hardware/vibrator/IVibratorCallback.h>
+
+namespace aidl::android::hardware::tests::extension::vibrator {
+
+using aidl::android::hardware::vibrator::IVibratorCallback;
+
+class CustomVibrator : public BnCustomVibrator {
+    ndk::ScopedAStatus getVendorCapabilities(int32_t* _aidl_return) override;
+    ndk::ScopedAStatus setDirectionality(Directionality directionality) override;
+    ndk::ScopedAStatus perform(VendorEffect effect,
+                               const std::shared_ptr<IVibratorCallback>& callback,
+                               int32_t* _aidl_return) override;
+};
+
+}  // namespace aidl::android::hardware::tests::extension::vibrator
diff --git a/tests/extension/vibrator/aidl/default/service.cpp b/tests/extension/vibrator/aidl/default/service.cpp
new file mode 100644
index 0000000..16290df
--- /dev/null
+++ b/tests/extension/vibrator/aidl/default/service.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vibrator-impl/Vibrator.h>
+#include "CustomVibrator.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::tests::extension::vibrator::CustomVibrator;
+using aidl::android::hardware::vibrator::Vibrator;
+
+int main() {
+    // these are threads in addition to the one we are joining below, so this
+    // service will have a single thread
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+    // making the core service
+    std::shared_ptr<Vibrator> vib = ndk::SharedRefBase::make<Vibrator>();
+    ndk::SpAIBinder vibBinder = vib->asBinder();
+
+    // making the extension service
+    std::shared_ptr<CustomVibrator> cvib = ndk::SharedRefBase::make<CustomVibrator>();
+
+    // need to attach the extension to the same binder we will be registering
+    CHECK(STATUS_OK == AIBinder_setExtension(vibBinder.get(), cvib->asBinder().get()));
+
+    const std::string instance = std::string() + Vibrator::descriptor + "/default";
+    CHECK(STATUS_OK == AServiceManager_addService(vibBinder.get(), instance.c_str()));
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reach
+}
diff --git a/vibrator/aidl/default/Android.bp b/vibrator/aidl/default/Android.bp
index f399887..dc8867f 100644
--- a/vibrator/aidl/default/Android.bp
+++ b/vibrator/aidl/default/Android.bp
@@ -1,3 +1,19 @@
+cc_library_static {
+    name: "libvibratorexampleimpl",
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "vintf-vibrator-ndk_platform",
+    ],
+    export_include_dirs: ["include"],
+    srcs: ["Vibrator.cpp"],
+    visibility: [
+         ":__subpackages__",
+         "//hardware/interfaces/tests/extension/vibrator:__subpackages__",
+    ],
+}
+
 cc_binary {
     name: "android.hardware.vibrator-service.example",
     relative_install_path: "hw",
@@ -9,5 +25,8 @@
         "libbinder_ndk",
         "vintf-vibrator-ndk_platform",
     ],
-    srcs: ["main.cpp", "Vibrator.cpp"],
+    static_libs: [
+        "libvibratorexampleimpl",
+    ],
+    srcs: ["main.cpp"],
 }
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index 18be1a6..09cd234 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "Vibrator.h"
+#include "vibrator-impl/Vibrator.h"
 
 #include <android-base/logging.h>
 #include <thread>
diff --git a/vibrator/aidl/default/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
similarity index 100%
rename from vibrator/aidl/default/Vibrator.h
rename to vibrator/aidl/default/include/vibrator-impl/Vibrator.h
diff --git a/vibrator/aidl/default/main.cpp b/vibrator/aidl/default/main.cpp
index d1619ff..ebb0905 100644
--- a/vibrator/aidl/default/main.cpp
+++ b/vibrator/aidl/default/main.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "Vibrator.h"
+#include "vibrator-impl/Vibrator.h"
 
 #include <android-base/logging.h>
 #include <android/binder_manager.h>