User is reporting my app crashes with this error trace
java.lang.SecurityException: com.android.phone from uid 10134 not allowed to perform OP_READ_PHONE_STATE at android.os.Parcel.readException(Parcel.java:1620) at android.os.Parcel.readException(Parcel.java:1573) at com.android.internal.telephony.IPhoneSubInfo$Stub$Proxy.getVoiceMailNumberForSubscriber(IPhoneSubInfo.java:858) at android.telephony.TelephonyManager.getVoiceMailNumber(TelephonyManager.java:2383) at android.telephony.TelephonyManager.getVoiceMailNumber(TelephonyManager.java:2366)
So far only one user has reported this problem. Several thousand other users are running this version of the app with no apparent problems.
The exception is thrown when we call TelephonyManager.getVoiceMailNumber()
. This operation is documented as required the READ_PHONE_STATE
permission, which has absolutely, positively been granted.
I tracked down the OP_READ_PHONE_STATE
permission to the android.apps.AppOpsManager
class but can not figure out exactly what it is unhappy about.
Can anyone explain just what is happening and what needs to be done to fix things.
Thanks, -Ken
Looking for that method in AOSP eventually leads to the cheakReadPhoneState() method.
In Android 6, that method was here.
In both cases, it looks pretty similar. Here's the Android 6 code:
private boolean checkReadPhoneState(String callingPackage, String message) { try { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message); // SKIP checking run-time OP_READ_PHONE_STATE since self or using PRIVILEGED return true; } catch (SecurityException e) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, message); } return mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED; }
First it checks to see if READ_PRIVILEGED_PHONE_STATE
is granted. If it is, then the rest of the code is short-circuited and it returns true. Otherwise, it makes sure that READ_PHONE_STATE
is granted, throwing a SecurityException otherwise.
Finally, if READ_PHONE_STATE
is granted, it makes sure that OP_READ_PHONE_STATE
is also granted. I'm not entirely sure why it's doing that, but that's where the problem is coming from. Whichever devices this error is occurring on have changed something with the way runtime permissions work. When the READ_PHONE_STATE
permission is granted, the OP_READ_PHONE_STATE
op should also be granted, but the system is revoking that op for whatever reason.
(It's also possible that the user is using an app to manage app-ops and has revoked it manually.)
For fixing it, I don't really think you can. The best you can do is catch the error and ask that users run an ADB command to manually grant the op:
adb shell appops set com.your.packagename READ_PHONE_STATE allow
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With