diff --git a/frameworks/native/inputmethod_ability/include/input_method_ability.h b/frameworks/native/inputmethod_ability/include/input_method_ability.h index 29629fce8b6ed488091b86478c9f8d57db44e873..d7cbc970bc66a830f4bf20e835c7589f3ea00e26 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_ability.h +++ b/frameworks/native/inputmethod_ability/include/input_method_ability.h @@ -182,6 +182,7 @@ private: std::mutex inputTypeLock_; InputType inputType_ = InputType::NONE; std::atomic isImeTerminating = false; + std::atomic_bool isShowAfterCreate_{ false }; }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp index c6a4cf98b171c6ef825611d8294813b59e17a99a..00bb421623ab8bec57bd84ae3128a6b5204100c0 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp @@ -32,6 +32,7 @@ #include "sys/prctl.h" #include "system_ability_definition.h" #include "tasks/task.h" +#include "tasks/task_imsa.h" #include "task_manager.h" namespace OHOS { @@ -436,6 +437,7 @@ int32_t InputMethodAbility::ShowKeyboardImplWithoutLock(int32_t cmdId) } return ShowPanel(panel, flag, Trigger::IMF); } + isShowAfterCreate_.store(true); IMSA_HILOGI("panel not create."); auto channel = GetInputDataChannelProxy(); if (channel != nullptr) { @@ -828,6 +830,11 @@ int32_t InputMethodAbility::CreatePanel(const std::shared_ptr(); + TaskManager::GetInstance().PostTask(task); + } return flag ? ErrorCode::NO_ERROR : ErrorCode::ERROR_OPERATE_PANEL; } @@ -865,7 +872,10 @@ int32_t InputMethodAbility::HidePanel(const std::shared_ptr &i IMSA_HILOGI("Current Ime is terminating, no need to hide keyboard."); return ErrorCode::NO_ERROR; } - + if (inputMethodPanel->GetPanelType() == PanelType::SOFT_KEYBOARD + && inputMethodPanel->GetPanelFlag() != PanelFlag::FLG_CANDIDATE_COLUMN) { + isShowAfterCreate_.store(false); + } std::lock_guard lock(keyboardCmdLock_); return HidePanel(inputMethodPanel, inputMethodPanel->GetPanelFlag(), Trigger::IME_APP); } @@ -951,6 +961,7 @@ InputAttribute InputMethodAbility::GetInputAttribute() int32_t InputMethodAbility::HideKeyboard(Trigger trigger) { + isShowAfterCreate_.store(false); InputMethodSyncTrace tracer("IMA_HideKeyboard"); if (imeListener_ == nullptr) { IMSA_HILOGE("imeListener_ is nullptr!"); diff --git a/services/include/peruser_session.h b/services/include/peruser_session.h index 14e3b4311c7e55c017eaaa814a52cf17a1b9f530..f9955c4e95641acce228fbe0d332bcc10359753d 100644 --- a/services/include/peruser_session.h +++ b/services/include/peruser_session.h @@ -64,9 +64,9 @@ enum class ImeEvent : uint32_t { enum class ImeAction : uint32_t { DO_NOTHING, HANDLE_STARTING_IME, - STOP_EXITING_IME, + FORCE_STOP_IME, STOP_READY_IME, - STOP_STARTING_IME, + START_IME_AFTER_FORCE_STOP_IME, DO_SET_CORE_AND_AGENT, DO_ACTION_IN_NULL_IME_DATA, DO_ACTION_IN_IME_EVENT_CONVERT_FAILED, @@ -236,9 +236,8 @@ private: bool StartCurrentIme(const std::shared_ptr &ime); bool StartNewIme(const std::shared_ptr &ime); bool StartInputService(const std::shared_ptr &ime); - bool ForceStopCurrentIme(bool isNeedWait = true); + bool ForceStopCurrentIme(); bool StopReadyCurrentIme(); - bool StopExitingCurrentIme(); bool HandleFirstStart(const std::shared_ptr &ime, bool isStopCurrentIme); bool HandleStartImeTimeout(const std::shared_ptr &ime); bool CheckInputTypeToStart(std::shared_ptr &imeToStart); @@ -262,13 +261,16 @@ private: static inline const std::map, std::pair> imeEventConverter_ = { { { ImeStatus::READY, ImeEvent::START_IME }, { ImeStatus::READY, ImeAction::DO_NOTHING } }, { { ImeStatus::STARTING, ImeEvent::START_IME }, { ImeStatus::STARTING, ImeAction::HANDLE_STARTING_IME } }, - { { ImeStatus::EXITING, ImeEvent::START_IME }, { ImeStatus::EXITING, ImeAction::STOP_EXITING_IME } }, + { { ImeStatus::EXITING, ImeEvent::START_IME }, + { ImeStatus::EXITING, ImeAction::START_IME_AFTER_FORCE_STOP_IME } }, { { ImeStatus::READY, ImeEvent::START_IME_TIMEOUT }, { ImeStatus::READY, ImeAction::DO_NOTHING } }, - { { ImeStatus::STARTING, ImeEvent::START_IME_TIMEOUT }, { ImeStatus::EXITING, ImeAction::STOP_EXITING_IME } }, - { { ImeStatus::EXITING, ImeEvent::START_IME_TIMEOUT }, { ImeStatus::EXITING, ImeAction::STOP_EXITING_IME } }, + { { ImeStatus::STARTING, ImeEvent::START_IME_TIMEOUT }, + { ImeStatus::EXITING, ImeAction::START_IME_AFTER_FORCE_STOP_IME } }, + { { ImeStatus::EXITING, ImeEvent::START_IME_TIMEOUT }, + { ImeStatus::EXITING, ImeAction::START_IME_AFTER_FORCE_STOP_IME } }, { { ImeStatus::READY, ImeEvent::STOP_IME }, { ImeStatus::EXITING, ImeAction::STOP_READY_IME } }, - { { ImeStatus::STARTING, ImeEvent::STOP_IME }, { ImeStatus::EXITING, ImeAction::STOP_STARTING_IME } }, - { { ImeStatus::EXITING, ImeEvent::STOP_IME }, { ImeStatus::EXITING, ImeAction::STOP_EXITING_IME } }, + { { ImeStatus::STARTING, ImeEvent::STOP_IME }, { ImeStatus::EXITING, ImeAction::FORCE_STOP_IME } }, + { { ImeStatus::EXITING, ImeEvent::STOP_IME }, { ImeStatus::EXITING, ImeAction::FORCE_STOP_IME } }, { { ImeStatus::READY, ImeEvent::SET_CORE_AND_AGENT }, { ImeStatus::READY, ImeAction::DO_NOTHING } }, { { ImeStatus::STARTING, ImeEvent::SET_CORE_AND_AGENT }, { ImeStatus::READY, ImeAction::DO_SET_CORE_AND_AGENT } }, diff --git a/services/src/peruser_session.cpp b/services/src/peruser_session.cpp index 4eea881becdf81daa3ef587fc3deea5ab8fde203..c171f1cf7b0621fd494264fed504016942029698 100644 --- a/services/src/peruser_session.cpp +++ b/services/src/peruser_session.cpp @@ -1535,7 +1535,7 @@ bool PerUserSession::StartCurrentIme(const std::shared_ptr &ime) } return StartInputService(ime); } - if (!StopExitingCurrentIme()) { + if (!ForceStopCurrentIme()) { return false; } return StartInputService(ime); @@ -1554,8 +1554,10 @@ bool PerUserSession::HandleStartImeTimeout(const std::shared_ptr & IMSA_HILOGW("ready when timeout"); return true; } - ForceStopCurrentIme(false); - return false; + if(!ForceStopCurrentIme()) { + return false; + } + return StartInputService(ime); } bool PerUserSession::StartNewIme(const std::shared_ptr &ime) @@ -1578,10 +1580,7 @@ bool PerUserSession::StopCurrentIme() if (action == ImeAction::STOP_READY_IME) { return StopReadyCurrentIme(); } - if (action == ImeAction::STOP_STARTING_IME) { - return ForceStopCurrentIme(); - } - return StopExitingCurrentIme(); + return ForceStopCurrentIme(); } bool PerUserSession::StopReadyCurrentIme() @@ -1614,31 +1613,21 @@ bool PerUserSession::StopReadyCurrentIme() return true; } -bool PerUserSession::StopExitingCurrentIme() +bool PerUserSession::ForceStopCurrentIme() { auto imeData = GetImeData(ImeType::IME); if (imeData == nullptr) { return true; } if (!ImeInfoInquirer::GetInstance().IsRunningIme(userId_, imeData->ime.first)) { - IMSA_HILOGD("already stop!"); - RemoveImeData(ImeType::IME, true); + IMSA_HILOGW("[%{public}s, %{public}s] already stop.", imeData->ime.first.c_str(), imeData->ime.second.c_str()); return true; } - return ForceStopCurrentIme(); -} - -bool PerUserSession::ForceStopCurrentIme(bool isNeedWait) -{ auto client = GetCurrentClient(); auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr; if (clientInfo != nullptr && clientInfo->bindImeType == ImeType::IME) { StopClientInput(clientInfo); } - auto imeData = GetImeData(ImeType::IME); - if (imeData == nullptr) { - return true; - } AAFwk::Want want; want.SetElementName(imeData->ime.first, imeData->ime.second); auto ret = AAFwk::AbilityManagerClient::GetInstance()->StopExtensionAbility( @@ -1648,9 +1637,6 @@ bool PerUserSession::ForceStopCurrentIme(bool isNeedWait) imeData->ime.first.c_str(), imeData->ime.second.c_str(), ret); return false; } - if (!isNeedWait) { - return true; - } WaitForCurrentImeStop(); if (ImeInfoInquirer::GetInstance().IsRunningIme(userId_, imeData->ime.first)) { IMSA_HILOGW("stop [%{public}s, %{public}s] timeout.", imeData->ime.first.c_str(), imeData->ime.second.c_str()); @@ -1682,22 +1668,16 @@ bool PerUserSession::HandleFirstStart(const std::shared_ptr &ime, int32_t PerUserSession::RestoreCurrentIme() { InputTypeManager::GetInstance().Set(false); - auto cfgIme = ImeInfoInquirer::GetInstance().GetImeToStart(userId_); + auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_); // may be null auto imeData = GetReadyImeData(ImeType::IME); if (imeData != nullptr && imeData->ime.first == cfgIme->bundleName && imeData->ime.second == cfgIme->extName) { return ErrorCode::NO_ERROR; } IMSA_HILOGD("need restore!"); - if (!StartIme(cfgIme)) { + if (!StartCurrentIme()) { IMSA_HILOGE("start ime failed!"); return ErrorCode::ERROR_IME_START_FAILED; } - SubProperty subProp = { .name = cfgIme->bundleName, .id = cfgIme->subName }; - auto subPropTemp = ImeInfoInquirer::GetInstance().GetCurrentSubtype(userId_); - if (subPropTemp != nullptr) { - subProp = *subPropTemp; - } - SwitchSubtype(subProp); return ErrorCode::NO_ERROR; } diff --git a/test/unittest/cpp_test/src/input_method_ability_test.cpp b/test/unittest/cpp_test/src/input_method_ability_test.cpp index f0effb6eda2edc2851ff556e5fdeabb6794a6fc9..91b1011baccba4a17ab633ac91b5628754c3c528 100644 --- a/test/unittest/cpp_test/src/input_method_ability_test.cpp +++ b/test/unittest/cpp_test/src/input_method_ability_test.cpp @@ -336,6 +336,45 @@ HWTEST_F(InputMethodAbilityTest, testStartInputWithoutPanel, TestSize.Level0) EXPECT_EQ(ret, ErrorCode::NO_ERROR); } +/** +* @tc.name: testStartInputBeforeCreatePanel +* @tc.desc: InputMethodAbility StartInput before create panel +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(InputMethodAbilityTest, testStartInputBeforeCreatePanel, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbilityTest testStartInputBeforeCreatePanel start."); + inputMethodAbility_->SetImeListener(std::make_shared()); + sptr channelStub = new InputDataChannelStub(); + InputClientInfo clientInfo; + clientInfo.channel = channelStub; + clientInfo.isShowKeyboard = true; + InputMethodAbilityTest::showKeyboard_ = false; + auto ret = inputMethodAbility_->StartInput(clientInfo, false); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + std::unique_lock lock(InputMethodAbilityTest::imeListenerCallbackLock_); + InputMethodAbilityTest::imeListenerCv_.wait_for( + lock, std::chrono::seconds(DEALY_TIME), [] { return InputMethodAbilityTest::showKeyboard_; }); + ASSERT_FALSE(InputMethodAbilityTest::showKeyboard_); + { + AccessScope scope(currentImeTokenId_, currentImeUid_); + std::shared_ptr softKeyboardPanel = nullptr; + PanelInfo panelInfo = { .panelType = SOFT_KEYBOARD, .panelFlag = FLG_FIXED }; + ret = inputMethodAbility_->CreatePanel(nullptr, panelInfo, softKeyboardPanel); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + } + std::unique_lock lock1(InputMethodAbilityTest::imeListenerCallbackLock_); + InputMethodAbilityTest::imeListenerCv_.wait_for( + lock1, std::chrono::seconds(DEALY_TIME), [] { return InputMethodAbilityTest::showKeyboard_; }); + EXPECT_TRUE(InputMethodAbilityTest::showKeyboard_); + + ret = inputMethodAbility_->StopInput(channelStub->AsObject()); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + ret = inputMethodAbility_->DestroyPanel(softKeyboardPanel1); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); +} + /** * @tc.name: testHideKeyboardSelf * @tc.desc: InputMethodAbility HideKeyboardSelf