diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java index 693f3a0cf8a0e..1bd5031d6c69d 100644 --- a/services/people/java/com/android/server/people/data/DataManager.java +++ b/services/people/java/com/android/server/people/data/DataManager.java @@ -788,7 +788,7 @@ public class DataManager { private void updateDefaultSmsApp(@NonNull UserData userData) { ComponentName component = SmsApplication.getDefaultSmsApplicationAsUser( - mContext, /* updateIfNeeded= */ false, userData.getUserId()); + mContext, /* updateIfNeeded= */ false, UserHandle.of(userData.getUserId())); String defaultSmsApp = component != null ? component.getPackageName() : null; userData.setDefaultSmsApp(defaultSmsApp); } diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java index f848c4013fa97..a9cdf7e5bc089 100644 --- a/telephony/common/com/android/internal/telephony/SmsApplication.java +++ b/telephony/common/com/android/internal/telephony/SmsApplication.java @@ -209,6 +209,15 @@ public final class SmsApplication { } } + /** + * Returns the userHandle of the current process, if called from a system app, + * otherwise it returns the caller's userHandle + * @return userHandle of the caller. + */ + private static UserHandle getIncomingUserHandle() { + return UserHandle.of(getIncomingUserId()); + } + /** * Returns the list of available SMS apps defined as apps that are registered for both the * SMS_RECEIVED_ACTION (SMS) and WAP_PUSH_RECEIVED_ACTION (MMS) broadcasts (and their broadcast @@ -951,24 +960,28 @@ public final class SmsApplication { */ @UnsupportedAppUsage public static ComponentName getDefaultSmsApplication(Context context, boolean updateIfNeeded) { - return getDefaultSmsApplicationAsUser(context, updateIfNeeded, getIncomingUserId()); + return getDefaultSmsApplicationAsUser(context, updateIfNeeded, getIncomingUserHandle()); } /** * Gets the default SMS application on a given user * @param context context from the calling app * @param updateIfNeeded update the default app if there is no valid default app configured. - * @param userId target user ID. + * @param userHandle target user handle + * if {@code null} is passed in then calling package uid is used to find out target user handle. * @return component name of the app and class to deliver SMS messages to */ - @VisibleForTesting public static ComponentName getDefaultSmsApplicationAsUser(Context context, - boolean updateIfNeeded, int userId) { + boolean updateIfNeeded, @Nullable UserHandle userHandle) { + if (userHandle == null) { + userHandle = getIncomingUserHandle(); + } + final long token = Binder.clearCallingIdentity(); try { ComponentName component = null; SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded, - userId); + userHandle.getIdentifier()); if (smsApplicationData != null) { component = new ComponentName(smsApplicationData.mPackageName, smsApplicationData.mSmsReceiverClass); @@ -987,23 +1000,28 @@ public final class SmsApplication { */ @UnsupportedAppUsage public static ComponentName getDefaultMmsApplication(Context context, boolean updateIfNeeded) { - return getDefaultMmsApplicationAsUser(context, updateIfNeeded, getIncomingUserId()); + return getDefaultMmsApplicationAsUser(context, updateIfNeeded, getIncomingUserHandle()); } /** * Gets the default MMS application on a given user * @param context context from the calling app * @param updateIfNeeded update the default app if there is no valid default app configured. - * @param userId target user ID. + * @param userHandle target user handle + * if {@code null} is passed in then calling package uid is used to find out target user handle. * @return component name of the app and class to deliver MMS messages to. */ public static ComponentName getDefaultMmsApplicationAsUser(Context context, - boolean updateIfNeeded, int userId) { + boolean updateIfNeeded, @Nullable UserHandle userHandle) { + if (userHandle == null) { + userHandle = getIncomingUserHandle(); + } + final long token = Binder.clearCallingIdentity(); try { ComponentName component = null; SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded, - userId); + userHandle.getIdentifier()); if (smsApplicationData != null) { component = new ComponentName(smsApplicationData.mPackageName, smsApplicationData.mMmsReceiverClass); @@ -1024,23 +1042,28 @@ public final class SmsApplication { public static ComponentName getDefaultRespondViaMessageApplication(Context context, boolean updateIfNeeded) { return getDefaultRespondViaMessageApplicationAsUser(context, updateIfNeeded, - getIncomingUserId()); + getIncomingUserHandle()); } /** * Gets the default Respond Via Message application on a given user * @param context context from the calling app * @param updateIfNeeded update the default app if there is no valid default app configured - * @param userId target user ID. + * @param userHandle target user handle + * if {@code null} is passed in then calling package uid is used to find out target user handle. * @return component name of the app and class to direct Respond Via Message intent to */ public static ComponentName getDefaultRespondViaMessageApplicationAsUser(Context context, - boolean updateIfNeeded, int userId) { + boolean updateIfNeeded, @Nullable UserHandle userHandle) { + if (userHandle == null) { + userHandle = getIncomingUserHandle(); + } + final long token = Binder.clearCallingIdentity(); try { ComponentName component = null; SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded, - userId); + userHandle.getIdentifier()); if (smsApplicationData != null) { component = new ComponentName(smsApplicationData.mPackageName, smsApplicationData.mRespondViaMessageClass); @@ -1062,6 +1085,7 @@ public final class SmsApplication { public static ComponentName getDefaultSendToApplication(Context context, boolean updateIfNeeded) { int userId = getIncomingUserId(); + final long token = Binder.clearCallingIdentity(); try { ComponentName component = null; @@ -1087,7 +1111,7 @@ public final class SmsApplication { public static ComponentName getDefaultExternalTelephonyProviderChangedApplication( Context context, boolean updateIfNeeded) { return getDefaultExternalTelephonyProviderChangedApplicationAsUser(context, updateIfNeeded, - getIncomingUserId()); + getIncomingUserHandle()); } /** @@ -1095,16 +1119,21 @@ public final class SmsApplication { * MmsProvider on a given user. * @param context context from the calling app * @param updateIfNeeded update the default app if there is no valid default app configured - * @param userId target user ID. + * @param userHandle target user handle + * if {@code null} is passed in then calling package uid is used to find out target user handle. * @return component name of the app and class to deliver change intents to. */ public static ComponentName getDefaultExternalTelephonyProviderChangedApplicationAsUser( - Context context, boolean updateIfNeeded, int userId) { + Context context, boolean updateIfNeeded, @Nullable UserHandle userHandle) { + if (userHandle == null) { + userHandle = getIncomingUserHandle(); + } + final long token = Binder.clearCallingIdentity(); try { ComponentName component = null; SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded, - userId); + userHandle.getIdentifier()); if (smsApplicationData != null && smsApplicationData.mProviderChangedReceiverClass != null) { component = new ComponentName(smsApplicationData.mPackageName, @@ -1124,23 +1153,28 @@ public final class SmsApplication { */ public static ComponentName getDefaultSimFullApplication( Context context, boolean updateIfNeeded) { - return getDefaultSimFullApplicationAsUser(context, updateIfNeeded, getIncomingUserId()); + return getDefaultSimFullApplicationAsUser(context, updateIfNeeded, getIncomingUserHandle()); } /** * Gets the default application that handles sim full event on a given user. * @param context context from the calling app * @param updateIfNeeded update the default app if there is no valid default app configured - * @param userId target user ID. + * @param userHandle target user handle + * if {@code null} is passed in then calling package uid is used to find out target user handle. * @return component name of the app and class to deliver change intents to */ public static ComponentName getDefaultSimFullApplicationAsUser(Context context, - boolean updateIfNeeded, int userId) { + boolean updateIfNeeded, @Nullable UserHandle userHandle) { + if (userHandle == null) { + userHandle = getIncomingUserHandle(); + } + final long token = Binder.clearCallingIdentity(); try { ComponentName component = null; SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded, - userId); + userHandle.getIdentifier()); if (smsApplicationData != null && smsApplicationData.mSimFullReceiverClass != null) { component = new ComponentName(smsApplicationData.mPackageName, @@ -1153,19 +1187,35 @@ public final class SmsApplication { } /** - * Returns whether need to wrgetIncomingUserIdite the SMS message to SMS database for this - * package. + * Returns whether it is required to write the SMS message to SMS database for this package. + * + * @param packageName the name of the package to be checked + * @param context context from the calling app + * @return true if it is required to write SMS message to SMS database for this package. + * *

* Caller must pass in the correct user context if calling from a singleton service. */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static boolean shouldWriteMessageForPackage(String packageName, Context context) { - return !shouldWriteMessageForPackageAsUser(packageName, context, getIncomingUserId()); + return !shouldWriteMessageForPackageAsUser(packageName, context, getIncomingUserHandle()); } + /** + * Returns whether it is required to write the SMS message to SMS database for this package. + * + * @param packageName the name of the package to be checked + * @param context context from the calling app + * @param userHandle target user handle + * if {@code null} is passed in then calling package uid is used to find out target user handle. + * @return true if it is required to write SMS message to SMS database for this package. + * + *

+ * Caller must pass in the correct user context if calling from a singleton service. + */ public static boolean shouldWriteMessageForPackageAsUser(String packageName, Context context, - int userId) { - return !isDefaultSmsApplicationAsUser(context, packageName, userId); + @Nullable UserHandle userHandle) { + return !isDefaultSmsApplicationAsUser(context, packageName, userHandle); } /** @@ -1177,7 +1227,7 @@ public final class SmsApplication { */ @UnsupportedAppUsage public static boolean isDefaultSmsApplication(Context context, String packageName) { - return isDefaultSmsApplicationAsUser(context, packageName, getIncomingUserId()); + return isDefaultSmsApplicationAsUser(context, packageName, getIncomingUserHandle()); } /** @@ -1185,16 +1235,22 @@ public final class SmsApplication { * * @param context context from the calling app * @param packageName the name of the package to be checked - * @param userId target user ID. + * @param userHandle target user handle + * if {@code null} is passed in then calling package uid is used to find out target user handle. * @return true if the package is default sms app or bluetooth */ public static boolean isDefaultSmsApplicationAsUser(Context context, String packageName, - int userId) { + @Nullable UserHandle userHandle) { if (packageName == null) { return false; } + + if (userHandle == null) { + userHandle = getIncomingUserHandle(); + } + ComponentName component = getDefaultSmsApplicationAsUser(context, false, - userId); + userHandle); if (component == null) { return false; } @@ -1222,7 +1278,7 @@ public final class SmsApplication { */ @UnsupportedAppUsage public static boolean isDefaultMmsApplication(Context context, String packageName) { - return isDefaultMmsApplicationAsUser(context, packageName, getIncomingUserId()); + return isDefaultMmsApplicationAsUser(context, packageName, getIncomingUserHandle()); } /** @@ -1230,17 +1286,22 @@ public final class SmsApplication { * * @param context context from the calling app * @param packageName the name of the package to be checked - * @param userId target user ID. + * @param userHandle target user handle + * if {@code null} is passed in then calling package uid is used to find out target user handle. * @return true if the package is default mms app or bluetooth */ public static boolean isDefaultMmsApplicationAsUser(Context context, String packageName, - int userId) { + @Nullable UserHandle userHandle) { if (packageName == null) { return false; } + if (userHandle == null) { + userHandle = getIncomingUserHandle(); + } + ComponentName component = getDefaultMmsApplicationAsUser(context, false, - userId); + userHandle); if (component == null) { return false; } diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java index 76d2b7d8fce59..3dc71117ace89 100644 --- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java +++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java @@ -27,6 +27,8 @@ import android.os.Binder; import android.os.Bundle; import android.os.PersistableBundle; import android.os.SystemProperties; +import android.os.UserHandle; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import java.io.PrintWriter; @@ -212,4 +214,30 @@ public final class TelephonyUtils { return "UNKNOWN(" + mobileDataPolicy + ")"; } } -} + + /** + * Utility method to get user handle associated with this subscription. + * + * This method should be used internally as it returns null instead of throwing + * IllegalArgumentException or IllegalStateException. + * + * @param context Context object + * @param subId the subId of the subscription. + * @return userHandle associated with this subscription + * or {@code null} if: + * 1. subscription is not associated with any user + * 2. subId is invalid. + * 3. subscription service is not available. + * + * @throws SecurityException if the caller doesn't have permissions required. + */ + @Nullable + public static UserHandle getSubscriptionUserHandle(Context context, int subId) { + UserHandle userHandle = null; + SubscriptionManager subManager = context.getSystemService(SubscriptionManager.class); + if ((subManager != null) && (SubscriptionManager.isValidSubscriptionId(subId))) { + userHandle = subManager.getSubscriptionUserHandle(subId); + } + return userHandle; + } +} \ No newline at end of file diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 51a7840a9fbe3..5f9d516e5eb69 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -71,6 +71,7 @@ import android.os.PersistableBundle; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemProperties; +import android.os.UserHandle; import android.os.WorkSource; import android.provider.Settings.SettingNotFoundException; import android.service.carrier.CarrierIdentifier; @@ -11999,8 +12000,9 @@ public class TelephonyManager { } /** - * Gets the default Respond Via Message application, updating the cache if there is no - * respond-via-message application currently configured. + * Get the component name of the default app to direct respond-via-message intent for the + * user associated with this subscription, update the cache if there is no respond-via-message + * application currently configured for this user. * @return component name of the app and class to direct Respond Via Message intent to, or * {@code null} if the functionality is not supported. * @hide @@ -12009,11 +12011,20 @@ public class TelephonyManager { @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS) @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING) public @Nullable ComponentName getAndUpdateDefaultRespondViaMessageApplication() { - return SmsApplication.getDefaultRespondViaMessageApplication(mContext, true); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getDefaultRespondViaMessageApplication(getSubId(), true); + } + } catch (RemoteException e) { + Log.e(TAG, "Error in getAndUpdateDefaultRespondViaMessageApplication: " + e); + } + return null; } /** - * Gets the default Respond Via Message application. + * Get the component name of the default app to direct respond-via-message intent for the + * user associated with this subscription. * @return component name of the app and class to direct Respond Via Message intent to, or * {@code null} if the functionality is not supported. * @hide @@ -12022,7 +12033,15 @@ public class TelephonyManager { @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS) @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING) public @Nullable ComponentName getDefaultRespondViaMessageApplication() { - return SmsApplication.getDefaultRespondViaMessageApplication(mContext, false); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getDefaultRespondViaMessageApplication(getSubId(), false); + } + } catch (RemoteException e) { + Log.e(TAG, "Error in getDefaultRespondViaMessageApplication: " + e); + } + return null; } /** diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 648866b6662da..bec84177c1ea9 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -17,6 +17,7 @@ package com.android.internal.telephony; import android.app.PendingIntent; +import android.content.ComponentName; import android.content.Intent; import android.content.IntentSender; import android.os.Bundle; @@ -2612,4 +2613,14 @@ interface ITelephony { * @hide */ boolean isRemovableEsimDefaultEuicc(String callingPackage); + + /** + * Get the component name of the default app to direct respond-via-message intent for the + * user associated with this subscription, update the cache if there is no respond-via-message + * application currently configured for this user. + * @return component name of the app and class to direct Respond Via Message intent to, or + * {@code null} if the functionality is not supported. + * @hide + */ + ComponentName getDefaultRespondViaMessageApplication(int subId, boolean updateIfNeeded); } diff --git a/tests/TelephonyCommonTests/Android.bp b/tests/TelephonyCommonTests/Android.bp index a9fbfd97225d0..81ec265c2c291 100644 --- a/tests/TelephonyCommonTests/Android.bp +++ b/tests/TelephonyCommonTests/Android.bp @@ -47,7 +47,7 @@ android_test { // Uncomment this and comment out the jarjar rule if you want to attach a debugger and step // through the renamed classes. - // platform_apis: true, + platform_apis: true, libs: [ "android.test.runner", diff --git a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java index 7a2af72c41d5b..adefac64dbaeb 100644 --- a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java +++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java @@ -44,6 +44,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.res.Resources; import android.net.Uri; import android.os.Handler; import android.os.UserHandle; @@ -75,9 +76,12 @@ import java.util.stream.Collectors; public class SmsApplicationTest { private static final ComponentName TEST_COMPONENT_NAME = ComponentName.unflattenFromString("com.android.test/.TestSmsApp"); + public static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth.services"; private static final String MMS_RECEIVER_NAME = "TestMmsReceiver"; private static final String RESPOND_VIA_SMS_NAME = "TestRespondViaSmsHandler"; private static final String SEND_TO_NAME = "TestSendTo"; + private static final String EXTERNAL_PROVIDER_CHANGE_NAME = "TestExternalProviderChangeHandler"; + private static final String SIM_FULL_NAME = "TestSimFullHandler"; private static final int SMS_APP_UID = 10001; private static final int FAKE_PHONE_UID = 10002; @@ -102,6 +106,7 @@ public class SmsApplicationTest { }).collect(Collectors.toSet()); @Mock private Context mContext; + @Mock private Resources mResources; @Mock private TelephonyManager mTelephonyManager; @Mock private RoleManager mRoleManager; @Mock private PackageManager mPackageManager; @@ -118,6 +123,9 @@ public class SmsApplicationTest { when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager); when(mContext.createContextAsUser(isNotNull(), anyInt())).thenReturn(mContext); + when(mContext.getResources()).thenReturn(mResources); + when(mResources.getString(eq(com.android.internal.R.string.config_systemBluetoothStack))) + .thenReturn(BLUETOOTH_PACKAGE_NAME); doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0))) .when(mPackageManager) @@ -146,24 +154,46 @@ public class SmsApplicationTest { } } + @Test - public void testGetDefaultSmsApplication() { + public void testGetDefaultSmsApplicationAsUser() { assertEquals(TEST_COMPONENT_NAME, - SmsApplication.getDefaultSmsApplicationAsUser(mContext, false, 0)); + SmsApplication.getDefaultSmsApplicationAsUser(mContext, false, + UserHandle.SYSTEM)); + } + + + @Test + public void testGetDefaultMmsApplicationAsUser() { + ComponentName componentName = SmsApplication.getDefaultMmsApplicationAsUser(mContext, + false, UserHandle.SYSTEM); + assertEquals(TEST_COMPONENT_NAME.getPackageName(), componentName.getPackageName()); + assertEquals(MMS_RECEIVER_NAME, componentName.getClassName()); } @Test - public void testGetDefaultMmsApplication() { - assertEquals(TEST_COMPONENT_NAME, - SmsApplication.getDefaultMmsApplicationAsUser(mContext, false, - UserHandle.USER_SYSTEM)); + public void testGetDefaultExternalTelephonyProviderChangedApplicationAsUser() { + ComponentName componentName = SmsApplication + .getDefaultExternalTelephonyProviderChangedApplicationAsUser(mContext, + false, UserHandle.SYSTEM); + assertEquals(TEST_COMPONENT_NAME.getPackageName(), componentName.getPackageName()); + assertEquals(EXTERNAL_PROVIDER_CHANGE_NAME, componentName.getClassName()); } @Test - public void testGetDefaultExternalTelephonyProviderChangedApplication() { - assertEquals(TEST_COMPONENT_NAME, - SmsApplication.getDefaultExternalTelephonyProviderChangedApplicationAsUser(mContext, - false, UserHandle.USER_SYSTEM)); + public void testGetDefaultRespondViaMessageApplicationAsUserAsUser() { + ComponentName componentName = SmsApplication.getDefaultRespondViaMessageApplicationAsUser( + mContext, false, UserHandle.SYSTEM); + assertEquals(TEST_COMPONENT_NAME.getPackageName(), componentName.getPackageName()); + assertEquals(RESPOND_VIA_SMS_NAME, componentName.getClassName()); + } + + @Test + public void testGetDefaultSimFullApplicationAsUser() { + ComponentName componentName = SmsApplication.getDefaultSimFullApplicationAsUser(mContext, + false, UserHandle.SYSTEM); + assertEquals(TEST_COMPONENT_NAME.getPackageName(), componentName.getPackageName()); + assertEquals(SIM_FULL_NAME, componentName.getClassName()); } @Test @@ -174,7 +204,8 @@ public class SmsApplicationTest { setupPackageInfosForCoreApps(); assertEquals(TEST_COMPONENT_NAME, - SmsApplication.getDefaultSmsApplicationAsUser(mContext, true, 0)); + SmsApplication.getDefaultSmsApplicationAsUser(mContext, true, + UserHandle.SYSTEM)); verify(mAppOpsManager, atLeastOnce()).setUidMode(AppOpsManager.OPSTR_READ_SMS, SMS_APP_UID, AppOpsManager.MODE_ALLOWED); } @@ -251,6 +282,10 @@ public class SmsApplicationTest { return Collections.singletonList(makeRespondViaMessageResolveInfo()); case Intent.ACTION_SENDTO: return Collections.singletonList(makeSendToResolveInfo()); + case Telephony.Sms.Intents.ACTION_EXTERNAL_PROVIDER_CHANGE: + return Collections.singletonList(makeExternalProviderChangeResolveInfo()); + case Telephony.Sms.Intents.SIM_FULL_ACTION: + return Collections.singletonList(makeSimFullResolveInfo()); } return Collections.emptyList(); } @@ -308,4 +343,26 @@ public class SmsApplicationTest { info.activityInfo = activityInfo; return info; } + + private ResolveInfo makeExternalProviderChangeResolveInfo() { + ResolveInfo info = new ResolveInfo(); + ActivityInfo activityInfo = new ActivityInfo(); + + activityInfo.packageName = TEST_COMPONENT_NAME.getPackageName(); + activityInfo.name = EXTERNAL_PROVIDER_CHANGE_NAME; + + info.activityInfo = activityInfo; + return info; + } + + private ResolveInfo makeSimFullResolveInfo() { + ResolveInfo info = new ResolveInfo(); + ActivityInfo activityInfo = new ActivityInfo(); + + activityInfo.packageName = TEST_COMPONENT_NAME.getPackageName(); + activityInfo.name = SIM_FULL_NAME; + + info.activityInfo = activityInfo; + return info; + } } diff --git a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java new file mode 100644 index 0000000000000..a62103e0030ba --- /dev/null +++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony.tests; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.telephony.SubscriptionManager; + +import com.android.internal.telephony.util.TelephonyUtils; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +public class TelephonyUtilsTest { + @Rule + public final MockitoRule mockito = MockitoJUnit.rule(); + + // Mocked classes + @Mock + private Context mContext; + @Mock + private SubscriptionManager mSubscriptionManager; + + @Before + public void setup() { + doReturn(mSubscriptionManager).when(mContext) + .getSystemService(eq(SubscriptionManager.class)); + } + + + @Test + public void getSubscriptionUserHandle_subId_invalid() { + int invalidSubId = -10; + doReturn(false).when(mSubscriptionManager).isActiveSubscriptionId(eq(invalidSubId)); + + TelephonyUtils.getSubscriptionUserHandle(mContext, invalidSubId); + + // getSubscriptionUserHandle should not be called if subID is inactive. + verify(mSubscriptionManager, never()).getSubscriptionUserHandle(eq(invalidSubId)); + } + + @Test + public void getSubscriptionUserHandle_subId_valid() { + int activeSubId = 1; + doReturn(true).when(mSubscriptionManager).isActiveSubscriptionId(eq(activeSubId)); + + TelephonyUtils.getSubscriptionUserHandle(mContext, activeSubId); + + // getSubscriptionUserHandle should be called if subID is active. + verify(mSubscriptionManager, times(1)).getSubscriptionUserHandle(eq(activeSubId)); + } +} + +