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 "nci_native_selector.h"
17 #include <dlfcn.h>
18 #include <string>
19 #include "loghelper.h"
20 
21 namespace OHOS {
22 namespace NFC {
23 namespace NCI {
NciNativeSelector()24 NciNativeSelector::NciNativeSelector()
25 {
26     InitNativeInterface();
27 }
28 
InitNativeInterface()29 void NciNativeSelector::InitNativeInterface()
30 {
31     nativeInterface_ = GetNciNativeInterface();
32 }
33 
GetNciNativeInterface()34 std::shared_ptr<INciNativeInterface> NciNativeSelector::GetNciNativeInterface()
35 {
36     loader_ = std::make_unique<NciLibsLoader>();
37     if (!loader_->LoadLib()) {
38         return nullptr;
39     }
40     return loader_->NewInstance();
41 }
42 
GetInstance()43 NciNativeSelector &NciNativeSelector::GetInstance()
44 {
45     static NciNativeSelector instance;
46     return instance;
47 }
48 
GetNciCeInterface()49 std::shared_ptr<INciCeInterface> NciNativeSelector::GetNciCeInterface()
50 {
51     if (nativeInterface_) {
52         return nativeInterface_->GetNciCeInterface();
53     }
54     return nullptr;
55 }
56 
GetNciNfccInterface()57 std::shared_ptr<INciNfccInterface> NciNativeSelector::GetNciNfccInterface()
58 {
59     if (nativeInterface_) {
60         return nativeInterface_->GetNciNfccInterface();
61     }
62     return nullptr;
63 }
64 
GetNciTagInterface()65 std::shared_ptr<INciTagInterface> NciNativeSelector::GetNciTagInterface()
66 {
67     if (nativeInterface_) {
68         return nativeInterface_->GetNciTagInterface();
69     }
70     return nullptr;
71 }
72 
NciLibsLoader(const std::string & newInterfaceSymbol,const std::string & deleteInterfaceSymbol)73 NciNativeSelector::NciLibsLoader::NciLibsLoader(const std::string &newInterfaceSymbol,
74     const std::string &deleteInterfaceSymbol): newInterfaceSymbol_(newInterfaceSymbol),
75     deleteInterfaceSymbol_(deleteInterfaceSymbol)
76 {
77 #ifdef USE_VENDOR_NCI_NATIVE
78     libPath_ = "libnci_native_vendor.z.so";
79 #else
80     libPath_ = "libnci_native_default.z.so";
81 #endif
82 }
83 
~NciLibsLoader()84 NciNativeSelector::NciLibsLoader::~NciLibsLoader()
85 {
86     (void)CloseLib();
87 }
88 
LoadLib()89 bool NciNativeSelector::NciLibsLoader::LoadLib()
90 {
91     if (libPath_.empty() || handle_) {
92         return false;
93     }
94     handle_ = dlopen(libPath_.c_str(), RTLD_LAZY | RTLD_LOCAL);
95     if (!handle_) {
96         ErrorLog("load %{public}s fail, %{public}s", libPath_.c_str(), dlerror());
97         return false;
98     }
99     InfoLog("load %{public}s success", libPath_.c_str());
100     return true;
101 }
102 
CloseLib()103 bool NciNativeSelector::NciLibsLoader::CloseLib()
104 {
105     if (handle_) {
106         if (dlclose(handle_) != 0) {
107             handle_ = nullptr;
108             ErrorLog("close %{public}s fail, %{public}s", libPath_.c_str(), dlerror());
109             return false;
110         }
111         handle_ = nullptr;
112     }
113     InfoLog("close %{public}s success", libPath_.c_str());
114     return true;
115 }
116 
NewInstance()117 std::shared_ptr<INciNativeInterface> NciNativeSelector::NciLibsLoader::NewInstance()
118 {
119     if (!handle_) {
120         ErrorLog("fail handle is null");
121         return nullptr;
122     }
123     using NewFuncType = INciNativeInterface *(*)(void);
124     using DeleteFuncType = void (*)(INciNativeInterface *);
125 
126     auto newInterface = reinterpret_cast<NewFuncType>(dlsym(handle_, newInterfaceSymbol_.c_str()));
127     auto deleteInterface = reinterpret_cast<DeleteFuncType>(dlsym(handle_, deleteInterfaceSymbol_.c_str()));
128     if (!newInterface || !deleteInterface) {
129         (void)CloseLib();
130         ErrorLog("fail not found sym  %{public}s", libPath_.c_str());
131         return nullptr;
132     }
133     InfoLog("new instance %{public}s success", libPath_.c_str());
134     return std::shared_ptr<INciNativeInterface>(newInterface(), deleteInterface);
135 }
136 }  // namespace NCI
137 }  // namespace NFC
138 }  // namespace OHOS