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