* Copyright (c) 2021-2024 Huawei Device Co., Ltd.
* 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_agent.h"
#include "parameters.h"
#include "sensors_errors.h"
#include "vibrator_service_client.h"
#undef LOG_TAG
#define LOG_TAG "VibratorNDK"
namespace OHOS {
namespace Sensors {
using OHOS::Sensors::VibratorServiceClient;
namespace {
const std::string PHONE_TYPE = "phone";
const int32_t INTENSITY_ADJUST_MIN = 0;
const int32_t INTENSITY_ADJUST_MAX = 100;
const int32_t FREQUENCY_ADJUST_MIN = -100;
const int32_t FREQUENCY_ADJUST_MAX = 100;
}
static int32_t NormalizeErrCode(int32_t code)
{
switch (code) {
case PERMISSION_DENIED: {
return PERMISSION_DENIED;
}
case PARAMETER_ERROR: {
return PARAMETER_ERROR;
}
case IS_NOT_SUPPORTED: {
return IS_NOT_SUPPORTED;
}
default: {
return DEVICE_OPERATION_FAILED;
}
}
}
bool SetLoopCount(int32_t count)
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return SetLoopCountEnhanced(identifier, count);
}
bool SetLoopCountEnhanced(const VibratorIdentifier identifier, int32_t count)
{
if (count <= 0) {
MISC_HILOGE("Input invalid, count is %{public}d", count);
return false;
}
auto &client = VibratorServiceClient::GetInstance();
client.SetLoopCount(identifier, count);
return true;
}
int32_t StartVibrator(const char *effectId)
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return StartVibratorEnhanced(identifier, effectId);
}
int32_t StartVibratorEnhanced(const VibratorIdentifier identifier, const char *effectId)
{
MISC_HILOGD("Time delay measurement:start time");
CHKPR(effectId, PARAMETER_ERROR);
auto &client = VibratorServiceClient::GetInstance();
VibratorEffectParameter vibratorEffectParameter = client.GetVibratorEffectParameter(identifier);
int32_t ret = client.Vibrate(identifier, effectId, vibratorEffectParameter.loopCount,
vibratorEffectParameter.usage, vibratorEffectParameter.systemUsage);
client.SetUsage(identifier, USAGE_UNKNOWN, false);
client.SetLoopCount(identifier, 1);
if (ret != ERR_OK) {
MISC_HILOGE("Vibrate effectId failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t StartVibratorOnce(int32_t duration)
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return StartVibratorOnceEnhanced(identifier, duration);
}
int32_t StartVibratorOnceEnhanced(const VibratorIdentifier identifier, int32_t duration)
{
if (duration <= 0) {
MISC_HILOGE("duration is invalid");
return PARAMETER_ERROR;
}
auto &client = VibratorServiceClient::GetInstance();
VibratorEffectParameter vibratorEffectParameter = client.GetVibratorEffectParameter(identifier);
int32_t ret = client.Vibrate(identifier, duration, vibratorEffectParameter.usage,
vibratorEffectParameter.systemUsage);
client.SetUsage(identifier, USAGE_UNKNOWN, false);
if (ret != ERR_OK) {
MISC_HILOGE("Vibrate duration failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
bool IsSupportVibratorCustom()
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return IsSupportVibratorCustomEnhanced(identifier);
}
bool IsSupportVibratorCustomEnhanced(const VibratorIdentifier identifier)
{
auto &client = VibratorServiceClient::GetInstance();
return client.IsSupportVibratorCustom(identifier);
}
int32_t PlayVibratorCustom(int32_t fd, int64_t offset, int64_t length)
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return PlayVibratorCustomEnhanced(identifier, fd, offset, length);
}
int32_t PlayVibratorCustomEnhanced(const VibratorIdentifier identifier, int32_t fd, int64_t offset, int64_t length)
{
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_CUSTOM
MISC_HILOGD("Time delay measurement:start time");
if (fd < 0 || offset < 0 || length <= 0) {
MISC_HILOGE("Input parameter invalid, fd:%{public}d, offset:%{public}lld, length:%{public}lld",
fd, static_cast<long long>(offset), static_cast<long long>(length));
return PARAMETER_ERROR;
}
auto &client = VibratorServiceClient::GetInstance();
RawFileDescriptor rawFd = {
.fd = fd,
.offset = offset,
.length = length
};
VibratorEffectParameter vibratorEffectParameter = client.GetVibratorEffectParameter(identifier);
int32_t ret = client.PlayVibratorCustom(identifier, rawFd, vibratorEffectParameter.usage,
vibratorEffectParameter.systemUsage, vibratorEffectParameter.vibratorParameter);
vibratorEffectParameter.vibratorParameter.intensity = INTENSITY_ADJUST_MAX;
vibratorEffectParameter.vibratorParameter.frequency = 0;
client.SetUsage(identifier, USAGE_UNKNOWN, false);
client.SetParameters(identifier, vibratorEffectParameter.vibratorParameter);
if (ret != ERR_OK) {
MISC_HILOGE("PlayVibratorCustom failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
#else
MISC_HILOGE("The device does not support this operation");
return IS_NOT_SUPPORTED;
#endif
}
int32_t StopVibrator(const char *mode)
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return StopVibratorEnhanced(identifier, mode);
}
int32_t StopVibratorEnhanced(const VibratorIdentifier identifier, const char *mode)
{
CHKPR(mode, PARAMETER_ERROR);
if (strcmp(mode, "time") != 0 && strcmp(mode, "preset") != 0) {
MISC_HILOGE("Input parameter invalid, mode is %{public}s", mode);
return PARAMETER_ERROR;
}
auto &client = VibratorServiceClient::GetInstance();
int32_t ret = client.StopVibrator(identifier, mode);
if (ret != ERR_OK) {
MISC_HILOGE("StopVibrator by mode failed, ret:%{public}d, mode:%{public}s", ret, mode);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t Cancel()
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return CancelEnhanced(identifier);
}
int32_t CancelEnhanced(const VibratorIdentifier identifier)
{
auto &client = VibratorServiceClient::GetInstance();
int32_t ret = client.StopVibrator(identifier);
if (ret != ERR_OK) {
MISC_HILOGE("StopVibrator failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
bool SetUsage(int32_t usage, bool systemUsage)
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return SetUsageEnhanced(identifier, usage, systemUsage);
}
bool SetUsageEnhanced(const VibratorIdentifier identifier, int32_t usage, bool systemUsage)
{
if ((usage < 0) || (usage >= USAGE_MAX)) {
MISC_HILOGE("Input invalid, usage is %{public}d", usage);
return false;
}
auto &client = VibratorServiceClient::GetInstance();
client.SetUsage(identifier, usage, systemUsage);
return true;
}
bool IsHdHapticSupported()
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return IsHdHapticSupportedEnhanced(identifier);
}
bool IsHdHapticSupportedEnhanced(const VibratorIdentifier identifier)
{
auto &client = VibratorServiceClient::GetInstance();
return client.IsHdHapticSupported(identifier);
}
int32_t IsSupportEffect(const char *effectId, bool *state)
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return IsSupportEffectEnhanced(identifier, effectId, state);
}
int32_t IsSupportEffectEnhanced(const VibratorIdentifier identifier, const char *effectId, bool *state)
{
CHKPR(effectId, PARAMETER_ERROR);
CHKPR(state, PARAMETER_ERROR);
auto &client = VibratorServiceClient::GetInstance();
int32_t ret = client.IsSupportEffect(identifier, effectId, *state);
if (ret != ERR_OK) {
MISC_HILOGE("Query effect support failed, ret:%{public}d, effectId:%{public}s", ret, effectId);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t PreProcess(const VibratorFileDescription &fd, VibratorPackage &package)
{
auto &client = VibratorServiceClient::GetInstance();
int32_t ret = client.PreProcess(fd, package);
if (ret != ERR_OK) {
MISC_HILOGE("DecodeVibratorFile failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t GetDelayTime(int32_t &delayTime)
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return GetDelayTimeEnhanced(identifier, delayTime);
}
int32_t GetDelayTimeEnhanced(const VibratorIdentifier identifier, int32_t &delayTime)
{
auto &client = VibratorServiceClient::GetInstance();
int32_t ret = client.GetDelayTime(identifier, delayTime);
if (ret != ERR_OK) {
MISC_HILOGE("GetDelayTime failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t PlayPattern(const VibratorPattern &pattern)
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return PlayPatternEnhanced(identifier, pattern);
}
int32_t PlayPatternEnhanced(const VibratorIdentifier identifier, const VibratorPattern &pattern)
{
auto &client = VibratorServiceClient::GetInstance();
VibratorEffectParameter vibratorEffectParameter = client.GetVibratorEffectParameter(identifier);
int32_t ret = client.PlayPattern(identifier, pattern, vibratorEffectParameter.usage,
vibratorEffectParameter.systemUsage, vibratorEffectParameter.vibratorParameter);
vibratorEffectParameter.vibratorParameter.intensity = INTENSITY_ADJUST_MAX;
vibratorEffectParameter.vibratorParameter.frequency = 0;
client.SetUsage(identifier, USAGE_UNKNOWN, false);
client.SetParameters(identifier, vibratorEffectParameter.vibratorParameter);
if (ret != ERR_OK) {
MISC_HILOGE("PlayPattern failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t SeekTimeOnPackage(int32_t seekTime, const VibratorPackage &completePackage, VibratorPackage &seekPackage)
{
auto &client = VibratorServiceClient::GetInstance();
int32_t ret = client.SeekTimeOnPackage(seekTime, completePackage, seekPackage);
if (ret != ERR_OK) {
MISC_HILOGE("SeekTimeOnPackage failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t ModulatePackage(VibratorCurvePoint* modulationCurve, const int32_t curvePointNum, const int32_t duration,
const VibratorPackage &beforeModulationPackage, VibratorPackage &afterModulationPackage)
{
VibratorEvent modulationEvent{.type = EVENT_TYPE_CONTINUOUS, .time = 0, .duration = duration,
.intensity = -1, .frequency = -1, .index = 0, .pointNum = curvePointNum,
.points = modulationCurve};
int32_t ret = VibratorServiceClient::ModulatePackage(
modulationEvent, beforeModulationPackage, afterModulationPackage);
if (ret != ERR_OK) {
MISC_HILOGE("ModulatePackage failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t FreeVibratorPackage(VibratorPackage &package)
{
int32_t ret = VibratorServiceClient::FreeVibratorPackage(package);
if (ret != ERR_OK) {
MISC_HILOGE("FreeVibratorPackage failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
bool SetParameters(const VibratorParameter ¶meter)
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return SetParametersEnhanced(identifier, parameter);
}
bool SetParametersEnhanced(const VibratorIdentifier identifier, const VibratorParameter ¶meter)
{
if ((parameter.intensity < INTENSITY_ADJUST_MIN) || (parameter.intensity > INTENSITY_ADJUST_MAX) ||
(parameter.frequency < FREQUENCY_ADJUST_MIN) || (parameter.frequency > FREQUENCY_ADJUST_MAX)) {
MISC_HILOGE("Input invalid, intensity parameter is %{public}d, frequency parameter is %{public}d",
parameter.intensity, parameter.frequency);
return false;
}
auto &client = VibratorServiceClient::GetInstance();
client.SetParameters(identifier, parameter);
return true;
}
int32_t PlayPrimitiveEffect(const char *effectId, int32_t intensity)
{
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
return PlayPrimitiveEffectEnhanced(identifier, effectId, intensity);
}
int32_t PlayPrimitiveEffectEnhanced(const VibratorIdentifier identifier, const char *effectId, int32_t intensity)
{
MISC_HILOGD("Time delay measurement:start time");
CHKPR(effectId, PARAMETER_ERROR);
auto &client = VibratorServiceClient::GetInstance();
VibratorEffectParameter vibratorEffectParameter = client.GetVibratorEffectParameter(identifier);
PrimitiveEffect primitiveEffect;
primitiveEffect.intensity = intensity;
primitiveEffect.usage = vibratorEffectParameter.usage;
primitiveEffect.systemUsage = vibratorEffectParameter.systemUsage;
primitiveEffect.count = vibratorEffectParameter.loopCount;
int32_t ret = client.PlayPrimitiveEffect(identifier, effectId, primitiveEffect);
client.SetUsage(identifier, USAGE_UNKNOWN, false);
client.SetLoopCount(identifier, 1);
if (ret != ERR_OK) {
MISC_HILOGE("Play primitive effect failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t GetVibratorList(const VibratorIdentifier& identifier, std::vector<VibratorInfos>& vibratorInfo)
{
CALL_LOG_ENTER;
CHKCR(&identifier, PARAMETER_ERROR, "Invalid parameters");
MISC_HILOGD("VibratorIdentifier = [deviceId = %{public}d, vibratorId = %{public}d]", identifier.deviceId,
identifier.vibratorId);
auto &client = VibratorServiceClient::GetInstance();
int32_t ret = client.GetVibratorList(identifier, vibratorInfo);
if (ret != ERR_OK) {
MISC_HILOGE("Get vibrator list failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t GetEffectInfo(const VibratorIdentifier& identifier, const std::string& effectType, EffectInfo& effectInfo)
{
CALL_LOG_ENTER;
CHKCR(&identifier, PARAMETER_ERROR, "Invalid parameters");
MISC_HILOGD("VibratorIdentifier = [deviceId = %{public}d, vibratorId = %{public}d]", identifier.deviceId,
identifier.vibratorId);
auto &client = VibratorServiceClient::GetInstance();
int32_t ret = client.GetEffectInfo(identifier, effectType, effectInfo);
if (ret != ERR_OK) {
effectInfo.isSupportEffect = false;
MISC_HILOGW("Get effect info failed, ret:%{public}d", ret);
}
return SUCCESS;
}
int32_t SubscribeVibratorPlug(const VibratorUser& user)
{
CALL_LOG_ENTER;
CHKCR(user.callback, PARAMETER_ERROR, "Invalid parameters");
auto &client = VibratorServiceClient::GetInstance();
int32_t ret = client.SubscribeVibratorPlugInfo(&user);
if (ret != ERR_OK) {
MISC_HILOGE("SubscribeVibratorPlug failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t UnSubscribeVibratorPlug(const VibratorUser& user)
{
CALL_LOG_ENTER;
CHKCR(user.callback, PARAMETER_ERROR, "Invalid parameters");
auto &client = VibratorServiceClient::GetInstance();
int32_t ret = client.UnsubscribeVibratorPlugInfo(&user);
if (ret != ERR_OK) {
MISC_HILOGE("UnsubscribeVibratorPlugInfo failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t PlayPatternBySessionId(uint32_t sessionId, const VibratorPattern &pattern)
{
CALL_LOG_ENTER;
if (sessionId == 0) {
MISC_HILOGE("sessionId invalid, ret:%{public}d", sessionId);
return PARAMETER_ERROR;
}
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
auto &client = VibratorServiceClient::GetInstance();
VibratorEffectParameter vibratorEffectParameter = client.GetVibratorEffectParameter(identifier);
vibratorEffectParameter.vibratorParameter.sessionId = sessionId;
int32_t ret = client.PlayPattern(identifier, pattern, vibratorEffectParameter.usage,
vibratorEffectParameter.systemUsage, vibratorEffectParameter.vibratorParameter);
vibratorEffectParameter.vibratorParameter.intensity = INTENSITY_ADJUST_MAX;
vibratorEffectParameter.vibratorParameter.frequency = 0;
client.SetUsage(identifier, USAGE_UNKNOWN, false);
client.SetParameters(identifier, vibratorEffectParameter.vibratorParameter);
if (ret != ERR_OK) {
MISC_HILOGE("PlayPatternBySessionId failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t PlayPackageBySessionId(uint32_t sessionId, const VibratorPackage &package)
{
CALL_LOG_ENTER;
if (sessionId == 0) {
MISC_HILOGE("sessionId invalid, ret:%{public}d", sessionId);
return PARAMETER_ERROR;
}
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
auto &client = VibratorServiceClient::GetInstance();
VibratorEffectParameter vibratorEffectParameter = client.GetVibratorEffectParameter(identifier);
vibratorEffectParameter.sessionId = sessionId;
int32_t ret = client.PlayPackageBySessionId(identifier, vibratorEffectParameter, package);
if (ret != ERR_OK) {
MISC_HILOGE("PlayPackageBySessionId failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
vibratorEffectParameter.vibratorParameter.intensity = INTENSITY_ADJUST_MAX;
vibratorEffectParameter.vibratorParameter.frequency = 0;
client.SetUsage(identifier, USAGE_UNKNOWN, false);
client.SetParameters(identifier, vibratorEffectParameter.vibratorParameter);
return SUCCESS;
}
int32_t StopVibrateBySessionId(uint32_t sessionId)
{
CALL_LOG_ENTER;
if (sessionId == 0) {
MISC_HILOGE("sessionId invalid, ret:%{public}d", sessionId);
return PARAMETER_ERROR;
}
VibratorIdentifier identifier = {
.deviceId = -1,
.vibratorId = -1
};
int32_t ret = VibratorServiceClient::GetInstance().StopVibrateBySessionId(identifier, sessionId);
if (ret != ERR_OK) {
MISC_HILOGE("StopVibrateBySessionId failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t DisableVibratorByPid(int32_t pid)
{
CALL_LOG_ENTER;
MISC_HILOGD("Agent Disable Vibrator for pid:%{public}d", pid);
if (pid <= 0) {
MISC_HILOGE("Invalid pid: %{pubilc}d", pid);
return PARAMETER_ERROR;
}
int32_t ret = VibratorServiceClient::GetInstance().DisableVibratorByPid(pid);
if (ret != ERR_OK) {
MISC_HILOGE("Agent disable failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
int32_t EnableVibratorByPid(int32_t pid)
{
CALL_LOG_ENTER;
MISC_HILOGD("Agent Enable Vibrator for pid:%{public}d", pid);
if (pid <= 0) {
MISC_HILOGE("Invalid pid: %{pubilc}d", pid);
return PARAMETER_ERROR;
}
int32_t ret = VibratorServiceClient::GetInstance().EnableVibratorByPid(pid);
if (ret != ERR_OK) {
MISC_HILOGE("Agent Enable failed, ret:%{public}d", ret);
return NormalizeErrCode(ret);
}
return SUCCESS;
}
}
}