UiccController.java revision bb36adde615d3d85fa0fc23935197c6bc6a799ed
1c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
2c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Copyright (C) 2011 The Android Open Source Project
3c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
4c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * you may not use this file except in compliance with the License.
6c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * You may obtain a copy of the License at
7c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
8c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
10c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Unless required by applicable law or agreed to in writing, software
11c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * See the License for the specific language governing permissions and
14c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * limitations under the License.
15c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
16c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
17c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepackage com.android.internal.telephony.uicc;
18c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
19bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport com.android.internal.telephony.CommandsInterface;
20c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.IccCard;
21bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport com.android.internal.telephony.IccCardStatus;
22bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport com.android.internal.telephony.IccCardStatus.CardState;
23c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.PhoneBase;
24c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
25bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.AsyncResult;
26bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.Handler;
27bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.Message;
28bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.Registrant;
29bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.RegistrantList;
30c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.util.Log;
31c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
32c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/* This class is responsible for keeping all knowledge about
33c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * ICCs in the system. It is also used as API to get appropriate
34c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * applications to pass them to phone and service trackers.
35c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
36bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkapublic class UiccController extends Handler {
37c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final boolean DBG = true;
38c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final String LOG_TAG = "RIL_UiccController";
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
40bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    private static final int EVENT_ICC_STATUS_CHANGED = 1;
41bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    private static final int EVENT_GET_ICC_STATUS_DONE = 2;
42bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
43c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static UiccController mInstance;
44c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
45c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private PhoneBase mCurrentPhone;
46bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    private CommandsInterface mCi;
47c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private IccCard mIccCard;
48bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    private boolean mRegisteredWithCi = false;
49bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
50bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    private RegistrantList mIccChangedRegistrants = new RegistrantList();
51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
52c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public static synchronized UiccController getInstance(PhoneBase phone) {
53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (mInstance == null) {
54c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            mInstance = new UiccController(phone);
55bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        } else if (phone != null) {
56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            mInstance.setNewPhone(phone);
57c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return mInstance;
59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
61bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    // This method is not synchronized as getInstance(PhoneBase) is.
62bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    public static UiccController getInstance() {
63bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        return getInstance(null);
64bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    }
65bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
66bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    public synchronized IccCard getIccCard() {
67c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return mIccCard;
68c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
69c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
70bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    //Notifies when card status changes
71bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    public void registerForIccChanged(Handler h, int what, Object obj) {
72bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        Registrant r = new Registrant (h, what, obj);
73bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        mIccChangedRegistrants.add(r);
74bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        //Notify registrant right after registering, so that it will get the latest ICC status,
75bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        //otherwise which may not happen until there is an actual change in ICC status.
76bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        r.notifyRegistrant();
77bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    }
78bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    public void unregisterForIccChanged(Handler h) {
79bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        mIccChangedRegistrants.remove(h);
80bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    }
81bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
82bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    @Override
83bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    public void handleMessage (Message msg) {
84bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        switch (msg.what) {
85bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            case EVENT_ICC_STATUS_CHANGED:
86bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus");
87bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
88bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                break;
89bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            case EVENT_GET_ICC_STATUS_DONE:
90bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE");
91bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                AsyncResult ar = (AsyncResult)msg.obj;
92bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                onGetIccCardStatusDone(ar);
93bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                break;
94bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            default:
95bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                Log.e(LOG_TAG, " Unknown Event " + msg.what);
96bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        }
97bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    }
98bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private UiccController(PhoneBase phone) {
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (DBG) log("Creating UiccController");
101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        setNewPhone(phone);
102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
104bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    private synchronized void onGetIccCardStatusDone(AsyncResult ar) {
105bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (ar.exception != null) {
106bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            Log.e(LOG_TAG,"Error getting ICC status. "
107bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                    + "RIL_REQUEST_GET_ICC_STATUS should "
108bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                    + "never return an error", ar.exception);
109bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            return;
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
112bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        IccCardStatus status = (IccCardStatus)ar.result;
113bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
114bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        //Update already existing card
115bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (mIccCard != null && status.getCardState() == CardState.CARDSTATE_PRESENT) {
116bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            mIccCard.update(mCurrentPhone, status);
117c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
119bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        //Dispose of removed card
120bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (mIccCard != null && status.getCardState() != CardState.CARDSTATE_PRESENT) {
121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            mIccCard.dispose();
122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            mIccCard = null;
123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
125bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        //Create new card
126bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (mIccCard == null && status.getCardState() == CardState.CARDSTATE_PRESENT) {
127bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            mIccCard = new IccCard(mCurrentPhone, status, mCurrentPhone.getPhoneName(), true);
128bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        }
129bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
130bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (DBG) log("Notifying IccChangedRegistrants");
131bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        mIccChangedRegistrants.notifyRegistrants();
132bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    }
133bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
134bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    private void setNewPhone(PhoneBase phone) {
135bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (phone == null) {
136bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            throw new RuntimeException("Phone can't be null in UiccController");
137bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            //return;
138bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        }
139bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
140bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (DBG) log("setNewPhone");
141bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (mCurrentPhone != phone) {
142bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            if (mIccCard != null) {
143bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                // Refresh card if phone changed
144bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                // TODO: Remove once card is simplified
145bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                if (DBG) log("Disposing card since phone object changed");
146bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                mIccCard.dispose();
147bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                mIccCard = null;
148bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            }
149bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            sendMessage(obtainMessage(EVENT_ICC_STATUS_CHANGED));
150bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            mCurrentPhone = phone;
151bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
152bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            if (!mRegisteredWithCi) {
153bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                // This needs to be done only once after we have valid phone object
154bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                mCi = mCurrentPhone.mCM;
155bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null);
156bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                // TODO remove this once modem correctly notifies the unsols
157bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null);
158bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                mRegisteredWithCi = true;
159bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            }
160bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        }
161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void log(String string) {
164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        Log.d(LOG_TAG, string);
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
166bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka}
167