vibrator: add CAP_EXTERNAL_AMPLITUDE_CONTROL

For HIDL, vibrator may change the value of supportsAmplitudeControl
based on context. Since the interface is being redone in AIDL, we're
avoiding this changing value and providing capabilities for amplitudes
we expect to be available in different states.

Bug: 141828236
Test: VtsHalVibratorTargetTest
Change-Id: Idf0b28ffe5b1175469d32e790b10b4232482dc2b
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,