• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 2023 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 "NativeWlcManager.h"
18 
19 #include <android-base/logging.h>
20 #include <android-base/stringprintf.h>
21 #include <cutils/properties.h>
22 #include <errno.h>
23 #include <nativehelper/JNIPlatformHelp.h>
24 #include <nativehelper/ScopedLocalRef.h>
25 #include <nativehelper/ScopedPrimitiveArray.h>
26 #include <nativehelper/ScopedUtfChars.h>
27 #include <semaphore.h>
28 
29 #include "JavaClassConstants.h"
30 #include "NfcJniUtil.h"
31 #include "SyncEvent.h"
32 #include "nfa_api.h"
33 
34 using android::base::StringPrintf;
35 
36 /*****************************************************************************
37 **
38 ** private variables and functions
39 **
40 *****************************************************************************/
41 
42 static void nfaWlcManagementCallback(tNFA_WLC_EVT wlcEvent,
43                                      tNFA_WLC_EVT_DATA* eventData);
44 
45 static SyncEvent sNfaWlcEnableEvent;  // event for NFA_WlcStart()
46 static SyncEvent sNfaWlcEvent;        // event for NFA_Wlc...()
47 
48 static bool sIsWlcpStarted = false;
49 
50 Mutex gMutexWlc;
51 
52 const JNINativeMethod NativeWlcManager::sMethods[] = {
53 
54     {"startWlcPowerTransfer", "(II)Z",
55      (void*)NativeWlcManager::com_android_nfc_wlc_chargeWlcListener},
56     {"enableWlc", "(I)Z",
57      (void*)NativeWlcManager::com_android_nfc_wlc_startWlcP},
58 
59 };
60 
61 /*******************************************************************************
62 **
63 ** Function:        NativeWlcManager
64 **
65 ** Description:     Initialize member variables.
66 **
67 ** Returns:         None
68 **
69 *******************************************************************************/
NativeWlcManager()70 NativeWlcManager::NativeWlcManager()
71     : mNativeData(NULL), mIsWlcEnabled(false) {}
72 
73 /*******************************************************************************
74 **
75 ** Function:        ~NativeWlcManager
76 **
77 ** Description:     Release all resources.
78 **
79 ** Returns:         None
80 **
81 *******************************************************************************/
~NativeWlcManager()82 NativeWlcManager::~NativeWlcManager() {}
83 
84 /*******************************************************************************
85 **
86 ** Function:        getInstance
87 **
88 ** Description:     Get a reference to the singleton NativeWlcManager object.
89 **
90 ** Returns:         Reference to NativeWlcManager object.
91 **
92 *******************************************************************************/
getInstance()93 NativeWlcManager& NativeWlcManager::getInstance() {
94   static NativeWlcManager manager;
95   return manager;
96 }
97 
98 /*******************************************************************************
99 **
100 ** Function:        initialize
101 **
102 ** Description:     Reset member variables.
103 **                  native: Native data.
104 **
105 ** Returns:         None
106 **
107 *******************************************************************************/
initialize(nfc_jni_native_data * native)108 void NativeWlcManager::initialize(nfc_jni_native_data* native) {
109   tNFA_STATUS stat = NFA_STATUS_FAILED;
110 
111   LOG(DEBUG) << StringPrintf("%s: enter", __func__);
112 
113   mNativeData = native;
114   mIsWlcEnabled = false;
115 
116   SyncEventGuard g(sNfaWlcEnableEvent);
117   // TODO: only do it once at NfcManager init if WLC allowed
118   stat = NFA_WlcEnable(nfaWlcManagementCallback);
119 
120   if (stat == NFA_STATUS_OK) {
121     // TODO: get enable result to stop directly if failed
122     sNfaWlcEnableEvent.wait();
123     LOG(DEBUG) << StringPrintf("%s: enable Wlc module success", __func__);
124   } else {
125     LOG(ERROR) << StringPrintf("%s: fail enable Wlc module; error=0x%X",
126                                __func__, stat);
127   }
128 }
129 
130 /*******************************************************************************
131 **
132 ** Function:        notifyWlcCompletion
133 **
134 ** Description:     Notify end of WLC procedure.
135 **                  wpt_end_condition: End condition from NFCC.
136 **
137 ** Returns:         None
138 **
139 *******************************************************************************/
notifyWlcCompletion(uint8_t wpt_end_condition)140 void NativeWlcManager::notifyWlcCompletion(uint8_t wpt_end_condition) {
141   JNIEnv* e = NULL;
142   ScopedAttach attach(mNativeData->vm, &e);
143   if (e == NULL) {
144     LOG(ERROR) << __func__ << ": jni env is null";
145     return;
146   }
147 
148   LOG(DEBUG) << StringPrintf("%s", __func__);
149 
150   e->CallVoidMethod(mNativeData->manager,
151                     android::gCachedNfcManagerNotifyWlcStopped,
152                     (int)wpt_end_condition);
153   if (e->ExceptionCheck()) {
154     e->ExceptionClear();
155     LOG(ERROR) << StringPrintf("%s: fail notify", __func__);
156   }
157 }
158 
159 /*******************************************************************************
160 **
161 ** Function:        nfaWlcManagementCallback
162 **
163 ** Description:     Receive Wlc management events from stack.
164 **                  wlcEvent: Wlc-management event ID.
165 **                  eventData: Data associated with event ID.
166 **
167 ** Returns:         None
168 **
169 *******************************************************************************/
nfaWlcManagementCallback(tNFA_WLC_EVT wlcEvent,tNFA_WLC_EVT_DATA * eventData)170 void nfaWlcManagementCallback(tNFA_WLC_EVT wlcEvent,
171                               tNFA_WLC_EVT_DATA* eventData) {
172   switch (wlcEvent) {
173     case NFA_WLC_ENABLE_RESULT_EVT:  // whether WLC module enabled
174     {
175       LOG(DEBUG) << StringPrintf("%s: NFA_WLC_ENABLE_RESULT_EVT: status = %u",
176                                  __func__, eventData->status);
177 
178       SyncEventGuard guard(sNfaWlcEnableEvent);
179       sNfaWlcEnableEvent.notifyOne();
180     } break;
181 
182     case NFA_WLC_START_RESULT_EVT:  // whether WLCP successfully started
183     {
184       LOG(DEBUG) << StringPrintf("%s: NFA_WLC_START_RESULT_EVT: status = %u",
185                                  __func__, eventData->status);
186 
187       sIsWlcpStarted = eventData->status == NFA_STATUS_OK;
188       SyncEventGuard guard(sNfaWlcEvent);
189       sNfaWlcEvent.notifyOne();
190     } break;
191 
192     case NFA_WLC_START_WPT_RESULT_EVT:  // whether WLC Power Transfer
193                                         // successfully started
194     {
195       LOG(DEBUG) << StringPrintf(
196           "%s: NFA_WLC_START_WPT_RESULT_EVT: status = %u", __func__,
197           eventData->status);
198 
199       SyncEventGuard guard(sNfaWlcEvent);
200       sNfaWlcEvent.notifyOne();
201     } break;
202 
203     case NFA_WLC_CHARGING_RESULT_EVT:  // notify completion of power transfer
204                                        // phase
205     {
206       LOG(DEBUG) << StringPrintf(
207           "%s: NFA_WLC_CHARGING_RESULT_EVT: End Condition = 0x%x", __func__,
208           eventData->wpt_end_cdt);
209 
210       /* Return WPT end condition to service */
211       NativeWlcManager::getInstance().notifyWlcCompletion(
212           eventData->wpt_end_cdt);
213     } break;
214 
215     default:
216       LOG(DEBUG) << StringPrintf("%s: unhandled event", __func__);
217       break;
218   }
219 }
220 
221 /*******************************************************************************
222 **
223 ** Function:        com_android_nfc_wlc_startWlcP
224 **
225 ** Description:     Start WLC Poller
226 **                  e: JVM environment.
227 **                  mode: WLC mode
228 **
229 ** Returns:         True if WLCP started done
230 **
231 *******************************************************************************/
com_android_nfc_wlc_startWlcP(JNIEnv * e,jobject,jint mode)232 jboolean NativeWlcManager::com_android_nfc_wlc_startWlcP(JNIEnv* e, jobject,
233                                                          jint mode) {
234   tNFA_STATUS stat = NFA_STATUS_FAILED;
235 
236   LOG(DEBUG) << StringPrintf("%s: enter", __func__);
237 
238   gMutexWlc.lock();
239   SyncEventGuard g(sNfaWlcEvent);
240   stat = NFA_WlcStart(mode);
241 
242   if (stat == NFA_STATUS_OK) {
243     LOG(DEBUG) << StringPrintf(
244         "%s: start Wlc Poller, wait for success confirmation", __func__);
245     sNfaWlcEvent.wait();
246   } else {
247     LOG(ERROR) << StringPrintf("%s: fail start WlcPoller; error=0x%X", __func__,
248                                stat);
249   }
250   gMutexWlc.unlock();
251   return sIsWlcpStarted ? JNI_TRUE : JNI_FALSE;
252 }
253 
254 /*******************************************************************************
255 **
256 ** Function:        com_android_nfc_wlc_chargeWlcListener
257 **
258 ** Description:     Start charging WLC Listener
259 **                  e: JVM environment.
260 **                  power_adj_req:
261 **                  wpt_time_int:
262 **
263 ** Returns:         True if WLCL charging started properly
264 **
265 *******************************************************************************/
com_android_nfc_wlc_chargeWlcListener(JNIEnv * e,jobject,jint power_adj_req,jint wpt_time_int)266 jboolean NativeWlcManager::com_android_nfc_wlc_chargeWlcListener(
267     JNIEnv* e, jobject, jint power_adj_req, jint wpt_time_int) {
268   tNFA_STATUS stat = NFA_STATUS_FAILED;
269 
270   LOG(DEBUG) << StringPrintf("%s: wpt_time_int = %d", __func__, wpt_time_int);
271 
272   gMutexWlc.lock();
273   SyncEventGuard g(sNfaWlcEvent);
274   // TODO: condition call to sIsWlcpStarted
275   // TODO: limit the min of wpt_time_int
276   stat = NFA_WlcStartWPT((uint16_t)(power_adj_req & 0xFFFF), wpt_time_int);
277   if (stat == NFA_STATUS_OK) {
278     LOG(DEBUG) << StringPrintf(
279         "%s: charge Wlc Listener, wait for success confirmation", __func__);
280     sNfaWlcEvent.wait();
281   } else {
282     LOG(ERROR) << StringPrintf("%s: fail charge Wlc Listener; error=0x%X",
283                                __func__, stat);
284     gMutexWlc.unlock();
285     return false;
286   }
287   gMutexWlc.unlock();
288   return true;
289 }
290 
291 /*******************************************************************************
292 **
293 ** Function:        registerJniFunctions
294 **
295 ** Description:     Register WLC feature JNI functions
296 **                  e: JVM environment.
297 **
298 ** Returns:         -1 if JNI register error
299 **
300 *******************************************************************************/
registerJniFunctions(JNIEnv * e)301 int NativeWlcManager::registerJniFunctions(JNIEnv* e) {
302   static const char fn[] = "NativeWlcManager::registerJniFunctions";
303   LOG(DEBUG) << StringPrintf("%s", fn);
304   return jniRegisterNativeMethods(e, "com/android/nfc/wlc/NfcCharging",
305                                   sMethods, NELEM(sMethods));
306 }
307