* Copyright (C) 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 "call_object_manager.h"
#include "call_wired_headset.h"
#include "input_manager.h"
#include "audio_device_manager.h"
#include "audio_control_manager.h"
#include "call_manager_base.h"
#include "system_ability_definition.h"
#include "call_control_manager.h"
#include "audio_proxy.h"
#include "call_manager_base.h"
#include "ims_conference.h"
namespace OHOS {
namespace Telephony {
using WiredHeadSetCallback = std::function<void(const std::shared_ptr<OHOS::MMI::KeyEvent>)>;
constexpr int32_t INVALID_VALUE = -1;
constexpr int32_t FINAL_KEY_DOWN_DURATION_TWO = 2000;
CallWiredHeadSet::CallWiredHeadSet()
{
isProcessed_ = false;
downFirstTime_ = 0;
subscribeIdForPressedUp_ = INVALID_VALUE;
subscribeIdForPressedDown_ = INVALID_VALUE;
subscribeIdForMediaPausedUp_ = INVALID_VALUE;
subscribeIdForMediaPauseDown_ = INVALID_VALUE;
}
CallWiredHeadSet::~CallWiredHeadSet()
{
DeInit();
}
bool CallWiredHeadSet::Init()
{
const int32_t HEADSETHOOK_KEY = MMI::KeyEvent::KEYCODE_HEADSETHOOK;
const int32_t MEDIA_PLAY_PAUSE_KEY = MMI::KeyEvent::KEYCODE_MEDIA_PLAY_PAUSE;
auto pressedUpCallBack = [this](const std::shared_ptr<OHOS::MMI::KeyEvent> event) {
this->DealKeyPressedUp(event);
};
auto pressedDownCallBack = [this](const std::shared_ptr<OHOS::MMI::KeyEvent> event) {
this->DealKeyPressedDown(event);
};
subscribeIdForPressedDown_ = RegistKeyEvent(HEADSETHOOK_KEY, true, pressedDownCallBack);
subscribeIdForPressedUp_ = RegistKeyEvent(HEADSETHOOK_KEY, false, pressedUpCallBack);
subscribeIdForMediaPauseDown_ = RegistKeyEvent(MEDIA_PLAY_PAUSE_KEY, true, pressedDownCallBack);
subscribeIdForMediaPausedUp_ = RegistKeyEvent(MEDIA_PLAY_PAUSE_KEY, false, pressedUpCallBack);
TELEPHONY_LOGI("pressDown = %{public}d, pressUp = %{public}d, pauseDown = %{public}d, pauseUp = %{public}d",
subscribeIdForPressedDown_, subscribeIdForPressedUp_, subscribeIdForMediaPauseDown_,
subscribeIdForMediaPausedUp_);
return true;
}
void CallWiredHeadSet::DeInit()
{
UnRegistKeyEvent(subscribeIdForPressedDown_);
UnRegistKeyEvent(subscribeIdForPressedUp_);
UnRegistKeyEvent(subscribeIdForMediaPauseDown_);
UnRegistKeyEvent(subscribeIdForMediaPausedUp_);
TELEPHONY_LOGI("CallWiredHeadSet UnRegisted KeyMute Pressed callback succeed");
}
std::shared_ptr<MMI::KeyOption> CallWiredHeadSet::InitOption(
const std::set<int32_t> &preKeys, int32_t finalKey, bool isFinalKeyDown, int32_t duration)
{
std::shared_ptr<MMI::KeyOption> keyOption = std::make_shared<MMI::KeyOption>();
keyOption->SetFinalKeyDown(isFinalKeyDown);
keyOption->SetFinalKey(finalKey);
keyOption->SetPreKeys(preKeys);
keyOption->SetFinalKeyDownDuration(duration);
return keyOption;
}
int32_t CallWiredHeadSet::RegistKeyEvent(int32_t keyCode, bool isFinalKeyDown, const WiredHeadSetCallback &callback)
{
std::set<int32_t> preKeys;
std::shared_ptr<MMI::KeyOption> keyOption = InitOption(preKeys, keyCode, isFinalKeyDown, 0);
if (keyCode == MMI::KeyEvent::KEYCODE_HEADSETHOOK) {
keyOption->SetPriority(MMI::SubscribePriority::PRIORITY_100);
}
int32_t subscribeId = MMI::InputManager::GetInstance()->SubscribeKeyEvent(keyOption, callback);
TELEPHONY_LOGI("keyCode: %{public}d, subscribeId: %{public}d", keyCode, subscribeId);
return subscribeId;
}
void CallWiredHeadSet::UnRegistKeyEvent(int32_t &subscribeId)
{
if (subscribeId >= 0) {
MMI::InputManager::GetInstance()->UnsubscribeKeyEvent(subscribeId);
subscribeId = INVALID_VALUE;
}
}
void CallWiredHeadSet::DealKeyPressedUp(std::shared_ptr<MMI::KeyEvent> event)
{
TELEPHONY_LOGI("received KeyMute Pressed Up event");
if (DelayedSingleton<AudioDeviceManager>::GetInstance()->IsWiredHeadsetConnected() == true) {
time_t currentTime = GetCurrentTimeMS();
if ((currentTime - downFirstTime_) < FINAL_KEY_DOWN_DURATION_TWO) {
DealKeyShortPressed();
} else if (!isProcessed_) {
DealKeyLongPressed();
}
}
downFirstTime_ = 0;
isProcessed_ = false;
}
void CallWiredHeadSet::DealKeyPressedDown(std::shared_ptr<MMI::KeyEvent> event)
{
TELEPHONY_LOGI("received KeyMute Pressed Down event");
if (isProcessed_) {
return;
}
if (DelayedSingleton<AudioDeviceManager>::GetInstance()->IsWiredHeadsetConnected() == true) {
time_t currentTime = GetCurrentTimeMS();
if (downFirstTime_ == 0) {
downFirstTime_ = GetCurrentTimeMS();
return;
}
if (!isProcessed_ && (currentTime - downFirstTime_ >= FINAL_KEY_DOWN_DURATION_TWO)) {
DealKeyLongPressed();
isProcessed_ = true;
}
}
}
void CallWiredHeadSet::DealKeyShortPressed()
{
sptr<CallBase> ringingCall = CallObjectManager::GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_RINGING);
if (ringingCall == nullptr) {
sptr<CallBase> holdCall = CallObjectManager::GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_HOLD);
sptr<CallBase> activeCall = CallObjectManager::GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_ACTIVE);
if (activeCall != nullptr && holdCall != nullptr) {
TELEPHONY_LOGI("DealKeyShortPressed UnHoldCall callid(%{public}d)", holdCall->GetCallID());
DelayedSingleton<CallControlManager>::GetInstance()->UnHoldCall(holdCall->GetCallID());
return;
}
sptr<CallBase> call = CallObjectManager::GetAudioLiveCall();
if (call != nullptr) {
bool isMuted = DelayedSingleton<AudioProxy>::GetInstance()->IsMicrophoneMute();
if (call->GetCallType() == CallType::TYPE_VOIP) {
isMuted = call->IsMuted();
}
TELEPHONY_LOGI("DealKeyShortPressed SetMuted isMuted(%{public}d)", (!isMuted));
DelayedSingleton<CallControlManager>::GetInstance()->SetMuted(!isMuted);
}
} else {
TELEPHONY_LOGI("DealKeyShortPressed AnswerCall callid(%{public}d)", ringingCall->GetCallID());
VideoStateType videoState = ringingCall->GetVideoStateType();
if (videoState != VideoStateType::TYPE_VOICE && videoState != VideoStateType::TYPE_VIDEO) {
TELEPHONY_LOGI("DealKeyShortPressed get original call type");
videoState = static_cast<VideoStateType>(ringingCall->GetOriginalCallType());
}
DelayedSingleton<CallControlManager>::GetInstance()->AnswerCall(
ringingCall->GetCallID(), static_cast<int32_t>(videoState));
}
}
void CallWiredHeadSet::DealKeyLongPressed()
{
sptr<CallBase> ringingCall = CallObjectManager::GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_RINGING);
if (ringingCall != nullptr) {
TELEPHONY_LOGI("DealKeyLongPressed RejectCall callid(%{public}d)", ringingCall->GetCallID());
ringingCall->RejectCall();
} else {
sptr<CallBase> foregroundCall = CallObjectManager::GetForegroundCall();
if (foregroundCall != nullptr) {
TelConferenceState confState = foregroundCall->GetTelConferenceState();
if (confState != TelConferenceState::TEL_CONFERENCE_IDLE) {
int32_t conferenceId = DelayedSingleton<ImsConference>::GetInstance()->GetMainCall();
TELEPHONY_LOGI("DealKeyLongPressed HangUpCall conferenceId(%{public}d)", conferenceId);
DelayedSingleton<CallControlManager>::GetInstance()->HangUpCall(conferenceId);
} else {
TELEPHONY_LOGI("DealKeyLongPressed HangUpCall callid(%{public}d)", foregroundCall->GetCallID());
foregroundCall->HangUpCall();
}
}
}
}
time_t CallWiredHeadSet::GetCurrentTimeMS()
{
std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> tpMicro
= std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
return tpMicro.time_since_epoch().count();
}
}
}