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() {