Loading src/java/com/android/internal/telephony/SubscriptionController.java +73 −14 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import com.android.internal.telephony.metrics.TelephonyMetrics; import com.android.internal.telephony.uicc.IccUtils; import com.android.internal.telephony.uicc.UiccCard; import com.android.internal.telephony.uicc.UiccController; import com.android.internal.util.ArrayUtils; import java.io.FileDescriptor; import java.io.PrintWriter; Loading Loading @@ -388,6 +389,8 @@ public class SubscriptionController extends ISub.Stub { SubscriptionManager.PROFILE_CLASS)); int subType = cursor.getInt(cursor.getColumnIndexOrThrow( SubscriptionManager.SUBSCRIPTION_TYPE)); String groupOwner = getOptionalStringFromCursor(cursor, SubscriptionManager.GROUP_OWNER, /*defaultVal*/ null); if (VDBG) { String iccIdToPrint = SubscriptionInfo.givePrintableIccid(iccId); Loading @@ -411,11 +414,18 @@ public class SubscriptionController extends ISub.Stub { SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso, isEmbedded, accessRules, cardId, publicCardId, isOpportunistic, groupUUID, false /* isGroupDisabled */, carrierId, profileClass, subType); groupUUID, false /* isGroupDisabled */, carrierId, profileClass, subType, groupOwner); info.setAssociatedPlmns(ehplmns, hplmns); return info; } private String getOptionalStringFromCursor(Cursor cursor, String column, String defaultVal) { // Return defaultVal if the column doesn't exist. int columnIndex = cursor.getColumnIndex(column); return (columnIndex == -1) ? defaultVal : cursor.getString(columnIndex); } /** * Query SubInfoRecord(s) from subinfo database * @param selection A filter declaring which rows to return Loading Loading @@ -2868,6 +2878,7 @@ public class SubscriptionController extends ISub.Stub { ContentValues value = new ContentValues(); value.put(SubscriptionManager.GROUP_UUID, groupUUID.toString()); value.put(SubscriptionManager.GROUP_OWNER, callingPackage); int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value, getSelectionForSubIdList(subIdList), null); Loading @@ -2885,14 +2896,31 @@ public class SubscriptionController extends ISub.Stub { } } // TODO: when having a group owner or packageName for subscription, use that to check. // Currently for this method to return false, all subscriptions in the group needs to have // carrier privilege rules loaded, which means active or available. private boolean canPackageManageGroup(ParcelUuid groupUuid, String callingPackage) { private String getOwnerPackageOfSubGroup(ParcelUuid groupUuid) { if (groupUuid == null) return null; List<SubscriptionInfo> infoList = getSubInfo(SubscriptionManager.GROUP_UUID + "=\'" + groupUuid.toString() + "\'", null); return ArrayUtils.isEmpty(infoList) ? null : infoList.get(0).getGroupOwner(); } /** * * @param groupUuid a UUID assigned to the subscription group. * @param callingPackage the package making the IPC. * @return if callingPackage has carrier privilege on sublist. * */ public boolean canPackageManageGroup(ParcelUuid groupUuid, String callingPackage) { if (groupUuid == null) { throw new IllegalArgumentException("Invalid groupUuid"); } if (TextUtils.isEmpty(callingPackage)) { throw new IllegalArgumentException("Empty callingPackage"); } List<SubscriptionInfo> infoList; // Getting all subscriptions in the group. Loading @@ -2904,13 +2932,36 @@ public class SubscriptionController extends ISub.Stub { Binder.restoreCallingIdentity(identity); } if (infoList == null || infoList.isEmpty()) { if (ArrayUtils.isEmpty(infoList)) { throw new IllegalArgumentException("No subscription in group " + groupUuid); } // If the calling package is the group owner, skip carrier permission check and return // true as it was done before. if (callingPackage.equals(infoList.get(0).getGroupOwner())) return true; // Check carrier privilege for all subscriptions in the group. int[] subIdArray = infoList.stream().mapToInt(info -> info.getSubscriptionId()).toArray(); return checkCarrierPrivilegeOnSubList(subIdArray, callingPackage); int[] subIdArray = infoList.stream().mapToInt(info -> info.getSubscriptionId()) .toArray(); return (checkCarrierPrivilegeOnSubList(subIdArray, callingPackage)); } private int updateGroupOwner(ParcelUuid groupUuid, String groupOwner) { // If the existing group owner is different from current caller, make caller the new // owner of all subscriptions in group. // This is for use-case of: // 1) Both package1 and package2 has permission (MODIFY_PHONE_STATE or carrier // privilege permission) of all related subscriptions. // 2) Package 1 created a group. // 3) Package 2 wants to add a subscription into it. // Step 3 should be granted as all operations are permission based. Which means as // long as the package passes the permission check, it can modify the subscription // and the group. And package 2 becomes the new group owner as it's the last to pass // permission checks on all members. ContentValues value = new ContentValues(1); value.put(SubscriptionManager.GROUP_OWNER, groupOwner); return mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value, SubscriptionManager.GROUP_UUID + "=\"" + groupUuid + "\"", null); } @Override Loading @@ -2924,6 +2975,8 @@ public class SubscriptionController extends ISub.Stub { throw new IllegalArgumentException("Invalid groupUuid"); } // Makes sure calling package matches caller UID. mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); // If it doesn't have modify phone state permission, or carrier privilege permission, // a SecurityException will be thrown. if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) Loading @@ -2949,11 +3002,11 @@ public class SubscriptionController extends ISub.Stub { if (DBG) logdl("addSubscriptionsIntoGroup update DB result: " + result); if (result > 0) { updateGroupOwner(groupUuid, callingPackage); refreshCachedActiveSubscriptionInfoList(); notifySubscriptionInfoChanged(); MultiSimSettingController.getInstance().notifySubscriptionGroupChanged(groupUuid); } } finally { Binder.restoreCallingIdentity(identity); } Loading Loading @@ -2981,12 +3034,15 @@ public class SubscriptionController extends ISub.Stub { if (subIdList == null || subIdList.length == 0) { return; } // Makes sure calling package matches caller UID. mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); // If it doesn't have modify phone state permission, or carrier privilege permission, // a SecurityException will be thrown. If it's due to invalid parameter or internal state, // it will return null. if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) != PERMISSION_GRANTED && !checkCarrierPrivilegeOnSubList( subIdList, callingPackage)) { != PERMISSION_GRANTED && !(checkCarrierPrivilegeOnSubList(subIdList, callingPackage) && canPackageManageGroup(groupUuid, callingPackage))) { throw new SecurityException("removeSubscriptionsFromGroup needs MODIFY_PHONE_STATE or" + " carrier privilege permission on all specified subscriptions"); } Loading @@ -3004,14 +3060,17 @@ public class SubscriptionController extends ISub.Stub { } ContentValues value = new ContentValues(); value.put(SubscriptionManager.GROUP_UUID, (String) null); value.put(SubscriptionManager.GROUP_OWNER, (String) null); int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value, getSelectionForSubIdList(subIdList), null); if (DBG) logdl("removeSubscriptionsFromGroup update DB result: " + result); if (result > 0) { updateGroupOwner(groupUuid, callingPackage); refreshCachedActiveSubscriptionInfoList(); notifySubscriptionInfoChanged(); } } finally { Binder.restoreCallingIdentity(identity); } Loading src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java +9 −5 Original line number Diff line number Diff line Loading @@ -858,19 +858,23 @@ public class SubscriptionInfoUpdater extends Handler { String groupUuidString = config.getString(CarrierConfigManager.KEY_SUBSCRIPTION_GROUP_UUID_STRING, ""); ParcelUuid groupId = null; ParcelUuid groupUuid = null; if (!TextUtils.isEmpty(groupUuidString)) { try { // Update via a UUID Structure to ensure consistent formatting ParcelUuid groupUuid = ParcelUuid.fromString(groupUuidString); groupUuid = ParcelUuid.fromString(groupUuidString); if (groupUuid.equals(REMOVE_GROUP_UUID) && currentSubInfo.getGroupUuid() != null) { cv.put(SubscriptionManager.GROUP_UUID, (String) null); if (DBG) logd("Group Removed for" + currentSubId); } else { // TODO: validate and update group owner information once feasible. } else if (SubscriptionController.getInstance().canPackageManageGroup(groupUuid, configPackageName)) { cv.put(SubscriptionManager.GROUP_UUID, groupUuid.toString()); cv.put(SubscriptionManager.GROUP_OWNER, configPackageName); if (DBG) logd("Group Added for" + currentSubId); } else { loge("configPackageName " + configPackageName + " doesn't own grouUuid " + groupUuid); } } catch (IllegalArgumentException e) { loge("Invalid Group UUID=" + groupUuidString); Loading @@ -880,7 +884,7 @@ public class SubscriptionInfoUpdater extends Handler { .getUriForSubscriptionId(currentSubId), cv, null, null) > 0) { sc.refreshCachedActiveSubscriptionInfoList(); sc.notifySubscriptionInfoChanged(); MultiSimSettingController.getInstance().notifySubscriptionGroupChanged(groupId); MultiSimSettingController.getInstance().onSubscriptionGroupChanged(groupUuid); } } Loading tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java +2 −1 Original line number Diff line number Diff line Loading @@ -107,7 +107,8 @@ public class FakeTelephonyProvider extends MockContentProvider { + SubscriptionManager.PROFILE_CLASS + " INTEGER DEFAULT " + SubscriptionManager.PROFILE_CLASS_DEFAULT + "," + SubscriptionManager.SUBSCRIPTION_TYPE + " INTEGER DEFAULT 0," + SubscriptionManager.WHITE_LISTED_APN_DATA + " INTEGER DEFAULT 0" + SubscriptionManager.WHITE_LISTED_APN_DATA + " INTEGER DEFAULT 0," + SubscriptionManager.GROUP_OWNER + " TEXT" + ");"; } Loading tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java +3 −3 Original line number Diff line number Diff line Loading @@ -72,19 +72,19 @@ public class MultiSimSettingControllerTest extends TelephonyTest { "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null, -1, false, mGroupUuid1.toString(), false, TelephonyManager.UNKNOWN_CARRIER_ID, SubscriptionManager.PROFILE_CLASS_DEFAULT, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null); private SubscriptionInfo mSubInfo3 = new SubscriptionInfo(3, "subInfo3 IccId", -1, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null, -1, false, mGroupUuid1.toString(), false, TelephonyManager.UNKNOWN_CARRIER_ID, SubscriptionManager.PROFILE_CLASS_DEFAULT, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null); private SubscriptionInfo mSubInfo4 = new SubscriptionInfo(4, "subInfo4 IccId", -1, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null, -1, false, mGroupUuid1.toString(), false, TelephonyManager.UNKNOWN_CARRIER_ID, SubscriptionManager.PROFILE_CLASS_DEFAULT, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null); @Before public void setUp() throws Exception { Loading tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java +50 −5 Original line number Diff line number Diff line Loading @@ -751,14 +751,51 @@ public class SubscriptionControllerTest extends TelephonyTest { doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(2); ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); subIdList, "packageName1"); assertNotEquals(null, groupId); mSubscriptionControllerUT.addSubscriptionsIntoGroup( new int[] {2}, groupId, mContext.getOpPackageName()); new int[] {2}, groupId, "packageName1"); List<SubscriptionInfo> infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( groupId, "packageName1"); assertEquals(2, infoList.size()); assertEquals(1, infoList.get(0).getSubscriptionId()); assertEquals(2, infoList.get(1).getSubscriptionId()); mSubscriptionControllerUT.removeSubscriptionsFromGroup( new int[] {2}, groupId, mContext.getOpPackageName()); new int[] {2}, groupId, "packageName1"); infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( groupId, "packageName1"); assertEquals(1, infoList.size()); assertEquals(1, infoList.get(0).getSubscriptionId()); // Make sub 1 inactive. mSubscriptionControllerUT.clearSubInfoRecord(0); try { mSubscriptionControllerUT.addSubscriptionsIntoGroup( new int[] {2}, groupId, "packageName2"); fail("addSubscriptionsIntoGroup should fail with wrong callingPackage name"); } catch (SecurityException e) { // Expected result. } // Adding and removing subscription should still work for packageName1, as it's the group // owner who created the group earlier.. mSubscriptionControllerUT.addSubscriptionsIntoGroup( new int[] {2}, groupId, "packageName1"); infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( groupId, "packageName1"); assertEquals(2, infoList.size()); assertEquals(1, infoList.get(0).getSubscriptionId()); assertEquals(2, infoList.get(1).getSubscriptionId()); mSubscriptionControllerUT.removeSubscriptionsFromGroup( new int[] {2}, groupId, "packageName1"); infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( groupId, "packageName1"); assertEquals(1, infoList.size()); assertEquals(1, infoList.get(0).getSubscriptionId()); } @Test Loading Loading @@ -826,7 +863,7 @@ public class SubscriptionControllerTest extends TelephonyTest { assertTrue(TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, 1, mContext.getOpPackageName(), "getSubscriptionsInGroup")); int[] subIdList = new int[] {1, 2}; int[] subIdList = new int[] {1}; ParcelUuid groupUuid = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, groupUuid); Loading @@ -835,8 +872,16 @@ public class SubscriptionControllerTest extends TelephonyTest { List<SubscriptionInfo> infoList = mSubscriptionControllerUT .getSubscriptionsInGroup(groupUuid, mContext.getOpPackageName()); assertNotEquals(null, infoList); assertEquals(2, infoList.size()); assertEquals(1, infoList.size()); assertEquals(1, infoList.get(0).getSubscriptionId()); subIdList = new int[] {2}; mSubscriptionControllerUT.addSubscriptionsIntoGroup( subIdList, groupUuid, mContext.getOpPackageName()); infoList = mSubscriptionControllerUT .getSubscriptionsInGroup(groupUuid, mContext.getOpPackageName()); assertEquals(2, infoList.size()); assertEquals(2, infoList.get(1).getSubscriptionId()); // Remove group of sub 1. Loading Loading
src/java/com/android/internal/telephony/SubscriptionController.java +73 −14 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import com.android.internal.telephony.metrics.TelephonyMetrics; import com.android.internal.telephony.uicc.IccUtils; import com.android.internal.telephony.uicc.UiccCard; import com.android.internal.telephony.uicc.UiccController; import com.android.internal.util.ArrayUtils; import java.io.FileDescriptor; import java.io.PrintWriter; Loading Loading @@ -388,6 +389,8 @@ public class SubscriptionController extends ISub.Stub { SubscriptionManager.PROFILE_CLASS)); int subType = cursor.getInt(cursor.getColumnIndexOrThrow( SubscriptionManager.SUBSCRIPTION_TYPE)); String groupOwner = getOptionalStringFromCursor(cursor, SubscriptionManager.GROUP_OWNER, /*defaultVal*/ null); if (VDBG) { String iccIdToPrint = SubscriptionInfo.givePrintableIccid(iccId); Loading @@ -411,11 +414,18 @@ public class SubscriptionController extends ISub.Stub { SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso, isEmbedded, accessRules, cardId, publicCardId, isOpportunistic, groupUUID, false /* isGroupDisabled */, carrierId, profileClass, subType); groupUUID, false /* isGroupDisabled */, carrierId, profileClass, subType, groupOwner); info.setAssociatedPlmns(ehplmns, hplmns); return info; } private String getOptionalStringFromCursor(Cursor cursor, String column, String defaultVal) { // Return defaultVal if the column doesn't exist. int columnIndex = cursor.getColumnIndex(column); return (columnIndex == -1) ? defaultVal : cursor.getString(columnIndex); } /** * Query SubInfoRecord(s) from subinfo database * @param selection A filter declaring which rows to return Loading Loading @@ -2868,6 +2878,7 @@ public class SubscriptionController extends ISub.Stub { ContentValues value = new ContentValues(); value.put(SubscriptionManager.GROUP_UUID, groupUUID.toString()); value.put(SubscriptionManager.GROUP_OWNER, callingPackage); int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value, getSelectionForSubIdList(subIdList), null); Loading @@ -2885,14 +2896,31 @@ public class SubscriptionController extends ISub.Stub { } } // TODO: when having a group owner or packageName for subscription, use that to check. // Currently for this method to return false, all subscriptions in the group needs to have // carrier privilege rules loaded, which means active or available. private boolean canPackageManageGroup(ParcelUuid groupUuid, String callingPackage) { private String getOwnerPackageOfSubGroup(ParcelUuid groupUuid) { if (groupUuid == null) return null; List<SubscriptionInfo> infoList = getSubInfo(SubscriptionManager.GROUP_UUID + "=\'" + groupUuid.toString() + "\'", null); return ArrayUtils.isEmpty(infoList) ? null : infoList.get(0).getGroupOwner(); } /** * * @param groupUuid a UUID assigned to the subscription group. * @param callingPackage the package making the IPC. * @return if callingPackage has carrier privilege on sublist. * */ public boolean canPackageManageGroup(ParcelUuid groupUuid, String callingPackage) { if (groupUuid == null) { throw new IllegalArgumentException("Invalid groupUuid"); } if (TextUtils.isEmpty(callingPackage)) { throw new IllegalArgumentException("Empty callingPackage"); } List<SubscriptionInfo> infoList; // Getting all subscriptions in the group. Loading @@ -2904,13 +2932,36 @@ public class SubscriptionController extends ISub.Stub { Binder.restoreCallingIdentity(identity); } if (infoList == null || infoList.isEmpty()) { if (ArrayUtils.isEmpty(infoList)) { throw new IllegalArgumentException("No subscription in group " + groupUuid); } // If the calling package is the group owner, skip carrier permission check and return // true as it was done before. if (callingPackage.equals(infoList.get(0).getGroupOwner())) return true; // Check carrier privilege for all subscriptions in the group. int[] subIdArray = infoList.stream().mapToInt(info -> info.getSubscriptionId()).toArray(); return checkCarrierPrivilegeOnSubList(subIdArray, callingPackage); int[] subIdArray = infoList.stream().mapToInt(info -> info.getSubscriptionId()) .toArray(); return (checkCarrierPrivilegeOnSubList(subIdArray, callingPackage)); } private int updateGroupOwner(ParcelUuid groupUuid, String groupOwner) { // If the existing group owner is different from current caller, make caller the new // owner of all subscriptions in group. // This is for use-case of: // 1) Both package1 and package2 has permission (MODIFY_PHONE_STATE or carrier // privilege permission) of all related subscriptions. // 2) Package 1 created a group. // 3) Package 2 wants to add a subscription into it. // Step 3 should be granted as all operations are permission based. Which means as // long as the package passes the permission check, it can modify the subscription // and the group. And package 2 becomes the new group owner as it's the last to pass // permission checks on all members. ContentValues value = new ContentValues(1); value.put(SubscriptionManager.GROUP_OWNER, groupOwner); return mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value, SubscriptionManager.GROUP_UUID + "=\"" + groupUuid + "\"", null); } @Override Loading @@ -2924,6 +2975,8 @@ public class SubscriptionController extends ISub.Stub { throw new IllegalArgumentException("Invalid groupUuid"); } // Makes sure calling package matches caller UID. mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); // If it doesn't have modify phone state permission, or carrier privilege permission, // a SecurityException will be thrown. if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) Loading @@ -2949,11 +3002,11 @@ public class SubscriptionController extends ISub.Stub { if (DBG) logdl("addSubscriptionsIntoGroup update DB result: " + result); if (result > 0) { updateGroupOwner(groupUuid, callingPackage); refreshCachedActiveSubscriptionInfoList(); notifySubscriptionInfoChanged(); MultiSimSettingController.getInstance().notifySubscriptionGroupChanged(groupUuid); } } finally { Binder.restoreCallingIdentity(identity); } Loading Loading @@ -2981,12 +3034,15 @@ public class SubscriptionController extends ISub.Stub { if (subIdList == null || subIdList.length == 0) { return; } // Makes sure calling package matches caller UID. mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); // If it doesn't have modify phone state permission, or carrier privilege permission, // a SecurityException will be thrown. If it's due to invalid parameter or internal state, // it will return null. if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) != PERMISSION_GRANTED && !checkCarrierPrivilegeOnSubList( subIdList, callingPackage)) { != PERMISSION_GRANTED && !(checkCarrierPrivilegeOnSubList(subIdList, callingPackage) && canPackageManageGroup(groupUuid, callingPackage))) { throw new SecurityException("removeSubscriptionsFromGroup needs MODIFY_PHONE_STATE or" + " carrier privilege permission on all specified subscriptions"); } Loading @@ -3004,14 +3060,17 @@ public class SubscriptionController extends ISub.Stub { } ContentValues value = new ContentValues(); value.put(SubscriptionManager.GROUP_UUID, (String) null); value.put(SubscriptionManager.GROUP_OWNER, (String) null); int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value, getSelectionForSubIdList(subIdList), null); if (DBG) logdl("removeSubscriptionsFromGroup update DB result: " + result); if (result > 0) { updateGroupOwner(groupUuid, callingPackage); refreshCachedActiveSubscriptionInfoList(); notifySubscriptionInfoChanged(); } } finally { Binder.restoreCallingIdentity(identity); } Loading
src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java +9 −5 Original line number Diff line number Diff line Loading @@ -858,19 +858,23 @@ public class SubscriptionInfoUpdater extends Handler { String groupUuidString = config.getString(CarrierConfigManager.KEY_SUBSCRIPTION_GROUP_UUID_STRING, ""); ParcelUuid groupId = null; ParcelUuid groupUuid = null; if (!TextUtils.isEmpty(groupUuidString)) { try { // Update via a UUID Structure to ensure consistent formatting ParcelUuid groupUuid = ParcelUuid.fromString(groupUuidString); groupUuid = ParcelUuid.fromString(groupUuidString); if (groupUuid.equals(REMOVE_GROUP_UUID) && currentSubInfo.getGroupUuid() != null) { cv.put(SubscriptionManager.GROUP_UUID, (String) null); if (DBG) logd("Group Removed for" + currentSubId); } else { // TODO: validate and update group owner information once feasible. } else if (SubscriptionController.getInstance().canPackageManageGroup(groupUuid, configPackageName)) { cv.put(SubscriptionManager.GROUP_UUID, groupUuid.toString()); cv.put(SubscriptionManager.GROUP_OWNER, configPackageName); if (DBG) logd("Group Added for" + currentSubId); } else { loge("configPackageName " + configPackageName + " doesn't own grouUuid " + groupUuid); } } catch (IllegalArgumentException e) { loge("Invalid Group UUID=" + groupUuidString); Loading @@ -880,7 +884,7 @@ public class SubscriptionInfoUpdater extends Handler { .getUriForSubscriptionId(currentSubId), cv, null, null) > 0) { sc.refreshCachedActiveSubscriptionInfoList(); sc.notifySubscriptionInfoChanged(); MultiSimSettingController.getInstance().notifySubscriptionGroupChanged(groupId); MultiSimSettingController.getInstance().onSubscriptionGroupChanged(groupUuid); } } Loading
tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java +2 −1 Original line number Diff line number Diff line Loading @@ -107,7 +107,8 @@ public class FakeTelephonyProvider extends MockContentProvider { + SubscriptionManager.PROFILE_CLASS + " INTEGER DEFAULT " + SubscriptionManager.PROFILE_CLASS_DEFAULT + "," + SubscriptionManager.SUBSCRIPTION_TYPE + " INTEGER DEFAULT 0," + SubscriptionManager.WHITE_LISTED_APN_DATA + " INTEGER DEFAULT 0" + SubscriptionManager.WHITE_LISTED_APN_DATA + " INTEGER DEFAULT 0," + SubscriptionManager.GROUP_OWNER + " TEXT" + ");"; } Loading
tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java +3 −3 Original line number Diff line number Diff line Loading @@ -72,19 +72,19 @@ public class MultiSimSettingControllerTest extends TelephonyTest { "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null, -1, false, mGroupUuid1.toString(), false, TelephonyManager.UNKNOWN_CARRIER_ID, SubscriptionManager.PROFILE_CLASS_DEFAULT, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null); private SubscriptionInfo mSubInfo3 = new SubscriptionInfo(3, "subInfo3 IccId", -1, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null, -1, false, mGroupUuid1.toString(), false, TelephonyManager.UNKNOWN_CARRIER_ID, SubscriptionManager.PROFILE_CLASS_DEFAULT, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null); private SubscriptionInfo mSubInfo4 = new SubscriptionInfo(4, "subInfo4 IccId", -1, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null, -1, false, mGroupUuid1.toString(), false, TelephonyManager.UNKNOWN_CARRIER_ID, SubscriptionManager.PROFILE_CLASS_DEFAULT, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null); @Before public void setUp() throws Exception { Loading
tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java +50 −5 Original line number Diff line number Diff line Loading @@ -751,14 +751,51 @@ public class SubscriptionControllerTest extends TelephonyTest { doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(2); ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); subIdList, "packageName1"); assertNotEquals(null, groupId); mSubscriptionControllerUT.addSubscriptionsIntoGroup( new int[] {2}, groupId, mContext.getOpPackageName()); new int[] {2}, groupId, "packageName1"); List<SubscriptionInfo> infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( groupId, "packageName1"); assertEquals(2, infoList.size()); assertEquals(1, infoList.get(0).getSubscriptionId()); assertEquals(2, infoList.get(1).getSubscriptionId()); mSubscriptionControllerUT.removeSubscriptionsFromGroup( new int[] {2}, groupId, mContext.getOpPackageName()); new int[] {2}, groupId, "packageName1"); infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( groupId, "packageName1"); assertEquals(1, infoList.size()); assertEquals(1, infoList.get(0).getSubscriptionId()); // Make sub 1 inactive. mSubscriptionControllerUT.clearSubInfoRecord(0); try { mSubscriptionControllerUT.addSubscriptionsIntoGroup( new int[] {2}, groupId, "packageName2"); fail("addSubscriptionsIntoGroup should fail with wrong callingPackage name"); } catch (SecurityException e) { // Expected result. } // Adding and removing subscription should still work for packageName1, as it's the group // owner who created the group earlier.. mSubscriptionControllerUT.addSubscriptionsIntoGroup( new int[] {2}, groupId, "packageName1"); infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( groupId, "packageName1"); assertEquals(2, infoList.size()); assertEquals(1, infoList.get(0).getSubscriptionId()); assertEquals(2, infoList.get(1).getSubscriptionId()); mSubscriptionControllerUT.removeSubscriptionsFromGroup( new int[] {2}, groupId, "packageName1"); infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( groupId, "packageName1"); assertEquals(1, infoList.size()); assertEquals(1, infoList.get(0).getSubscriptionId()); } @Test Loading Loading @@ -826,7 +863,7 @@ public class SubscriptionControllerTest extends TelephonyTest { assertTrue(TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, 1, mContext.getOpPackageName(), "getSubscriptionsInGroup")); int[] subIdList = new int[] {1, 2}; int[] subIdList = new int[] {1}; ParcelUuid groupUuid = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, groupUuid); Loading @@ -835,8 +872,16 @@ public class SubscriptionControllerTest extends TelephonyTest { List<SubscriptionInfo> infoList = mSubscriptionControllerUT .getSubscriptionsInGroup(groupUuid, mContext.getOpPackageName()); assertNotEquals(null, infoList); assertEquals(2, infoList.size()); assertEquals(1, infoList.size()); assertEquals(1, infoList.get(0).getSubscriptionId()); subIdList = new int[] {2}; mSubscriptionControllerUT.addSubscriptionsIntoGroup( subIdList, groupUuid, mContext.getOpPackageName()); infoList = mSubscriptionControllerUT .getSubscriptionsInGroup(groupUuid, mContext.getOpPackageName()); assertEquals(2, infoList.size()); assertEquals(2, infoList.get(1).getSubscriptionId()); // Remove group of sub 1. Loading