UiccController.java revision 5d8e4457b03d166aa249989916b66a85df898516
1c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
2e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * Copyright (C) 2011-2012 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
19e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport android.content.Context;
20bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.AsyncResult;
21bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.Handler;
22bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.Message;
23bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.Registrant;
24bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.RegistrantList;
25a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.TelephonyManager;
26ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog;
27c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
28e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport com.android.internal.telephony.CommandsInterface;
29a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneConstants;
30a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.SubscriptionController;
31e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
3205ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenkaimport java.io.FileDescriptor;
3305ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenkaimport java.io.PrintWriter;
3405ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka
35e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka/**
36e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * This class is responsible for keeping all knowledge about
37e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * Universal Integrated Circuit Card (UICC), also know as SIM's,
38e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * in the system. It is also used as API to get appropriate
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * applications to pass them to phone and service trackers.
40e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *
41e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * UiccController is created with the call to make() function.
42e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * UiccController is a singleton and make() must only be called once
43e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * and throws an exception if called multiple times.
44e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *
45e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * Once created UiccController registers with RIL for "on" and "unsol_sim_status_changed"
46e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * notifications. When such notification arrives UiccController will call
47e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * getIccCardStatus (GET_SIM_STATUS). Based on the response of GET_SIM_STATUS
48e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * request appropriate tree of uicc objects will be created.
49e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *
50e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * Following is class diagram for uicc classes:
51e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *
52e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                       UiccController
53e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                            #
54e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                            |
55e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                        UiccCard
56e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                          #   #
57e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                          |   ------------------
58e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                    UiccCardApplication    CatService
59e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                      #            #
60e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                      |            |
61e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                 IccRecords    IccFileHandler
62e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                 ^ ^ ^           ^ ^ ^ ^ ^
63e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *    SIMRecords---- | |           | | | | ---SIMFileHandler
64e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *    RuimRecords----- |           | | | ----RuimFileHandler
65e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *    IsimUiccRecords---           | | -----UsimFileHandler
66e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                                 | ------CsimFileHandler
67e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *                                 ----IsimFileHandler
68e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *
69e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * Legend: # stands for Composition
70e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *         ^ stands for Generalization
71e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka *
72e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * See also {@link com.android.internal.telephony.IccCard}
73cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville * and {@link com.android.internal.telephony.uicc.IccCardProxy}
74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
75bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkapublic class UiccController extends Handler {
76c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final boolean DBG = true;
77cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    private static final String LOG_TAG = "UiccController";
78c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
79e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public static final int APP_FAM_3GPP =  1;
80e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public static final int APP_FAM_3GPP2 = 2;
81e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public static final int APP_FAM_IMS   = 3;
82e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
83bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    private static final int EVENT_ICC_STATUS_CHANGED = 1;
84bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    private static final int EVENT_GET_ICC_STATUS_DONE = 2;
855d8e4457b03d166aa249989916b66a85df898516Steven Liu    private static final int EVENT_RADIO_UNAVAILABLE = 3;
86bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
87a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private CommandsInterface[] mCis;
88a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private UiccCard[] mUiccCards = new UiccCard[TelephonyManager.getDefault().getPhoneCount()];
89a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
90e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private static final Object mLock = new Object();
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static UiccController mInstance;
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
93e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private Context mContext;
94a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
95bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    private CommandsInterface mCi;
96e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private UiccCard mUiccCard;
97a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville*/
98bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
99a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected RegistrantList mIccChangedRegistrants = new RegistrantList();
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
101a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
102e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public static UiccController make(Context c, CommandsInterface ci) {
103e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        synchronized (mLock) {
104e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (mInstance != null) {
105e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                throw new RuntimeException("UiccController.make() should only be called once");
106e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
107e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mInstance = new UiccController(c, ci);
108e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return mInstance;
109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville*/
112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public static UiccController make(Context c, CommandsInterface[] ci) {
114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        synchronized (mLock) {
115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mInstance != null) {
116a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new RuntimeException("MSimUiccController.make() should only be called once");
117a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
118a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mInstance = new UiccController(c, ci);
119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return (UiccController)mInstance;
120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private UiccController(Context c, CommandsInterface []ci) {
124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("Creating UiccController");
125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mContext = c;
126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCis = ci;
127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0; i < mCis.length; i++) {
128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Integer index = new Integer(i);
129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, index);
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // TODO remove this once modem correctly notifies the unsols
131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mCis[i].registerForAvailable(this, EVENT_ICC_STATUS_CHANGED, index);
1325d8e4457b03d166aa249989916b66a85df898516Steven Liu            mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, index);
133a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
134a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
136bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    public static UiccController getInstance() {
137e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        synchronized (mLock) {
138e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (mInstance == null) {
139e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                throw new RuntimeException(
140e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                        "UiccController.getInstance can't be called before make()");
141e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
142e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return mInstance;
143e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
144e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
145e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
146e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public UiccCard getUiccCard() {
147a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return getUiccCard(SubscriptionController.getInstance().getPhoneId(SubscriptionController.getInstance().getDefaultSubId()));
148e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
149e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
150a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public UiccCard getUiccCard(int slotId) {
151e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        synchronized (mLock) {
152a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (isValidCardIndex(slotId)) {
153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return mUiccCards[slotId];
154e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
155e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return null;
156e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
157bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    }
158bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
159a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public UiccCard[] getUiccCards() {
160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // Return cloned array since we don't want to give out reference
161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // to internal data structure.
162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        synchronized (mLock) {
163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return mUiccCards.clone();
164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    // Easy to use API
168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public UiccCardApplication getUiccCardApplication(int family) {
169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return getUiccCardApplication(SubscriptionController.getInstance().getPhoneId(SubscriptionController.getInstance().getDefaultSubId()), family);
170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
171a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
173e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // Easy to use API
174e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public IccRecords getIccRecords(int family) {
175e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        synchronized (mLock) {
176e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (mUiccCard != null) {
177e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                UiccCardApplication app = mUiccCard.getApplication(family);
178e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (app != null) {
179e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    return app.getIccRecords();
180e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
181e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
182e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return null;
183e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
184e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville*/
186e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
187e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // Easy to use API
188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public IccRecords getIccRecords(int slotId, int family) {
189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        synchronized (mLock) {
190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            UiccCardApplication app = getUiccCardApplication(slotId, family);
191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (app != null) {
192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return app.getIccRecords();
193a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
194a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return null;
195a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
196a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
197a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
198a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
199a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    // Easy to use API
200e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public IccFileHandler getIccFileHandler(int family) {
201e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        synchronized (mLock) {
202e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (mUiccCard != null) {
203e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                UiccCardApplication app = mUiccCard.getApplication(family);
204e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (app != null) {
205e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    return app.getIccFileHandler();
206e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
207e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
208e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return null;
209e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
211a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville*/
212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    // Easy to use API
214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public IccFileHandler getIccFileHandler(int slotId, int family) {
215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        synchronized (mLock) {
216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            UiccCardApplication app = getUiccCardApplication(slotId, family);
217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (app != null) {
218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return app.getIccFileHandler();
219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return null;
221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
223a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
225bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    //Notifies when card status changes
226bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    public void registerForIccChanged(Handler h, int what, Object obj) {
227e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        synchronized (mLock) {
228e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            Registrant r = new Registrant (h, what, obj);
229e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mIccChangedRegistrants.add(r);
230e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            //Notify registrant right after registering, so that it will get the latest ICC status,
231e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            //otherwise which may not happen until there is an actual change in ICC status.
232e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            r.notifyRegistrant();
233e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
234bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    }
235e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
236bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    public void unregisterForIccChanged(Handler h) {
237e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        synchronized (mLock) {
238e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mIccChangedRegistrants.remove(h);
239e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
240bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    }
241bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
242bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    @Override
243bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    public void handleMessage (Message msg) {
244e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        synchronized (mLock) {
245a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Integer index = getCiIndex(msg);
246a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
247a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (index < 0 || index >= mCis.length) {
248a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Rlog.e(LOG_TAG, "Invalid index : " + index + " received with event " + msg.what);
249a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return;
250a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
251a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
252e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            switch (msg.what) {
253e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case EVENT_ICC_STATUS_CHANGED:
254e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus");
255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index));
256e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    break;
257e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case EVENT_GET_ICC_STATUS_DONE:
258e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE");
259e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    AsyncResult ar = (AsyncResult)msg.obj;
260a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    onGetIccCardStatusDone(ar, index);
261e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    break;
2625d8e4457b03d166aa249989916b66a85df898516Steven Liu                case EVENT_RADIO_UNAVAILABLE:
2635d8e4457b03d166aa249989916b66a85df898516Steven Liu                    if (DBG) log("EVENT_RADIO_UNAVAILABLE, dispose card");
2645d8e4457b03d166aa249989916b66a85df898516Steven Liu                    if (mUiccCards[index] != null) {
2655d8e4457b03d166aa249989916b66a85df898516Steven Liu                        mUiccCards[index].dispose();
2665d8e4457b03d166aa249989916b66a85df898516Steven Liu                    }
2675d8e4457b03d166aa249989916b66a85df898516Steven Liu                    mUiccCards[index] = null;
2685d8e4457b03d166aa249989916b66a85df898516Steven Liu                    mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null));
2695d8e4457b03d166aa249989916b66a85df898516Steven Liu                    break;
270e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                default:
271ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                    Rlog.e(LOG_TAG, " Unknown Event " + msg.what);
272e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
273bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        }
274bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    }
275bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
276a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Integer getCiIndex(Message msg) {
277a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        AsyncResult ar;
278a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Integer index = new Integer(PhoneConstants.DEFAULT_CARD_INDEX);
279a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
280a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        /*
281a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * The events can be come in two ways. By explicitly sending it using
282a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * sendMessage, in this case the user object passed is msg.obj and from
283a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * the CommandsInterface, in this case the user object is msg.obj.userObj
284a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         */
285a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (msg != null) {
286a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (msg.obj != null && msg.obj instanceof Integer) {
287a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                index = (Integer)msg.obj;
288a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else if(msg.obj != null && msg.obj instanceof AsyncResult) {
289a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ar = (AsyncResult)msg.obj;
290a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (ar.userObj != null && ar.userObj instanceof Integer) {
291a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    index = (Integer)ar.userObj;
292a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
293a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return index;
296a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
297a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
298a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
299e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private UiccController(Context c, CommandsInterface ci) {
300c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (DBG) log("Creating UiccController");
301e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mContext = c;
302e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mCi = ci;
303e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null);
3041a792b265d929c27246c5b173f2f2694f30dc228Suresh Koleti        // This is needed so that we query for sim status in the case when we boot in APM
3051a792b265d929c27246c5b173f2f2694f30dc228Suresh Koleti        mCi.registerForAvailable(this, EVENT_ICC_STATUS_CHANGED, null);
306c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
307a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville*/
308c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    // Easy to use API
310a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public UiccCardApplication getUiccCardApplication(int slotId, int family) {
311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        synchronized (mLock) {
312a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (isValidCardIndex(slotId)) {
313a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                UiccCard c = mUiccCards[slotId];
314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (c != null) {
315a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    return mUiccCards[slotId].getApplication(family);
316a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
317a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return null;
319a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
320a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
321a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
322a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private synchronized void onGetIccCardStatusDone(AsyncResult ar, Integer index) {
323bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (ar.exception != null) {
324ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(LOG_TAG,"Error getting ICC status. "
325bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                    + "RIL_REQUEST_GET_ICC_STATUS should "
326bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                    + "never return an error", ar.exception);
327bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            return;
328c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
329a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!isValidCardIndex(index)) {
330a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.e(LOG_TAG,"onGetIccCardStatusDone: invalid index : " + index);
331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
334bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        IccCardStatus status = (IccCardStatus)ar.result;
335bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mUiccCards[index] == null) {
337e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            //Create new card
338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mUiccCards[index] = new UiccCard(mContext, mCis[index], status, index);
339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
340a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Update the UiccCard in base class, so that if someone calls
342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // UiccManager.getUiccCard(), it will return the default card.
343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (index == PhoneConstants.DEFAULT_CARD_INDEX) {
344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mUiccCard = mUiccCards[index];
345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville*/
347e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        } else {
348e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            //Update already existing card
349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mUiccCards[index].update(mContext, mCis[index] , status);
350bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        }
351bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
352bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (DBG) log("Notifying IccChangedRegistrants");
353a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null));
354a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
356a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
357a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean isValidCardIndex(int index) {
358a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return (index >= 0 && index < mUiccCards.length);
359bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka    }
360bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
361c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void log(String string) {
362ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(LOG_TAG, string);
363c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
36405ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka
365a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
36605ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
36705ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println("UiccController: " + this);
36805ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mContext=" + mContext);
36905ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mInstance=" + mInstance);
370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville//        pw.println(" mCi=" + mCi);
371a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville//        pw.println(" mUiccCard=" + mUiccCard);
37205ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mIccChangedRegistrants: size=" + mIccChangedRegistrants.size());
37305ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        for (int i = 0; i < mIccChangedRegistrants.size(); i++) {
37405ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka            pw.println("  mIccChangedRegistrants[" + i + "]="
37505ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka                    + ((Registrant)mIccChangedRegistrants.get(i)).getHandler());
37605ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        }
37705ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println();
37805ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.flush();
379a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville//        for (int i = 0; i < mUiccCards.length; i++) {
380a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville//            mUiccCards[i].dump(fd, pw, args);
381a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville//        }
38205ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka    }
383bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka}
384