1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18package com.android.internal.telephony.cdma;
19
20import android.content.Context;
21import android.os.AsyncResult;
22import android.os.Handler;
23import android.os.Message;
24import android.util.Log;
25
26import com.android.internal.telephony.IccConstants;
27import com.android.internal.telephony.IccSmsInterfaceManager;
28import com.android.internal.telephony.IccUtils;
29import com.android.internal.telephony.PhoneProxy;
30import com.android.internal.telephony.SmsRawData;
31
32import java.util.ArrayList;
33import java.util.List;
34
35import static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
36
37/**
38 * RuimSmsInterfaceManager to provide an inter-process communication to
39 * access Sms in Ruim.
40 */
41public class RuimSmsInterfaceManager extends IccSmsInterfaceManager {
42    static final String LOG_TAG = "CDMA";
43    static final boolean DBG = true;
44
45    private final Object mLock = new Object();
46    private boolean mSuccess;
47    private List<SmsRawData> mSms;
48
49    private static final int EVENT_LOAD_DONE = 1;
50    private static final int EVENT_UPDATE_DONE = 2;
51
52    Handler mHandler = new Handler() {
53        @Override
54        public void handleMessage(Message msg) {
55            AsyncResult ar;
56
57            switch (msg.what) {
58                case EVENT_UPDATE_DONE:
59                    ar = (AsyncResult) msg.obj;
60                    synchronized (mLock) {
61                        mSuccess = (ar.exception == null);
62                        mLock.notifyAll();
63                    }
64                    break;
65                case EVENT_LOAD_DONE:
66                    ar = (AsyncResult)msg.obj;
67                    synchronized (mLock) {
68                        if (ar.exception == null) {
69                            mSms  = (List<SmsRawData>)
70                                    buildValidRawData((ArrayList<byte[]>) ar.result);
71                        } else {
72                            if(DBG) log("Cannot load Sms records");
73                            if (mSms != null)
74                                mSms.clear();
75                        }
76                        mLock.notifyAll();
77                    }
78                    break;
79            }
80        }
81    };
82
83    public RuimSmsInterfaceManager(CDMAPhone phone) {
84        super(phone);
85        mDispatcher = new CdmaSMSDispatcher(phone);
86    }
87
88    public void dispose() {
89    }
90
91    protected void finalize() {
92        if(DBG) Log.d(LOG_TAG, "RuimSmsInterfaceManager finalized");
93    }
94
95    /**
96     * Update the specified message on the RUIM.
97     *
98     * @param index record index of message to update
99     * @param status new message status (STATUS_ON_ICC_READ,
100     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
101     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
102     * @param pdu the raw PDU to store
103     * @return success or not
104     *
105     */
106    public boolean
107    updateMessageOnIccEf(int index, int status, byte[] pdu) {
108        if (DBG) log("updateMessageOnIccEf: index=" + index +
109                " status=" + status + " ==> " +
110                "("+ pdu + ")");
111        enforceReceiveAndSend("Updating message on RUIM");
112        synchronized(mLock) {
113            mSuccess = false;
114            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
115
116            if (status == STATUS_ON_ICC_FREE) {
117                // Special case FREE: call deleteSmsOnRuim instead of
118                // manipulating the RUIM record
119                mPhone.mCM.deleteSmsOnRuim(index, response);
120            } else {
121                byte[] record = makeSmsRecordData(status, pdu);
122                mPhone.getIccFileHandler().updateEFLinearFixed(
123                        IccConstants.EF_SMS, index, record, null, response);
124            }
125            try {
126                mLock.wait();
127            } catch (InterruptedException e) {
128                log("interrupted while trying to update by index");
129            }
130        }
131        return mSuccess;
132    }
133
134    /**
135     * Copy a raw SMS PDU to the RUIM.
136     *
137     * @param pdu the raw PDU to store
138     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
139     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
140     * @return success or not
141     *
142     */
143    public boolean copyMessageToIccEf(int status, byte[] pdu, byte[] smsc) {
144        //NOTE smsc not used in RUIM
145        if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " +
146                "pdu=("+ pdu + ")");
147        enforceReceiveAndSend("Copying message to RUIM");
148        synchronized(mLock) {
149            mSuccess = false;
150            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
151
152            mPhone.mCM.writeSmsToRuim(status, IccUtils.bytesToHexString(pdu),
153                    response);
154
155            try {
156                mLock.wait();
157            } catch (InterruptedException e) {
158                log("interrupted while trying to update by index");
159            }
160        }
161        return mSuccess;
162    }
163
164    /**
165     * Retrieves all messages currently stored on RUIM.
166     */
167    public List<SmsRawData> getAllMessagesFromIccEf() {
168        if (DBG) log("getAllMessagesFromEF");
169
170        Context context = mPhone.getContext();
171
172        context.enforceCallingPermission(
173                "android.permission.RECEIVE_SMS",
174                "Reading messages from RUIM");
175        synchronized(mLock) {
176            Message response = mHandler.obtainMessage(EVENT_LOAD_DONE);
177            mPhone.getIccFileHandler().loadEFLinearFixedAll(IccConstants.EF_SMS, response);
178
179            try {
180                mLock.wait();
181            } catch (InterruptedException e) {
182                log("interrupted while trying to load from the RUIM");
183            }
184        }
185        return mSms;
186    }
187
188    protected void log(String msg) {
189        Log.d(LOG_TAG, "[RuimSmsInterfaceManager] " + msg);
190    }
191}
192
193