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 "jni.h"
     20 #include "JNIHelp.h"
     21 
     22 #include "android_nfc.h"
     23 
     24 namespace android {
     25 
     26 static jint android_nfc_NdefMessage_parseNdefMessage(JNIEnv *e, jobject o,
     27         jbyteArray array)
     28 {
     29     uint16_t status;
     30     uint32_t i;
     31     jbyte *raw_msg;
     32     jsize raw_msg_size;
     33     uint32_t num_of_records = 0;
     34     uint8_t **records = NULL;
     35     uint8_t *is_chunked = NULL;
     36     jint ret = -1;
     37     phFriNfc_NdefRecord_t record;
     38 
     39     jclass record_cls;
     40     jobjectArray records_array;
     41     jmethodID ctor;
     42 
     43     jclass msg_cls;
     44     jfieldID mrecords;
     45 
     46     raw_msg_size = e->GetArrayLength(array);
     47     raw_msg = e->GetByteArrayElements(array, NULL);
     48     if (raw_msg == NULL)
     49         return -1;
     50 
     51     /* Get the number of records in the message so we can allocate buffers */
     52     TRACE("phFriNfc_NdefRecord_GetRecords(NULL)");
     53 
     54     status = phFriNfc_NdefRecord_GetRecords((uint8_t *)raw_msg,
     55             (uint32_t)raw_msg_size, NULL, NULL, &num_of_records);
     56 
     57     if (status) {
     58         LOGE("phFriNfc_NdefRecord_GetRecords(NULL) returned 0x%04x", status);
     59         goto end;
     60     }
     61     TRACE("phFriNfc_NdefRecord_GetRecords(NULL) returned 0x%04x, with %d records", status, num_of_records);
     62 
     63     is_chunked = (uint8_t*)malloc(num_of_records);
     64     if (is_chunked == NULL)
     65         goto end;
     66     records = (uint8_t**)malloc(num_of_records * sizeof(uint8_t *));
     67     if (records == NULL)
     68         goto end;
     69 
     70     /* Now, actually retrieve records position in message */
     71     TRACE("phFriNfc_NdefRecord_GetRecords()");
     72 
     73     status = phFriNfc_NdefRecord_GetRecords((uint8_t *)raw_msg,
     74             (uint32_t)raw_msg_size, records, is_chunked, &num_of_records);
     75 
     76     if (status) {
     77         LOGE("phFriNfc_NdefRecord_GetRecords() returned 0x%04x", status);
     78         goto end;
     79     }
     80     TRACE("phFriNfc_NdefRecord_GetRecords() returned 0x%04x, with %d records", status, num_of_records);
     81 
     82     /* Build NDEF records array */
     83     record_cls = e->FindClass("android/nfc/NdefRecord");
     84     records_array = e->NewObjectArray((jsize)num_of_records, record_cls,
     85             NULL);
     86     if (records_array == NULL)
     87         goto end;
     88 
     89     ctor = e->GetMethodID(record_cls, "<init>", "(S[B[B[B)V");
     90 
     91     for (i = 0; i < num_of_records; i++) {
     92         jbyteArray type, id, payload;
     93         jobject new_record;
     94 
     95         TRACE("phFriNfc_NdefRecord_Parse()");
     96 
     97         status = phFriNfc_NdefRecord_Parse(&record, records[i]);
     98 
     99         if (status) {
    100             LOGE("phFriNfc_NdefRecord_Parse() returned 0x%04x", status);
    101             goto end;
    102         }
    103         TRACE("phFriNfc_NdefRecord_Parse() returned 0x%04x", status);
    104 
    105         type = e->NewByteArray(record.TypeLength);
    106         if (type == NULL) {
    107             LOGD("NFC_Set Record Type Error\n");
    108             goto end;
    109         }
    110 
    111         id = e->NewByteArray(record.IdLength);
    112         if(id == NULL) {
    113             LOGD("NFC_Set Record ID Error\n");
    114             goto end;
    115         }
    116 
    117         payload = e->NewByteArray(record.PayloadLength);
    118         if(payload == NULL) {
    119             LOGD("NFC_Set Record Payload Error\n");
    120             goto end;
    121         }
    122 
    123         e->SetByteArrayRegion(type, 0, record.TypeLength,
    124                 (jbyte *)record.Type);
    125         e->SetByteArrayRegion(id, 0, record.IdLength,
    126                 (jbyte *)record.Id);
    127         e->SetByteArrayRegion(payload, 0, record.PayloadLength,
    128                 (jbyte *)record.PayloadData);
    129 
    130         new_record = e->NewObject(record_cls, ctor,
    131                 (jshort)record.Tnf, type, id, payload);
    132 
    133         e->SetObjectArrayElement(records_array, i, new_record);
    134 
    135         /* Try not to clutter the Java stack too much */
    136         e->DeleteLocalRef(new_record);
    137         e->DeleteLocalRef(type);
    138         e->DeleteLocalRef(id);
    139         e->DeleteLocalRef(payload);
    140     }
    141 
    142     /* Store built array in our NDEFMessage instance */
    143     msg_cls = e->GetObjectClass(o);
    144     mrecords = e->GetFieldID(msg_cls, "mRecords", "[Landroid/nfc/NdefRecord;");
    145 
    146     e->SetObjectField(o, mrecords, (jobject)records_array);
    147 
    148     ret = 0;
    149 
    150 end:
    151     if(is_chunked)
    152         free(is_chunked);
    153     if(records)
    154         free(records);
    155     e->ReleaseByteArrayElements(array, raw_msg, JNI_ABORT);
    156 
    157     return ret;
    158 }
    159 
    160 static JNINativeMethod gMethods[] = {
    161         {"parseNdefMessage", "([B)I", (void *)android_nfc_NdefMessage_parseNdefMessage},
    162 };
    163 
    164 int register_android_nfc_NdefMessage(JNIEnv *e)
    165 {
    166     return jniRegisterNativeMethods(e, "android/nfc/NdefMessage", gMethods, NELEM(gMethods));
    167 }
    168 
    169 } // namespace android
    170