UiccController.java revision 073ffbd395b7c3942c75a0880cafd1ddb84b4b07
1/*
2 * Copyright (C) 2011 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
17package com.android.internal.telephony.uicc;
18
19import com.android.internal.telephony.CommandsInterface;
20import com.android.internal.telephony.IccCard;
21import com.android.internal.telephony.IccCardStatus;
22import com.android.internal.telephony.IccCardStatus.CardState;
23import com.android.internal.telephony.PhoneBase;
24import com.android.internal.telephony.sip.SipPhone;
25
26import android.os.AsyncResult;
27import android.os.Handler;
28import android.os.Message;
29import android.os.Registrant;
30import android.os.RegistrantList;
31import android.util.Log;
32
33/* This class is responsible for keeping all knowledge about
34 * ICCs in the system. It is also used as API to get appropriate
35 * applications to pass them to phone and service trackers.
36 */
37public class UiccController extends Handler {
38    private static final boolean DBG = true;
39    private static final String LOG_TAG = "RIL_UiccController";
40
41    private static final int EVENT_ICC_STATUS_CHANGED = 1;
42    private static final int EVENT_GET_ICC_STATUS_DONE = 2;
43
44    private static UiccController mInstance;
45
46    private PhoneBase mCurrentPhone;
47    private CommandsInterface mCi;
48    private IccCard mIccCard;
49    private boolean mRegisteredWithCi = false;
50
51    private RegistrantList mIccChangedRegistrants = new RegistrantList();
52
53    public static synchronized UiccController getInstance(PhoneBase phone) {
54        if (mInstance == null) {
55            mInstance = new UiccController(phone);
56        } else if (phone != null) {
57            mInstance.setNewPhone(phone);
58        }
59        return mInstance;
60    }
61
62    // This method is not synchronized as getInstance(PhoneBase) is.
63    public static UiccController getInstance() {
64        return getInstance(null);
65    }
66
67    public synchronized IccCard getIccCard() {
68        return mIccCard;
69    }
70
71    //Notifies when card status changes
72    public void registerForIccChanged(Handler h, int what, Object obj) {
73        Registrant r = new Registrant (h, what, obj);
74        mIccChangedRegistrants.add(r);
75        //Notify registrant right after registering, so that it will get the latest ICC status,
76        //otherwise which may not happen until there is an actual change in ICC status.
77        r.notifyRegistrant();
78    }
79    public void unregisterForIccChanged(Handler h) {
80        mIccChangedRegistrants.remove(h);
81    }
82
83    @Override
84    public void handleMessage (Message msg) {
85        switch (msg.what) {
86            case EVENT_ICC_STATUS_CHANGED:
87                if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus");
88                mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
89                break;
90            case EVENT_GET_ICC_STATUS_DONE:
91                if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE");
92                AsyncResult ar = (AsyncResult)msg.obj;
93                onGetIccCardStatusDone(ar);
94                break;
95            default:
96                Log.e(LOG_TAG, " Unknown Event " + msg.what);
97        }
98    }
99
100    private UiccController(PhoneBase phone) {
101        if (DBG) log("Creating UiccController");
102        setNewPhone(phone);
103    }
104
105    private synchronized void onGetIccCardStatusDone(AsyncResult ar) {
106        if (ar.exception != null) {
107            Log.e(LOG_TAG,"Error getting ICC status. "
108                    + "RIL_REQUEST_GET_ICC_STATUS should "
109                    + "never return an error", ar.exception);
110            return;
111        }
112
113        IccCardStatus status = (IccCardStatus)ar.result;
114
115        //Update already existing card
116        if (mIccCard != null) {
117            mIccCard.update(mCurrentPhone, status);
118        }
119
120        //Create new card
121        if (mIccCard == null) {
122            mIccCard = new IccCard(mCurrentPhone, status, mCurrentPhone.getPhoneName(), true);
123        }
124
125        if (DBG) log("Notifying IccChangedRegistrants");
126        mIccChangedRegistrants.notifyRegistrants();
127    }
128
129    private void setNewPhone(PhoneBase phone) {
130        if (phone == null) {
131            throw new RuntimeException("Phone can't be null in UiccController");
132            //return;
133        }
134
135        if (DBG) log("setNewPhone");
136        // TODO: remove this
137        if (phone instanceof SipPhone) {
138            if (DBG) log("Got SipPhone. Ignore.");
139            return;
140        }
141
142        if (mCurrentPhone != phone) {
143            if (mIccCard != null) {
144                // Refresh card if phone changed
145                // TODO: Remove once card is simplified
146                if (DBG) log("Disposing card since phone object changed");
147                mIccCard.dispose();
148                mIccCard = null;
149            }
150            sendMessage(obtainMessage(EVENT_ICC_STATUS_CHANGED));
151            mCurrentPhone = phone;
152
153            if (!mRegisteredWithCi) {
154                // This needs to be done only once after we have valid phone object
155                mCi = mCurrentPhone.mCM;
156                mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null);
157                // TODO remove this once modem correctly notifies the unsols
158                mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null);
159                mRegisteredWithCi = true;
160            }
161        }
162    }
163
164    private void log(String string) {
165        Log.d(LOG_TAG, string);
166    }
167}
168