UiccのUiccController(元)
UiccControllerは、UICCトランザクション全体のエントリであり、IccRecords、IccFileHandler、UIcCardApplicationなどのオブジェクトを外部に提供し、UICCシステム全体の初期化を完了します.
一、UiccControllerが提供する主な機能
私たちが提供するpublic方法を通じて、彼の主な機能を見てみましょう.
上記の方法から分かるように、UiccControllerの主な役割は2つの面に現れている.
1.UiccCard、UiccCardApplication、IccRecords、IccFileHandlerなどのオブジェクトを作成して外部に提供する
2、SIM状態の傍受を提供する
二、UiccControllerの作成過程
まずUiccControllerがどこで作成されたかを見てみましょう.PhoneオブジェクトはPhoneモジュールの初期化でPhoneFactoryによって作成されたことを知っています.
次に、UiccControllerのmake()メソッドを使用して、特定の作成プロセスを見てみましょう.
UiccControllerオブジェクトは1つのみ存在します.
UiccControllerのコンストラクション関数では、registerForIcccStatusChangedとregisterForOnの2つのリスナーを登録することしかできません.この2つのリスナーはSIMカードとRadioの状態を傍受しており、彼らはUiccController更新のトリガである.
三、UiccController更新メカニズム
先ほどお話ししたように、UiccControllerの初期化プロセスは主にRILJに2つのListenerを登録していますが、この2つのListenerはUiccController更新メカニズムのトリガであり、リスニングされたイベントが発生すると、UiccControllerはUICCフレームワーク全体の更新メカニズムを起動します.
具体的な更新手順を見てみましょう.
3.1.リスナーが傍受するイベント
3.1.1.registerForIccStatusChangedリスナー
registerForIccStatusChangedという登録の動作は、RILクラスに直接呼び出されるのではなく、RILの親BaseCommandsに呼び出されます.
1、誤ったPINまたはPUKを入力した場合:
2、SIMカードの状態が変化した場合:
3.1.2、registerForOnリスナーはregisterForIccStatusChangedと類似しており、registerForOn()もBaseCommandsで実現されている.
1、Radio状態が変化した場合:
2、RILJとRILC通路が切り離された場合
上記の分析から、RILは、以下のイベントが発生すると、現在のUIcControllerに通知を開始することがわかります.
1、入力エラーのPIN、PUKコード2、SIMカード状態変化3、Radio状態変化4、Socketチャネルオフ
次に、UiccControllerの動作を確認します.
3.2.UiccControllerによるリスニングイベントの処理フローUiccControllerが上記の2種類のリスナーを登録する際に使用するwhatパラメータはいずれも「EVENT_ICC_STATUS_CHANGED」であるため、上記リスニングイベントが発生した場合、いずれも同じEVENT_ICC_STATUS_CHANGEDのcaseブランチ:
RILJがgetIccCardStatus()のリクエストを取得すると、Modemに現在のSIMカードのステータスを問い合わせるリクエストが開始されます.
1、UiccCardを作成または更新する;2.他のサブリスナーに通知する.
また、2つの情報を取得しました.1、UiccCardオブジェクトは、UiccControllerがSIMカードの状態を更新したときに作成されます.2、その他のオブジェクトはregisterForIccChanged()メソッドでUIcControllerにSIMカードのステータスリスニングを申請することができる.
これで、UiccControllerの解析は終了し、次の章ではUiccCardオブジェクトについて説明します.
一、UiccControllerが提供する主な機能
私たちが提供するpublic方法を通じて、彼の主な機能を見てみましょう.
public UiccCard getUiccCard() {}
public UiccCardApplication getUiccCardApplication(int family) {}
public IccRecords getIccRecords(int family) {}
public IccFileHandler getIccFileHandler(int family) {}
public void registerForIccChanged(Handler h, int what, Object obj) {}
上記の方法から分かるように、UiccControllerの主な役割は2つの面に現れている.
1.UiccCard、UiccCardApplication、IccRecords、IccFileHandlerなどのオブジェクトを作成して外部に提供する
2、SIM状態の傍受を提供する
二、UiccControllerの作成過程
まずUiccControllerがどこで作成されたかを見てみましょう.PhoneオブジェクトはPhoneモジュールの初期化でPhoneFactoryによって作成されたことを知っています.
@PhoneGlobals.java
public void onCreate() {
if (phone == null) {
// Phone
PhoneFactory.makeDefaultPhones(this);
// Phone
phone = PhoneFactory.getDefaultPhone();
}
}
次にmakeDefaultPhones()のプロセスを見ます. @PhoneFactory.java
public static void makeDefaultPhones(Context context) {
makeDefaultPhone(context);
}
public static void makeDefaultPhone(Context context) {
// RILJ
sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
// UiccController
UiccController.make(context, sCommandsInterface);
// phone Type
int phoneType = TelephonyManager.getPhoneType(networkMode);
// PhoneProxy
if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
sProxyPhone = new PhoneProxy(new GSMPhone(context, sCommandsInterface, sPhoneNotifier));
} else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
switch (TelephonyManager.getLteOnCdmaModeStatic()) {
case PhoneConstants.LTE_ON_CDMA_TRUE:
sProxyPhone = new PhoneProxy(new CDMALTEPhone(context, sCommandsInterface, sPhoneNotifier));
break;
case PhoneConstants.LTE_ON_CDMA_FALSE:
default:
sProxyPhone = new PhoneProxy(new CDMAPhone(context, sCommandsInterface, sPhoneNotifier));
break;
}
}
}
ここでは、newがRILオブジェクトを完了した後に、UiccControllerのmake()メソッドによってUiccControllerが作成され、渡された2つのパラメータのうちの1つがContextタイプオブジェクトであり、もう1つがCommandsInterfaceタイプのRILオブジェクトであることを示します.次に、UiccControllerのmake()メソッドを使用して、特定の作成プロセスを見てみましょう.
@UiccController.java
public static UiccController make(Context c, CommandsInterface ci) {
synchronized (mLock) {
if (mInstance != null) {
throw new RuntimeException("UiccController.make() should only be called once");
}
mInstance = new UiccController(c, ci);
return mInstance;
}
}
ここで注意すべきことは、UiccControllerのmake()メソッドは、一度だけ呼び出されます.つまり、グローバル全体で、UiccControllerオブジェクトは1つのみ存在します.
private UiccController(Context c, CommandsInterface ci) {
mContext = c;
mCi = ci;
mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null);
mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null);
}
UiccControllerのコンストラクション関数では、registerForIcccStatusChangedとregisterForOnの2つのリスナーを登録することしかできません.この2つのリスナーはSIMカードとRadioの状態を傍受しており、彼らはUiccController更新のトリガである.
三、UiccController更新メカニズム
先ほどお話ししたように、UiccControllerの初期化プロセスは主にRILJに2つのListenerを登録していますが、この2つのListenerはUiccController更新メカニズムのトリガであり、リスニングされたイベントが発生すると、UiccControllerはUICCフレームワーク全体の更新メカニズムを起動します.
具体的な更新手順を見てみましょう.
3.1.リスナーが傍受するイベント
3.1.1.registerForIccStatusChangedリスナー
registerForIccStatusChangedという登録の動作は、RILクラスに直接呼び出されるのではなく、RILの親BaseCommandsに呼び出されます.
@BaseCommands.java
public void registerForIccStatusChanged(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
mIccStatusChangedRegistrants.add(r);
}
ここでの登録プロセスは、mIcccStatusChangedRegistrantsオブジェクトリストに現在の登録オブジェクトを追加し、次の2つのイベントが発生すると、リスト内のリスナーに通知されます.1、誤ったPINまたはPUKを入力した場合:
private RILRequest processSolicited (Parcel p) {
switch (rr.mRequest) {
case RIL_REQUEST_ENTER_SIM_PUK:
case RIL_REQUEST_ENTER_SIM_PUK2:
if (mIccStatusChangedRegistrants != null) {
mIccStatusChangedRegistrants.notifyRegistrants();
}
break;
}
}
2、SIMカードの状態が変化した場合:
private void processUnsolicited (Parcel p) {
switch(response) {
case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:
if (mIccStatusChangedRegistrants != null) {
mIccStatusChangedRegistrants.notifyRegistrants();
}
break;
}
}
3.1.2、registerForOnリスナーはregisterForIccStatusChangedと類似しており、registerForOn()もBaseCommandsで実現されている.
@BaseCommands.java
public void registerForOn(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
synchronized (mStateMonitor) {
// mOnRegistrants
mOnRegistrants.add(r);
if (mState.isOn()) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
}
登録のプロセスは、mOnRegistrants変数のリストにリスナー情報を保存し、次の2つのイベントが発生するとリストを巡回してリスナーに通知することです.1、Radio状態が変化した場合:
private void processUnsolicited (Parcel p) {
switch(response) {
case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:
RadioState newState = getRadioStateFromInt(p.readInt());
switchToRadioState(newState);
break;
}
}
private void switchToRadioState(RadioState newState) {
setRadioState(newState);
}
protected void setRadioState(RadioState newState) {
synchronized (mStateMonitor) {
//
mRadioStateChangedRegistrants.notifyRegistrants();
}
}
2、RILJとRILC通路が切り離された場合
class RILReceiver implements Runnable {
@Override
public void run() {
//Socket , Radio unavailable
setRadioState (RadioState.RADIO_UNAVAILABLE);
}
}
上記の分析から、RILは、以下のイベントが発生すると、現在のUIcControllerに通知を開始することがわかります.
1、入力エラーのPIN、PUKコード2、SIMカード状態変化3、Radio状態変化4、Socketチャネルオフ
次に、UiccControllerの動作を確認します.
3.2.UiccControllerによるリスニングイベントの処理フローUiccControllerが上記の2種類のリスナーを登録する際に使用するwhatパラメータはいずれも「EVENT_ICC_STATUS_CHANGED」であるため、上記リスニングイベントが発生した場合、いずれも同じEVENT_ICC_STATUS_CHANGEDのcaseブランチ:
@UiccController.java
public void handleMessage (Message msg) {
synchronized (mLock) {
switch (msg.what) {
case EVENT_ICC_STATUS_CHANGED:
// SIM Radio , case
mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
break;
case EVENT_GET_ICC_STATUS_DONE:
AsyncResult ar = (AsyncResult)msg.obj;
onGetIccCardStatusDone(ar);
break;
default:
Rlog.e(LOG_TAG, " Unknown Event " + msg.what);
}
}
}
はRILを呼び出す.JAvaのgetIccCardStatus()メソッドは、最新のSIMとRadio状態をクエリーします.RILJがgetIccCardStatus()のリクエストを取得すると、Modemに現在のSIMカードのステータスを問い合わせるリクエストが開始されます.
@RIL.java
public void getIccCardStatus(Message result) {
// Modem , SIM
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_SIM_STATUS, result);
send(rr);
}
そして最新の状態を取得した後、結果を開始要求の対象にフィードバックします.現在はUiccControllerです. private RILRequest processSolicited (Parcel p) {
switch (rr.mRequest) {
case RIL_REQUEST_GET_SIM_STATUS:
// Modem IccCardStatus
ret = responseIccCardStatus(p); break;
}
if (rr.mResult != null) {
AsyncResult.forMessage(rr.mResult, ret, null);
// UiccController
rr.mResult.sendToTarget();
}
}
続いて、UiccControllerは再びhandleMessage()メソッドで次の流れを処理しますが、今回入ったのはEVENT_です.GET_ICC_STATUS_DONEのケースフロー: @UiccController.java
public void handleMessage (Message msg) {
synchronized (mLock) {
switch (msg.what) {
case EVENT_ICC_STATUS_CHANGED:
// ,
mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
break;
case EVENT_GET_ICC_STATUS_DONE:
// SIM
AsyncResult ar = (AsyncResult)msg.obj;
onGetIccCardStatusDone(ar);
break;
default:
Rlog.e(LOG_TAG, " Unknown Event " + msg.what);
}
}
}
UiccControllerの最新状態に対する処理を引き続き見る: private synchronized void onGetIccCardStatusDone(AsyncResult ar) {
if (ar.exception != null) {
return;
}
// RIL IccCardStatus
IccCardStatus status = (IccCardStatus)ar.result;
// UiccCard
if (mUiccCard == null) {
mUiccCard = new UiccCard(mContext, mCi, status);
} else {
mUiccCard.update(mContext, mCi , status);
}
//
mIccChangedRegistrants.notifyRegistrants();
}
ここでは、UiccControllerが最新のSIMカードのステータスを取得した後、2つのことをしました.1、UiccCardを作成または更新する;2.他のサブリスナーに通知する.
また、2つの情報を取得しました.1、UiccCardオブジェクトは、UiccControllerがSIMカードの状態を更新したときに作成されます.2、その他のオブジェクトはregisterForIccChanged()メソッドでUIcControllerにSIMカードのステータスリスニングを申請することができる.
これで、UiccControllerの解析は終了し、次の章ではUiccCardオブジェクトについて説明します.