WebAPI/WebIccManager/Multi-SIM
Proposal: WebIccManager API for Multi-SIM
Currently B2G supports a single SIM architecture. This proposal wants to extend WebIccManager to support multi-SIMs. In multi-SIM device, each SIM card is independent and has it own information and operation. Here we introduce multiple nsIDOMMozIcc objects, each instance represents a icc card, you can use iccId as index to get corresponding icc object from nsIDOMMozIccManager.
Web API
interface nsIDOMMozIcc : nsIDOMEventTarget { // UICC Card Information. readonly attribute nsIDOMMozIccInfo iccInfo; [implicit_jscontext] attribute jsval oniccinfochange; // UICC Card State. readonly attribute DOMString cardState; [implicit_jscontext] attribute jsval oncardstatechange; // UICC Card STK. void sendStkResponse(in jsval command, in jsval response); void sendStkMenuSelection(in unsigned short itemIdentifier, in boolean helpRequested); void sendStkTimerExpiration(in jsval timer); void sendStkEventDownload(in jsval event); [implicit_jscontext] attribute jsval onstkcommand; [implicit_jscontext] attribute jsval onstksessionend; // UICC Card Lock interfaces. nsIDOMDOMRequest getCardLock(in DOMString lockType); nsIDOMDOMRequest unlockCardLock(in jsval info); nsIDOMDOMRequest setCardLock(in jsval info); nsIDOMDOMRequest getCardLockRetryCount(in DOMString lockType);[implicit_jscontext] attribute jsval onicccardlockerror;// this event has already been removed in bug 873380. // UICC Phonebook Interfaces. nsIDOMDOMRequest readContacts(in DOMString contactType); nsIDOMDOMRequest updateContact(in DOMString contactType, in nsIDOMContact contact, [optional] in DOMString pin2); // UICC Secure Element Interfaces. nsIDOMDOMRequest iccOpenChannel(in DOMString aid); nsIDOMDOMRequest iccExchangeAPDU(in long channel, in jsval apdu); nsIDOMDOMRequest iccCloseChannel(in long channe); }
interface nsIDOMMozIccManager : nsIDOMEventTarget { readonly attribute jsval iccIds; nsIDOMMozIcc getIccById(in DOMString iccId); [implicit_jscontext] attribute jsval oniccdetected; [implicit_jscontext] attribute jsval oniccundetected; }
Use Case
Stk
- Current B2G:
var icc = navigator.mozIccManager; icc.onstkcommand = function (evt) { var command = evt.command; switch (command.typeOfCommand) { ... } }
icc.sendStkResponse(command, response);
- Multi-SIM:
var iccManager = navigator.mozIccManager; var icc = iccManager.getIccById(iccId); icc.onstkcommand = function (evt) { var command = evt.command; switch (command.typeOfCommand) { ... } }
icc.sendStkResponse(command, response);
Remark: In either single-SIM or multi-SIM scenario, a system message 'icc-stkcommand' is required to launch STK app.
Stk system message
- Current B2G:
window.navigator.mozSetMessageHandler('icc-stkcommand', function callHandleSTKCommand(message) { var command = message; ...... });
- Multi-SIM:
window.navigator.mozSetMessageHandler('icc-stkcommand', function callHandleSTKCommand(message) { var iccId = message.iccId; // The iccId of sim card that propagates this stk command. var command = message.command; ...... });
Enumerate icc cards detected in device
- iccIds:
var iccIds = navigator.mozIccManager.iccIds; for (let iccId in iccIds) { var icc = navigator.mozIccManager.getIccById(iccId); .... }
- Nmber of icc cards which are detected in device:
var numberOfIcc = navigator.mozIccManager.iccIds.length;
Get iccId
- Enumerate from iccManager:
var iccManager = navigator.mozIccManager; var iccId = iccManager.iccIds[0]; // The iccId of the first icc card, not the iccId of the first service, service 0. (Note that service 0 may not have icc card detected.) var icc = iccManager.getIccById(iccId); icc.iccInfo; icc.cardState; ...
- Get from MobileConnection:
var iccId = navigator.mozMobileConnections[1].iccId; // The iccId of the icc card that is detected in service 1. var icc = iccManager.getIccById(iccId); icc.cardState;
Remark: the index of iccIds may not map to service id directly.
Icc Object Life Cycle
Icc object only be created when corresponding icc is detected by system. And becomes invalid after it can not be detected by system.
- You can use IccManager to monitor this.
var iccManager = navigator.mozIccManager; iccManager.oniccdetected = function (evt) { var iccId = evt.iccId; // A new icc is detected by device. // You can use this iccId to get icc object from iccManager. } iccManager.oniccundetected = function (evt) { var iccId = evt.iccId; // An icc becomes undetected. }
- If you already hold a reference for a specific icc object, you can monitor this via cardState or iccInfo.
var icc = iccManager.getIccById(iccId); icc.oncardstatechange = function () { if (icc.cardState === null) { // System can not detect this icc any more, this icc object becomes invalid. } } icc.oniccinfochange = function () { if (icc.iccInfo === null) { // System can not detect this icc any more, this icc object becomes invalid. } }
Remark: Once the icc object becomes invalid, calling asynchronous functions raises exception.
Implementation
Add iccId in the interface of nsIIccProvider.idl and change the implementation of getting iccInfo, cardState.
interface nsIIccListener : nsISupports { void notifyStkCommand(in DOMString aMessage); void notifyStkSessionEnd();void notifyIccCardLockError(in DOMString lockType, in unsigned long retryCount);// This event has already been removed in bug 873380. void notifyCardStateChanged(); void notifyIccInfoChanged(); };
interface nsIIccProvider: nsISupports { void registerIccMsg(in unsigned long clientId, in nsIIccListener listener); void unregisterIccMsg(in unsigned long clientId, in nsIIccListener listener); DOMString getCardState(in unsigned long clientId); nsIDOMMozIccInfo getIccInfo(in unsigned long clientId); void sendStkResponse(in unsigned long clientId, in nsIDOMWindow window, in jsval command, in jsval response); void sendStkMenuSelection(in unsigned long clientId, in nsIDOMWindow window, in unsigned short itemIdentifier, in boolean helpRequested); void sendStkTimerExpiration(in unsigned long clientId, in nsIDOMWindow window, in jsval timer); void sendStkEventDownload(in unsigned long clientId, in nsIDOMWindow window, in jsval event); nsIDOMDOMRequest readContacts(in unsigned long clientId, in nsIDOMWindow window, in DOMString contactType); nsIDOMDOMRequest updateContact(in unsigned long clientId, in nsIDOMWindow window, in DOMString contactType, in nsIDOMContact contact, in DOMString pin2); nsIDOMDOMRequest iccOpenChannel(in unsigned long clientId, in nsIDOMWindow window, in DOMString aid); nsIDOMDOMRequest iccExchangeAPDU(in unsigned long clientId, in nsIDOMWindow window, in long channel, in jsval apdu); nsIDOMDOMRequest iccCloseChannel(in unsigned long clientId, in nsIDOMWindow window, in long channel); nsIDOMDOMRequest getCardLock(in unsigned long clientId, in nsIDOMWindow window, in DOMString lockType); nsIDOMDOMRequest unlockCardLock(in unsigned long clientId, in nsIDOMWindow window, in jsval info); nsIDOMDOMRequest setCardLock(in unsigned long clientId, in nsIDOMWindow window, in jsval info); }
DOM needs to implement the mapping between iccId and clientId. And need to dispatch event to correct icc object.
Proposal: Architecture
Current Architecture
This is the current architecture supporting a single SIM card. API user uses IccManager to get the icc information and handle icc related operation.
Proposal Architecture for Multi-SIM
Status
- Bug 814637 for WebIccManager API. (Ongoing)
- Bug 926343 for IccProvider interface. (Landed)