/* * Copyright (C) 2021 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 #include #include #include #include #include #include #include #include namespace aidl { namespace android { namespace hardware { namespace vibrator { class Vibrator : public BnVibrator { public: // APIs for interfacing with the kernel driver. class HwApi { public: virtual ~HwApi() = default; // Stores the LRA resonant frequency to be used for PWLE playback // and click compensation. virtual bool setF0(std::string value) = 0; // Stores the frequency offset for long vibrations. virtual bool setF0Offset(uint32_t value) = 0; // Stores the LRA series resistance to be used for click // compensation. virtual bool setRedc(std::string value) = 0; // Stores the LRA Q factor to be used for Q-dependent waveform // selection. virtual bool setQ(std::string value) = 0; // Reports the number of effect waveforms loaded in firmware. virtual bool getEffectCount(uint32_t *value) = 0; // Blocks until timeout or vibrator reaches desired state // (2 = ASP enabled, 1 = haptic enabled, 0 = disabled). virtual bool pollVibeState(uint32_t value, int32_t timeoutMs = -1) = 0; // Reports whether getOwtFreeSpace() is supported. virtual bool hasOwtFreeSpace() = 0; // Reports the available OWT bytes. virtual bool getOwtFreeSpace(uint32_t *value) = 0; // Enables/Disables F0 compensation enable status virtual bool setF0CompEnable(bool value) = 0; // Enables/Disables Redc compensation enable status virtual bool setRedcCompEnable(bool value) = 0; // Stores the minumun delay time between playback and stop effects. virtual bool setMinOnOffInterval(uint32_t value) = 0; // Gets the scaling factor for contextual haptic events. virtual uint32_t getContextScale() = 0; // Gets the enable status for contextual haptic events. virtual bool getContextEnable() = 0; // Gets the settling time for contextual haptic events. // This will allow the device to stay face up for the duration given, // even if InMotion events were detected. virtual uint32_t getContextSettlingTime() = 0; // Gets the cooldown time for contextual haptic events. // This is used to avoid changing the scale of close playback events. virtual uint32_t getContextCooldownTime() = 0; // Checks the enable status for contextual haptics fade feature. When enabled // this feature will cause the scaling factor to fade back up to max over // the setting time set, instead of instantaneously changing it back to max. virtual bool getContextFadeEnable() = 0; // Indicates the number of 0.125-dB steps of attenuation to apply to // waveforms triggered in response to vibration calls from the // Android vibrator HAL. virtual bool setFFGain(int fd, uint16_t value) = 0; // Create/modify custom effects for all physical waveforms. virtual bool setFFEffect(int fd, struct ff_effect *effect, uint16_t timeoutMs) = 0; // Activates/deactivates the effect index after setFFGain() and setFFEffect(). virtual bool setFFPlay(int fd, int8_t index, bool value) = 0; // Get the Alsa device for the audio coupled haptics effect virtual bool getHapticAlsaDevice(int *card, int *device) = 0; // Set haptics PCM amplifier before triggering audio haptics feature virtual bool setHapticPcmAmp(struct pcm **haptic_pcm, bool enable, int card, int device) = 0; // Set OWT waveform for compose or compose PWLE request virtual bool uploadOwtEffect(int fd, uint8_t *owtData, uint32_t numBytes, struct ff_effect *effect, uint32_t *outEffectIndex, int *status) = 0; // Erase OWT waveform virtual bool eraseOwtEffect(int fd, int8_t effectIndex, std::vector *effect) = 0; // Emit diagnostic information to the given file. virtual void debug(int fd) = 0; }; // APIs for obtaining calibration/configuration data from persistent memory. class HwCal { public: virtual ~HwCal() = default; // Obtain the calibration version virtual bool getVersion(uint32_t *value) = 0; // Obtains the LRA resonant frequency to be used for PWLE playback // and click compensation. virtual bool getF0(std::string *value) = 0; // Obtains the LRA series resistance to be used for click // compensation. virtual bool getRedc(std::string *value) = 0; // Obtains the LRA Q factor to be used for Q-dependent waveform // selection. virtual bool getQ(std::string *value) = 0; // Obtains frequency shift for long vibrations. virtual bool getLongFrequencyShift(int32_t *value) = 0; // Obtains the v0/v1(min/max) voltage levels to be applied for // tick/click/long in units of 1%. virtual bool getTickVolLevels(std::array *value) = 0; virtual bool getClickVolLevels(std::array *value) = 0; virtual bool getLongVolLevels(std::array *value) = 0; // Checks if the chirp feature is enabled. virtual bool isChirpEnabled() = 0; // Obtains the supported primitive effects. virtual bool getSupportedPrimitives(uint32_t *value) = 0; // Checks if the f0 compensation feature needs to be enabled. virtual bool isF0CompEnabled() = 0; // Checks if the redc compensation feature needs to be enabled. virtual bool isRedcCompEnabled() = 0; // Emit diagnostic information to the given file. virtual void debug(int fd) = 0; }; public: Vibrator(std::unique_ptr hwapi, std::unique_ptr hwcal); ndk::ScopedAStatus getCapabilities(int32_t *_aidl_return) override; ndk::ScopedAStatus off() override; ndk::ScopedAStatus on(int32_t timeoutMs, const std::shared_ptr &callback) override; ndk::ScopedAStatus perform(Effect effect, EffectStrength strength, const std::shared_ptr &callback, int32_t *_aidl_return) override; ndk::ScopedAStatus getSupportedEffects(std::vector *_aidl_return) override; ndk::ScopedAStatus setAmplitude(float amplitude) override; ndk::ScopedAStatus setExternalControl(bool enabled) override; ndk::ScopedAStatus getCompositionDelayMax(int32_t *maxDelayMs); ndk::ScopedAStatus getCompositionSizeMax(int32_t *maxSize); ndk::ScopedAStatus getSupportedPrimitives(std::vector *supported) override; ndk::ScopedAStatus getPrimitiveDuration(CompositePrimitive primitive, int32_t *durationMs) override; ndk::ScopedAStatus compose(const std::vector &composite, const std::shared_ptr &callback) override; ndk::ScopedAStatus getSupportedAlwaysOnEffects(std::vector *_aidl_return) override; ndk::ScopedAStatus alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) override; ndk::ScopedAStatus alwaysOnDisable(int32_t id) override; ndk::ScopedAStatus getResonantFrequency(float *resonantFreqHz) override; ndk::ScopedAStatus getQFactor(float *qFactor) override; ndk::ScopedAStatus getFrequencyResolution(float *freqResolutionHz) override; ndk::ScopedAStatus getFrequencyMinimum(float *freqMinimumHz) override; ndk::ScopedAStatus getBandwidthAmplitudeMap(std::vector *_aidl_return) override; ndk::ScopedAStatus getPwlePrimitiveDurationMax(int32_t *durationMs) override; ndk::ScopedAStatus getPwleCompositionSizeMax(int32_t *maxSize) override; ndk::ScopedAStatus getSupportedBraking(std::vector *supported) override; ndk::ScopedAStatus composePwle(const std::vector &composite, const std::shared_ptr &callback) override; binder_status_t dump(int fd, const char **args, uint32_t numArgs) override; private: ndk::ScopedAStatus on(uint32_t timeoutMs, uint32_t effectIndex, struct dspmem_chunk *ch, const std::shared_ptr &callback); // set 'amplitude' based on an arbitrary scale determined by 'maximum' ndk::ScopedAStatus setEffectAmplitude(float amplitude, float maximum, bool scalable); ndk::ScopedAStatus setGlobalAmplitude(bool set); // 'simple' effects are those precompiled and loaded into the controller ndk::ScopedAStatus getSimpleDetails(Effect effect, EffectStrength strength, uint32_t *outEffectIndex, uint32_t *outTimeMs, uint32_t *outVolLevel); // 'compound' effects are those composed by stringing multiple 'simple' effects ndk::ScopedAStatus getCompoundDetails(Effect effect, EffectStrength strength, uint32_t *outTimeMs, struct dspmem_chunk *outCh); ndk::ScopedAStatus getPrimitiveDetails(CompositePrimitive primitive, uint32_t *outEffectIndex); ndk::ScopedAStatus performEffect(Effect effect, EffectStrength strength, const std::shared_ptr &callback, int32_t *outTimeMs); ndk::ScopedAStatus performEffect(uint32_t effectIndex, uint32_t volLevel, struct dspmem_chunk *ch, const std::shared_ptr &callback); ndk::ScopedAStatus setPwle(const std::string &pwleQueue); bool isUnderExternalControl(); void waitForComplete(std::shared_ptr &&callback); uint32_t intensityToVolLevel(float intensity, uint32_t effectIndex); bool findHapticAlsaDevice(int *card, int *device); bool hasHapticAlsaDevice(); bool enableHapticPcmAmp(struct pcm **haptic_pcm, bool enable, int card, int device); uint16_t amplitudeToScale(float amplitude, float maximum, bool scalable); void updateContext(); std::unique_ptr mHwApi; std::unique_ptr mHwCal; uint32_t mF0Offset; std::array mTickEffectVol; std::array mClickEffectVol; std::array mLongEffectVol; std::vector mFfEffects; std::vector mEffectDurations; std::future mAsyncHandle; ::android::base::unique_fd mInputFd; int8_t mActiveId{-1}; struct pcm *mHapticPcm; int mCard; int mDevice; bool mHasHapticAlsaDevice{false}; bool mIsUnderExternalControl; float mLongEffectScale = 1.0; bool mIsChirpEnabled; uint32_t mScaleTime; bool mFadeEnable; uint32_t mScalingFactor; uint32_t mScaleCooldown; bool mContextEnable; uint32_t mSupportedPrimitivesBits = 0x0; std::vector mSupportedPrimitives; bool mConfigHapticAlsaDeviceDone{false}; }; } // namespace vibrator } // namespace hardware } // namespace android } // namespace aidl