blob: 41099cb503af841ac6eda67bd6ccbea12212ee85 [file] [log] [blame]
Nick Pellybc21fde2010-10-13 17:25:24 -07001/*
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
Nick Pelly1af97f02010-10-22 06:59:54 -070017#include <stdlib.h>
18
Nick Pellybc21fde2010-10-13 17:25:24 -070019#include "jni.h"
20#include "JNIHelp.h"
21
22#include "android_nfc.h"
23
Nick Pellybc21fde2010-10-13 17:25:24 -070024namespace android {
25
26static 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 */
Jeff Hamilton5629d512010-11-08 11:36:21 -060052 TRACE("phFriNfc_NdefRecord_GetRecords(NULL)");
Nick Pellybc21fde2010-10-13 17:25:24 -070053
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 }
Jeff Hamilton5629d512010-11-08 11:36:21 -060061 TRACE("phFriNfc_NdefRecord_GetRecords(NULL) returned 0x%04x, with %d records", status, num_of_records);
Nick Pellybc21fde2010-10-13 17:25:24 -070062
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 */
Jeff Hamilton5629d512010-11-08 11:36:21 -060071 TRACE("phFriNfc_NdefRecord_GetRecords()");
Nick Pellybc21fde2010-10-13 17:25:24 -070072
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 }
Jeff Hamilton5629d512010-11-08 11:36:21 -060080 TRACE("phFriNfc_NdefRecord_GetRecords() returned 0x%04x, with %d records", status, num_of_records);
Nick Pellybc21fde2010-10-13 17:25:24 -070081
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
Martijn Coenen8bede172011-04-08 16:42:22 +020089 ctor = e->GetMethodID(record_cls, "<init>", "(S[B[B[BB)V");
Nick Pellybc21fde2010-10-13 17:25:24 -070090
Nick Pellybc21fde2010-10-13 17:25:24 -070091 for (i = 0; i < num_of_records; i++) {
92 jbyteArray type, id, payload;
93 jobject new_record;
94
Jeff Hamilton5629d512010-11-08 11:36:21 -060095 TRACE("phFriNfc_NdefRecord_Parse()");
Nick Pellybc21fde2010-10-13 17:25:24 -070096
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 }
Jeff Hamilton5629d512010-11-08 11:36:21 -0600103 TRACE("phFriNfc_NdefRecord_Parse() returned 0x%04x", status);
Nick Pellybc21fde2010-10-13 17:25:24 -0700104
Martijn Coenen0aa10172011-05-31 16:03:26 -0700105 // We don't exactly know what *is* a valid length, but a simple
106 // sanity check is to make sure that the length of the header
107 // plus all fields does not exceed raw_msg_size. The min length
108 // of the header is 3 bytes: TNF, Type Length, Payload Length
109 // (ID length field is optional!)
110 uint64_t indicatedMsgLength = 3 + record.TypeLength + record.IdLength +
111 (uint64_t)record.PayloadLength;
112 if (indicatedMsgLength >
113 (uint64_t)raw_msg_size) {
114 LOGE("phFri_NdefRecord_Parse: invalid length field");
115 goto end;
116 }
117
Nick Pellybc21fde2010-10-13 17:25:24 -0700118 type = e->NewByteArray(record.TypeLength);
119 if (type == NULL) {
120 LOGD("NFC_Set Record Type Error\n");
121 goto end;
122 }
123
124 id = e->NewByteArray(record.IdLength);
125 if(id == NULL) {
126 LOGD("NFC_Set Record ID Error\n");
127 goto end;
128 }
129
130 payload = e->NewByteArray(record.PayloadLength);
131 if(payload == NULL) {
132 LOGD("NFC_Set Record Payload Error\n");
133 goto end;
134 }
135
136 e->SetByteArrayRegion(type, 0, record.TypeLength,
137 (jbyte *)record.Type);
138 e->SetByteArrayRegion(id, 0, record.IdLength,
139 (jbyte *)record.Id);
140 e->SetByteArrayRegion(payload, 0, record.PayloadLength,
141 (jbyte *)record.PayloadData);
142
143 new_record = e->NewObject(record_cls, ctor,
Martijn Coenen8bede172011-04-08 16:42:22 +0200144 (jshort)record.Tnf, type, id, payload, (jbyte)record.Flags);
Nick Pellybc21fde2010-10-13 17:25:24 -0700145
146 e->SetObjectArrayElement(records_array, i, new_record);
147
148 /* Try not to clutter the Java stack too much */
149 e->DeleteLocalRef(new_record);
150 e->DeleteLocalRef(type);
151 e->DeleteLocalRef(id);
152 e->DeleteLocalRef(payload);
153 }
154
155 /* Store built array in our NDEFMessage instance */
156 msg_cls = e->GetObjectClass(o);
157 mrecords = e->GetFieldID(msg_cls, "mRecords", "[Landroid/nfc/NdefRecord;");
158
159 e->SetObjectField(o, mrecords, (jobject)records_array);
160
161 ret = 0;
162
163end:
164 if(is_chunked)
165 free(is_chunked);
166 if(records)
167 free(records);
168 e->ReleaseByteArrayElements(array, raw_msg, JNI_ABORT);
169
170 return ret;
171}
172
173static JNINativeMethod gMethods[] = {
174 {"parseNdefMessage", "([B)I", (void *)android_nfc_NdefMessage_parseNdefMessage},
175};
176
177int register_android_nfc_NdefMessage(JNIEnv *e)
178{
179 return jniRegisterNativeMethods(e, "android/nfc/NdefMessage", gMethods, NELEM(gMethods));
180}
181
182} // namespace android