Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2010 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 <stdlib.h>
     18 
     19 #include "errno.h"
     20 #include "com_android_nfc.h"
     21 #include "com_android_nfc_list.h"
     22 #include "phLibNfcStatus.h"
     23 
     24 /*
     25  * JNI Initialization
     26  */
     27 jint JNI_OnLoad(JavaVM *jvm, void *reserved)
     28 {
     29    JNIEnv *e;
     30 
     31    ALOGD("NFC Service : loading JNI\n");
     32 
     33    // Check JNI version
     34    if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6))
     35       return JNI_ERR;
     36 
     37    android::vm = jvm;
     38 
     39    if (android::register_com_android_nfc_NativeNfcManager(e) == -1)
     40       return JNI_ERR;
     41    if (android::register_com_android_nfc_NativeNfcTag(e) == -1)
     42       return JNI_ERR;
     43    if (android::register_com_android_nfc_NativeP2pDevice(e) == -1)
     44       return JNI_ERR;
     45    if (android::register_com_android_nfc_NativeLlcpSocket(e) == -1)
     46       return JNI_ERR;
     47    if (android::register_com_android_nfc_NativeLlcpConnectionlessSocket(e) == -1)
     48       return JNI_ERR;
     49    if (android::register_com_android_nfc_NativeLlcpServiceSocket(e) == -1)
     50       return JNI_ERR;
     51    if (android::register_com_android_nfc_NativeNfcSecureElement(e) == -1)
     52       return JNI_ERR;
     53 
     54    return JNI_VERSION_1_6;
     55 }
     56 
     57 namespace android {
     58 
     59 extern struct nfc_jni_native_data *exported_nat;
     60 
     61 JavaVM *vm;
     62 
     63 /*
     64  * JNI Utils
     65  */
     66 JNIEnv *nfc_get_env()
     67 {
     68     JNIEnv *e;
     69     if (vm->GetEnv((void **)&e, JNI_VERSION_1_6) != JNI_OK) {
     70         ALOGE("Current thread is not attached to VM");
     71         phLibNfc_Mgt_Recovery();
     72         abort();
     73     }
     74     return e;
     75 }
     76 
     77 bool nfc_cb_data_init(nfc_jni_callback_data* pCallbackData, void* pContext)
     78 {
     79    /* Create semaphore */
     80    if(sem_init(&pCallbackData->sem, 0, 0) == -1)
     81    {
     82       ALOGE("Semaphore creation failed (errno=0x%08x)", errno);
     83       return false;
     84    }
     85 
     86    /* Set default status value */
     87    pCallbackData->status = NFCSTATUS_FAILED;
     88 
     89    /* Copy the context */
     90    pCallbackData->pContext = pContext;
     91 
     92    /* Add to active semaphore list */
     93    if (!listAdd(&nfc_jni_get_monitor()->sem_list, pCallbackData))
     94    {
     95       ALOGE("Failed to add the semaphore to the list");
     96    }
     97 
     98    return true;
     99 }
    100 
    101 void nfc_cb_data_deinit(nfc_jni_callback_data* pCallbackData)
    102 {
    103    /* Destroy semaphore */
    104    if (sem_destroy(&pCallbackData->sem))
    105    {
    106       ALOGE("Failed to destroy semaphore (errno=0x%08x)", errno);
    107    }
    108 
    109    /* Remove from active semaphore list */
    110    if (!listRemove(&nfc_jni_get_monitor()->sem_list, pCallbackData))
    111    {
    112       ALOGE("Failed to remove semaphore from the list");
    113    }
    114 
    115 }
    116 
    117 void nfc_cb_data_releaseAll()
    118 {
    119    nfc_jni_callback_data* pCallbackData;
    120 
    121    while (listGetAndRemoveNext(&nfc_jni_get_monitor()->sem_list, (void**)&pCallbackData))
    122    {
    123       pCallbackData->status = NFCSTATUS_FAILED;
    124       sem_post(&pCallbackData->sem);
    125    }
    126 }
    127 
    128 int nfc_jni_cache_object(JNIEnv *e, const char *clsname,
    129    jobject *cached_obj)
    130 {
    131    jclass cls;
    132    jobject obj;
    133    jmethodID ctor;
    134 
    135    cls = e->FindClass(clsname);
    136    if(cls == NULL)
    137    {
    138       return -1;
    139       ALOGD("Find class error\n");
    140    }
    141 
    142 
    143    ctor = e->GetMethodID(cls, "<init>", "()V");
    144 
    145    obj = e->NewObject(cls, ctor);
    146    if(obj == NULL)
    147    {
    148       return -1;
    149       ALOGD("Create object error\n");
    150    }
    151 
    152    *cached_obj = e->NewGlobalRef(obj);
    153    if(*cached_obj == NULL)
    154    {
    155       e->DeleteLocalRef(obj);
    156       ALOGD("Global ref error\n");
    157       return -1;
    158    }
    159 
    160    e->DeleteLocalRef(obj);
    161 
    162    return 0;
    163 }
    164 
    165 
    166 struct nfc_jni_native_data* nfc_jni_get_nat(JNIEnv *e, jobject o)
    167 {
    168    jclass c;
    169    jfieldID f;
    170 
    171    /* Retrieve native structure address */
    172    c = e->GetObjectClass(o);
    173    f = e->GetFieldID(c, "mNative", "I");
    174    return (struct nfc_jni_native_data*)e->GetIntField(o, f);
    175 }
    176 
    177 struct nfc_jni_native_data* nfc_jni_get_nat_ext(JNIEnv *e)
    178 {
    179    return exported_nat;
    180 }
    181 
    182 static nfc_jni_native_monitor_t *nfc_jni_native_monitor = NULL;
    183 
    184 nfc_jni_native_monitor_t* nfc_jni_init_monitor(void)
    185 {
    186 
    187    pthread_mutexattr_t recursive_attr;
    188 
    189    pthread_mutexattr_init(&recursive_attr);
    190    pthread_mutexattr_settype(&recursive_attr, PTHREAD_MUTEX_RECURSIVE_NP);
    191 
    192    if(nfc_jni_native_monitor == NULL)
    193    {
    194       nfc_jni_native_monitor = (nfc_jni_native_monitor_t*)malloc(sizeof(nfc_jni_native_monitor_t));
    195    }
    196 
    197    if(nfc_jni_native_monitor != NULL)
    198    {
    199       memset(nfc_jni_native_monitor, 0, sizeof(nfc_jni_native_monitor_t));
    200 
    201       if(pthread_mutex_init(&nfc_jni_native_monitor->reentrance_mutex, &recursive_attr) == -1)
    202       {
    203          ALOGE("NFC Manager Reentrance Mutex creation returned 0x%08x", errno);
    204          return NULL;
    205       }
    206 
    207       if(pthread_mutex_init(&nfc_jni_native_monitor->concurrency_mutex, NULL) == -1)
    208       {
    209          ALOGE("NFC Manager Concurrency Mutex creation returned 0x%08x", errno);
    210          return NULL;
    211       }
    212 
    213       if(!listInit(&nfc_jni_native_monitor->sem_list))
    214       {
    215          ALOGE("NFC Manager Semaphore List creation failed");
    216          return NULL;
    217       }
    218 
    219       LIST_INIT(&nfc_jni_native_monitor->incoming_socket_head);
    220 
    221       if(pthread_mutex_init(&nfc_jni_native_monitor->incoming_socket_mutex, NULL) == -1)
    222       {
    223          ALOGE("NFC Manager incoming socket mutex creation returned 0x%08x", errno);
    224          return NULL;
    225       }
    226 
    227       if(pthread_cond_init(&nfc_jni_native_monitor->incoming_socket_cond, NULL) == -1)
    228       {
    229          ALOGE("NFC Manager incoming socket condition creation returned 0x%08x", errno);
    230          return NULL;
    231       }
    232 
    233 }
    234 
    235    return nfc_jni_native_monitor;
    236 }
    237 
    238 nfc_jni_native_monitor_t* nfc_jni_get_monitor(void)
    239 {
    240    return nfc_jni_native_monitor;
    241 }
    242 
    243 
    244 phLibNfc_Handle nfc_jni_get_p2p_device_handle(JNIEnv *e, jobject o)
    245 {
    246    jclass c;
    247    jfieldID f;
    248 
    249    c = e->GetObjectClass(o);
    250    f = e->GetFieldID(c, "mHandle", "I");
    251 
    252    return e->GetIntField(o, f);
    253 }
    254 
    255 jshort nfc_jni_get_p2p_device_mode(JNIEnv *e, jobject o)
    256 {
    257    jclass c;
    258    jfieldID f;
    259 
    260    c = e->GetObjectClass(o);
    261    f = e->GetFieldID(c, "mMode", "S");
    262 
    263    return e->GetShortField(o, f);
    264 }
    265 
    266 
    267 int nfc_jni_get_connected_tech_index(JNIEnv *e, jobject o)
    268 {
    269 
    270    jclass c;
    271    jfieldID f;
    272 
    273    c = e->GetObjectClass(o);
    274    f = e->GetFieldID(c, "mConnectedTechIndex", "I");
    275 
    276    return e->GetIntField(o, f);
    277 
    278 }
    279 
    280 jint nfc_jni_get_connected_technology(JNIEnv *e, jobject o)
    281 {
    282    jclass c;
    283    jfieldID f;
    284    int connectedTech = -1;
    285 
    286    int connectedTechIndex = nfc_jni_get_connected_tech_index(e,o);
    287    jintArray techTypes = nfc_jni_get_nfc_tag_type(e, o);
    288 
    289    if ((connectedTechIndex != -1) && (techTypes != NULL) &&
    290            (connectedTechIndex < e->GetArrayLength(techTypes))) {
    291        jint* technologies = e->GetIntArrayElements(techTypes, 0);
    292        if (technologies != NULL) {
    293            connectedTech = technologies[connectedTechIndex];
    294            e->ReleaseIntArrayElements(techTypes, technologies, JNI_ABORT);
    295        }
    296    }
    297 
    298    return connectedTech;
    299 
    300 }
    301 
    302 jint nfc_jni_get_connected_technology_libnfc_type(JNIEnv *e, jobject o)
    303 {
    304    jclass c;
    305    jfieldID f;
    306    jint connectedLibNfcType = -1;
    307 
    308    int connectedTechIndex = nfc_jni_get_connected_tech_index(e,o);
    309    c = e->GetObjectClass(o);
    310    f = e->GetFieldID(c, "mTechLibNfcTypes", "[I");
    311    jintArray libNfcTypes =  (jintArray) e->GetObjectField(o, f);
    312 
    313    if ((connectedTechIndex != -1) && (libNfcTypes != NULL) &&
    314            (connectedTechIndex < e->GetArrayLength(libNfcTypes))) {
    315        jint* types = e->GetIntArrayElements(libNfcTypes, 0);
    316        if (types != NULL) {
    317            connectedLibNfcType = types[connectedTechIndex];
    318            e->ReleaseIntArrayElements(libNfcTypes, types, JNI_ABORT);
    319        }
    320    }
    321    return connectedLibNfcType;
    322 
    323 }
    324 
    325 phLibNfc_Handle nfc_jni_get_connected_handle(JNIEnv *e, jobject o)
    326 {
    327    jclass c;
    328    jfieldID f;
    329 
    330    c = e->GetObjectClass(o);
    331    f = e->GetFieldID(c, "mConnectedHandle", "I");
    332 
    333    return e->GetIntField(o, f);
    334 }
    335 
    336 phLibNfc_Handle nfc_jni_get_nfc_socket_handle(JNIEnv *e, jobject o)
    337 {
    338    jclass c;
    339    jfieldID f;
    340 
    341    c = e->GetObjectClass(o);
    342    f = e->GetFieldID(c, "mHandle", "I");
    343 
    344    return e->GetIntField(o, f);
    345 }
    346 
    347 jintArray nfc_jni_get_nfc_tag_type(JNIEnv *e, jobject o)
    348 {
    349   jclass c;
    350   jfieldID f;
    351   jintArray techtypes;
    352 
    353   c = e->GetObjectClass(o);
    354   f = e->GetFieldID(c, "mTechList","[I");
    355 
    356   /* Read the techtypes  */
    357   techtypes = (jintArray) e->GetObjectField(o, f);
    358 
    359   return techtypes;
    360 }
    361 
    362 
    363 
    364 //Display status code
    365 const char* nfc_jni_get_status_name(NFCSTATUS status)
    366 {
    367    #define STATUS_ENTRY(status) { status, #status }
    368 
    369    struct status_entry {
    370       NFCSTATUS   code;
    371       const char  *name;
    372    };
    373 
    374    const struct status_entry sNameTable[] = {
    375       STATUS_ENTRY(NFCSTATUS_SUCCESS),
    376       STATUS_ENTRY(NFCSTATUS_FAILED),
    377       STATUS_ENTRY(NFCSTATUS_INVALID_PARAMETER),
    378       STATUS_ENTRY(NFCSTATUS_INSUFFICIENT_RESOURCES),
    379       STATUS_ENTRY(NFCSTATUS_TARGET_LOST),
    380       STATUS_ENTRY(NFCSTATUS_INVALID_HANDLE),
    381       STATUS_ENTRY(NFCSTATUS_MULTIPLE_TAGS),
    382       STATUS_ENTRY(NFCSTATUS_ALREADY_REGISTERED),
    383       STATUS_ENTRY(NFCSTATUS_FEATURE_NOT_SUPPORTED),
    384       STATUS_ENTRY(NFCSTATUS_SHUTDOWN),
    385       STATUS_ENTRY(NFCSTATUS_ABORTED),
    386       STATUS_ENTRY(NFCSTATUS_REJECTED ),
    387       STATUS_ENTRY(NFCSTATUS_NOT_INITIALISED),
    388       STATUS_ENTRY(NFCSTATUS_PENDING),
    389       STATUS_ENTRY(NFCSTATUS_BUFFER_TOO_SMALL),
    390       STATUS_ENTRY(NFCSTATUS_ALREADY_INITIALISED),
    391       STATUS_ENTRY(NFCSTATUS_BUSY),
    392       STATUS_ENTRY(NFCSTATUS_TARGET_NOT_CONNECTED),
    393       STATUS_ENTRY(NFCSTATUS_MULTIPLE_PROTOCOLS),
    394       STATUS_ENTRY(NFCSTATUS_DESELECTED),
    395       STATUS_ENTRY(NFCSTATUS_INVALID_DEVICE),
    396       STATUS_ENTRY(NFCSTATUS_MORE_INFORMATION),
    397       STATUS_ENTRY(NFCSTATUS_RF_TIMEOUT),
    398       STATUS_ENTRY(NFCSTATUS_RF_ERROR),
    399       STATUS_ENTRY(NFCSTATUS_BOARD_COMMUNICATION_ERROR),
    400       STATUS_ENTRY(NFCSTATUS_INVALID_STATE),
    401       STATUS_ENTRY(NFCSTATUS_NOT_REGISTERED),
    402       STATUS_ENTRY(NFCSTATUS_RELEASED),
    403       STATUS_ENTRY(NFCSTATUS_NOT_ALLOWED),
    404       STATUS_ENTRY(NFCSTATUS_INVALID_REMOTE_DEVICE),
    405       STATUS_ENTRY(NFCSTATUS_SMART_TAG_FUNC_NOT_SUPPORTED),
    406       STATUS_ENTRY(NFCSTATUS_READ_FAILED),
    407       STATUS_ENTRY(NFCSTATUS_WRITE_FAILED),
    408       STATUS_ENTRY(NFCSTATUS_NO_NDEF_SUPPORT),
    409       STATUS_ENTRY(NFCSTATUS_EOF_NDEF_CONTAINER_REACHED),
    410       STATUS_ENTRY(NFCSTATUS_INVALID_RECEIVE_LENGTH),
    411       STATUS_ENTRY(NFCSTATUS_INVALID_FORMAT),
    412       STATUS_ENTRY(NFCSTATUS_INSUFFICIENT_STORAGE),
    413       STATUS_ENTRY(NFCSTATUS_FORMAT_ERROR),
    414    };
    415 
    416    int i = sizeof(sNameTable)/sizeof(status_entry);
    417 
    418    while(i>0)
    419    {
    420       i--;
    421       if (sNameTable[i].code == PHNFCSTATUS(status))
    422       {
    423          return sNameTable[i].name;
    424       }
    425    }
    426 
    427    return "UNKNOWN";
    428 }
    429 
    430 int addTechIfNeeded(int *techList, int* handleList, int* typeList, int listSize,
    431         int maxListSize, int techToAdd, int handleToAdd, int typeToAdd) {
    432     bool found = false;
    433     for (int i = 0; i < listSize; i++) {
    434         if (techList[i] == techToAdd) {
    435             found = true;
    436             break;
    437         }
    438     }
    439     if (!found && listSize < maxListSize) {
    440         techList[listSize] = techToAdd;
    441         handleList[listSize] = handleToAdd;
    442         typeList[listSize] = typeToAdd;
    443         return listSize + 1;
    444     }
    445     else {
    446         return listSize;
    447     }
    448 }
    449 
    450 
    451 #define MAX_NUM_TECHNOLOGIES 32
    452 
    453 /*
    454  *  Utility to get a technology tree and a corresponding handle list from a detected tag.
    455  */
    456 void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList,
    457         uint8_t count, jintArray* techList, jintArray* handleList,
    458         jintArray* libnfcTypeList)
    459 {
    460    int technologies[MAX_NUM_TECHNOLOGIES];
    461    int handles[MAX_NUM_TECHNOLOGIES];
    462    int libnfctypes[MAX_NUM_TECHNOLOGIES];
    463 
    464    int index = 0;
    465    // TODO: This counts from up to down because on multi-protocols, the
    466    // ISO handle is usually the second, and we prefer the ISO. Should implement
    467    // a method to find the "preferred handle order" and use that instead,
    468    // since we shouldn't have dependencies on the tech list ordering.
    469    for (int target = count - 1; target >= 0; target--) {
    470        int type = devList[target].psRemoteDevInfo->RemDevType;
    471        int handle = devList[target].hTargetDev;
    472        switch (type)
    473        {
    474           case phNfc_eISO14443_A_PICC:
    475           case phNfc_eISO14443_4A_PICC:
    476             {
    477               index = addTechIfNeeded(technologies, handles, libnfctypes, index,
    478                       MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_4, handle, type);
    479               break;
    480             }
    481           case phNfc_eISO14443_4B_PICC:
    482             {
    483               index = addTechIfNeeded(technologies, handles, libnfctypes, index,
    484                       MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_4, handle, type);
    485               index = addTechIfNeeded(technologies, handles, libnfctypes, index,
    486                       MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3B, handle, type);
    487             }break;
    488           case phNfc_eISO14443_3A_PICC:
    489             {
    490               index = addTechIfNeeded(technologies, handles, libnfctypes,
    491                       index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3A, handle, type);
    492             }break;
    493           case phNfc_eISO14443_B_PICC:
    494             {
    495               // TODO a bug in libnfc will cause 14443-3B only cards
    496               // to be returned as this type as well, but these cards
    497               // are very rare. Hence assume it's -4B
    498               index = addTechIfNeeded(technologies, handles, libnfctypes,
    499                       index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_4, handle, type);
    500               index = addTechIfNeeded(technologies, handles, libnfctypes,
    501                       index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3B, handle, type);
    502             }break;
    503           case phNfc_eISO15693_PICC:
    504             {
    505               index = addTechIfNeeded(technologies, handles, libnfctypes,
    506                       index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO15693, handle, type);
    507             }break;
    508           case phNfc_eMifare_PICC:
    509             {
    510               // We don't want to be too clever here; libnfc has already determined
    511               // it's a Mifare, so we only check for UL, for all other tags
    512               // we assume it's a mifare classic. This should make us more
    513               // future-proof.
    514               int sak = devList[target].psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak;
    515               switch(sak)
    516               {
    517                 case 0x00:
    518                   // could be UL or UL-C
    519                   index = addTechIfNeeded(technologies, handles, libnfctypes,
    520                           index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_MIFARE_UL, handle, type);
    521                   break;
    522                 default:
    523                   index = addTechIfNeeded(technologies, handles, libnfctypes,
    524                           index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_MIFARE_CLASSIC, handle, type);
    525                   break;
    526               }
    527             }break;
    528           case phNfc_eFelica_PICC:
    529             {
    530               index = addTechIfNeeded(technologies, handles, libnfctypes,
    531                       index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_FELICA, handle, type);
    532             }break;
    533           case phNfc_eJewel_PICC:
    534             {
    535               // Jewel represented as NfcA
    536               index = addTechIfNeeded(technologies, handles, libnfctypes,
    537                       index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3A, handle, type);
    538             }break;
    539           default:
    540             {
    541               index = addTechIfNeeded(technologies, handles, libnfctypes,
    542                       index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_UNKNOWN, handle, type);
    543             }
    544         }
    545    }
    546 
    547    // Build the Java arrays
    548    if (techList != NULL) {
    549        *techList = e->NewIntArray(index);
    550        e->SetIntArrayRegion(*techList, 0, index, technologies);
    551    }
    552 
    553    if (handleList != NULL) {
    554        *handleList = e->NewIntArray(index);
    555        e->SetIntArrayRegion(*handleList, 0, index, handles);
    556    }
    557 
    558    if (libnfcTypeList != NULL) {
    559        *libnfcTypeList = e->NewIntArray(index);
    560        e->SetIntArrayRegion(*libnfcTypeList, 0, index, libnfctypes);
    561    }
    562 }
    563 
    564 } // namespace android
    565