Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SecurityException: not allowed to perform OP_READ_PHONE_STATE

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

like image 268
kencorbin Avatar asked Sep 26 '16 03:09

kencorbin


1 Answers

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.

like image 142
TheWanderer Avatar answered Sep 19 '22 18:09

TheWanderer