1/*
2 * Copyright (C) 2022 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 "input_method_system_ability_stub.h"
17
18#include <chrono>
19#include <cinttypes>
20#include <memory>
21
22#include "element_name.h"
23#include "input_client_proxy.h"
24#include "input_method_core_proxy.h"
25#include "ipc_skeleton.h"
26#include "itypes_util.h"
27#include "xcollie/xcollie.h"
28#include "xcollie/xcollie_define.h"
29namespace OHOS {
30namespace MiscServices {
31using namespace std::chrono;
32using namespace HiviewDFX;
33constexpr uint32_t FATAL_TIMEOUT = 30;    // 30s
34constexpr int64_t WARNING_TIMEOUT = 5000; // 5s
35int32_t InputMethodSystemAbilityStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
36    MessageOption &option)
37{
38    if (code != static_cast<uint32_t>(InputMethodInterfaceCode::RELEASE_INPUT)) {
39        IMSA_HILOGI("IMSA, code = %{public}u, callingPid/Uid/timestamp: %{public}d/%{public}d/%{public}lld", code,
40            IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(),
41            std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
42                .count());
43    }
44    std::u16string remoteDescriptor = data.ReadInterfaceToken();
45    if (remoteDescriptor != IInputMethodSystemAbility::GetDescriptor()) {
46        IMSA_HILOGE("%{public}s descriptor failed!", __func__);
47        return ErrorCode::ERROR_STATUS_UNKNOWN_TRANSACTION;
48    }
49    if (code >= static_cast<uint32_t>(InputMethodInterfaceCode::IMS_CMD_BEGIN) &&
50        code < static_cast<uint32_t>(InputMethodInterfaceCode::IMS_CMD_END)) {
51        // service reboot when timeout 30s
52        auto id = XCollie::GetInstance().SetTimer("IMSA_API[" + std::to_string(code) + "]", FATAL_TIMEOUT, nullptr,
53            nullptr, XCOLLIE_FLAG_DEFAULT);
54        int64_t startPoint = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
55        auto ret = (this->*HANDLERS[code])(data, reply);
56        int64_t costTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count() - startPoint;
57        // log warning when timeout 5s
58        if (costTime > WARNING_TIMEOUT) {
59            IMSA_HILOGW("code: %{public}d, pid: %{public}d, uid: %{public}d, cost: %{public}" PRId64 "", code,
60                IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), costTime);
61        }
62        XCollie::GetInstance().CancelTimer(id);
63        return ret;
64    } else {
65        IMSA_HILOGE("code error, code = %{public}u, callingPid: %{public}d, callingUid: %{public}d.", code,
66            IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
67        return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
68    }
69}
70
71int32_t InputMethodSystemAbilityStub::StartInputOnRemote(MessageParcel &data, MessageParcel &reply)
72{
73    InputClientInfo clientInfo;
74    sptr<IRemoteObject> client = nullptr;
75    if (!ITypesUtil::Unmarshal(data, clientInfo, client, clientInfo.channel)) {
76        IMSA_HILOGE("read clientInfo failed!");
77        return ErrorCode::ERROR_EX_PARCELABLE;
78    }
79    clientInfo.client = iface_cast<IInputClient>(client);
80    sptr<IRemoteObject> agent = nullptr;
81    int32_t ret = StartInput(clientInfo, agent);
82    return reply.WriteInt32(ret) && reply.WriteRemoteObject(agent) ? ErrorCode::NO_ERROR
83                                                                   : ErrorCode::ERROR_EX_PARCELABLE;
84}
85
86int32_t InputMethodSystemAbilityStub::ShowCurrentInputOnRemote(MessageParcel &data, MessageParcel &reply)
87{
88    int32_t ret = ShowCurrentInput();
89    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
90}
91
92int32_t InputMethodSystemAbilityStub::HideCurrentInputOnRemote(MessageParcel &data, MessageParcel &reply)
93{
94    int32_t ret = HideCurrentInput();
95    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
96}
97
98int32_t InputMethodSystemAbilityStub::StopInputSessionOnRemote(MessageParcel &data, MessageParcel &reply)
99{
100    int32_t ret = StopInputSession();
101    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
102}
103
104int32_t InputMethodSystemAbilityStub::ShowInputOnRemote(MessageParcel &data, MessageParcel &reply)
105{
106    auto clientObject = data.ReadRemoteObject();
107    if (clientObject == nullptr) {
108        IMSA_HILOGE("clientObject is nullptr!");
109        return ErrorCode::ERROR_EX_PARCELABLE;
110    }
111    int32_t ret = ShowInput(iface_cast<IInputClient>(clientObject));
112    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
113}
114
115int32_t InputMethodSystemAbilityStub::HideInputOnRemote(MessageParcel &data, MessageParcel &reply)
116{
117    auto clientObject = data.ReadRemoteObject();
118    if (clientObject == nullptr) {
119        IMSA_HILOGE("clientObject is nullptr!");
120        return ErrorCode::ERROR_EX_PARCELABLE;
121    }
122    int32_t ret = HideInput(iface_cast<IInputClient>(clientObject));
123    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
124}
125
126int32_t InputMethodSystemAbilityStub::ReleaseInputOnRemote(MessageParcel &data, MessageParcel &reply)
127{
128    auto clientObject = data.ReadRemoteObject();
129    if (clientObject == nullptr) {
130        IMSA_HILOGE("clientObject is nullptr!");
131        return ErrorCode::ERROR_EX_PARCELABLE;
132    }
133    int32_t ret = ReleaseInput(iface_cast<IInputClient>(clientObject));
134    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
135}
136
137int32_t InputMethodSystemAbilityStub::RequestShowInputOnRemote(MessageParcel &data, MessageParcel &reply)
138{
139    return reply.WriteInt32(RequestShowInput()) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
140}
141
142int32_t InputMethodSystemAbilityStub::RequestHideInputOnRemote(MessageParcel &data, MessageParcel &reply)
143{
144    return reply.WriteInt32(RequestHideInput()) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
145}
146
147int32_t InputMethodSystemAbilityStub::DisplayOptionalInputMethodOnRemote(MessageParcel &data, MessageParcel &reply)
148{
149    int32_t ret = DisplayOptionalInputMethod();
150    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
151}
152
153int32_t InputMethodSystemAbilityStub::SetCoreAndAgentOnRemote(MessageParcel &data, MessageParcel &reply)
154{
155    auto coreObject = data.ReadRemoteObject();
156    if (coreObject == nullptr) {
157        IMSA_HILOGE("coreObject is nullptr!");
158        return ErrorCode::ERROR_EX_PARCELABLE;
159    }
160    auto agentObject = data.ReadRemoteObject();
161    if (agentObject == nullptr) {
162        IMSA_HILOGE("agentObject is nullptr!");
163        return ErrorCode::ERROR_EX_PARCELABLE;
164    }
165    int32_t ret = SetCoreAndAgent(iface_cast<IInputMethodCore>(coreObject), agentObject);
166    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
167}
168
169int32_t InputMethodSystemAbilityStub::GetDefaultInputMethodOnRemote(MessageParcel &data, MessageParcel &reply)
170{
171    std::shared_ptr<Property> prop = std::make_shared<Property>();
172    bool isBrief = false;
173    auto ret = data.ReadBool(isBrief);
174    if (!ret) {
175        IMSA_HILOGE("read isBrief failed!");
176    }
177    ret = GetDefaultInputMethod(prop, isBrief);
178    if (prop == nullptr) {
179        return ErrorCode::ERROR_EX_PARCELABLE;
180    }
181    return ITypesUtil::Marshal(reply, ret, *prop) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
182}
183
184int32_t InputMethodSystemAbilityStub::IsDefaultImeSetOnRemote(MessageParcel &data, MessageParcel &reply)
185{
186    return ITypesUtil::Marshal(reply, ErrorCode::NO_ERROR, IsDefaultImeSet()) ? ErrorCode::NO_ERROR
187                                                                           : ErrorCode::ERROR_EX_PARCELABLE;
188}
189
190int32_t InputMethodSystemAbilityStub::EnableImeOnRemote(MessageParcel &data, MessageParcel &reply)
191{
192    std::string bundleName;
193    if (!ITypesUtil::Unmarshal(data, bundleName)) {
194        IMSA_HILOGE("unmarshal failed!");
195        return ErrorCode::ERROR_EX_PARCELABLE;
196    }
197    return ITypesUtil::Marshal(reply, ErrorCode::NO_ERROR, EnableIme(bundleName)) ? ErrorCode::NO_ERROR
198                                                                        : ErrorCode::ERROR_EX_PARCELABLE;
199}
200
201int32_t InputMethodSystemAbilityStub::GetInputMethodConfigOnRemote(MessageParcel &data, MessageParcel &reply)
202{
203    OHOS::AppExecFwk::ElementName inputMethodConfig;
204    auto ret = GetInputMethodConfig(inputMethodConfig);
205    IMSA_HILOGD("GetInputMethodConfigOnRemote inputMethodConfig is %{public}s, %{public}s",
206        inputMethodConfig.GetBundleName().c_str(), inputMethodConfig.GetAbilityName().c_str());
207    return ITypesUtil::Marshal(reply, ret, inputMethodConfig) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
208}
209
210int32_t InputMethodSystemAbilityStub::GetSecurityModeOnRemote(MessageParcel &data, MessageParcel &reply)
211{
212    IMSA_HILOGD("GetSecurityModeOnRemote start.");
213    int32_t security;
214    auto ret = GetSecurityMode(security);
215    IMSA_HILOGD("GetSecurityModeOnRemote, security: %{public}d", security);
216    return ITypesUtil::Marshal(reply, ret, security) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
217}
218
219int32_t InputMethodSystemAbilityStub::GetCurrentInputMethodOnRemote(MessageParcel &data, MessageParcel &reply)
220{
221    auto property = GetCurrentInputMethod();
222    if (property == nullptr) {
223        IMSA_HILOGE("property is nullptr!");
224        return reply.WriteInt32(ErrorCode::ERROR_EX_NULL_POINTER) ? ErrorCode::NO_ERROR
225                                                                  : ErrorCode::ERROR_EX_PARCELABLE;
226    }
227    if (!ITypesUtil::Marshal(reply, ErrorCode::NO_ERROR, *property)) {
228        IMSA_HILOGE("marshal failed!");
229        return ErrorCode::ERROR_EX_PARCELABLE;
230    }
231    return ErrorCode::NO_ERROR;
232}
233
234int32_t InputMethodSystemAbilityStub::GetCurrentInputMethodSubtypeOnRemote(MessageParcel &data, MessageParcel &reply)
235{
236    auto property = GetCurrentInputMethodSubtype();
237    if (property == nullptr) {
238        IMSA_HILOGE("property is nullptr!");
239        return reply.WriteInt32(ErrorCode::ERROR_EX_NULL_POINTER) ? ErrorCode::NO_ERROR
240                                                                  : ErrorCode::ERROR_EX_PARCELABLE;
241    }
242    if (!ITypesUtil::Marshal(reply, ErrorCode::NO_ERROR, *property)) {
243        IMSA_HILOGE("marshal failed!");
244        return ErrorCode::ERROR_EX_PARCELABLE;
245    }
246    return ErrorCode::NO_ERROR;
247}
248
249int32_t InputMethodSystemAbilityStub::ListInputMethodOnRemote(MessageParcel &data, MessageParcel &reply)
250{
251    uint32_t status;
252    if (!ITypesUtil::Unmarshal(data, status)) {
253        IMSA_HILOGE("read status failed!");
254        return ErrorCode::ERROR_EX_PARCELABLE;
255    }
256    std::vector<Property> properties = {};
257    auto ret = ListInputMethod(InputMethodStatus(status), properties);
258    if (!ITypesUtil::Marshal(reply, ret, properties)) {
259        IMSA_HILOGE("marshal failed!");
260        return ErrorCode::ERROR_EX_PARCELABLE;
261    }
262    return ErrorCode::NO_ERROR;
263}
264
265int32_t InputMethodSystemAbilityStub::ListInputMethodSubtypeOnRemote(MessageParcel &data, MessageParcel &reply)
266{
267    std::string bundleName;
268    if (!ITypesUtil::Unmarshal(data, bundleName)) {
269        IMSA_HILOGE("read bundleName failed!");
270        return ErrorCode::ERROR_EX_PARCELABLE;
271    }
272    std::vector<SubProperty> subProps = {};
273    auto ret = ListInputMethodSubtype(bundleName, subProps);
274    if (!ITypesUtil::Marshal(reply, ret, subProps)) {
275        IMSA_HILOGE("marshal failed!");
276        return ErrorCode::ERROR_EX_PARCELABLE;
277    }
278    return ErrorCode::NO_ERROR;
279}
280
281int32_t InputMethodSystemAbilityStub::ListCurrentInputMethodSubtypeOnRemote(MessageParcel &data, MessageParcel &reply)
282{
283    std::vector<SubProperty> subProps = {};
284    auto ret = ListCurrentInputMethodSubtype(subProps);
285    if (!ITypesUtil::Marshal(reply, ret, subProps)) {
286        IMSA_HILOGE("marshal failed!");
287        return ErrorCode::ERROR_EX_PARCELABLE;
288    }
289    return ErrorCode::NO_ERROR;
290}
291
292int32_t InputMethodSystemAbilityStub::SwitchInputMethodOnRemote(MessageParcel &data, MessageParcel &reply)
293{
294    std::string name;
295    std::string subName;
296    SwitchTrigger trigger;
297    if (!ITypesUtil::Unmarshal(data, name, subName, trigger)) {
298        IMSA_HILOGE("unmarshal failed!");
299        return ErrorCode::ERROR_EX_PARCELABLE;
300    }
301    return reply.WriteInt32(SwitchInputMethod(name, subName, trigger)) ? ErrorCode::NO_ERROR
302                                                                       : ErrorCode::ERROR_EX_PARCELABLE;
303}
304
305int32_t InputMethodSystemAbilityStub::PanelStatusChangeOnRemote(MessageParcel &data, MessageParcel &reply)
306{
307    uint32_t status = 0;
308    ImeWindowInfo info;
309    if (!ITypesUtil::Unmarshal(data, status, info)) {
310        IMSA_HILOGE("unmarshal failed!");
311        return ErrorCode::ERROR_EX_PARCELABLE;
312    }
313    int32_t ret = PanelStatusChange(static_cast<InputWindowStatus>(status), info);
314    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
315}
316
317int32_t InputMethodSystemAbilityStub::UpdateListenEventFlagOnRemote(MessageParcel &data, MessageParcel &reply)
318{
319    InputClientInfo clientInfo;
320    sptr<IRemoteObject> client = nullptr;
321    uint32_t eventFlag = 0;
322    if (!ITypesUtil::Unmarshal(data, clientInfo, client, clientInfo.channel, eventFlag)) {
323        IMSA_HILOGE("unmarshal failed!");
324        return ErrorCode::ERROR_EX_PARCELABLE;
325    }
326    clientInfo.client = iface_cast<IInputClient>(client);
327    int32_t ret = UpdateListenEventFlag(clientInfo, eventFlag);
328    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
329}
330
331int32_t InputMethodSystemAbilityStub::ShowCurrentInputOnRemoteDeprecated(MessageParcel &data, MessageParcel &reply)
332{
333    int32_t ret = ShowCurrentInputDeprecated();
334    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
335}
336
337int32_t InputMethodSystemAbilityStub::HideCurrentInputOnRemoteDeprecated(MessageParcel &data, MessageParcel &reply)
338{
339    int32_t ret = HideCurrentInputDeprecated();
340    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
341}
342
343int32_t InputMethodSystemAbilityStub::IsCurrentImeOnRemote(MessageParcel &data, MessageParcel &reply)
344{
345    return ITypesUtil::Marshal(reply, ErrorCode::NO_ERROR, IsCurrentIme()) ? ErrorCode::NO_ERROR
346                                                                           : ErrorCode::ERROR_EX_PARCELABLE;
347}
348
349int32_t InputMethodSystemAbilityStub::UnRegisteredProxyImeOnRemote(MessageParcel &data, MessageParcel &reply)
350{
351    int32_t type = -1;
352    sptr<IRemoteObject> coreObject = nullptr;
353    if (!ITypesUtil::Unmarshal(data, type, coreObject) || coreObject == nullptr) {
354        IMSA_HILOGE("coreObject is nullptr!");
355        return ErrorCode::ERROR_EX_PARCELABLE;
356    }
357    int32_t ret = UnRegisteredProxyIme(static_cast<UnRegisteredType>(type), iface_cast<IInputMethodCore>(coreObject));
358    return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
359}
360
361int32_t InputMethodSystemAbilityStub::IsInputTypeSupportedOnRemote(MessageParcel &data, MessageParcel &reply)
362{
363    InputType type;
364    if (!ITypesUtil::Unmarshal(data, type)) {
365        IMSA_HILOGE("unmarshal failed!");
366        return ErrorCode::ERROR_EX_PARCELABLE;
367    }
368    return ITypesUtil::Marshal(reply, ErrorCode::NO_ERROR, IsInputTypeSupported(type)) ? ErrorCode::NO_ERROR
369                                                                                       : ErrorCode::ERROR_EX_PARCELABLE;
370}
371
372int32_t InputMethodSystemAbilityStub::StartInputTypeOnRemote(MessageParcel &data, MessageParcel &reply)
373{
374    InputType type;
375    if (!ITypesUtil::Unmarshal(data, type)) {
376        IMSA_HILOGE("unmarshal failed!");
377        return ErrorCode::ERROR_EX_PARCELABLE;
378    }
379    return ITypesUtil::Marshal(reply, StartInputType(type)) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
380}
381
382int32_t InputMethodSystemAbilityStub::ExitCurrentInputTypeOnRemote(MessageParcel &data, MessageParcel &reply)
383{
384    return ITypesUtil::Marshal(reply, ExitCurrentInputType()) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
385}
386
387int32_t InputMethodSystemAbilityStub::IsPanelShownOnRemote(MessageParcel &data, MessageParcel &reply)
388{
389    PanelInfo info;
390    if (!ITypesUtil::Unmarshal(data, info)) {
391        IMSA_HILOGE("unmarshal failed!");
392        return ErrorCode::ERROR_EX_PARCELABLE;
393    }
394    bool isShown = false;
395    int32_t ret = IsPanelShown(info, isShown);
396    return ITypesUtil::Marshal(reply, ret, isShown) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
397}
398
399int32_t InputMethodSystemAbilityStub::IsDefaultImeOnRemote(MessageParcel &data, MessageParcel &reply)
400{
401    return ITypesUtil::Marshal(reply, IsDefaultIme()) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
402}
403
404int32_t InputMethodSystemAbilityStub::ConnectSystemCmdOnRemote(MessageParcel &data, MessageParcel &reply)
405{
406    auto systemCmdStub = data.ReadRemoteObject();
407    if (systemCmdStub == nullptr) {
408        IMSA_HILOGE("systemCmdStub is nullptr!");
409        return ErrorCode::ERROR_EX_PARCELABLE;
410    }
411    sptr<IRemoteObject> agent = nullptr;
412    int32_t ret = ConnectSystemCmd(systemCmdStub, agent);
413    return reply.WriteInt32(ret) && reply.WriteRemoteObject(agent) ? ErrorCode::NO_ERROR
414                                                                   : ErrorCode::ERROR_EX_PARCELABLE;
415}
416
417int32_t InputMethodSystemAbilityStub::IsCurrentImeByPidOnRemote(MessageParcel &data, MessageParcel &reply)
418{
419    int32_t pid = -1;
420    if (!ITypesUtil::Unmarshal(data, pid)) {
421        IMSA_HILOGE("unmarshal failed!");
422        return ErrorCode::ERROR_EX_PARCELABLE;
423    }
424    return ITypesUtil::Marshal(reply, ErrorCode::NO_ERROR, IsCurrentImeByPid(pid)) ? ErrorCode::NO_ERROR
425                                                                           : ErrorCode::ERROR_EX_PARCELABLE;
426}
427
428int32_t InputMethodSystemAbilityStub::InitConnectOnRemote(MessageParcel &data, MessageParcel &reply)
429{
430    return reply.WriteInt32(InitConnect()) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
431}
432} // namespace MiscServices
433} // namespace OHOS