From 41ba9dc658a4792ae299012f8f0d1a3561a5f72b Mon Sep 17 00:00:00 2001 From: rambowang Date: Wed, 20 Dec 2023 19:57:14 -0600 Subject: [PATCH] Support reset IMS stack in Reset Mobile Network flow Reset the IMS stack for the specified subscription with the help of API TelephonyManager#resetIms. Bug: 271921464 Test: ResetNetworkOperationBuilderTest Change-Id: I61575f18bcc300f362000dc7f4257b9d794b6b69 --- Android.bp | 1 + src/com/android/settings/ResetNetwork.java | 15 ++++-- .../android/settings/ResetNetworkRequest.java | 51 +++++++++++++++++-- .../settings/ResetSubscriptionContract.java | 6 +-- .../network/ResetNetworkOperationBuilder.java | 27 ++++++++++ .../ResetNetworkOperationBuilderTest.java | 46 ++++++++++++++++- 6 files changed, 134 insertions(+), 12 deletions(-) diff --git a/Android.bp b/Android.bp index 79df743c573..8353634e312 100644 --- a/Android.bp +++ b/Android.bp @@ -104,6 +104,7 @@ android_library { "settings-telephony-protos-lite", "statslog-settings", "androidx.test.rules", + "telephony_flags_core_java_lib", ], plugins: ["androidx.room_room-compiler-plugin"], diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java index 80f5962d92a..8e59a7fac82 100644 --- a/src/com/android/settings/ResetNetwork.java +++ b/src/com/android/settings/ResetNetwork.java @@ -44,6 +44,7 @@ import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import com.android.internal.telephony.flags.Flags; import com.android.settings.core.InstrumentedFragment; import com.android.settings.core.SubSettingLauncher; import com.android.settings.network.ResetNetworkRestrictionViewBuilder; @@ -121,16 +122,22 @@ public class ResetNetwork extends InstrumentedFragment { void showFinalConfirmation() { Bundle args = new Bundle(); - ResetNetworkRequest request = new ResetNetworkRequest( - ResetNetworkRequest.RESET_CONNECTIVITY_MANAGER | - ResetNetworkRequest.RESET_VPN_MANAGER - ); + // TODO(b/317276437) Simplify the logic once flag is released + int resetOptions = ResetNetworkRequest.RESET_CONNECTIVITY_MANAGER + | ResetNetworkRequest.RESET_VPN_MANAGER; + if (Flags.resetMobileNetworkSettings()) { + resetOptions |= ResetNetworkRequest.RESET_IMS_STACK; + } + ResetNetworkRequest request = new ResetNetworkRequest(resetOptions); if (mSubscriptions != null && mSubscriptions.size() > 0) { int selectedIndex = mSubscriptionSpinner.getSelectedItemPosition(); SubscriptionInfo subscription = mSubscriptions.get(selectedIndex); int subId = subscription.getSubscriptionId(); request.setResetTelephonyAndNetworkPolicyManager(subId) .setResetApn(subId); + if (Flags.resetMobileNetworkSettings()) { + request.setResetImsSubId(subId); + } } if (mEsimContainer.getVisibility() == View.VISIBLE && mEsimCheckbox.isChecked()) { request.setResetEsim(getContext().getPackageName()) diff --git a/src/com/android/settings/ResetNetworkRequest.java b/src/com/android/settings/ResetNetworkRequest.java index 40eebb0eb29..71c12b1932e 100644 --- a/src/com/android/settings/ResetNetworkRequest.java +++ b/src/com/android/settings/ResetNetworkRequest.java @@ -48,11 +48,23 @@ public class ResetNetworkRequest { /* Reset option - reset BluetoothManager */ public static final int RESET_BLUETOOTH_MANAGER = 0x10; - /* Subscription ID for not performing reset TelephonyAndNetworkPolicy or reset APN */ + /* Reset option - reset IMS stack */ + public static final int RESET_IMS_STACK = 0x20; + + /** + * Subscription ID indicates NOT resetting any of the components below: + * - TelephonyAndNetworkPolicy + * - APN + * - IMS + */ public static final int INVALID_SUBSCRIPTION_ID = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - /* Subscription ID for performing reset TelephonyAndNetworkPolicy or reset APN - on all subscriptions */ + /** + * Subscription ID indicates resetting components below for ALL subscriptions: + * - TelephonyAndNetworkPolicy + * - APN + * - IMS + */ public static final int ALL_SUBSCRIPTION_ID = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; /* Key within Bundle. To store some connectivity options for reset */ @@ -75,10 +87,14 @@ public class ResetNetworkRequest { @VisibleForTesting protected static final String KEY_APN_SUBID = "resetApnSubId"; + /** Key within Bundle. To store subscription ID for resetting IMS. */ + protected static final String KEY_RESET_IMS_SUBID = "resetImsSubId"; + private int mResetOptions = RESET_NONE; private String mResetEsimPackageName; private int mResetTelephonyManager = INVALID_SUBSCRIPTION_ID; private int mResetApn = INVALID_SUBSCRIPTION_ID; + private int mSubscriptionIdToResetIms = INVALID_SUBSCRIPTION_ID; /** * Reconstruct based on keys stored within Bundle. @@ -93,6 +109,8 @@ public class ResetNetworkRequest { mResetTelephonyManager = optionsFromBundle.getInt( KEY_TELEPHONY_NET_POLICY_MANAGER_SUBID, INVALID_SUBSCRIPTION_ID); mResetApn = optionsFromBundle.getInt(KEY_APN_SUBID, INVALID_SUBSCRIPTION_ID); + mSubscriptionIdToResetIms = optionsFromBundle.getInt(KEY_RESET_IMS_SUBID, + INVALID_SUBSCRIPTION_ID); } /** @@ -172,6 +190,29 @@ public class ResetNetworkRequest { return this; } + /** + * Get the subscription ID applied for resetting IMS. + * @return subscription ID. + * {@code ALL_SUBSCRIPTION_ID} for applying to all subscriptions. + * {@code INVALID_SUBSCRIPTION_ID} means resetting IMS + * is not part of the option within this request. + */ + public int getResetImsSubId() { + return mSubscriptionIdToResetIms; + } + + /** + * Set the subscription ID applied for resetting APN. + * @param subId is the subscription ID referenced from SubscriptionManager. + * {@code ALL_SUBSCRIPTION_ID} for applying to all subscriptions. + * {@code INVALID_SUBSCRIPTION_ID} means resetting IMS will not take place. + * @return this + */ + public ResetNetworkRequest setResetImsSubId(int subId) { + mSubscriptionIdToResetIms = subId; + return this; + } + /** * Store a copy of this request into Bundle given. * @param writeToBundle is a Bundle for storing configurations of this request. @@ -182,6 +223,7 @@ public class ResetNetworkRequest { writeToBundle.putString(KEY_ESIM_PACKAGE, mResetEsimPackageName); writeToBundle.putInt(KEY_TELEPHONY_NET_POLICY_MANAGER_SUBID, mResetTelephonyManager); writeToBundle.putInt(KEY_APN_SUBID, mResetApn); + writeToBundle.putInt(KEY_RESET_IMS_SUBID, mSubscriptionIdToResetIms); return this; } @@ -219,6 +261,9 @@ public class ResetNetworkRequest { if (mResetApn != INVALID_SUBSCRIPTION_ID) { builder.resetApn(mResetApn); } + if ((mResetOptions & RESET_IMS_STACK) != 0) { + builder.resetIms(mSubscriptionIdToResetIms); + } return builder; } } diff --git a/src/com/android/settings/ResetSubscriptionContract.java b/src/com/android/settings/ResetSubscriptionContract.java index 580e907707b..528a16def5a 100644 --- a/src/com/android/settings/ResetSubscriptionContract.java +++ b/src/com/android/settings/ResetSubscriptionContract.java @@ -23,8 +23,8 @@ import android.util.Log; import androidx.annotation.VisibleForTesting; -import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.IntStream; @@ -53,8 +53,8 @@ public class ResetSubscriptionContract implements AutoCloseable { mContext = context; // Only keeps specific subscription ID required to perform reset operation IntStream subIdStream = IntStream.of( - resetRequest.getResetTelephonyAndNetworkPolicyManager() - , resetRequest.getResetApnSubId()); + resetRequest.getResetTelephonyAndNetworkPolicyManager(), + resetRequest.getResetApnSubId(), resetRequest.getResetImsSubId()); mResetSubscriptionIds = subIdStream.sorted().distinct() .filter(id -> SubscriptionManager.isUsableSubscriptionId(id)) .toArray(); diff --git a/src/com/android/settings/network/ResetNetworkOperationBuilder.java b/src/com/android/settings/network/ResetNetworkOperationBuilder.java index 3583d06b2b4..61f57f949df 100644 --- a/src/com/android/settings/network/ResetNetworkOperationBuilder.java +++ b/src/com/android/settings/network/ResetNetworkOperationBuilder.java @@ -33,6 +33,7 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; +import com.android.settings.ResetNetworkRequest; import com.android.settings.network.apn.ApnSettings; import java.util.ArrayList; @@ -212,6 +213,32 @@ public class ResetNetworkOperationBuilder { return this; } + /** + * Append a step of resetting IMS stack. + * + * @return this + */ + public ResetNetworkOperationBuilder resetIms(int subId) { + attachSystemServiceWork(Context.TELEPHONY_SERVICE, + (Consumer) tm -> { + if (subId == ResetNetworkRequest.INVALID_SUBSCRIPTION_ID) { + // Do nothing + return; + } + if (subId == ResetNetworkRequest.ALL_SUBSCRIPTION_ID) { + // Reset IMS for all slots + for (int slotIndex = 0; slotIndex < tm.getActiveModemCount(); slotIndex++) { + tm.resetIms(slotIndex); + } + } else { + // Reset IMS for the slot specified by the sucriptionId. + final int slotIndex = SubscriptionManager.getSlotIndex(subId); + tm.resetIms(slotIndex); + } + }); + return this; + } + /** * Construct a Runnable containing all operations appended. * @return Runnable diff --git a/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java b/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java index 6f5440ba5a7..41b6b27471b 100644 --- a/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java +++ b/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java @@ -16,12 +16,12 @@ package com.android.settings.network; -import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.content.Context; import android.net.ConnectivityManager; @@ -34,6 +34,8 @@ import android.telephony.TelephonyManager; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.android.settings.ResetNetworkRequest; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -129,4 +131,44 @@ public class ResetNetworkOperationBuilderTest { verify(mTelephonyManager).resetSettings(); verify(mNetworkPolicyManager).factoryReset(imsi); } + + @Test + public void resetIms_performReset_whenBuildAndRun_withSingleValidSubId() { + final int subId = 1; + doReturn(mTelephonyManager).when(mTelephonyManager) + .createForSubscriptionId(anyInt()); + doReturn(mTelephonyManager).when(mContext) + .getSystemService(Context.TELEPHONY_SERVICE); + + mBuilder.resetIms(subId).build().run(); + + verify(mTelephonyManager).resetIms(anyInt()); + } + + @Test + public void resetIms_performReset_whenBuildAndRun_withInvalidSubId() { + final int subId = ResetNetworkRequest.INVALID_SUBSCRIPTION_ID; + doReturn(mTelephonyManager).when(mTelephonyManager) + .createForSubscriptionId(anyInt()); + doReturn(mTelephonyManager).when(mContext) + .getSystemService(Context.TELEPHONY_SERVICE); + + mBuilder.resetIms(subId).build().run(); + + verify(mTelephonyManager, never()).resetIms(anyInt()); + } + + @Test + public void resetIms_performReset_whenBuildAndRun_withAllValidSubId() { + final int subId = ResetNetworkRequest.ALL_SUBSCRIPTION_ID; + doReturn(mTelephonyManager).when(mTelephonyManager) + .createForSubscriptionId(anyInt()); + doReturn(mTelephonyManager).when(mContext) + .getSystemService(Context.TELEPHONY_SERVICE); + doReturn(2).when(mTelephonyManager).getActiveModemCount(); + + mBuilder.resetIms(subId).build().run(); + + verify(mTelephonyManager, times(2)).resetIms(anyInt()); + } }