Factor out telephony permission checks into a helper class.
The aim is to cut down on duplicate code (for a particularly high-risk
area) and make it easier to expand READ_PHONE_STATE access to
carrier-privileged apps in a follow-up CL.
No major functional changes are intended, although some logging will
change slightly (different tag / less verbose carrier privilege
logging without DBG flag).
Bug: 70041899
Test: bit FrameworksTelephonyTests:*, nothing visibly broken on boot
Merged-In: I3b2aa9b8d6177a25d532060009508ef31baea69c
Change-Id: I3b2aa9b8d6177a25d532060009508ef31baea69c
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index ce78665..8b5176e 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -56,6 +56,7 @@
import com.android.internal.telephony.PhoneConstantConversions;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyPermissions;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.am.BatteryStatsService;
@@ -384,20 +385,9 @@
+ " callback.asBinder=" + callback.asBinder());
}
- try {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
- "addOnSubscriptionsChangedListener");
- // SKIP checking for run-time permission since caller or self has PRIVILEGED permission
- } catch (SecurityException e) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.READ_PHONE_STATE,
- "addOnSubscriptionsChangedListener");
-
- if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
- callingPackage) != AppOpsManager.MODE_ALLOWED) {
- return;
- }
+ if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+ mContext, callingPackage, "addOnSubscriptionsChangedListener")) {
+ return;
}
@@ -493,21 +483,11 @@
}
if (events != PhoneStateListener.LISTEN_NONE) {
- /* Checks permission and throws Security exception */
- checkListenerPermission(events);
-
- if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
- try {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
- // SKIP checking for run-time permission since caller or self has PRIVILEGED
- // permission
- } catch (SecurityException e) {
- if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
- callingPackage) != AppOpsManager.MODE_ALLOWED) {
- return;
- }
- }
+ // Checks permission and throws SecurityException for disallowed operations. For pre-M
+ // apps whose runtime permission has been revoked, we return immediately to skip sending
+ // events to the app without crashing it.
+ if (!checkListenerPermission(events, callingPackage, "listen")) {
+ return;
}
int phoneId = SubscriptionManager.getPhoneId(subId);
@@ -526,7 +506,8 @@
r.callerPid = Binder.getCallingPid();
boolean isPhoneStateEvent = (events & (CHECK_PHONE_STATE_PERMISSION_MASK
| ENFORCE_PHONE_STATE_PERMISSION_MASK)) != 0;
- r.canReadPhoneState = isPhoneStateEvent && canReadPhoneState(callingPackage);
+ r.canReadPhoneState =
+ isPhoneStateEvent && canReadPhoneState(callingPackage, "listen");
// Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
// force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
@@ -686,21 +667,13 @@
}
}
- private boolean canReadPhoneState(String callingPackage) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) ==
- PackageManager.PERMISSION_GRANTED) {
- // SKIP checking for run-time permission since caller or self has PRIVILEGED permission
- return true;
- }
- boolean canReadPhoneState = mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED;
- if (canReadPhoneState &&
- mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
- callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ private boolean canReadPhoneState(String callingPackage, String message) {
+ try {
+ return TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+ mContext, callingPackage, message);
+ } catch (SecurityException e) {
return false;
}
- return canReadPhoneState;
}
private String getCallIncomingNumber(Record record, int phoneId) {
@@ -1672,11 +1645,12 @@
}
private void enforceNotifyPermissionOrCarrierPrivilege(String method) {
- if (checkNotifyPermission()) {
+ if (checkNotifyPermission()) {
return;
}
- enforceCarrierPrivilege();
+ TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
+ SubscriptionManager.getDefaultSubscriptionId(), method);
}
private boolean checkNotifyPermission(String method) {
@@ -1694,23 +1668,7 @@
== PackageManager.PERMISSION_GRANTED;
}
- private void enforceCarrierPrivilege() {
- TelephonyManager tm = TelephonyManager.getDefault();
- String[] pkgs = mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid());
- for (String pkg : pkgs) {
- if (tm.checkCarrierPrivilegesForPackage(pkg) ==
- TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
- return;
- }
- }
-
- String msg = "Carrier Privilege Permission Denial: from pid=" + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid();
- if (DBG) log(msg);
- throw new SecurityException(msg);
- }
-
- private void checkListenerPermission(int events) {
+ private boolean checkListenerPermission(int events, String callingPackage, String message) {
if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
@@ -1724,22 +1682,18 @@
}
if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
- try {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
- // SKIP checking for run-time permission since caller or self has PRIVILEGED
- // permission
- } catch (SecurityException e) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.READ_PHONE_STATE, null);
+ if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+ mContext, callingPackage, message)) {
+ return false;
}
}
if ((events & PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
-
}
+
+ return true;
}
private void handleRemoveListLocked() {