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 "concurrent_task_service_stub.h"
17#include "concurrent_task_log.h"
18#include "concurrent_task_errors.h"
19#include "string_ex.h"
20#include "ipc_skeleton.h"
21
22namespace OHOS {
23namespace ConcurrentTask {
24namespace {
25    bool IsValidToken(MessageParcel& data)
26    {
27        std::u16string descriptor = ConcurrentTaskServiceStub::GetDescriptor();
28        std::u16string remoteDescriptor = data.ReadInterfaceToken();
29        return descriptor == remoteDescriptor;
30    }
31}
32
33ConcurrentTaskServiceStub::ConcurrentTaskServiceStub()
34{
35    Init();
36}
37
38ConcurrentTaskServiceStub::~ConcurrentTaskServiceStub()
39{
40    funcMap_.clear();
41}
42
43int32_t ConcurrentTaskServiceStub::ReportDataInner(MessageParcel& data, [[maybe_unused]] MessageParcel& reply)
44{
45    if (!IsValidToken(data)) {
46        return ERR_CONCURRENT_TASK_PARCEL_ERROR;
47    }
48
49    uint32_t type = 0;
50    int64_t value = 0;
51    std::string payload;
52    if (!data.ReadUint32(type) || !data.ReadInt64(value) || !data.ReadString(payload)) {
53        CONCUR_LOGE("Read info failed in ReportData Stub");
54        return IPC_STUB_ERR;
55    }
56    if (payload.empty()) {
57        return ERR_OK;
58    }
59    ReportData(type, value, StringToJson(payload));
60    return ERR_OK;
61}
62
63int32_t ConcurrentTaskServiceStub::QueryIntervalInner(MessageParcel& data, [[maybe_unused]] MessageParcel& reply)
64{
65    if (!IsValidToken(data)) {
66        return ERR_CONCURRENT_TASK_PARCEL_ERROR;
67    }
68    int item;
69    IntervalReply queryRs;
70    queryRs.rtgId = -1;
71    queryRs.tid = -1;
72    queryRs.paramA = -1;
73    queryRs.paramB = -1;
74    if (!data.ReadInt32(item) || !data.ReadInt32(queryRs.tid)) {
75        CONCUR_LOGE("Read info failed in QueryInterval Stub");
76        return IPC_STUB_ERR;
77    }
78    QueryInterval(item, queryRs);
79    if (!reply.WriteInt32(queryRs.rtgId) || !reply.WriteInt32(queryRs.tid)
80        || !reply.WriteInt32(queryRs.paramA) || !reply.WriteInt32(queryRs.paramB)
81        || !reply.WriteString(queryRs.bundleName)) {
82        CONCUR_LOGE("Write info failed in QueryInterval Stub");
83        return IPC_STUB_ERR;
84    }
85    return ERR_OK;
86}
87
88int32_t ConcurrentTaskServiceStub::QueryDeadlineInner(MessageParcel& data, [[maybe_unused]] MessageParcel& reply)
89{
90    if (!IsValidToken(data)) {
91        return ERR_CONCURRENT_TASK_PARCEL_ERROR;
92    }
93    int queryItem;
94    DeadlineReply ddlReply;
95    std::string payload;
96    if (!data.ReadInt32(queryItem) || !data.ReadString(payload)) {
97        CONCUR_LOGE("Read info failed in QueryDeadline Stub");
98        return IPC_STUB_ERR;
99    }
100    if (payload.empty()) {
101        return ERR_OK;
102    }
103    QueryDeadline(queryItem, ddlReply, StringToJson(payload));
104    return ERR_OK;
105}
106
107int32_t ConcurrentTaskServiceStub::RequestAuthInner(MessageParcel& data, [[maybe_unused]] MessageParcel& reply)
108{
109    if (!IsValidToken(data)) {
110        return ERR_CONCURRENT_TASK_PARCEL_ERROR;
111    }
112
113    std::string payload;
114    if (!data.ReadString(payload)) {
115        CONCUR_LOGE("Read info failed in RequestAuth Stub");
116        return IPC_STUB_ERR;
117    }
118    if (payload.empty()) {
119        return ERR_OK;
120    }
121    RequestAuth(StringToJson(payload));
122    return ERR_OK;
123}
124
125int32_t ConcurrentTaskServiceStub::OnRemoteRequest(uint32_t code, MessageParcel& data,
126    MessageParcel& reply, MessageOption& option)
127{
128    auto uid = IPCSkeleton::GetCallingUid();
129    auto pid = IPCSkeleton::GetCallingPid();
130    CONCUR_LOGD("ConcurrentTaskServiceStub::OnRemoteRequest, code = %{public}u, flags = %{public}d,"
131        " uid = %{public}d pid = %{public}d", code, option.GetFlags(), uid, pid);
132
133    auto itFunc = funcMap_.find(code);
134    if (itFunc != funcMap_.end()) {
135        auto requestFunc = itFunc->second;
136        if (requestFunc) {
137            return requestFunc(data, reply);
138        }
139    }
140    return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
141}
142
143Json::Value ConcurrentTaskServiceStub::StringToJson(const std::string& payload)
144{
145    bool res;
146    Json::CharReaderBuilder readerBuilder;
147    JSONCPP_STRING errs;
148    std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
149    Json::Value root;
150    if (!IsAsciiString(payload)) {
151        CONCUR_LOGE("Payload is not ascii string");
152        return root;
153    }
154    try {
155        res = jsonReader->parse(payload.c_str(), payload.c_str() + payload.length(), &root, &errs);
156    } catch (...) {
157        CONCUR_LOGE("Unexpected json parse");
158        return root;
159    }
160    if (!res || !errs.empty()) {
161        CONCUR_LOGE("ConcurentTaskServiceStub::payload = %{public}s Incorrect JSON format ", payload.c_str());
162    }
163    return root;
164}
165
166void ConcurrentTaskServiceStub::Init()
167{
168    funcMap_ = {
169        { static_cast<uint32_t>(ConcurrentTaskInterfaceCode::REPORT_DATA),
170            [this](auto& data, auto& reply) {return ReportDataInner(data, reply); } },
171        { static_cast<uint32_t>(ConcurrentTaskInterfaceCode::QUERY_INTERVAL),
172            [this](auto& data, auto& reply) {return QueryIntervalInner(data, reply); } },
173        { static_cast<uint32_t>(ConcurrentTaskInterfaceCode::QUERY_DEADLINE),
174            [this](auto& data, auto& reply) {return QueryDeadlineInner(data, reply); } },
175        { static_cast<uint32_t>(ConcurrentTaskInterfaceCode::REQUEST_AUTH),
176            [this](auto& data, auto& reply) {return RequestAuthInner(data, reply); } },
177    };
178}
179} // namespace ResourceSchedule
180} // namespace OHOS
181