Why it is impossible to intercept incoming calls on Android
For last several weeks, I’ve been struggling to intercept (not only get notice of) incoming calls on Android, but finally I have to admit that I failed.
Actually, I’m doomed to fail, because it is just Mission Impossible.
For the time being, a BroadcastReceiver
for android.intent.action.PHONE_STATE
is the only chance for application developers to generally probe for incoming calls. However, it comes too late.
Here is why.
com.android.internal.telephony.gsm.RIL.RILReceiver.run(): +---+
android.net.LocalSocket.getInputStream() <-----------------------| |
/ | |
| | |
v | R |
com.android.internal.telephony.gsm.RIL.readRilMessage(InputStream, byte[]) | A |
com.android.internal.telephony.gsm.RIL.processResponse(Parcel): | D |
Case 1: Unsolicited Commands - Incoming Call | I |
com.android.internal.telephony.gsm.RIL.processUnsolicited(Parcel) | O |
com.android.internal.telephony.BaseCommands.mCallStateRegistrants.notifyRegistrants(AsyncResult) | |
com.android.internal.telephony.gsm.CallTracker.sendMessage(Message) | |
| | |
| | S |
v | Y |
com.android.internal.telephony.gsm.CallTracker.handleMessage(Message) | S |
com.android.internal.telephony.gsm.CallTracker.pollCallsWhenSafe() | T |
com.android.internal.telephony.gsm.RIL.getCurrentCalls(Message) | E |
com.android.internal.telephony.gsm.RIL.send(RILRequest) | M |
| | |
| | |
v | |
com.android.internal.telephony.gsm.RIL.RILSender.handleMessage(Message) | |
android.net.LocalSocket.getOutputStream().write(byte[]) ---------------->| |
+---+
Case 2: Solicited Commands - Request Call Info
com.android.internal.telephony.gsm.RIL.processSolicited(Parcel)
com.android.internal.telephony.gsm.RIL.findAndRemoveRequestFromList(int)
com.android.internal.telephony.gsm.RILRequest.mResult.sendToTarget()
|
|
v
com.android.internal.telephony.gsm.CallTracker.handleMessage(Message)
com.android.internal.telephony.gsm.CallTracker.handlePollCalls(AsyncResult)
com.android.internal.telephony.gsm.GSMPhone.notifyNewRingingConnection(Connection)
com.android.internal.telephony.PhoneBase.notifyNewRingingConnectionP(Connection):
com.android.phone.CallNotifier.sendMessage(Message)
|
|
v
com.android.phone.CallNotifier.handleMessage(Message)
com.android.phone.CallNotifier.onNewRingingConnection(AsyncResult)
com.android.phone.PhoneUtils.showIncomingCallUi() <---------------- Users see incoming call
com.android.internal.telephony.gsm.CallTracker.updatePhoneState()
com.android.internal.telephony.gsm.GSMPhone.notifyPhoneStateChanged()
com.android.internal.telephony.DefaultPhoneNotifier.notifyPhoneState(Phone)
com.android.server.TelephonyRegistry.notifyCallState(int, String)
com.android.server.TelephonyRegistry.broadcastCallStateChanged(int, String) <--- Too late to interfere