1 /* 2 * Copyright (C) 2012 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 #include "OverrideLog.h" 17 #include "SecureElement.h" 18 #include "JavaClassConstants.h" 19 #include "PowerSwitch.h" 20 #include "NfcTag.h" 21 #include <ScopedPrimitiveArray.h> 22 23 namespace android 24 { 25 26 27 extern void com_android_nfc_NfcManager_disableDiscovery (JNIEnv* e, jobject o); 28 extern void com_android_nfc_NfcManager_enableDiscovery (JNIEnv* e, jobject o, jint mode); 29 30 // These must match the EE_ERROR_ types in NfcService.java 31 static const int EE_ERROR_IO = -1; 32 static const int EE_ERROR_ALREADY_OPEN = -2; 33 static const int EE_ERROR_INIT = -3; 34 static const int EE_ERROR_LISTEN_MODE = -4; 35 static const int EE_ERROR_EXT_FIELD = -5; 36 static const int EE_ERROR_NFC_DISABLED = -6; 37 38 /******************************************************************************* 39 ** 40 ** Function: nativeNfcSecureElement_doOpenSecureElementConnection 41 ** 42 ** Description: Connect to the secure element. 43 ** e: JVM environment. 44 ** o: Java object. 45 ** 46 ** Returns: Handle of secure element. values < 0 represent failure. 47 ** 48 *******************************************************************************/ 49 static jint nativeNfcSecureElement_doOpenSecureElementConnection (JNIEnv*, jobject) 50 { 51 ALOGD("%s: enter", __FUNCTION__); 52 bool stat = true; 53 jint secElemHandle = EE_ERROR_INIT; 54 SecureElement &se = SecureElement::getInstance(); 55 56 if (se.isActivatedInListenMode()) { 57 ALOGD("Denying SE open due to SE listen mode active"); 58 secElemHandle = EE_ERROR_LISTEN_MODE; 59 goto TheEnd; 60 } 61 62 if (se.isRfFieldOn()) { 63 ALOGD("Denying SE open due to SE in active RF field"); 64 secElemHandle = EE_ERROR_EXT_FIELD; 65 goto TheEnd; 66 } 67 //tell the controller to power up to get ready for sec elem operations 68 PowerSwitch::getInstance ().setLevel (PowerSwitch::FULL_POWER); 69 PowerSwitch::getInstance ().setModeOn (PowerSwitch::SE_CONNECTED); 70 71 //if controller is not routing AND there is no pipe connected, 72 //then turn on the sec elem 73 if (! se.isBusy()) 74 stat = se.activate(0); 75 76 if (stat) 77 { 78 //establish a pipe to sec elem 79 stat = se.connectEE(); 80 if (stat) 81 { 82 secElemHandle = se.mActiveEeHandle; 83 } 84 else 85 { 86 se.deactivate (0); 87 } 88 } 89 90 //if code fails to connect to the secure element, and nothing is active, then 91 //tell the controller to power down 92 if ((!stat) && (! PowerSwitch::getInstance ().setModeOff (PowerSwitch::SE_CONNECTED))) 93 { 94 PowerSwitch::getInstance ().setLevel (PowerSwitch::LOW_POWER); 95 } 96 97 TheEnd: 98 ALOGD("%s: exit; return handle=0x%X", __FUNCTION__, secElemHandle); 99 return secElemHandle; 100 } 101 102 103 /******************************************************************************* 104 ** 105 ** Function: nativeNfcSecureElement_doDisconnectSecureElementConnection 106 ** 107 ** Description: Disconnect from the secure element. 108 ** e: JVM environment. 109 ** o: Java object. 110 ** handle: Handle of secure element. 111 ** 112 ** Returns: True if ok. 113 ** 114 *******************************************************************************/ 115 static jboolean nativeNfcSecureElement_doDisconnectSecureElementConnection (JNIEnv*, jobject, jint handle) 116 { 117 ALOGD("%s: enter; handle=0x%04x", __FUNCTION__, handle); 118 bool stat = false; 119 120 stat = SecureElement::getInstance().disconnectEE (handle); 121 122 //if controller is not routing AND there is no pipe connected, 123 //then turn off the sec elem 124 if (! SecureElement::getInstance().isBusy()) 125 SecureElement::getInstance().deactivate (handle); 126 127 //if nothing is active after this, then tell the controller to power down 128 if (! PowerSwitch::getInstance ().setModeOff (PowerSwitch::SE_CONNECTED)) 129 PowerSwitch::getInstance ().setLevel (PowerSwitch::LOW_POWER); 130 131 ALOGD("%s: exit", __FUNCTION__); 132 return stat ? JNI_TRUE : JNI_FALSE; 133 } 134 135 136 /******************************************************************************* 137 ** 138 ** Function: nativeNfcSecureElement_doTransceive 139 ** 140 ** Description: Send data to the secure element; retrieve response. 141 ** e: JVM environment. 142 ** o: Java object. 143 ** handle: Secure element's handle. 144 ** data: Data to send. 145 ** 146 ** Returns: Buffer of received data. 147 ** 148 *******************************************************************************/ 149 static jbyteArray nativeNfcSecureElement_doTransceive (JNIEnv* e, jobject, jint handle, jbyteArray data) 150 { 151 const INT32 recvBufferMaxSize = 1024; 152 UINT8 recvBuffer [recvBufferMaxSize]; 153 INT32 recvBufferActualSize = 0; 154 int timeout = NfcTag::getInstance ().getTransceiveTimeout (TARGET_TYPE_ISO14443_4); //NFC service expects JNI to use ISO-DEP's timeout 155 ScopedByteArrayRW bytes(e, data); 156 157 ALOGD("%s: enter; handle=0x%X; buf len=%zu", __FUNCTION__, handle, bytes.size()); 158 SecureElement::getInstance().transceive(reinterpret_cast<UINT8*>(&bytes[0]), bytes.size(), recvBuffer, recvBufferMaxSize, recvBufferActualSize, timeout); 159 160 //copy results back to java 161 jbyteArray result = e->NewByteArray(recvBufferActualSize); 162 if (result != NULL) 163 { 164 e->SetByteArrayRegion(result, 0, recvBufferActualSize, (jbyte *) recvBuffer); 165 } 166 167 ALOGD("%s: exit: recv len=%ld", __FUNCTION__, recvBufferActualSize); 168 return result; 169 } 170 171 /***************************************************************************** 172 ** 173 ** Description: JNI functions 174 ** 175 *****************************************************************************/ 176 static JNINativeMethod gMethods[] = 177 { 178 {"doNativeOpenSecureElementConnection", "()I", (void *) nativeNfcSecureElement_doOpenSecureElementConnection}, 179 {"doNativeDisconnectSecureElementConnection", "(I)Z", (void *) nativeNfcSecureElement_doDisconnectSecureElementConnection}, 180 {"doTransceive", "(I[B)[B", (void *) nativeNfcSecureElement_doTransceive}, 181 }; 182 183 184 /******************************************************************************* 185 ** 186 ** Function: register_com_android_nfc_NativeNfcSecureElement 187 ** 188 ** Description: Regisgter JNI functions with Java Virtual Machine. 189 ** e: Environment of JVM. 190 ** 191 ** Returns: Status of registration. 192 ** 193 *******************************************************************************/ 194 int register_com_android_nfc_NativeNfcSecureElement(JNIEnv *e) 195 { 196 return jniRegisterNativeMethods(e, gNativeNfcSecureElementClassName, 197 gMethods, NELEM(gMethods)); 198 } 199 200 201 } // namespace android 202