1 /* 2 * Copyright (C) 2013 Samsung System LSI 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 package com.android.bluetooth.map; 16 17 import android.util.Log; 18 19 import com.android.bluetooth.DeviceWorkArounds; 20 import com.android.bluetooth.map.BluetoothMapSmsPdu.SmsPdu; 21 import com.android.bluetooth.map.BluetoothMapUtils.TYPE; 22 23 import java.nio.charset.StandardCharsets; 24 import java.util.ArrayList; 25 import java.util.List; 26 27 public class BluetoothMapbMessageSms extends BluetoothMapbMessage { 28 29 private List<SmsPdu> mSmsBodyPdus = null; 30 private String mSmsBody = null; 31 setSmsBodyPdus(List<SmsPdu> smsBodyPdus)32 public void setSmsBodyPdus(List<SmsPdu> smsBodyPdus) { 33 this.mSmsBodyPdus = smsBodyPdus; 34 this.mCharset = null; 35 if (smsBodyPdus.size() > 0) { 36 this.mEncoding = smsBodyPdus.get(0).getEncodingString(); 37 } 38 } 39 getSmsBody()40 public String getSmsBody() { 41 return mSmsBody; 42 } 43 setSmsBody(String smsBody)44 public void setSmsBody(String smsBody) { 45 this.mSmsBody = smsBody; 46 this.mCharset = "UTF-8"; 47 this.mEncoding = null; 48 } 49 50 @Override parseMsgPart(String msgPart)51 public void parseMsgPart(String msgPart) { 52 if (mAppParamCharset == BluetoothMapAppParams.CHARSET_NATIVE) { 53 Log.d(TAG, "Decoding \"" + msgPart + "\" as native PDU"); 54 byte[] msgBytes = decodeBinary(msgPart); 55 if (msgBytes.length > 0 56 && msgBytes[0] < msgBytes.length - 1 57 && (msgBytes[msgBytes[0] + 1] & 0x03) != 0x01) { 58 Log.d(TAG, "Only submit PDUs are supported"); 59 throw new IllegalArgumentException("Only submit PDUs are supported"); 60 } 61 62 mSmsBody = 63 mSmsBody 64 + BluetoothMapSmsPdu.decodePdu( 65 msgBytes, 66 mType == TYPE.SMS_CDMA 67 ? BluetoothMapSmsPdu.SMS_TYPE_CDMA 68 : BluetoothMapSmsPdu.SMS_TYPE_GSM); 69 } else { 70 mSmsBody = mSmsBody + msgPart; 71 } 72 } 73 74 @Override parseMsgInit()75 public void parseMsgInit() { 76 mSmsBody = ""; 77 } 78 79 @Override encode()80 public byte[] encode() { 81 List<byte[]> bodyFragments = new ArrayList<>(); 82 83 /* Store the messages in an ArrayList to be able to handle the different message types in 84 a generic way. 85 * We use byte[] since we need to extract the length in bytes. 86 */ 87 if (mSmsBody != null) { 88 String tmpBody = 89 mSmsBody.replaceAll( 90 "END:MSG", 91 "/END\\:MSG"); // Replace any occurrences of END:MSG with \END:MSG 92 String remoteAddress = 93 BluetoothMapService.getBluetoothMapService().getRemoteDevice().getAddress(); 94 /* Fix IOT issue with PCM carkit where carkit is unable to parse 95 message if carriage return is present in it */ 96 if (DeviceWorkArounds.addressStartsWith(remoteAddress, DeviceWorkArounds.PCM_CARKIT)) { 97 tmpBody = tmpBody.replaceAll("\r", ""); 98 /* Fix Message Display issue with FORD SYNC carkit - 99 * Remove line feed and include only carriage return */ 100 } else if (DeviceWorkArounds.addressStartsWith( 101 remoteAddress, DeviceWorkArounds.FORD_SYNC_CARKIT)) { 102 tmpBody = tmpBody.replaceAll("\n", ""); 103 /* Fix IOT issue with SYNC carkit to remove trailing line feeds in the message body 104 */ 105 } else if (DeviceWorkArounds.addressStartsWith( 106 remoteAddress, DeviceWorkArounds.SYNC_CARKIT) 107 && tmpBody.length() > 0) { 108 int trailingLF = 0; 109 while ((tmpBody.charAt(tmpBody.length() - trailingLF - 1)) == '\n') trailingLF++; 110 tmpBody = tmpBody.substring(0, (tmpBody.length() - trailingLF)); 111 } 112 bodyFragments.add(tmpBody.getBytes(StandardCharsets.UTF_8)); 113 } else if (mSmsBodyPdus != null && mSmsBodyPdus.size() > 0) { 114 for (SmsPdu pdu : mSmsBodyPdus) { 115 // This cannot(must not) contain END:MSG 116 bodyFragments.add( 117 encodeBinary(pdu.getData(), pdu.getScAddress()) 118 .getBytes(StandardCharsets.UTF_8)); 119 } 120 } else { 121 bodyFragments.add(new byte[0]); // An empty message - no text 122 } 123 124 return encodeGeneric(bodyFragments); 125 } 126 } 127