diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java index 732277b3d8a..9c4f8f18915 100644 --- a/src/com/android/settings/sim/SimDialogActivity.java +++ b/src/com/android/settings/sim/SimDialogActivity.java @@ -65,6 +65,8 @@ public class SimDialogActivity extends FragmentActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + SimDialogProhibitService.supportDismiss(this); + getWindow().addSystemFlags( WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); showOrUpdateDialog(); @@ -225,4 +227,15 @@ public class SimDialogActivity extends FragmentActivity { } return null; } + + /* + * Force dismiss this Activity. + */ + protected void forceClose() { + if (isFinishing() || isDestroyed()) { + return; + } + Log.d(TAG, "Dismissed by Service"); + finishAndRemoveTask(); + } } diff --git a/src/com/android/settings/sim/SimDialogProhibitService.java b/src/com/android/settings/sim/SimDialogProhibitService.java new file mode 100644 index 00000000000..1558fb3ec0f --- /dev/null +++ b/src/com/android/settings/sim/SimDialogProhibitService.java @@ -0,0 +1,89 @@ +/* + * 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.settings.sim; + +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import java.lang.ref.WeakReference; +import java.util.concurrent.RejectedExecutionException; + +/** + * A class for routing dismiss dialog request to SimDialogActivity. + */ +public class SimDialogProhibitService { + + private static final String TAG = "SimDialogProhibitService"; + + private static WeakReference sSimDialogActivity; + + /** + * Support the dismiss of {@link SimDialogActivity} (singletone.) + * + * @param activity {@link SimDialogActivity} + */ + public static void supportDismiss(SimDialogActivity activity) { + sSimDialogActivity = new WeakReference(activity); + } + + /** + * Dismiss SimDialogActivity dialog. + * + * @param context is a {@link Context} + */ + public static void dismissDialog(Context context) { + // Dismiss existing dialog. + if (!dismissDialogThroughRunnable()) { + dismissDialogThroughIntent(context); + } + } + + /** + * Dismiss dialog (if there's any). + * + * @return {@code true} when success, {@code false} when failure. + */ + protected static boolean dismissDialogThroughRunnable() { + final SimDialogActivity activity = (sSimDialogActivity == null) ? + null : sSimDialogActivity.get(); + if (activity == null) { + Log.i(TAG, "No SimDialogActivity for dismiss."); + return true; + } + + try { + activity.getMainExecutor().execute(() -> activity.forceClose()); + return true; + } catch (RejectedExecutionException exception) { + Log.w(TAG, "Fail to close SimDialogActivity through executor", exception); + } + return false; + } + + /** + * Dismiss dialog through {@link Intent}. + * + * @param uiContext is {@link Context} for start SimDialogActivity. + */ + protected static void dismissDialogThroughIntent(Context uiContext) { + Intent newIntent = new Intent(uiContext, SimDialogActivity.class); + newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, SimDialogActivity.PICK_DISMISS); + uiContext.startActivity(newIntent); + } +} diff --git a/src/com/android/settings/sim/SimSelectNotification.java b/src/com/android/settings/sim/SimSelectNotification.java index 5902b926020..9d3f860a014 100644 --- a/src/com/android/settings/sim/SimSelectNotification.java +++ b/src/com/android/settings/sim/SimSelectNotification.java @@ -164,10 +164,7 @@ public class SimSelectNotification extends BroadcastReceiver { // If the dialog type is to dismiss. if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS) { - Intent newIntent = new Intent(context, SimDialogActivity.class); - newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, PICK_DISMISS); - context.startActivity(newIntent); + SimDialogProhibitService.dismissDialog(context); return; } diff --git a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java index 10e291cf2c0..b33e94ba52e 100644 --- a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java +++ b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java @@ -42,6 +42,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -74,6 +75,7 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import java.util.Arrays; +import java.util.concurrent.Executor; @RunWith(RobolectricTestRunner.class) @Config(shadows = ShadowAlertDialogCompat.class) @@ -81,6 +83,8 @@ public class SimSelectNotificationTest { @Mock private Context mContext; @Mock + private Executor mExecutor; + @Mock private NotificationManager mNotificationManager; @Mock private TelephonyManager mTelephonyManager; @@ -94,6 +98,8 @@ public class SimSelectNotificationTest { private SubscriptionInfo mSubInfo; @Mock private DisplayMetrics mDisplayMetrics; + @Mock + private SimDialogActivity mActivity; private final String mFakeDisplayName = "fake_display_name"; private final CharSequence mFakeNotificationChannelTitle = "fake_notification_channel_title"; @@ -236,27 +242,18 @@ public class SimSelectNotificationTest { @Test public void onReceivePrimarySubListChange_WithDismissExtra_shouldDismiss() { + doReturn(mExecutor).when(mActivity).getMainExecutor(); + SimDialogProhibitService.supportDismiss(mActivity); + Intent intent = new Intent(TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED); intent.putExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, - EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA); + EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS); mSimSelectNotification.onReceive(mContext, intent); clearInvocations(mContext); // Dismiss. - intent.putExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, - EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS); - mSimSelectNotification.onReceive(mContext, intent); - ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).startActivity(intentCaptor.capture()); - Intent capturedIntent = intentCaptor.getValue(); - assertThat(capturedIntent).isNotNull(); - assertThat(capturedIntent.getComponent().getClassName()).isEqualTo( - SimDialogActivity.class.getName()); - assertThat(capturedIntent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) - .isNotEqualTo(0); - assertThat(capturedIntent.getIntExtra(SimDialogActivity.DIALOG_TYPE_KEY, INVALID_PICK)) - .isEqualTo(PICK_DISMISS); + verify(mExecutor).execute(any()); } @Test public void onReceivePrimarySubListChange_DualCdmaWarning_notificationShouldSend() {