1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "Nfc.h"
18 
19 #include <android-base/logging.h>
20 
21 #include "StNfc_hal_api.h"
22 
23 namespace aidl {
24 namespace android {
25 namespace hardware {
26 namespace nfc {
27 
28 typedef struct {
29   uint64_t mOpenCount;
30   Nfc* nfc;
31 } stHalCookie;
32 
33 std::shared_ptr<INfcClientCallback> Nfc::mCallback = nullptr;
34 AIBinder_DeathRecipient* clientDeathRecipient = nullptr;
35 pthread_mutex_t mLockOpenClose = PTHREAD_MUTEX_INITIALIZER;
36 uint64_t mOpenCount = 0;
37 stHalCookie mHalCookie;
38 
OnDeath(void * cookie)39 void OnDeath(void* cookie) {
40   pthread_mutex_lock(&mLockOpenClose);
41   stHalCookie* mCookie = static_cast<stHalCookie*>(cookie);
42   LOG(INFO) << __func__ << "cookie : " << mCookie->mOpenCount
43             << " mOpenCount : " << mOpenCount;
44   if (mCookie->mOpenCount == mOpenCount) {
45     if (Nfc::mCallback != nullptr &&
46         !AIBinder_isAlive(Nfc::mCallback->asBinder().get())) {
47       LOG(INFO) << __func__ << " Nfc service has died";
48       pthread_mutex_unlock(&mLockOpenClose);
49       mCookie->nfc->close(NfcCloseType::DISABLE);
50     }
51   }
52   pthread_mutex_unlock(&mLockOpenClose);
53 }
54 
open(const std::shared_ptr<INfcClientCallback> & clientCallback)55 ::ndk::ScopedAStatus Nfc::open(
56     const std::shared_ptr<INfcClientCallback>& clientCallback) {
57   LOG(INFO) << "open";
58   if (clientCallback == nullptr) {
59     LOG(INFO) << "Nfc::open null callback";
60     return ndk::ScopedAStatus::fromServiceSpecificError(
61         static_cast<int32_t>(NfcStatus::FAILED));
62   } else {
63     pthread_mutex_lock(&mLockOpenClose);
64     mOpenCount++;
65     Nfc::mCallback = clientCallback;
66     mHalCookie.mOpenCount = mOpenCount;
67     mHalCookie.nfc = this;
68 
69     clientDeathRecipient = AIBinder_DeathRecipient_new(OnDeath);
70     auto linkRet =
71         AIBinder_linkToDeath(clientCallback->asBinder().get(),
72                              clientDeathRecipient, &mHalCookie /* cookie */);
73     if (linkRet != STATUS_OK) {
74       LOG(ERROR) << __func__ << ": linkToDeath failed: " << linkRet;
75       // Just ignore the error.
76     }
77 
78     int ret = StNfc_hal_open(eventCallback, dataCallback);
79     LOG(INFO) << "Nfc::open Exit count " << mOpenCount;
80     pthread_mutex_unlock(&mLockOpenClose);
81     return ret == 0 ? ndk::ScopedAStatus::ok()
82                     : ndk::ScopedAStatus::fromServiceSpecificError(
83                           static_cast<int32_t>(NfcStatus::FAILED));
84   }
85 }
86 
close(NfcCloseType type)87 ::ndk::ScopedAStatus Nfc::close(NfcCloseType type) {
88   LOG(INFO) << "close";
89   if (Nfc::mCallback == nullptr) {
90     LOG(ERROR) << __func__ << "mCallback null";
91     return ndk::ScopedAStatus::fromServiceSpecificError(
92         static_cast<int32_t>(NfcStatus::FAILED));
93   }
94   pthread_mutex_lock(&mLockOpenClose);
95   int ret = 0;
96   if (type == NfcCloseType::HOST_SWITCHED_OFF) {
97     ret = StNfc_hal_closeForPowerOffCase();
98   } else {
99     ret = StNfc_hal_close(NFC_MODE_OFF);
100   }
101   Nfc::mCallback = nullptr;
102   AIBinder_DeathRecipient_delete(clientDeathRecipient);
103   clientDeathRecipient = nullptr;
104   pthread_mutex_unlock(&mLockOpenClose);
105   return ret == 0 ? ndk::ScopedAStatus::ok()
106                   : ndk::ScopedAStatus::fromServiceSpecificError(
107                         static_cast<int32_t>(NfcStatus::FAILED));
108 }
109 
coreInitialized()110 ::ndk::ScopedAStatus Nfc::coreInitialized() {
111   LOG(INFO) << "coreInitialized";
112   if (Nfc::mCallback == nullptr) {
113     LOG(ERROR) << __func__ << "mCallback null";
114     return ndk::ScopedAStatus::fromServiceSpecificError(
115         static_cast<int32_t>(NfcStatus::FAILED));
116   }
117   int ret = StNfc_hal_core_initialized();
118 
119   return ret == 0 ? ndk::ScopedAStatus::ok()
120                   : ndk::ScopedAStatus::fromServiceSpecificError(
121                         static_cast<int32_t>(NfcStatus::FAILED));
122 }
123 
factoryReset()124 ::ndk::ScopedAStatus Nfc::factoryReset() {
125   LOG(INFO) << "factoryReset";
126   StNfc_hal_factoryReset();
127   return ndk::ScopedAStatus::ok();
128 }
129 
getConfig(NfcConfig * _aidl_return)130 ::ndk::ScopedAStatus Nfc::getConfig(NfcConfig* _aidl_return) {
131   LOG(INFO) << "getConfig";
132   NfcConfig nfcVendorConfig;
133   StNfc_hal_getConfig(nfcVendorConfig);
134 
135   *_aidl_return = nfcVendorConfig;
136   return ndk::ScopedAStatus::ok();
137 }
138 
powerCycle()139 ::ndk::ScopedAStatus Nfc::powerCycle() {
140   LOG(INFO) << "powerCycle";
141   if (Nfc::mCallback == nullptr) {
142     LOG(ERROR) << __func__ << "mCallback null";
143     return ndk::ScopedAStatus::fromServiceSpecificError(
144         static_cast<int32_t>(NfcStatus::FAILED));
145   }
146   return StNfc_hal_power_cycle() ? ndk::ScopedAStatus::fromServiceSpecificError(
147                                        static_cast<int32_t>(NfcStatus::FAILED))
148                                  : ndk::ScopedAStatus::ok();
149 }
150 
preDiscover()151 ::ndk::ScopedAStatus Nfc::preDiscover() {
152   if (Nfc::mCallback == nullptr) {
153     LOG(ERROR) << __func__ << "mCallback null";
154     return ndk::ScopedAStatus::fromServiceSpecificError(
155         static_cast<int32_t>(NfcStatus::FAILED));
156   }
157   return StNfc_hal_pre_discover()
158              ? ndk::ScopedAStatus::fromServiceSpecificError(
159                    static_cast<int32_t>(NfcStatus::FAILED))
160              : ndk::ScopedAStatus::ok();
161 }
162 
write(const std::vector<uint8_t> & data,int32_t * _aidl_return)163 ::ndk::ScopedAStatus Nfc::write(const std::vector<uint8_t>& data,
164                                 int32_t* _aidl_return) {
165   if (Nfc::mCallback == nullptr) {
166     LOG(ERROR) << __func__ << "mCallback null";
167     return ndk::ScopedAStatus::fromServiceSpecificError(
168         static_cast<int32_t>(NfcStatus::FAILED));
169   }
170   *_aidl_return = StNfc_hal_write(data.size(), &data[0]);
171   return ndk::ScopedAStatus::ok();
172 }
173 
setEnableVerboseLogging(bool enable)174 ::ndk::ScopedAStatus Nfc::setEnableVerboseLogging(bool enable) {
175   LOG(INFO) << "setVerboseLogging";
176   StNfc_hal_setLogging(enable);
177   return ndk::ScopedAStatus::ok();
178 }
179 
isVerboseLoggingEnabled(bool * _aidl_return)180 ::ndk::ScopedAStatus Nfc::isVerboseLoggingEnabled(bool* _aidl_return) {
181   *_aidl_return = StNfc_hal_isLoggingEnabled();
182   return ndk::ScopedAStatus::ok();
183 }
184 
185 }  // namespace nfc
186 }  // namespace hardware
187 }  // namespace android
188 }  // namespace aidl
189