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 "aot_compiler_client.h"
17#include "aot_compiler_error_utils.h"
18#include "aot_compiler_load_callback.h"
19#include "ecmascript/log_wrapper.h"
20#include "hitrace_meter.h"
21#include "iservice_registry.h"
22#include "system_ability_definition.h"
23
24namespace OHOS::ArkCompiler {
25namespace {
26    const int LOAD_SA_TIMEOUT_MS = 6 * 1000;
27} // namespace
28
29AotCompilerClient::AotCompilerClient()
30{
31    aotCompilerDiedRecipient_ = new (std::nothrow) AotCompilerDiedRecipient();
32    if (aotCompilerDiedRecipient_ == nullptr) {
33        LOG_SA(ERROR) << "create aot compiler died recipient failed";
34    }
35}
36
37AotCompilerClient &AotCompilerClient::GetInstance()
38{
39    static AotCompilerClient singleAotCompilerClient;
40    return singleAotCompilerClient;
41}
42
43int32_t AotCompilerClient::AotCompiler(const std::unordered_map<std::string, std::string> &argsMap,
44                                       std::vector<int16_t> &sigData)
45{
46    HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
47    LOG_SA(DEBUG) << "aot compiler function called";
48    auto aotCompilerProxy = GetAotCompilerProxy();
49    if (aotCompilerProxy == nullptr) {
50        LOG_SA(ERROR) << "get aot compiler service failed";
51        return ERR_AOT_COMPILER_CONNECT_FAILED;
52    }
53    return aotCompilerProxy->AotCompiler(argsMap, sigData);
54}
55
56int32_t AotCompilerClient::StopAotCompiler()
57{
58    HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
59    LOG_SA(DEBUG) << "aot compiler function called";
60    auto aotCompilerProxy = GetAotCompilerProxy();
61    if (aotCompilerProxy == nullptr) {
62        LOG_SA(ERROR) << "get aot compiler service failed";
63        return ERR_AOT_COMPILER_CONNECT_FAILED;
64    }
65    return aotCompilerProxy->StopAotCompiler();
66}
67
68int32_t AotCompilerClient::GetAOTVersion(std::string& sigData)
69{
70    HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
71    LOG_SA(DEBUG) << "aot compiler get AOT version called";
72    auto aotCompilerProxy = GetAotCompilerProxy();
73    if (aotCompilerProxy == nullptr) {
74        LOG_SA(ERROR) << "get aot compiler service failed";
75        return ERR_AOT_COMPILER_CONNECT_FAILED;
76    }
77
78    return aotCompilerProxy->GetAOTVersion(sigData);
79}
80
81int32_t AotCompilerClient::NeedReCompile(const std::string& oldVersion, bool& sigData)
82{
83    HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
84    LOG_SA(DEBUG) << "aot compiler check need re-compile called";
85    auto aotCompilerProxy = GetAotCompilerProxy();
86    if (aotCompilerProxy == nullptr) {
87        LOG_SA(ERROR) << "get aot compiler service failed";
88        return ERR_AOT_COMPILER_CONNECT_FAILED;
89    }
90    return aotCompilerProxy->NeedReCompile(oldVersion, sigData);
91}
92
93sptr<IAotCompilerInterface> AotCompilerClient::GetAotCompilerProxy()
94{
95    LOG_SA(DEBUG) << "get aot compiler proxy function called";
96    auto aotCompilerProxy = GetAotCompiler();
97    if (aotCompilerProxy != nullptr) {
98        LOG_SA(DEBUG) << "aot compiler service proxy has been started";
99        return aotCompilerProxy;
100    }
101    auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
102    if (systemAbilityMgr == nullptr) {
103        LOG_SA(ERROR) << "failed to get system ability manager";
104        return nullptr;
105    }
106    auto remoteObject = systemAbilityMgr->CheckSystemAbility(AOT_COMPILER_SERVICE_ID);
107    if (remoteObject != nullptr) {
108        aotCompilerProxy = iface_cast<IAotCompilerInterface>(remoteObject);
109        return aotCompilerProxy;
110    }
111    if (!LoadAotCompilerService()) {
112        LOG_SA(ERROR) << "load aot compiler service failed";
113        return nullptr;
114    }
115    aotCompilerProxy = GetAotCompiler();
116    if (aotCompilerProxy == nullptr || aotCompilerProxy->AsObject() == nullptr) {
117        LOG_SA(ERROR) << "failed to get aot compiler service";
118        return nullptr;
119    }
120    LOG_SA(DEBUG) << "get aot compiler proxy function finished";
121    return aotCompilerProxy;
122}
123
124bool AotCompilerClient::LoadAotCompilerService()
125{
126    {
127        std::unique_lock<std::mutex> lock(loadSaMutex_);
128        loadSaFinished_ = false;
129    }
130    auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
131    if (systemAbilityMgr == nullptr) {
132        LOG_SA(ERROR) << "failed to get system ability manager";
133        return false;
134    }
135    sptr<AotCompilerLoadCallback> loadCallback = new (std::nothrow) AotCompilerLoadCallback();
136    if (loadCallback == nullptr) {
137        LOG_SA(ERROR) << "failed to create load callback";
138        return false;
139    }
140    auto ret = systemAbilityMgr->LoadSystemAbility(AOT_COMPILER_SERVICE_ID, loadCallback);
141    if (ret != 0) {
142        LOG_SA(ERROR) << "load system ability " << AOT_COMPILER_SERVICE_ID << " failed with " << ret;
143        return false;
144    }
145    {
146        std::unique_lock<std::mutex> lock(loadSaMutex_);
147        auto waitStatus = loadSaCondition_.wait_for(lock, std::chrono::milliseconds(LOAD_SA_TIMEOUT_MS),
148        [this]() {
149            return loadSaFinished_;
150        });
151        if (!waitStatus) {
152            LOG_SA(ERROR) << "wait for load SA timeout";
153            return false;
154        }
155    }
156    return true;
157}
158
159void AotCompilerClient::SetAotCompiler(const sptr<IRemoteObject> &remoteObject)
160{
161    std::lock_guard<std::mutex> lock(mutex_);
162    aotCompilerProxy_ = iface_cast<IAotCompilerInterface>(remoteObject);
163}
164
165sptr<IAotCompilerInterface> AotCompilerClient::GetAotCompiler()
166{
167    std::lock_guard<std::mutex> lock(mutex_);
168    return aotCompilerProxy_;
169}
170
171void AotCompilerClient::OnLoadSystemAbilitySuccess(const sptr<IRemoteObject> &remoteObject)
172{
173    if (aotCompilerDiedRecipient_ == nullptr) {
174        LOG_SA(ERROR) << "register aot compiler died recipient failed";
175        return;
176    }
177    if (!remoteObject->AddDeathRecipient(aotCompilerDiedRecipient_)) {
178        LOG_SA(ERROR) << "add aot compiler died recipient failed";
179        return;
180    }
181    SetAotCompiler(remoteObject);
182    std::unique_lock<std::mutex> lock(loadSaMutex_);
183    loadSaFinished_ = true;
184    loadSaCondition_.notify_one();
185}
186
187void AotCompilerClient::OnLoadSystemAbilityFail()
188{
189    SetAotCompiler(nullptr);
190    std::unique_lock<std::mutex> lock(loadSaMutex_);
191    loadSaFinished_ = true;
192    loadSaCondition_.notify_one();
193}
194
195void AotCompilerClient::AotCompilerDiedRecipient::OnRemoteDied(const wptr<IRemoteObject> &remoteObject)
196{
197    if (remoteObject == nullptr) {
198        LOG_SA(ERROR) << "remote object of aot compiler died recipient is nullptr";
199        return;
200    }
201    AotCompilerClient::GetInstance().AotCompilerOnRemoteDied(remoteObject);
202}
203
204void AotCompilerClient::AotCompilerOnRemoteDied(const wptr<IRemoteObject> &remoteObject)
205{
206    LOG_SA(INFO) << "remote object of aot compiler died recipient is died";
207    auto aotCompilerProxy = GetAotCompiler();
208    if (aotCompilerProxy == nullptr) {
209        LOG_SA(ERROR) << "aot compiler proxy is nullptr";
210        return;
211    }
212    sptr<IRemoteObject> remotePromote = remoteObject.promote();
213    if (remotePromote == nullptr) {
214        LOG_SA(ERROR) << "remote object of aot compiler promote fail";
215        return;
216    }
217    if (aotCompilerProxy->AsObject() != remotePromote) {
218        LOG_SA(ERROR) << "aot compiler died recipient not find remote object";
219        return;
220    }
221    remotePromote->RemoveDeathRecipient(aotCompilerDiedRecipient_);
222    SetAotCompiler(nullptr);
223}
224} // namespace OHOS::ArkCompiler