Android O CellLocation notification flow

CellLocation, that is, the cell location. It saves the location of the network where the device is currently located. For different access technologies, the parameters used to describe the CellLocation are slightly different.  
 

3GPP:  
Including LAC (Location Area Code/Location Area Code), CID (Cell ID/Cell ID), PSC (Primary Scrambling Code/Primary Scrambling Code),  
among which PSC is exclusive to UMTS  
. LAC/RAC is used instead of TAC, so the value of TAC is directly stored as LAC in GsmCellLocation.  
Generally speaking, a location area includes multiple base stations, one base station corresponds to one or more sectors, and one sector corresponds to one cell, but sometimes a cell may also consist of multiple sectors.  

3GPP2:  
Contains SID (System ID/System ID), NID (Network ID/Network ID), BID (Base station ID/Base Station ID), BS Longitude (base station longitude), BS Latitude (base station latitude),  
a System contains multiple network, and there are multiple BSs under one network.  

When querying the voice registration status, the returned result contains CellLocation related information.  
Let's look directly at the places where the voice registration status is queried in the ServiceStateTracker. There are two: 

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));
            ......
}

Let's look at the first one. After returning the query result through RIL, the EVENT_GET_LOC_DONE message is triggered, and then the CellLocation change is notified directly through the Phone.  

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();
            }
        ......
}

Let's look at the return processing flow of the second query voice registration status, triggering the EVENT_POLL_STATE_REGISTRATION message,  

public void handleMessage(Message msg) {
        ......
        case EVENT_POLL_STATE_REGISTRATION:
        ......
            handlePollStateResult(msg.what, ar);
        ......
}

process query results,  

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();
    }

}

It will first call handlePollStateResultMessage() to update the query result,  

void handlePollStateResultMessage(int what, AsyncResult ar) {
    int ints[];
    switch (what) {
        case EVENT_POLL_STATE_REGISTRATION: {
            ......
            processCellLocationInfo(mNewCellLoc, voiceRegStateResult);
        ......
}

Obtain the corresponding CellLocation parameters according to different access technologies, and update the result to 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.CellIdentityTdscdma
                            cellIdentityTdscdma =
                            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);
    }
}

Go back to handlePollStateResult(), and continue to call pollStateDone() after updating the query result.  

If the CellLocation is different from the current value, then send the notification through the Phone,  
which is the same process as the original EVENT_GET_LOC_DONE process.  

private void pollStateDone() {
    ......
    boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc);
    ......
    if (hasLocationChanged) {
        mPhone.notifyLocationChanged();
    }
    ......
}

There is no additional processing in GsmCdmaPhone, continue to notify up.  

public void notifyLocationChanged() {
    mNotifier.notifyCellLocation(this);
}

Then come to DefaultPhoneNotifier, continue to notify TelephonyRegistry,  

public void notifyCellLocation(Phone sender) {
    ......
            mRegistry.notifyCellLocationForSubscriber(subId, data);
    ......
}

Then query the object registered with LISTEN_CELL_LOCATION in the TelephonyRegistry and make a callback.  

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));
    ......
}

By searching for the code, I found that there are a total of 2 places registered to listen to the LISTEN_CELL_LOCATION event.  
One is related to emergency calls, listening when the phone is turned on and off airplane mode.  
EmergencyAffordanceService.java  

public void onBootPhase(int phase) {
    ......
        startScanning();
    ......
}

private BroadcastReceiver mAirplaneModeReceiver = new BroadcastReceiver() {
    @Override
    public 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);
}

The other is in Settings,  
RadioInfo.java  

protected void onResume() {
    ......
    mTelephonyManager.listen(mPhoneStateListener,
              ......
            | PhoneStateListener.LISTEN_CELL_LOCATION
            ......);
    ......
}

 

 

 

 
 
G
M
T
 
 
Detect languageAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEsperantoEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekGujaratiHaitian CreoleHausaHebrewHindiHmongHungarianIcelandicIgboIndonesianIrishItalianJapaneseJavaneseKannadaKazakhKhmerKoreanLaoLatinLatvianLithuanianMacedonianMalagasyMalayMalayalamMalteseMaoriMarathiMongolianMyanmar (Burmese)NepaliNorwegianPersianPolishPortuguesePunjabiRomanianRussianSerbianSesothoSinhalaSlovakSlovenianSomaliSpanishSundaneseSwahiliSwedishTajikTamilTeluguThaiTurkishUkrainianUrduUzbekVietnameseWelshYiddishYorubaZulu
 
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEsperantoEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekGujaratiHaitian CreoleHausaHebrewHindiHmongHungarianIcelandicIgboIndonesianIrishItalianJapaneseJavaneseKannadaKazakhKhmerKoreanLaoLatinLatvianLithuanianMacedonianMalagasyMalayMalayalamMalteseMaoriMarathiMongolianMyanmar (Burmese)NepaliNorwegianPersianPolishPortuguesePunjabiRomanianRussianSerbianSesothoSinhalaSlovakSlovenianSomaliSpanishSundaneseSwahiliSwedishTajikTamilTeluguThaiTurkishUkrainianUrduUzbekVietnameseWelshYiddishYorubaZulu
 
 
 
 
 
 
 
 
 
Text-to-speech function is limited to 200 characters
 
 
Options : History : Feedback : Donate Close

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324928568&siteId=291194637