mroczis / netmonster-core

Android Telephony SDK bridge with some additional features
Apache License 2.0
334 stars 71 forks source link

MOCN postprocessor: False positves #44

Closed handymenny closed 2 years ago

handymenny commented 2 years ago

When network operator isn't "synchronized" with cellinfo, MOCN post processor may replace the correct PLMN with the wrong one.

Example:

pre : CellLte(network=Network(mcc=222, mnc=10, iso=IT), eci=2***5, tac=4***, pci=0, band=BandLte(downlinkEarfcn=3025, number=7, name=2600), bandwidth=null, signal=SignalLte(rssi=-83, rsrp=-116.0, rsrq=-12.0, cqi=null, snr=null, timingAdvance=null), connectionStatus=PrimaryConnection(), subscriptionId=12, timestamp=602895)

service state network = Network(mcc=222, mnc=01, iso=IT)
network operator = Network(mcc=222, mnc=01, iso=IT)

post: CellLte(network=Network(mcc=222, mnc=01, iso=IT), eci=2***5, tac=4***, pci=0, band=BandLte(downlinkEarfcn=3025, number=7, name=2600), bandwidth=null, signal=SignalLte(rssi=-83, rsrp=-116.0, rsrq=-12.0, cqi=null, snr=null, timingAdvance=null), connectionStatus=PrimaryConnection(), subscriptionId=12, timestamp=602895)

## After 5 seconds

pre : CellLte(network=Network(mcc=222, mnc=10, iso=IT), eci=2***5, tac=4***, pci=0, band=BandLte(downlinkEarfcn=3025, number=7, name=2600), bandwidth=null, signal=SignalLte(rssi=-81, rsrp=-118.0, rsrq=-16.0, cqi=null, snr=null, timingAdvance=null), connectionStatus=NoneConnection(), subscriptionId=2147483647, timestamp=608775)

service state network = null
network operator = null

post: CellLte(network=Network(mcc=222, mnc=10, iso=IT), eci=2***5, tac=4***, pci=0, band=BandLte(downlinkEarfcn=3025, number=7, name=2600), bandwidth=null, signal=SignalLte(rssi=-81, rsrp=-118.0, rsrq=-16.0, cqi=null, snr=null, timingAdvance=null), connectionStatus=NoneConnection(), subscriptionId=2147483647, timestamp=608775)

This happens mostly in roaming or "emergency only" and is temporary, lasting at most two minutes and usually about ten seconds or so. But for those who use this library for cell mapping, it can significantly increase the number of cells with wrong plmn.

So I was wondering if the problem could be somehow mitigated, maybe applying that postprocessor only for some Android versions? For example I see that Google marked the bug as fixed and added specific tests/APIs for MOCN in Android R.

mroczis commented 2 years ago

Can you provide full ServiceState as a String? Maybe NetworkRegistrationInfo can be used as a source of correct PLMN.

handymenny commented 2 years ago

This is from my main device (Android P), mMnc is always null but ServiceState.operatorNumeric is ok :

2022-07-10 14:04:06.848 31894-31894/cz.mroczis.netmonster.sample V/netmonster-bug: {mVoiceRegState=0(IN_SERVICE), mDataRegState=1(OUT_OF_SERVICE), mChannelNumber=3025, duplexMode()=0, mCellBandwidths=[], mVoiceRoamingType=home, mDataRoamingType=home, mVoiceOperatorAlphaLong=TIM, mVoiceOperatorAlphaShort=CV, mDataOperatorAlphaLong=TIM, mDataOperatorAlphaShort=CV, isManualNetworkSelection=true(manual), mRilVoiceRadioTechnology=14(LTE), mRilDataRadioTechnology=0(Unknown), mCssIndicator=unsupported, mNetworkId=-1, mSystemId=-1, mCdmaRoamingIndicator=-1, mCdmaDefaultRoamingIndicator=-1, mIsEmergencyOnly=false, mIsDataRoamingFromRegistration=false, mIsUsingCarrierAggregation=false, mLteEarfcnRsrpBoost=0, mNetworkRegistrationStates=[NetworkRegistrationState{transportType=1 domain=PS regState=NOT_REG_NOT_SEARCHING accessNetworkTechnology=UNKNOWN reasonForDenial=0 emergencyEnabled=false supportedServices=null cellIdentity=null voiceSpecificStates=null dataSpecificStates=DataSpecificRegistrationStates { mMaxDataCalls=20}}, NetworkRegistrationState{transportType=1 domain=CS regState=HOME accessNetworkTechnology=LTE reasonForDenial=0 emergencyEnabled=false supportedServices=[I@ad03e6d cellIdentity=CellIdentityLte:{ mCi=2***3 mPci=0 mTac=6***0 mEarfcn=3025 mBandwidth=2147483647 mMcc=222 mMnc=null mAlphaLong=null mAlphaShort=null mRat=UNDEFINED_OR_NO_CHANGE mState=UNKNOWN} voiceSpecificStates=VoiceSpecificRegistrationStates { mCssSupported=false mRoamingIndicator=-1 mSystemIsInPrl=-1 mDefaultRoamingIndicator=-1} dataSpecificStates=null}]}

2022-07-10 14:04:06.859 31894-31894/cz.mroczis.netmonster.sample D/NTM-RES:  
    CellLte(network=Network(mcc=222, mnc=01, iso=IT), eci=2***3, tac=4***2, pci=0, band=BandLte(downlinkEarfcn=3025, number=7, name=2600), bandwidth=null, signal=SignalLte(rssi=-73, rsrp=-109.0, rsrq=-13.0, cqi=null, snr=null, timingAdvance=3), connectionStatus=PrimaryConnection(), subscriptionId=12, timestamp=35478035)
    CellLte(network=Network(mcc=222, mnc=01, iso=IT), eci=null, tac=null, pci=108, band=BandLte(downlinkEarfcn=3025, number=7, name=2600), bandwidth=null, signal=SignalLte(rssi=-85, rsrp=-111.0, rsrq=-15.0, cqi=null, snr=null, timingAdvance=null), connectionStatus=NoneConnection(), subscriptionId=12, timestamp=35478035)

This, instead, is from a device running Android R:

[SUB-2147483647]
[CellInfoLte:{mRegistered=NO mTimeStamp=196838806377281ns mCellConnectionStatus=0 CellIdentityLte:{ mCi=10554882 mPci=124 mTac=45 mEarfcn=1350 mBands=[] mBandwidth=2147483647 mMcc=297 mMnc=01 mAlphaLong=Telenor mAlphaShort=Telenor mAdditionalPlmns={} mCsgInfo=null} CellSignalStrengthLte: rssi=-105 rsrp=-126 rsrq=-19 rssnr=2147483647 cqi=2147483647 ta=2147483647 level=0 parametersUseForLevel=0 android.telephony.CellConfigLte :{ isEndcAvailable = false }}

[SS]
[SUB-2147483647]
{mVoiceRegState=1(OUT_OF_SERVICE), mDataRegState=0(IN_SERVICE), mChannelNumber=3063, duplexMode()=0, mCellBandwidths=[], mOperatorAlphaLong=WINDTRE, mOperatorAlphaShort=WINDTRE, isManualNetworkSelection=false(automatic), getRilVoiceRadioTechnology=0(Unknown), getRilDataRadioTechnology=11(HSPA), mCssIndicator=unsupported, mNetworkId=-1, mSystemId=-1, mCdmaRoamingIndicator=-1, mCdmaDefaultRoamingIndicator=-1, mIsEmergencyOnly=false, isUsingCarrierAggregation=false, mNetworkRegistrationInfos=[NetworkRegistrationInfo{ domain=PS transportType=WLAN registrationState=NOT_REG_OR_SEARCHING roamingType=NOT_ROAMING accessNetworkTechnology=UNKNOWN rejectCause=0 emergencyEnabled=false availableServices=[] cellIdentity=null voiceSpecificInfo=null dataSpecificInfo=android.telephony.DataSpecificRegistrationInfo :{ maxDataCalls = 0 isDcNrRestricted = false isNrAvailable = false isEnDcAvailable = false LteVopsSupportInfo :  mVopsSupport = 1 mEmcBearerSupport = 1 mIsUsingCarrierAggregation = false } nrState=NONE rRplmn=null}, NetworkRegistrationInfo{ domain=CS transportType=WWAN registrationState=NOT_REG_SEARCHING roamingType=NOT_ROAMING accessNetworkTechnology=UNKNOWN rejectCause=0 emergencyEnabled=false availableServices=[] cellIdentity=null voiceSpecificInfo=VoiceSpecificRegistrationInfo { mCssSupported=false mRoamingIndicator=0 mSystemIsInPrl=0 mDefaultRoamingIndicator=0} dataSpecificInfo=null nrState=NONE rRplmn=}, NetworkRegistrationInfo{ domain=PS transportType=WWAN registrationState=HOME roamingType=NOT_ROAMING accessNetworkTechnology=HSPA rejectCause=0 emergencyEnabled=false availableServices=[DATA] cellIdentity=CellIdentityWcdma:{ mLac=44621 mCid=41743090 mPsc=418 mUarfcn=3063 mMcc=222 mMnc=88 mAlphaLong=WINDTRE mAlphaShort=WINDTRE mAdditionalPlmns={} mCsgInfo=null} voiceSpecificInfo=null dataSpecificInfo=android.telephony.DataSpecificRegistrationInfo :{ maxDataCalls = 16 isDcNrRestricted = false isNrAvailable = false isEnDcAvailable = false LteVopsSupportInfo :  mVopsSupport = 1 mEmcBearerSupport = 1 mIsUsingCarrierAggregation = false } nrState=NONE rRplmn=22288}], mNrFrequencyRange=0, mOperatorAlphaLongRaw=WINDTRE, mOperatorAlphaShortRaw=, mIsIwlanPreferred=false, Ril Voice Regist state=2, Ril Data Regist state=1, mProprietaryDataRadioTechnology=0, VoiceRejectCause=-1, DataRejectCause=-1, IwlanRegState=1, CellularVoiceRegState=1, CellularDataRegState=0, RilCellularDataRegState=1, CellularDataRoamingType=0, CellularDataNetworkType=10}
22288 | WINDTRE | WINDTRE

[RAW-CORE]
CellLte(network=Network(mcc=222, mnc=88, iso=IT), eci=10554882, tac=45, pci=124, band=BandLte(downlinkEarfcn=1350, number=3, name=1800), bandwidth=null, signal=SignalLte(rssi=-105, rsrp=-126.0, rsrq=-19.0, cqi=null, snr=null, timingAdvance=null), connectionStatus=PrimaryConnection(), subscriptionId=2147483647, timestamp=196838806)

I noticed that when this issue happens, CellInfo.isRegistered and NetworkRegistrationInfo#isRegistered are false. If the device isn't registered it cannot know the right PLMN, so this issue could be solved by checking whether it's registered or not, but for API < 30 only CellInfo.isRegistered is available...

mroczis commented 2 years ago

I have adjusted MOCN postprocessor for Android R+ and added a few checks that will prevent it tampering data.

handymenny commented 2 years ago

Thank you, nice solution. I would add an MCC check there, though: https://github.com/mroczis/netmonster-core/blob/9603c1746e386320f3798d8670360c882a92267e/library/src/main/java/cz/mroczis/netmonster/core/feature/postprocess/MocnNetworkPostprocessor.kt#L47 Mainly for devices with Android Q and below.

Also, it might be useful to put "(cell is CellLte || cell.network == null)" before getNetworkOperator, that's a lot of code you can avoid running