OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / telephony / java / com / android / internal / telephony / cdma / RuimRecords.java
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 package com.android.internal.telephony.cdma;
18
19 import android.os.AsyncResult;
20 import android.os.Handler;
21 import android.os.Message;
22 import android.os.Registrant;
23 import android.util.Log;
24
25 import com.android.internal.telephony.AdnRecord;
26 import com.android.internal.telephony.AdnRecordCache;
27 import com.android.internal.telephony.AdnRecordLoader;
28 import com.android.internal.telephony.CommandsInterface;
29 import com.android.internal.telephony.TelephonyProperties;
30 import com.android.internal.telephony.cdma.RuimCard;
31 import com.android.internal.telephony.MccTable;
32
33 // can't be used since VoiceMailConstants is not public
34 //import com.android.internal.telephony.gsm.VoiceMailConstants;
35 import com.android.internal.telephony.IccException;
36 import com.android.internal.telephony.IccRecords;
37 import com.android.internal.telephony.IccUtils;
38 import com.android.internal.telephony.PhoneProxy;
39
40
41 /**
42  * {@hide}
43  */
44 public final class RuimRecords extends IccRecords {
45     static final String LOG_TAG = "CDMA";
46
47     private static final boolean DBG = true;
48     private boolean  m_ota_commited=false;
49
50     // ***** Instance Variables
51
52     private String mImsi;
53     private String mMyMobileNumber;
54     private String mMin2Min1;
55
56     private String mPrlVersion;
57
58     // ***** Event Constants
59
60     private static final int EVENT_RUIM_READY = 1;
61     private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 2;
62     private static final int EVENT_GET_DEVICE_IDENTITY_DONE = 4;
63     private static final int EVENT_GET_ICCID_DONE = 5;
64     private static final int EVENT_GET_CDMA_SUBSCRIPTION_DONE = 10;
65     private static final int EVENT_UPDATE_DONE = 14;
66     private static final int EVENT_GET_SST_DONE = 17;
67     private static final int EVENT_GET_ALL_SMS_DONE = 18;
68     private static final int EVENT_MARK_SMS_READ_DONE = 19;
69
70     private static final int EVENT_SMS_ON_RUIM = 21;
71     private static final int EVENT_GET_SMS_DONE = 22;
72
73     private static final int EVENT_RUIM_REFRESH = 31;
74
75
76     RuimRecords(CDMAPhone p) {
77         super(p);
78
79         adnCache = new AdnRecordCache(phone);
80
81         recordsRequested = false;  // No load request is made till SIM ready
82
83         // recordsToLoad is set to 0 because no requests are made yet
84         recordsToLoad = 0;
85
86
87         p.mCM.registerForRUIMReady(this, EVENT_RUIM_READY, null);
88         p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
89         // NOTE the EVENT_SMS_ON_RUIM is not registered
90         p.mCM.setOnIccRefresh(this, EVENT_RUIM_REFRESH, null);
91
92         // Start off by setting empty state
93         onRadioOffOrNotAvailable();
94
95     }
96
97     public void dispose() {
98         //Unregister for all events
99         phone.mCM.unregisterForRUIMReady(this);
100         phone.mCM.unregisterForOffOrNotAvailable( this);
101         phone.mCM.unSetOnIccRefresh(this);
102     }
103
104     @Override
105     protected void finalize() {
106         if(DBG) Log.d(LOG_TAG, "RuimRecords finalized");
107     }
108
109     @Override
110     protected void onRadioOffOrNotAvailable() {
111         countVoiceMessages = 0;
112         mncLength = UNINITIALIZED;
113         iccid = null;
114
115         adnCache.reset();
116
117         // recordsRequested is set to false indicating that the SIM
118         // read requests made so far are not valid. This is set to
119         // true only when fresh set of read requests are made.
120         recordsRequested = false;
121     }
122
123     public String getMdnNumber() {
124         return mMyMobileNumber;
125     }
126
127     public String getCdmaMin() {
128          return mMin2Min1;
129     }
130
131     /** Returns null if RUIM is not yet ready */
132     public String getPrlVersion() {
133         return mPrlVersion;
134     }
135
136     @Override
137     public void setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete){
138         // In CDMA this is Operator/OEM dependent
139         AsyncResult.forMessage((onComplete)).exception =
140                 new IccException("setVoiceMailNumber not implemented");
141         onComplete.sendToTarget();
142         Log.e(LOG_TAG, "method setVoiceMailNumber is not implemented");
143     }
144
145     /**
146      * Called by CCAT Service when REFRESH is received.
147      * @param fileChanged indicates whether any files changed
148      * @param fileList if non-null, a list of EF files that changed
149      */
150     @Override
151     public void onRefresh(boolean fileChanged, int[] fileList) {
152         if (fileChanged) {
153             // A future optimization would be to inspect fileList and
154             // only reload those files that we care about.  For now,
155             // just re-fetch all RUIM records that we cache.
156             fetchRuimRecords();
157         }
158     }
159
160     /**
161      * Returns the 5 or 6 digit MCC/MNC of the operator that
162      *  provided the RUIM card. Returns null of RUIM is not yet ready
163      */
164     public String getRUIMOperatorNumeric() {
165         if (mImsi == null) {
166             return null;
167         }
168
169         if (mncLength != UNINITIALIZED && mncLength != UNKNOWN) {
170             // Length = length of MCC + length of MNC
171             // length of mcc = 3 (3GPP2 C.S0005 - Section 2.3)
172             return mImsi.substring(0, 3 + mncLength);
173         }
174
175         // Guess the MNC length based on the MCC if we don't
176         // have a valid value in ef[ad]
177
178         int mcc = Integer.parseInt(mImsi.substring(0,3));
179         return mImsi.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
180     }
181
182     @Override
183     public void handleMessage(Message msg) {
184         AsyncResult ar;
185
186         byte data[];
187
188         boolean isRecordLoadResponse = false;
189
190         try { switch (msg.what) {
191             case EVENT_RUIM_READY:
192                 onRuimReady();
193             break;
194
195             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
196                 onRadioOffOrNotAvailable();
197             break;
198
199             case EVENT_GET_DEVICE_IDENTITY_DONE:
200                 Log.d(LOG_TAG, "Event EVENT_GET_DEVICE_IDENTITY_DONE Received");
201             break;
202
203             /* IO events */
204
205             case EVENT_GET_CDMA_SUBSCRIPTION_DONE:
206                 ar = (AsyncResult)msg.obj;
207                 String localTemp[] = (String[])ar.result;
208                 if (ar.exception != null) {
209                     break;
210                 }
211
212                 mMyMobileNumber = localTemp[0];
213                 mMin2Min1 = localTemp[3];
214                 mPrlVersion = localTemp[4];
215
216                 Log.d(LOG_TAG, "MDN: " + mMyMobileNumber + " MIN: " + mMin2Min1);
217
218             break;
219
220             case EVENT_GET_ICCID_DONE:
221                 isRecordLoadResponse = true;
222
223                 ar = (AsyncResult)msg.obj;
224                 data = (byte[])ar.result;
225
226                 if (ar.exception != null) {
227                     break;
228                 }
229
230                 iccid = IccUtils.bcdToString(data, 0, data.length);
231
232                 Log.d(LOG_TAG, "iccid: " + iccid);
233
234             break;
235
236             case EVENT_UPDATE_DONE:
237                 ar = (AsyncResult)msg.obj;
238                 if (ar.exception != null) {
239                     Log.i(LOG_TAG, "RuimRecords update failed", ar.exception);
240                 }
241             break;
242
243             case EVENT_GET_ALL_SMS_DONE:
244             case EVENT_MARK_SMS_READ_DONE:
245             case EVENT_SMS_ON_RUIM:
246             case EVENT_GET_SMS_DONE:
247                 Log.w(LOG_TAG, "Event not supported: " + msg.what);
248                 break;
249
250             // TODO: probably EF_CST should be read instead
251             case EVENT_GET_SST_DONE:
252                 Log.d(LOG_TAG, "Event EVENT_GET_SST_DONE Received");
253             break;
254
255             case EVENT_RUIM_REFRESH:
256                 isRecordLoadResponse = false;
257                 ar = (AsyncResult)msg.obj;
258                 if (ar.exception == null) {
259                     handleRuimRefresh((int[])(ar.result));
260                 }
261                 break;
262
263         }}catch (RuntimeException exc) {
264             // I don't want these exceptions to be fatal
265             Log.w(LOG_TAG, "Exception parsing RUIM record", exc);
266         } finally {
267             // Count up record load responses even if they are fails
268             if (isRecordLoadResponse) {
269                 onRecordLoaded();
270             }
271         }
272     }
273
274     @Override
275     protected void onRecordLoaded() {
276         // One record loaded successfully or failed, In either case
277         // we need to update the recordsToLoad count
278         recordsToLoad -= 1;
279
280         if (recordsToLoad == 0 && recordsRequested == true) {
281             onAllRecordsLoaded();
282         } else if (recordsToLoad < 0) {
283             Log.e(LOG_TAG, "RuimRecords: recordsToLoad <0, programmer error suspected");
284             recordsToLoad = 0;
285         }
286     }
287
288     @Override
289     protected void onAllRecordsLoaded() {
290         Log.d(LOG_TAG, "RuimRecords: record load complete");
291
292         // Further records that can be inserted are Operator/OEM dependent
293
294         recordsLoadedRegistrants.notifyRegistrants(
295             new AsyncResult(null, null, null));
296         ((CDMAPhone) phone).mRuimCard.broadcastIccStateChangedIntent(
297                 RuimCard.INTENT_VALUE_ICC_LOADED, null);
298     }
299
300     private void onRuimReady() {
301         /* broadcast intent ICC_READY here so that we can make sure
302           READY is sent before IMSI ready
303         */
304
305         ((CDMAPhone) phone).mRuimCard.broadcastIccStateChangedIntent(
306                 RuimCard.INTENT_VALUE_ICC_READY, null);
307
308         fetchRuimRecords();
309
310         phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
311
312     }
313
314
315     private void fetchRuimRecords() {
316         recordsRequested = true;
317
318         Log.v(LOG_TAG, "RuimRecords:fetchRuimRecords " + recordsToLoad);
319
320         phone.getIccFileHandler().loadEFTransparent(EF_ICCID,
321                 obtainMessage(EVENT_GET_ICCID_DONE));
322         recordsToLoad++;
323
324         // Further records that can be inserted are Operator/OEM dependent
325     }
326
327     @Override
328     protected int getDisplayRule(String plmn) {
329         // TODO together with spn
330         return 0;
331     }
332
333     @Override
334     public void setVoiceMessageWaiting(int line, int countWaiting) {
335         if (line != 1) {
336             // only profile 1 is supported
337             return;
338         }
339
340         // range check
341         if (countWaiting < 0) {
342             countWaiting = -1;
343         } else if (countWaiting > 0xff) {
344             // C.S0015-B v2, 4.5.12
345             // range: 0-99
346             countWaiting = 0xff;
347         }
348         countVoiceMessages = countWaiting;
349
350         ((CDMAPhone) phone).notifyMessageWaitingIndicator();
351     }
352
353     private void handleRuimRefresh(int[] result) {
354         if (result == null || result.length == 0) {
355             if (DBG) log("handleRuimRefresh without input");
356             return;
357         }
358
359         switch ((result[0])) {
360             case CommandsInterface.SIM_REFRESH_FILE_UPDATED:
361                 if (DBG) log("handleRuimRefresh with SIM_REFRESH_FILE_UPDATED");
362                 adnCache.reset();
363                 fetchRuimRecords();
364                 break;
365             case CommandsInterface.SIM_REFRESH_INIT:
366                 if (DBG) log("handleRuimRefresh with SIM_REFRESH_INIT");
367                 // need to reload all files (that we care about)
368                 fetchRuimRecords();
369                 break;
370             case CommandsInterface.SIM_REFRESH_RESET:
371                 if (DBG) log("handleRuimRefresh with SIM_REFRESH_RESET");
372                 phone.mCM.setRadioPower(false, null);
373                 /* Note: no need to call setRadioPower(true).  Assuming the desired
374                 * radio power state is still ON (as tracked by ServiceStateTracker),
375                 * ServiceStateTracker will call setRadioPower when it receives the
376                 * RADIO_STATE_CHANGED notification for the power off.  And if the
377                 * desired power state has changed in the interim, we don't want to
378                 * override it with an unconditional power on.
379                 */
380                 break;
381             default:
382                 // unknown refresh operation
383                 if (DBG) log("handleRuimRefresh with unknown operation");
384                 break;
385         }
386     }
387
388     @Override
389     protected void log(String s) {
390         Log.d(LOG_TAG, "[RuimRecords] " + s);
391     }
392
393 }