• 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     sptr<CallBase> ringCall = controlManager->GetOneCarrierCallObject(CallRunningState::CALL_RUNNING_STATE_RINGING);
128 
129     switch (motionData.type) {
130         case MOTION_TYPE_FLIP:
131             if (motionData.status == FilpDirection::FLIP_UP) {
132                 if (controlManager != nullptr && ringCall != nullptr) {
133                     controlManager->MuteRinger();
134                     TELEPHONY_LOGI("flip motion muteRinger");
135                 }
136             }
137             break;
138         case MOTION_TYPE_PICKUP:
139             if (motionData.status != 0) {
140                 break;
141             }
142             MotionRecogntion::UnsubscribePickupSensor();
143             ffrt::submit([=]() {
144                 MotionRecogntion::ReduceRingToneVolume();
145             });
146             break;
147         default:
148             break;
149     }
150 }
151 
ReduceRingToneVolume()152 void MotionRecogntion::ReduceRingToneVolume()
153 {
154     int32_t count = 0;
155     float value = 0.0f;
156     int32_t currentVolume = DelayedSingleton<AudioProxy>::GetInstance()->GetVolume(
157         AudioStandard::AudioVolumeType::STREAM_RING);
158     if (currentVolume <= 1) {
159         TELEPHONY_LOGE("currentVolume = %{public}d, return it", currentVolume);
160         return;
161     }
162     float beginVolumeDb = DelayedSingleton<AudioProxy>::GetInstance()->GetSystemRingVolumeInDb(currentVolume);
163     if (beginVolumeDb == 0.0f) {
164         TELEPHONY_LOGE("GetSystemRingVolumeInDb fail");
165         return;
166     }
167     int32_t reduceCount = currentVolume - 1;
168     while (count < reduceCount) {
169         count++;
170         float endVolumeDb = DelayedSingleton<AudioProxy>::GetInstance()->GetSystemRingVolumeInDb(currentVolume - count);
171         if (endVolumeDb == 0.0f || beginVolumeDb <= endVolumeDb) {
172             TELEPHONY_LOGE("GetSystemRingVolumeInDb fail or beginVolumeDb unexpected");
173             return;
174         }
175         DelayedSingleton<AudioControlManager>::GetInstance()->SetRingToneVolume(endVolumeDb / beginVolumeDb);
176         ffrt_usleep(REDUCE_RING_TOTAL_LENGTH / reduceCount);
177     }
178 }
179 
CloseToEarMotionEventCallback(const Rosen::MotionSensorEvent & motionData)180 void CloseToEarMotionEventCallback(const Rosen::MotionSensorEvent &motionData)
181 {
182     TELEPHONY_LOGI("type = %{public}d, status = %{public}d", motionData.type, motionData.status);
183     auto controlManager = DelayedSingleton<CallControlManager>::GetInstance();
184     sptr<CallBase> ringCall = controlManager->GetOneCarrierCallObject(CallRunningState::CALL_RUNNING_STATE_RINGING);
185     sptr<CallBase> dialingCall = controlManager->GetOneCarrierCallObject(CallRunningState::CALL_RUNNING_STATE_DIALING);
186     sptr<CallBase> activeCall = controlManager->GetOneCarrierCallObject(CallRunningState::CALL_RUNNING_STATE_ACTIVE);
187     sptr<CallBase> holdingCall = controlManager->GetOneCarrierCallObject(CallRunningState::CALL_RUNNING_STATE_HOLD);
188     AudioDevice device = {
189         .deviceType = AudioDeviceType::DEVICE_EARPIECE,
190         .address = { 0 },
191     };
192     AudioDeviceType deviceType = DelayedSingleton<AudioDeviceManager>::GetInstance()->GetCurrentAudioDevice();
193     switch (motionData.type) {
194         case MOTION_TYPE_CLOSE_TO_EAR:
195             if (motionData.status != 0) {
196                 TELEPHONY_LOGI("ignore status is not success");
197                 break;
198             }
199             if (dialingCall == nullptr && activeCall == nullptr && holdingCall == nullptr &&
200                 controlManager != nullptr && ringCall != nullptr) {
201                 controlManager->AnswerCall(ringCall->GetCallID(), static_cast<int32_t>(VideoStateType::TYPE_VOICE));
202                 TELEPHONY_LOGI("close to ear: AnswerCall");
203             };
204             if (controlManager != nullptr && (dialingCall != nullptr || activeCall != nullptr)) {
205                 if (deviceType == AudioDeviceType::DEVICE_SPEAKER ||
206                     deviceType == AudioDeviceType::DEVICE_BLUETOOTH_SCO) {
207                         TELEPHONY_LOGI("current deviceType = %{public}d, det audioDevice to earpiece",
208                             static_cast<int32_t>(deviceType));
209                         controlManager->SetAudioDevice(device);
210                 }
211             }
212             break;
213         default:
214             break;
215     }
216 }
217 
SubscribePickupMotion()218 void MotionPickupSubscriber::SubscribePickupMotion()
219 {
220     if (isMotionPickupSubscribed_) {
221         return;
222     }
223     if (!SubscribeCallback(MOTION_TYPE_PICKUP, FlipMotionEventCallback)) {
224         TELEPHONY_LOGI("Pickup motion subscribe failed");
225         return;
226     }
227     isMotionPickupSubscribed_ = true;
228 }
229 
UnsubscribePickupMotion()230 void MotionPickupSubscriber::UnsubscribePickupMotion()
231 {
232     if (!isMotionPickupSubscribed_)  {
233         TELEPHONY_LOGI("Unsubscribe Pickup motion");
234         return;
235     }
236 
237     if (!UnsubscribeCallback(MOTION_TYPE_PICKUP, FlipMotionEventCallback)) {
238         TELEPHONY_LOGI("Pickup motion unsubscribe failed");
239         return;
240     }
241     isMotionPickupSubscribed_ = false;
242 }
243 
SubscribeFlipMotion()244 void MotionFlipSubscriber::SubscribeFlipMotion()
245 {
246     if (isMotionFlipSubscribed_) {
247         return;
248     }
249     if (!SubscribeCallback(MOTION_TYPE_FLIP, FlipMotionEventCallback)) {
250         TELEPHONY_LOGI("flip motion subscribe failed");
251         return;
252     }
253     isMotionFlipSubscribed_ = true;
254 }
255 
UnsubscribeFlipMotion()256 void MotionFlipSubscriber::UnsubscribeFlipMotion()
257 {
258     if (!isMotionFlipSubscribed_)  {
259         TELEPHONY_LOGI("Unsubscribe flip motion");
260         return;
261     }
262 
263     if (!UnsubscribeCallback(MOTION_TYPE_FLIP, FlipMotionEventCallback)) {
264         TELEPHONY_LOGI("flip motion unsubscribe failed");
265         return;
266     }
267     isMotionFlipSubscribed_ = false;
268 }
269 
SubscribeCloseToEarMotion()270 void MotionCloseToEarSubscriber::SubscribeCloseToEarMotion()
271 {
272     if (isMotionCloseToEarSubscribed_) {
273         return;
274     }
275     if (!SubscribeCallback(MOTION_TYPE_CLOSE_TO_EAR, CloseToEarMotionEventCallback)) {
276         TELEPHONY_LOGI("close to ear motion subscribe failed");
277         return;
278     }
279     isMotionCloseToEarSubscribed_ = true;
280 }
281 
UnsubscribeCloseToEarMotion()282 void MotionCloseToEarSubscriber::UnsubscribeCloseToEarMotion()
283 {
284     if (!isMotionCloseToEarSubscribed_)  {
285         TELEPHONY_LOGI("Unsubscribe close to ear motion");
286         return;
287     }
288     if (!UnsubscribeCallback(MOTION_TYPE_CLOSE_TO_EAR, CloseToEarMotionEventCallback)) {
289         TELEPHONY_LOGI("close to ear motion unsubscribe failed");
290         return;
291     }
292     isMotionCloseToEarSubscribed_ = false;
293 }
294 #endif
295 } // namespace Telephony
296 } // namespace OHOS