Update sms test app and integrate PERFORM_IMS_SINGLE_REGISTRATION into permission checks

1) Make a system app
2) Add a button that checks for the PERFORM_IMS_SINGLE_REGISTRATION permission
3) Move to checking PERFORM_IMS_SINGLE_REGISTRATION API check instead of further overloading phone state permissions.
4) Add permissions to test app

Bug: 168923956
Bug: 173652571
Bug: 149426399
Test: atest CtsTelephonyTestCases; use RcsTestApp to check perms
Merged-In: I91c5e49450545b76c6ccbaa900388abcc756aeb8
Merged-In: I9ebc9416f177b030ae531300b3024f31ddb07ca2
Change-Id: I9ebc9416f177b030ae531300b3024f31ddb07ca2
diff --git a/src/com/android/phone/ImsRcsController.java b/src/com/android/phone/ImsRcsController.java
index 701a759..5e616b7 100644
--- a/src/com/android/phone/ImsRcsController.java
+++ b/src/com/android/phone/ImsRcsController.java
@@ -16,6 +16,7 @@
 
 package com.android.phone;
 
+import android.Manifest;
 import android.app.ActivityManager;
 import android.content.pm.PackageManager;
 import android.net.Uri;
@@ -402,7 +403,10 @@
 
     @Override
     public boolean isSipDelegateSupported(int subId) {
-        enforceReadPrivilegedPermission("isSipDelegateSupported");
+        TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
+                "isSipDelegateSupported",
+                Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
+                Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         if (!isImsSingleRegistrationSupportedOnDevice()) {
             return false;
         }
@@ -430,7 +434,7 @@
     public void createSipDelegate(int subId, DelegateRequest request, String packageName,
             ISipDelegateConnectionStateCallback delegateState,
             ISipDelegateMessageCallback delegateMessage) {
-        enforceModifyPermission();
+        enforceImsSingleRegistrationPermission("createSipDelegate");
         if (!isImsSingleRegistrationSupportedOnDevice()) {
             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
                     "SipDelegate creation is only supported for devices supporting IMS single "
@@ -468,7 +472,7 @@
 
     @Override
     public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
-        enforceModifyPermission();
+        enforceImsSingleRegistrationPermission("destroySipDelegate");
 
         final long identity = Binder.clearCallingIdentity();
         try {
@@ -486,7 +490,7 @@
     @Override
     public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
             String sipReason) {
-        enforceModifyPermission();
+        enforceImsSingleRegistrationPermission("triggerNetworkRegistration");
 
         final long identity = Binder.clearCallingIdentity();
         try {
@@ -548,6 +552,15 @@
     }
 
     /**
+     * @throws SecurityException if the caller does not have the required
+     *     PERFORM_IMS_SINGLE_REGISTRATION permission.
+     */
+    private void enforceImsSingleRegistrationPermission(String message) {
+        mApp.enforceCallingOrSelfPermission(
+                Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION, message);
+    }
+
+    /**
      * Make sure the caller has the MODIFY_PHONE_STATE permission.
      *
      * @throws SecurityException if the caller does not have the required permission
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index eac13bb..79bb301 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -21,6 +21,7 @@
 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_IMS;
 import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
 
+import android.Manifest;
 import android.Manifest.permission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -9416,9 +9417,11 @@
     @Override
     public void bootstrapAuthenticationRequest(int subId, int appType, Uri nafUrl,
             UaSecurityProtocolIdentifier securityProtocol,
-            boolean forceBootStrapping, IBootstrapAuthenticationCallback callback)
-            throws RemoteException {
-        enforceModifyPermission();
+            boolean forceBootStrapping, IBootstrapAuthenticationCallback callback) {
+        TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
+                Binder.getCallingUid(), "bootstrapAuthenticationRequest",
+                Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
+                Manifest.permission.MODIFY_PHONE_STATE);
         if (DBG) {
             log("bootstrapAuthenticationRequest, subId:" + subId + ", appType:"
                     + appType + ", NAF:" + nafUrl + ", sp:" + securityProtocol
@@ -9694,7 +9697,10 @@
      */
     @Override
     public boolean isRcsVolteSingleRegistrationCapable(int subId) {
-        enforceReadPrivilegedPermission("isRcsVolteSingleRegistrationCapable");
+        TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
+                Binder.getCallingUid(), "isRcsVolteSingleRegistrationCapable",
+                Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
+                permission.READ_PRIVILEGED_PHONE_STATE);
 
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
@@ -9718,7 +9724,10 @@
     @Override
     public void registerRcsProvisioningChangedCallback(int subId,
             IRcsConfigCallback callback) {
-        enforceReadPrivilegedPermission("registerRcsProvisioningChangedCallback");
+        TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
+                Binder.getCallingUid(), "registerRcsProvisioningChangedCallback",
+                Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
+                permission.READ_PRIVILEGED_PHONE_STATE);
 
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
@@ -9746,7 +9755,10 @@
     @Override
     public void unregisterRcsProvisioningChangedCallback(int subId,
             IRcsConfigCallback callback) {
-        enforceReadPrivilegedPermission("unregisterRcsProvisioningChangedCallback");
+        TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
+                Binder.getCallingUid(), "unregisterRcsProvisioningChangedCallback",
+                Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
+                permission.READ_PRIVILEGED_PHONE_STATE);
 
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
@@ -9769,8 +9781,9 @@
      * trigger RCS reconfiguration.
      */
     public void triggerRcsReconfiguration(int subId) {
-        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
-                mApp, subId, "triggerRcsReconfiguration");
+        TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
+                "triggerRcsReconfiguration",
+                Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION);
 
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
@@ -9792,8 +9805,9 @@
      * Provide the client configuration parameters of the RCS application.
      */
     public void setRcsClientConfiguration(int subId, RcsClientConfiguration rcc) {
-        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
-                mApp, subId, "setRcsClientConfiguration");
+        TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
+                "setRcsClientConfiguration",
+                Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION);
 
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
diff --git a/src/com/android/phone/RcsProvisioningMonitor.java b/src/com/android/phone/RcsProvisioningMonitor.java
index 13dddec..2191e28 100644
--- a/src/com/android/phone/RcsProvisioningMonitor.java
+++ b/src/com/android/phone/RcsProvisioningMonitor.java
@@ -16,6 +16,7 @@
 
 package com.android.phone;
 
+import android.Manifest;
 import android.app.role.OnRoleHoldersChangedListener;
 import android.app.role.RoleManager;
 import android.content.BroadcastReceiver;
@@ -784,8 +785,7 @@
         // Only send permission to the default sms app if it has the correct permissions
         // except test mode enabled
         if (!mTestModeEnabled) {
-            //mPhone.sendBroadcast(intent, Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION);
-            mPhone.sendBroadcast(intent);
+            mPhone.sendBroadcast(intent, Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION);
         } else {
             mPhone.sendBroadcast(intent);
         }
diff --git a/testapps/SmsManagerTestApp/Android.bp b/testapps/SmsManagerTestApp/Android.bp
index e451b2d..4d4afcb 100644
--- a/testapps/SmsManagerTestApp/Android.bp
+++ b/testapps/SmsManagerTestApp/Android.bp
@@ -10,5 +10,7 @@
 android_app {
     name: "SmsManagerTestApp",
     srcs: ["src/**/*.java"],
-    sdk_version: "current",
+    platform_apis: true,
+    certificate: "platform",
+    privileged: true,
 }
diff --git a/testapps/SmsManagerTestApp/AndroidManifest.xml b/testapps/SmsManagerTestApp/AndroidManifest.xml
index 7dc717f..1be2b2d 100644
--- a/testapps/SmsManagerTestApp/AndroidManifest.xml
+++ b/testapps/SmsManagerTestApp/AndroidManifest.xml
@@ -21,6 +21,7 @@
          android:targetSdkVersion="29"/>
     <uses-permission android:name="android.permission.SEND_SMS"/>
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.PERFORM_IMS_SINGLE_REGISTRATION"/>
     <application android:label="SmsManagerTestApp">
         <activity android:name=".SmsManagerTestApp"
              android:label="SmsManagerTestApp"
@@ -54,6 +55,7 @@
 
         <!-- Fake BroadcastReceiver that listens for incoming SMS messages -->
         <receiver android:name=".SmsReceiver"
+                  android:exported="true"
                   android:permission="android.permission.BROADCAST_SMS">
             <intent-filter>
                 <action android:name="android.provider.Telephony.SMS_DELIVER" />
@@ -62,7 +64,8 @@
 
         <!-- Fake BroadcastReceiver that listens for incoming MMS messages -->
         <receiver android:name=".MmsReceiver"
-                  android:permission="android.permission.BROADCAST_WAP_PUSH">
+                  android:permission="android.permission.BROADCAST_WAP_PUSH"
+                  android:exported="true">
             <intent-filter>
                 <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
                 <data android:mimeType="application/vnd.wap.mms-message" />
@@ -70,7 +73,7 @@
         </receiver>
 
         <!-- Fake Activity that allows the user to send new SMS/MMS messages -->
-        <activity android:name=".ComposeSmsActivity" >
+        <activity android:name=".ComposeSmsActivity" android:exported="true" >
             <intent-filter>
                 <action android:name="android.intent.action.SEND" />
                 <action android:name="android.intent.action.SENDTO" />
diff --git a/testapps/SmsManagerTestApp/res/layout/activity_main.xml b/testapps/SmsManagerTestApp/res/layout/activity_main.xml
index 185e0e2..d889936 100644
--- a/testapps/SmsManagerTestApp/res/layout/activity_main.xml
+++ b/testapps/SmsManagerTestApp/res/layout/activity_main.xml
@@ -75,5 +75,11 @@
             android:layout_height="wrap_content"
             android:paddingRight="4dp"
             android:text="@string/disable_persistent_service"/>
+        <Button
+            android:id="@+id/check_single_reg_permission"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingRight="4dp"
+            android:text="@string/check_single_reg_permission"/>
     </LinearLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/testapps/SmsManagerTestApp/res/values/donottranslate_strings.xml b/testapps/SmsManagerTestApp/res/values/donottranslate_strings.xml
index c8b9f91..7383a4a 100644
--- a/testapps/SmsManagerTestApp/res/values/donottranslate_strings.xml
+++ b/testapps/SmsManagerTestApp/res/values/donottranslate_strings.xml
@@ -21,4 +21,5 @@
     <string name="get_sub_for_result_button">Ask user for sub id.</string>
     <string name="enable_persistent_service">Enable Persistent Service</string>
     <string name="disable_persistent_service">Disable Persistent Service</string>
-</resources>
\ No newline at end of file
+    <string name="check_single_reg_permission">Check RCS Single Reg Perm</string>
+</resources>
diff --git a/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/SmsManagerTestApp.java b/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/SmsManagerTestApp.java
index 785fe3f..cc3769e 100644
--- a/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/SmsManagerTestApp.java
+++ b/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/SmsManagerTestApp.java
@@ -44,6 +44,10 @@
     private static final ComponentName SETTINGS_SUB_PICK_ACTIVITY = new ComponentName(
             "com.android.settings", "com.android.settings.sim.SimDialogActivity");
 
+    // Can't import PERFORM_IMS_SINGLE_REGISTRATION const directly beause it's a @SystemApi
+    private static final String PERFORM_IMS_SINGLE_REGISTRATION =
+            "android.permission.PERFORM_IMS_SINGLE_REGISTRATION";
+
     /*
      * Forwarded constants from SimDialogActivity.
      */
@@ -70,6 +74,8 @@
                 .setOnClickListener(this::setPersistentServiceComponentEnabled);
         findViewById(R.id.disable_persistent_service)
                 .setOnClickListener(this::setPersistentServiceComponentDisabled);
+        findViewById(R.id.check_single_reg_permission)
+                .setOnClickListener(this::checkSingleRegPermission);
         mPhoneNumber = (EditText) findViewById(R.id.phone_number_text);
     }
 
@@ -201,6 +207,17 @@
                 PackageManager.DONT_KILL_APP);
     }
 
+    private void checkSingleRegPermission(View view) {
+        if (checkSelfPermission(PERFORM_IMS_SINGLE_REGISTRATION)
+                == PackageManager.PERMISSION_GRANTED) {
+            Toast.makeText(this, "Single Reg permission granted",
+                    Toast.LENGTH_SHORT).show();
+        } else {
+            Toast.makeText(this, "Single Reg permission NOT granted",
+                    Toast.LENGTH_SHORT).show();
+        }
+
+    }
 
     private Intent getSendStatusIntent() {
         // Encode requestId in intent data
diff --git a/testapps/TestRcsApp/TestApp/AndroidManifest.xml b/testapps/TestRcsApp/TestApp/AndroidManifest.xml
index 6bd5f32..2eea909 100644
--- a/testapps/TestRcsApp/TestApp/AndroidManifest.xml
+++ b/testapps/TestRcsApp/TestApp/AndroidManifest.xml
@@ -28,6 +28,11 @@
 
     <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
     <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+    <!-- Granted by SMS role-->
+    <uses-permission android:name="android.permission.PERFORM_IMS_SINGLE_REGISTRATION" />
+    <!-- Required for UCE and granted by SMS role -->
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE" />
 
     <application
         android:allowBackup="true"
diff --git a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
index d72b348..f77dd55 100644
--- a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
+++ b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
@@ -282,7 +282,7 @@
                     mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE + i)));
         }
 
-        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture());
+        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture(), any());
         Intent capturedIntent = captorIntent.getAllValues().get(1);
         assertEquals(ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE,
                 capturedIntent.getAction());
@@ -296,7 +296,7 @@
         ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
         createMonitor(3);
 
-        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture());
+        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture(), any());
         Intent capturedIntent = captorIntent.getAllValues().get(1);
 
         assertEquals(ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE,
@@ -315,7 +315,7 @@
             assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(),
                     mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE + i)));
         }
-        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture());
+        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture(), any());
         Intent capturedIntent = captorIntent.getAllValues().get(1);
         assertEquals(ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE,
                 capturedIntent.getAction());
@@ -377,7 +377,7 @@
                 CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
         broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
         processAllMessages();
-        verify(mPhone, atLeastOnce()).sendBroadcast(captorIntent.capture());
+        verify(mPhone, atLeastOnce()).sendBroadcast(captorIntent.capture(), any());
         Intent capturedIntent = captorIntent.getValue();
         assertEquals(capturedIntent.getAction(),
                 ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE);
@@ -390,7 +390,7 @@
                 CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
         broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
         processAllMessages();
-        verify(mPhone, atLeastOnce()).sendBroadcast(captorIntent.capture());
+        verify(mPhone, atLeastOnce()).sendBroadcast(captorIntent.capture(), any());
         capturedIntent = captorIntent.getValue();
         assertEquals(capturedIntent.getAction(),
                 ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE);
@@ -404,7 +404,7 @@
                 eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(false);
         broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
         processAllMessages();
-        verify(mPhone, atLeastOnce()).sendBroadcast(captorIntent.capture());
+        verify(mPhone, atLeastOnce()).sendBroadcast(captorIntent.capture(), any());
         capturedIntent = captorIntent.getValue();
         assertEquals(capturedIntent.getAction(),
                 ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE);