1 /*
2 * Copyright (c) 2025 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 "cj_inputmethod_extension.h"
17 #include "ability_handler.h"
18 #include "configuration_utils.h"
19 #include "global.h"
20 #include "inputmethod_extension_ability_service_impl.h"
21 #include "inputmethod_trace.h"
22 #include "iservice_registry.h"
23 #include "system_ability_definition.h"
24 #include "task_manager.h"
25 #include "tasks/task_ams.h"
26 #include "tasks/task_imsa.h"
27
28 namespace OHOS {
29 namespace AbilityRuntime {
30
31 CjInputMethodExtension *CjInputMethodExtension::cjInputMethodExtension = nullptr;
32 using namespace OHOS::AppExecFwk;
33 using namespace OHOS::MiscServices;
34
35 constexpr int32_t SUCCESS_CODE = 0;
36
OHOS_ABILITY_CjInputMethodExtension()37 extern "C" __attribute__((visibility("default"))) InputMethodExtension *OHOS_ABILITY_CjInputMethodExtension()
38 {
39 return new (std::nothrow) CjInputMethodExtension();
40 }
41
CjInputMethodExtension()42 CjInputMethodExtension::CjInputMethodExtension() { }
43
~CjInputMethodExtension()44 CjInputMethodExtension::~CjInputMethodExtension()
45 {
46 IMSA_HILOGD("~CjInputMethodExtension");
47 auto context = GetContext();
48 if (context != nullptr) {
49 context->Unbind();
50 }
51 cjObj_.Destroy();
52 }
53
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)54 void CjInputMethodExtension::Init(const std::shared_ptr<AbilityLocalRecord> &record,
55 const std::shared_ptr<OHOSApplication> &application, std::shared_ptr<AbilityHandler> &handler,
56 const sptr<IRemoteObject> &token)
57 {
58 IMSA_HILOGD("initalize CjInputMethodExtension");
59 InputMethodExtension::Init(record, application, handler, token);
60 // init and bindContext
61 int32_t ret = cjObj_.Init(abilityInfo_->name, this);
62 if (ret != SUCCESS_CODE) {
63 IMSA_HILOGE("initalization failed");
64 return;
65 }
66 handler_ = handler;
67 InitDisplayCache();
68 ListenWindowManager();
69 IMSA_HILOGI("initalize success");
70 }
71
ListenWindowManager()72 void CjInputMethodExtension::ListenWindowManager()
73 {
74 IMSA_HILOGD("register window manager service listener.");
75 auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
76 if (abilityManager == nullptr) {
77 IMSA_HILOGE("failed to get SaMgr!");
78 return;
79 }
80
81 auto cjInputMethodExtension = std::static_pointer_cast<CjInputMethodExtension>(shared_from_this());
82 displayListener_ = sptr<CjInputMethodExtensionDisplayListener>::MakeSptr(cjInputMethodExtension);
83 if (displayListener_ == nullptr) {
84 IMSA_HILOGE("failed to create display listener!");
85 return;
86 }
87
88 auto listener = sptr<SystemAbilityStatusChangeListener>::MakeSptr(displayListener_);
89 if (listener == nullptr) {
90 IMSA_HILOGE("failed to create status change listener!");
91 return;
92 }
93
94 auto ret = abilityManager->SubscribeSystemAbility(WINDOW_MANAGER_SERVICE_ID, listener);
95 if (ret != 0) {
96 IMSA_HILOGE("failed to subscribe system ability, ret: %{public}d!", ret);
97 }
98 }
99
OnConfigurationUpdated(const AppExecFwk::Configuration & config)100 void CjInputMethodExtension::OnConfigurationUpdated(const AppExecFwk::Configuration &config) { }
101
ConfigurationUpdated()102 void CjInputMethodExtension::ConfigurationUpdated() { }
103
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)104 void CjInputMethodExtension::SystemAbilityStatusChangeListener::OnAddSystemAbility(
105 int32_t systemAbilityId, const std::string &deviceId)
106 {
107 IMSA_HILOGD("add systemAbilityId: %{public}d.", systemAbilityId);
108 if (systemAbilityId == WINDOW_MANAGER_SERVICE_ID) {
109 Rosen::DisplayManager::GetInstance().RegisterDisplayListener(listener_);
110 }
111 }
112
OnStart(const AAFwk::Want & want)113 void CjInputMethodExtension::OnStart(const AAFwk::Want &want)
114 {
115 auto task = std::make_shared<TaskAmsInit>();
116 TaskManager::GetInstance().PostTask(task);
117 InputMethodAbility::GetInstance().InitConnect();
118 StartAsync("OnStart", static_cast<int32_t>(TraceTaskId::ONSTART_EXTENSION));
119 StartAsync("Extension::OnStart", static_cast<int32_t>(TraceTaskId::ONSTART_MIDDLE_EXTENSION));
120 Extension::OnStart(want);
121 FinishAsync("Extension::OnStart", static_cast<int32_t>(TraceTaskId::ONSTART_MIDDLE_EXTENSION));
122 IMSA_HILOGI("CjInputMethodExtension OnStart begin.");
123 StartAsync("onCreate", static_cast<int32_t>(TraceTaskId::ONCREATE_EXTENSION));
124 cjObj_.OnCreate(want);
125 FinishAsync("onCreate", static_cast<int32_t>(TraceTaskId::ONCREATE_EXTENSION));
126 TaskManager::GetInstance().PostTask(std::make_shared<TaskImsaSetCoreAndAgent>());
127 IMSA_HILOGI("ime bind imf");
128 FinishAsync("OnStart", static_cast<int32_t>(TraceTaskId::ONSTART_EXTENSION));
129 TaskManager::GetInstance().Complete(task->GetSeqId());
130 }
131
InitDisplayCache()132 void CjInputMethodExtension::InitDisplayCache()
133 {
134 auto foldStatus = Rosen::DisplayManager::GetInstance().GetFoldStatus();
135 auto displayPtr = Rosen::DisplayManager::GetInstance().GetDefaultDisplaySync();
136 if (displayPtr == nullptr) {
137 IMSA_HILOGE("displayPtr is null");
138 return;
139 }
140 cacheDisplay_.SetCacheDisplay(
141 displayPtr->GetWidth(), displayPtr->GetHeight(), displayPtr->GetRotation(), foldStatus);
142 }
143
OnStop()144 void CjInputMethodExtension::OnStop()
145 {
146 InputMethodExtension::OnStop();
147 IMSA_HILOGI("CjInputMethodExtension OnStop start.");
148 cjObj_.OnDestroy();
149 auto context = GetContext();
150 if (context == nullptr) {
151 IMSA_HILOGE("context is invalid!");
152 return;
153 }
154 bool ret = ConnectionManager::GetInstance().DisconnectCaller(context->GetToken());
155 if (ret) {
156 IMSA_HILOGI("the input method extension connection is not disconnected.");
157 }
158 IMSA_HILOGI("CjInputMethodExtension OnStop end.");
159 }
160
OnConnect(const AAFwk::Want & want)161 sptr<IRemoteObject> CjInputMethodExtension::OnConnect(const AAFwk::Want &want)
162 {
163 IMSA_HILOGI("CjInputMethodExtension OnConnect start.");
164 Extension::OnConnect(want);
165 auto remoteObj = new (std::nothrow) InputMethodExtensionAbilityServiceImpl();
166 if (remoteObj == nullptr) {
167 IMSA_HILOGE("failed to create InputMethodExtensionAbilityServiceImpl!");
168 return nullptr;
169 }
170 return remoteObj;
171 }
172
OnDisconnect(const AAFwk::Want & want)173 void CjInputMethodExtension::OnDisconnect(const AAFwk::Want &want) { }
174
OnCommand(const AAFwk::Want & want,bool restart,int startId)175 void CjInputMethodExtension::OnCommand(const AAFwk::Want &want, bool restart, int startId) { }
176
OnCreate(Rosen::DisplayId displayId)177 void CjInputMethodExtension::OnCreate(Rosen::DisplayId displayId)
178 {
179 IMSA_HILOGD("enter");
180 }
181
OnDestroy(Rosen::DisplayId displayId)182 void CjInputMethodExtension::OnDestroy(Rosen::DisplayId displayId)
183 {
184 IMSA_HILOGD("exit");
185 }
186
CheckNeedAdjustKeyboard(Rosen::DisplayId displayId)187 void CjInputMethodExtension::CheckNeedAdjustKeyboard(Rosen::DisplayId displayId)
188 {
189 auto displayPtr = Rosen::DisplayManager::GetInstance().GetDefaultDisplaySync();
190 if (displayPtr == nullptr) {
191 return;
192 }
193 auto defaultDisplayId = displayPtr->GetId();
194 if (displayId != defaultDisplayId) {
195 return;
196 }
197 auto foldStatus = Rosen::DisplayManager::GetInstance().GetFoldStatus();
198 auto width = displayPtr->GetWidth();
199 auto height = displayPtr->GetHeight();
200 auto rotation = displayPtr->GetRotation();
201 IMSA_HILOGD("display width: %{public}d, height: %{public}d, rotation: %{public}d, foldStatus: %{public}d",
202 width, height, rotation, foldStatus);
203 if (!cacheDisplay_.IsEmpty()) {
204 if ((cacheDisplay_.displayWidth != width ||
205 cacheDisplay_.displayHeight != height) &&
206 cacheDisplay_.displayFoldStatus == foldStatus &&
207 cacheDisplay_.displayRotation == rotation) {
208 InputMethodAbility::GetInstance().AdjustKeyboard();
209 }
210 }
211 cacheDisplay_.SetCacheDisplay(width, height, rotation, foldStatus);
212 }
213
OnChange(Rosen::DisplayId displayId)214 void CjInputMethodExtension::OnChange(Rosen::DisplayId displayId)
215 {
216 IMSA_HILOGD("displayId: %{public}" PRIu64 "", displayId);
217 auto context = GetContext();
218 if (context == nullptr) {
219 IMSA_HILOGE("context is invalid!");
220 return;
221 }
222
223 auto contextConfig = context->GetConfiguration();
224 if (contextConfig == nullptr) {
225 IMSA_HILOGE("configuration is invalid!");
226 return;
227 }
228
229 bool isConfigChanged = false;
230 auto configUtils = std::make_shared<ConfigurationUtils>();
231 configUtils->UpdateDisplayConfig(displayId, contextConfig, context->GetResourceManager(), isConfigChanged);
232 IMSA_HILOGD("OnChange, isConfigChanged: %{public}d, Config after update: %{public}s.", isConfigChanged,
233 contextConfig->GetName().c_str());
234
235 if (!isConfigChanged) {
236 return;
237 }
238 auto inputMethodExtension = std::static_pointer_cast<CjInputMethodExtension>(shared_from_this());
239 auto task = [inputMethodExtension]() {
240 if (inputMethodExtension) {
241 inputMethodExtension->ConfigurationUpdated();
242 }
243 };
244 if (handler_ != nullptr) {
245 handler_->PostTask(task, "CjInputMethodExtension:OnChange", 0, AppExecFwk::EventQueue::Priority::VIP);
246 }
247 }
248 } // namespace AbilityRuntime
249 } // namespace OHOS
250