Throw IAE for non-existent sub association query
For user handle association query, if the queried sub id has no records on the device, throw IAE.
Bug: 294125411
Test: Manually sending/receiving SMS/MMS,
atest com.android.providers.telephony.SmsProviderTest,
atest com.android.providers.telephony.MmsProviderTest,
atest com.android.providers.telephony.ProviderUtilTest,
atest CtsTelephonyProviderTestCases,
atest CtsTelephonyTestCases
Change-Id: Ie49b8a564f1db2f812f9f0b1ecadee1e8b18c68e
diff --git a/flags/messaging.aconfig b/flags/messaging.aconfig
index 84e491e..777edb7 100644
--- a/flags/messaging.aconfig
+++ b/flags/messaging.aconfig
@@ -1 +1,8 @@
-package: "com.android.internal.telephony.flags"
\ No newline at end of file
+package: "com.android.internal.telephony.flags"
+
+flag {
+ name: "reject_bad_sub_id_interaction"
+ namespace: "telephony"
+ description: "Previously, the DB allows insertion of a random sub Id, but doesn't allow query it. This change rejects such interaction."
+ bug: "294125411"
+}
\ No newline at end of file
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index 83048d8..f3329eb 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -3646,7 +3646,7 @@
* else {@code false} if subscription is not associated with user.
*
* @throws SecurityException if the caller doesn't have permissions required.
- *
+ * @throws IllegalArgumentException if the subscription has no records on device.
*/
@Override
public boolean isSubscriptionAssociatedWithUser(int subscriptionId,
@@ -3656,18 +3656,11 @@
long token = Binder.clearCallingIdentity();
try {
- // Return true if there are no subscriptions on the device.
- List<SubscriptionInfo> subInfoList = getAllSubInfoList(
- mContext.getOpPackageName(), mContext.getAttributionTag());
- if (subInfoList == null || subInfoList.isEmpty()) {
- return true;
- }
-
- List<Integer> subIdList = subInfoList.stream().map(SubscriptionInfo::getSubscriptionId)
- .collect(Collectors.toList());
- if (!subIdList.contains(subscriptionId)) {
- // Return true as this subscription is not available on the device.
- return true;
+ // Throw IAE if no record of the sub's association state.
+ if (mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subscriptionId) == null) {
+ throw new IllegalArgumentException(
+ "[isSubscriptionAssociatedWithUser]: Subscription doesn't exist: "
+ + subscriptionId);
}
// Get list of subscriptions associated with this user.
@@ -3709,23 +3702,21 @@
long token = Binder.clearCallingIdentity();
try {
- List<SubscriptionInfo> subInfoList = getAllSubInfoList(
- mContext.getOpPackageName(), mContext.getAttributionTag());
- if (subInfoList == null || subInfoList.isEmpty()) {
+ List<SubscriptionInfoInternal> subInfoList = mSubscriptionDatabaseManager
+ .getAllSubscriptions();
+ if (subInfoList.isEmpty()) {
return new ArrayList<>();
}
List<SubscriptionInfo> subscriptionsAssociatedWithUser = new ArrayList<>();
List<SubscriptionInfo> subscriptionsWithNoAssociation = new ArrayList<>();
- for (SubscriptionInfo subInfo : subInfoList) {
- int subId = subInfo.getSubscriptionId();
- UserHandle subIdUserHandle = getSubscriptionUserHandle(subId);
- if (userHandle.equals(subIdUserHandle)) {
+ for (SubscriptionInfoInternal subInfo : subInfoList) {
+ if (subInfo.getUserId() == userHandle.getIdentifier()) {
// Store subscriptions whose user handle matches with required user handle.
- subscriptionsAssociatedWithUser.add(subInfo);
- } else if (subIdUserHandle == null) {
+ subscriptionsAssociatedWithUser.add(subInfo.toSubscriptionInfo());
+ } else if (subInfo.getUserId() == UserHandle.USER_NULL) {
// Store subscriptions whose user handle is set to null.
- subscriptionsWithNoAssociation.add(subInfo);
+ subscriptionsWithNoAssociation.add(subInfo.toSubscriptionInfo());
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
index a053c56..ad66b55 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
@@ -48,6 +48,7 @@
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.pm.permission.LegacyPermissionManagerService;
@@ -57,7 +58,6 @@
import java.lang.reflect.Field;
import java.util.Map;
-
@SmallTest
public class TelephonyPermissionsTest {
@@ -71,6 +71,7 @@
// Mocked classes
private Context mMockContext;
+ private FeatureFlags mMockFeatureFlag;
private AppOpsManager mMockAppOps;
private SubscriptionManager mMockSubscriptionManager;
private ITelephony mMockTelephony;
@@ -84,10 +85,12 @@
private MockContentResolver mMockContentResolver;
private FakeSettingsConfigProvider mFakeSettingsConfigProvider;
+ private FeatureFlags mRealFeatureFlagToBeRestored;
@Before
public void setUp() throws Exception {
mMockContext = mock(Context.class);
+ mMockFeatureFlag = mock(FeatureFlags.class);
mMockAppOps = mock(AppOpsManager.class);
mMockSubscriptionManager = mock(SubscriptionManager.class);
mMockTelephony = mock(ITelephony.class);
@@ -129,13 +132,17 @@
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
PID, UID)).thenReturn(PackageManager.PERMISSION_DENIED);
+
+ replaceFeatureFlag(mMockFeatureFlag);
setTelephonyMockAsService();
}
@After
- public void tearDown() {
+ public void tearDown() throws Exception {
+ replaceFeatureFlag(mRealFeatureFlagToBeRestored);
mMockContentResolver = null;
mFakeSettingsConfigProvider = null;
+ mRealFeatureFlagToBeRestored = null;
}
@Test
@@ -540,6 +547,30 @@
UserHandle.SYSTEM, "911"));
}
+ @Test
+ public void testCheckSubscriptionAssociatedWithUser_badSub_flag_enabled() {
+ doReturn(true).when(mMockFeatureFlag).rejectBadSubIdInteraction();
+
+ doThrow(new IllegalArgumentException("has no records on device"))
+ .when(mMockSubscriptionManager).isSubscriptionAssociatedWithUser(SUB_ID,
+ UserHandle.SYSTEM);
+ assertFalse(TelephonyPermissions.checkSubscriptionAssociatedWithUser(mMockContext, SUB_ID,
+ UserHandle.SYSTEM));
+ }
+
+ @Test
+ public void testCheckSubscriptionAssociatedWithUser_badSub_flag_disabled() {
+ doReturn(false).when(mMockFeatureFlag).rejectBadSubIdInteraction();
+
+ doThrow(new IllegalArgumentException("No records found for sub"))
+ .when(mMockSubscriptionManager).isSubscriptionAssociatedWithUser(SUB_ID,
+ UserHandle.SYSTEM);
+ assertTrue(TelephonyPermissions.checkSubscriptionAssociatedWithUser(mMockContext, SUB_ID,
+ UserHandle.SYSTEM));
+ assertTrue(TelephonyPermissions.checkSubscriptionAssociatedWithUser(mMockContext,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID, UserHandle.SYSTEM));
+ }
+
// Put mMockTelephony into service cache so that TELEPHONY_SUPPLIER will get it.
private void setTelephonyMockAsService() throws Exception {
when(mMockTelephonyBinder.queryLocalInterface(anyString())).thenReturn(mMockTelephony);
@@ -630,4 +661,12 @@
field.set(providerHolder, iContentProvider);
}
+ private synchronized void replaceFeatureFlag(final FeatureFlags newValue)
+ throws Exception {
+ Field field = TelephonyPermissions.class.getDeclaredField("sFeatureFlag");
+ field.setAccessible(true);
+
+ mRealFeatureFlagToBeRestored = (FeatureFlags) field.get(null);
+ field.set(null, newValue);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
index ab531a6..05489dc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -1113,8 +1113,6 @@
@Test
public void testIsSubscriptionAssociatedWithUser() {
- insertSubscription(FAKE_SUBSCRIPTION_INFO1);
-
// Should fail without MANAGE_SUBSCRIPTION_USER_ASSOCIATION
assertThrows(SecurityException.class, () -> mSubscriptionManagerServiceUT
.isSubscriptionAssociatedWithUser(1, FAKE_USER_HANDLE));
@@ -1125,6 +1123,12 @@
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ // Should fail for non-existent sub Id
+ assertThrows(IllegalArgumentException.class, () -> mSubscriptionManagerServiceUT
+ .isSubscriptionAssociatedWithUser(1, FAKE_USER_HANDLE));
+
+ insertSubscription(FAKE_SUBSCRIPTION_INFO1);
+
mSubscriptionManagerServiceUT.setSubscriptionUserHandle(FAKE_USER_HANDLE, 1);
processAllMessages();
verify(mMockedSubscriptionManagerServiceCallback).onSubscriptionChanged(eq(1));