From 4c384506d5e484e9583c74e26228247534acf06b Mon Sep 17 00:00:00 2001 From: Rambo Wang Date: Thu, 4 Jan 2024 04:33:23 +0000 Subject: [PATCH] Reset telephony stack during Reset Mobile Network flow This CL introduces two more steps to restart Phone process and RILD during the Reset mobile network flow by the help of the TelephonyContentProvider which has been used by Pixel Adaptive Connectivity Services ("SCONE") for a while. The additional reset options can resolve issues like resources leak and internal state stuck, effectively recover telephony stack into fresh state. The reset options are performed in the background and have no impact on UX of the reset flow. Bug: 271921464 Test: ResetNetworkOperationBuilderTest Test: Feature test with both flag on and off Change-Id: If09d20d79e908dd43f3f654fb7cca7f713b7f03a --- AndroidManifest.xml | 1 + res/values/strings.xml | 3 + src/com/android/settings/ResetNetwork.java | 3 +- .../android/settings/ResetNetworkRequest.java | 12 ++++ .../network/ResetNetworkOperationBuilder.java | 59 +++++++++++++++++++ .../ResetNetworkOperationBuilderTest.java | 49 +++++++++++++++ 6 files changed, 126 insertions(+), 1 deletion(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 6ad4c055e31..854d4099fc1 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -140,6 +140,7 @@ + Password is now set up + + + diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java index ebfa9352123..f05f65c3cb6 100644 --- a/src/com/android/settings/ResetNetwork.java +++ b/src/com/android/settings/ResetNetwork.java @@ -21,7 +21,6 @@ import android.app.Activity; import android.app.settings.SettingsEnums; import android.content.ContentResolver; import android.content.Context; -import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; import android.provider.Settings; @@ -128,6 +127,8 @@ public class ResetNetwork extends InstrumentedFragment { | ResetNetworkRequest.RESET_VPN_MANAGER; if (Flags.resetMobileNetworkSettings()) { resetOptions |= ResetNetworkRequest.RESET_IMS_STACK; + resetOptions |= ResetNetworkRequest.RESET_PHONE_PROCESS; + resetOptions |= ResetNetworkRequest.RESET_RILD; } ResetNetworkRequest request = new ResetNetworkRequest(resetOptions); if (mSubscriptions != null && mSubscriptions.size() > 0) { diff --git a/src/com/android/settings/ResetNetworkRequest.java b/src/com/android/settings/ResetNetworkRequest.java index 71c12b1932e..4be8b3206a6 100644 --- a/src/com/android/settings/ResetNetworkRequest.java +++ b/src/com/android/settings/ResetNetworkRequest.java @@ -51,6 +51,12 @@ public class ResetNetworkRequest { /* Reset option - reset IMS stack */ public static final int RESET_IMS_STACK = 0x20; + /* Reset option - reset phone process */ + public static final int RESET_PHONE_PROCESS = 0x40; + + /* Reset option - reset RILD */ + public static final int RESET_RILD = 0x80; + /** * Subscription ID indicates NOT resetting any of the components below: * - TelephonyAndNetworkPolicy @@ -264,6 +270,12 @@ public class ResetNetworkRequest { if ((mResetOptions & RESET_IMS_STACK) != 0) { builder.resetIms(mSubscriptionIdToResetIms); } + if ((mResetOptions & RESET_PHONE_PROCESS) != 0) { + builder.restartPhoneProcess(); + } + if ((mResetOptions & RESET_RILD) != 0) { + builder.restartRild(); + } return builder; } } diff --git a/src/com/android/settings/network/ResetNetworkOperationBuilder.java b/src/com/android/settings/network/ResetNetworkOperationBuilder.java index 61f57f949df..ac07897aebb 100644 --- a/src/com/android/settings/network/ResetNetworkOperationBuilder.java +++ b/src/com/android/settings/network/ResetNetworkOperationBuilder.java @@ -33,6 +33,8 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; +import com.android.settings.R; import com.android.settings.ResetNetworkRequest; import com.android.settings.network.apn.ApnSettings; @@ -50,6 +52,13 @@ public class ResetNetworkOperationBuilder { private static final boolean DRY_RUN = false; + // TelephonyContentProvider method to restart phone process + @VisibleForTesting + static final String METHOD_RESTART_PHONE_PROCESS = "restartPhoneProcess"; + // TelephonyContentProvider method to restart RILD + @VisibleForTesting + static final String METHOD_RESTART_RILD = "restartRild"; + private Context mContext; private List mResetSequence = new ArrayList(); @@ -229,16 +238,56 @@ public class ResetNetworkOperationBuilder { // Reset IMS for all slots for (int slotIndex = 0; slotIndex < tm.getActiveModemCount(); slotIndex++) { tm.resetIms(slotIndex); + Log.i(TAG, "IMS was reset for slot " + slotIndex); } } else { // Reset IMS for the slot specified by the sucriptionId. final int slotIndex = SubscriptionManager.getSlotIndex(subId); tm.resetIms(slotIndex); + Log.i(TAG, "IMS was reset for slot " + slotIndex); } }); return this; } + /** + * Append a step to restart phone process by the help of TelephonyContentProvider. + * It's a no-op if TelephonyContentProvider doesn't exist. + * @return this + */ + public ResetNetworkOperationBuilder restartPhoneProcess() { + try { + mContext.getContentResolver().call( + getResetTelephonyContentProviderAuthority(), + METHOD_RESTART_PHONE_PROCESS, + /* arg= */ null, + /* extras= */ null); + Log.i(TAG, "Phone process was restarted."); + } catch (IllegalArgumentException iae) { + Log.w(TAG, "Fail to restart phone process: " + iae); + } + return this; + } + + /** + * Append a step to restart RILD by the help of TelephonyContentProvider. + * It's a no-op if TelephonyContentProvider doesn't exist. + * @return this + */ + public ResetNetworkOperationBuilder restartRild() { + try { + mContext.getContentResolver().call( + getResetTelephonyContentProviderAuthority(), + METHOD_RESTART_RILD, + /* arg= */ null, + /* extras= */ null); + Log.i(TAG, "RILD was restarted."); + } catch (IllegalArgumentException iae) { + Log.w(TAG, "Fail to restart RILD: " + iae); + } + return this; + } + /** * Construct a Runnable containing all operations appended. * @return Runnable @@ -262,4 +311,14 @@ public class ResetNetworkOperationBuilder { }; mResetSequence.add(runnable); } + + /** + * @return the authority of the telephony content provider that support methods + * resetPhoneProcess and resetRild. + */ + @VisibleForTesting + String getResetTelephonyContentProviderAuthority() { + return mContext.getResources().getString( + R.string.reset_telephony_stack_content_provider_authority); + } } diff --git a/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java b/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java index 41b6b27471b..6213f8eeb33 100644 --- a/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java +++ b/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java @@ -16,13 +16,20 @@ package com.android.settings.network; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; 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 android.content.ContentProvider; +import android.content.ContentResolver; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkPolicyManager; @@ -59,6 +66,9 @@ public class ResetNetworkOperationBuilderTest { private TelephonyManager mTelephonyManager; @Mock private NetworkPolicyManager mNetworkPolicyManager; + @Mock + private ContentProvider mContentProvider;; + private Context mContext; private ResetNetworkOperationBuilder mBuilder; @@ -67,6 +77,7 @@ public class ResetNetworkOperationBuilderTest { public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(ApplicationProvider.getApplicationContext()); + doReturn(ContentResolver.wrap(mContentProvider)).when(mContext).getContentResolver(); mBuilder = spy(new ResetNetworkOperationBuilder(mContext)); } @@ -171,4 +182,42 @@ public class ResetNetworkOperationBuilderTest { verify(mTelephonyManager, times(2)).resetIms(anyInt()); } + + @Test + public void restartPhoneProcess_withoutTelephonyContentProvider_shouldNotCrash() { + doThrow(new IllegalArgumentException()).when(mContentProvider).call( + anyString(), anyString(), anyString(), any()); + + mBuilder.restartPhoneProcess(); + } + + @Test + public void restartRild_withoutTelephonyContentProvider_shouldNotCrash() { + doThrow(new IllegalArgumentException()).when(mContentProvider).call( + anyString(), anyString(), anyString(), any()); + + mBuilder.restartRild(); + } + + @Test + public void restartPhoneProcess_withTelephonyContentProvider_shouldCallRestartPhoneProcess() { + mBuilder.restartPhoneProcess(); + + verify(mContentProvider).call( + eq(mBuilder.getResetTelephonyContentProviderAuthority()), + eq(ResetNetworkOperationBuilder.METHOD_RESTART_PHONE_PROCESS), + isNull(), + isNull()); + } + + @Test + public void restartRild_withTelephonyContentProvider_shouldCallRestartRild() { + mBuilder.restartRild(); + + verify(mContentProvider).call( + eq(mBuilder.getResetTelephonyContentProviderAuthority()), + eq(ResetNetworkOperationBuilder.METHOD_RESTART_RILD), + isNull(), + isNull()); + } }