1/*
2 * Copyright (C) 2023 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 "nfc_sa_client.h"
17
18#include "iremote_broker.h"
19#include "iremote_object.h"
20#include "iservice_registry.h"
21#include "infc_controller_callback.h"
22#include "loghelper.h"
23
24namespace OHOS {
25namespace NFC {
26static constexpr int32_t NFC_LOADSA_TIMEOUT_MS = 1000; // ms
27
28NfcSaClient &NfcSaClient::GetInstance()
29{
30    DebugLog("NfcSaClient::%{public}s enter", __func__);
31    static NfcSaClient nfcSaClient;
32    return nfcSaClient;
33}
34
35bool NfcSaClient::CheckNfcSystemAbility()
36{
37    sptr<ISystemAbilityManager> samgr =
38        SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
39    if (samgr == nullptr) {
40        ErrorLog("Get system ability manager failed!");
41        return false;
42    }
43    auto object = samgr->CheckSystemAbility(KITS::NFC_MANAGER_SYS_ABILITY_ID);
44    return (object != nullptr);
45}
46
47sptr<IRemoteObject> NfcSaClient::LoadNfcSa(int32_t systemAbilityId)
48{
49    InfoLog("NfcSaClient::%{public}s enter, systemAbilityId [%{public}d] loading", __func__, systemAbilityId);
50    InitLoadState();
51    sptr<ISystemAbilityManager> samgr =
52        SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
53    if (samgr == nullptr) {
54        ErrorLog("NfcSaClient::%{public}s get system ability manager failed!", __func__);
55        return nullptr;
56    }
57    auto object = samgr->CheckSystemAbility(systemAbilityId);
58    if (object != nullptr) {
59        InfoLog("NfcSaClient::%{public}s CheckSystemAbility systemAbilityId [%{public}d] SUCCESS",
60            __func__, systemAbilityId);
61        remoteObject_ = object;
62        return remoteObject_;
63    }
64
65    auto nfcSaLoadCallback = sptr<NfcSaLoadCallback>(new NfcSaLoadCallback());
66    int32_t ret = samgr->LoadSystemAbility(systemAbilityId, nfcSaLoadCallback);
67    if (ret != ERR_NONE) {
68        ErrorLog("NfcSaClient::%{public}s LoadSystemAbility systemAbilityId [%{public}d] FAILED, ret %{public}d",
69            __func__, systemAbilityId, ret);
70        return nullptr;
71    }
72    if (WaitLoadStateChange(systemAbilityId)) {
73        InfoLog("NfcSaClient::%{public}s LoadSystemAbility systemAbilityId [%{public}d] SUCCESS",
74            __func__, systemAbilityId);
75        return remoteObject_;
76    }
77    ErrorLog("NfcSaClient::%{public}s LoadSystemAbility systemAbilityId [%{public}d] FAILED",
78        __func__, systemAbilityId);
79    return nullptr;
80}
81
82void NfcSaClient::InitLoadState()
83{
84    std::unique_lock<std::mutex> lock(locatorMutex_);
85    loadState_ = false;
86}
87
88bool NfcSaClient::WaitLoadStateChange(int32_t systemAbilityId)
89{
90    std::unique_lock<std::mutex> lock(locatorMutex_);
91    auto wait = locatorCond_.wait_for(lock, std::chrono::milliseconds(NFC_LOADSA_TIMEOUT_MS), [this] {
92        return loadState_ == true;
93    });
94    if (!wait) {
95        ErrorLog("NfcSaClient::%{public}s locator sa  [%{public}d] time out.", __func__, systemAbilityId);
96        return false;
97    }
98    return true;
99}
100
101void NfcSaClient::LoadSystemAbilitySuccess(const sptr<IRemoteObject> &remoteObject)
102{
103    std::unique_lock<std::mutex> lock(locatorMutex_);
104    loadState_ = true;
105    remoteObject_ = remoteObject;
106    locatorCond_.notify_one();
107}
108
109void NfcSaClient::LoadSystemAbilityFail()
110{
111    std::unique_lock<std::mutex> lock(locatorMutex_);
112    loadState_ = false;
113    locatorCond_.notify_one();
114}
115
116void NfcSaLoadCallback::OnLoadSystemAbilitySuccess(
117    int32_t systemAbilityId, const sptr<IRemoteObject> &remoteObject)
118{
119    InfoLog("NfcSaClient Load SA success, systemAbilityId = [%{public}d]", systemAbilityId);
120    NfcSaClient::GetInstance().LoadSystemAbilitySuccess(remoteObject);
121}
122
123void NfcSaLoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId)
124{
125    InfoLog("NfcSaClient Load SA failed, systemAbilityId = [%{public}d]", systemAbilityId);
126    NfcSaClient::GetInstance().LoadSystemAbilityFail();
127}
128}  // namespace NFC
129}  // namespace OHOS