• 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 "ime_system_channel.h"
17 
18 #include "global.h"
19 #include "input_method_agent_proxy.h"
20 #include "input_method_controller.h"
21 #include "input_method_system_ability_proxy.h"
22 #include "iservice_registry.h"
23 #include "on_demand_start_stop_sa.h"
24 #include "system_ability_definition.h"
25 #include "system_cmd_channel_service_impl.h"
26 
27 namespace OHOS {
28 namespace MiscServices {
29 constexpr const char *SMART_MENU_METADATA_NAME = "ohos.extension.smart_menu";
30 std::mutex ImeSystemCmdChannel::instanceLock_;
31 sptr<ImeSystemCmdChannel> ImeSystemCmdChannel::instance_;
ImeSystemCmdChannel()32 ImeSystemCmdChannel::ImeSystemCmdChannel() { }
33 
~ImeSystemCmdChannel()34 ImeSystemCmdChannel::~ImeSystemCmdChannel() { }
35 
GetInstance()36 sptr<ImeSystemCmdChannel> ImeSystemCmdChannel::GetInstance()
37 {
38     if (instance_ == nullptr) {
39         std::lock_guard<std::mutex> autoLock(instanceLock_);
40         if (instance_ == nullptr) {
41             IMSA_HILOGD("System IMC instance_ is nullptr.");
42             instance_ = new (std::nothrow) ImeSystemCmdChannel();
43             if (instance_ == nullptr) {
44                 IMSA_HILOGE("failed to create ImeSystemCmdChannel!");
45                 return instance_;
46             }
47         }
48     }
49     return instance_;
50 }
51 
GetSystemAbilityProxy()52 sptr<IInputMethodSystemAbility> ImeSystemCmdChannel::GetSystemAbilityProxy()
53 {
54     std::lock_guard<std::mutex> lock(abilityLock_);
55     if (systemAbility_ != nullptr) {
56         return systemAbility_;
57     }
58     IMSA_HILOGI("get input method service proxy.");
59     auto systemAbility = OnDemandStartStopSa::GetInputMethodSystemAbility();
60     if (systemAbility == nullptr) {
61         IMSA_HILOGE("systemAbility is nullptr!");
62         return nullptr;
63     }
64     if (deathRecipient_ == nullptr) {
65         deathRecipient_ = new (std::nothrow) InputDeathRecipient();
66         if (deathRecipient_ == nullptr) {
67             IMSA_HILOGE("create death recipient failed!");
68             return nullptr;
69         }
70     }
71     deathRecipient_->SetDeathRecipient([this](const wptr<IRemoteObject> &remote) {
72         OnRemoteSaDied(remote);
73     });
74     if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) {
75         IMSA_HILOGE("failed to add death recipient!");
76         return nullptr;
77     }
78     systemAbility_ = iface_cast<IInputMethodSystemAbility>(systemAbility);
79     return systemAbility_;
80 }
81 // LCOV_EXCL_START
OnRemoteSaDied(const wptr<IRemoteObject> & remote)82 void ImeSystemCmdChannel::OnRemoteSaDied(const wptr<IRemoteObject> &remote)
83 {
84     IMSA_HILOGI("input method service death.");
85     {
86         std::lock_guard<std::mutex> lock(abilityLock_);
87         systemAbility_ = nullptr;
88     }
89     ClearSystemCmdAgent();
90 }
91 // LCOV_EXCL_STOP
ConnectSystemCmd(const sptr<OnSystemCmdListener> & listener)92 int32_t ImeSystemCmdChannel::ConnectSystemCmd(const sptr<OnSystemCmdListener> &listener)
93 {
94     IMSA_HILOGD("start.");
95     SetSystemCmdListener(listener);
96     if (isSystemCmdConnect_.load()) {
97         IMSA_HILOGD("in connected state.");
98         return ErrorCode::NO_ERROR;
99     }
100     return RunConnectSystemCmd();
101 }
102 
RunConnectSystemCmd()103 int32_t ImeSystemCmdChannel::RunConnectSystemCmd()
104 {
105     if (systemChannelStub_ == nullptr) {
106         std::lock_guard<decltype(systemChannelMutex_)> lock(systemChannelMutex_);
107         if (systemChannelStub_ == nullptr) {
108             systemChannelStub_ = new (std::nothrow) SystemCmdChannelServiceImpl();
109         }
110         if (systemChannelStub_ == nullptr) {
111             IMSA_HILOGE("channel is nullptr!");
112             return ErrorCode::ERROR_NULL_POINTER;
113         }
114     }
115 
116     auto proxy = GetSystemAbilityProxy();
117     if (proxy == nullptr) {
118         IMSA_HILOGE("proxy is nullptr!");
119         return ErrorCode::ERROR_SERVICE_START_FAILED;
120     }
121     sptr<IRemoteObject> agent = nullptr;
122     static constexpr uint32_t RETRY_INTERVAL = 100;
123     static constexpr uint32_t BLOCK_RETRY_TIMES = 5;
124     if (!BlockRetry(RETRY_INTERVAL, BLOCK_RETRY_TIMES, [&agent, this, proxy]() -> bool {
125             int32_t ret = proxy->ConnectSystemCmd(systemChannelStub_->AsObject(), agent);
126             return ret == ErrorCode::NO_ERROR;
127         })) {
128         IMSA_HILOGE("failed to connect system cmd!");
129         return ErrorCode::ERROR_SYSTEM_CMD_CHANNEL_ERROR;
130     }
131     OnConnectCmdReady(agent);
132     IMSA_HILOGI("connect system cmd success.");
133     return ErrorCode::NO_ERROR;
134 }
135 
OnConnectCmdReady(const sptr<IRemoteObject> & agentObject)136 void ImeSystemCmdChannel::OnConnectCmdReady(const sptr<IRemoteObject> &agentObject)
137 {
138     if (agentObject == nullptr) {
139         IMSA_HILOGE("agentObject is nullptr!");
140         return;
141     }
142     isSystemCmdConnect_.store(true);
143     std::lock_guard<std::mutex> autoLock(systemAgentLock_);
144     if (systemAgent_ != nullptr) {
145         IMSA_HILOGD("agent has already been set.");
146         return;
147     }
148     systemAgent_ = new (std::nothrow) InputMethodAgentProxy(agentObject);
149     if (agentDeathRecipient_ == nullptr) {
150         agentDeathRecipient_ = new (std::nothrow) InputDeathRecipient();
151         if (agentDeathRecipient_ == nullptr) {
152             IMSA_HILOGE("create death recipient failed!");
153             return;
154         }
155     }
156     agentDeathRecipient_->SetDeathRecipient([this](const wptr<IRemoteObject> &remote) {
157         OnSystemCmdAgentDied(remote);
158     });
159     if (!agentObject->AddDeathRecipient(agentDeathRecipient_)) {
160         IMSA_HILOGE("failed to add death recipient!");
161         return;
162     }
163 }
164 
OnSystemCmdAgentDied(const wptr<IRemoteObject> & remote)165 void ImeSystemCmdChannel::OnSystemCmdAgentDied(const wptr<IRemoteObject> &remote)
166 {
167     IMSA_HILOGI("input method death.");
168     ClearSystemCmdAgent();
169     RunConnectSystemCmd();
170 }
171 
GetSystemCmdAgent()172 sptr<IInputMethodAgent> ImeSystemCmdChannel::GetSystemCmdAgent()
173 {
174     IMSA_HILOGD("GetSystemCmdAgent start.");
175     std::lock_guard<std::mutex> autoLock(systemAgentLock_);
176     return systemAgent_;
177 }
178 
SetSystemCmdListener(const sptr<OnSystemCmdListener> & listener)179 void ImeSystemCmdChannel::SetSystemCmdListener(const sptr<OnSystemCmdListener> &listener)
180 {
181     std::lock_guard<std::mutex> lock(systemCmdListenerLock_);
182     systemCmdListener_ = std::move(listener);
183 }
184 
GetSystemCmdListener()185 sptr<OnSystemCmdListener> ImeSystemCmdChannel::GetSystemCmdListener()
186 {
187     std::lock_guard<std::mutex> lock(systemCmdListenerLock_);
188     return systemCmdListener_;
189 }
190 
ClearSystemCmdAgent()191 void ImeSystemCmdChannel::ClearSystemCmdAgent()
192 {
193     {
194         std::lock_guard<std::mutex> autoLock(systemAgentLock_);
195         systemAgent_ = nullptr;
196     }
197     isSystemCmdConnect_.store(false);
198 }
199 
ReceivePrivateCommand(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)200 int32_t ImeSystemCmdChannel::ReceivePrivateCommand(
201     const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
202 {
203     auto cmdlistener = GetSystemCmdListener();
204     if (cmdlistener == nullptr) {
205         IMSA_HILOGE("cmdlistener is nullptr!");
206         return ErrorCode::ERROR_EX_NULL_POINTER;
207     }
208     cmdlistener->ReceivePrivateCommand(privateCommand);
209     return ErrorCode::NO_ERROR;
210 }
211 // LCOV_EXCL_START
SendPrivateCommand(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)212 int32_t ImeSystemCmdChannel::SendPrivateCommand(const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
213 {
214     IMSA_HILOGD("start.");
215     if (TextConfig::IsSystemPrivateCommand(privateCommand)) {
216         if (!TextConfig::IsPrivateCommandValid(privateCommand)) {
217             IMSA_HILOGE("invalid private command size!");
218             return ErrorCode::ERROR_INVALID_PRIVATE_COMMAND_SIZE;
219         }
220         auto agent = GetSystemCmdAgent();
221         if (agent == nullptr) {
222             IMSA_HILOGE("agent is nullptr!");
223             return ErrorCode::ERROR_CLIENT_NOT_BOUND;
224         }
225         Value value(privateCommand);
226         return agent->SendPrivateCommand(value);
227     }
228     return ErrorCode::ERROR_INVALID_PRIVATE_COMMAND;
229 }
230 // LCOV_EXCL_STOP
NotifyPanelStatus(const SysPanelStatus & sysPanelStatus)231 int32_t ImeSystemCmdChannel::NotifyPanelStatus(const SysPanelStatus &sysPanelStatus)
232 {
233     auto listener = GetSystemCmdListener();
234     if (listener == nullptr) {
235         IMSA_HILOGE("listener is nullptr!");
236         return ErrorCode::ERROR_NULL_POINTER;
237     }
238     listener->NotifyPanelStatus(sysPanelStatus);
239     return ErrorCode::NO_ERROR;
240 }
241 
GetSmartMenuCfg()242 std::string ImeSystemCmdChannel::GetSmartMenuCfg()
243 {
244     std::shared_ptr<Property> defaultIme = nullptr;
245     int32_t ret = GetDefaultImeCfg(defaultIme);
246     if (ret != ErrorCode::NO_ERROR || defaultIme == nullptr) {
247         IMSA_HILOGE("failed to GetDefaultInputMethod!");
248         return "";
249     }
250     BundleMgrClient client;
251     BundleInfo bundleInfo;
252     if (!client.GetBundleInfo(defaultIme->name, BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo)) {
253         IMSA_HILOGE("failed to GetBundleInfo!");
254         return "";
255     }
256     ExtensionAbilityInfo extInfo;
257     GetExtensionInfo(bundleInfo.extensionInfos, extInfo);
258     std::vector<std::string> profiles;
259     if (!client.GetResConfigFile(extInfo, SMART_MENU_METADATA_NAME, profiles) || profiles.empty()) {
260         IMSA_HILOGE("failed to GetResConfigFile!");
261         return "";
262     }
263     return profiles[0];
264 }
265 // LCOV_EXCL_START
GetExtensionInfo(std::vector<ExtensionAbilityInfo> extensionInfos,ExtensionAbilityInfo & extInfo)266 void ImeSystemCmdChannel::GetExtensionInfo(
267     std::vector<ExtensionAbilityInfo> extensionInfos, ExtensionAbilityInfo &extInfo)
268 {
269     for (size_t i = 0; i < extensionInfos.size(); i++) {
270         auto metadata = extensionInfos[i].metadata;
271         for (size_t j = 0; j < metadata.size(); j++) {
272             if (metadata[j].name == SMART_MENU_METADATA_NAME) {
273                 extInfo = extensionInfos[i];
274                 return;
275             }
276         }
277     }
278 }
279 // LCOV_EXCL_STOP
GetDefaultImeCfg(std::shared_ptr<Property> & property)280 int32_t ImeSystemCmdChannel::GetDefaultImeCfg(std::shared_ptr<Property> &property)
281 {
282     IMSA_HILOGD("InputMethodAbility::GetDefaultImeCfg start.");
283     auto proxy = GetSystemAbilityProxy();
284     if (proxy == nullptr) {
285         IMSA_HILOGE("proxy is nullptr!");
286         return ErrorCode::ERROR_NULL_POINTER;
287     }
288     Property prop;
289     auto ret = proxy->GetDefaultInputMethod(prop, true);
290     if (ret != ErrorCode::NO_ERROR) {
291         return ret;
292     }
293     property = std::make_shared<Property>(prop);
294     return ret;
295 }
296 } // namespace MiscServices
297 } // namespace OHOS