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 #include "res_sched_exe_client.h"
16 
17 #include <new>
18 #include <string>
19 #include <unistd.h>
20 #include <unordered_map>
21 #include <utility>
22 
23 #include "if_system_ability_manager.h"
24 #include "iremote_broker.h"
25 #include "iservice_registry.h"
26 #include "system_ability_definition.h"
27 
28 #include "res_exe_type.h"
29 #include "res_sched_exe_constants.h"
30 #include "res_sched_exe_log.h"
31 
32 namespace OHOS {
33 namespace ResourceSchedule {
GetInstance()34 ResSchedExeClient& ResSchedExeClient::GetInstance()
35 {
36     static ResSchedExeClient instance;
37     return instance;
38 }
39 
~ResSchedExeClient()40 ResSchedExeClient::~ResSchedExeClient()
41 {
42     StopRemoteObject();
43 }
44 
SendRequestSync(uint32_t resType,int64_t value,const nlohmann::json & context,nlohmann::json & reply)45 int32_t ResSchedExeClient::SendRequestSync(uint32_t resType, int64_t value,
46     const nlohmann::json& context, nlohmann::json& reply)
47 {
48     return SendRequestInner(true, resType, value, context, reply);
49 }
50 
SendRequestAsync(uint32_t resType,int64_t value,const nlohmann::json & context)51 void ResSchedExeClient::SendRequestAsync(uint32_t resType, int64_t value,
52     const nlohmann::json& context)
53 {
54     nlohmann::json reply;
55     SendRequestInner(false, resType, value, context, reply);
56 }
57 
KillProcess(pid_t pid)58 int32_t ResSchedExeClient::KillProcess(pid_t pid)
59 {
60     RSSEXE_LOGD("kill process receive pid = %{public}d", pid);
61     auto proxy = GetProxy();
62     if (proxy == nullptr) {
63         RSSEXE_LOGE("fail to get resource schedule executor");
64         return ResIpcErrCode::RSSEXE_CONNECT_FAIL;
65     }
66     return proxy->KillProcess(pid);
67 }
68 
SendRequestInner(bool isSync,uint32_t resType,int64_t value,const nlohmann::json & context,nlohmann::json & reply)69 int32_t ResSchedExeClient::SendRequestInner(bool isSync, uint32_t resType, int64_t value,
70     const nlohmann::json& context, nlohmann::json& reply)
71 {
72     RSSEXE_LOGD("receive resType = %{public}u, value = %{public}lld.", resType, (long long)value);
73     auto proxy = GetProxy();
74     if (proxy == nullptr) {
75         RSSEXE_LOGE("fail to get resource schedule executor.");
76         return ResIpcErrCode::RSSEXE_CONNECT_FAIL;
77     }
78 
79     RSSEXE_LOGD("send request.");
80     if (isSync) {
81         return proxy->SendRequestSync(resType, value, context, reply);
82     } else {
83         proxy->SendRequestAsync(resType, value, context);
84         return ResErrCode::RSSEXE_NO_ERR;
85     }
86 }
87 
SendDebugCommand(bool isSync)88 void ResSchedExeClient::SendDebugCommand(bool isSync)
89 {
90     nlohmann::json tempJson;
91     SendRequestInner(isSync, ResExeType::RES_TYPE_DEBUG, 0, tempJson, tempJson);
92 }
93 
GetProxy()94 sptr<IResSchedExeService> ResSchedExeClient::GetProxy()
95 {
96     if (TryConnect() == ResErrCode::RSSEXE_NO_ERR) {
97         std::lock_guard<std::mutex> lock(mutex_);
98         return resSchedExe_;
99     }
100     return nullptr;
101 }
102 
TryConnect()103 ErrCode ResSchedExeClient::TryConnect()
104 {
105     std::lock_guard<std::mutex> lock(mutex_);
106     if (resSchedExe_) {
107         return ResErrCode::RSSEXE_NO_ERR;
108     }
109 
110     sptr<ISystemAbilityManager> systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
111     if (!systemManager) {
112         RSSEXE_LOGE("Fail to get registry.");
113         return ResIpcErrCode::RSSEXE_GET_SERVICE_FAIL;
114     }
115 
116     remoteObject_ = systemManager->CheckSystemAbility(RES_SCHED_EXE_ABILITY_ID);
117     if (!remoteObject_) {
118         RSSEXE_LOGE("Fail to connect resource schedule executor.");
119         return ResIpcErrCode::RSSEXE_GET_SERVICE_FAIL;
120     }
121 
122     resSchedExe_ = iface_cast<IResSchedExeService>(remoteObject_);
123     if (!resSchedExe_) {
124         return ResIpcErrCode::RSSEXE_GET_SERVICE_FAIL;
125     }
126     recipient_ = new (std::nothrow) ResSchedExeDeathRecipient(*this);
127     if (!recipient_) {
128         RSSEXE_LOGE("New ResSchedDeathRecipient failed.");
129         return ResIpcErrCode::RSSEXE_GET_SERVICE_FAIL;
130     }
131     resSchedExe_->AsObject()->AddDeathRecipient(recipient_);
132     RSSEXE_LOGD("Connect resource schedule executor success.");
133     return ResErrCode::RSSEXE_NO_ERR;
134 }
135 
StopRemoteObject()136 void ResSchedExeClient::StopRemoteObject()
137 {
138     std::lock_guard<std::mutex> lock(mutex_);
139     if (resSchedExe_ && resSchedExe_->AsObject()) {
140         resSchedExe_->AsObject()->RemoveDeathRecipient(recipient_);
141     }
142     resSchedExe_ = nullptr;
143 }
144 
ResSchedExeDeathRecipient(ResSchedExeClient & resSchedExeClient)145 ResSchedExeClient::ResSchedExeDeathRecipient::ResSchedExeDeathRecipient(ResSchedExeClient& resSchedExeClient)
146     : resSchedExeClient_(resSchedExeClient) {}
147 
~ResSchedExeDeathRecipient()148 ResSchedExeClient::ResSchedExeDeathRecipient::~ResSchedExeDeathRecipient() {}
149 
OnRemoteDied(const wptr<IRemoteObject> & remote)150 void ResSchedExeClient::ResSchedExeDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
151 {
152     resSchedExeClient_.StopRemoteObject();
153 }
154 } // namespace ResourceSchedule
155 } // namespace OHOS
156