• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.uicc;
18 
19 import android.annotation.NonNull;
20 import android.content.Context;
21 import android.os.IBinder;
22 import android.os.Message;
23 import android.os.RemoteException;
24 import android.telephony.SubscriptionInfo;
25 import android.util.IndentingPrintWriter;
26 
27 import com.android.internal.annotations.GuardedBy;
28 import com.android.internal.annotations.VisibleForTesting;
29 import com.android.internal.telephony.CommandsInterface;
30 import com.android.internal.telephony.IccLogicalChannelRequest;
31 import com.android.internal.telephony.TelephonyComponentFactory;
32 import com.android.telephony.Rlog;
33 
34 import java.io.FileDescriptor;
35 import java.io.PrintWriter;
36 import java.util.ArrayList;
37 import java.util.List;
38 
39 public class UiccPort {
40     protected static final String LOG_TAG = "UiccPort";
41     protected static final boolean DBG = true;
42 
43     // The lock object is created by UiccSlot that owns this UiccCard - this is to share the lock
44     // between UiccSlot, UiccCard, EuiccCard, UiccPort, EuiccPort and UiccProfile for now.
45     protected final Object mLock;
46 
47     private String mIccid;
48     protected String mCardId;
49     private Context mContext;
50     private CommandsInterface mCi;
51     private UiccProfile mUiccProfile;
52 
53     private final int mPhoneId;
54     private int mPortIdx;
55     private int mPhysicalSlotIndex;
56 
57     // The list of the opened logical channel record. The channels will be closed by us when
58     // detecting client died without closing them in advance.
59     @GuardedBy("mOpenChannelRecords")
60     private final List<OpenLogicalChannelRecord> mOpenChannelRecords = new ArrayList<>();
61 
UiccPort(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId, Object lock, UiccCard uiccCard)62     public UiccPort(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId, Object lock,
63             UiccCard uiccCard) {
64         if (DBG) log("Creating");
65         mPhoneId = phoneId;
66         mLock = lock;
67         update(c, ci, ics, uiccCard);
68     }
69 
70     /**
71      * Update port. The main trigger for this is a change in the ICC Card status.
72      */
update(Context c, CommandsInterface ci, IccCardStatus ics, UiccCard uiccCard)73     public void update(Context c, CommandsInterface ci, IccCardStatus ics, UiccCard uiccCard) {
74         synchronized (mLock) {
75             mContext = c;
76             mCi = ci;
77             mIccid = ics.iccid;
78             mPortIdx = ics.mSlotPortMapping.mPortIndex;
79             mPhysicalSlotIndex = ics.mSlotPortMapping.mPhysicalSlotIndex;
80             if (mUiccProfile == null) {
81                 mUiccProfile = TelephonyComponentFactory.getInstance()
82                         .inject(UiccProfile.class.getName()).makeUiccProfile(
83                                 mContext, mCi, ics, mPhoneId, uiccCard, mLock);
84             } else {
85                 mUiccProfile.update(mContext, mCi, ics);
86             }
87         }
88     }
89 
90     /**
91      * Dispose the port and its related Uicc profiles.
92      */
dispose()93     public void dispose() {
94         synchronized (mLock) {
95             if (DBG) log("Disposing Port");
96             if (mUiccProfile != null) {
97                 mUiccProfile.dispose();
98             }
99             mUiccProfile = null;
100         }
101     }
102 
103     @Override
finalize()104     protected void finalize() {
105         if (DBG) log("UiccPort finalized");
106     }
107 
108     /**
109      * @deprecated Please use
110      * {@link UiccProfile#isApplicationOnIcc(IccCardApplicationStatus.AppType)} instead.
111      */
112     @Deprecated
isApplicationOnIcc(IccCardApplicationStatus.AppType type)113     public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) {
114         synchronized (mLock) {
115             if (mUiccProfile != null) {
116                 return mUiccProfile.isApplicationOnIcc(type);
117             } else {
118                 return false;
119             }
120         }
121     }
122 
123     /**
124      * @deprecated Please use {@link UiccProfile#getUniversalPinState()} instead.
125      */
126     @Deprecated
getUniversalPinState()127     public IccCardStatus.PinState getUniversalPinState() {
128         synchronized (mLock) {
129             if (mUiccProfile != null) {
130                 return mUiccProfile.getUniversalPinState();
131             } else {
132                 return IccCardStatus.PinState.PINSTATE_UNKNOWN;
133             }
134         }
135     }
136 
137     /**
138      * @deprecated Please use {@link UiccProfile#getApplication(int)} instead.
139      */
140     @Deprecated
getApplication(int family)141     public UiccCardApplication getApplication(int family) {
142         synchronized (mLock) {
143             if (mUiccProfile != null) {
144                 return mUiccProfile.getApplication(family);
145             } else {
146                 return null;
147             }
148         }
149     }
150 
151     /**
152      * @deprecated Please use {@link UiccProfile#getApplicationIndex(int)} instead.
153      */
154     @Deprecated
getApplicationIndex(int index)155     public UiccCardApplication getApplicationIndex(int index) {
156         synchronized (mLock) {
157             if (mUiccProfile != null) {
158                 return mUiccProfile.getApplicationIndex(index);
159             } else {
160                 return null;
161             }
162         }
163     }
164 
165     /**
166      * Returns the SIM application of the specified type.
167      *
168      * @param type ICC application type
169      * (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
170      * @return application corresponding to type or a null if no match found
171      *
172      * @deprecated Please use {@link UiccProfile#getApplicationByType(int)} instead.
173      */
174     @Deprecated
getApplicationByType(int type)175     public UiccCardApplication getApplicationByType(int type) {
176         synchronized (mLock) {
177             if (mUiccProfile != null) {
178                 return mUiccProfile.getApplicationByType(type);
179             } else {
180                 return null;
181             }
182         }
183     }
184 
185     /**
186      * Resets the application with the input AID. Returns true if any changes were made.
187      *
188      * A null aid implies a card level reset - all applications must be reset.
189      *
190      * @deprecated Please use {@link UiccProfile#resetAppWithAid(String, boolean)} instead.
191      */
192     @Deprecated
resetAppWithAid(String aid, boolean reset)193     public boolean resetAppWithAid(String aid, boolean reset) {
194         synchronized (mLock) {
195             if (mUiccProfile != null) {
196                 return mUiccProfile.resetAppWithAid(aid, reset);
197             } else {
198                 return false;
199             }
200         }
201     }
202 
203     /**
204      * Exposes {@link CommandsInterface#iccOpenLogicalChannel}
205      * @deprecated Please use
206      * {@link UiccProfile#iccOpenLogicalChannel(String, int, Message)} instead.
207      */
208     @Deprecated
iccOpenLogicalChannel(String AID, int p2, Message response)209     public void iccOpenLogicalChannel(String AID, int p2, Message response) {
210         if (mUiccProfile != null) {
211             mUiccProfile.iccOpenLogicalChannel(AID, p2, response);
212         } else {
213             loge("iccOpenLogicalChannel Failed!");
214         }
215     }
216 
217     /**
218      * Exposes {@link CommandsInterface#iccCloseLogicalChannel}
219      * @deprecated Please use
220      * {@link UiccProfile#iccCloseLogicalChannel(int, boolean, Message)} instead.
221      */
222     @Deprecated
iccCloseLogicalChannel(int channel, Message response)223     public void iccCloseLogicalChannel(int channel, Message response) {
224         if (mUiccProfile != null) {
225             mUiccProfile.iccCloseLogicalChannel(channel, false /*isEs10*/, response);
226         } else {
227             loge("iccCloseLogicalChannel Failed!");
228         }
229     }
230 
231     /**
232      * Exposes {@link CommandsInterface#iccTransmitApduLogicalChannel}
233      * @deprecated Please use {@link
234      * UiccProfile#iccTransmitApduLogicalChannel(int, int, int, int, int, int, String,
235      * boolean, Message)} instead.
236      */
237     @Deprecated
iccTransmitApduLogicalChannel(int channel, int cla, int command, int p1, int p2, int p3, String data, Message response)238     public void iccTransmitApduLogicalChannel(int channel, int cla, int command,
239             int p1, int p2, int p3, String data, Message response) {
240         if (mUiccProfile != null) {
241             mUiccProfile.iccTransmitApduLogicalChannel(channel, cla, command, p1, p2, p3,
242                     data, false /*isEs10Command*/, response);
243         } else {
244             loge("iccTransmitApduLogicalChannel Failed!");
245         }
246     }
247 
248     /**
249      * Exposes {@link CommandsInterface#iccTransmitApduBasicChannel}
250      * @deprecated Please use
251      * {@link UiccProfile#iccTransmitApduBasicChannel(int, int, int, int, int, String, Message)}
252      * instead.
253      */
254     @Deprecated
iccTransmitApduBasicChannel(int cla, int command, int p1, int p2, int p3, String data, Message response)255     public void iccTransmitApduBasicChannel(int cla, int command,
256             int p1, int p2, int p3, String data, Message response) {
257         if (mUiccProfile != null) {
258             mUiccProfile.iccTransmitApduBasicChannel(cla, command, p1, p2, p3, data, response);
259         } else {
260             loge("iccTransmitApduBasicChannel Failed!");
261         }
262     }
263 
264     /**
265      * Exposes {@link CommandsInterface#iccIO}
266      * @deprecated Please use
267      * {@link UiccProfile#iccExchangeSimIO(int, int, int, int, int, String, Message)} instead.
268      */
269     @Deprecated
iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3, String pathID, Message response)270     public void iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
271             String pathID, Message response) {
272         if (mUiccProfile != null) {
273             mUiccProfile.iccExchangeSimIO(fileID, command, p1, p2, p3, pathID, response);
274         } else {
275             loge("iccExchangeSimIO Failed!");
276         }
277     }
278 
279     /**
280      * Exposes {@link CommandsInterface#sendEnvelopeWithStatus}
281      * @deprecated Please use {@link UiccProfile#sendEnvelopeWithStatus(String, Message)} instead.
282      */
283     @Deprecated
sendEnvelopeWithStatus(String contents, Message response)284     public void sendEnvelopeWithStatus(String contents, Message response) {
285         if (mUiccProfile != null) {
286             mUiccProfile.sendEnvelopeWithStatus(contents, response);
287         } else {
288             loge("sendEnvelopeWithStatus Failed!");
289         }
290     }
291 
292     /**
293      * Returns number of applications on this card
294      * @deprecated Please use {@link UiccProfile#getNumApplications()} instead.
295      */
296     @Deprecated
getNumApplications()297     public int getNumApplications() {
298         if (mUiccProfile != null) {
299             return mUiccProfile.getNumApplications();
300         } else {
301             return 0;
302         }
303     }
304 
getPhoneId()305     public int getPhoneId() {
306         return mPhoneId;
307     }
308 
getPortIdx()309     public int getPortIdx() {
310         return mPortIdx;
311     }
312 
getUiccProfile()313     public UiccProfile getUiccProfile() {
314         return mUiccProfile;
315     }
316 
317     /**
318      * @deprecated Please use {@link UiccProfile#setOperatorBrandOverride(String)} instead.
319      */
320     @Deprecated
setOperatorBrandOverride(String brand)321     public boolean setOperatorBrandOverride(String brand) {
322         if (mUiccProfile != null) {
323             return mUiccProfile.setOperatorBrandOverride(brand);
324         } else {
325             return false;
326         }
327     }
328 
329     /**
330      * @deprecated Please use {@link UiccProfile#getOperatorBrandOverride()} instead.
331      */
332     @Deprecated
getOperatorBrandOverride()333     public String getOperatorBrandOverride() {
334         if (mUiccProfile != null) {
335             return mUiccProfile.getOperatorBrandOverride();
336         } else {
337             return null;
338         }
339     }
340 
341     /**
342      * Return the IccId corresponding to the port.
343      */
getIccId()344     public String getIccId() {
345         if (mIccid != null) {
346             return mIccid;
347         } else if (mUiccProfile != null) {
348             return mUiccProfile.getIccId();
349         } else {
350             return null;
351         }
352     }
353 
log(String msg)354     private void log(String msg) {
355         Rlog.d(LOG_TAG, msg);
356     }
357 
loge(String msg)358     private void loge(String msg) {
359         Rlog.e(LOG_TAG, msg);
360     }
361 
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)362     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
363         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
364         pw.println("UiccPort:");
365         pw.increaseIndent();
366         pw.println("mPortIdx=" + mPortIdx);
367         pw.println("mCi=" + mCi);
368         pw.println("mIccid=" + SubscriptionInfo.getPrintableId(mIccid));
369         pw.println("mPhoneId=" + mPhoneId);
370         pw.println("mPhysicalSlotIndex=" + mPhysicalSlotIndex);
371         synchronized (mOpenChannelRecords) {
372             pw.println("mOpenChannelRecords=" + mOpenChannelRecords);
373         }
374         pw.println("mUiccProfile");
375         if (mUiccProfile != null) {
376             mUiccProfile.dump(fd, pw, args);
377         }
378     }
379 
380     /**
381      * Informed that a logical channel has been successfully opened.
382      *
383      * @param request the original request to open the channel, with channel id attached.
384      * @hide
385      */
onLogicalChannelOpened(@onNull IccLogicalChannelRequest request)386     public void onLogicalChannelOpened(@NonNull IccLogicalChannelRequest request) {
387         OpenLogicalChannelRecord record = new OpenLogicalChannelRecord(request);
388         try {
389             request.binder.linkToDeath(record, /*flags=*/ 0);
390             addOpenLogicalChannelRecord(record);
391             if (DBG) log("onLogicalChannelOpened: monitoring client " + record);
392         } catch (RemoteException | NullPointerException ex) {
393             loge("IccOpenLogicChannel client has died, clean up manually");
394             record.binderDied();
395         }
396     }
397 
398     /**
399      * Informed that a logical channel has been successfully closed.
400      *
401      * @param channelId the channel id of the logical channel that was just closed.
402      * @hide
403      */
onLogicalChannelClosed(int channelId)404     public void onLogicalChannelClosed(int channelId) {
405         OpenLogicalChannelRecord record = getOpenLogicalChannelRecord(channelId);
406         if (record != null && record.mRequest != null && record.mRequest.binder != null) {
407             if (DBG) log("onLogicalChannelClosed: stop monitoring client " + record);
408             record.mRequest.binder.unlinkToDeath(record, /*flags=*/ 0);
409             removeOpenLogicalChannelRecord(record);
410             record.mRequest.binder = null;
411         }
412     }
413 
414     /** Get the OpenLogicalChannelRecord matching the channel id. */
415     @VisibleForTesting
getOpenLogicalChannelRecord(int channelId)416     public OpenLogicalChannelRecord getOpenLogicalChannelRecord(int channelId) {
417         synchronized (mOpenChannelRecords) {
418             for (OpenLogicalChannelRecord channelRecord : mOpenChannelRecords) {
419                 if (channelRecord.mRequest != null
420                         && channelRecord.mRequest.channel == channelId) {
421                     return channelRecord;
422                 }
423             }
424         }
425         return null;
426     }
427 
addOpenLogicalChannelRecord(OpenLogicalChannelRecord record)428     private void addOpenLogicalChannelRecord(OpenLogicalChannelRecord record) {
429         synchronized (mOpenChannelRecords) {
430             mOpenChannelRecords.add(record);
431         }
432     }
433 
removeOpenLogicalChannelRecord(OpenLogicalChannelRecord record)434     private void removeOpenLogicalChannelRecord(OpenLogicalChannelRecord record) {
435         synchronized (mOpenChannelRecords) {
436             mOpenChannelRecords.remove(record);
437         }
438     }
439 
440     /** Record to keep open logical channel info. */
441     @VisibleForTesting
442     public class OpenLogicalChannelRecord implements IBinder.DeathRecipient {
443         IccLogicalChannelRequest mRequest;
444 
OpenLogicalChannelRecord(IccLogicalChannelRequest request)445         OpenLogicalChannelRecord(IccLogicalChannelRequest request) {
446             this.mRequest = request;
447         }
448 
449         @Override
binderDied()450         public void binderDied() {
451             loge("IccOpenLogicalChannelRecord: client died, close channel in record " + this);
452             iccCloseLogicalChannel(mRequest.channel, /* response= */ null);
453             onLogicalChannelClosed(mRequest.channel);
454         }
455 
456         @Override
toString()457         public String toString() {
458             StringBuilder sb = new StringBuilder("OpenLogicalChannelRecord {");
459             sb.append(" mRequest=" + mRequest).append("}");
460             return sb.toString();
461         }
462     }
463 }
464