Use vibrator information to initialize HapticGenerator.
Use vibrator's resonant frequency and Q factor to initialize
HapticGenerator when they are available. Otherwise, use default value.
Bug: 182612056
Test: atest HapticGeneratorTest, manual
Change-Id: Ib861e7fbb0ede3a33c0a93fbca8d80c022461d9a
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 64a335a..19d68a0 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -348,6 +348,7 @@
"aidl/android/media/AudioUniqueIdUse.aidl",
"aidl/android/media/AudioUsage.aidl",
"aidl/android/media/AudioUuid.aidl",
+ "aidl/android/media/AudioVibratorInfo.aidl",
"aidl/android/media/EffectDescriptor.aidl",
"aidl/android/media/ExtraAudioDescriptor.aidl",
],
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index f476b7d..0bc592d 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -2258,6 +2258,15 @@
return NO_ERROR;
}
+status_t AudioSystem::setVibratorInfos(
+ const std::vector<media::AudioVibratorInfo>& vibratorInfos) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == nullptr) {
+ return PERMISSION_DENIED;
+ }
+ return af->setVibratorInfos(vibratorInfos);
+}
+
// ---------------------------------------------------------------------------
int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 4103630..0feafc5 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -733,6 +733,11 @@
return statusTFromBinderStatus(mDelegate->setAudioHalPids(pidsAidl));
}
+status_t AudioFlingerClientAdapter::setVibratorInfos(
+ const std::vector<media::AudioVibratorInfo>& vibratorInfos) {
+ return statusTFromBinderStatus(mDelegate->setVibratorInfos(vibratorInfos));
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
// AudioFlingerServerAdapter
@@ -1174,4 +1179,9 @@
return Status::ok();
}
+Status AudioFlingerServerAdapter::setVibratorInfos(
+ const std::vector<media::AudioVibratorInfo>& vibratorInfos) {
+ return Status::fromStatusT(mDelegate->setVibratorInfos(vibratorInfos));
+}
+
} // namespace android
diff --git a/media/libaudioclient/aidl/android/media/AudioVibratorInfo.aidl b/media/libaudioclient/aidl/android/media/AudioVibratorInfo.aidl
new file mode 100644
index 0000000..f88fc3c
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioVibratorInfo.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+/**
+ * {@hide}
+ * A class for vibrator information. The information will be used in HapticGenerator effect.
+ */
+parcelable AudioVibratorInfo {
+ int id;
+ float resonantFrequency;
+ float qFactor;
+}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index e63f391..abbced5 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -23,6 +23,7 @@
import android.media.AudioStreamType;
import android.media.AudioUniqueIdUse;
import android.media.AudioUuid;
+import android.media.AudioVibratorInfo;
import android.media.CreateEffectRequest;
import android.media.CreateEffectResponse;
import android.media.CreateRecordRequest;
@@ -202,4 +203,8 @@
MicrophoneInfoData[] getMicrophones();
void setAudioHalPids(in int[] /* pid_t[] */ pids);
+
+ // Set vibrators' information.
+ // The value will be used to initialize HapticGenerator.
+ void setVibratorInfos(in AudioVibratorInfo[] vibratorInfos);
}
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index c63d29f..4c99dbd 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -19,9 +19,10 @@
#include <sys/types.h>
-#include <android/media/permission/Identity.h>
+#include <android/media/AudioVibratorInfo.h>
#include <android/media/BnAudioFlingerClient.h>
#include <android/media/BnAudioPolicyServiceClient.h>
+#include <android/media/permission/Identity.h>
#include <media/AidlConversionUtil.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioPolicy.h>
@@ -553,6 +554,8 @@
static audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);
+ static status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos);
+
private:
class AudioFlingerClient: public IBinder::DeathRecipient, public media::BnAudioFlingerClient
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index efd7fed..7f7ca85 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -35,6 +35,7 @@
#include <string>
#include <vector>
+#include <android/media/AudioVibratorInfo.h>
#include <android/media/BnAudioFlingerService.h>
#include <android/media/BpAudioFlingerService.h>
#include <android/media/permission/Identity.h>
@@ -331,6 +332,11 @@
virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids) = 0;
+
+ // Set vibrators' information.
+ // The values will be used to initialize HapticGenerator.
+ virtual status_t setVibratorInfos(
+ const std::vector<media::AudioVibratorInfo>& vibratorInfos) = 0;
};
/**
@@ -422,6 +428,7 @@
size_t frameCountHAL(audio_io_handle_t ioHandle) const override;
status_t getMicrophones(std::vector<media::MicrophoneInfo>* microphones) override;
status_t setAudioHalPids(const std::vector<pid_t>& pids) override;
+ status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) override;
private:
const sp<media::IAudioFlingerService> mDelegate;
@@ -504,6 +511,7 @@
GET_MASTER_BALANCE = media::BnAudioFlingerService::TRANSACTION_getMasterBalance,
SET_EFFECT_SUSPENDED = media::BnAudioFlingerService::TRANSACTION_setEffectSuspended,
SET_AUDIO_HAL_PIDS = media::BnAudioFlingerService::TRANSACTION_setAudioHalPids,
+ SET_VIBRATOR_INFOS = media::BnAudioFlingerService::TRANSACTION_setVibratorInfos,
};
/**
@@ -605,6 +613,7 @@
Status frameCountHAL(int32_t ioHandle, int64_t* _aidl_return) override;
Status getMicrophones(std::vector<media::MicrophoneInfoData>* _aidl_return) override;
Status setAudioHalPids(const std::vector<int32_t>& pids) override;
+ Status setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) override;
private:
const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
diff --git a/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp b/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
index f2245b1..65a20a7 100644
--- a/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
+++ b/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
@@ -26,11 +26,16 @@
#include <errno.h>
#include <inttypes.h>
+#include <math.h>
#include <audio_effects/effect_hapticgenerator.h>
#include <audio_utils/format.h>
#include <system/audio.h>
+static constexpr float DEFAULT_RESONANT_FREQUENCY = 150.0f;
+static constexpr float DEFAULT_BSF_ZERO_Q = 8.0f;
+static constexpr float DEFAULT_BSF_POLE_Q = 4.0f;
+
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
@@ -101,11 +106,11 @@
context->param.audioChannelCount = 0;
context->param.maxHapticIntensity = os::HapticScale::MUTE;
- context->param.resonantFrequency = 150.0f;
+ context->param.resonantFrequency = DEFAULT_RESONANT_FREQUENCY;
context->param.bpfQ = 1.0f;
context->param.slowEnvNormalizationPower = -0.8f;
- context->param.bsfZeroQ = 8.0f;
- context->param.bsfPoleQ = 4.0f;
+ context->param.bsfZeroQ = DEFAULT_BSF_ZERO_Q;
+ context->param.bsfPoleQ = DEFAULT_BSF_POLE_Q;
context->param.distortionCornerFrequency = 300.0f;
context->param.distortionInputGain = 0.3f;
context->param.distortionCubeThreshold = 0.1f;
@@ -173,6 +178,7 @@
addBiquadFilter(processingChain, processorsRecord, lpf);
auto bpf = createBPF(param->resonantFrequency, param->bpfQ, sampleRate, channelCount);
+ processorsRecord.bpf = bpf;
addBiquadFilter(processingChain, processorsRecord, bpf);
float normalizationPower = param->slowEnvNormalizationPower;
@@ -191,6 +197,7 @@
auto bsf = createBSF(
param->resonantFrequency, param->bsfZeroQ, param->bsfPoleQ, sampleRate, channelCount);
+ processorsRecord.bsf = bsf;
addBiquadFilter(processingChain, processorsRecord, bsf);
// The process chain captures the shared pointer of the Distortion in lambda. It will
@@ -279,7 +286,32 @@
}
break;
}
+ case HG_PARAM_VIBRATOR_INFO: {
+ if (value == nullptr || size != 2 * sizeof(float)) {
+ return -EINVAL;
+ }
+ const float resonantFrequency = *(float*) value;
+ const float qFactor = *((float *) value + 1);
+ context->param.resonantFrequency =
+ isnan(resonantFrequency) ? DEFAULT_RESONANT_FREQUENCY : resonantFrequency;
+ context->param.bsfZeroQ = isnan(qFactor) ? DEFAULT_BSF_POLE_Q : qFactor;
+ context->param.bsfPoleQ = context->param.bsfZeroQ / 2.0f;
+ if (context->processorsRecord.bpf != nullptr) {
+ context->processorsRecord.bpf->setCoefficients(
+ bpfCoefs(context->param.resonantFrequency,
+ context->param.bpfQ,
+ context->config.inputCfg.samplingRate));
+ }
+ if (context->processorsRecord.bsf != nullptr) {
+ context->processorsRecord.bsf->setCoefficients(
+ bsfCoefs(context->param.resonantFrequency,
+ context->param.bsfZeroQ,
+ context->param.bsfPoleQ,
+ context->config.inputCfg.samplingRate));
+ }
+ HapticGenerator_Reset(context);
+ } break;
default:
ALOGW("Unknown param: %d", param);
return -EINVAL;
diff --git a/media/libeffects/hapticgenerator/EffectHapticGenerator.h b/media/libeffects/hapticgenerator/EffectHapticGenerator.h
index d2d7afe..96b744a 100644
--- a/media/libeffects/hapticgenerator/EffectHapticGenerator.h
+++ b/media/libeffects/hapticgenerator/EffectHapticGenerator.h
@@ -69,6 +69,11 @@
std::vector<std::shared_ptr<Ramp>> ramps;
std::vector<std::shared_ptr<SlowEnvelope>> slowEnvs;
std::vector<std::shared_ptr<Distortion>> distortions;
+
+ // Cache band-pass filter and band-stop filter for updating parameters
+ // according to vibrator info
+ std::shared_ptr<HapticBiquadFilter> bpf;
+ std::shared_ptr<HapticBiquadFilter> bsf;
};
// A structure to keep all the context for HapticGenerator.
diff --git a/media/libeffects/hapticgenerator/Processors.cpp b/media/libeffects/hapticgenerator/Processors.cpp
index 79a4e2c..4fe3a75 100644
--- a/media/libeffects/hapticgenerator/Processors.cpp
+++ b/media/libeffects/hapticgenerator/Processors.cpp
@@ -211,9 +211,9 @@
}
BiquadFilterCoefficients bsfCoefs(const float ringingFrequency,
- const float sampleRate,
const float zq,
- const float pq) {
+ const float pq,
+ const float sampleRate) {
BiquadFilterCoefficients coefficient;
const auto [zeroReal, zeroImg] = getComplexPoleZ(ringingFrequency, zq, sampleRate);
float zeroCoeff1 = -2 * zeroReal;
@@ -275,7 +275,7 @@
const float pq,
const float sampleRate,
const size_t channelCount) {
- BiquadFilterCoefficients coefficient = bsfCoefs(ringingFrequency, sampleRate, zq, pq);
+ BiquadFilterCoefficients coefficient = bsfCoefs(ringingFrequency, zq, pq, sampleRate);
return std::make_shared<HapticBiquadFilter>(channelCount, coefficient);
}
diff --git a/media/libeffects/hapticgenerator/Processors.h b/media/libeffects/hapticgenerator/Processors.h
index 452a985..74ca77d 100644
--- a/media/libeffects/hapticgenerator/Processors.h
+++ b/media/libeffects/hapticgenerator/Processors.h
@@ -102,9 +102,9 @@
const float sampleRate);
BiquadFilterCoefficients bsfCoefs(const float ringingFrequency,
- const float sampleRate,
const float zq,
- const float pq);
+ const float pq,
+ const float sampleRate);
std::shared_ptr<HapticBiquadFilter> createLPF(const float cornerFrequency,
const float sampleRate,
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 7a89805..7cdac30 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -278,6 +278,21 @@
return NO_ERROR;
}
+status_t AudioFlinger::setVibratorInfos(
+ const std::vector<media::AudioVibratorInfo>& vibratorInfos) {
+ Mutex::Autolock _l(mLock);
+ mAudioVibratorInfos = vibratorInfos;
+ return NO_ERROR;
+}
+
+// getDefaultVibratorInfo_l must be called with AudioFlinger lock held.
+const media::AudioVibratorInfo* AudioFlinger::getDefaultVibratorInfo_l() {
+ if (mAudioVibratorInfos.empty()) {
+ return nullptr;
+ }
+ return &mAudioVibratorInfos.front();
+}
+
AudioFlinger::~AudioFlinger()
{
while (!mRecordThreads.isEmpty()) {
@@ -4122,7 +4137,8 @@
case TransactionCode::SET_MIC_MUTE:
case TransactionCode::SET_LOW_RAM_DEVICE:
case TransactionCode::SYSTEM_READY:
- case TransactionCode::SET_AUDIO_HAL_PIDS: {
+ case TransactionCode::SET_AUDIO_HAL_PIDS:
+ case TransactionCode::SET_VIBRATOR_INFOS: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 1cfdffc..a980752 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -267,6 +267,8 @@
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
+ virtual status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos);
+
status_t onPreTransact(TransactionCode code, const Parcel& data, uint32_t flags) override;
// end of IAudioFlinger interface
@@ -296,6 +298,8 @@
void updateDownStreamPatches_l(const struct audio_patch *patch,
const std::set<audio_io_handle_t> streams);
+ const media::AudioVibratorInfo* getDefaultVibratorInfo_l();
+
private:
// FIXME The 400 is temporarily too high until a leak of writers in media.log is fixed.
static const size_t kLogMemorySize = 400 * 1024;
@@ -971,6 +975,8 @@
SimpleLog mAppSetParameterLog;
SimpleLog mSystemSetParameterLog;
+ std::vector<media::AudioVibratorInfo> mAudioVibratorInfos;
+
static inline constexpr const char *mMetricsId = AMEDIAMETRICS_KEY_AUDIO_FLINGER;
};
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 031e0cf..d75b13b 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1585,6 +1585,34 @@
return status;
}
+status_t AudioFlinger::EffectModule::setVibratorInfo(const media::AudioVibratorInfo* vibratorInfo)
+{
+ if (mStatus != NO_ERROR) {
+ return mStatus;
+ }
+ if (!isHapticGenerator()) {
+ ALOGW("Should not set vibrator info for effects that are not HapticGenerator");
+ return INVALID_OPERATION;
+ }
+
+ std::vector<uint8_t> request(
+ sizeof(effect_param_t) + sizeof(int32_t) + 2 * sizeof(float));
+ effect_param_t *param = (effect_param_t*) request.data();
+ param->psize = sizeof(int32_t);
+ param->vsize = 2 * sizeof(float);
+ *(int32_t*)param->data = HG_PARAM_VIBRATOR_INFO;
+ float* vibratorInfoPtr = reinterpret_cast<float*>(param->data + sizeof(int32_t));
+ vibratorInfoPtr[0] = vibratorInfo->resonantFrequency;
+ vibratorInfoPtr[1] = vibratorInfo->qFactor;
+ std::vector<uint8_t> response;
+ status_t status = command(EFFECT_CMD_SET_PARAM, request, sizeof(int32_t), &response);
+ if (status == NO_ERROR) {
+ LOG_ALWAYS_FATAL_IF(response.size() != sizeof(status_t));
+ status = *reinterpret_cast<const status_t*>(response.data());
+ }
+ return status;
+}
+
static std::string dumpInOutBuffer(bool isInput, const sp<EffectBufferHalInterface> &buffer) {
std::stringstream ss;
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 8e82d53..9da95bc 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -258,6 +258,7 @@
bool isHapticGenerator() const;
status_t setHapticIntensity(int id, int intensity);
+ status_t setVibratorInfo(const media::AudioVibratorInfo* vibratorInfo);
void dump(int fd, const Vector<String16>& args);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 7f91a54..f1bcfcd 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1439,6 +1439,16 @@
effect->setMode(mAudioFlinger->getMode());
effect->setAudioSource(mAudioSource);
}
+ if (effect->isHapticGenerator()) {
+ // TODO(b/184194057): Use the vibrator information from the vibrator that will be used
+ // for the HapticGenerator.
+ const media::AudioVibratorInfo* defaultVibratorInfo =
+ mAudioFlinger->getDefaultVibratorInfo_l();
+ if (defaultVibratorInfo != nullptr) {
+ // Only set the vibrator info when it is a valid one.
+ effect->setVibratorInfo(defaultVibratorInfo);
+ }
+ }
// create effect handle and connect it to effect module
handle = new EffectHandle(effect, client, effectClient, priority);
lStatus = handle->initCheck();