/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.telephony;
import android.app.PendingIntent;
import android.content.Context;
import android.util.Log;
import com.android.internal.util.HexDump;
import java.util.ArrayList;
import java.util.List;
import static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
/**
* IccSmsInterfaceManager to provide an inter-process communication to
* access Sms in Icc.
*/
public abstract class IccSmsInterfaceManager extends ISms.Stub {
protected PhoneBase mPhone;
protected Context mContext;
protected SMSDispatcher mDispatcher;
protected IccSmsInterfaceManager(PhoneBase phone){
mPhone = phone;
mContext = phone.getContext();
}
protected void enforceReceiveAndSend(String message) {
mContext.enforceCallingPermission(
"android.permission.RECEIVE_SMS", message);
mContext.enforceCallingPermission(
"android.permission.SEND_SMS", message);
}
/**
* Send a data based SMS to a specific application port.
*
* @param destAddr the address to send the message to
* @param scAddr is the service center address or null to use
* the current default SMSC
* @param destPort the port to deliver the message to
* @param data the body of the message to send
* @param sentIntent if not NULL this PendingIntent
is
* broadcast when the message is successfully sent, or failed.
* The result code will be Activity.RESULT_OK for success,
* or one of these errors:
* RESULT_ERROR_GENERIC_FAILURE
* RESULT_ERROR_RADIO_OFF
* RESULT_ERROR_NULL_PDU
* For RESULT_ERROR_GENERIC_FAILURE
the sentIntent may include
* the extra "errorCode" containing a radio technology specific value,
* generally only useful for troubleshooting.
* The per-application based SMS control checks sentIntent. If sentIntent
* is NULL the caller will be checked against all unknown applications,
* which cause smaller number of SMS to be sent in checking period.
* @param deliveryIntent if not NULL this PendingIntent
is
* broadcast when the message is delivered to the recipient. The
* raw pdu of the status report is in the extended data ("pdu").
*/
public void sendData(String destAddr, String scAddr, int destPort,
byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
mPhone.getContext().enforceCallingPermission(
"android.permission.SEND_SMS",
"Sending SMS message");
if (Log.isLoggable("SMS", Log.VERBOSE)) {
log("sendData: destAddr=" + destAddr + " scAddr=" + scAddr + " destPort=" +
destPort + " data='"+ HexDump.toHexString(data) + "' sentIntent=" +
sentIntent + " deliveryIntent=" + deliveryIntent);
}
mDispatcher.sendData(destAddr, scAddr, destPort, data, sentIntent, deliveryIntent);
}
/**
* Send a text based SMS.
*
* @param destAddr the address to send the message to
* @param scAddr is the service center address or null to use
* the current default SMSC
* @param text the body of the message to send
* @param sentIntent if not NULL this PendingIntent
is
* broadcast when the message is successfully sent, or failed.
* The result code will be Activity.RESULT_OK for success,
* or one of these errors:
* RESULT_ERROR_GENERIC_FAILURE
* RESULT_ERROR_RADIO_OFF
* RESULT_ERROR_NULL_PDU
* For RESULT_ERROR_GENERIC_FAILURE
the sentIntent may include
* the extra "errorCode" containing a radio technology specific value,
* generally only useful for troubleshooting.
* The per-application based SMS control checks sentIntent. If sentIntent
* is NULL the caller will be checked against all unknown applications,
* which cause smaller number of SMS to be sent in checking period.
* @param deliveryIntent if not NULL this PendingIntent
is
* broadcast when the message is delivered to the recipient. The
* raw pdu of the status report is in the extended data ("pdu").
*/
public void sendText(String destAddr, String scAddr,
String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
mPhone.getContext().enforceCallingPermission(
"android.permission.SEND_SMS",
"Sending SMS message");
if (Log.isLoggable("SMS", Log.VERBOSE)) {
log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr +
" text='"+ text + "' sentIntent=" +
sentIntent + " deliveryIntent=" + deliveryIntent);
}
mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent);
}
/**
* Send a multi-part text based SMS.
*
* @param destAddr the address to send the message to
* @param scAddr is the service center address or null to use
* the current default SMSC
* @param parts an ArrayList
of strings that, in order,
* comprise the original message
* @param sentIntents if not null, an ArrayList
of
* PendingIntent
s (one for each message part) that is
* broadcast when the corresponding message part has been sent.
* The result code will be Activity.RESULT_OK for success,
* or one of these errors:
* RESULT_ERROR_GENERIC_FAILURE
* RESULT_ERROR_RADIO_OFF
* RESULT_ERROR_NULL_PDU
.
* The per-application based SMS control checks sentIntent. If sentIntent
* is NULL the caller will be checked against all unknown applications,
* which cause smaller number of SMS to be sent in checking period.
* @param deliveryIntents if not null, an ArrayList
of
* PendingIntent
s (one for each message part) that is
* broadcast when the corresponding message part has been delivered
* to the recipient. The raw pdu of the status report is in the
* extended data ("pdu").
*/
public void sendMultipartText(String destAddr, String scAddr, List parts,
List sentIntents, List deliveryIntents) {
mPhone.getContext().enforceCallingPermission(
"android.permission.SEND_SMS",
"Sending SMS message");
if (Log.isLoggable("SMS", Log.VERBOSE)) {
int i = 0;
for (String part : parts) {
log("sendMultipartText: destAddr=" + destAddr + ", srAddr=" + scAddr +
", part[" + (i++) + "]=" + part);
}
}
mDispatcher.sendMultipartText(destAddr, scAddr, (ArrayList) parts,
(ArrayList) sentIntents, (ArrayList) deliveryIntents);
}
/**
* create SmsRawData lists from all sms record byte[]
* Use null to indicate "free" record
*
* @param messages List of message records from EF_SMS.
* @return SmsRawData list of all in-used records
*/
protected ArrayList buildValidRawData(ArrayList messages) {
int count = messages.size();
ArrayList ret;
ret = new ArrayList(count);
for (int i = 0; i < count; i++) {
byte[] ba = messages.get(i);
if (ba[0] == STATUS_ON_ICC_FREE) {
ret.add(null);
} else {
ret.add(new SmsRawData(messages.get(i)));
}
}
return ret;
}
/**
* Generates an EF_SMS record from status and raw PDU.
*
* @param status Message status. See TS 51.011 10.5.3.
* @param pdu Raw message PDU.
* @return byte array for the record.
*/
protected byte[] makeSmsRecordData(int status, byte[] pdu) {
byte[] data = new byte[IccConstants.SMS_RECORD_LENGTH];
// Status bits for this record. See TS 51.011 10.5.3
data[0] = (byte)(status & 7);
System.arraycopy(pdu, 0, data, 1, pdu.length);
// Pad out with 0xFF's.
for (int j = pdu.length+1; j < IccConstants.SMS_RECORD_LENGTH; j++) {
data[j] = -1;
}
return data;
}
protected abstract void log(String msg);
}