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