SecurityException: not allowed to perform OP_READ_PHONE_STATE

Solution 1:

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.