• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "custom_vibration_matcher.h"
17 
18 #include <cmath>
19 #include <map>
20 
21 #include "sensors_errors.h"
22 
23 namespace OHOS {
24 namespace Sensors {
25 namespace {
26 const std::map<int32_t, std::vector<int32_t>> TRANSIENT_VIBRATION_INFOS = {
27     {0x28, {0x4d, 0x4d, 0x0b}}, {0x2c, {0x2a, 0x64, 0x07}}, {0x30, {0x44, 0x52, 0x16}},
28     {0x3c, {0x45, 0x34, 0x0a}}, {0x40, {0x2e, 0x43, 0x0a}}, {0x48, {0x51, 0x52, 0x0a}},
29     {0x4c, {0x3a, 0x0c, 0x0f}}, {0x50, {0x64, 0x20, 0x14}}, {0x54, {0x55, 0x34, 0x1c}},
30     {0x5c, {0x32, 0x0c, 0x13}}, {0x60, {0x12, 0x07, 0x0a}}
31 };
32 constexpr int32_t INTENSITY_MAX = 100;
33 constexpr int32_t TRANSIENT_GRADE_NUM = 4;
34 constexpr int32_t CONTINUOUS_GRADE_NUM = 8;
35 constexpr int32_t CONTINUOUS_GRADE_MASK = 100;
36 constexpr float ROUND_OFFSET = 0.5;
37 constexpr float TRANSIENT_GRADE_GAIN = 0.25;
38 constexpr float CONTINUOUS_GRADE_SCALE = 100. / 8;
39 constexpr float INTENSITY_WEIGHT = 0.5;
40 constexpr float FREQUENCY_WEIGHT = 0.5;
41 constexpr float WEIGHT_SUM_INIT = 100;
42 constexpr int32_t STOP_WAVEFORM = 0;
43 constexpr int32_t EFFECT_ID_BOUNDARY = 1000;
44 constexpr int32_t DURATION_MAX = 1600;
45 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MISC_LOG_DOMAIN, "CustomVibrationMatcher" };
46 }  // namespace
47 
TransformEffect(const std::set<VibrateEvent> & vibrateSet,std::vector<CompositeEffect> & compositeEffects)48 int32_t CustomVibrationMatcher::TransformEffect(const std::set<VibrateEvent> &vibrateSet,
49     std::vector<CompositeEffect> &compositeEffects)
50 {
51     CALL_LOG_ENTER;
52     int32_t preStartTime = 0;
53     int32_t preDuration = 0;
54     for (const auto &event : vibrateSet) {
55         if ((preDuration != 0) && (event.startTime < preStartTime + preDuration)) {
56             MISC_HILOGE("Vibration events overlap");
57             return ERROR;
58         }
59         if (event.tag == EVENT_TAG_CONTINUOUS) {
60             ProcessContinuousEvent(event, preStartTime, preDuration, compositeEffects);
61         } else if (event.tag == EVENT_TAG_TRANSIENT) {
62             ProcessTransientEvent(event, preStartTime, preDuration, compositeEffects);
63         } else {
64             MISC_HILOGE("Unknown event tag, tag:%{public}d", event.tag);
65             return ERROR;
66         }
67     }
68     PrimitiveEffect primitiveEffect;
69     primitiveEffect.delay = preDuration;
70     primitiveEffect.effectId = STOP_WAVEFORM;
71     CompositeEffect compositeEffect;
72     compositeEffect.primitiveEffect = primitiveEffect;
73     compositeEffects.push_back(compositeEffect);
74     return SUCCESS;
75 }
76 
ProcessContinuousEvent(const VibrateEvent & event,int32_t & preStartTime,int32_t & preDuration,std::vector<CompositeEffect> & compositeEffects)77 void CustomVibrationMatcher::ProcessContinuousEvent(const VibrateEvent &event, int32_t &preStartTime,
78     int32_t &preDuration, std::vector<CompositeEffect> &compositeEffects)
79 {
80     int32_t grade = -1;
81     if (event.intensity == INTENSITY_MAX) {
82         grade = CONTINUOUS_GRADE_NUM - 1;
83     } else {
84         grade = round(event.intensity / CONTINUOUS_GRADE_SCALE + ROUND_OFFSET) - 1;
85     }
86     if ((!compositeEffects.empty()) && (event.startTime == preStartTime + preDuration)) {
87         PrimitiveEffect& prePrimitiveEffect = compositeEffects.back().primitiveEffect;
88         int32_t preEffectId = prePrimitiveEffect.effectId;
89         int32_t preGrade = preEffectId % CONTINUOUS_GRADE_MASK;
90         int32_t mergeDuration = preDuration + event.duration;
91         if (preEffectId > EFFECT_ID_BOUNDARY && preGrade == grade && mergeDuration < DURATION_MAX) {
92             prePrimitiveEffect.effectId = mergeDuration * CONTINUOUS_GRADE_MASK + grade;
93             preDuration = mergeDuration;
94             return;
95         }
96     }
97     PrimitiveEffect primitiveEffect;
98     primitiveEffect.delay = event.startTime - preStartTime;
99     primitiveEffect.effectId = event.duration * CONTINUOUS_GRADE_MASK + grade;
100     CompositeEffect compositeEffect;
101     compositeEffect.primitiveEffect = primitiveEffect;
102     compositeEffects.push_back(compositeEffect);
103     preStartTime = event.startTime;
104     preDuration = event.duration;
105 }
106 
ProcessTransientEvent(const VibrateEvent & event,int32_t & preStartTime,int32_t & preDuration,std::vector<CompositeEffect> & compositeEffects)107 void CustomVibrationMatcher::ProcessTransientEvent(const VibrateEvent &event, int32_t &preStartTime,
108     int32_t &preDuration, std::vector<CompositeEffect> &compositeEffects)
109 {
110     int32_t matchId = 0;
111     float minWeightSum = WEIGHT_SUM_INIT;
112     for (const auto &transientInfo : TRANSIENT_VIBRATION_INFOS) {
113         int32_t id = transientInfo.first;
114         const std::vector<int32_t> &info = transientInfo.second;
115         float frequencyDistance = std::abs(event.frequency - info[1]);
116         for (int32_t j = 0; j < TRANSIENT_GRADE_NUM; ++j) {
117             float intensityDistance = std::abs(event.intensity - info[0] * (1 - j * TRANSIENT_GRADE_GAIN));
118             float weightSum = INTENSITY_WEIGHT * intensityDistance + FREQUENCY_WEIGHT * frequencyDistance;
119             if (weightSum < minWeightSum) {
120                 minWeightSum = weightSum;
121                 matchId = id + j;
122             }
123         }
124     }
125     PrimitiveEffect primitiveEffect;
126     primitiveEffect.delay = event.startTime - preStartTime;
127     primitiveEffect.effectId = matchId;
128     CompositeEffect compositeEffect;
129     compositeEffect.primitiveEffect = primitiveEffect;
130     compositeEffects.push_back(compositeEffect);
131     preStartTime = event.startTime;
132     preDuration = event.duration;
133 }
134 }  // namespace Sensors
135 }  // namespace OHOS