"Subscription ID" always "1" in block "call incoming" on dual SIM phone

2,860 views
Skip to first unread message

metat...@gmail.com

unread,
Dec 29, 2016, 4:08:28 PM12/29/16
to Automate
Hello,

I am trying to start a flow when a call is incoming on a specific SIM card on a dual SIM phone (Sony Xperia XA Dual, F3112 with Android 6.0.1).
In the configuration of the "Call incoming" block, the combo box displays properly the 2 SIM cards, with the 2 nicknames I gave them in the Xperia system configuration.
However, when actually calling the phone from another phone to its number 1 or number 2 the field "Subscription ID" contains always value "1".
Can you please tell me whether this a problem/limitation of the phone firmware, or a bug in Automate ?

Thanks in advance,
Regards,

metatech

Henrik "The Developer" Lindqvist

unread,
Dec 30, 2016, 2:32:41 PM12/30/16
to Automate
Dual-SIM support in Android is still incomplete so Automate has to reply on an undocumented "hack" to find the proper subscription ID of incoming calls:
https://www.skoumal.net/en/android-duplicated-phone-state-broadcast-on-lollipop/

Please try a simple test flow:

  Flow beginning
         |
+------->+
|        |
| Broadcast receive
| Action= "android.intent.action.PHONE_STATE"
| Broadcast extras: extras
|        |
|    Log append
|      extras
+---------+


Then post the flow log. I'm interested in the value of extra "subscription" for the calls state broadcast.

metat...@gmail.com

unread,
Dec 30, 2016, 4:15:32 PM12/30/16
to Automate
Hello,

Thanks for your debugging suggestion.

In the log, I see :
incoming_number as String: +3312345678, state as String: RINGING

Other output variables of the PHONE_STATE intent are empty : uri, mime, categories

Could the same information be obtained with the calls "createForSubscriptionId(1 or 2)" and "getCallState()" method ?

Is there any other verbose logging/debugging that can be helpful ?

Thanks,

metatech

metat...@gmail.com

unread,
Dec 31, 2016, 10:45:00 AM12/31/16
to Automate
Hi,

After more investigation, it seems that the "subscription" extra was indeed removed from Android 6.0 in the default case.
The difference can be seen in the "com/android/server/TelephonyRegistry.java" class, in the "broadcastCallStateChanged" method :
Telephony for Android 5.0
Telephony for Android 6.0

Under Android 5.x, the extra "subscription" is added unconditionally in the intent :
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);


Under Android 6.0+, the extra "subscription" is only added if the TelephonyManager was instantiated for a specific subscription (ie SIM card).

// If a valid subId was specified, we should fire off a subId-specific state
 
// change intent and include the subId.
 
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
     intent
.setAction(PhoneConstants.ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
     intent
.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
 
}


Note : the code is identical in 6.0, 7.0 and "master" (all subsequent versions).

So, it is true that the "subscription" extra is not present anymore in the default case starting in Android 6.0, but the TelephonyManager can be instantiated for a specific subscription/SIM card, which will contain the "subscription" extra.

Do you think is it feasible to integrate this feature into Automate ?

Thanks in advance,
Best regards,

Henrik "The Developer" Lindqvist

unread,
Jan 1, 2017, 2:42:15 PM1/1/17
to Automate
Thanks for helping with the investigation. Sigh, Google making a mess again.
According to the code it seems the broadcast is no longer standard ACTION_PHONE_STATE_CHANGED but instead an undocumented ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED, but only if an subscription id is specified:
https://github.com/android/platform_frameworks_base/blob/marshmallow-release/services/core/java/com/android/server/TelephonyRegistry.java#L1452

So now we need to register for both actions.

metat...@gmail.com

unread,
Jan 1, 2017, 5:16:07 PM1/1/17
to Automate
Hi Henrik,

Yes, you are right, I had overlooked the fact that there is an additional intent "android.intent.action.SUBSCRIPTION_PHONE_STATE" in Android 6.0.
I hope that the additional complexity will remain limited to registering to this new intent.
There is also a new API in Android 5.1 "SubscriptionManager" to retrieve informations for the different SIM cards (including a listener method for changes).
Lastly, when I do "dumpsys activity broadcasts" on a rooted Android 5.0, I see in the output that the "subscription" extra field sometimes contains "1", and sometimes a 19-digit number, so I hope that the numbering scheme is consistent in Android 6.0.
Anyway, thanks already for your time reverse engineering this stuff !

Best regards,

metatech

Henrik "The Developer" Lindqvist

unread,
Jan 1, 2017, 6:49:53 PM1/1/17
to Automate
The SubscriptionManager is already used to get the list of available subscriptions.

Please join the Alpha and help me test the next version prior to public release:
https://plus.google.com/110165001747691845730/posts/ZgetBzG9Kdt

metat...@gmail.com

unread,
Jan 2, 2017, 3:56:55 PM1/2/17
to Automate
Hi,

I created a flow with a broadcast receiver for intent "android.intent.action.SUBSCRIPTION_PHONE_STATE".   When the phone is ringing, the intent is not received in Automate. 

In the class "TelephonyRegistry.java", the method "
broadcastCallStateChanged" is called from 2 locations :
- method "
notifyCallStateForSubscriber", with defined "subId" argument
- method "notifyCallState", with undefined "subId" argument.
If "subId" is defined, the intent action is replaced from "normal" PHONE_STATE to SUBSCRIPTION_PHONE_STATE (not duplicated).
Therefore, if the broadcast receiver does receive a "normal" PHONE_STATE, it means that the "subId" information was not available.

The class calling the
"notifyCallState*" method must be responsible for setting the "subId", but I could not find which one it is.
Do you have any idea ?

Of course, I joined the Alpha and will test the dual SIM setup as soon as there is a version ready.

Thanks,
Regards,

metatech

metat...@gmail.com

unread,
Jan 2, 2017, 4:20:34 PM1/2/17
to Automate
Hi,

After some more thinking, probably it is not reliable to expect the "subId" to be available in the "phone_state" intent received by the broadcast receiver.
But what the receiver can do is perform secondary calls to fulfill the missing field, by calling the "TelephonyManager.createForSubscriptionId(1 or 2)" method, and then call "getCallState()" method on each of the 2 TelephonyManager instances, to check which of the 2 is in the "RINGING" state (at most one in "dual sim dual passive" mode I assume).
Do you think it would work ?

Regards,

metatech

Henrik "The Developer" Lindqvist

unread,
Jan 2, 2017, 6:14:58 PM1/2/17
to Automate
For the Call incoming/outgoing block, only listening for the "android.intent.action.SUBSCRIPTION_PHONE_STATE" broadcast on Android 6+ is the fix i'am testing, it seems to work on my single SIM device at least.
The Call state block will require an subscription id, and the call in/out blocks will get an output variable for it to use.

metat...@gmail.com

unread,
Jan 4, 2017, 4:53:30 PM1/4/17
to Automate
Good news that it does work !

Actually, the Android system, starting from version 5.x, must be calling successively the 2 methods "notifyCallState" and "notifyCallStateForSubscriber" :
- the first without the "subscription" extra, for backward compatibility with Android 4.x and below.
- the second with the "subscription" extra, to transmit this field to the requesting application.

In Android 5, the same intent action
"PHONE_STATE" was used for both, which was the reason why the workaround described by V. Skoumal was needed (ie in order to ignore one of them).
In Android 6.x, 7.x and higher, they are now using a more specific intent action "
SUBSCRIPTION_PHONE_STATE" , so that only applications requesting explicitly this additional information would receive this intent.

Regards,

metatech

metat...@gmail.com

unread,
Jan 25, 2017, 2:55:07 PM1/25/17
to Automate
Hi,

I downloaded the beta 1.6.0a1 and tested the dual SIM for the "Call incoming" block.
It works perfectly !  I am now able to set a different ringtone on-the-fly when the SIM 1 or SIM 2 is calling.
Sony does not support it anymore since Android 6, pretending it is a "limitation on platform level from our platform supplier and this feature will not be available on our products on Android 6."  The fact that it works very well in Automate is a nice counterproof.

Thanks a lot !

metatech

Henrik "The Developer" Lindqvist

unread,
Jan 25, 2017, 3:51:06 PM1/25/17
to Automate
Great, thanks for reporting back.

Jay G.

unread,
Mar 7, 2017, 12:37:53 AM3/7/17
to Automate
Hi, How did you manage to select subscirbtion on dual sim? On my samsung 4.4.4 only 1 simcard is showing, Hope you can help Thanks

Henrik "The Developer" Lindqvist

unread,
Mar 7, 2017, 3:09:42 PM3/7/17
to Automate
Dual SIM support requires Android 5.

Jay G.

unread,
Mar 14, 2017, 12:08:59 PM3/14/17
to Automate
Any chance for lower version? As the call state is not functioning anymore on lower devices as it was working before.
Thanks

Jay G.

unread,
Mar 14, 2017, 12:11:46 PM3/14/17
to Automate
or is there any chance that I can download the older version?
thanks

Henrik "The Developer" Lindqvist

unread,
Mar 14, 2017, 4:14:32 PM3/14/17
to Automate
Subscription id is, or should be ignored prior to Android 5.

Please help me with a simple test.
If your flow is using the Call incoming/outgoing blocks,  add an Log append block logging the Subscription id of the call. What does it say?

Jay G.

unread,
Mar 16, 2017, 1:15:31 PM3/16/17
to Automate
Hello Henrik,

Can you show me how to do it? and what/where will I find the logging file?
Thanks

metat...@gmail.com

unread,
Jan 5, 2018, 3:12:25 PM1/5/18
to Automate
Hi,

For the record, I updated my phone to Android 7.0, and the "Call incoming" block still works perfectly...
I am glad Automate still serves as a good workaround for this feature dropped by Sony...

Regards,

metatech
Reply all
Reply to author
Forward
0 new messages