RoutingManager.cpp revision 51956bf06ab443954683ea2cf5e015a876e006d9
1
2/*
3 * Copyright (C) 2013 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 *  Manage the listen-mode routing table.
20 */
21
22#include <cutils/log.h>
23#include <ScopedLocalRef.h>
24#include "config.h"
25#include "JavaClassConstants.h"
26#include "RoutingManager.h"
27
28RoutingManager::RoutingManager ()
29{
30}
31
32RoutingManager::~RoutingManager ()
33{
34    NFA_EeDeregister (nfaEeCallback);
35}
36
37bool RoutingManager::initialize (nfc_jni_native_data* native)
38{
39    static const char fn [] = "RoutingManager::initialize()";
40    unsigned long num = 0;
41    mNativeData = native;
42
43    tNFA_STATUS nfaStat;
44    {
45        SyncEventGuard guard (mEeRegisterEvent);
46        ALOGD ("%s: try ee register", fn);
47        nfaStat = NFA_EeRegister (nfaEeCallback);
48        if (nfaStat != NFA_STATUS_OK)
49        {
50            ALOGE ("%s: fail ee register; error=0x%X", fn, nfaStat);
51            return false;
52        }
53        mEeRegisterEvent.wait ();
54    }
55
56    // Get the "default" route
57    if (GetNumValue("DEFAULT_ISODEP_ROUTE", &num, sizeof(num)))
58        mDefaultEe = num;
59    else
60        mDefaultEe = 0x00;
61
62    ALOGD("%s: default route is 0x%02X", fn, mDefaultEe);
63    setDefaultRouting();
64    return true;
65}
66
67RoutingManager& RoutingManager::getInstance ()
68{
69    static RoutingManager manager;
70    return manager;
71}
72
73void RoutingManager::setDefaultRouting()
74{
75    tNFA_STATUS nfaStat;
76    SyncEventGuard guard (mRoutingEvent);
77    // Default routing for NFC-A technology
78    nfaStat = NFA_EeSetDefaultTechRouting (mDefaultEe, 0x01, 0, 0);
79    if (nfaStat == NFA_STATUS_OK)
80        mRoutingEvent.wait ();
81    else
82        ALOGE ("Fail to set default tech routing");
83
84    // Default routing for IsoDep protocol
85    nfaStat = NFA_EeSetDefaultProtoRouting(mDefaultEe, NFA_PROTOCOL_MASK_ISO_DEP, 0, 0);
86    if (nfaStat == NFA_STATUS_OK)
87        mRoutingEvent.wait ();
88    else
89        ALOGE ("Fail to set default proto routing");
90
91    // Tell the UICC to only listen on Nfc-A
92    nfaStat = NFA_CeConfigureUiccListenTech (mDefaultEe, 0x01);
93    if (nfaStat != NFA_STATUS_OK)
94        ALOGE ("Failed to configure UICC listen technologies");
95
96    // Tell the host-routing to only listen on Nfc-A
97    nfaStat = NFA_CeSetIsoDepListenTech(0x01);
98    if (nfaStat != NFA_STATUS_OK)
99        ALOGE ("Failed to configure CE IsoDep technologies");
100
101    // Register a wild-card for AIDs routed to the host
102    nfaStat = NFA_CeRegisterAidOnDH (NULL, 0, stackCallback);
103    if (nfaStat != NFA_STATUS_OK)
104        ALOGE("Failed to register wildcard AID for DH");
105
106    // Commit the routing configuration
107    nfaStat = NFA_EeUpdateNow();
108    if (nfaStat != NFA_STATUS_OK)
109        ALOGE("Failed to commit routing configuration");
110}
111
112bool RoutingManager::addAidRouting(const UINT8* aid, UINT8 aidLen, int route)
113{
114    static const char fn [] = "RoutingManager::addAidRouting";
115    ALOGD ("%s: enter", fn);
116    tNFA_STATUS nfaStat = NFA_EeAddAidRouting(route, aidLen, (UINT8*) aid, 0x01);
117    if (nfaStat == NFA_STATUS_OK)
118    {
119        ALOGD ("%s: routed AID", fn);
120        return true;
121    } else
122    {
123        ALOGE ("%s: failed to route AID");
124        return false;
125    }
126}
127
128bool RoutingManager::removeAidRouting(const UINT8* aid, UINT8 aidLen)
129{
130    static const char fn [] = "RoutingManager::removeAidRouting";
131    ALOGD ("%s: enter", fn);
132    tNFA_STATUS nfaStat = NFA_EeRemoveAidRouting(aidLen, (UINT8*) aid);
133    if (nfaStat == NFA_STATUS_OK)
134    {
135        ALOGD ("%s: removed AID", fn);
136        return true;
137    } else
138    {
139        ALOGE ("%s: failed to remove AID");
140        return false;
141    }
142}
143
144bool RoutingManager::commitRouting()
145{
146    tNFA_STATUS nfaStat = NFA_EeUpdateNow();
147    return (nfaStat == NFA_STATUS_OK);
148}
149
150void RoutingManager::notifyActivated ()
151{
152    JNIEnv* e = NULL;
153    ScopedAttach attach(mNativeData->vm, &e);
154    if (e == NULL)
155    {
156        ALOGE ("jni env is null");
157        return;
158    }
159
160    e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifyHostEmuActivated);
161    if (e->ExceptionCheck())
162    {
163        e->ExceptionClear();
164        ALOGE ("fail notify");
165    }
166}
167
168void RoutingManager::notifyDeactivated ()
169{
170    SecureElement::getInstance().notifyListenModeState (false);
171
172    JNIEnv* e = NULL;
173    ScopedAttach attach(mNativeData->vm, &e);
174    if (e == NULL)
175    {
176        ALOGE ("jni env is null");
177        return;
178    }
179
180    e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifyHostEmuDeactivated);
181    if (e->ExceptionCheck())
182    {
183        e->ExceptionClear();
184        ALOGE ("fail notify");
185    }
186}
187
188void RoutingManager::handleData (const UINT8* data, UINT8 dataLen)
189{
190    if (dataLen <= 0)
191    {
192        ALOGE("no data");
193        return;
194    }
195
196    JNIEnv* e = NULL;
197    ScopedAttach attach(mNativeData->vm, &e);
198    if (e == NULL)
199    {
200        ALOGE ("jni env is null");
201        return;
202    }
203
204    ScopedLocalRef<jobject> dataJavaArray(e, e->NewByteArray(dataLen));
205    if (dataJavaArray.get() == NULL)
206    {
207        ALOGE ("fail allocate array");
208        return;
209    }
210
211    e->SetByteArrayRegion ((jbyteArray)dataJavaArray.get(), 0, dataLen, (jbyte *)data);
212    if (e->ExceptionCheck())
213    {
214        e->ExceptionClear();
215        ALOGE ("fail fill array");
216        return;
217    }
218
219    e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifyHostEmuData, dataJavaArray.get());
220    if (e->ExceptionCheck())
221    {
222        e->ExceptionClear();
223        ALOGE ("fail notify");
224    }
225}
226
227void RoutingManager::stackCallback (UINT8 event, tNFA_CONN_EVT_DATA* eventData)
228{
229    static const char fn [] = "RoutingManager::stackCallback";
230    ALOGD("%s: event=0x%X", fn, event);
231    RoutingManager& routingManager = RoutingManager::getInstance();
232
233    switch (event)
234    {
235    case NFA_CE_REGISTERED_EVT:
236        {
237            tNFA_CE_REGISTERED& ce_registered = eventData->ce_registered;
238            ALOGD("%s: NFA_CE_REGISTERED_EVT; status=0x%X; h=0x%X", fn, ce_registered.status, ce_registered.handle);
239        }
240        break;
241
242    case NFA_CE_DEREGISTERED_EVT:
243        {
244            tNFA_CE_DEREGISTERED& ce_deregistered = eventData->ce_deregistered;
245            ALOGD("%s: NFA_CE_DEREGISTERED_EVT; h=0x%X", fn, ce_deregistered.handle);
246        }
247        break;
248
249    case NFA_CE_ACTIVATED_EVT:
250        {
251            routingManager.notifyActivated();
252        }
253        break;
254    case NFA_CE_DEACTIVATED_EVT:
255        {
256            routingManager.notifyDeactivated();
257        }
258        break;
259    case NFA_CE_DATA_EVT:
260        {
261            tNFA_CE_DATA& ce_data = eventData->ce_data;
262            ALOGD("%s: NFA_CE_DATA_EVT; h=0x%X; data len=%u", fn, ce_data.handle, ce_data.len);
263            getInstance().handleData(ce_data.p_data, ce_data.len);
264        }
265        break;
266    }
267
268}
269/*******************************************************************************
270**
271** Function:        nfaEeCallback
272**
273** Description:     Receive execution environment-related events from stack.
274**                  event: Event code.
275**                  eventData: Event data.
276**
277** Returns:         None
278**
279*******************************************************************************/
280void RoutingManager::nfaEeCallback (tNFA_EE_EVT event, tNFA_EE_CBACK_DATA* eventData)
281{
282    static const char fn [] = "RoutingManager::nfaEeCallback";
283
284    SecureElement& se = SecureElement::getInstance();
285    RoutingManager& routingManager = RoutingManager::getInstance();
286
287    switch (event)
288    {
289    case NFA_EE_REGISTER_EVT:
290        {
291            SyncEventGuard guard (routingManager.mEeRegisterEvent);
292            ALOGD ("%s: NFA_EE_REGISTER_EVT; status=%u", fn, eventData->ee_register);
293            routingManager.mEeRegisterEvent.notifyOne();
294        }
295        break;
296
297    case NFA_EE_MODE_SET_EVT:
298        {
299            ALOGD ("%s: NFA_EE_MODE_SET_EVT; status: 0x%04X  handle: 0x%04X  mActiveEeHandle: 0x%04X", fn,
300                    eventData->mode_set.status, eventData->mode_set.ee_handle, se.mActiveEeHandle);
301            se.notifyModeSet(eventData->mode_set.ee_handle, eventData->mode_set.status);
302        }
303        break;
304
305    case NFA_EE_SET_TECH_CFG_EVT:
306        {
307            ALOGD ("%s: NFA_EE_SET_TECH_CFG_EVT; status=0x%X", fn, eventData->status);
308            SyncEventGuard guard(routingManager.mRoutingEvent);
309            routingManager.mRoutingEvent.notifyOne();
310        }
311        break;
312
313    case NFA_EE_SET_PROTO_CFG_EVT:
314        {
315            ALOGD ("%s: NFA_EE_SET_PROTO_CFG_EVT; status=0x%X", fn, eventData->status);
316            SyncEventGuard guard(routingManager.mRoutingEvent);
317            routingManager.mRoutingEvent.notifyOne();
318        }
319        break;
320
321    case NFA_EE_ACTION_EVT:
322        {
323            tNFA_EE_ACTION& action = eventData->action;
324            if (action.trigger == NFC_EE_TRIG_SELECT)
325                ALOGD ("%s: NFA_EE_ACTION_EVT; h=0x%X; trigger=select (0x%X)", fn, action.ee_handle, action.trigger);
326            else if (action.trigger == NFC_EE_TRIG_APP_INIT)
327            {
328                tNFC_APP_INIT& app_init = action.param.app_init;
329                ALOGD ("%s: NFA_EE_ACTION_EVT; h=0x%X; trigger=app-init (0x%X); aid len=%u; data len=%u", fn,
330                        action.ee_handle, action.trigger, app_init.len_aid, app_init.len_data);
331                //if app-init operation is successful;
332                //app_init.data[] contains two bytes, which are the status codes of the event;
333                //app_init.data[] does not contain an APDU response;
334                //see EMV Contactless Specification for Payment Systems; Book B; Entry Point Specification;
335                //version 2.1; March 2011; section 3.3.3.5;
336                if ( (app_init.len_data > 1) &&
337                     (app_init.data[0] == 0x90) &&
338                     (app_init.data[1] == 0x00) )
339                {
340                    se.notifyTransactionListenersOfAid (app_init.aid, app_init.len_aid);
341                }
342            }
343            else if (action.trigger == NFC_EE_TRIG_RF_PROTOCOL)
344                ALOGD ("%s: NFA_EE_ACTION_EVT; h=0x%X; trigger=rf protocol (0x%X)", fn, action.ee_handle, action.trigger);
345            else if (action.trigger == NFC_EE_TRIG_RF_TECHNOLOGY)
346                ALOGD ("%s: NFA_EE_ACTION_EVT; h=0x%X; trigger=rf tech (0x%X)", fn, action.ee_handle, action.trigger);
347            else
348                ALOGE ("%s: NFA_EE_ACTION_EVT; h=0x%X; unknown trigger (0x%X)", fn, action.ee_handle, action.trigger);
349        }
350        break;
351
352    case NFA_EE_DISCOVER_REQ_EVT:
353        ALOGD ("%s: NFA_EE_DISCOVER_REQ_EVT; status=0x%X; num ee=%u", __FUNCTION__,
354                eventData->discover_req.status, eventData->discover_req.num_ee);
355        break;
356
357    case NFA_EE_NO_CB_ERR_EVT:
358        ALOGD ("%s: NFA_EE_NO_CB_ERR_EVT  status=%u", fn, eventData->status);
359        break;
360
361    case NFA_EE_ADD_AID_EVT:
362        {
363            ALOGD ("%s: NFA_EE_ADD_AID_EVT  status=%u", fn, eventData->status);
364        }
365        break;
366
367    case NFA_EE_REMOVE_AID_EVT:
368        {
369            ALOGD ("%s: NFA_EE_REMOVE_AID_EVT  status=%u", fn, eventData->status);
370        }
371        break;
372
373    case NFA_EE_NEW_EE_EVT:
374        {
375            ALOGD ("%s: NFA_EE_NEW_EE_EVT  h=0x%X; status=%u", fn,
376                eventData->new_ee.ee_handle, eventData->new_ee.ee_status);
377        }
378        break;
379
380    default:
381        ALOGE ("%s: unknown event=%u ????", fn, event);
382        break;
383    }
384}
385