• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 "motion_recognition.h"
17 
18 #include "chrono"
19 #include "securec.h"
20 
21 #include "audio_control_manager.h"
22 #include "audio_device_manager.h"
23 #include "audio_proxy.h"
24 #include "call_base.h"
25 #include "call_control_manager.h"
26 #include "call_object_manager.h"
27 #include "telephony_log_wrapper.h"
28 
29 namespace OHOS {
30 namespace Telephony {
31 
32 #ifdef OHOS_SUBSCRIBE_MOTION_ENABLE
33 /**
34 * 表示拿起动作
35 * <p>
36 * 上报数据:</b>
37 * <ul>
38 * <li> status: 返回0表示设备发生拿起动作。</li>
39  */
40 constexpr int32_t MOTION_TYPE_PICKUP = 100;
41 
42 /**
43 * 表示翻转动作
44 * <p>
45 * 上报数据:</b>
46 * <ul>
47 * <li> status: 返回0表示设备发生拿起靠近耳朵动作。</li>
48  */
49 constexpr int32_t MOTION_TYPE_FLIP = 200;
50 
51 /**
52 * 表示靠近耳朵动作
53 * <p>
54 * 上报数据:</b>
55 * <ul>
56 * <li> status: 返回0表示设备被拿起靠近耳朵。 </li>
57  */
58 constexpr int32_t MOTION_TYPE_CLOSE_TO_EAR = 300;
59 
60 //来电铃声减弱总时长
61 constexpr int32_t REDUCE_RING_TOTAL_LENGTH = 1500000;  //us
62 
63 /**
64 * @brief 翻转方向
65 *
66  */
67 typedef enum FilpDirection {
68     FLIP_DOWN = 3,  /**向上翻转 */
69     FLIP_UP = 4,  /**向下翻转 */
70 } FilpDirection;
71 
72 bool MotionFlipSubscriber::isMotionFlipSubscribed_ = false;
73 bool MotionCloseToEarSubscriber::isMotionCloseToEarSubscribed_ = false;
74 bool MotionPickupSubscriber::isMotionPickupSubscribed_ = false;
75 
76 static void FlipMotionEventCallback(const Rosen::MotionSensorEvent &motionData);
77 static void CloseToEarMotionEventCallback(const Rosen::MotionSensorEvent &motionData);
78 #endif
79 
SubscribePickupSensor()80 void MotionRecogntion::SubscribePickupSensor()
81 {
82 #ifdef OHOS_SUBSCRIBE_MOTION_ENABLE
83     MotionPickupSubscriber::SubscribePickupMotion();
84 #endif
85 }
86 
UnsubscribePickupSensor()87 void MotionRecogntion::UnsubscribePickupSensor()
88 {
89 #ifdef OHOS_SUBSCRIBE_MOTION_ENABLE
90     MotionPickupSubscriber::UnsubscribePickupMotion();
91 #endif
92 }
93 
SubscribeFlipSensor()94 void MotionRecogntion::SubscribeFlipSensor()
95 {
96 #ifdef OHOS_SUBSCRIBE_MOTION_ENABLE
97     MotionFlipSubscriber::SubscribeFlipMotion();
98 #endif
99 }
100 
UnsubscribeFlipSensor()101 void MotionRecogntion::UnsubscribeFlipSensor()
102 {
103 #ifdef OHOS_SUBSCRIBE_MOTION_ENABLE
104     MotionFlipSubscriber::UnsubscribeFlipMotion();
105 #endif
106 }
107 
SubscribeCloseToEarSensor()108 void MotionRecogntion::SubscribeCloseToEarSensor()
109 {
110 #ifdef  OHOS_SUBSCRIBE_MOTION_ENABLE
111     MotionCloseToEarSubscriber::SubscribeCloseToEarMotion();
112 #endif
113 }
114 
UnsubscribeCloseToEarSensor()115 void MotionRecogntion::UnsubscribeCloseToEarSensor()
116 {
117 #ifdef  OHOS_SUBSCRIBE_MOTION_ENABLE
118     MotionCloseToEarSubscriber::UnsubscribeCloseToEarMotion();
119 #endif
120 }
121 
122 #ifdef  OHOS_SUBSCRIBE_MOTION_ENABLE
FlipMotionEventCallback(const Rosen::MotionSensorEvent & motionData)123 void FlipMotionEventCallback(const Rosen::MotionSensorEvent &motionData)
124 {
125     TELEPHONY_LOGI("type = %{public}d, status = %{public}d", motionData.type, motionData.status);
126     auto controlManager = DelayedSingleton<CallControlManager>::GetInstance();
127 
128     switch (motionData.type) {
129         case MOTION_TYPE_FLIP:
130             if (motionData.status == FilpDirection::FLIP_UP && controlManager != nullptr) {
131                 sptr<CallBase> ringCall = controlManager->
132                     GetOneCarrierCallObject(CallRunningState::CALL_RUNNING_STATE_RINGING);
133                 if (ringCall != nullptr) {
134                     controlManager->MuteRinger();
135                     TELEPHONY_LOGI("flip motion muteRinger");
136                 }
137                 controlManager->StopFlashRemind();
138             }
139             break;
140         case MOTION_TYPE_PICKUP:
141             if (motionData.status != 0) {
142                 break;
143             }
144             MotionRecogntion::UnsubscribePickupSensor();
145             if (controlManager != nullptr) {
146                 controlManager->StopFlashRemind();
147             }
148             ffrt::submit([=]() {
149                 MotionRecogntion::ReduceRingToneVolume();
150             });
151             break;
152         default:
153             break;
154     }
155 }
156 
ReduceRingToneVolume()157 void MotionRecogntion::ReduceRingToneVolume()
158 {
159     int32_t count = 0;
160     float value = 0.0f;
161     int32_t currentVolume = DelayedSingleton<AudioProxy>::GetInstance()->GetVolume(
162         AudioStandard::AudioVolumeType::STREAM_RING);
163     if (currentVolume <= 1) {
164         TELEPHONY_LOGE("currentVolume = %{public}d, return it", currentVolume);
165         return;
166     }
167     float beginVolumeDb = DelayedSingleton<AudioProxy>::GetInstance()->GetSystemRingVolumeInDb(currentVolume);
168     if (beginVolumeDb == 0.0f) {
169         TELEPHONY_LOGE("GetSystemRingVolumeInDb fail");
170         return;
171     }
172     int32_t reduceCount = currentVolume - 1;
173     while (count < reduceCount) {
174         count++;
175         float endVolumeDb = DelayedSingleton<AudioProxy>::GetInstance()->GetSystemRingVolumeInDb(currentVolume - count);
176         if (endVolumeDb == 0.0f || beginVolumeDb <= endVolumeDb) {
177             TELEPHONY_LOGE("GetSystemRingVolumeInDb fail or beginVolumeDb unexpected");
178             return;
179         }
180         DelayedSingleton<AudioControlManager>::GetInstance()->SetRingToneVolume(endVolumeDb / beginVolumeDb);
181         ffrt_usleep(REDUCE_RING_TOTAL_LENGTH / reduceCount);
182     }
183 }
184 
CloseToEarMotionEventCallback(const Rosen::MotionSensorEvent & motionData)185 void CloseToEarMotionEventCallback(const Rosen::MotionSensorEvent &motionData)
186 {
187     TELEPHONY_LOGI("type = %{public}d, status = %{public}d", motionData.type, motionData.status);
188     auto controlManager = DelayedSingleton<CallControlManager>::GetInstance();
189     if (controlManager == nullptr) {
190         return;
191     }
192     sptr<CallBase> ringCall = controlManager->GetOneCarrierCallObject(CallRunningState::CALL_RUNNING_STATE_RINGING);
193     sptr<CallBase> dialingCall = controlManager->GetOneCarrierCallObject(CallRunningState::CALL_RUNNING_STATE_DIALING);
194     sptr<CallBase> activeCall = controlManager->GetOneCarrierCallObject(CallRunningState::CALL_RUNNING_STATE_ACTIVE);
195     sptr<CallBase> holdingCall = controlManager->GetOneCarrierCallObject(CallRunningState::CALL_RUNNING_STATE_HOLD);
196     AudioDevice device = {
197         .deviceType = AudioDeviceType::DEVICE_EARPIECE,
198         .address = { 0 },
199     };
200     AudioDeviceType deviceType = DelayedSingleton<AudioDeviceManager>::GetInstance()->GetCurrentAudioDevice();
201 
202     switch (motionData.type) {
203         case MOTION_TYPE_CLOSE_TO_EAR:
204             if (motionData.status != 0) {
205                 TELEPHONY_LOGI("ignore status is not success");
206                 break;
207             }
208             if (dialingCall == nullptr && activeCall == nullptr && holdingCall == nullptr && ringCall != nullptr) {
209                 controlManager->AnswerCall(ringCall->GetCallID(), static_cast<int32_t>(VideoStateType::TYPE_VOICE));
210                 TELEPHONY_LOGI("close to ear: AnswerCall");
211             };
212             if (dialingCall != nullptr || activeCall != nullptr) {
213                 if (deviceType == AudioDeviceType::DEVICE_SPEAKER ||
214                     deviceType == AudioDeviceType::DEVICE_BLUETOOTH_SCO ||
215                     deviceType == AudioDeviceType::DEVICE_NEARLINK) {
216                         TELEPHONY_LOGI("current deviceType = %{public}d, det audioDevice to earpiece",
217                             static_cast<int32_t>(deviceType));
218                         controlManager->SetAudioDevice(device);
219                 }
220             }
221             controlManager->StopFlashRemind();
222             break;
223         default:
224             break;
225     }
226 }
227 
SubscribePickupMotion()228 void MotionPickupSubscriber::SubscribePickupMotion()
229 {
230     if (isMotionPickupSubscribed_) {
231         return;
232     }
233     if (!SubscribeCallback(MOTION_TYPE_PICKUP, FlipMotionEventCallback)) {
234         TELEPHONY_LOGI("Pickup motion subscribe failed");
235         return;
236     }
237     isMotionPickupSubscribed_ = true;
238 }
239 
UnsubscribePickupMotion()240 void MotionPickupSubscriber::UnsubscribePickupMotion()
241 {
242     if (!isMotionPickupSubscribed_)  {
243         TELEPHONY_LOGI("Unsubscribe Pickup motion");
244         return;
245     }
246 
247     if (!UnsubscribeCallback(MOTION_TYPE_PICKUP, FlipMotionEventCallback)) {
248         TELEPHONY_LOGI("Pickup motion unsubscribe failed");
249         return;
250     }
251     isMotionPickupSubscribed_ = false;
252 }
253 
SubscribeFlipMotion()254 void MotionFlipSubscriber::SubscribeFlipMotion()
255 {
256     if (isMotionFlipSubscribed_) {
257         return;
258     }
259     if (!SubscribeCallback(MOTION_TYPE_FLIP, FlipMotionEventCallback)) {
260         TELEPHONY_LOGI("flip motion subscribe failed");
261         return;
262     }
263     isMotionFlipSubscribed_ = true;
264 }
265 
UnsubscribeFlipMotion()266 void MotionFlipSubscriber::UnsubscribeFlipMotion()
267 {
268     if (!isMotionFlipSubscribed_)  {
269         TELEPHONY_LOGI("Unsubscribe flip motion");
270         return;
271     }
272 
273     if (!UnsubscribeCallback(MOTION_TYPE_FLIP, FlipMotionEventCallback)) {
274         TELEPHONY_LOGI("flip motion unsubscribe failed");
275         return;
276     }
277     isMotionFlipSubscribed_ = false;
278 }
279 
SubscribeCloseToEarMotion()280 void MotionCloseToEarSubscriber::SubscribeCloseToEarMotion()
281 {
282     if (isMotionCloseToEarSubscribed_) {
283         return;
284     }
285     if (!SubscribeCallback(MOTION_TYPE_CLOSE_TO_EAR, CloseToEarMotionEventCallback)) {
286         TELEPHONY_LOGI("close to ear motion subscribe failed");
287         return;
288     }
289     isMotionCloseToEarSubscribed_ = true;
290 }
291 
UnsubscribeCloseToEarMotion()292 void MotionCloseToEarSubscriber::UnsubscribeCloseToEarMotion()
293 {
294     if (!isMotionCloseToEarSubscribed_)  {
295         TELEPHONY_LOGI("Unsubscribe close to ear motion");
296         return;
297     }
298     if (!UnsubscribeCallback(MOTION_TYPE_CLOSE_TO_EAR, CloseToEarMotionEventCallback)) {
299         TELEPHONY_LOGI("close to ear motion unsubscribe failed");
300         return;
301     }
302     isMotionCloseToEarSubscribed_ = false;
303 }
304 #endif
305 } // namespace Telephony
306 } // namespace OHOS