1d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka/* 2d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Copyright (C) 2006 The Android Open Source Project 3d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 4d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Licensed under the Apache License, Version 2.0 (the "License"); 5d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * you may not use this file except in compliance with the License. 6d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * You may obtain a copy of the License at 7d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 8d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * http://www.apache.org/licenses/LICENSE-2.0 9d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 10d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Unless required by applicable law or agreed to in writing, software 11d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * distributed under the License is distributed on an "AS IS" BASIS, 12d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * See the License for the specific language governing permissions and 14d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * limitations under the License. 15d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka */ 16d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 17d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkapackage com.android.internal.telephony.uicc; 18d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 19d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport android.content.res.Resources; 20d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport android.content.res.Resources.NotFoundException; 21d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport android.graphics.Bitmap; 22d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport android.graphics.Color; 23d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport android.telephony.Rlog; 24d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 25d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.GsmAlphabet; 26d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport java.io.UnsupportedEncodingException; 27d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 28d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka/** 29d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Various methods, useful for dealing with SIM data. 30d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka */ 31d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkapublic class IccUtils { 32d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka static final String LOG_TAG="IccUtils"; 33d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 34d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka /** 35d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Many fields in GSM SIM's are stored as nibble-swizzled BCD 36d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 37d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Assumes left-justified field that may be padded right with 0xf 38d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * values. 39d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 40d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Stops on invalid BCD value, returning string so far 41d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka */ 42d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka public static String 43d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka bcdToString(byte[] data, int offset, int length) { 44d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka StringBuilder ret = new StringBuilder(length*2); 45d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 46d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka for (int i = offset ; i < offset + length ; i++) { 47d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka byte b; 48d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int v; 49d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 50d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka v = data[i] & 0xf; 51d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (v > 9) break; 52d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret.append((char)('0' + v)); 53d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 54d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka v = (data[i] >> 4) & 0xf; 55d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // Some PLMNs have 'f' as high nibble, ignore it 56d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (v == 0xf) continue; 57d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (v > 9) break; 58d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret.append((char)('0' + v)); 59d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 60d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 61d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return ret.toString(); 62d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 63d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 64d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka /** 65d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Decode cdma byte into String. 66d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka */ 67d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka public static String 68d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka cdmaBcdToString(byte[] data, int offset, int length) { 69d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka StringBuilder ret = new StringBuilder(length); 70d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 71d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int count = 0; 72d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka for (int i = offset; count < length; i++) { 73d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int v; 74d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka v = data[i] & 0xf; 75d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (v > 9) v = 0; 76d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret.append((char)('0' + v)); 77d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 78d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (++count == length) break; 79d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 80d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka v = (data[i] >> 4) & 0xf; 81d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (v > 9) v = 0; 82d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret.append((char)('0' + v)); 83d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ++count; 84d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 85d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return ret.toString(); 86d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 87d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 88d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka /** 89d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Decodes a GSM-style BCD byte, returning an int ranging from 0-99. 90d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 91d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * In GSM land, the least significant BCD digit is stored in the most 92d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * significant nibble. 93d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 94d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Out-of-range digits are treated as 0 for the sake of the time stamp, 95d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * because of this: 96d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 97d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * TS 23.040 section 9.2.3.11 98d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * "if the MS receives a non-integer value in the SCTS, it shall 99d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * assume the digit is set to 0 but shall store the entire field 100d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * exactly as received" 101d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka */ 102d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka public static int 103d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka gsmBcdByteToInt(byte b) { 104d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int ret = 0; 105d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 106d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // treat out-of-range BCD values as 0 107d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if ((b & 0xf0) <= 0x90) { 108d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret = (b >> 4) & 0xf; 109d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 110d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 111d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if ((b & 0x0f) <= 0x09) { 112d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret += (b & 0xf) * 10; 113d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 114d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 115d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return ret; 116d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 117d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 118d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka /** 119cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville * Decodes a CDMA style BCD byte like {@link #gsmBcdByteToInt}, but 120d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * opposite nibble format. The least significant BCD digit 121d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * is in the least significant nibble and the most significant 122d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * is in the most significant nibble. 123d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka */ 124d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka public static int 125d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka cdmaBcdByteToInt(byte b) { 126d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int ret = 0; 127d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 128d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // treat out-of-range BCD values as 0 129d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if ((b & 0xf0) <= 0x90) { 130d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret = ((b >> 4) & 0xf) * 10; 131d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 132d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 133d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if ((b & 0x0f) <= 0x09) { 134d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret += (b & 0xf); 135d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 136d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 137d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return ret; 138d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 139d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 140d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka /** 141d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Decodes a string field that's formatted like the EF[ADN] alpha 142d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * identifier 143d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 144d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * From TS 51.011 10.5.1: 145d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Coding: 146d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * this alpha tagging shall use either 147d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * - the SMS default 7 bit coded alphabet as defined in 148d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * TS 23.038 [12] with bit 8 set to 0. The alpha identifier 149d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * shall be left justified. Unused bytes shall be set to 'FF'; or 150d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * - one of the UCS2 coded options as defined in annex B. 151d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 152d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Annex B from TS 11.11 V8.13.0: 153d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 1) If the first octet in the alpha string is '80', then the 154d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * remaining octets are 16 bit UCS2 characters ... 155d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 2) if the first octet in the alpha string is '81', then the 156d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * second octet contains a value indicating the number of 157d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * characters in the string, and the third octet contains an 158d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 8 bit number which defines bits 15 to 8 of a 16 bit 159d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * base pointer, where bit 16 is set to zero and bits 7 to 1 160d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * are also set to zero. These sixteen bits constitute a 161d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * base pointer to a "half page" in the UCS2 code space, to be 162d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * used with some or all of the remaining octets in the string. 163d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * The fourth and subsequent octets contain codings as follows: 164d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * If bit 8 of the octet is set to zero, the remaining 7 bits 165d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * of the octet contain a GSM Default Alphabet character, 166d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * whereas if bit 8 of the octet is set to one, then the 167d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * remaining seven bits are an offset value added to the 168d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 16 bit base pointer defined earlier... 169d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 3) If the first octet of the alpha string is set to '82', then 170d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * the second octet contains a value indicating the number of 171d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * characters in the string, and the third and fourth octets 172d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * contain a 16 bit number which defines the complete 16 bit 173d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * base pointer to a "half page" in the UCS2 code space... 174d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka */ 175d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka public static String 176d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka adnStringFieldToString(byte[] data, int offset, int length) { 177d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (length == 0) { 178d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return ""; 179d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 180d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (length >= 1) { 181d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (data[offset] == (byte) 0x80) { 182d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int ucslen = (length - 1) / 2; 183d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka String ret = null; 184d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 185d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka try { 186d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret = new String(data, offset + 1, ucslen * 2, "utf-16be"); 187d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } catch (UnsupportedEncodingException ex) { 188d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka Rlog.e(LOG_TAG, "implausible UnsupportedEncodingException", 189d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ex); 190d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 191d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 192d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (ret != null) { 193d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // trim off trailing FFFF characters 194d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 195d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ucslen = ret.length(); 196d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka while (ucslen > 0 && ret.charAt(ucslen - 1) == '\uFFFF') 197d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ucslen--; 198d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 199d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return ret.substring(0, ucslen); 200d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 201d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 202d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 203d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 204d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka boolean isucs2 = false; 205d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka char base = '\0'; 206d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int len = 0; 207d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 208d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (length >= 3 && data[offset] == (byte) 0x81) { 209d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka len = data[offset + 1] & 0xFF; 210d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (len > length - 3) 211d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka len = length - 3; 212d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 213d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka base = (char) ((data[offset + 2] & 0xFF) << 7); 214d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka offset += 3; 215d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka isucs2 = true; 216d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } else if (length >= 4 && data[offset] == (byte) 0x82) { 217d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka len = data[offset + 1] & 0xFF; 218d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (len > length - 4) 219d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka len = length - 4; 220d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 221d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka base = (char) (((data[offset + 2] & 0xFF) << 8) | 222d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka (data[offset + 3] & 0xFF)); 223d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka offset += 4; 224d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka isucs2 = true; 225d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 226d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 227d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (isucs2) { 228d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka StringBuilder ret = new StringBuilder(); 229d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 230d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka while (len > 0) { 231d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // UCS2 subset case 232d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 233d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (data[offset] < 0) { 234d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret.append((char) (base + (data[offset] & 0x7F))); 235d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka offset++; 236d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka len--; 237d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 238d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 239d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // GSM character set case 240d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 241d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int count = 0; 242d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka while (count < len && data[offset + count] >= 0) 243d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka count++; 244d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 245d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret.append(GsmAlphabet.gsm8BitUnpackedToString(data, 246d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka offset, count)); 247d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 248d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka offset += count; 249d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka len -= count; 250d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 251d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 252d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return ret.toString(); 253d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 254d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 255d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka Resources resource = Resources.getSystem(); 256d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka String defaultCharset = ""; 257d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka try { 258d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka defaultCharset = 259d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka resource.getString(com.android.internal.R.string.gsm_alphabet_default_charset); 260d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } catch (NotFoundException e) { 261d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // Ignore Exception and defaultCharset is set to a empty string. 262d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 263d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return GsmAlphabet.gsm8BitUnpackedToString(data, offset, length, defaultCharset.trim()); 264d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 265d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 266d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka static int 267d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka hexCharToInt(char c) { 268d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (c >= '0' && c <= '9') return (c - '0'); 269d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (c >= 'A' && c <= 'F') return (c - 'A' + 10); 270d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (c >= 'a' && c <= 'f') return (c - 'a' + 10); 271d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 272d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka throw new RuntimeException ("invalid hex char '" + c + "'"); 273d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 274d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 275d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka /** 276d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Converts a hex String to a byte array. 277d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 278d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * @param s A string of hexadecimal characters, must be an even number of 279d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * chars long 280d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 281d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * @return byte array representation 282d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 283d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * @throws RuntimeException on invalid format 284d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka */ 285d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka public static byte[] 286d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka hexStringToBytes(String s) { 287d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka byte[] ret; 288d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 289d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (s == null) return null; 290d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 291d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int sz = s.length(); 292d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 293d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret = new byte[sz/2]; 294d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 295d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka for (int i=0 ; i <sz ; i+=2) { 296d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret[i/2] = (byte) ((hexCharToInt(s.charAt(i)) << 4) 297d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka | hexCharToInt(s.charAt(i+1))); 298d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 299d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 300d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return ret; 301d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 302d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 303d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 304d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka /** 305d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Converts a byte array into a String of hexadecimal characters. 306d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 307d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * @param bytes an array of bytes 308d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 309d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * @return hex string representation of bytes array 310d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka */ 311d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka public static String 312d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka bytesToHexString(byte[] bytes) { 313d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (bytes == null) return null; 314d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 315d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka StringBuilder ret = new StringBuilder(2*bytes.length); 316d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 317d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka for (int i = 0 ; i < bytes.length ; i++) { 318d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int b; 319d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 320d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka b = 0x0f & (bytes[i] >> 4); 321d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 322d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret.append("0123456789abcdef".charAt(b)); 323d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 324d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka b = 0x0f & bytes[i]; 325d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 326d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret.append("0123456789abcdef".charAt(b)); 327d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 328d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 329d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return ret.toString(); 330d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 331d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 332d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 333d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka /** 334d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Convert a TS 24.008 Section 10.5.3.5a Network Name field to a string 335d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * "offset" points to "octet 3", the coding scheme byte 336d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * empty string returned on decode error 337d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka */ 338d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka public static String 339d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka networkNameToString(byte[] data, int offset, int length) { 340d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka String ret; 341d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 342d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if ((data[offset] & 0x80) != 0x80 || length < 1) { 343d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return ""; 344d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 345d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 346d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka switch ((data[offset] >>> 4) & 0x7) { 347d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka case 0: 348d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // SMS character set 349d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int countSeptets; 350d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int unusedBits = data[offset] & 7; 351d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka countSeptets = (((length - 1) * 8) - unusedBits) / 7 ; 352d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret = GsmAlphabet.gsm7BitPackedToString(data, offset + 1, countSeptets); 353d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka break; 354d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka case 1: 355d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // UCS2 356d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka try { 357d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret = new String(data, 358d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka offset + 1, length - 1, "utf-16"); 359d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } catch (UnsupportedEncodingException ex) { 360d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret = ""; 361d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka Rlog.e(LOG_TAG,"implausible UnsupportedEncodingException", ex); 362d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 363d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka break; 364d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 365d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // unsupported encoding 366d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka default: 367d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka ret = ""; 368d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka break; 369d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 370d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 371d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // "Add CI" 372d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // "The MS should add the letters for the Country's Initials and 373d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // a separator (e.g. a space) to the text string" 374d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 375d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if ((data[offset] & 0x40) != 0) { 376d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // FIXME(mkf) add country initials here 377d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 378d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 379d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 380d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return ret; 381d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 382d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 383d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka /** 384d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * Convert a TS 131.102 image instance of code scheme '11' into Bitmap 385d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * @param data The raw data 386d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * @param length The length of image body 387d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * @return The bitmap 388d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka */ 389d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka public static Bitmap parseToBnW(byte[] data, int length){ 390d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int valueIndex = 0; 391d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int width = data[valueIndex++] & 0xFF; 392d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int height = data[valueIndex++] & 0xFF; 393d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int numOfPixels = width*height; 394d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 395d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int[] pixels = new int[numOfPixels]; 396d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 397d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int pixelIndex = 0; 398d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int bitIndex = 7; 399d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka byte currentByte = 0x00; 400d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka while (pixelIndex < numOfPixels) { 401d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // reassign data and index for every byte (8 bits). 402d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (pixelIndex % 8 == 0) { 403d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka currentByte = data[valueIndex++]; 404d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka bitIndex = 7; 405d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 406d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka pixels[pixelIndex++] = bitToRGB((currentByte >> bitIndex-- ) & 0x01); 407cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville } 408d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 409d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (pixelIndex != numOfPixels) { 410d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka Rlog.e(LOG_TAG, "parse end and size error"); 411d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 412d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return Bitmap.createBitmap(pixels, width, height, Bitmap.Config.ARGB_8888); 413d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 414d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 415d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka private static int bitToRGB(int bit){ 416d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if(bit == 1){ 417d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return Color.WHITE; 418d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } else { 419d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return Color.BLACK; 420d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 421d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 422d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 423d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka /** 424d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * a TS 131.102 image instance of code scheme '11' into color Bitmap 425d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * 426d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * @param data The raw data 427d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * @param length the length of image body 428d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * @param transparency with or without transparency 429d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka * @return The color bitmap 430d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka */ 431d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka public static Bitmap parseToRGB(byte[] data, int length, 432d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka boolean transparency) { 433d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int valueIndex = 0; 434d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int width = data[valueIndex++] & 0xFF; 435d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int height = data[valueIndex++] & 0xFF; 436d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int bits = data[valueIndex++] & 0xFF; 437d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int colorNumber = data[valueIndex++] & 0xFF; 438d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int clutOffset = ((data[valueIndex++] & 0xFF) << 8) 439d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka | (data[valueIndex++] & 0xFF); 440d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 441d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int[] colorIndexArray = getCLUT(data, clutOffset, colorNumber); 442d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (true == transparency) { 443d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka colorIndexArray[colorNumber - 1] = Color.TRANSPARENT; 444d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 445d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 446d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int[] resultArray = null; 447d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (0 == (8 % bits)) { 448d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka resultArray = mapTo2OrderBitColor(data, valueIndex, 449d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka (width * height), colorIndexArray, bits); 450d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } else { 451d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka resultArray = mapToNon2OrderBitColor(data, valueIndex, 452d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka (width * height), colorIndexArray, bits); 453d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 454d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 455d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return Bitmap.createBitmap(resultArray, width, height, 456d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka Bitmap.Config.RGB_565); 457d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 458d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 459d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka private static int[] mapTo2OrderBitColor(byte[] data, int valueIndex, 460d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int length, int[] colorArray, int bits) { 461d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (0 != (8 % bits)) { 462d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka Rlog.e(LOG_TAG, "not event number of color"); 463d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return mapToNon2OrderBitColor(data, valueIndex, length, colorArray, 464d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka bits); 465d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 466d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 467d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int mask = 0x01; 468d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka switch (bits) { 469d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka case 1: 470d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka mask = 0x01; 471d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka break; 472d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka case 2: 473d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka mask = 0x03; 474d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka break; 475d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka case 4: 476d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka mask = 0x0F; 477d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka break; 478d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka case 8: 479d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka mask = 0xFF; 480d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka break; 481d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 482d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 483d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int[] resultArray = new int[length]; 484d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int resultIndex = 0; 485d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int run = 8 / bits; 486d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka while (resultIndex < length) { 487d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka byte tempByte = data[valueIndex++]; 488d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka for (int runIndex = 0; runIndex < run; ++runIndex) { 489d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int offset = run - runIndex - 1; 490d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka resultArray[resultIndex++] = colorArray[(tempByte >> (offset * bits)) 491d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka & mask]; 492d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 493d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 494d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return resultArray; 495d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 496d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 497d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka private static int[] mapToNon2OrderBitColor(byte[] data, int valueIndex, 498d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int length, int[] colorArray, int bits) { 499d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (0 == (8 % bits)) { 500d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka Rlog.e(LOG_TAG, "not odd number of color"); 501d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return mapTo2OrderBitColor(data, valueIndex, length, colorArray, 502d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka bits); 503d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 504d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 505d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int[] resultArray = new int[length]; 506d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka // TODO fix me: 507d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return resultArray; 508d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 509d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 510d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka private static int[] getCLUT(byte[] rawData, int offset, int number) { 511d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka if (null == rawData) { 512d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return null; 513d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 514d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 515d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int[] result = new int[number]; 516d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int endIndex = offset + (number * 3); // 1 color use 3 bytes 517d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int valueIndex = offset; 518d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int colorIndex = 0; 519d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka int alpha = 0xff << 24; 520d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka do { 521d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka result[colorIndex++] = alpha 522d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka | ((rawData[valueIndex++] & 0xFF) << 16) 523d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka | ((rawData[valueIndex++] & 0xFF) << 8) 524d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka | ((rawData[valueIndex++] & 0xFF)); 525d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } while (valueIndex < endIndex); 526d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka return result; 527d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka } 528d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka} 529