2019独角兽企业重金招聘Python工程师标准>>>
CellLocation,即小区位置。它保存了设备当前所处网络的位置,对于不同的接入技术,其用来描述CellLocation的参数略有不同。
3GPP:
包含LAC(Location Area Code/位置区域码)、CID(Cell ID/小区ID)、PSC(Primary Scrambling Code/主扰码),
其中PSC是UMTS专有的,
另外,由于LTE中已不再使用LAC/RAC,取而代之的是TAC,因此在GsmCellLocation中直接把其TAC的值作为LAC来保存。
一般来讲,一个位置区包含多个基站,一个基站对应一个或多个扇区,而一个扇区对应一个小区,但有时一个小区也可能由多个扇区组成。
3GPP2:
包含SID(System ID/系统ID)、NID(Network ID/网络ID)、BID(Base station ID/基站ID)、BS Longitude(基站经度)、BS Latitude(基站纬度),
一个System下面包含多个Network,而一个Network下面又有多个BS。
当查询voice注册状态时,返回的结果中就包含了CellLocation相关信息。
我们直接来看ServiceStateTracker中查询voice注册状态的地方,有如下2个:
public void handleMessage(Message msg) {......case EVENT_LOCATION_UPDATES_ENABLED:ar = (AsyncResult) msg.obj;if (ar.exception == null) {mCi.getVoiceRegistrationState(obtainMessage(EVENT_GET_LOC_DONE, null));}break;......
}public void pollState(boolean modemTriggered) {......mCi.getVoiceRegistrationState(obtainMessage(EVENT_POLL_STATE_REGISTRATION,mPollingContext));......
}
先来看第一个,通过RIL返回查询结果后触发EVENT_GET_LOC_DONE消息,然后就直接通过Phone往上通知CellLocation改变。
public void handleMessage(Message msg) {......case EVENT_GET_LOC_DONE:ar = (AsyncResult) msg.obj;if (ar.exception == null) {processCellLocationInfo(mCellLoc, (VoiceRegStateResult) ar.result);mPhone.notifyLocationChanged();}......
}
再来看第二个查询voice注册状态的返回处理流程,触发EVENT_POLL_STATE_REGISTRATION消息,
public void handleMessage(Message msg) {......case EVENT_POLL_STATE_REGISTRATION:......handlePollStateResult(msg.what, ar);......
}
处理查询结果,
protected void handlePollStateResult(int what, AsyncResult ar) {......if (ar.exception != null) {......} else try {handlePollStateResultMessage(what, ar);} catch (RuntimeException ex) {......}mPollingContext[0]--;if (mPollingContext[0] == 0) {......pollStateDone();}}
会先调用handlePollStateResultMessage()更新查询结果,
void handlePollStateResultMessage(int what, AsyncResult ar) {int ints[];switch (what) {case EVENT_POLL_STATE_REGISTRATION: {......processCellLocationInfo(mNewCellLoc, voiceRegStateResult);......
}
根据不同接入技术获取相应的CellLocation参数,并将结果更新到ServiceStateTracker.mNewCellLoc中。
private void processCellLocationInfo(CellLocation cellLocation,VoiceRegStateResult voiceRegStateResult) {if (mPhone.isPhoneTypeGsm()) {......switch(voiceRegStateResult.cellIdentity.cellInfoType) {case CellInfoType.GSM: {if (voiceRegStateResult.cellIdentity.cellIdentityGsm.size() == 1) {android.hardware.radio.V1_0.CellIdentityGsm cellIdentityGsm =voiceRegStateResult.cellIdentity.cellIdentityGsm.get(0);cid = cellIdentityGsm.cid;lac = cellIdentityGsm.lac;}break;}case CellInfoType.WCDMA: {if (voiceRegStateResult.cellIdentity.cellIdentityWcdma.size() == 1) {android.hardware.radio.V1_0.CellIdentityWcdma cellIdentityWcdma =voiceRegStateResult.cellIdentity.cellIdentityWcdma.get(0);cid = cellIdentityWcdma.cid;lac = cellIdentityWcdma.lac;psc = cellIdentityWcdma.psc;}break;}case CellInfoType.TD_SCDMA: {if (voiceRegStateResult.cellIdentity.cellIdentityTdscdma.size() == 1) {android.hardware.radio.V1_0.CellIdentityTdscdmacellIdentityTdscdma =voiceRegStateResult.cellIdentity.cellIdentityTdscdma.get(0);cid = cellIdentityTdscdma.cid;lac = cellIdentityTdscdma.lac;}break;}case CellInfoType.LTE: {if (voiceRegStateResult.cellIdentity.cellIdentityLte.size() == 1) {android.hardware.radio.V1_0.CellIdentityLte cellIdentityLte =voiceRegStateResult.cellIdentity.cellIdentityLte.get(0);cid = cellIdentityLte.ci;/* Continuing the historical behaviour of using tac as lac. */lac = cellIdentityLte.tac;}break;}default: {break;}}// LAC and CID are -1 if not avail((GsmCellLocation) cellLocation).setLacAndCid(lac, cid);((GsmCellLocation) cellLocation).setPsc(psc);} else {......switch(voiceRegStateResult.cellIdentity.cellInfoType) {case CellInfoType.CDMA: {if (voiceRegStateResult.cellIdentity.cellIdentityCdma.size() == 1) {android.hardware.radio.V1_0.CellIdentityCdma cellIdentityCdma =voiceRegStateResult.cellIdentity.cellIdentityCdma.get(0);baseStationId = cellIdentityCdma.baseStationId;baseStationLatitude = cellIdentityCdma.latitude;baseStationLongitude = cellIdentityCdma.longitude;systemId = cellIdentityCdma.systemId;networkId = cellIdentityCdma.networkId;}break;}default: {break;}}......((CdmaCellLocation) cellLocation).setCellLocationData(baseStationId,baseStationLatitude, baseStationLongitude, systemId, networkId);}
}
再回到handlePollStateResult()中,更新完查询结果后继续调用pollStateDone(),
如果CellLocation和当前值不同,那就通过Phone发送通知,
这就与最开始处理EVENT_GET_LOC_DONE的流程相同了。
private void pollStateDone() {......boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc);......if (hasLocationChanged) {mPhone.notifyLocationChanged();}......
}
GsmCdmaPhone中没有任何额外处理,继续向上通知。
public void notifyLocationChanged() {mNotifier.notifyCellLocation(this);
}
然后来到DefaultPhoneNotifier中,继续通知TelephonyRegistry,
public void notifyCellLocation(Phone sender) {......mRegistry.notifyCellLocationForSubscriber(subId, data);......
}
然后就在TelephonyRegistry中查询注册了LISTEN_CELL_LOCATION的对象,并进行回调。
public void notifyCellLocationForSubscriber(int subId, Bundle cellLocation) {......for (Record r : mRecords) {if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&idMatch(r.subId, subId, phoneId)) {......r.callback.onCellLocationChanged(new Bundle(cellLocation));......
}
通过搜索代码,发现共有如下2个地方注册监听了LISTEN_CELL_LOCATION事件。
一个是和紧急呼叫相关的,在手机启动及关闭飞行模式时进行监听。
EmergencyAffordanceService.java
public void onBootPhase(int phase) {......startScanning();......
}private BroadcastReceiver mAirplaneModeReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {if (Settings.Global.getInt(context.getContentResolver(),Settings.Global.AIRPLANE_MODE_ON, 0) == 0) {startScanning();requestCellScan();}}
};private void startScanning() {mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CELL_INFO| PhoneStateListener.LISTEN_CELL_LOCATION);
}
另一个就是在Settings中,
RadioInfo.java
protected void onResume() {......mTelephonyManager.listen(mPhoneStateListener,......| PhoneStateListener.LISTEN_CELL_LOCATION......);......
}
Detect languageAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEsperantoEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekGujaratiHaitian CreoleHausaHebrewHindiHmongHungarianIcelandicIgboIndonesianIrishItalianJapaneseJavaneseKannadaKazakhKhmerKoreanLaoLatinLatvianLithuanianMacedonianMalagasyMalayMalayalamMalteseMaoriMarathiMongolianMyanmar (Burmese)NepaliNorwegianPersianPolishPortuguesePunjabiRomanianRussianSerbianSesothoSinhalaSlovakSlovenianSomaliSpanishSundaneseSwahiliSwedishTajikTamilTeluguThaiTurkishUkrainianUrduUzbekVietnameseWelshYiddishYorubaZulu | AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEsperantoEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekGujaratiHaitian CreoleHausaHebrewHindiHmongHungarianIcelandicIgboIndonesianIrishItalianJapaneseJavaneseKannadaKazakhKhmerKoreanLaoLatinLatvianLithuanianMacedonianMalagasyMalayMalayalamMalteseMaoriMarathiMongolianMyanmar (Burmese)NepaliNorwegianPersianPolishPortuguesePunjabiRomanianRussianSerbianSesothoSinhalaSlovakSlovenianSomaliSpanishSundaneseSwahiliSwedishTajikTamilTeluguThaiTurkishUkrainianUrduUzbekVietnameseWelshYiddishYorubaZulu |
Options : History : Feedback : Donate | Close |