Enforce READ_PHONE_STATE for APIs involving call state
For API version 31+, ensure that READ_PHONE_STATE is checked on
APIs that retrieve/notify the call state of the device.
Bug: 157233955
Test: atest CtsTelecomTestCases2 CtsTelephony2TestCases
Change-Id: I9f8674a3075d3e0f75ee4f41eefce328c0fa6b91
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 1677c8c..4886789 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -25,6 +25,8 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -1004,6 +1006,17 @@
PRESENTATION_PAYPHONE})
public @interface Presentation {}
+
+ /**
+ * Enable READ_PHONE_STATE protection on APIs querying and notifying call state, such as
+ * {@code TelecomManager#getCallState}, {@link TelephonyManager#getCallStateForSubscription()},
+ * and {@link android.telephony.TelephonyCallback.CallStateListener}.
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
+ // this magic number is a bug ID
+ public static final long ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION = 157233955L;
+
private static final String TAG = "TelecomManager";
@@ -1758,21 +1771,23 @@
* {@link TelephonyManager#CALL_STATE_OFFHOOK}
* {@link TelephonyManager#CALL_STATE_IDLE}
*
- * Note that this API does not require the
- * {@link android.Manifest.permission#READ_PHONE_STATE} permission. This is intentional, to
- * preserve the behavior of {@link TelephonyManager#getCallState()}, which also did not require
- * the permission.
- *
* Takes into consideration both managed and self-managed calls.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} for applications
+ * targeting API level 31+.
*
* @hide
*/
+ @RequiresPermission(anyOf = {READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PHONE_STATE}, conditional = true)
@SystemApi
public @CallState int getCallState() {
ITelecomService service = getTelecomService();
if (service != null) {
try {
- return service.getCallState();
+ return service.getCallStateUsingPackage(mContext.getPackageName(),
+ mContext.getAttributionTag());
} catch (RemoteException e) {
Log.d(TAG, "RemoteException calling getCallState().", e);
}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 78283fa..18afde7 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -195,11 +195,18 @@
/**
* @see TelecomServiceImpl#getCallState
+ * Note: only kept around to not break app compat, however this will throw a SecurityException
+ * on API 31+.
*/
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
int getCallState();
/**
+ * @see TelecomServiceImpl#getCallState
+ */
+ int getCallStateUsingPackage(String callingPackage, String callingFeatureId);
+
+ /**
* @see TelecomServiceImpl#endCall
*/
boolean endCall(String callingPackage);