/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Manage listen-mode AID routing to the host. */ #include "OverrideLog.h" #include "HostAidRouter.h" #include "config.h" #include "SecureElement.h" HostAidRouter HostAidRouter::sHostAidRouter; //singleton HostAidRouter object /******************************************************************************* ** ** Function: HostAidRouter ** ** Description: Private constructor to prevent public call. ** ** Returns: None. ** *******************************************************************************/ HostAidRouter::HostAidRouter () : mTempHandle (NFA_HANDLE_INVALID), mIsFeatureEnabled (true) { } /******************************************************************************* ** ** Function: ~HostAidRouter ** ** Description: Private destructor to prevent public call. ** ** Returns: None. ** *******************************************************************************/ HostAidRouter::~HostAidRouter () { } /******************************************************************************* ** ** Function: getInstance ** ** Description: Obtain a reference to the singleton object of HostAidRouter ** ** Returns: Reference to HostAidRouter object. ** *******************************************************************************/ HostAidRouter& HostAidRouter::getInstance () { return sHostAidRouter; } /******************************************************************************* ** ** Function: initialize ** ** Description: Initialize all resources. ** ** Returns: True if ok. ** *******************************************************************************/ bool HostAidRouter::initialize () { unsigned long num = 0; mTempHandle = NFA_HANDLE_INVALID; mHandleDatabase.clear (); if (GetNumValue (NAME_REGISTER_VIRTUAL_SE, &num, sizeof (num))) mIsFeatureEnabled = num != 0; return true; } /******************************************************************************* ** ** Function: addPpseRoute ** ** Description: Route Proximity Payment System Environment request ** to the host. This function is called when there is no ** route data. ** ** Returns: True if ok. ** *******************************************************************************/ bool HostAidRouter::addPpseRoute () { static const char fn [] = "HostAidRouter::addPpseRoute"; ALOGD ("%s: enter", fn); tNFA_STATUS nfaStat = NFA_STATUS_FAILED; bool retval = false; if (! mIsFeatureEnabled) { ALOGD ("%s: feature disabled", fn); goto TheEnd; } { ALOGD ("%s: register PPSE AID", fn); SyncEventGuard guard (mRegisterEvent); mTempHandle = NFA_HANDLE_INVALID; nfaStat = NFA_CeRegisterAidOnDH ((UINT8*) "2PAY.SYS.DDF01", 14, stackCallback); if (nfaStat == NFA_STATUS_OK) { mRegisterEvent.wait (); //wait for NFA_CE_REGISTERED_EVT if (mTempHandle == NFA_HANDLE_INVALID) { ALOGE ("%s: received invalid handle", fn); goto TheEnd; } else mHandleDatabase.push_back (mTempHandle); } else { ALOGE ("%s: fail register", fn); goto TheEnd; } } retval = true; TheEnd: ALOGD ("%s: exit; ok=%u", fn, retval); return retval; } /******************************************************************************* ** ** Function: deleteAllRoutes ** ** Description: Delete all AID routes to the host. ** ** Returns: True if ok. ** *******************************************************************************/ bool HostAidRouter::deleteAllRoutes () { static const char fn [] = "HostAidRouter::deleteAllRoutes"; ALOGD ("%s: enter", fn); tNFA_STATUS nfaStat = NFA_STATUS_FAILED; bool retval = false; if (! mIsFeatureEnabled) { ALOGD ("%s: feature disabled", fn); goto TheEnd; } //deregister each registered AID from the stack for (AidHandleDatabase::iterator iter1 = mHandleDatabase.begin(); iter1 != mHandleDatabase.end(); iter1++) { tNFA_HANDLE aidHandle = *iter1; ALOGD ("%s: deregister h=0x%X", fn, aidHandle); SyncEventGuard guard (mDeregisterEvent); nfaStat = NFA_CeDeregisterAidOnDH (aidHandle); if (nfaStat == NFA_STATUS_OK) mDeregisterEvent.wait (); //wait for NFA_CE_DEREGISTERED_EVT else ALOGE ("%s: fail deregister", fn); } mHandleDatabase.clear (); retval = true; TheEnd: ALOGD ("%s: exit; ok=%u", fn, retval); return retval; } /******************************************************************************* ** ** Function: startRoute ** ** Description: Begin to route AID request to the host. ** aid: Buffer that contains Application ID ** aidLen: Actual length of the buffer. ** ** Returns: True if ok. ** *******************************************************************************/ bool HostAidRouter::startRoute (const UINT8* aid, UINT8 aidLen) { static const char fn [] = "HostAidRouter::startRoute"; ALOGD ("%s: enter", fn); tNFA_STATUS nfaStat = NFA_STATUS_FAILED; bool retval = false; if (! mIsFeatureEnabled) { ALOGD ("%s: feature disabled", fn); goto TheEnd; } { ALOGD ("%s: register AID; len=%u", fn, aidLen); SyncEventGuard guard (mRegisterEvent); mTempHandle = NFA_HANDLE_INVALID; nfaStat = NFA_CeRegisterAidOnDH ((UINT8*) aid, aidLen, stackCallback); if (nfaStat == NFA_STATUS_OK) { mRegisterEvent.wait (); //wait for NFA_CE_REGISTERED_EVT if (mTempHandle == NFA_HANDLE_INVALID) { ALOGE ("%s: received invalid handle", fn); goto TheEnd; } else mHandleDatabase.push_back (mTempHandle); } else { ALOGE ("%s: fail register", fn); goto TheEnd; } } TheEnd: ALOGD ("%s: exit; ok=%u", fn, retval); return retval; } /******************************************************************************* ** ** Function: stackCallback ** ** Description: Receive events from the NFC stack. ** ** Returns: None. ** *******************************************************************************/ void HostAidRouter::stackCallback (UINT8 event, tNFA_CONN_EVT_DATA* eventData) { static const char fn [] = "HostAidRouter::stackCallback"; ALOGD("%s: event=0x%X", fn, event); switch (event) { case NFA_CE_REGISTERED_EVT: { tNFA_CE_REGISTERED& ce_registered = eventData->ce_registered; ALOGD("%s: NFA_CE_REGISTERED_EVT; status=0x%X; h=0x%X", fn, ce_registered.status, ce_registered.handle); SyncEventGuard guard (sHostAidRouter.mRegisterEvent); if (ce_registered.status == NFA_STATUS_OK) sHostAidRouter.mTempHandle = ce_registered.handle; else sHostAidRouter.mTempHandle = NFA_HANDLE_INVALID; sHostAidRouter.mRegisterEvent.notifyOne(); } break; case NFA_CE_DEREGISTERED_EVT: { tNFA_CE_DEREGISTERED& ce_deregistered = eventData->ce_deregistered; ALOGD("%s: NFA_CE_DEREGISTERED_EVT; h=0x%X", fn, ce_deregistered.handle); SyncEventGuard guard (sHostAidRouter.mDeregisterEvent); sHostAidRouter.mDeregisterEvent.notifyOne(); } break; case NFA_CE_DATA_EVT: { tNFA_CE_DATA& ce_data = eventData->ce_data; ALOGD("%s: NFA_CE_DATA_EVT; h=0x%X; data len=%u", fn, ce_data.handle, ce_data.len); SecureElement::getInstance().notifyTransactionListenersOfAid ((UINT8 *)"2PAY.SYS.DDF01", 14); } break; } }