| /* |
| ** Copyright 2007, 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.gsm; |
| |
| import android.content.Context; |
| import android.os.AsyncResult; |
| import android.os.Handler; |
| import android.os.Message; |
| import android.util.Log; |
| |
| import com.android.internal.telephony.IccConstants; |
| import com.android.internal.telephony.IccSmsInterfaceManager; |
| import com.android.internal.telephony.IccUtils; |
| import com.android.internal.telephony.SmsRawData; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import static android.telephony.SmsManager.STATUS_ON_ICC_FREE; |
| |
| /** |
| * SimSmsInterfaceManager to provide an inter-process communication to |
| * access Sms in Sim. |
| */ |
| public class SimSmsInterfaceManager extends IccSmsInterfaceManager { |
| static final String LOG_TAG = "GSM"; |
| static final boolean DBG = true; |
| |
| private final Object mLock = new Object(); |
| private boolean mSuccess; |
| private List<SmsRawData> mSms; |
| |
| private static final int EVENT_LOAD_DONE = 1; |
| private static final int EVENT_UPDATE_DONE = 2; |
| |
| Handler mHandler = new Handler() { |
| @Override |
| public void handleMessage(Message msg) { |
| AsyncResult ar; |
| |
| switch (msg.what) { |
| case EVENT_UPDATE_DONE: |
| ar = (AsyncResult) msg.obj; |
| synchronized (mLock) { |
| mSuccess = (ar.exception == null); |
| mLock.notifyAll(); |
| } |
| break; |
| case EVENT_LOAD_DONE: |
| ar = (AsyncResult)msg.obj; |
| synchronized (mLock) { |
| if (ar.exception == null) { |
| mSms = buildValidRawData((ArrayList<byte[]>) ar.result); |
| } else { |
| if(DBG) log("Cannot load Sms records"); |
| if (mSms != null) |
| mSms.clear(); |
| } |
| mLock.notifyAll(); |
| } |
| break; |
| } |
| } |
| }; |
| |
| public SimSmsInterfaceManager(GSMPhone phone) { |
| super(phone); |
| mDispatcher = new GsmSMSDispatcher(phone); |
| } |
| |
| public void dispose() { |
| } |
| |
| protected void finalize() { |
| try { |
| super.finalize(); |
| } catch (Throwable throwable) { |
| Log.e(LOG_TAG, "Error while finalizing:", throwable); |
| } |
| if(DBG) Log.d(LOG_TAG, "SimSmsInterfaceManager finalized"); |
| } |
| |
| /** |
| * Update the specified message on the SIM. |
| * |
| * @param index record index of message to update |
| * @param status new message status (STATUS_ON_ICC_READ, |
| * STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT, |
| * STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE) |
| * @param pdu the raw PDU to store |
| * @return success or not |
| * |
| */ |
| public boolean |
| updateMessageOnIccEf(int index, int status, byte[] pdu) { |
| if (DBG) log("updateMessageOnIccEf: index=" + index + |
| " status=" + status + " ==> " + |
| "("+ Arrays.toString(pdu) + ")"); |
| enforceReceiveAndSend("Updating message on SIM"); |
| synchronized(mLock) { |
| mSuccess = false; |
| Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE); |
| |
| if (status == STATUS_ON_ICC_FREE) { |
| // Special case FREE: call deleteSmsOnSim instead of |
| // manipulating the SIM record |
| mPhone.mCM.deleteSmsOnSim(index, response); |
| } else { |
| byte[] record = makeSmsRecordData(status, pdu); |
| mPhone.getIccFileHandler().updateEFLinearFixed( |
| IccConstants.EF_SMS, |
| index, record, null, response); |
| } |
| try { |
| mLock.wait(); |
| } catch (InterruptedException e) { |
| log("interrupted while trying to update by index"); |
| } |
| } |
| return mSuccess; |
| } |
| |
| /** |
| * Copy a raw SMS PDU to the SIM. |
| * |
| * @param pdu the raw PDU to store |
| * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD, |
| * STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT) |
| * @return success or not |
| * |
| */ |
| public boolean copyMessageToIccEf(int status, byte[] pdu, byte[] smsc) { |
| if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " + |
| "pdu=("+ Arrays.toString(pdu) + |
| "), smsm=(" + Arrays.toString(smsc) +")"); |
| enforceReceiveAndSend("Copying message to SIM"); |
| synchronized(mLock) { |
| mSuccess = false; |
| Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE); |
| |
| mPhone.mCM.writeSmsToSim(status, IccUtils.bytesToHexString(smsc), |
| IccUtils.bytesToHexString(pdu), response); |
| |
| try { |
| mLock.wait(); |
| } catch (InterruptedException e) { |
| log("interrupted while trying to update by index"); |
| } |
| } |
| return mSuccess; |
| } |
| |
| /** |
| * Retrieves all messages currently stored on ICC. |
| * |
| * @return list of SmsRawData of all sms on ICC |
| */ |
| public List<SmsRawData> getAllMessagesFromIccEf() { |
| if (DBG) log("getAllMessagesFromEF"); |
| |
| Context context = mPhone.getContext(); |
| |
| context.enforceCallingPermission( |
| "android.permission.RECEIVE_SMS", |
| "Reading messages from SIM"); |
| synchronized(mLock) { |
| Message response = mHandler.obtainMessage(EVENT_LOAD_DONE); |
| mPhone.getIccFileHandler().loadEFLinearFixedAll(IccConstants.EF_SMS, response); |
| |
| try { |
| mLock.wait(); |
| } catch (InterruptedException e) { |
| log("interrupted while trying to load from the SIM"); |
| } |
| } |
| return mSms; |
| } |
| |
| protected void log(String msg) { |
| Log.d(LOG_TAG, "[SimSmsInterfaceManager] " + msg); |
| } |
| } |