In java there is an optimal buffer size of 32 Kb which is based solely on the cpu architecture being used. On Android phones does the Dalvik VM dynamically know the proper cache of the cpu to get the largest buffer size independent of the many different phones out there? If so how would I figure that out at runtime?
Say I want to optimize a audio recording activity by making the buffer the largest it can be and also the fastest. I know you can get the minimal size for it but what about the optimal size?
Maybe it depends on what device you have or mind.
However, experimentally, 8K < buffer size < 32K does work well and there are significant performance improvements under 8K. Somewhat interesting is that some data with buffer > 64K showed poorer performance than data with under 64K buffer
(I've tested on several android devices and tried to read 20MB binary file with various buffer size.)
Here's exp result and you'd better to paste them to spreadsheet if you wanna convert data in pretty form. header means buffer size and units are millisecond
graph: http://fb.com/photo.php?fbid=468345876512381
128 256 512 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M 2M 4M 8M 16M
Galaxy S 4047 3060 269 155 100 65 64 52 51 45 47 50 49 43 44 46 45 58
Optimus LTE 1178 617 322 172 101 65 47 42 41 35 36 39 44 61 56 51 72 60
HTC EVO 3971 1884 941 480 251 141 95 69 56 50 48 55 50 49 48 48 48 47
Galaxy S2 750 383 210 123 74 50 41 37 35 34 34 37 39 44 46 44 45 44
Galaxy Nexus 2272 1216 659 341 187 108 70 52 41 38 38 45 44 54 56 66 68 58
Galaxy Note 1549 799 404 220 127 75 58 54 52 56 52 45 44 62 43 39 44 46
InputStream in = openFileInput(FILE_NAME);
startTime = System.currentTimeMillis();
while (in.read(buffer) > 0) {
readCount++;
}
elapsedTime = System.currentTimeMillis() - startTime;
Related
I am working on android app which is used to read sugar level from BLE device (Any Glocometer) whenever new data available. I am able to read data from device. Below is the HEX formatted data i received.
0B 04 00 E4 07 05 0E 0C 31 1D 4E 01 68 B0 F8 00 00
Field3: Date Time (54 bits): E4 07 05 0E 0C 31 1D
I am not able to get year from this data, value of E4 is 228 and what about 07
Other data is month, date, hour, minute, second
How to get year from the above datetime data. Any help
For me, it looks like it's 2020 May(or June) 14, 12:49:29. In a case like this wherein the document protocol is not available, we can do some guessing.
07E4 => 2020 - E4 is low byte and 07 is high byte - this is a common practice
05 => May - It's my guess that this is the month. The other numbers are more than 12. It can also be June if 00 represents January
0E => 14 - Since it follows after the month byte, I guess this is the day.
0C => 12 - It's my guess that this is the hour, 49 and 29 can never be the hour value
31 => 49 - minute
1D => 29 - second
This can be verified by getting the actual values in the glucometer and see if it matches to the parsed data.
This has a very detailed explanation on how to decode the data.
The data format is given at: https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.glucose_measurement.xml
Using this format, what I understood was if we convert your hex (
0B 04 00 E4 07 05 0E 0C 31 1D 4E 01 68 B0 F8 00 00
) to binary and then look at it byte by byte, we'll be able to decode the data. For eg. :
(Here I have prepended the binary 1011 with 0000)
Bytes
76543210 : Bit index (Remember Little Endian)
00001011 11 | 1 byte (Flag byte) | C1,C2,C5 are present
00000100 4 | 2 byte Sequence Number
00000000 0 | 4 + (0<<8) = 4 [Because Little Endian]
11100100 228 | 228 + (7<<8) = 228 + (1792) = 2020
00000111 7
00000101 5 | 1 byte | 5 = May
00001110 14 | 1 byte | 14 = Date
00001100 12 | 1 byte | 12 = Hour
00110001 49 | 1 byte | 49 = Minute
00011101 29 | 1 byte | 29 = seconds
01001110 78 | 2 byte | 78 + (1<<8) = 334 Time Offset
00000001 1
01101000 0.104 | Glucose reading in kg/l
10110000 | SFLOAT datatype of 2 bytes where first 12 bytes are mantissa and next 4 bits give exponent. Therefore 000001101000 = 104 | 1011 = -3. Thereby total value = 104 * 10^-3 = 0.104 kg/mol
11111000 | 2 Nibbles (values are 8 and 15)
00000000 0 | 7 6 5 4 3 2 1 0 Bit indexes
00000000 0 | 15 14 13 12 11 10 9 8 Bit indexes
When reading a MIFARE card with Android and converting the data to UTF-8 I get strange characters like �.
I'm trying to build an application that can read some kind of ID card we're using. The problem now is that I get weird characters between words and some words are split between blocks so how can I safely get a word I'm looking for?
For instance my readings is something like this:
43224���19032019��
at block 2 sektor 2 bindex :8
and with splitting where rest of the number starting with 19 is at a new block:
�me Name���M���19
at block 1 sektor 1 bindex :4
930402���NO934951
at block 2 sektor 1 bindex :4
c5 42 4e 49 44 00 07 4f 4f 4f 4f 4f 4f 00 4b 42 "Åbnid" "OOOOOO" "KB"
44 44 44 20 44 44 44 44 44 00 82 4d 00 c9 31 39 "DDD DDDDD" "M" "19"
39 34 34 33 34 32 00 d0 4e 4f 39 36 36 36 35 31 "944342" "NO966651"
00 00 00 00 00 00 70 f7 88 00 00 00 00 00 00 00
30 32 32 20 20 41 53 00 d3 54 4f 54 41 4c 20 4b "022" "AS" "Total k"
4f 4e 54 52 4f 4c 4c 20 41 53 20 00 c9 30 32 38 "ONTROLL AS" "028"
37 30 34 33 33 00 c9 32 30 32 31 30 32 31 31 00 "70433" "20210211"
00 00 00 00 00 00 70 f7 88 00 00 00 00 00 00 00
This is how I read from the card:
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
MifareClassic mfc = MifareClassic.get(tagFromIntent);
Here is my code I use for reading inside a for loop:
data = mfc.readBlock(bIndex + block);
and then for converting data to UTF8 for printing I use:
public String convertByteArrayToUTF8(byte[] bytes){
String encoded = null;
try {
encoded = new String(bytes, StandardCharsets.UTF_8);
}
catch (Exception e){
encoded = new String(bytes, Charset.defaultCharset());
}
return encoded;
}
I've tried with ASCII, UTF-16 etc with no luck.
First of all LOL for the question heading. I was in the same situation when I was a newbie. There is no tutorial online that provides you the exact code to read data from a Mifare classic card.
First understand the memory structure of the Mifare cards.
The memory of Mifare Classic divided into sectors, which are also divided into blocks of 16 bytes.
The MIFARE Classic 1K card has 16 sectors, each of which are divided into four blocks. If we do the math, we can figure out how the memory structure would be like: 16 bytes (1 block) * 4 blocks * 16 sectors = 1024 bytes.
The MIFARE Classic 4K card has 40 sectors, 32 of which are divided into four blocks and the remaining 8 are divided into 16 blocks. 16 bytes (1 block) * 4 blocks * 32 sectors + 16 bytes (1 block) * 16 blocks * 8 sectors = 4096 bytes. The memory structure is as follows:
The number on the blocks indicates its index. Each sector is protected by the site key written in the last block of the sector. For example, block 3 contains the site key for sector 1 and block 7 for sector 2. The last block in each sector also contains access conditions information such as “write”, “read” and “read & write”. The following figure demonstrates how the last block consists of:
Moreover, the data written in the card is binary i.e; 0 & 1.
Now, the steps you need to follow to read the data are:
step1: check whether the device support NFC or not.
step2: check if the device has NXP chip (especially for reading Mifare classic cards).
step3: instantiate the NFC manager and NFC adpater & define the techlist of card that you want to read.
step4: ask permission to access device NFC.
step5: create a intent to detect card and specify the MIME type you want to read(in most cases it is all MIME types).
step6: enable and disable foreground dispatch of adapter in onResume() and onPause() so that your app gets the priority to read the card when your activity is in foreground.
step7: When card comes in contact to device, you can get the tag information from intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
step8: read the card information i.e; card type, tech list etc..
step9: to read the data in the card you need to connect to the card via tag info retrieved above.
step10: iterate through all the sectors. Authenticate each sector with the default key
//https://developer.android.com/reference/android/nfc/tech/MifareClassic.html#authenticateSectorWithKeyA(int,%20byte[])
step11: on successful authentication read the binary data in the blocks of each sector.
step12: convert the binary data to string data so that we can read it.
step13: That's all, do whatever you want to do with the data.
surprise! get the complete working code at my github repositiory here:
https://github.com/codes29/RFIDReader
Note: I empathised how you feeling as a newbie and got this task where there is no proper tutorial for the same. So I updated my code that I wrote after a lot of struggle for days.
Here's the sample that you'll get after successful authentication and reading the data. The card that I scanned is empty as per now. But if there is data here then it'll surely be here instead of 0's.
Cheers! Happy coding bro!
So the data on your tag (excluding the sector trailers looks somewhat like that:
C5 42 4E 49 44 00 07 4F 4F 4F 4F 4F 4F 00 4B 42 ÅBNID..OOOOOO.KB
44 44 44 20 44 44 44 44 44 00 82 4D 00 C9 31 39 DDD DDDDD.‚M.É19
39 34 34 33 34 32 00 D0 4E 4F 39 36 36 36 35 31 944342.ÐNO966651
30 32 32 20 20 41 53 00 D3 54 4F 54 41 4C 20 4B 022 AS.ÓTOTAL K
4F 4E 54 52 4F 4C 4C 20 41 53 20 00 C9 30 32 38 ONTROLL AS .É028
37 30 34 33 33 00 C9 32 30 32 31 30 32 31 31 00 70433.É20210211.
This seems to be some form of structured data. Simply converting the whole binary blob into a UTF-8 (or ASCII) encoded string doesn't make much sense. Instead, you will need to reverse engineer the way that the data is structured (or, even better, you try to obtain the specification from the system manufacturer).
From what I can see, it looks as if that data consisted of multiple null-terminated strings embedded into some compact (Tag)-Length-Value format. The first byte seems to be the tag(?) + length, so we have
C5 Length = 5
42 4E 49 44 00 "BNID"
07 Length = 7
4F 4F 4F 4F 4F 4F 00 "OOOOOO"
4B Length = 11
42 44 44 44 20 44 44 44 44 44 00 "KBDDD DDDDD"
82 Length = 2
4D 00 "M"
C9 Length = 9
31 39 39 34 34 33 34 32 00 "19944342"
D0 Length = 16
4E 4F 39 36 36 36 35 31 30 32 32 20 20 41 53 00 "NO966651022 AS"
D3 Length = 19
54 4F 54 41 4C 20 4B 4F 4E 54 52 4F 4C 4C 20 41 53 20 00 "TOTAL KONTROLL AS "
C9 Length = 9
30 32 38 37 30 34 33 33 00 "02870433"
C9 Length = 9
32 30 32 31 30 32 31 31 00 "20210211"
The first byte could, for instance, be split into tag and length like this: TTTL LLLL (upper 3 bits encode the tag, lower 5 bits encode the length of the following value). This would give the following tags
0x6 for "BNID", "19944342", "NO966651022 AS", "TOTAL KONTROLL AS ", "02870433", and "20210211"
0x0 for "OOOOOO"
0x2 for "KBDDD DDDDD"
0x4 for "M"
Hence, the split between tag and length might also be TTLL LLLL (upper 2 bits encode the tag, lower 6 bits encode the length of the following value).
Unfortunately, the format doesn't resemble any of the popular formats that I'm aware of. So you could just continue your reverse engineering by comparing multiple different cards and by deriving meaning from the values.
So far, in order to decode the above, you would start by reading the first byte, extract the length from that byte, cut that amount of follow-up bytes and convert them into a string (based on the sample that you provided, ASCII encoding should do). You can then continue with the next byte, extract the length information from it, ...
I'm trying to send BLE Notification from android (GAP:central, GATT:server) to peer device (GAP: peripheral, GATT: client).
The problem is that on android 5.0 there is command: BluetoothGatt.requestMtu(int mtu).
But I do not know the way how to find out if peer device support requested MTU and what is actually negotiated MTU.
The required function:
BluetoothGattCallback.onMtuChanged(BluetoothGatt gatt, int mtu, int status)
was added only in API level 22 (Android L 5.1).
My problem is that I do not know how many bytes in packet I can send.
I write a test code to send bigger packet than 20B and it seems android sends just first 20B of data and never tell me that it discarded rest of the data!!! That is terrible behavior. Either I'm missing something, or Android 5.0 is useless for bigger packets than 20 bytes :(
I wrote test code and logs prove that all is sent and returns true:
BluetoothGattCharacteristic mCharacVal;
BluetoothGattServer mGattServer;
...
//log: I/vbeOryNotify: bleNotify snd:msg body; id:27; len:60 :I should have known those alien maggots booby-trapped this s
ret = mCharacVal.setValue(toSnd);
Log.i("vbeOry","bleNotify: setValue "+AppCommon.ByteArrayToHexStr(toSnd)+" ret:"+ret);
//log: I/vbeOry: bleNotify: setValue 03 1B 00 00 00 3C 49 20 73 68 6F 75 6C 64 20 68 61 76 65 20 6B 6E 6F 77 6E 20 74 68 6F 73 65 20 61 6C 69 65 6E 20 6D 61 67 67 6F 74 73 20 62 6F 6F 62 79 2D 74 72 61 70 70 65 64 20 74 68 69 73 20 73
//log: ret:true
byte[] dataRdBck = mCharacVal.getValue();
Log.i("vbeOry","bleNotify: getValue "+AppCommon.ByteArrayToHexStr(dataRdBck));
//log: I/vbeOry: bleNotify: getValue 03 1B 00 00 00 3C 49 20 73 68 6F 75 6C 64 20 68 61 76 65 20 6B 6E 6F 77 6E 20 74 68 6F 73 65 20 61 6C 69 65 6E 20 6D 61 67 67 6F 74 73 20 62 6F 6F 62 79 2D 74 72 61 70 70 65 64 20 74 68 69 73 20 73
ret = mGattServer.notifyCharacteristicChanged(device, mCharacVal, false);
Log.i("vbeOry","bleNotify: notifyCharacteristicChanged "+AppCommon.ByteArrayToHexStr(toSnd)+" ret:"+ret);
//log: I/vbeOry: bleNotify: notifyCharacteristicChanged 03 1B 00 00 00 3C 49 20 73 68 6F 75 6C 64 20 68 61 76 65 20 6B 6E 6F 77 6E 20 74 68 6F 73 65 20 61 6C 69 65 6E 20 6D 61 67 67 6F 74 73 20 62 6F 6F 62 79 2D 74 72 61 70 70 65 64 20 74 68 69 73 20 73
//log: ret:true
Even from call back I do not get any error:
private BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() {
public void onNotificationSent(BluetoothDevice device, int status){
Log.i("vbeGattServ", "onNotificationSent status: "+status);
//log: I/vbeGattServ: onNotificationSent status: 0
but then I look with my BLE analyzer and I see that only first 20 B of notification data is send:
So my question is either how to find out negotiated MTU or at least how to find out that not all data was sent? (Constrain is Android 5.0).
Perhaps it has no solution for Android 5.0 :( And I have to stick with 20B even when both device could support higher. Only work around would be to implement mechanism for returning MTU from peer device as was suggested here on stack overflow.
Your issue is not Android but Bluetooth / the app running on your central.
Increasing the useful data size from 20B is only possible with BLE v4.2 and newer. I suppose your radio is running with BLE v4.0 or v4.1 or there is an issue setting up your MTU.
Either way this should not affect reading data. The central device can read a characteristic with an offset. Assuming you have 60B, you would have 3 requests from the central:
Read, offset=0
Read, offset=20
Read, offset=40
TL;DR: Your GATT central simply handles reads wrong.
What factors do I need to look at when benchmarking the performance of an android device with swap enabled? and what applications are recommended to use if there are any?
Enabling swap requires the phone to be rooted and it's kernel to support swap. "a-swapper" is one of the applications I use for enabling swap, basically it launches commands to enable swap. The swap file or swap partition is located at the external SD card.
Link to "a-swapper" at google code:
http://code.google.com/p/a-swapper/
Following is a report of my paging tests on a Raspberry Pi (ARM CPU, 512 MB RAM, SD drive). A test program writes and reads increasing volumes of data, checking for correct results and measuring speed in MB/second. Data sizes reported are 350, 400, 420 and 600 MB. Speed was at about one tenth max at 420 MB and three times slower at 600 MB. Links are included to obtain the benchmarks and C source code (FREE for anyone to play with and no Ads on any pages). As with my other benchmarks, this can be converted for Android.
http://www.roylongbottom.org.uk/Raspberry%20Pi%20Stress%20Tests.htm#anchor18
The report also provides vmstat monitoring of memory used, swapped, cache size, drive I/O and CPU utilisation. At least on my Android tablet, I can run vmstat via a Terminal Emulator at the same time as executing benchmarks.
For Windows and Linux, I have an image processing benchmark that increasingly enlarges images, with writing and reading to a drive, rotating and scrolling (You can find details by Googling for bmpspeed results.htm and Linux SDL Image Processing Benchmarks). If there is a suitable photo editor for Android, you can do the same with that using manual timing, and possibly monitor with vmstat.
Paging Test Results
StressInt uses normal memory writing and reading functions. Part 1 writes then reads the specified space with six passes using different data patterns. Reading is at high speed using AND and OR to produce a sumcheck. Part 2 writes the patterns (not timed) and reads them for at least a minimum time, in this case there is only one read pass for each pattern. The four paging tests specified 350, 400, 420 and 600 MB on a Raspberry Pi that has 512 MB RAM, with the main drive being an SD card. Vmstat was run at the same time.
At 350 MB, there is no swapping, but cache and buffer sizes are reduced, slowing down the first write pass. At 400 KB, swapping in and out at start then full speed when sorted. At 420 MB, chaos, continuous data transfer to and from the drive, CPU waiting for I/O.
1. Commands Example
lxterminal -e ./stressInt KB 600000
vmstat 10 > vmburn4.txt
2. Results
MBytes Per Second At MB Data Size
MB 350 400 420 600
Write/Read No.
1 139 24 15 14
2 209 181 16 8
3 206 203 24 8
4 206 204 26 8
5 202 205 18 8
6 206 205 20 8
Write/Rd secs 19.6 48.4 204.9 460.7
Read No.
1 158 159 20 9
2 158 159 14 9
3 159 159 39 8
4 160 155 9 9
5 159 160 25 9
6 160 159 10 9
Total secs 85 125 1082 3085
vmstat si so KB swaps in and out, bi bo KB I/O in and out, wa = waiting for I/O
350 MB vmstat 10 second samples
KBytes KB KB/sec Per sec %
procs ----------memory---------- ---swap-- -----io---- -system-- ----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 0 314260 12340 56724 0 0 70 3 1123 232 19 5 76 0
1 1 4 8920 48 21844 0 0 37 10 1141 298 42 16 42 0
1 0 8 12392 64 18404 0 0 2 9 1161 89 99 1 0 0
1 0 8 12144 80 18704 0 0 30 6 1167 82 99 1 0 0
1 0 8 11896 88 18868 0 0 16 2 1157 71 99 1 0 0
1 0 8 11764 96 18972 0 0 10 7 1163 71 99 1 0 0
1 0 8 11772 104 18972 0 0 0 3 1152 61 100 0 0 0
1 0 8 11772 112 18972 0 0 0 3 1153 65 100 0 0 0
1 0 8 11772 120 18972 0 0 0 4 1154 68 100 0 0 0
1 0 8 11772 128 18972 0 0 0 3 1153 64 100 0 0 0
0 0 8 362344 136 21384 0 0 239 5 1194 294 22 4 73 1
400 MB
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 8 355220 924 26480 0 0 63 3 1125 236 24 4 72 0
1 5 92368 8968 60 5464 10 9236 338 9245 1739 587 31 20 28 21
0 2 52492 9108 44 5092 4775 3802 6938 3807 3429 1169 10 22 0 68
1 2 71168 11236 44 4920 4654 8936 4929 8936 2428 1036 6 18 0 77
1 1 42216 9224 44 4788 4477 5600 5059 5602 3313 992 37 19 0 45
1 1 40948 11008 44 4932 143 0 591 3 1391 163 98 2 0 0
1 0 40924 12248 60 5032 15 0 33 6 1170 87 98 2 0 0
1 0 40912 12116 60 5228 2 0 21 0 1155 66 99 1 0 0
1 0 40912 12000 68 5228 0 0 0 3 1152 58 100 1 0 0
1 0 40912 12000 76 5260 3 0 6 3 1154 60 100 1 0 0
1 0 40892 12000 84 5260 0 0 0 3 1153 63 99 1 0 0
1 0 40704 11628 92 5260 34 0 34 3 1167 69 100 1 0 0
1 0 40700 11628 100 5260 0 0 0 3 1153 61 100 0 0 0
0 0 37956 401996 236 12804 474 0 1208 0 1626 229 89 5 3 3
0 0 36900 400392 244 13372 103 0 160 7 1125 180 6 2 91 1
420 MB Sample
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 3 59316 8820 48 4212 4238 4269 5132 4272 3592 939 20 16 0 65
0 1 68268 11732 44 3400 4281 5112 4736 5114 3337 938 6 19 0 75
1 3 60804 8820 76 4428 4715 3860 5877 3864 3518 1007 13 17 0 70
1 1 56408 9948 44 2976 4710 4164 6948 4168 4389 1186 5 19 0 75
2 2 70864 11704 44 2068 3975 6458 4908 6461 3854 1021 7 14 0 79
Following are results on 64 bit Windows systems, essentially from same C code as on Raspberry Pi but using one write/read pass. For these tests the benchmark was run with increasing data demands up to 5, 8 and 14 GB on the three systems.
64 Bit IntBurn64 64 Bit IntBurn64 64 Bit IntBurn64
CPU Athlon 64 Core 2 Duo Phenom II
MHz 2210 2400 3000
RAM MB 1024 4096 8192
Windows XP x64 64-Bit Vista 64-Bit Windows 7
Disk W/R
MB/sec 55 55 92
KB Secs MB/sec KB Secs MB/sec KB Secs MB/sec
100000 2041 100000 3393 100000 5146
800000 1 1976 2500000 2 2868 2000000 1 4900
850000 23 77 3000000 2 2878 3000000 1 4658
900000 58 32 3100000 2 2847 3500000 2 4651
920000 61 31 3200000 2 2899 4000000 2 4488
930000 91 21 3300000 3 2698 4500000 2 4489
940000 96 20 3400000 3 2610 5000000 2 4477
950000 93 21 3500000 7 1075 5500000 3 4166
960000 89 22 3600000 10 750 6000000 3 4051
970000 142 14 3700000 17 459 6500000 3 4036
980000 125 16 3800000 107 73 7000000 4 4078
990000 119 17 3900000 210 38 7500000 72 214
1000000 128 16 4000000 146 56 7600000 170 91
1100000 188 12 7700000 168 94
1200000 205 12 5000000 1024 10 7800000 230 69
1300000 266 10 7000000 652 22 7900000 239 68
1400000 358 8 7900000 770 21 8000000 227 72
8000000 N/A 9000000 697 26
2000000 683 6 10000000 1231 17
2100000 14000000 2742 10
5000000 1707 6 15000000 N/A
BMPSpeed Benchmark generates BMP files up to 512 MB. It measures speed of saving, loading, scrolling, rotating and editing/enlarging of 0.5, 1, 2, 4 etc. MB files upwards. Memory used is up to 2.5 times image size. The original had to be modifies for a Windows XP as 1.25 GB of sequential memory space could not be allocated. The first example below reflects paging at 256 MB but some memory would be cleared for a rerun. A second problem arises on later systems, with more graphics RAM, where fast BitBlt copying can be used at larger image sizes and this requires far more space than the slower StretchDIBits method.
I might produce a new 64 bit version to see if I can bust my new benchmarking toy with 32 GB RAM.
BMPSpeed Results
2.08 GHz CPU, 512 MB RAM, fast disk, slow GeForce graphics
Input Enlarge Save Load Scroll Scroll Rotate Use
Image Display Display /Repeat Overall 90 deg Fast
Mbytes Secs Secs Secs msecs MB/Sec Secs BitBlt
0.5 0.05 0.01 0.03 0.7 992.8 0.04 3
1.0 0.06 0.02 0.05 1.3 1013.2 0.06 3
2.0 0.08 0.03 0.12 2.3 1019.8 0.09 3
4.0 0.11 0.06 0.17 2.9 1032.4 0.15 3
8.0 0.15 0.14 0.43 11.4 262.7 0.25 3
16.0 0.24 0.29 0.51 11.4 262.7 0.81 3
32.0 0.45 0.61 0.88 11.4 262.5 1.10 3
64.0 0.55 1.31 1.49 41.4 72.2 2.79 0
128.0 0.97 2.50 2.83 53.9 55.5 6.21 0
256.0 73.02 88.77 14.84 109.7 27.3 86.60 0
512.0 82.93 20.70 89.05 842.4 3.5 67.98 0
2.4 GHz Core 2 Duo with 4 GB RAM and 64 Bit Vista, fast GeForce
Input Enlarge Save Load Scroll Scroll Rotate Use
Image Display Display /Repeat Overall 90 deg Fast
Mbytes Secs Secs Secs msecs MB/Sec Secs BitBlt
0.5 0.05 0.01 0.05 0.1 4748.4 0.02 3
1.0 0.05 0.02 0.08 0.3 4463.6 0.03 3
2.0 0.07 0.02 0.11 1.1 2475.2 0.04 3
4.0 0.09 0.03 0.19 2.4 1866.0 0.06 3
8.0 0.13 0.08 0.31 2.9 1765.0 0.10 3
16.0 0.20 0.24 0.48 2.7 1832.5 0.17 3
32.0 0.26 0.52 0.78 2.9 1741.2 0.28 3
64.0 0.39 1.08 1.38 2.9 1760.0 0.52 3
128.0 0.68 2.37 2.63 2.9 1740.3 1.03 3
256.0 1.35 4.62 5.38 3.1 1645.6 4.39 3
512.0 27.91 13.05 10.59 3.2 1595.6 57.11 3
I am trying to communicate between PN532 and HCE on Android with ISO 7816-4 command, I am successfully select the AID (a DF), but when I select the EF under that DF (that EF does not exist, so I assume that Select command will create that EF), and then write the records to that EF but it display like this:
inList passive target
write: 4A 1 0
read: 4B 1 1 0 4 60 4 8 23 5A 4D 5 75 80 70 2
write: 40 1 0 A4 4 0 7 F0 1 2 3 4 5 6 0
read: 41 0 48 65 6C 6C 6F 20 44 65 73 6B 74 6F 70 21
Successfully hehe
48 65 6C 6C 6F 20 44 65 73 6B 74 6F 70 21 Hello Desktop!
write: 40 1 0 A4 2 C 1 1 0
read: 41 0 48 65 6C 6C 6F 20 44 65 73 6B 74 6F 70 21
Not enough space
write: 40 1 0 D2 0 0 7 42 41 4F 47 49 41 40 0
read: 41 0 4D 65 73 73 61 67 65 20 66 72 6F 6D 20 61 6E 64 72 6F 69 64 3A 20 30
Not enough space
write: 40 1 0 D2 0 2 4 44 4F 41 4E 0
read: 41 0 4D 65 73 73 61 67 65 20 66 72 6F 6D 20 61 6E 64 72 6F 69 64 3A 20 31
Not enough space
write: 40 1 0 B2 0 0 7 42 41 4F 47 49
read: 41 0 4D 65 73 73 61 67 65 20 66 72 6F 6D 20 61 6E 64 72 6F 69 64 3A 20 32
Not enough space
write: 40 1 0 B2 0 2 4 44 4F 41 4E 0
read: 41 0 4D 65 73 73 61 67 65 20 66 72 6F 6D 20 61 6E 64 72 6F 69 64 3A 20 33
Not enough space
I don't know what I am doing wrong here?
On Android, the log is :
04-15 09:36:54.024: D/HostEmulationManager(929): notifyHostEmulationData
04-15 09:36:54.024: W/System.err(17710): [B#41ed5970
04-15 09:36:54.024: I/HCEDEMO(17710): Received: ???????BAOGI
04-15 09:36:54.024: D/HostEmulationManager(929): Sending data
04-15 09:36:54.164: D/BrcmNfcJni(929): RoutingManager::stackCallback: event=0x17
04-15 09:36:54.164: D/BrcmNfcJni(929): RoutingManager::stackCallback: NFA_CE_DATA_EVT; h=0x302; data len=10
04-15 09:36:54.164: D/HostEmulationManager(929): notifyHostEmulationData
04-15 09:36:54.164: W/System.err(17710): [B#41ed5e20
04-15 09:36:54.164: I/HCEDEMO(17710): Received: ?????DOAN??
04-15 09:36:54.174: D/HostEmulationManager(929): Sending data
04-15 09:36:54.885: D/BrcmNfcJni(929): RoutingManager::stackCallback: event=0x19
04-15 09:36:54.885: D/HostEmulationManager(929): notifyHostEmulationDeactivated
04-15 09:36:54.885: I/HCEDEMO(17710): Deactivated: 0
04-15 09:36:54.885: D/HostEmulationManager(929): Unbinding from service ComponentInfo{de.grundid.hcedemo/de.grundid.hcedemo.MyHostApduService}
04-15 09:36:54.895: E/BrcmNfcNfa(929): UICC[0x0] is not activated
It displays that it can receive some data, but it misses some elements I want to transmit, but, from PN532, when I use read records, it does not display these data?
The commands that your Android HCE emulated smartcard application understands and processes are completely up to you (as long as they are formatted as valid ISO 7816-4 APDUs).
In your case, your Android HCE service obviously processes the SELECT (by DF name) APDU,
00 A4 04 00 07 F0010203040506 00
and gives this as a response:
48 65 6C 6C 6F 20 44 65 73 6B 74 6F 70 21 ("Hello Desktop!" when interpreted as ASCII)
(Note that this response is not a valid response APDU according to ISO 7816-4 as it lacks a status word.)
The next command you send is an invalid SELECT (by EF) command:
00 A4 02 0C 01 01 00
For that command, Lc should be 2 and the EF identifier should consist of two bytes if following ISO 7816-4. In response to that, your Android HCE service again sends
48 65 6C 6C 6F 20 44 65 73 6B 74 6F 70 21 ("Hello Desktop!" when interpreted as ASCII)
(Note that this response is not a valid response APDU according to ISO 7816-4 as it lacks a status word.)
So I would guess, that your Android HCE service performs a check like this:
public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
if (apdu[1] == (byte)0xA4) {
return "Hello Desktop!".getBytes("US-ASCII");
}
}
The next command that you send is a malformed WRITE RECORD command that tries to write "BAOGIA#" in the first record of the cuirrently selected file (malformed, because a WRITE RECORD command normally does not have an Le field):
00 D2 00 00 07 42 41 4F 47 49 41 40 00
As a response your Android HCE service sends:
4D 65 73 73 61 67 65 20 66 72 6F 6D 20 61 6E 64 72 6F 69 64 3A 20 30 ("Message from android: 0" when interpreted as ASCII)
(Note that this response is again not a valid response APDU according to ISO 7816-4 as it lacks a status word.)
You then repeat the WRITE RECORD command with a different record payload and after that you send two malformed READ RECORD commands:
00 D2 00 02 04 44 4F 41 4E 00
00 B2 00 00 07 42 41 4F 47 49
00 B2 00 02 04 44 4F 41 4E 00
As a response your Android HCE service sends:
4D 65 73 73 61 67 65 20 66 72 6F 6D 20 61 6E 64 72 6F 69 64 3A 20 xx ("Message from android: X" when interpreted as ASCII)
Where xx seems to be an ASCII digit X that is incremented for each received command.
So I would guess, that your Android HCE service looks like this:
private int mCommandCounter = 0;
public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
String response;
if (apdu[1] == (byte)0xA4) {
response = "Hello Desktop!";
} else {
response = "Message from android: " + Integer.toString(mCommandCounter);
++mCommandCounter;
}
return response.getBytes("US-ASCII");
}
So, to summarize this, your Android HCE service will understand and process only those commands that you (or whoever develops it) implement. So it is up to you what commands you can send to the HCE device. There is no file system behind it. ISO 7816-4 only suggests a file system layout for smartcard applications.