Merge "vibrator: add CAP_EXTERNAL_AMPLITUDE_CONTROL"
am: 00fab92a7f

Change-Id: I90cb13116aa47243d39212f4d178824c3d436280
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index d21274b..ceaa0a0 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -31,16 +31,20 @@
      */
     const int CAP_PERFORM_CALLBACK = 1 << 1;
     /**
-     * Whether setAmplitude is supported.
+     * Whether setAmplitude is supported (when external control is disabled)
      */
     const int CAP_AMPLITUDE_CONTROL = 1 << 2;
     /**
      * Whether setExternalControl is supported.
      */
     const int CAP_EXTERNAL_CONTROL = 1 << 3;
+    /**
+     * Whether setAmplitude is supported (when external control is enabled)
+     */
+    const int CAP_EXTERNAL_AMPLITUDE_CONTROL = 1 << 4;
 
     /**
-     * Determine capabilities of the vibrator HAL (CAP_* values)
+     * Determine capabilities of the vibrator HAL (CAP_* mask)
      */
     int getCapabilities();
 
@@ -55,7 +59,9 @@
      * Turn on vibrator
      *
      * This function must only be called after the previous timeout has expired or
-     * was canceled (through off()).
+     * was canceled (through off()). A callback is only expected to be supported when
+     * getCapabilities CAP_ON_CALLBACK is specified.
+     *
      * @param timeoutMs number of milliseconds to vibrate.
      * @param callback A callback used to inform Frameworks of state change, if supported.
      */
@@ -64,6 +70,9 @@
     /**
      * Fire off a predefined haptic event.
      *
+     * A callback is only expected to be supported when getCapabilities CAP_PERFORM_CALLBACK
+     * is specified.
+     *
      * @param effect The type of haptic event to trigger.
      * @param strength The intensity of haptic event to trigger.
      * @param callback A callback used to inform Frameworks of state change, if supported.
@@ -84,7 +93,11 @@
     /**
      * Sets the motor's vibrational amplitude.
      *
-     * Changes the force being produced by the underlying motor.
+     * Changes the force being produced by the underlying motor. This may not be supported and
+     * this support is reflected in getCapabilities (CAP_AMPLITUDE_CONTROL). When this device
+     * is under external control (via setExternalControl), amplitude control may not be supported
+     * even though it is supported normally. This can be checked with
+     * CAP_EXTERNAL_AMPLITUDE_CONTROL.
      *
      * @param amplitude The unitless force setting. Note that this number must
      *                  be between 1 and 255, inclusive. If the motor does not
@@ -96,12 +109,14 @@
     /**
      * Enables/disables control override of vibrator to audio.
      *
+     * Support is reflected in getCapabilities (CAP_EXTERNAL_CONTROL).
+     *
      * When this API is set, the vibrator control should be ceded to audio system
      * for haptic audio. While this is enabled, issuing of other commands to control
      * the vibrator is unsupported and the resulting behavior is undefined. Amplitude
      * control may or may not be supported and is reflected in the return value of
-     * supportsAmplitudeControl() while this is enabled. When this is disabled, the
-     * vibrator should resume to an off state.
+     * getCapabilities (CAP_EXTERNAL_AMPLITUDE_CONTROL) while this is enabled. When this is
+     * disabled, the vibrator should resume to an off state.
      *
      * @param enabled Whether external control should be enabled or disabled.
      */
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index 2aec8c5..18be1a6 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -27,7 +27,8 @@
 ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
     LOG(INFO) << "Vibrator reporting capabilities";
     *_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
-                    IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL;
+                    IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL |
+                    IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL;
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index b0e6c72..aeb9b70 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -221,6 +221,25 @@
     }
 }
 
+TEST_P(VibratorAidl, ExternalAmplitudeControl) {
+    const bool supportsExternalAmplitudeControl =
+            (capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0;
+
+    if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
+        EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
+
+        Status amplitudeStatus = vibrator->setAmplitude(128);
+        if (supportsExternalAmplitudeControl) {
+            EXPECT_TRUE(amplitudeStatus.isOk());
+        } else {
+            EXPECT_EQ(amplitudeStatus.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+        }
+        EXPECT_TRUE(vibrator->setExternalControl(false).isOk());
+    } else {
+        EXPECT_FALSE(supportsExternalAmplitudeControl);
+    }
+}
+
 TEST_P(VibratorAidl, ExternalControlUnsupportedMatchingCapabilities) {
     if ((capabilities & IVibrator::CAP_EXTERNAL_CONTROL) == 0) {
         EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,